Initial load
diff --git a/test/javax/crypto/Cipher/ByteBuffers.java b/test/javax/crypto/Cipher/ByteBuffers.java
new file mode 100644
index 0000000..8d1ea92
--- /dev/null
+++ b/test/javax/crypto/Cipher/ByteBuffers.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2003-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 4844847
+ * @summary Test the Cipher.update/doFinal(ByteBuffer, ByteBuffer) methods
+ * @author Andreas Sterbenz
+ */
+
+import java.util.*;
+import java.nio.*;
+
+import java.security.*;
+
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+public class ByteBuffers {
+
+ public static void main(String[] args) throws Exception {
+ Provider p = Security.getProvider("SunJCE");
+ Random random = new Random();
+ int n = 10 * 1024;
+ byte[] t = new byte[n];
+ random.nextBytes(t);
+
+ byte[] keyBytes = new byte[8];
+ random.nextBytes(keyBytes);
+ SecretKey key = new SecretKeySpec(keyBytes, "DES");
+
+ Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");
+ cipher.init(Cipher.ENCRYPT_MODE, key);
+
+ byte[] outBytes = cipher.doFinal(t);
+
+ // create ByteBuffers for input (i1, i2, i3) and fill them
+ ByteBuffer i0 = ByteBuffer.allocate(n + 256);
+ i0.position(random.nextInt(256));
+ i0.limit(i0.position() + n);
+ ByteBuffer i1 = i0.slice();
+ i1.put(t);
+
+ ByteBuffer i2 = ByteBuffer.allocateDirect(t.length);
+ i2.put(t);
+
+ i1.clear();
+ ByteBuffer i3 = i1.asReadOnlyBuffer();
+
+ ByteBuffer o0 = ByteBuffer.allocate(n + 512);
+ o0.position(random.nextInt(256));
+ o0.limit(o0.position() + n + 256);
+ ByteBuffer o1 = o0.slice();
+
+ ByteBuffer o2 = ByteBuffer.allocateDirect(t.length + 256);
+
+ crypt(cipher, i1, o1, outBytes, random);
+ crypt(cipher, i2, o1, outBytes, random);
+ crypt(cipher, i3, o1, outBytes, random);
+ crypt(cipher, i1, o2, outBytes, random);
+ crypt(cipher, i2, o2, outBytes, random);
+ crypt(cipher, i3, o2, outBytes, random);
+
+ System.out.println("All tests passed");
+ }
+
+ private static void crypt(Cipher cipher, ByteBuffer in, ByteBuffer out, byte[] outBytes, Random random) throws Exception {
+ in.clear();
+ out.clear();
+ out.put(new byte[out.remaining()]);
+ out.clear();
+ int lim = in.limit();
+ in.limit(random.nextInt(lim));
+ cipher.update(in, out);
+ if (in.hasRemaining()) {
+ throw new Exception("Buffer not consumed");
+ }
+ in.limit(lim);
+ cipher.doFinal(in, out);
+ if (in.hasRemaining()) {
+ throw new Exception("Buffer not consumed");
+ }
+ out.flip();
+ byte[] b = new byte[out.remaining()];
+ out.get(b);
+ if (Arrays.equals(outBytes, b) == false) {
+ throw new Exception("Encryption output mismatch");
+ }
+ }
+}
diff --git a/test/javax/crypto/Cipher/ByteBuffersNull.java b/test/javax/crypto/Cipher/ByteBuffersNull.java
new file mode 100644
index 0000000..c0a8ced
--- /dev/null
+++ b/test/javax/crypto/Cipher/ByteBuffersNull.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2004-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 5000980
+ * @summary Check NullPointerException for cipherSpi.engineUpdate(x, null)
+ */
+
+import javax.crypto.CipherSpi;
+import java.security.InvalidKeyException;
+import java.security.AlgorithmParameters;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.Key;
+import java.security.Security;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.BadPaddingException;
+import javax.crypto.ShortBufferException;
+import javax.crypto.NoSuchPaddingException;
+import java.security.GeneralSecurityException;
+import java.nio.ByteBuffer;
+
+public class ByteBuffersNull {
+
+ static final int bufSize = 1024;
+
+ public void testCase010() throws Exception {
+ CipherSpiImpl c = new CipherSpiImpl();
+ BufferDescr[] inBuffers = getByteBuffersForTest(bufSize);
+ int failureCount = 0;
+
+ for (int i = 0; i < inBuffers.length; i++) {
+ String key = inBuffers[i].descr;
+ ByteBuffer bb = inBuffers[i].buf;
+
+ try {
+
+ c.engineUpdate(bb, null);
+
+ throw new Exception("No Exception?!");
+ } catch (NullPointerException npe) {
+ // Expected behaviour - pass
+ System.out.println("OK: " + npe);
+ }
+ }
+ }
+
+ // Creates a ByteBuffer with a desired properties
+ ByteBuffer getByteBuffer(int capacity, int position,
+ boolean limitAt0) {
+ ByteBuffer bb = ByteBuffer.allocate(capacity);
+
+ bb.position(position);
+
+ if (limitAt0)
+ bb.limit(0);
+
+ return bb;
+ }
+
+ BufferDescr[] getByteBuffersForTest(int defaultSize) {
+ int caseNum = 4;
+
+ BufferDescr[] buffers = new BufferDescr[caseNum];
+
+ // ByteBuffer with capacity 0
+ buffers[0]= new BufferDescr("ByteBuffer with capacity == 0",
+ getByteBuffer(0,0,false));
+
+ // ByteBuffer with some space but limit = 0
+ buffers[1] = new BufferDescr(
+ "ByteBuffer with some capacity but limit == 0",
+ getByteBuffer(defaultSize, 0, true));
+
+ // ByteBuffer with some remaining data (limit = capacity)
+ buffers[2] = new BufferDescr("ByteBuffer with some data",
+ getByteBuffer(defaultSize,0,false));
+
+ // ByteBuffer with some data but position is at the limit
+ buffers[3] = new BufferDescr(
+ "ByteBuffer with data but position at the limit",
+ getByteBuffer(defaultSize, defaultSize,false));
+
+ return buffers;
+ }
+
+ public static void main(String argv[]) throws Exception {
+ ByteBuffersNull test = new ByteBuffersNull();
+ test.testCase010();
+ }
+
+ class BufferDescr {
+ BufferDescr(String d, ByteBuffer b) {
+ descr = d;
+ buf = b;
+ }
+
+ public String descr;
+ public ByteBuffer buf;
+ }
+
+ public class CipherSpiImpl extends CipherSpi {
+
+ public CipherSpiImpl() {
+ super();
+ }
+
+ public void engineSetMode(String mode)
+ throws NoSuchAlgorithmException { }
+
+ public void engineSetPadding(String padding)
+ throws NoSuchPaddingException { }
+
+ public int engineGetBlockSize() {
+ return 0;
+ }
+
+ public int engineGetOutputSize(int inputLen) {
+ return 0;
+ }
+
+ public byte[] engineGetIV() {
+ return null;
+ }
+
+ public AlgorithmParameters engineGetParameters() {
+ return null;
+ }
+
+ public void engineInit(int opmode, Key key, SecureRandom random)
+ throws InvalidKeyException { }
+
+ public void engineInit(int opmode, Key key,
+ AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException { }
+
+ public void engineInit(int opmode, Key key, AlgorithmParameters params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException { }
+
+ public byte[] engineUpdate(byte[] input, int offset, int len) {
+ return null;
+ }
+
+ public int engineUpdate(byte[] input, int inputOffset, int inputLen,
+ byte[] output, int outputOffset)
+ throws ShortBufferException {
+ return 0;
+ }
+
+ public byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen)
+ throws IllegalBlockSizeException, BadPaddingException {
+ return null;
+ }
+
+ public int engineDoFinal(byte[] input, int inputOffset, int inputLen,
+ byte[] output, int outputOffset)
+ throws ShortBufferException, IllegalBlockSizeException,
+ BadPaddingException {
+ return 0;
+ }
+
+ public byte[] engineWrap(Key key)
+ throws IllegalBlockSizeException, InvalidKeyException {
+ return super.engineWrap(key);
+ }
+
+ public Key engineUnwrap(byte[] wKey, String wKeyAlgorithm,
+ int wKeyType) throws InvalidKeyException,
+ NoSuchAlgorithmException {
+ return super.engineUnwrap(wKey, wKeyAlgorithm, wKeyType);
+ }
+
+ public int engineGetKeySize(Key key) throws InvalidKeyException {
+ return super.engineGetKeySize(key);
+ }
+
+ public int engineDoFinal(ByteBuffer input, ByteBuffer output)
+ throws ShortBufferException, IllegalBlockSizeException,
+ BadPaddingException {
+ return super.engineDoFinal(input, output);
+ }
+
+ public int engineUpdate(ByteBuffer input, ByteBuffer output)
+ throws ShortBufferException {
+ return super.engineUpdate(input, output);
+ }
+ }
+}
diff --git a/test/javax/crypto/Cipher/GetMaxAllowed.java b/test/javax/crypto/Cipher/GetMaxAllowed.java
new file mode 100644
index 0000000..0f9bbd2
--- /dev/null
+++ b/test/javax/crypto/Cipher/GetMaxAllowed.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2003-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 4807942
+ * @summary Test the Cipher.getMaxAllowedKeyLength(String) and
+ * getMaxAllowedParameterSpec(String) methods
+ * @author Valerie Peng
+ */
+
+import java.util.*;
+import java.nio.*;
+
+import java.security.*;
+import java.security.spec.*;
+
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+public class GetMaxAllowed {
+
+ private static void runTest(boolean isUnlimited) throws Exception {
+ System.out.println("Testing " + (isUnlimited? "un":"") +
+ "limited policy...");
+
+ String algo = "Blowfish";
+ int keyLength = Cipher.getMaxAllowedKeyLength(algo);
+ AlgorithmParameterSpec spec = Cipher.getMaxAllowedParameterSpec(algo);
+ if (isUnlimited) {
+ if ((keyLength != Integer.MAX_VALUE) || (spec != null)) {
+ throw new Exception("Check for " + algo +
+ " failed under unlimited policy");
+ }
+ } else {
+ if ((keyLength != 128) || (spec != null)) {
+ throw new Exception("Check for " + algo +
+ " failed under default policy");
+ }
+ }
+ algo = "RC5";
+ keyLength = Cipher.getMaxAllowedKeyLength(algo);
+ RC5ParameterSpec rc5param = (RC5ParameterSpec)
+ Cipher.getMaxAllowedParameterSpec(algo);
+ if (isUnlimited) {
+ if ((keyLength != Integer.MAX_VALUE) || (rc5param != null)) {
+ throw new Exception("Check for " + algo +
+ " failed under unlimited policy");
+ }
+ } else {
+ if ((keyLength != 128) || (rc5param.getRounds() != 12) ||
+ (rc5param.getVersion() != Integer.MAX_VALUE) ||
+ (rc5param.getWordSize() != Integer.MAX_VALUE)) {
+ throw new Exception("Check for " + algo +
+ " failed under default policy");
+ }
+ }
+ System.out.println("All tests passed");
+ }
+
+ public static void main(String[] args) throws Exception {
+ // decide if the installed jurisdiction policy file is the
+ // unlimited version
+ boolean isUnlimited = true;
+ Cipher c = Cipher.getInstance("AES", "SunJCE");
+ try {
+ c.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(new byte[24], "AES"));
+ } catch (InvalidKeyException ike) {
+ isUnlimited = false;
+ }
+ runTest(isUnlimited);
+ }
+}
diff --git a/test/javax/crypto/Cipher/InOutBuffers.java b/test/javax/crypto/Cipher/InOutBuffers.java
new file mode 100644
index 0000000..7060791
--- /dev/null
+++ b/test/javax/crypto/Cipher/InOutBuffers.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2003-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 4925226
+ * @summary ensure IllegalArgumentException is thrown if in == out
+ * @author Andreas Sterbenz
+ */
+
+import java.nio.*;
+
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+public class InOutBuffers {
+
+ public static void main(String[] args) throws Exception {
+ Cipher c = Cipher.getInstance("RC4");
+ SecretKey key = new SecretKeySpec(new byte[16], "RC4");
+ c.init(Cipher.ENCRYPT_MODE, key);
+ ByteBuffer b = ByteBuffer.allocate(16);
+ b.putInt(0x12345678);
+ try {
+ c.update(b, b);
+ throw new Exception("Unexpectedly completed call");
+ } catch (IllegalArgumentException e) {
+ System.out.println(e);
+ }
+ b.flip();
+ try {
+ c.doFinal(b, b);
+ throw new Exception("Unexpectedly completed call");
+ } catch (IllegalArgumentException e) {
+ System.out.println(e);
+ }
+ System.out.println("Passed");
+ }
+}
diff --git a/test/javax/crypto/Cipher/TestCipherMode.java b/test/javax/crypto/Cipher/TestCipherMode.java
new file mode 100644
index 0000000..b6ba502
--- /dev/null
+++ b/test/javax/crypto/Cipher/TestCipherMode.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2004-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4953556
+ * @summary ensure that IllegalStateException is thrown if the
+ * Cipher object is initialized with a wrong mode, e.g. WRAP_MODE
+ * for update()/doFinal() calls.
+ * @author Valerie Peng
+ */
+
+
+import java.security.*;
+import java.security.spec.*;
+
+import javax.crypto.*;
+import javax.crypto.spec.SecretKeySpec;
+
+public class TestCipherMode {
+
+ private static final String ALGO = "DES";
+
+ public static void main(String[] argv) throws Exception {
+ TestCipherMode test = new TestCipherMode();
+ System.out.println("Testing ENCRYPT_MODE...");
+ test.checkMode(Cipher.ENCRYPT_MODE);
+ System.out.println("Testing DECRYPT_MODE...");
+ test.checkMode(Cipher.DECRYPT_MODE);
+ System.out.println("Testing WRAP_MODE...");
+ test.checkMode(Cipher.WRAP_MODE);
+ System.out.println("Testing UNWRAP_MODE...");
+ test.checkMode(Cipher.UNWRAP_MODE);
+ System.out.println("All Tests Passed");
+ }
+
+ private Cipher c = null;
+ private SecretKey key = null;
+
+ private TestCipherMode() throws NoSuchAlgorithmException,
+ NoSuchProviderException, NoSuchPaddingException {
+ c = Cipher.getInstance(ALGO + "/ECB/PKCS5Padding", "SunJCE");
+ key = new SecretKeySpec(new byte[8], ALGO);
+ }
+
+ private void checkMode(int mode) throws Exception {
+ c.init(mode, key);
+
+ switch (mode) {
+ case Cipher.ENCRYPT_MODE:
+ case Cipher.DECRYPT_MODE:
+ // call wrap()/unwrap() and see if ISE is thrown.
+ try {
+ c.wrap(key);
+ throw new Exception("ERROR: should throw ISE for wrap()");
+ } catch (IllegalStateException ise) {
+ System.out.println("expected ISE is thrown for wrap()");
+ }
+ try {
+ c.unwrap(new byte[16], ALGO, Cipher.SECRET_KEY);
+ throw new Exception("ERROR: should throw ISE for unwrap()");
+ } catch (IllegalStateException ise) {
+ System.out.println("expected ISE is thrown for unwrap()");
+ }
+ break;
+ case Cipher.WRAP_MODE:
+ case Cipher.UNWRAP_MODE:
+ try {
+ c.update(new byte[16]);
+ throw new Exception("ERROR: should throw ISE for update()");
+ } catch (IllegalStateException ise) {
+ System.out.println("expected ISE is thrown for update()");
+ }
+ try {
+ c.doFinal();
+ throw new Exception("ERROR: should throw ISE for doFinal()");
+ } catch (IllegalStateException ise) {
+ System.out.println("expected ISE is thrown for doFinal()");
+ }
+ break;
+ }
+ }
+}
diff --git a/test/javax/crypto/Cipher/TestGetInstance.java b/test/javax/crypto/Cipher/TestGetInstance.java
new file mode 100644
index 0000000..736bac9
--- /dev/null
+++ b/test/javax/crypto/Cipher/TestGetInstance.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2003-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4898428
+ * @summary test that the new getInstance() implementation works correctly
+ * @author Andreas Sterbenz
+ */
+
+import java.security.*;
+import java.security.spec.*;
+
+import javax.crypto.*;
+
+public class TestGetInstance {
+
+ private static void same(Provider p1, Provider p2) throws Exception {
+ if (p1 != p2) {
+ throw new Exception("not same object");
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ Provider p = Security.getProvider("SunJCE");
+
+ Cipher c;
+
+ c = Cipher.getInstance("des");
+ same(p, c.getProvider());
+ c = Cipher.getInstance("des/cbc/pkcs5padding");
+ same(p, c.getProvider());
+
+ c = Cipher.getInstance("des", "SunJCE");
+ same(p, c.getProvider());
+ c = Cipher.getInstance("des/cbc/pkcs5padding", "SunJCE");
+ same(p, c.getProvider());
+
+ c = Cipher.getInstance("des", p);
+ same(p, c.getProvider());
+ c = Cipher.getInstance("des/cbc/pkcs5padding", p);
+ same(p, c.getProvider());
+
+ try {
+ c = Cipher.getInstance("DES/XYZ/PKCS5Padding");
+ throw new AssertionError();
+ } catch (NoSuchAlgorithmException e) {
+ System.out.println(e);
+ }
+ try {
+ c = Cipher.getInstance("DES/XYZ/PKCS5Padding", "SunJCE");
+ throw new AssertionError();
+ } catch (NoSuchAlgorithmException e) {
+ System.out.println(e);
+ }
+ try {
+ c = Cipher.getInstance("DES/XYZ/PKCS5Padding", p);
+ throw new AssertionError();
+ } catch (NoSuchAlgorithmException e) {
+ System.out.println(e);
+ }
+
+ try {
+ c = Cipher.getInstance("DES/CBC/XYZPadding");
+ throw new AssertionError();
+ } catch (NoSuchAlgorithmException e) {
+ System.out.println(e);
+ }
+ try {
+ c = Cipher.getInstance("DES/CBC/XYZPadding", "SunJCE");
+ throw new AssertionError();
+ } catch (NoSuchPaddingException e) {
+ System.out.println(e);
+ }
+ try {
+ c = Cipher.getInstance("DES/CBC/XYZPadding", p);
+ throw new AssertionError();
+ } catch (NoSuchPaddingException e) {
+ System.out.println(e);
+ }
+
+ try {
+ c = Cipher.getInstance("foo");
+ throw new AssertionError();
+ } catch (NoSuchAlgorithmException e) {
+ System.out.println(e);
+ }
+ try {
+ c = Cipher.getInstance("foo", "SunJCE");
+ throw new AssertionError();
+ } catch (NoSuchAlgorithmException e) {
+ System.out.println(e);
+ }
+ try {
+ c = Cipher.getInstance("foo", p);
+ throw new AssertionError();
+ } catch (NoSuchAlgorithmException e) {
+ System.out.println(e);
+ }
+
+ try {
+ c = Cipher.getInstance("foo", "SUN");
+ throw new AssertionError();
+ } catch (NoSuchAlgorithmException e) {
+ System.out.println(e);
+ }
+ try {
+ c = Cipher.getInstance("foo", Security.getProvider("SUN"));
+ throw new AssertionError();
+ } catch (NoSuchAlgorithmException e) {
+ System.out.println(e);
+ }
+ try {
+ c = Cipher.getInstance("foo", "bar");
+ throw new AssertionError();
+ } catch (NoSuchProviderException e) {
+ System.out.println(e);
+ }
+
+ System.out.println("All Tests ok");
+ }
+}
diff --git a/test/javax/crypto/Cipher/Turkish.java b/test/javax/crypto/Cipher/Turkish.java
new file mode 100644
index 0000000..2115861
--- /dev/null
+++ b/test/javax/crypto/Cipher/Turkish.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2005-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6220064
+ * @summary make sure everything works ok in the Turkish local (dotted/dotless i problem)
+ * @author Andreas Sterbenz
+ */
+
+import java.util.Locale;
+
+import javax.crypto.Cipher;
+
+public class Turkish {
+
+ public static void main(String[] args) throws Exception {
+ Locale.setDefault(new Locale("tr", "TR"));
+
+ System.out.println(Cipher.getInstance("RSA/ECB/PKCS1Padding"));
+ System.out.println(Cipher.getInstance("RSA/ECB/PKCS1PADDING"));
+ System.out.println(Cipher.getInstance("rsa/ecb/pkcs1padding"));
+ System.out.println(Cipher.getInstance("Blowfish"));
+ System.out.println(Cipher.getInstance("blowfish"));
+ System.out.println(Cipher.getInstance("BLOWFISH"));
+
+ System.out.println("OK");
+ }
+}
diff --git a/test/javax/crypto/CryptoPermission/AllPermCheck.java b/test/javax/crypto/CryptoPermission/AllPermCheck.java
new file mode 100644
index 0000000..37014aa
--- /dev/null
+++ b/test/javax/crypto/CryptoPermission/AllPermCheck.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2003-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 4953554
+ * @summary Ensure either IllegalAlgorithmParameterException or
+ * InvalidKeyException is thrown instead of SecurityException when
+ * crypto permssion checks failed.
+ * @author Valerie Peng
+ */
+
+import java.io.*;
+import java.util.*;
+
+import java.security.*;
+import java.security.spec.*;
+
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+public class AllPermCheck {
+
+ private static String SYM_ALGOS[] = {
+ "AES", "Blowfish", "RC2", "ARCFOUR"
+ };
+
+ public static void runTest(Cipher c, Key key) throws Exception {
+ SecureRandom sr = new SecureRandom();
+
+ for (int i = 0; i < 6; i++) {
+ try {
+ switch (i) {
+ case 0:
+ c.init(Cipher.ENCRYPT_MODE, key);
+ break;
+ case 1:
+ c.init(Cipher.ENCRYPT_MODE, key, sr);
+ break;
+ case 2:
+ c.init(Cipher.ENCRYPT_MODE, key,
+ (AlgorithmParameters)null);
+ break;
+ case 3:
+ c.init(Cipher.ENCRYPT_MODE, key,
+ (AlgorithmParameters)null, sr);
+ break;
+ case 4:
+ c.init(Cipher.ENCRYPT_MODE, key,
+ (AlgorithmParameterSpec)null);
+ break;
+ case 5:
+ c.init(Cipher.ENCRYPT_MODE, key,
+ (AlgorithmParameterSpec)null, sr);
+ break;
+ }
+ throw new Exception("...#" + i + " should throw IKE for " +
+ key.getEncoded().length + "-byte keys");
+ } catch (InvalidKeyException ike) {
+ System.out.println("...#" + i + " expected IKE thrown");
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ Provider p = Security.getProvider("SunJCE");
+ System.out.println("Testing provider " + p.getName() + "...");
+ if (Cipher.getMaxAllowedKeyLength("DES") == Integer.MAX_VALUE) {
+ // skip this test for unlimited jurisdiction policy files
+ System.out.println("Skip this test due to unlimited version");
+ return;
+ }
+ for (int i = 0; i < SYM_ALGOS.length; i++) {
+ String algo = SYM_ALGOS[i];
+ Cipher c = Cipher.getInstance(algo, p);
+ int keyLength = Cipher.getMaxAllowedKeyLength(algo);
+ SecretKey key = new SecretKeySpec(new byte[keyLength/8 + 8], algo);
+ System.out.println("Testing " + algo + " Cipher");
+ runTest(c, key);
+ }
+ System.out.println("All tests passed!");
+ }
+}
diff --git a/test/javax/crypto/CryptoPermission/LowercasePermCheck.java b/test/javax/crypto/CryptoPermission/LowercasePermCheck.java
new file mode 100644
index 0000000..ad6ada7
--- /dev/null
+++ b/test/javax/crypto/CryptoPermission/LowercasePermCheck.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2005-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6229618
+ * @summary Ensure that the correct crypto permission is granted
+ * even when the transformation algorithm is lowercase or mixed
+ * case.
+ * @author Valerie Peng
+ */
+
+import java.io.*;
+import java.util.*;
+
+import java.security.*;
+import java.security.spec.*;
+
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+public class LowercasePermCheck {
+
+ private static String[] ALGOS = {
+ "des", "desede", "rsa"
+ };
+
+ public static void main(String[] args) throws Exception {
+ Provider p = Security.getProvider("SunJCE");
+ System.out.println("Testing provider " + p.getName() + "...");
+ if (Cipher.getMaxAllowedKeyLength("DES") == Integer.MAX_VALUE) {
+ // skip this test for unlimited jurisdiction policy files
+ System.out.println("Skip this test due to unlimited version");
+ return;
+ }
+ boolean isFailed = false;
+ for (int i = 0; i < ALGOS.length; i++) {
+ String algo = ALGOS[i];
+ Cipher c = Cipher.getInstance(algo, p);
+ int keyLen1 = Cipher.getMaxAllowedKeyLength(algo);
+ int keyLen2 = Cipher.getMaxAllowedKeyLength(algo.toUpperCase());
+
+ if (keyLen1 != keyLen2) {
+ System.out.println("ERROR: Wrong keysize limit for " + algo);
+ System.out.println("Configured: " + keyLen2);
+ System.out.println("Actual: " + keyLen1);
+ isFailed = true;
+ }
+ System.out.println(algo + ": max " + keyLen1 + "-bit keys");
+ }
+ if (isFailed) {
+ throw new Exception("Test Failed!");
+ } else {
+ System.out.println("Test Passed!");
+ }
+ }
+}
diff --git a/test/javax/crypto/CryptoPermission/RC2PermCheck.java b/test/javax/crypto/CryptoPermission/RC2PermCheck.java
new file mode 100644
index 0000000..d570349
--- /dev/null
+++ b/test/javax/crypto/CryptoPermission/RC2PermCheck.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2003-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 4892365
+ * @summary Ensure the crypto permission check on cipher algorithms
+ * with restricted parameter values are correctly enforced.
+ * @author Valerie Peng
+ */
+
+import java.io.*;
+import java.util.*;
+
+import java.security.*;
+import java.security.spec.*;
+
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+public class RC2PermCheck {
+
+ public static void main(String[] args) throws Exception {
+ Provider p = Security.getProvider("SunJCE");
+ System.out.println("Testing provider " + p.getName() + "...");
+ if (Cipher.getMaxAllowedKeyLength("DES") == Integer.MAX_VALUE) {
+ // skip this test for unlimited jurisdiction policy files
+ System.out.println("Skip this test due to unlimited version");
+ return;
+ }
+ // Currently, RC2 is the only algorithm whose parameter values
+ // are restricted
+ String algo = "RC2";
+ Cipher c = Cipher.getInstance(algo + "/CBC/PKCS5Padding", p);
+ SecretKeySpec key = new SecretKeySpec(new byte[16], "RC2");
+ SecureRandom srand = new SecureRandom();
+ int numOfTests = 6;
+ boolean result = true;
+ // test set#1: init with no parameter supplied
+ for (int i = 0; i < numOfTests; i++) {
+ try {
+ switch (i) {
+ case 0:
+ c.init(Cipher.ENCRYPT_MODE, key);
+ break;
+ case 1:
+ c.init(Cipher.ENCRYPT_MODE, key, srand);
+ break;
+ case 2:
+ c.init(Cipher.ENCRYPT_MODE, key,
+ (AlgorithmParameters) null);
+ break;
+ case 3:
+ c.init(Cipher.ENCRYPT_MODE, key,
+ (AlgorithmParameters) null, srand);
+ break;
+ case 4:
+ c.init(Cipher.ENCRYPT_MODE, key,
+ (AlgorithmParameterSpec) null);
+ break;
+ case 5:
+ c.init(Cipher.ENCRYPT_MODE, key,
+ (AlgorithmParameterSpec) null, srand);
+ break;
+ }
+ } catch (Exception ex) {
+ result = false;
+ System.out.println("Test#1." + i + " failed!");
+ ex.printStackTrace();
+ continue;
+ }
+ }
+ // test set#2: init with parameter within limit
+ RC2ParameterSpec paramSpec = new RC2ParameterSpec(128, new byte[8]);
+ AlgorithmParameters param = AlgorithmParameters.getInstance(algo, p);
+ param.init(paramSpec);
+ numOfTests = 4;
+ for (int i = 0; i < numOfTests; i++) {
+ try {
+ switch (i) {
+ case 0:
+ c.init(Cipher.ENCRYPT_MODE, key, paramSpec);
+ break;
+ case 1:
+ c.init(Cipher.ENCRYPT_MODE, key, paramSpec, srand);
+ break;
+ case 2:
+ c.init(Cipher.ENCRYPT_MODE, key, param);
+ break;
+ case 3:
+ c.init(Cipher.ENCRYPT_MODE, key, param, srand);
+ break;
+ }
+ } catch (Exception ex) {
+ result = false;
+ System.out.println("Test#2." + i + " failed!");
+ ex.printStackTrace();
+ }
+ }
+ // test set#3: init with parameter over limit
+ paramSpec = new RC2ParameterSpec(256, new byte[8]);
+ param = AlgorithmParameters.getInstance(algo);
+ param.init(paramSpec);
+
+ for (int i = 0; i < numOfTests; i++) {
+ try {
+ switch (i) {
+ case 0:
+ c.init(Cipher.ENCRYPT_MODE, key, paramSpec);
+ result = false;
+ System.out.println("Test#3." + i + " failed!");
+ break;
+ case 1:
+ c.init(Cipher.ENCRYPT_MODE, key, paramSpec, srand);
+ result = false;
+ System.out.println("Test#3." + i + " failed!");
+ break;
+ case 2:
+ c.init(Cipher.ENCRYPT_MODE, key, param);
+ result = false;
+ System.out.println("Test#3." + i + " failed!");
+ break;
+ case 3:
+ c.init(Cipher.ENCRYPT_MODE, key, param, srand);
+ result = false;
+ System.out.println("Test#3." + i + " failed!");
+ break;
+ }
+ } catch (InvalidAlgorithmParameterException iape) {
+ // expected exception thrown; proceed to next test
+ continue;
+ }
+ }
+ if (result) {
+ System.out.println("All tests passed!");
+ } else {
+ throw new Exception("One or more test failed!");
+ }
+ }
+}
diff --git a/test/javax/crypto/CryptoPermission/RC4AliasPermCheck.java b/test/javax/crypto/CryptoPermission/RC4AliasPermCheck.java
new file mode 100644
index 0000000..9ed9a94
--- /dev/null
+++ b/test/javax/crypto/CryptoPermission/RC4AliasPermCheck.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2005-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 5056438
+ * @summary Ensure the crypto permission check on RC4 ciphers
+ * do not fail accidentally due to the use of an alias, i.e.
+ * "ARCFOUR" vs "RC4".
+ * @author Valerie Peng
+ */
+
+import java.io.*;
+import java.security.*;
+import javax.crypto.*;
+
+public class RC4AliasPermCheck {
+ /**
+ * Testing the crypto permission check using both standard
+ * and alias names.
+ *
+ * @param algo algorithm for key and cipher
+ * @param keyLen key length must be positive
+ */
+ private static void test(String algo, int keyLen) throws Exception {
+ Provider p = Security.getProvider("SunJCE");
+ System.out.println("=>Testing " + algo + " cipher with "
+ + keyLen + "-bit key");
+ KeyGenerator kg = KeyGenerator.getInstance(algo, p);
+ kg.init(keyLen);
+ SecretKey key = kg.generateKey();
+ System.out.println("Generated key with algorithm " +
+ key.getAlgorithm());
+ Cipher cipher = Cipher.getInstance(algo, p);
+ System.out.println("Requested cipher with algorithm " +
+ algo);
+ cipher.init(Cipher.ENCRYPT_MODE, key);
+ System.out.println("Initialization succeeded as expected");
+ }
+
+ public static void main(String[] argv) throws Exception {
+ test("ARCFOUR", 120);
+ test("RC4", 120);
+ System.out.println("TEST PASSED");
+ }
+}
diff --git a/test/javax/crypto/CryptoPermission/RSANoLimit.java b/test/javax/crypto/CryptoPermission/RSANoLimit.java
new file mode 100644
index 0000000..3b9daf9
--- /dev/null
+++ b/test/javax/crypto/CryptoPermission/RSANoLimit.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2005-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6353783
+ * @summary Ensure that the 2048 bit RSA keysize limit has been
+ * lifted.
+ *
+ * @author Valerie Peng
+ */
+
+import java.io.*;
+import java.util.*;
+import java.math.BigInteger;
+
+import java.security.*;
+import java.security.spec.RSAPublicKeySpec;
+import java.security.interfaces.RSAPublicKey;
+
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+public class RSANoLimit {
+ private static final byte[] MODULUS4096 = {
+(byte)0x70, (byte)0x80, (byte)0x7C, (byte)0x77, (byte)0x16, (byte)0xD0,
+(byte)0x11, (byte)0xF7, (byte)0xA1, (byte)0xAE, (byte)0x3D, (byte)0xEC,
+(byte)0x75, (byte)0xC7, (byte)0xC0, (byte)0x65, (byte)0x8F, (byte)0x0D,
+(byte)0x16, (byte)0x80, (byte)0xDE, (byte)0x44, (byte)0xB8, (byte)0x32,
+(byte)0xA5, (byte)0x33, (byte)0xA1, (byte)0x6A, (byte)0x21, (byte)0xF1,
+(byte)0x84, (byte)0xFF, (byte)0xD9, (byte)0x2B, (byte)0x24, (byte)0x53,
+(byte)0x6B, (byte)0x23, (byte)0x55, (byte)0xA9, (byte)0xB4, (byte)0x05,
+(byte)0x93, (byte)0x5A, (byte)0x0E, (byte)0xA5, (byte)0x51, (byte)0xBE,
+(byte)0x50, (byte)0x90, (byte)0xBD, (byte)0x88, (byte)0x07, (byte)0x6E,
+(byte)0x07, (byte)0x2E, (byte)0xFD, (byte)0xCE, (byte)0x32, (byte)0x0C,
+(byte)0x48, (byte)0x03, (byte)0x26, (byte)0x95, (byte)0x64, (byte)0x92,
+(byte)0x8D, (byte)0xB8, (byte)0x09, (byte)0x31, (byte)0xFB, (byte)0x80,
+(byte)0x32, (byte)0x20, (byte)0x38, (byte)0x72, (byte)0x7A, (byte)0x5F,
+(byte)0xF9, (byte)0x5A, (byte)0x73, (byte)0x84, (byte)0x5A, (byte)0xDA,
+(byte)0x4C, (byte)0xB2, (byte)0x6C, (byte)0x9C, (byte)0x18, (byte)0xA2,
+(byte)0xC8, (byte)0xC5, (byte)0x87, (byte)0x62, (byte)0xA1, (byte)0x59,
+(byte)0xEA, (byte)0x04, (byte)0xD8, (byte)0xB7, (byte)0xE4, (byte)0xB6,
+(byte)0xA1, (byte)0xD1, (byte)0xDA, (byte)0xB8, (byte)0x61, (byte)0x24,
+(byte)0xC6, (byte)0xD4, (byte)0x20, (byte)0xBC, (byte)0x01, (byte)0x32,
+(byte)0xAB, (byte)0xDF, (byte)0x30, (byte)0x12, (byte)0xE1, (byte)0xB0,
+(byte)0x80, (byte)0xCB, (byte)0x0A, (byte)0x25, (byte)0xAB, (byte)0xC6,
+(byte)0xEB, (byte)0xE2, (byte)0x3B, (byte)0x77, (byte)0xAD, (byte)0x90,
+(byte)0x16, (byte)0xC8, (byte)0xCC, (byte)0xF9, (byte)0x94, (byte)0xBB,
+(byte)0xF0, (byte)0xE7, (byte)0x77, (byte)0xA9, (byte)0x4E, (byte)0x7D,
+(byte)0xFC, (byte)0x76, (byte)0x11, (byte)0xA1, (byte)0xE8, (byte)0x22,
+(byte)0xD1, (byte)0xC5, (byte)0xAA, (byte)0x51, (byte)0x2B, (byte)0xBD,
+(byte)0x0B, (byte)0x2E, (byte)0x3A, (byte)0x97, (byte)0xAC, (byte)0x19,
+(byte)0x4B, (byte)0xA2, (byte)0x01, (byte)0x89, (byte)0x1A, (byte)0x9E,
+(byte)0x2C, (byte)0x0C, (byte)0x7E, (byte)0x83, (byte)0xAD, (byte)0xCB,
+(byte)0xED, (byte)0x5B, (byte)0x67, (byte)0x67, (byte)0x9E, (byte)0x85,
+(byte)0x1E, (byte)0x68, (byte)0xB6, (byte)0x5D, (byte)0xB9, (byte)0xD6,
+(byte)0xBD, (byte)0x80, (byte)0x92, (byte)0x7A, (byte)0x54, (byte)0xB3,
+(byte)0x5F, (byte)0x2E, (byte)0x8C, (byte)0x53, (byte)0x83, (byte)0xBD,
+(byte)0xF9, (byte)0x0D, (byte)0x65, (byte)0x0B, (byte)0xCD, (byte)0x22,
+(byte)0x21, (byte)0x51, (byte)0xB3, (byte)0x8F, (byte)0x19, (byte)0x53,
+(byte)0x6F, (byte)0x62, (byte)0x88, (byte)0x09, (byte)0xB0, (byte)0x8F,
+(byte)0xB5, (byte)0xDA, (byte)0x6E, (byte)0x2A, (byte)0x2F, (byte)0xF9,
+(byte)0xA6, (byte)0x65, (byte)0x59, (byte)0x17, (byte)0xEC, (byte)0x05,
+(byte)0x6A, (byte)0xA4, (byte)0xC6, (byte)0x21, (byte)0x3F, (byte)0x81,
+(byte)0xB9, (byte)0xB0, (byte)0x72, (byte)0xBB, (byte)0x84, (byte)0x79,
+(byte)0xEC, (byte)0x3E, (byte)0xA5, (byte)0x25, (byte)0x37, (byte)0x9D,
+(byte)0xC3, (byte)0x2E, (byte)0x79, (byte)0x69, (byte)0xE6, (byte)0x80,
+(byte)0x5E, (byte)0x1E, (byte)0x03, (byte)0x8D, (byte)0xD9, (byte)0x62,
+(byte)0xCC, (byte)0x6C, (byte)0x7C, (byte)0x27, (byte)0x52, (byte)0xE5,
+(byte)0xC2, (byte)0x24, (byte)0xBF, (byte)0x95, (byte)0xCC, (byte)0x2E,
+(byte)0xFA, (byte)0x9C, (byte)0x88, (byte)0xAB, (byte)0x48, (byte)0x43,
+(byte)0xDB, (byte)0x36, (byte)0xFD, (byte)0x41, (byte)0x3C, (byte)0x71,
+(byte)0xE4, (byte)0x5C, (byte)0x30, (byte)0xE0, (byte)0x00, (byte)0x24,
+(byte)0x18, (byte)0xC2, (byte)0xD1, (byte)0x11, (byte)0x79, (byte)0xCE,
+(byte)0xD8, (byte)0x19, (byte)0xE5, (byte)0xA6, (byte)0xD3, (byte)0xFE,
+(byte)0x79, (byte)0x5F, (byte)0xA8, (byte)0xC3, (byte)0x92, (byte)0xBB,
+(byte)0x63, (byte)0xD2, (byte)0x3D, (byte)0x17, (byte)0x6D, (byte)0xFB,
+(byte)0x39, (byte)0xD2, (byte)0x32, (byte)0x5F, (byte)0xE1, (byte)0x54,
+(byte)0xD6, (byte)0x72, (byte)0xDB, (byte)0xA8, (byte)0xA3, (byte)0xFE,
+(byte)0x49, (byte)0x98, (byte)0xAA, (byte)0x55, (byte)0x67, (byte)0x1C,
+(byte)0xAB, (byte)0x83, (byte)0xA2, (byte)0x0F, (byte)0x03, (byte)0x52,
+(byte)0x3D, (byte)0x15, (byte)0xAF, (byte)0xDD, (byte)0x8A, (byte)0xAB,
+(byte)0x35, (byte)0x82, (byte)0xEF, (byte)0x6D, (byte)0xBD, (byte)0x8E,
+(byte)0xF3, (byte)0xB5, (byte)0x5E, (byte)0xD9, (byte)0xC9, (byte)0x45,
+(byte)0x99, (byte)0x46, (byte)0x4A, (byte)0xA5, (byte)0x28, (byte)0xAF,
+(byte)0x4E, (byte)0x6B, (byte)0xDE, (byte)0x9F, (byte)0xD7, (byte)0x20,
+(byte)0x7D, (byte)0x81, (byte)0xDB, (byte)0x34, (byte)0x25, (byte)0xDF,
+(byte)0x08, (byte)0xCA, (byte)0x06, (byte)0x77, (byte)0xC4, (byte)0xBC,
+(byte)0x69, (byte)0x4D, (byte)0x93, (byte)0x05, (byte)0x9C, (byte)0x8B,
+(byte)0xDB, (byte)0x84, (byte)0xB0, (byte)0xE7, (byte)0xBA, (byte)0xD2,
+(byte)0xEA, (byte)0x8D, (byte)0x64, (byte)0xF6, (byte)0xE3, (byte)0x96,
+(byte)0x2F, (byte)0x88, (byte)0x65, (byte)0x92, (byte)0x54, (byte)0x50,
+(byte)0xF6, (byte)0x33, (byte)0x15, (byte)0x2A, (byte)0xBF, (byte)0xB0,
+(byte)0xD4, (byte)0xD5, (byte)0x0C, (byte)0xCA, (byte)0x78, (byte)0x95,
+(byte)0xF4, (byte)0xC1, (byte)0x11, (byte)0xA7, (byte)0x52, (byte)0xA1,
+(byte)0xC9, (byte)0x49, (byte)0x63, (byte)0x41, (byte)0xD3, (byte)0x3E,
+(byte)0xA0, (byte)0xBE, (byte)0x7F, (byte)0x2F, (byte)0x17, (byte)0x2E,
+(byte)0xFD, (byte)0xA1, (byte)0x55, (byte)0x95, (byte)0x7F, (byte)0x24,
+(byte)0x90, (byte)0x68, (byte)0x4C, (byte)0x05, (byte)0xFD, (byte)0x52,
+(byte)0x9B, (byte)0x04, (byte)0x59, (byte)0xA0, (byte)0xEF, (byte)0x69,
+(byte)0x65, (byte)0x68, (byte)0x58, (byte)0x0F, (byte)0xF5, (byte)0x04,
+(byte)0x0E, (byte)0x23, (byte)0xEE, (byte)0xFA, (byte)0x04, (byte)0x80,
+(byte)0x8C, (byte)0x24, (byte)0xE5, (byte)0xB0, (byte)0x2B, (byte)0xA6,
+(byte)0x35, (byte)0x60, (byte)0xFA, (byte)0x08, (byte)0xD4, (byte)0x13,
+(byte)0x3E, (byte)0xE0, (byte)0xB0, (byte)0x63, (byte)0x1D, (byte)0xDB,
+(byte)0x1F, (byte)0x8C, (byte)0x2F, (byte)0xD0, (byte)0x47, (byte)0x8F,
+(byte)0x73, (byte)0x91, (byte)0xD7, (byte)0xDC, (byte)0x8A, (byte)0xE8,
+(byte)0x2D, (byte)0xF2, (byte)0x22, (byte)0x9C, (byte)0xEE, (byte)0x23,
+(byte)0xFA, (byte)0x4C, (byte)0xC1, (byte)0x86, (byte)0xE0, (byte)0x15,
+(byte)0xC7, (byte)0x52, (byte)0xFE, (byte)0x81, (byte)0xD6, (byte)0x27,
+(byte)0x6C, (byte)0x4F
+ };
+ private static final byte[] PUB4096 = {
+ (byte)0x01, (byte)0x00, (byte)0x01
+ };
+ public static void main(String[] args) throws Exception {
+ boolean result = true;
+ Provider p = Security.getProvider("SunJCE");
+ System.out.println("Testing provider " + p.getName() + "...");
+ // Test#1: make sure Cipher.getMaxAllowedKeyLength returns the
+ // correct value
+ if (Cipher.getMaxAllowedKeyLength("RSA") != Integer.MAX_VALUE) {
+ result = false;
+ System.out.println("Test#1 failed");
+ }
+ // Test#2: try initializing RSA cipher with 4096 key
+ String algo = "RSA";
+ RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec
+ (new BigInteger(MODULUS4096), new BigInteger(PUB4096));
+ KeyFactory kf = KeyFactory.getInstance(algo);
+ RSAPublicKey pubKey = (RSAPublicKey) kf.generatePublic(pubKeySpec);
+
+ Cipher c = Cipher.getInstance(algo + "/ECB/NoPadding", p);
+ try {
+ c.init(Cipher.ENCRYPT_MODE, pubKey);
+ } catch (InvalidKeyException ike) {
+ result = false;
+ System.out.println("Test#2 failed");
+ ike.printStackTrace();
+ }
+
+ if (result) {
+ System.out.println("All tests passed!");
+ } else {
+ throw new Exception("One or more test failed!");
+ }
+ }
+}
diff --git a/test/javax/crypto/EncryptedPrivateKeyInfo/GetAlgName.java b/test/javax/crypto/EncryptedPrivateKeyInfo/GetAlgName.java
new file mode 100644
index 0000000..24166d6
--- /dev/null
+++ b/test/javax/crypto/EncryptedPrivateKeyInfo/GetAlgName.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2003-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 4941596
+ * @summary Test the EncryptedPrivateKeyInfo.getAlgName(...) methods.
+ * @author Valerie Peng
+ */
+import java.util.*;
+import java.nio.*;
+import java.io.*;
+import java.security.*;
+import java.util.Arrays;
+import java.security.spec.*;
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+public class GetAlgName {
+ private static String PASSWD = "password";
+
+ private static final String[] ALGOS = {
+ "PBEWithMD5AndDES", "PBEWithSHA1AndDESede", "PBEWithSHA1AndRC2_40"
+ };
+ private static final byte[] BYTES = new byte[20];
+
+ public static void main(String[] argv) throws Exception {
+ boolean status = true;
+ PBEKeySpec ks = new PBEKeySpec(PASSWD.toCharArray());
+ EncryptedPrivateKeyInfo epki;
+ for (int i = 0; i < ALGOS.length; i++) {
+ String algo = ALGOS[i];
+ // generate AlgorithmParameters object
+ SecretKeyFactory skf =
+ SecretKeyFactory.getInstance(algo, "SunJCE");
+ SecretKey key = skf.generateSecret(ks);
+ Cipher c = Cipher.getInstance(algo, "SunJCE");
+ c.init(Cipher.ENCRYPT_MODE, key);
+ c.doFinal(BYTES); // force the parameter generation if not already
+
+ AlgorithmParameters ap = c.getParameters();
+ epki = new EncryptedPrivateKeyInfo(ap, BYTES);
+ if (!epki.getAlgName().equalsIgnoreCase(algo)) {
+ System.out.println("...expect: " + algo);
+ System.out.println("...got: " + epki.getAlgName());
+ status = false;
+ }
+ }
+ if (!status) {
+ throw new Exception("One or more tests failed");
+ } else {
+ System.out.println("Test Passed");
+ }
+ }
+}
diff --git a/test/javax/crypto/EncryptedPrivateKeyInfo/GetKeySpec.java b/test/javax/crypto/EncryptedPrivateKeyInfo/GetKeySpec.java
new file mode 100644
index 0000000..f221106
--- /dev/null
+++ b/test/javax/crypto/EncryptedPrivateKeyInfo/GetKeySpec.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2003-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 4508341
+ * @summary Test the EncryptedPrivateKeyInfo.getKeySpec(...) methods.
+ * @author Valerie Peng
+ */
+import java.util.*;
+import java.nio.*;
+import java.io.*;
+import java.security.*;
+import java.util.Arrays;
+import java.security.spec.*;
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+public class GetKeySpec {
+ private static final String cipherAlg = "PBEWithMD5AndDES";
+ private static final char[] passwd = { 'p','a','s','s','w','d' };
+ private static AlgorithmParameters GOOD_PARAMS;
+
+ static {
+ try {
+ PBEParameterSpec goodParamSpec =
+ new PBEParameterSpec(new byte[8], 1024);
+ GOOD_PARAMS = AlgorithmParameters.getInstance
+ (cipherAlg, "SunJCE");
+ GOOD_PARAMS.init(goodParamSpec);
+ } catch (Exception ex) {
+ // should never happen
+ GOOD_PARAMS = null;
+ }
+ }
+
+ private static String pkcs8Encoded = "30:82:01:53:02:01:00:30:0D:06:09:2A:86:48:86:F7:0D:01:01:01:05:00:04:82:01:3D:30:82:01:39:02:01:00:02:40:6E:A4:13:65:97:A2:C2:47:5E:F2:23:6B:94:D8:D7:25:13:BB:A4:AE:8A:AA:A7:27:A4:9A:04:DC:15:F7:9B:E4:39:18:99:9E:27:EA:92:BB:D0:0E:F3:26:F4:95:89:33:02:65:6D:84:69:2C:CE:B7:FA:68:8E:FE:8D:63:44:6B:02:03:01:00:01:02:40:59:6E:1C:13:98:FE:C1:04:89:75:35:36:27:29:22:B5:E0:7E:62:BD:86:6E:2C:10:7A:16:D8:68:C1:04:D4:A7:10:41:F7:B9:B4:84:05:03:A5:C0:28:73:24:A7:24:F1:1B:C3:4F:BF:05:20:D0:D9:00:08:7F:C3:29:64:1B:29:02:21:00:C4:63:4D:0C:32:51:44:AE:DD:90:A9:B7:B6:C2:6B:11:BE:D2:07:E7:B5:C2:4A:9F:4D:0F:2F:30:5F:E6:1C:6D:02:21:00:90:39:A4:2D:93:0B:08:AF:2F:6F:18:CC:1A:EF:B6:E6:01:E7:21:3A:7F:45:C7:3F:39:12:B8:CC:DF:44:2D:37:02:21:00:B3:9B:61:9E:B2:F2:12:4F:9E:C1:2C:06:A1:B5:A3:38:62:7D:31:CF:9F:32:67:0E:D3:E9:FC:2D:50:B7:61:ED:02:20:5B:FD:77:FB:5D:A3:97:09:6E:1E:D5:59:32:01:1D:CE:7C:FE:38:12:80:A5:38:1D:DA:40:57:C0:CC:D3:46:67:02:20:52:EC:61:05:0D:EC:8A:ED:F7:1E:95:67:D0:7C:8B:D9:AA:A5:33:B8:26:26:2E:8F:D7:A7:18:16:2A:83:63:5C";
+ private static String encryptedPKCS8 = "AE:20:81:4F:4D:38:73:C0:51:70:42:DA:C2:EF:61:49:07:E9:B5:D5:55:6D:D1:50:54:B2:0B:41:3E:2F:B6:00:BC:30:89:7B:32:A5:5F:B6:86:92:9E:06:6E:E2:40:8E:3E:E8:0B:CA:97:DB:3E:72:3E:03:22:34:35:EA:5F:B0:71:B2:07:BC:0D:97:94:0A:E6:12:9B:60:7A:77:D4:6C:99:60:2E:68:D6:55:BE:83:B8:A9:0F:19:8A:BE:91:30:D0:FE:52:94:5A:4C:D7:24:07:B3:61:EB:B5:4A:C6:6F:96:8A:C0:20:E9:73:40:FA:A2:56:04:F2:43:35:90:EA:35:C9:8C:08:9D:0B:BC:37:F0:01:D5:DF:BE:E4:4A:57:E0:13:0C:D5:F0:E8:5C:3B:B3:CD:7E:B5:E8:A5:84:63:F6:DA:3E:F2:CF:53:1F:A2:86:44:61:DD:AF:C1:78:70:3A:E6:06:41:77:6C:5B:8D:FA:C4:39:D7:4D:2F:87:D8:31:F4:B6:2B:94:D9:87:17:0E:C8:E3:FA:54:C8:B2:44:56:E0:37:5F:4C:5D:B2:21:DD:15:9E:94:63:89:CF:07:8C:79:F8:65:B2:22:45:D5:F0:2A:70:19:61:16:1D:52:5E:0C:35:3B:20:88:17:7E:FD:05:CC:08:09:2F:05:61:F7:A8:F5:EA:DE:77:DE:5D:55:4E:A0:36:A1:13:FF:2D:57:E8:4E:06:CE:C9:C1:B1:AE:C6:52:A6:EB:35:4C:81:91:DE:71:BA:34:DA:8A:99:1A:47:2E:66:52:AF:E3:2A:E4:0A:27:7F:72:C4:90:7E:8D:8F:64:8D:21:7E:00:DC:1C:62:0F:CC:96:80:C7:E5:5B:70:48:A5:E7:34:27:1A:7C:48:A7:9E:8B:2B:A6:E2";
+
+ private static byte[] parse(String s) {
+ try {
+ int n = s.length();
+ ByteArrayOutputStream out = new ByteArrayOutputStream(n / 3);
+ StringReader r = new StringReader(s);
+ while (true) {
+ int b1 = nextNibble(r);
+ if (b1 < 0) {
+ break;
+ }
+ int b2 = nextNibble(r);
+ if (b2 < 0) {
+ throw new RuntimeException("Invalid string " + s);
+ }
+ int b = (b1 << 4) | b2;
+ out.write(b);
+ }
+ return out.toByteArray();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ private static int nextNibble(StringReader r) throws IOException {
+ while (true) {
+ int ch = r.read();
+ if (ch == -1) {
+ return -1;
+ } else if ((ch >= '0') && (ch <= '9')) {
+ return ch - '0';
+ } else if ((ch >= 'a') && (ch <= 'f')) {
+ return ch - 'a' + 10;
+ } else if ((ch >= 'A') && (ch <= 'F')) {
+ return ch - 'A' + 10;
+ }
+ }
+ }
+
+ public static void main(String[] argv) throws Exception {
+ if (GOOD_PARAMS == null) {
+ throw new Exception("Static parameter generation failed");
+ }
+ byte[] encodedKey = parse(pkcs8Encoded);
+ byte[] encryptedData = parse(encryptedPKCS8);
+ boolean result = true;
+
+ Provider p = Security.getProvider("SunJCE");
+
+ // generate encrypted data and EncryptedPrivateKeyInfo object
+ EncryptedPrivateKeyInfo epki =
+ new EncryptedPrivateKeyInfo(GOOD_PARAMS, encryptedData);
+
+ PKCS8EncodedKeySpec pkcs8Spec;
+ // TEST#1 getKeySpec(Cipher)
+ System.out.println("Testing getKeySpec(Cipher)...");
+ // Prepare Cipher for decryption
+ PBEKeySpec pbeKeySpec = new PBEKeySpec(passwd);
+ SecretKeyFactory skf = SecretKeyFactory.getInstance(cipherAlg, p);
+ SecretKey cipherKey = skf.generateSecret(pbeKeySpec);
+ Cipher cipher = Cipher.getInstance(cipherAlg, p);
+ cipher.init(Cipher.DECRYPT_MODE, cipherKey, GOOD_PARAMS);
+ pkcs8Spec = epki.getKeySpec(cipher);
+ if (Arrays.equals(pkcs8Spec.getEncoded(), encodedKey)) {
+ System.out.println("passed");
+ } else {
+ result = false;
+ }
+
+ // TEST#2 getKeySpec(Key)
+ System.out.println("Testing getKeySpec(Key)...");
+ pkcs8Spec = epki.getKeySpec(cipherKey);
+ if (Arrays.equals(pkcs8Spec.getEncoded(), encodedKey)) {
+ System.out.println("passed");
+ } else {
+ result = false;
+ }
+
+ // TEST#3 getKeySpec(Key, String)
+ System.out.println("Testing getKeySpec(Key, String)...");
+ pkcs8Spec = epki.getKeySpec(cipherKey, p.getName());
+ if (Arrays.equals(pkcs8Spec.getEncoded(), encodedKey)) {
+ System.out.println("passed");
+ } else {
+ result = false;
+ }
+
+ // TEST#4 getKeySpec(Key, Provider)
+ System.out.println("Testing getKeySpec(Key, Provider)...");
+ pkcs8Spec = epki.getKeySpec(cipherKey, p);
+ if (Arrays.equals(pkcs8Spec.getEncoded(), encodedKey)) {
+ System.out.println("passed");
+ } else {
+ result = false;
+ }
+
+ if (result) {
+ System.out.println("All Tests Passed");
+ } else {
+ throw new Exception("One or More Test Failed");
+ }
+ }
+}
diff --git a/test/javax/crypto/EncryptedPrivateKeyInfo/GetKeySpecException.java b/test/javax/crypto/EncryptedPrivateKeyInfo/GetKeySpecException.java
new file mode 100644
index 0000000..ada0146
--- /dev/null
+++ b/test/javax/crypto/EncryptedPrivateKeyInfo/GetKeySpecException.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2003-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 4508341
+ * @summary Test the error conditions of
+ * EncryptedPrivateKeyInfo.getKeySpec(...) methods.
+ * @author Valerie Peng
+ */
+import java.security.*;
+import java.util.Arrays;
+import java.util.Vector;
+import java.security.spec.*;
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+public class GetKeySpecException {
+ private static final String cipherAlg = "PBEWithMD5AndDES";
+ private static final char[] passwd = { 'p','a','s','s','w','d' };
+ private static SecretKey cipherKey;
+ private static Cipher cipher = null;
+ private static byte[] encryptedData = null;
+ private static Provider sunjce = null;
+ private static final SecretKey INVALID_KEY =
+ new SecretKeySpec(new byte[8], "DES");
+ private static AlgorithmParameters BAD_PARAMS;
+ private static AlgorithmParameters GOOD_PARAMS;
+
+ static {
+ try {
+ sunjce = Security.getProvider("SunJCE");
+ PBEParameterSpec badParamSpec =
+ new PBEParameterSpec(new byte[10], 10);
+ BAD_PARAMS = AlgorithmParameters.getInstance(cipherAlg, sunjce);
+ BAD_PARAMS.init(badParamSpec);
+ PBEParameterSpec goodParamSpec =
+ new PBEParameterSpec(new byte[8], 1024);
+ GOOD_PARAMS = AlgorithmParameters.getInstance(cipherAlg, sunjce);
+ GOOD_PARAMS.init(goodParamSpec);
+ PBEKeySpec keySpec = new PBEKeySpec(passwd);
+ SecretKeyFactory skf =
+ SecretKeyFactory.getInstance(cipherAlg, "SunJCE");
+ cipherKey = skf.generateSecret(keySpec);
+ } catch (Exception ex) {
+ // should never happen
+ BAD_PARAMS = null;
+ GOOD_PARAMS = null;
+ }
+ }
+
+ private static void throwException(String msg) throws Exception {
+ throw new Exception(msg);
+ }
+
+ private static Provider[] removeProviders(String cipherAlg) {
+ Vector providers = new Vector();
+ boolean done = false;
+ while (!done) {
+ try {
+ Cipher c = Cipher.getInstance(cipherAlg);
+ Provider p = c.getProvider();
+ providers.add(p);
+ Security.removeProvider(p.getName());
+ } catch (NoSuchAlgorithmException nsae) {
+ done = true;
+ } catch (NoSuchPaddingException nspe) {
+ // should never happen
+ }
+ }
+ return (Provider[]) (providers.toArray(new Provider[0]));
+ }
+
+ private static void addProviders(Provider[] provs) {
+ for (int i=0; i<provs.length; i++) {
+ Security.addProvider(provs[i]);
+ }
+ }
+
+ public static void main(String[] argv) throws Exception {
+ if ((GOOD_PARAMS == null) || (BAD_PARAMS == null)) {
+ throw new Exception("Static parameter generation failed");
+ }
+ // use random data
+ byte[] encryptedData = new byte[30];
+ encryptedData[20] = (byte) 8;
+
+ PKCS8EncodedKeySpec pkcs8Spec = null;
+
+ // generate encrypted data and EncryptedPrivateKeyInfo objects
+ EncryptedPrivateKeyInfo epki =
+ new EncryptedPrivateKeyInfo(GOOD_PARAMS, encryptedData);
+ EncryptedPrivateKeyInfo epkiBad =
+ new EncryptedPrivateKeyInfo(BAD_PARAMS, encryptedData);
+
+ // TEST#1: getKeySpec(Cipher)
+ System.out.println("Testing getKeySpec(Cipher)...");
+ try {
+ pkcs8Spec = epki.getKeySpec((Cipher) null);
+ throwException("Should throw NPE for null Cipher!");
+ } catch (NullPointerException npe) {
+ System.out.println("Expected NPE thrown");
+ }
+
+ // TEST#2: getKeySpec(Key)
+ System.out.println("Testing getKeySpec(Key)...");
+ try {
+ pkcs8Spec = epki.getKeySpec((Key) null);
+ throwException("Should throw NPE for null Key!");
+ } catch (NullPointerException npe) {
+ System.out.println("Expected NPE thrown");
+ }
+ try {
+ pkcs8Spec = epki.getKeySpec(INVALID_KEY);
+ throwException("Should throw IKE for invalid Key!");
+ } catch (InvalidKeyException ikse) {
+ System.out.println("Expected IKE thrown");
+ }
+ try {
+ pkcs8Spec = epkiBad.getKeySpec(cipherKey);
+ throwException("Should throw IKE for corrupted epki!");
+ } catch (InvalidKeyException ike) {
+ System.out.println("Expected IKE thrown");
+ }
+ Provider[] removedProvs = null;
+ try {
+ removedProvs = removeProviders(cipherAlg);
+ pkcs8Spec = epki.getKeySpec(cipherKey);
+ throwException("Should throw NSAE if no matching impl!");
+ } catch (NoSuchAlgorithmException nsae) {
+ System.out.println("Expected NSAE thrown");
+ addProviders(removedProvs);
+ }
+ // TEST#3: getKeySpec(Key, String)
+ System.out.println("Testing getKeySpec(Key, String)...");
+ try {
+ pkcs8Spec = epki.getKeySpec(null, "SunJCE");
+ throwException("Should throw NPE for null Key!");
+ } catch (NullPointerException npe) {
+ System.out.println("Expected NPE thrown");
+ }
+ try {
+ pkcs8Spec = epki.getKeySpec(cipherKey, (String)null);
+ throwException("Should throw NPE for null String!");
+ } catch (NullPointerException npe) {
+ System.out.println("Expected NPE thrown");
+ }
+ try {
+ pkcs8Spec = epki.getKeySpec(INVALID_KEY, "SunJCE");
+ throwException("Should throw IKE for invalid Key!");
+ } catch (InvalidKeyException ikse) {
+ System.out.println("Expected IKE thrown");
+ }
+ try {
+ pkcs8Spec = epkiBad.getKeySpec(cipherKey, "SunJCE");
+ throwException("Should throw IKE for corrupted epki!");
+ } catch (InvalidKeyException ike) {
+ System.out.println("Expected IKE thrown");
+ }
+ try {
+ pkcs8Spec = epki.getKeySpec(cipherKey, "SUN");
+ throwException("Should throw NSAE for provider without " +
+ "matching implementation!");
+ } catch (NoSuchAlgorithmException nsae) {
+ System.out.println("Expected NSAE thrown");
+ }
+ try {
+ Security.removeProvider("SunJCE");
+ pkcs8Spec = epki.getKeySpec(cipherKey, "SunJCE");
+ throwException("Should throw NSPE for unconfigured provider!");
+ } catch (NoSuchProviderException nspe) {
+ System.out.println("Expected NSPE thrown");
+ Security.addProvider(sunjce);
+ }
+ // TEST#4: getKeySpec(Key, Provider)
+ System.out.println("Testing getKeySpec(Key, Provider)...");
+ try {
+ pkcs8Spec = epki.getKeySpec(null, sunjce);
+ throwException("Should throw NPE for null Key!");
+ } catch (NullPointerException npe) {
+ System.out.println("Expected NPE thrown");
+ }
+ try {
+ pkcs8Spec = epki.getKeySpec(cipherKey, (Provider)null);
+ throwException("Should throw NPE for null Provider!");
+ } catch (NullPointerException npe) {
+ System.out.println("Expected NPE thrown");
+ }
+ try {
+ pkcs8Spec = epki.getKeySpec(INVALID_KEY, sunjce);
+ throwException("Should throw IKE for invalid Key!");
+ } catch (InvalidKeyException ikse) {
+ System.out.println("Expected IKE thrown");
+ }
+ try {
+ pkcs8Spec = epkiBad.getKeySpec(cipherKey, sunjce);
+ throwException("Should throw IKE for corrupted epki!");
+ } catch (InvalidKeyException ike) {
+ System.out.println("Expected IKE thrown");
+ }
+ System.out.println("All Tests Passed");
+ }
+}
diff --git a/test/javax/crypto/EncryptedPrivateKeyInfo/GetKeySpecException2.java b/test/javax/crypto/EncryptedPrivateKeyInfo/GetKeySpecException2.java
new file mode 100644
index 0000000..056cdac
--- /dev/null
+++ b/test/javax/crypto/EncryptedPrivateKeyInfo/GetKeySpecException2.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2004-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 5028661
+ * @summary Test the error conditions of Cipher initialized
+ * with wrong mode with EncryptedPrivateKeyInfo.getKeySpec
+ * (Cipher) method.
+ * @author Valerie Peng
+ */
+import java.security.*;
+import java.util.Arrays;
+import java.util.Vector;
+import java.security.spec.*;
+import javax.crypto.*;
+import javax.crypto.interfaces.PBEKey;
+import javax.crypto.spec.*;
+
+public class GetKeySpecException2 {
+ private static final String cipherAlg = "PBEWithMD5AndDES";
+ private static final char[] passwd = { 'p','a','s','s','w','d' };
+
+ public static void main(String[] argv) throws Exception {
+
+ // use random data
+ byte[] encryptedData = new byte[30];
+ encryptedData[20] = (byte) 8;
+
+ // generate encrypted data and EncryptedPrivateKeyInfo objects
+ EncryptedPrivateKeyInfo epki =
+ new EncryptedPrivateKeyInfo(cipherAlg, encryptedData);
+
+ // TEST#1: getKeySpec(Cipher) with Cipher in an illegal state,
+ // i.e. WRAP_MODE, UNWRAP_MODE.
+ System.out.println("Testing getKeySpec(Cipher) with WRAP_MODE...");
+ Cipher c = Cipher.getInstance(cipherAlg, "SunJCE");
+ MyPBEKey key = new MyPBEKey(passwd);
+ c.init(Cipher.WRAP_MODE, key);
+ try {
+ epki.getKeySpec(c);
+ throw new Exception("Should throw InvalidKeyException");
+ } catch (InvalidKeySpecException npe) {
+ System.out.println("Expected IKE thrown");
+ }
+ AlgorithmParameters params = c.getParameters();
+ System.out.println("Testing getKeySpec(Cipher) with UNWRAP_MODE...");
+ c.init(Cipher.UNWRAP_MODE, key, params);
+ try {
+ epki.getKeySpec(c);
+ throw new Exception("Should throw InvalidKeyException");
+ } catch (InvalidKeySpecException npe) {
+ System.out.println("Expected IKE thrown");
+ }
+ System.out.println("All Tests Passed");
+ }
+}
+
+class MyPBEKey implements PBEKey {
+
+ private char[] password = null;
+
+ MyPBEKey(char[] password) {
+ this.password = (char[]) password.clone();
+ }
+ public int getIterationCount() {
+ return 0;
+ }
+ public char[] getPassword() {
+ return (char[]) password.clone();
+ }
+ public byte[] getSalt() {
+ return null;
+ }
+ public String getAlgorithm() {
+ return "PBE";
+ }
+ public String getFormat() {
+ return "RAW";
+ }
+ public byte[] getEncoded() {
+ return new byte[8];
+ }
+}
diff --git a/test/javax/crypto/EncryptedPrivateKeyInfo/GetKeySpecInvalidEncoding.java b/test/javax/crypto/EncryptedPrivateKeyInfo/GetKeySpecInvalidEncoding.java
new file mode 100644
index 0000000..b119452
--- /dev/null
+++ b/test/javax/crypto/EncryptedPrivateKeyInfo/GetKeySpecInvalidEncoding.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2003-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 4900891
+ * @summary Test the EncryptedPrivateKeyInfo.getKeySpec(...)
+ * methods with scenarios where the decrypted bytes are not
+ * encoded correctly per PKCS#8 standard.
+ * @author Valerie Peng
+ */
+import java.util.*;
+import java.nio.*;
+import java.io.*;
+import java.security.*;
+import java.util.Arrays;
+import java.security.spec.*;
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+public class GetKeySpecInvalidEncoding {
+ private static final String cipherAlg = "PBEWithMD5AndDES";
+ private static final char[] passwd = { 'p','a','s','s', 'w', 'd' };
+ private static AlgorithmParameters GOOD_PARAMS;
+
+ static {
+ try {
+ PBEParameterSpec goodParamSpec =
+ new PBEParameterSpec(new byte[8], 6);
+ GOOD_PARAMS = AlgorithmParameters.getInstance
+ (cipherAlg, "SunJCE");
+ GOOD_PARAMS.init(goodParamSpec);
+ } catch (Exception ex) {
+ // should never happen
+ GOOD_PARAMS = null;
+ }
+ }
+
+ private static String encryptedPKCS8 = "5C:BC:13:5D:40:2F:02:28:94:3C:A9:F7:98:A6:58:DC:F9:12:B7:CB:0F:40:DD:66:AB:58:6B:23:2F:8A:5A:81:9D:55:2A:EB:3F:AA:6A:CE:AE:23:8A:96:12:21:5A:09:BF:59:65:3F:B8:48:59:69:C6:D0:9C:48:B6:78:C3:C6:B4:24:F9:BE:10:00:D5:F3:52:88:53:CD:07:CA:88:93:15:3F:BA:19:4A:E9:5D:C7:44:46:49:F6:19:83:86:E0:25:51:9E:83:6D:AE:F2:14:9C:BF:02:7B:8C:64:B4:5F:F1:7B:28:2F:39:55:32:A4:F5:41:85:9E:77:F2:07:09:CD:97:90:5A:04:81:23:30";
+
+ private static byte[] parse(String s) {
+ try {
+ int n = s.length();
+ ByteArrayOutputStream out = new ByteArrayOutputStream(n / 3);
+ StringReader r = new StringReader(s);
+ while (true) {
+ int b1 = nextNibble(r);
+ if (b1 < 0) {
+ break;
+ }
+ int b2 = nextNibble(r);
+ if (b2 < 0) {
+ throw new RuntimeException("Invalid string " + s);
+ }
+ int b = (b1 << 4) | b2;
+ out.write(b);
+ }
+ return out.toByteArray();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ private static int nextNibble(StringReader r) throws IOException {
+ while (true) {
+ int ch = r.read();
+ if (ch == -1) {
+ return -1;
+ } else if ((ch >= '0') && (ch <= '9')) {
+ return ch - '0';
+ } else if ((ch >= 'a') && (ch <= 'f')) {
+ return ch - 'a' + 10;
+ } else if ((ch >= 'A') && (ch <= 'F')) {
+ return ch - 'A' + 10;
+ }
+ }
+ }
+
+ public static void main(String[] argv) throws Exception {
+ if (GOOD_PARAMS == null) {
+ throw new Exception("Static parameter generation failed");
+ }
+ byte[] encryptedData = parse(encryptedPKCS8);
+
+ Provider p = Security.getProvider("SunJCE");
+
+ // generate encrypted data and EncryptedPrivateKeyInfo object
+ EncryptedPrivateKeyInfo epki =
+ new EncryptedPrivateKeyInfo(GOOD_PARAMS, encryptedData);
+
+ PKCS8EncodedKeySpec pkcs8Spec;
+ // TEST#1 getKeySpec(Cipher)
+ System.out.println("Testing getKeySpec(Cipher)...");
+ // Prepare Cipher for decryption
+ PBEKeySpec pbeKeySpec = new PBEKeySpec(passwd);
+ SecretKeyFactory skf = SecretKeyFactory.getInstance(cipherAlg, p);
+ SecretKey cipherKey = skf.generateSecret(pbeKeySpec);
+ Cipher cipher = Cipher.getInstance(cipherAlg, p);
+ cipher.init(Cipher.DECRYPT_MODE, cipherKey, GOOD_PARAMS);
+ try {
+ pkcs8Spec = epki.getKeySpec(cipher);
+ throw new Exception("getKeySpec(Cipher): should throw IKSE");
+ } catch (InvalidKeySpecException ikse) {
+ // expected
+ }
+ // TEST#2 getKeySpec(Key)
+ System.out.println("Testing getKeySpec(Key)...");
+ try {
+ pkcs8Spec = epki.getKeySpec(cipherKey);
+ throw new Exception("getKeySpec(Key): should throw IKE");
+ } catch (InvalidKeyException ike) {
+ // expected
+ }
+
+ // TEST#3 getKeySpec(Key, String)
+ System.out.println("Testing getKeySpec(Key, String)...");
+ try {
+ pkcs8Spec = epki.getKeySpec(cipherKey, p.getName());
+ throw new Exception("getKeySpec(Key, String): should throw IKE");
+ } catch (InvalidKeyException ike) {
+ // expected
+ }
+
+ // TEST#4 getKeySpec(Key, Provider)
+ System.out.println("Testing getKeySpec(Key, Provider)...");
+ try {
+ pkcs8Spec = epki.getKeySpec(cipherKey, p);
+ throw new Exception("getKeySpec(Key, Provider): should throw IKE");
+ } catch (InvalidKeyException ike) {
+ // expected
+ }
+ System.out.println("All Tests Passed");
+ }
+}
diff --git a/test/javax/crypto/JceSecurity/MyCertificateFactory.java b/test/javax/crypto/JceSecurity/MyCertificateFactory.java
new file mode 100644
index 0000000..eed1ac1
--- /dev/null
+++ b/test/javax/crypto/JceSecurity/MyCertificateFactory.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2006-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * test
+ * @bug 6377058
+ * @summary SunJCE depends on sun.security.provider.SignatureImpl
+ * behaviour, BC can't load into 1st slot.
+ * @author Brad R. Wetmore
+ */
+
+import java.io.*;
+import java.util.*;
+import java.security.cert.*;
+import java.security.cert.CertificateException;
+
+public class MyCertificateFactory extends CertificateFactorySpi {
+
+ CertificateFactory cf;
+
+ public MyCertificateFactory() {
+ try {
+ cf = CertificateFactory.getInstance("X.509", "SUN");
+ } catch (Exception e) {
+ throw new RuntimeException(
+ "Couldn't create the Sun X.509 CertificateFactory");
+ }
+ }
+
+ public Certificate engineGenerateCertificate(InputStream inStream)
+ throws CertificateException {
+
+ Certificate cert = cf.generateCertificate(inStream);
+ if (!(cert instanceof X509Certificate)) {
+ throw new RuntimeException("Not an X509Certificate");
+ }
+ return new MyX509CertImpl((X509Certificate)cert);
+ }
+
+ public CertPath engineGenerateCertPath(InputStream inStream)
+ throws CertificateException {
+ return cf.generateCertPath(inStream);
+ }
+
+ public CertPath engineGenerateCertPath(InputStream inStream,
+ String encoding)
+ throws CertificateException {
+ return cf.generateCertPath(inStream, encoding);
+ }
+
+ public CertPath
+ engineGenerateCertPath(List<? extends Certificate> certificates)
+ throws CertificateException {
+ return cf.generateCertPath(certificates);
+ }
+
+ public Iterator<String> engineGetCertPathEncodings() {
+ return cf.getCertPathEncodings();
+ }
+
+ public Collection<? extends Certificate>
+ engineGenerateCertificates(InputStream inStream)
+ throws CertificateException {
+ return cf.generateCertificates(inStream);
+ }
+
+ public CRL engineGenerateCRL(InputStream inStream)
+ throws CRLException {
+ return cf.generateCRL(inStream);
+ }
+
+ public Collection<? extends CRL> engineGenerateCRLs
+ (InputStream inStream) throws CRLException {
+ return cf.generateCRLs(inStream);
+ }
+}
diff --git a/test/javax/crypto/JceSecurity/MyProvider.java b/test/javax/crypto/JceSecurity/MyProvider.java
new file mode 100644
index 0000000..ba9c4da
--- /dev/null
+++ b/test/javax/crypto/JceSecurity/MyProvider.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2006-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * test
+ * @bug 6377058
+ * @summary SunJCE depends on sun.security.provider.SignatureImpl
+ * behaviour, BC can't load into 1st slot.
+ * @author Brad R. Wetmore
+ */
+
+import java.security.*;
+
+public class MyProvider extends Provider {
+
+ public MyProvider() {
+ super("MyProvider", 1.0, "CertImpl");
+ put("CertificateFactory.X.509", "MyCertificateFactory");
+ }
+}
diff --git a/test/javax/crypto/JceSecurity/MyX509CertImpl.java b/test/javax/crypto/JceSecurity/MyX509CertImpl.java
new file mode 100644
index 0000000..dc015d4
--- /dev/null
+++ b/test/javax/crypto/JceSecurity/MyX509CertImpl.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2006-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * test
+ * @bug 6377058
+ * @summary SunJCE depends on sun.security.provider.SignatureImpl
+ * behaviour, BC can't load into 1st slot.
+ * @author Brad R. Wetmore
+ */
+
+
+import java.util.*;
+import java.math.*;
+import java.security.*;
+import java.security.cert.*;
+import javax.security.auth.x500.*;
+
+public class MyX509CertImpl extends X509Certificate
+ implements X509Extension {
+
+ X509Certificate c;
+
+ protected MyX509CertImpl(X509Certificate cert) {
+ c = cert;
+ }
+
+ public void checkValidity() throws CertificateExpiredException,
+ CertificateNotYetValidException {
+ c.checkValidity();
+ }
+
+
+ public void checkValidity(Date date) throws CertificateExpiredException,
+ CertificateNotYetValidException {
+ c.checkValidity(date);
+ }
+
+ public int getVersion() {
+ return c.getVersion();
+ }
+
+ public BigInteger getSerialNumber() {
+ return c.getSerialNumber();
+ }
+
+ public Principal getIssuerDN() {
+ return c.getIssuerDN();
+ }
+
+ public X500Principal getIssuerX500Principal() {
+ return c.getIssuerX500Principal();
+ }
+
+ public Principal getSubjectDN() {
+ return c.getSubjectDN();
+ }
+
+ public X500Principal getSubjectX500Principal() {
+ return c.getSubjectX500Principal();
+ }
+
+ public Date getNotBefore() {
+ return c.getNotBefore();
+ }
+
+ public Date getNotAfter() {
+ return c.getNotAfter();
+ }
+
+ public byte[] getTBSCertificate()
+ throws CertificateEncodingException {
+ return c.getTBSCertificate();
+ }
+
+ public byte[] getSignature() {
+ return c.getSignature();
+ }
+
+ public String getSigAlgName() {
+ return c.getSigAlgName();
+ }
+
+ public String getSigAlgOID() {
+ return c.getSigAlgOID();
+ }
+
+ public byte[] getSigAlgParams() {
+ return c.getSigAlgParams();
+ }
+
+ public boolean[] getIssuerUniqueID() {
+ return c.getIssuerUniqueID();
+ }
+
+ public boolean[] getSubjectUniqueID() {
+ return c.getSubjectUniqueID();
+ }
+
+ public boolean[] getKeyUsage() {
+ return c.getKeyUsage();
+ }
+
+ public List<String> getExtendedKeyUsage()
+ throws CertificateParsingException {
+ return c.getExtendedKeyUsage();
+ }
+
+ public int getBasicConstraints() {
+ return c.getBasicConstraints();
+ }
+
+ public Collection<List<?>> getSubjectAlternativeNames()
+ throws CertificateParsingException {
+ return c.getSubjectAlternativeNames();
+ }
+
+ public Collection<List<?>> getIssuerAlternativeNames()
+ throws CertificateParsingException {
+ return c.getIssuerAlternativeNames();
+ }
+
+ /*
+ * The following are from X509Extension
+ */
+ public boolean hasUnsupportedCriticalExtension() {
+ return c.hasUnsupportedCriticalExtension();
+ }
+
+ public Set<String> getCriticalExtensionOIDs() {
+ return c.getCriticalExtensionOIDs();
+ }
+
+ public Set<String> getNonCriticalExtensionOIDs() {
+ return c.getNonCriticalExtensionOIDs();
+ }
+
+ public byte[] getExtensionValue(String oid) {
+ return c.getExtensionValue(oid);
+ }
+
+ /*
+ * The rest are from Certificate
+ */
+ public boolean equals(Object other) {
+ return c.equals(other);
+ }
+
+ public int hashCode() {
+ return c.hashCode();
+ }
+
+ public byte[] getEncoded()
+ throws CertificateEncodingException {
+ return c.getEncoded();
+ }
+
+ public void verify(PublicKey key)
+ throws CertificateException, NoSuchAlgorithmException,
+ InvalidKeyException, NoSuchProviderException,
+ SignatureException {
+ System.out.println("Trying a verify");
+ try {
+ c.verify(key);
+ } catch (SignatureException e) {
+ System.out.println("Rethrowing \"acceptable\" exception");
+ throw new InvalidKeyException(
+ "Rethrowing as a SignatureException", e);
+ }
+ }
+
+ public void verify(PublicKey key, String sigProvider)
+ throws CertificateException, NoSuchAlgorithmException,
+ InvalidKeyException, NoSuchProviderException,
+ SignatureException {
+
+ System.out.println("Trying a verify");
+ try {
+ c.verify(key, sigProvider);
+ } catch (SignatureException e) {
+ System.out.println("Rethrowing \"acceptable\" exception");
+ throw new InvalidKeyException(
+ "Rethrowing as a SignatureException", e);
+ }
+ }
+
+ public String toString() {
+ return c.toString();
+ }
+
+ public PublicKey getPublicKey() {
+ return c.getPublicKey();
+ }
+}
diff --git a/test/javax/crypto/JceSecurity/SunJCE_BC_LoadOrdering.java b/test/javax/crypto/JceSecurity/SunJCE_BC_LoadOrdering.java
new file mode 100644
index 0000000..279d73d
--- /dev/null
+++ b/test/javax/crypto/JceSecurity/SunJCE_BC_LoadOrdering.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2006-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6377058
+ * @summary SunJCE depends on sun.security.provider.SignatureImpl
+ * behaviour, BC can't load into 1st slot.
+ * @author Brad R. Wetmore
+ */
+
+import java.security.*;
+import javax.crypto.*;
+import java.io.*;
+
+public class SunJCE_BC_LoadOrdering {
+
+ public static void main(String args[]) throws Exception {
+ /*
+ * Generate a random key, and encrypt the data
+ */
+ Security.insertProviderAt(new MyProvider(), 1);
+ KeyGenerator keyGen = KeyGenerator.getInstance("DES");
+ keyGen.init(new SecureRandom());
+
+ Key key = keyGen.generateKey();
+
+ Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
+ cipher.init(Cipher.ENCRYPT_MODE, key);
+
+ cipher.doFinal("some string".getBytes());
+ }
+}
diff --git a/test/javax/crypto/KeyGenerator/TestGetInstance.java b/test/javax/crypto/KeyGenerator/TestGetInstance.java
new file mode 100644
index 0000000..dcd7b6a
--- /dev/null
+++ b/test/javax/crypto/KeyGenerator/TestGetInstance.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2003-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4898428
+ * @summary test that the new getInstance() implementation works correctly
+ * @author Andreas Sterbenz
+ */
+
+import java.security.*;
+
+import javax.crypto.*;
+
+public class TestGetInstance {
+
+ private static void same(Object o1, Object o2) throws Exception {
+ if (o1 != o2) {
+ throw new Exception("not same object");
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ long start = System.currentTimeMillis();
+
+ Provider p = Security.getProvider("SunJCE");
+
+ KeyGenerator kg;
+
+ kg = KeyGenerator.getInstance("des");
+ System.out.println("Default: " + kg.getProvider().getName());
+ kg = KeyGenerator.getInstance("des", "SunJCE");
+ same(p, kg.getProvider());
+ kg = KeyGenerator.getInstance("des", p);
+ same(p, kg.getProvider());
+
+ try {
+ kg = KeyGenerator.getInstance("foo");
+ throw new AssertionError();
+ } catch (NoSuchAlgorithmException e) {
+ System.out.println(e);
+ }
+ try {
+ kg = KeyGenerator.getInstance("foo", "SunJCE");
+ throw new AssertionError();
+ } catch (NoSuchAlgorithmException e) {
+ System.out.println(e);
+ }
+ try {
+ kg = KeyGenerator.getInstance("foo", p);
+ throw new AssertionError();
+ } catch (NoSuchAlgorithmException e) {
+ System.out.println(e);
+ }
+
+ try {
+ kg = KeyGenerator.getInstance("foo", "SUN");
+ throw new AssertionError();
+ } catch (NoSuchAlgorithmException e) {
+ System.out.println(e);
+ }
+ try {
+ kg = KeyGenerator.getInstance("foo", Security.getProvider("SUN"));
+ throw new AssertionError();
+ } catch (NoSuchAlgorithmException e) {
+ System.out.println(e);
+ }
+ try {
+ kg = KeyGenerator.getInstance("foo", "foo");
+ throw new AssertionError();
+ } catch (NoSuchProviderException e) {
+ System.out.println(e);
+ }
+
+ long stop = System.currentTimeMillis();
+ System.out.println("Done (" + (stop - start) + " ms).");
+ }
+}
diff --git a/test/javax/crypto/Mac/ByteBuffers.java b/test/javax/crypto/Mac/ByteBuffers.java
new file mode 100644
index 0000000..fe65560
--- /dev/null
+++ b/test/javax/crypto/Mac/ByteBuffers.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2003-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 4844847
+ * @summary Test the Mac.update(ByteBuffer) method
+ * @author Andreas Sterbenz
+ */
+
+import java.util.*;
+import java.nio.*;
+
+import java.security.*;
+
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+public class ByteBuffers {
+
+ public static void main(String[] args) throws Exception {
+ Provider p = Security.getProvider("SunJCE");
+ Random random = new Random();
+ int n = 10 * 1024;
+ byte[] t = new byte[n];
+ random.nextBytes(t);
+
+ byte[] keyBytes = new byte[16];
+ random.nextBytes(keyBytes);
+ SecretKey key = new SecretKeySpec(keyBytes, "HmacMD5");
+
+ Mac mac = Mac.getInstance("HmacMD5");
+ mac.init(key);
+ byte[] macValue = mac.doFinal(t);
+
+ // test 1: ByteBuffer with an accessible backing array
+ ByteBuffer b1 = ByteBuffer.allocate(n + 256);
+ b1.position(random.nextInt(256));
+ b1.limit(b1.position() + n);
+ ByteBuffer b2 = b1.slice();
+ b2.put(t);
+ b2.clear();
+ verify(mac, macValue, b2, random);
+
+ // test 2: direct ByteBuffer
+ ByteBuffer b3 = ByteBuffer.allocateDirect(t.length);
+ b3.put(t);
+ b3.clear();
+ verify(mac, macValue, b3, random);
+
+ // test 3: ByteBuffer without an accessible backing array
+ b2.clear();
+ ByteBuffer b4 = b2.asReadOnlyBuffer();
+ verify(mac, macValue, b4, random);
+
+ System.out.println("All tests passed");
+ }
+
+ private static void verify(Mac mac, byte[] macValue, ByteBuffer b, Random random) throws Exception {
+ int lim = b.limit();
+ b.limit(random.nextInt(lim));
+ mac.update(b);
+ if (b.hasRemaining()) {
+ throw new Exception("Buffer not consumed");
+ }
+ b.limit(lim);
+ mac.update(b);
+ if (b.hasRemaining()) {
+ throw new Exception("Buffer not consumed");
+ }
+ byte[] newMacValue = mac.doFinal();
+ if (Arrays.equals(macValue, newMacValue) == false) {
+ throw new Exception("Mac did not verify");
+ }
+ }
+}
diff --git a/test/javax/crypto/Mac/NullMacSpi.java b/test/javax/crypto/Mac/NullMacSpi.java
new file mode 100644
index 0000000..ea23476
--- /dev/null
+++ b/test/javax/crypto/Mac/NullMacSpi.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2003-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4955833
+ * @summary Make sure that there is no unexpected NPE when calling
+ * getProvider() with null MacSpi object.
+ * @author Valerie Peng
+ */
+import javax.crypto.*;
+import java.security.Provider;
+
+public class NullMacSpi {
+
+ public static void main(String[] args) throws Exception {
+ MyMac mm = new MyMac(null, null, null);
+ if (mm.getProvider() == null) {
+ System.out.println("Test Passed");
+ }
+ }
+}
+
+class MyMac extends Mac {
+ public MyMac(MacSpi macSpi, Provider provider,String algorithm) {
+ super(macSpi, provider, algorithm);
+ }
+}
diff --git a/test/javax/crypto/Mac/TestGetInstance.java b/test/javax/crypto/Mac/TestGetInstance.java
new file mode 100644
index 0000000..8e3c6b4
--- /dev/null
+++ b/test/javax/crypto/Mac/TestGetInstance.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2003-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4898428
+ * @summary test that the new getInstance() implementation works correctly
+ * @author Andreas Sterbenz
+ */
+
+import java.security.*;
+
+import javax.crypto.*;
+
+public class TestGetInstance {
+
+ private static void same(Object o1, Object o2) throws Exception {
+ if (o1 != o2) {
+ throw new Exception("not same object");
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ long start = System.currentTimeMillis();
+
+ Provider p = Security.getProvider("SunJCE");
+
+ Mac mac;
+
+ mac = Mac.getInstance("hmacmd5");
+ System.out.println("Default: " + mac.getProvider().getName());
+ mac = Mac.getInstance("hmacmd5", "SunJCE");
+ same(p, mac.getProvider());
+ mac = Mac.getInstance("hmacmd5", p);
+ same(p, mac.getProvider());
+
+ try {
+ mac = Mac.getInstance("foo");
+ throw new AssertionError();
+ } catch (NoSuchAlgorithmException e) {
+ System.out.println(e);
+ }
+ try {
+ mac = Mac.getInstance("foo", "SunJCE");
+ throw new AssertionError();
+ } catch (NoSuchAlgorithmException e) {
+ System.out.println(e);
+ }
+ try {
+ mac = Mac.getInstance("foo", p);
+ throw new AssertionError();
+ } catch (NoSuchAlgorithmException e) {
+ System.out.println(e);
+ }
+
+ try {
+ mac = Mac.getInstance("foo", "SUN");
+ throw new AssertionError();
+ } catch (NoSuchAlgorithmException e) {
+ System.out.println(e);
+ }
+ try {
+ mac = Mac.getInstance("foo", Security.getProvider("SUN"));
+ throw new AssertionError();
+ } catch (NoSuchAlgorithmException e) {
+ System.out.println(e);
+ }
+ try {
+ mac = Mac.getInstance("foo", "foo");
+ throw new AssertionError();
+ } catch (NoSuchProviderException e) {
+ System.out.println(e);
+ }
+ long stop = System.currentTimeMillis();
+ System.out.println("Done (" + (stop - start) + " ms).");
+ }
+}
diff --git a/test/javax/crypto/NullCipher/TestNPE.java b/test/javax/crypto/NullCipher/TestNPE.java
new file mode 100644
index 0000000..b69d10b
--- /dev/null
+++ b/test/javax/crypto/NullCipher/TestNPE.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2003-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4937853
+ * @summary Make sure normal calls of NullCipher does not throw NPE.
+ * @author Valerie Peng
+ */
+import java.util.Arrays;
+import java.security.AlgorithmParameters;
+import java.security.Key;
+import java.security.SecureRandom;
+import java.security.cert.Certificate;
+import java.security.spec.AlgorithmParameterSpec;
+import javax.crypto.Cipher;
+import javax.crypto.NullCipher;
+import javax.crypto.spec.SecretKeySpec;
+
+public class TestNPE {
+ private static byte[] BYTES = new byte[16];
+ static {
+ new SecureRandom().nextBytes(BYTES);
+ }
+
+ public static void main(String[] args) throws Exception {
+ NullCipher nc = new NullCipher();
+ // testing init(...)
+ nc.init(Cipher.ENCRYPT_MODE, (Certificate) null);
+ nc.init(Cipher.ENCRYPT_MODE, (Certificate) null, (SecureRandom) null);
+ nc.init(Cipher.ENCRYPT_MODE, (Key) null);
+ nc.init(Cipher.ENCRYPT_MODE, (Key) null, (AlgorithmParameters) null);
+ nc.init(Cipher.ENCRYPT_MODE, (Key) null, (AlgorithmParameterSpec) null);
+ nc.init(Cipher.ENCRYPT_MODE, (Key) null, (AlgorithmParameterSpec) null,
+ (SecureRandom) null);
+ nc.init(Cipher.ENCRYPT_MODE, (Key) null, (AlgorithmParameters) null,
+ (SecureRandom) null);
+ nc.init(Cipher.ENCRYPT_MODE, (Key) null, (SecureRandom) null);
+ // testing getBlockSize()
+ if (nc.getBlockSize() != 1) {
+ throw new Exception("Error with getBlockSize()");
+ }
+ // testing update(...)
+ byte[] out = nc.update(BYTES);
+ if (!Arrays.equals(out, BYTES)) {
+ throw new Exception("Error with update(byte[])");
+ }
+ out = nc.update(BYTES, 0, BYTES.length);
+ if (!Arrays.equals(out, BYTES)) {
+ throw new Exception("Error with update(byte[], int, int)");
+ }
+ if (nc.update(BYTES, 0, BYTES.length, out) != BYTES.length) {
+ throw new Exception("Error with update(byte[], int, int, byte[])");
+ }
+ if (nc.update(BYTES, 0, BYTES.length, out, 0) != BYTES.length) {
+ throw new Exception(
+ "Error with update(byte[], int, int, byte[], int)");
+ }
+ // testing doFinal(...)
+ if (nc.doFinal() != null) {
+ throw new Exception("Error with doFinal()");
+ }
+ if (nc.doFinal(out, 0) != 0) {
+ throw new Exception("Error with doFinal(byte[], 0)");
+ }
+ out = nc.doFinal(BYTES);
+ if (!Arrays.equals(out, BYTES)) {
+ throw new Exception("Error with doFinal(byte[])");
+ }
+ out = nc.doFinal(BYTES, 0, BYTES.length);
+ if (!Arrays.equals(out, BYTES)) {
+ throw new Exception("Error with doFinal(byte[], int, int)");
+ }
+ if (nc.doFinal(BYTES, 0, BYTES.length, out) != BYTES.length) {
+ throw new Exception(
+ "Error with doFinal(byte[], int, int, byte[])");
+ }
+ if (nc.doFinal(BYTES, 0, BYTES.length, out, 0) != BYTES.length) {
+ throw new Exception(
+ "Error with doFinal(byte[], int, int, byte[], int)");
+ }
+ // testing getExemptionMechanism()
+ if (nc.getExemptionMechanism() != null) {
+ throw new Exception("Error with getExemptionMechanism()");
+ }
+ // testing getOutputSize(int)
+ if (nc.getOutputSize(5) != 5) {
+ throw new Exception("Error with getOutputSize()");
+ }
+ // testing getIV(), getParameters(), getAlgorithm(), etc.
+ if (nc.getIV() == null) { // should've been null;
+ // left it as is for backward-compatibility
+ throw new Exception("Error with getIV()");
+ }
+ if (nc.getParameters() != null) {
+ throw new Exception("Error with getParameters()");
+ }
+ if (nc.getAlgorithm() != null) {
+ throw new Exception("Error with getAlgorithm()");
+ }
+ if (nc.getProvider() != null) { // not associated with any provider
+ throw new Exception("Error with getProvider()");
+ }
+ System.out.println("Test Done");
+ }
+}
diff --git a/test/javax/crypto/NullCipher/TestWithoutInit.java b/test/javax/crypto/NullCipher/TestWithoutInit.java
new file mode 100644
index 0000000..b5c4e4f
--- /dev/null
+++ b/test/javax/crypto/NullCipher/TestWithoutInit.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2004-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4991790
+ * @summary Make sure NullCipher can be used without initialization.
+ * @author Valerie Peng
+ */
+import java.io.PrintStream;
+import java.util.Random;
+import java.security.*;
+import java.security.spec.*;
+
+import javax.crypto.*;
+import javax.crypto.spec.*;
+import com.sun.crypto.provider.*;
+
+public class TestWithoutInit {
+
+ public static void main(String argv[]) throws Exception {
+ // Initialization
+ Cipher ci = new NullCipher();
+
+ byte[] in = new byte[8];
+
+ // try calling doFinal() directly
+ ci.doFinal(in);
+
+ // try calling update() directly
+ ci.update(in);
+ ci.doFinal(); // reset cipher state
+
+ // try calling wrap() and unwrap() directly
+ Key key = new SecretKeySpec(in, "any");
+ try {
+ ci.wrap(key);
+ } catch (UnsupportedOperationException uoe) {
+ // expected
+ }
+ try {
+ ci.unwrap(in, "any", Cipher.SECRET_KEY);
+ } catch (UnsupportedOperationException uoe) {
+ // expected
+ }
+ System.out.println("Test Passed");
+ }
+}
diff --git a/test/javax/crypto/SealedObject/NullKeySealedObject.java b/test/javax/crypto/SealedObject/NullKeySealedObject.java
new file mode 100644
index 0000000..b7e3c7f
--- /dev/null
+++ b/test/javax/crypto/SealedObject/NullKeySealedObject.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2005-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6205732
+ * @summary (spec) javax.crypto.SealedObject.getObject(Key, String): NPE
+ * is not specified
+ * @author Brad R. Wetmore
+ */
+import java.security.*;
+import javax.crypto.*;
+import javax.crypto.spec.*;
+import java.util.Arrays;
+
+public class NullKeySealedObject {
+
+ public static void main(String[] argv) throws Exception {
+
+ Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding");
+ SecretKey cipherKey = new SecretKeySpec(new byte[8], "DES");
+
+ Key obj = new SecretKeySpec(new byte[8], "ANY");
+ c.init(Cipher.ENCRYPT_MODE, cipherKey);
+ SealedObject so = new SealedObject(obj, c);
+
+ try {
+ so.getObject((Key)null);
+ throw new Exception("Sealed Object didn't throw an exception");
+ } catch (NullPointerException e) {
+ System.out.println("Got expected NullPointer");
+ }
+
+ try {
+ so.getObject((Key)null, "ANY");
+ throw new Exception("Sealed Object didn't throw an exception");
+ } catch (NullPointerException e) {
+ System.out.println("Got expected NullPointer");
+ }
+ }
+}
diff --git a/test/javax/crypto/SecretKeyFactory/FailOverTest.java b/test/javax/crypto/SecretKeyFactory/FailOverTest.java
new file mode 100644
index 0000000..04c89b7
--- /dev/null
+++ b/test/javax/crypto/SecretKeyFactory/FailOverTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2006-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * test
+ * @bug 6370923
+ * @summary SecretKeyFactory failover does not work
+ * @author Brad R. Wetmore
+ */
+
+import java.security.*;
+import javax.crypto.*;
+
+public class FailOverTest {
+
+ public static void main(String args[]) throws Exception {
+ Provider p1 = new com.p1.Provider1();
+ Provider p2 = new com.p2.Provider2();
+
+ Security.insertProviderAt(p1, 1);
+ Security.insertProviderAt(p2, 2);
+
+ SecretKeyFactory skf = SecretKeyFactory.getInstance("DUMMY");
+ skf.translateKey((SecretKey)null);
+
+ if (skf.getProvider() != p2) {
+ throw new Exception("Should have gotten Provider 2");
+ } else {
+ System.out.println("Test Passed!");
+ }
+ }
+}
diff --git a/test/javax/crypto/SecretKeyFactory/FailOverTest.sh b/test/javax/crypto/SecretKeyFactory/FailOverTest.sh
new file mode 100644
index 0000000..b433ded
--- /dev/null
+++ b/test/javax/crypto/SecretKeyFactory/FailOverTest.sh
@@ -0,0 +1,90 @@
+#
+# Copyright 2006-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+#
+# @test
+# @bug 6370923
+# @summary SecretKeyFactory failover does not work
+# @author Brad R. Wetmore
+#
+
+if [ "${TESTJAVA}" = "" ]
+then
+ echo "TESTJAVA not set. Test cannot execute. Failed."
+ exit 1
+fi
+echo "TESTJAVA=${TESTJAVA}"
+
+if [ "${TESTSRC}" = "" ]
+then
+ TESTSRC="."
+fi
+echo "TESTSRC=${TESTSRC}"
+
+
+if [ "${TESTCLASSES}" = "" ]
+then
+ TESTCLASSES="."
+fi
+echo "TESTCLASSES=${TESTCLASSES}"
+
+# set platform-dependent variables
+OS=`uname -s`
+case "$OS" in
+ SunOS | Linux )
+ NULL=/dev/null
+ PS=":"
+ FS="/"
+ ;;
+ Windows* )
+ NULL=NUL
+ PS=";"
+ FS="\\"
+ ;;
+ * )
+ echo "Unrecognized system!"
+ exit 1;
+ ;;
+esac
+
+${TESTJAVA}${FS}bin${FS}javac \
+ -d . \
+ -classpath ${TESTSRC}${FS}P1.jar${PS}${TESTSRC}${FS}P2.jar \
+ ${TESTSRC}${FS}FailOverTest.java
+
+if [ $? -ne 0 ]; then
+ exit 1
+fi
+
+${TESTJAVA}${FS}bin${FS}java \
+ -classpath ${TESTSRC}${FS}P1.jar${PS}${TESTSRC}${FS}P2.jar${PS}. \
+ FailOverTest
+result=$?
+
+if [ $result -eq 0 ]
+then
+ echo "Passed"
+else
+ echo "Failed"
+fi
+exit $result
diff --git a/test/javax/crypto/SecretKeyFactory/P1.jar b/test/javax/crypto/SecretKeyFactory/P1.jar
new file mode 100644
index 0000000..f8aae38
--- /dev/null
+++ b/test/javax/crypto/SecretKeyFactory/P1.jar
Binary files differ
diff --git a/test/javax/crypto/SecretKeyFactory/P1SecretKeyFactory.java b/test/javax/crypto/SecretKeyFactory/P1SecretKeyFactory.java
new file mode 100644
index 0000000..3f37aa7
--- /dev/null
+++ b/test/javax/crypto/SecretKeyFactory/P1SecretKeyFactory.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2006-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * test
+ * @bug 6370923
+ * @summary SecretKeyFactory failover does not work
+ * @author Brad R. Wetmore
+ */
+
+package com.p1;
+
+import java.security.*;
+import java.security.spec.*;
+import javax.crypto.*;
+
+public class P1SecretKeyFactory extends SecretKeyFactorySpi {
+
+ public P1SecretKeyFactory() {
+ System.out.println("Creating a P1SecretKeyFactory");
+ }
+
+ protected SecretKey engineGenerateSecret(KeySpec keySpec)
+ throws InvalidKeySpecException {
+ System.out.println("Trying the broken provider");
+ throw new InvalidKeySpecException("I'm broken!!!");
+ }
+
+ protected KeySpec engineGetKeySpec(SecretKey key, Class keySpec)
+ throws InvalidKeySpecException {
+ System.out.println("Trying the broken provider");
+ throw new InvalidKeySpecException("I'm broken!!!");
+ }
+
+ protected SecretKey engineTranslateKey(SecretKey key)
+ throws InvalidKeyException {
+ System.out.println("Trying the broken provider");
+ throw new InvalidKeyException("I'm broken!!!");
+ }
+}
diff --git a/test/javax/crypto/SecretKeyFactory/P2.jar b/test/javax/crypto/SecretKeyFactory/P2.jar
new file mode 100644
index 0000000..d828f45
--- /dev/null
+++ b/test/javax/crypto/SecretKeyFactory/P2.jar
Binary files differ
diff --git a/test/javax/crypto/SecretKeyFactory/P2SecretKeyFactory.java b/test/javax/crypto/SecretKeyFactory/P2SecretKeyFactory.java
new file mode 100644
index 0000000..86858de
--- /dev/null
+++ b/test/javax/crypto/SecretKeyFactory/P2SecretKeyFactory.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2006-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * test
+ * @bug 6370923
+ * @summary SecretKeyFactory failover does not work
+ * @author Brad R. Wetmore
+ */
+
+package com.p2;
+
+import java.security.*;
+import java.security.spec.*;
+import javax.crypto.*;
+
+public class P2SecretKeyFactory extends SecretKeyFactorySpi {
+
+ public P2SecretKeyFactory() {
+ System.out.println("Creating a P2SecretKeyFactory");
+ }
+
+ protected SecretKey engineGenerateSecret(KeySpec keySpec)
+ throws InvalidKeySpecException {
+ System.out.println("Trying the good provider");
+ return null;
+ }
+
+ protected KeySpec engineGetKeySpec(SecretKey key, Class keySpec)
+ throws InvalidKeySpecException {
+ System.out.println("Trying the good provider");
+ return null;
+ }
+
+ protected SecretKey engineTranslateKey(SecretKey key)
+ throws InvalidKeyException {
+ System.out.println("Trying the good provider");
+ return null;
+ }
+}
diff --git a/test/javax/crypto/SecretKeyFactory/Provider1.java b/test/javax/crypto/SecretKeyFactory/Provider1.java
new file mode 100644
index 0000000..aad6269
--- /dev/null
+++ b/test/javax/crypto/SecretKeyFactory/Provider1.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2006-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * test
+ * @bug 6370923
+ * @summary SecretKeyFactory failover does not work
+ * @author Brad R. Wetmore
+ */
+
+package com.p1;
+
+import java.security.*;
+
+public class Provider1 extends Provider {
+
+ public Provider1() {
+ super("Provider1", 1.0, "SecretKeyFactory");
+ System.out.println("Creating Provider1");
+ put("SecretKeyFactory.DUMMY", "com.p1.P1SecretKeyFactory");
+ }
+}
diff --git a/test/javax/crypto/SecretKeyFactory/Provider2.java b/test/javax/crypto/SecretKeyFactory/Provider2.java
new file mode 100644
index 0000000..1f5dd87
--- /dev/null
+++ b/test/javax/crypto/SecretKeyFactory/Provider2.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2006-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * test
+ * @bug 6370923
+ * @summary SecretKeyFactory failover does not work
+ * @author Brad R. Wetmore
+ */
+
+package com.p2;
+
+import java.security.*;
+
+public class Provider2 extends Provider {
+
+ public Provider2() {
+ super("Provider2", 1.0, "SecretKeyFactory");
+ System.out.println("Creating Provider2");
+ put("SecretKeyFactory.DUMMY", "com.p2.P2SecretKeyFactory");
+ }
+}
diff --git a/test/javax/crypto/SecretKeyFactory/README.FailOverTest b/test/javax/crypto/SecretKeyFactory/README.FailOverTest
new file mode 100644
index 0000000..86f8822
--- /dev/null
+++ b/test/javax/crypto/SecretKeyFactory/README.FailOverTest
@@ -0,0 +1,16 @@
+To recreate P1.jar/P2.jar, although I doubt this will ever be necessary, do
+the following.
+
+mkdir classes
+javac -d classes \
+ P1SecretKeyFactory.java Provider1.java \
+ P2SecretKeyFactory.java Provider2.java
+
+cd classes
+jar -cvf ../P1.jar com/p1
+jar -cvf ../P2.jar com/p2
+cd ..
+rm -rf classes
+
+jarsigner -keystore YourJCESigningKeyKeyStore.ks P1.jar yourKeySigningAlias
+jarsigner -keystore YourJCESigningKeyKeyStore.ks P2.jar yourKeySigningAlias
diff --git a/test/javax/crypto/spec/DESKeySpec/CheckParity.java b/test/javax/crypto/spec/DESKeySpec/CheckParity.java
new file mode 100644
index 0000000..d781287
--- /dev/null
+++ b/test/javax/crypto/spec/DESKeySpec/CheckParity.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2005-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6325952
+ * @summary DESKey constructor is parity-adjusting the parameters
+ * @author Brad R. Wetmore
+ */
+import java.security.InvalidKeyException;
+import java.util.Arrays;
+import java.security.spec.KeySpec;
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+public class CheckParity {
+
+ static byte [] testKey = {
+ (byte)0x00, // 00000000 even
+ (byte)0x01, // 00000001 odd
+ (byte)0x02, // 00000010 odd
+ (byte)0x03, // 00000011 even
+ (byte)0xfc, // 11111100 even
+ (byte)0xfd, // 11111101 odd
+ (byte)0xfe, // 11111110 odd
+ (byte)0xff, // 11111111 even
+ };
+
+ static byte [] expectedKey = {
+ (byte)0x01, // 00000001 odd
+ (byte)0x01, // 00000001 odd
+ (byte)0x02, // 00000010 odd
+ (byte)0x02, // 00000010 odd
+ (byte)0xfd, // 11111101 odd
+ (byte)0xfd, // 11111101 odd
+ (byte)0xfe, // 11111110 odd
+ (byte)0xfe, // 11111110 odd
+ };
+
+ static private void check(String alg, byte [] key,
+ byte [] expected, KeySpec ks) throws Exception {
+
+ SecretKeyFactory skf = SecretKeyFactory.getInstance(alg, "SunJCE");
+ SecretKey sk = skf.generateSecret(ks);
+
+ if (DESKeySpec.isParityAdjusted(key, 0)) {
+ throw new Exception("Initial Key is somehow parity adjusted!");
+ }
+
+ byte [] encoded = sk.getEncoded();
+ if (!Arrays.equals(expected, encoded)) {
+ throw new Exception("encoded key is not the expected key");
+ }
+
+ if (!DESKeySpec.isParityAdjusted(encoded, 0)) {
+ throw new Exception("Generated Key is not parity adjusted");
+ }
+ }
+
+ static private void checkDESKey() throws Exception {
+ check("DES", testKey, expectedKey, new DESKeySpec(testKey));
+ }
+
+ static private void checkDESedeKey() throws Exception {
+
+ byte [] key3 = new byte [testKey.length * 3];
+ byte [] expectedKey3 = new byte [expectedKey.length * 3];
+
+ for (int i = 0; i < 3; i++) {
+ System.arraycopy(testKey, 0, key3,
+ i * testKey.length, testKey.length);
+ System.arraycopy(expectedKey, 0, expectedKey3,
+ i * testKey.length, testKey.length);
+ }
+
+ check("DESede", key3, expectedKey3, new DESedeKeySpec(key3));
+ }
+
+ public static void main(String[] args) throws Exception {
+ checkDESKey();
+ checkDESedeKey();
+ System.out.println("Test Passed!");
+ }
+}
diff --git a/test/javax/crypto/spec/DESKeySpec/CheckWeakKeys.java b/test/javax/crypto/spec/DESKeySpec/CheckWeakKeys.java
new file mode 100644
index 0000000..61590e7
--- /dev/null
+++ b/test/javax/crypto/spec/DESKeySpec/CheckWeakKeys.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2005-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6340919
+ * @summary Incorrect list of keys reported as weak by DESKeySpec.isWeak()
+ * @author Brad R. Wetmore
+ */
+import javax.crypto.spec.DESKeySpec;
+
+public class CheckWeakKeys {
+
+ /**
+ * Weak/semi-weak keys copied from FIPS 74.
+ *
+ * "...The first 6 keys have duals different than themselves, hence
+ * each is both a key and a dual giving 12 keys with duals. The last
+ * four keys equal their duals, and are called self-dual keys..."
+ *
+ * 1. E001E001F101F101 01E001E001F101F1
+ * 2. FE1FFE1FFEOEFEOE 1FFE1FFEOEFEOEFE
+ * 3. E01FE01FF10EF10E 1FE01FEOOEF10EF1
+ * 4. 01FE01FE01FE01FE FE01FE01FE01FE01
+ * 5. 011F011F010E010E 1F011F010E010E01
+ * 6. E0FEE0FEF1FEF1FE FEE0FEE0FEF1FEF1
+ * 7. 0101010101010101 0101010101010101
+ * 8. FEFEFEFEFEFEFEFE FEFEFEFEFEFEFEFE
+ * 9. E0E0E0E0F1F1F1F1 E0E0E0E0F1F1F1F1
+ * 10. 1F1F1F1F0E0E0E0E 1F1F1F1F0E0E0E0E
+ */
+ static private byte [][] weakKeys = {
+ { (byte)0xE0, (byte)0x01, (byte)0xE0, (byte)0x01,
+ (byte)0xF1, (byte)0x01, (byte)0xF1, (byte)0x01 },
+
+ { (byte)0x01, (byte)0xE0, (byte)0x01, (byte)0xE0,
+ (byte)0x01, (byte)0xF1, (byte)0x01, (byte)0xF1 },
+
+ { (byte)0xFE, (byte)0x1F, (byte)0xFE, (byte)0x1F,
+ (byte)0xFE, (byte)0x0E, (byte)0xFE, (byte)0x0E },
+
+ { (byte)0x1F, (byte)0xFE, (byte)0x1F, (byte)0xFE,
+ (byte)0x0E, (byte)0xFE, (byte)0x0E, (byte)0xFE },
+
+ { (byte)0xE0, (byte)0x1F, (byte)0xE0, (byte)0x1F,
+ (byte)0xF1, (byte)0x0E, (byte)0xF1, (byte)0x0E },
+
+ { (byte)0x1F, (byte)0xE0, (byte)0x1F, (byte)0xE0,
+ (byte)0x0E, (byte)0xF1, (byte)0x0E, (byte)0xF1 },
+
+ { (byte)0x01, (byte)0xFE, (byte)0x01, (byte)0xFE,
+ (byte)0x01, (byte)0xFE, (byte)0x01, (byte)0xFE },
+
+ { (byte)0xFE, (byte)0x01, (byte)0xFE, (byte)0x01,
+ (byte)0xFE, (byte)0x01, (byte)0xFE, (byte)0x01 },
+
+ { (byte)0x01, (byte)0x1F, (byte)0x01, (byte)0x1F,
+ (byte)0x01, (byte)0x0E, (byte)0x01, (byte)0x0E },
+
+ { (byte)0x1F, (byte)0x01, (byte)0x1F, (byte)0x01,
+ (byte)0x0E, (byte)0x01, (byte)0x0E, (byte)0x01 },
+
+ { (byte)0xE0, (byte)0xFE, (byte)0xE0, (byte)0xFE,
+ (byte)0xF1, (byte)0xFE, (byte)0xF1, (byte)0xFE },
+
+ { (byte)0xFE, (byte)0xE0, (byte)0xFE, (byte)0xE0,
+ (byte)0xFE, (byte)0xF1, (byte)0xFE, (byte)0xF1 },
+
+ { (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01,
+ (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01 },
+
+ { (byte)0xFE, (byte)0xFE, (byte)0xFE, (byte)0xFE,
+ (byte)0xFE, (byte)0xFE, (byte)0xFE, (byte)0xFE },
+
+ { (byte)0xE0, (byte)0xE0, (byte)0xE0, (byte)0xE0,
+ (byte)0xF1, (byte)0xF1, (byte)0xF1, (byte)0xF1 },
+
+ { (byte)0x1F, (byte)0x1F, (byte)0x1F, (byte)0x1F,
+ (byte)0x0E, (byte)0x0E, (byte)0x0E, (byte)0x0E }
+ };
+
+ public static void main(String[] args) throws Exception {
+
+ boolean failed = false;
+
+ for (int i = 0; i < weakKeys.length; i++) {
+ DESKeySpec desSpec = new DESKeySpec(weakKeys[i]);
+ if (!DESKeySpec.isWeak(weakKeys[i], 0)) {
+ failed = true;
+ System.out.println("Entry " + i + " should be weak");
+ }
+ }
+
+ if (failed) {
+ throw new Exception("Failed test!!!");
+ }
+
+ System.out.println("Passed test.");
+ }
+}
diff --git a/test/javax/crypto/spec/DESKeySpec/NullKey.java b/test/javax/crypto/spec/DESKeySpec/NullKey.java
new file mode 100644
index 0000000..bf5d19b
--- /dev/null
+++ b/test/javax/crypto/spec/DESKeySpec/NullKey.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2004-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4959570
+ * @summary DESKeySpec constructors and static methods should throw exception
+ * if the key parameter is null.
+ * @author Sean Mullan
+ */
+import java.security.InvalidKeyException;
+import javax.crypto.spec.DESKeySpec;
+
+public class NullKey {
+
+ public static void main(String[] args) throws Exception {
+
+ try {
+ DESKeySpec desSpec = new DESKeySpec(null);
+ throw new Exception("expected NullPointerException");
+ } catch (NullPointerException npe) {}
+
+ try {
+ DESKeySpec desSpec = new DESKeySpec(null, 0);
+ throw new Exception("expected NullPointerException");
+ } catch (NullPointerException npe) {}
+
+ try {
+ boolean parityAdjusted = DESKeySpec.isParityAdjusted(null, 0);
+ throw new Exception("expected InvalidKeyException");
+ } catch (InvalidKeyException ike) {}
+
+ try {
+ boolean weak = DESKeySpec.isWeak(null, 0);
+ throw new Exception("expected InvalidKeyException");
+ } catch (InvalidKeyException ike) {}
+
+ }
+}
diff --git a/test/javax/crypto/spec/IvParameterSpec/InvalidArgs.java b/test/javax/crypto/spec/IvParameterSpec/InvalidArgs.java
new file mode 100644
index 0000000..e5a923c
--- /dev/null
+++ b/test/javax/crypto/spec/IvParameterSpec/InvalidArgs.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2004-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 5006291
+ * @summary Ensure IvParameterSpec constructor throw the stated
+ * exception for negative 'offset' and 'len' arguments.
+ * @author Valerie Peng
+ */
+import javax.crypto.spec.IvParameterSpec;
+
+public class InvalidArgs {
+
+ public static void main(String[] args) throws Exception {
+ byte[] in = new byte[8];
+ try {
+ IvParameterSpec iv = new IvParameterSpec(in, 0, -2);
+ throw new Exception("expected ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException aiobe) {}
+ try {
+ IvParameterSpec iv = new IvParameterSpec(in, -2, in.length);
+ throw new Exception("expected ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException aiobe) {}
+ }
+}
diff --git a/test/javax/crypto/spec/IvParameterSpec/NullIV.java b/test/javax/crypto/spec/IvParameterSpec/NullIV.java
new file mode 100644
index 0000000..13ac47e
--- /dev/null
+++ b/test/javax/crypto/spec/IvParameterSpec/NullIV.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2004-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 4960776
+ * @summary IvParameterSpec constructors should throw exception
+ * if the iv parameter is null.
+ * @author Sean Mullan
+ */
+import javax.crypto.spec.IvParameterSpec;
+
+public class NullIV {
+
+ public static void main(String[] args) throws Exception {
+
+ try {
+ IvParameterSpec ivParams = new IvParameterSpec(null);
+ throw new Exception("expected NullPointerException");
+ } catch (NullPointerException npe) {}
+
+ try {
+ IvParameterSpec ivParams = new IvParameterSpec(null, 0, 0);
+ throw new Exception("expected IllegalArgumentException");
+ } catch (IllegalArgumentException iae) {}
+
+ }
+}
diff --git a/test/javax/crypto/spec/RC2ParameterSpec/RC2AlgorithmParameters.java b/test/javax/crypto/spec/RC2ParameterSpec/RC2AlgorithmParameters.java
new file mode 100644
index 0000000..3a0c6f9
--- /dev/null
+++ b/test/javax/crypto/spec/RC2ParameterSpec/RC2AlgorithmParameters.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright 2003-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4894159
+ * @summary unit test to test basic functionality of RC2 AlgorithmParameters
+ * implementation
+ * @author Sean Mullan
+ */
+import java.io.ByteArrayOutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.StringReader;
+import java.security.AlgorithmParameters;
+import java.util.Arrays;
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.RC2ParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+public class RC2AlgorithmParameters {
+
+// much of code copied from test/cipher/rc2arcfour/CipherKAT.java
+
+ private final static char[] hexDigits = "0123456789abcdef".toCharArray();
+
+ public static void main(String[] args) throws Exception {
+
+ byte[] iv_1 = {
+ (byte)0x11,(byte)0x11,(byte)0x11,(byte)0x11,
+ (byte)0x11,(byte)0x11,(byte)0x11,(byte)0x11,
+ (byte)0x33,(byte)0x33
+ };
+
+ // check that RC2 is supported by our provider
+ AlgorithmParameters rc2Params =
+ AlgorithmParameters.getInstance("RC2", "SunJCE");
+
+ // check that getAlgorithm returns "RC2"
+ if (!rc2Params.getAlgorithm().equals("RC2")) {
+ throw new Exception("getAlgorithm() returned "
+ + rc2Params.getAlgorithm() + " instead of RC2");
+ }
+
+ // test parameters with effective key size and iv
+ byte[] encoded = testParams(rc2Params, new RC2ParameterSpec(2, iv_1));
+
+ // test parameters with just iv
+ encoded = testParams(AlgorithmParameters.getInstance("RC2"),
+ new RC2ParameterSpec(0, iv_1));
+
+ // test vectors in RFC 2268
+ runTests(tests);
+ }
+
+ static void runTests(CipherTest[] tests) throws Exception {
+ for (int i = 0; i < tests.length; i++) {
+ CipherTest test = tests[i];
+ test.run();
+ }
+ System.out.println("All tests passed");
+ }
+
+ private static byte[] testParams(AlgorithmParameters rc2Params,
+ RC2ParameterSpec rc2Spec) throws Exception {
+
+ // test getParameterSpec returns object equal to input
+ rc2Params.init(rc2Spec);
+ RC2ParameterSpec rc2OtherSpec = (RC2ParameterSpec)
+ rc2Params.getParameterSpec(RC2ParameterSpec.class);
+ if (!rc2Spec.equals(rc2OtherSpec)) {
+ throw new Exception("AlgorithmParameterSpecs should be equal");
+ }
+
+ // test RC2ParameterSpec with RC2 Cipher
+ Cipher rc2Cipher = Cipher.getInstance("RC2/CBC/PKCS5PADDING", "SunJCE");
+ rc2Cipher.init(Cipher.ENCRYPT_MODE,
+ new SecretKeySpec("secret".getBytes("ASCII"), "RC2"), rc2Spec);
+
+ // get IV
+ byte[] iv = rc2Cipher.getIV();
+ if (!Arrays.equals(iv, rc2Spec.getIV())) {
+ throw new Exception("ivs should be equal");
+ }
+
+ // test encoding and decoding
+ byte[] encoded = rc2Params.getEncoded();
+ AlgorithmParameters params = AlgorithmParameters.getInstance("RC2");
+ params.init(encoded);
+
+ // test RC2 AlgorithmParameters with RC2 Cipher
+ rc2Cipher.init(Cipher.ENCRYPT_MODE,
+ new SecretKeySpec("secret".getBytes("ASCII"), "RC2"), params);
+
+ // get IV
+ iv = rc2Cipher.getIV();
+ if (!Arrays.equals(iv, rc2Spec.getIV())) {
+ throw new Exception("ivs should be equal");
+ }
+ return encoded;
+ }
+
+ private static void dumpBytes(byte[] encoded, String file)
+ throws Exception {
+
+ FileOutputStream fos = new FileOutputStream(file);
+ fos.write(encoded);
+ fos.close();
+ }
+
+ public static String toString(byte[] b) {
+ if (b == null) {
+ return "(null)";
+ }
+ StringBuffer sb = new StringBuffer(b.length * 3);
+ for (int i = 0; i < b.length; i++) {
+ int k = b[i] & 0xff;
+ if (i != 0) {
+ sb.append(':');
+ }
+ sb.append(hexDigits[k >>> 4]);
+ sb.append(hexDigits[k & 0xf]);
+ }
+ return sb.toString();
+ }
+
+ public static byte[] parse(String s) {
+ try {
+ int n = s.length();
+ ByteArrayOutputStream out = new ByteArrayOutputStream(n / 3);
+ StringReader r = new StringReader(s);
+ while (true) {
+ int b1 = nextNibble(r);
+ if (b1 < 0) {
+ break;
+ }
+ int b2 = nextNibble(r);
+ if (b2 < 0) {
+ throw new RuntimeException("Invalid string " + s);
+ }
+ int b = (b1 << 4) | b2;
+ out.write(b);
+ }
+ return out.toByteArray();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static byte[] b(String s) {
+ return parse(s);
+ }
+
+ private static int nextNibble(StringReader r) throws IOException {
+ while (true) {
+ int ch = r.read();
+ if (ch == -1) {
+ return -1;
+ } else if ((ch >= '0') && (ch <= '9')) {
+ return ch - '0';
+ } else if ((ch >= 'a') && (ch <= 'f')) {
+ return ch - 'a' + 10;
+ } else if ((ch >= 'A') && (ch <= 'F')) {
+ return ch - 'A' + 10;
+ }
+ }
+ }
+
+ static class CipherTest {
+ private final byte[] plaintext;
+ private final byte[] ciphertext;
+ private final byte[] key;
+ private final int effectiveKeySize;
+ CipherTest(String plaintext, String ciphertext,
+ String key, int effectiveKeySize) {
+ this.plaintext = b(plaintext);
+ this.ciphertext = b(ciphertext);
+ this.key = b(key);
+ this.effectiveKeySize = effectiveKeySize;
+ }
+ void run() throws Exception {
+ Cipher cipher = Cipher.getInstance("RC2/ECB/NOPADDING", "SunJCE");
+ SecretKey keySpec = new SecretKeySpec(key, "RC2");
+ RC2ParameterSpec rc2Spec = new RC2ParameterSpec(effectiveKeySize);
+ cipher.init(Cipher.ENCRYPT_MODE, keySpec, rc2Spec);
+ byte[] enc = cipher.doFinal(plaintext);
+ if (Arrays.equals(ciphertext, enc) == false) {
+ System.out.println("RC2AlgorithmParameters Cipher test " +
+ "encryption failed:");
+ System.out.println("plaintext: "
+ + RC2AlgorithmParameters.toString(plaintext));
+ System.out.println("ciphertext: "
+ + RC2AlgorithmParameters.toString(ciphertext));
+ System.out.println("encrypted: "
+ + RC2AlgorithmParameters.toString(enc));
+ System.out.println("key: "
+ + RC2AlgorithmParameters.toString(key));
+ System.out.println("effective key length: "
+ + effectiveKeySize);
+ throw new Exception("RC2AlgorithmParameters Cipher test "
+ + "encryption failed");
+ }
+ enc = cipher.doFinal(plaintext);
+ if (Arrays.equals(ciphertext, enc) == false) {
+ throw new Exception("Re-encryption test failed");
+ }
+ cipher.init(Cipher.DECRYPT_MODE, keySpec, rc2Spec);
+ byte[] dec = cipher.doFinal(ciphertext);
+ if (Arrays.equals(plaintext, dec) == false) {
+ System.out.println("RC2AlgorithmParameters Cipher test "
+ + "decryption failed:");
+ System.out.println("plaintext: "
+ + RC2AlgorithmParameters.toString(plaintext));
+ System.out.println("ciphertext: "
+ + RC2AlgorithmParameters.toString(ciphertext));
+ System.out.println("decrypted: "
+ + RC2AlgorithmParameters.toString(dec));
+ System.out.println("key: "
+ + RC2AlgorithmParameters.toString(key));
+ System.out.println("effective key length: "
+ + effectiveKeySize);
+ throw new Exception("RC2AlgorithmParameters Cipher test "
+ + "decryption failed");
+ }
+ System.out.println("passed");
+ }
+ }
+
+
+ // test vectors listed in RFC 2268
+ private final static CipherTest[] tests = {
+ new CipherTest("00:00:00:00:00:00:00:00", "EB:B7:73:F9:93:27:8E:FF",
+ "00:00:00:00:00:00:00:00", 63),
+ new CipherTest("FF:FF:FF:FF:FF:FF:FF:FF", "27:8B:27:E4:2E:2F:0D:49",
+ "FF:FF:FF:FF:FF:FF:FF:FF", 64),
+ new CipherTest("10:00:00:00:00:00:00:01", "30:64:9E:DF:9B:E7:D2:C2",
+ "30:00:00:00:00:00:00:00", 64),
+// This vector is not tested because it will throw an exception because the
+// key size is too small (less than 40 bits)
+// new CipherTest("00:00:00:00:00:00:00:00", "61:A8:A2:44:AD:AC:CC:F0",
+// "88", 64),
+ new CipherTest("00:00:00:00:00:00:00:00", "6C:CF:43:08:97:4C:26:7F",
+ "88:BC:A9:0E:90:87:5A", 64),
+ new CipherTest("00:00:00:00:00:00:00:00", "1A:80:7D:27:2B:BE:5D:B1",
+ "88:BC:A9:0E:90:87:5A:7F:0F:79:C3:84:62:7B:AF:B2", 64),
+ new CipherTest("00:00:00:00:00:00:00:00", "22:69:55:2A:B0:F8:5C:A6",
+ "88:BC:A9:0E:90:87:5A:7F:0F:79:C3:84:62:7B:AF:B2", 128),
+ };
+}
diff --git a/test/javax/crypto/spec/RC2ParameterSpec/RC2ParameterSpecEquals.java b/test/javax/crypto/spec/RC2ParameterSpec/RC2ParameterSpecEquals.java
new file mode 100644
index 0000000..a160028
--- /dev/null
+++ b/test/javax/crypto/spec/RC2ParameterSpec/RC2ParameterSpecEquals.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 1999-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 0000000
+ * @summary RC2ParameterSpecEquals
+ * @author Jan Luehe
+ */
+import javax.crypto.spec.*;
+
+public class RC2ParameterSpecEquals {
+
+ public static void main(String[] args) throws Exception {
+
+ byte[] iv_1 = {
+ (byte)0x11,(byte)0x11,(byte)0x11,(byte)0x11,
+ (byte)0x11,(byte)0x11,(byte)0x11,(byte)0x11,
+ (byte)0x33,(byte)0x33
+ };
+ byte[] iv_2 = {
+ (byte)0x22,(byte)0x22,(byte)0x22,(byte)0x22,
+ (byte)0x22,(byte)0x22,(byte)0x22,(byte)0x22,
+ };
+
+ RC2ParameterSpec rc_1 = new RC2ParameterSpec(2);
+ RC2ParameterSpec rc_2 = new RC2ParameterSpec(2);
+ if (!(rc_1.equals(rc_2)))
+ throw new Exception("Should be equal");
+
+ RC2ParameterSpec rc_3 = new RC2ParameterSpec(2, iv_1);
+ RC2ParameterSpec rc_4 = new RC2ParameterSpec(2, iv_1);
+ if (!(rc_3.equals(rc_4)))
+ throw new Exception("Should be equal");
+
+ RC2ParameterSpec rc_5 = new RC2ParameterSpec(2, iv_2);
+ if (rc_3.equals(rc_5))
+ throw new Exception("Should be different");
+
+ RC2ParameterSpec rc_6 = new RC2ParameterSpec(2, iv_1, 2);
+ if (rc_3.equals(rc_6))
+ throw new Exception("Should be different");
+ }
+}
diff --git a/test/javax/crypto/spec/RC5ParameterSpec/InvalidIV.java b/test/javax/crypto/spec/RC5ParameterSpec/InvalidIV.java
new file mode 100644
index 0000000..50c20da
--- /dev/null
+++ b/test/javax/crypto/spec/RC5ParameterSpec/InvalidIV.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2004-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 4960803
+ * @summary RC5ParameterSpec constructors should throw IllegalArgumentException
+ * if the size of the iv parameter is invalid.
+ * @author Sean Mullan
+ */
+import javax.crypto.spec.RC5ParameterSpec;
+
+public class InvalidIV {
+
+ public static void main(String[] args) throws Exception {
+
+ byte[] iv_1 = {
+ (byte)0x11
+ };
+ byte[] iv_2 = {
+ (byte)0x22,(byte)0x22,(byte)0x22,(byte)0x22
+ };
+
+ try {
+ RC5ParameterSpec rc5Params = new RC5ParameterSpec(1, 2, 8, iv_1);
+ throw new Exception("expected IllegalArgumentException");
+ } catch (IllegalArgumentException iae) {}
+
+ try {
+ RC5ParameterSpec rc5Params = new RC5ParameterSpec(1, 2, 8, iv_2, 3);
+ throw new Exception("expected IllegalArgumentException");
+ } catch (IllegalArgumentException iae) {}
+
+ }
+}
diff --git a/test/javax/crypto/spec/RC5ParameterSpec/RC5ParameterSpecEquals.java b/test/javax/crypto/spec/RC5ParameterSpec/RC5ParameterSpecEquals.java
new file mode 100644
index 0000000..2638b88
--- /dev/null
+++ b/test/javax/crypto/spec/RC5ParameterSpec/RC5ParameterSpecEquals.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 1999-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 0000000
+ * @summary RC5ParameterSpecEquals
+ * @author Jan Luehe
+ */
+import javax.crypto.spec.*;
+
+public class RC5ParameterSpecEquals {
+
+ public static void main(String[] args) throws Exception {
+
+ byte[] iv_1 = {
+ (byte)0x11,(byte)0x11,(byte)0x11,(byte)0x11,
+ (byte)0x11,(byte)0x11,(byte)0x11,(byte)0x11
+ };
+ byte[] iv_2 = {
+ (byte)0x22,(byte)0x22,(byte)0x22,(byte)0x22,
+ (byte)0x22,(byte)0x22,(byte)0x22,(byte)0x22
+ };
+
+ RC5ParameterSpec rc_1 = new RC5ParameterSpec(1, 2, 3);
+ RC5ParameterSpec rc_2 = new RC5ParameterSpec(1, 2, 3);
+ if (!(rc_1.equals(rc_2)))
+ throw new Exception("Should be equal");
+
+ rc_1 = new RC5ParameterSpec(1, 2, 3, iv_1);
+ rc_2 = new RC5ParameterSpec(1, 2, 3, iv_1);
+ if (!(rc_1.equals(rc_2)))
+ throw new Exception("Should be equal");
+
+ rc_1 = new RC5ParameterSpec(1, 2, 32, iv_1);
+ rc_2 = new RC5ParameterSpec(1, 2, 32, iv_2);
+ if (rc_1.equals(rc_2))
+ throw new Exception("Should be different");
+ }
+}
diff --git a/test/javax/imageio/EmptyFileTest.java b/test/javax/imageio/EmptyFileTest.java
new file mode 100644
index 0000000..158624c
--- /dev/null
+++ b/test/javax/imageio/EmptyFileTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6438508
+ * @summary Test verifies that ImageIO.write() does not create new
+ * empty file if requested image format is not supported.
+ *
+ * @run main EmptyFileTest
+ */
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import javax.imageio.ImageIO;
+
+public class EmptyFileTest {
+ public static void main(String[] args) throws IOException {
+ String format = "MY_IMG";
+
+ File out = new File("output.myimg");
+
+ System.out.printf("File %s: %s\n", out.getAbsolutePath(),
+ out.exists() ? "EXISTS" : "NEW");
+
+ BufferedImage img = createTestImage();
+
+ boolean status = false;
+ try {
+ status = ImageIO.write(img, format, out);
+ } catch (IOException e) {
+ throw new RuntimeException("Test FAILED: unexpected exception", e);
+ }
+ if (status) {
+ throw new RuntimeException("Test FAILED: Format " +
+ format + " is supported.");
+ }
+
+ if (out.exists()) {
+ throw new RuntimeException("Test FAILED.");
+ }
+ System.out.println("Test PASSED.");
+ }
+
+ private static BufferedImage createTestImage() {
+ return new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
+ }
+}
diff --git a/test/javax/imageio/metadata/DOML3Node.java b/test/javax/imageio/metadata/DOML3Node.java
new file mode 100644
index 0000000..b9c0b40
--- /dev/null
+++ b/test/javax/imageio/metadata/DOML3Node.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6559064
+ *
+ * @summary Verify DOM L3 Node APIs behave as per Image I/O spec.
+ *
+ * @run main DOML3Node
+ */
+
+import javax.imageio.metadata.IIOMetadataNode;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.UserDataHandler;
+
+
+public class DOML3Node {
+
+ public static void main(String args[]) {
+ IIOMetadataNode node = new IIOMetadataNode("node");
+
+ try {
+ node.setIdAttribute("name", true);
+ throw new RuntimeException("No expected DOM exception");
+ } catch (DOMException e) {
+ }
+
+ try {
+ node.setIdAttributeNS("namespaceURI", "localName", true);
+ throw new RuntimeException("No expected DOM exception");
+ } catch (DOMException e) {
+ }
+
+ try {
+ node.setIdAttributeNode((Attr)null, true);
+ throw new RuntimeException("No expected DOM exception");
+ } catch (DOMException e) {
+ }
+
+ try {
+ node.getSchemaTypeInfo();
+ throw new RuntimeException("No expected DOM exception");
+ } catch (DOMException e) {
+ }
+
+ try {
+ node.setUserData("key", null, (UserDataHandler)null);
+ throw new RuntimeException("No expected DOM exception");
+ } catch (DOMException e) {
+ }
+
+ try {
+ node.setUserData("key");
+ throw new RuntimeException("No expected DOM exception");
+ } catch (DOMException e) {
+ }
+
+ try {
+ node.getFeature("feature", "version");
+ throw new RuntimeException("No expected DOM exception");
+ } catch (DOMException e) {
+ }
+
+ try {
+ node.isSameNode((Node)null);
+ throw new RuntimeException("No expected DOM exception");
+ } catch (DOMException e) {
+ }
+
+ try {
+ node.isEqualNode((Node)null);
+ throw new RuntimeException("No expected DOM exception");
+ } catch (DOMException e) {
+ }
+
+ try {
+ node.lookupNamespaceURI("prefix");
+ throw new RuntimeException("No expected DOM exception");
+ } catch (DOMException e) {
+ }
+
+ try {
+ node.isDefaultNamespace("namespaceURI");
+ throw new RuntimeException("No expected DOM exception");
+ } catch (DOMException e) {
+ }
+
+ try {
+ node.lookupPrefix("namespaceURI");
+ throw new RuntimeException("No expected DOM exception");
+ } catch (DOMException e) {
+ }
+
+ try {
+ node.lookupPrefix("namespaceURI");
+ throw new RuntimeException("No expected DOM exception");
+ } catch (DOMException e) {
+ }
+
+ try {
+ node.getTextContent();
+ throw new RuntimeException("No expected DOM exception");
+ } catch (DOMException e) {
+ }
+
+ try {
+ node.setTextContent("textContent");
+ throw new RuntimeException("No expected DOM exception");
+ } catch (DOMException e) {
+ }
+
+ try {
+ node.compareDocumentPosition((Node)null);
+ throw new RuntimeException("No expected DOM exception");
+ } catch (DOMException e) {
+ }
+
+ try {
+ node.getBaseURI();
+ throw new RuntimeException("No expected DOM exception");
+ } catch (DOMException e) {
+ }
+ }
+}
diff --git a/test/javax/imageio/plugins/bmp/BMPSubsamplingTest.java b/test/javax/imageio/plugins/bmp/BMPSubsamplingTest.java
new file mode 100644
index 0000000..a2bfafe
--- /dev/null
+++ b/test/javax/imageio/plugins/bmp/BMPSubsamplingTest.java
@@ -0,0 +1,366 @@
+/*
+ * Copyright 2006-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6299168 6399660 6519600
+ * @summary Test verifies that the subsampling usage does not causes color
+ * changes.
+ * @run main BMPSubsamplingTest
+ * @author andrew.brygin
+ */
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.ComponentColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.DirectColorModel;
+import java.awt.image.IndexColorModel;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+import java.io.File;
+import java.io.IOException;
+import javax.imageio.IIOImage;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageTypeSpecifier;
+import javax.imageio.ImageWriteParam;
+import javax.imageio.ImageWriter;
+import javax.imageio.stream.ImageOutputStream;
+
+
+public class BMPSubsamplingTest {
+ private static final int TYPE_INT_GRB = 0x100;
+ private static final int TYPE_INT_GBR = 0x101;
+ private static final int TYPE_INT_RBG = 0x102;
+ private static final int TYPE_INT_BRG = 0x103;
+ private static final int TYPE_3BYTE_RGB = 0x104;
+ private static final int TYPE_3BYTE_GRB = 0x105;
+ private static final int TYPE_USHORT_555_GRB = 0x106;
+ private static final int TYPE_USHORT_555_BGR = 0x107;
+ private static final int TYPE_USHORT_565_BGR = 0x108;
+ private static final int TYPE_4BPP_INDEXED = 0x109;
+
+ private String format = "BMP";
+
+ private int[] img_types = new int[] {
+ BufferedImage.TYPE_INT_RGB,
+ BufferedImage.TYPE_INT_BGR,
+ TYPE_INT_GRB,
+ TYPE_INT_GBR,
+ TYPE_INT_RBG,
+ TYPE_INT_BRG,
+ BufferedImage.TYPE_USHORT_555_RGB,
+ BufferedImage.TYPE_USHORT_565_RGB,
+ TYPE_USHORT_555_GRB,
+ TYPE_USHORT_555_BGR,
+ TYPE_USHORT_565_BGR,
+ BufferedImage.TYPE_3BYTE_BGR,
+ TYPE_3BYTE_RGB,
+ TYPE_3BYTE_GRB,
+ BufferedImage.TYPE_BYTE_INDEXED,
+ TYPE_4BPP_INDEXED
+ };
+ Color[] colors = new Color[] { Color.red, Color.green, Color.blue };
+
+ private final int srcXSubsampling = 3;
+ private final int srcYSubsampling = 3;
+
+ int dx = 300;
+ int h = 300;
+ int w = dx * colors.length + srcXSubsampling;
+
+
+
+ public BMPSubsamplingTest() throws IOException {
+ ImageWriter writer =
+ ImageIO.getImageWritersByFormatName(format).next();
+
+ ImageWriteParam wparam = writer.getDefaultWriteParam();
+ wparam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
+ String[] types = wparam.getCompressionTypes();
+ for (int t = 0; t < img_types.length; t++) {
+ int img_type = img_types[t];
+ System.out.println("Test for " + getImageTypeName(img_type));
+ BufferedImage image = getTestImage(img_type);
+
+ ImageTypeSpecifier specifier = new ImageTypeSpecifier(image);
+
+ if (!writer.getOriginatingProvider().canEncodeImage(specifier)) {
+ System.out.println("Writer does not support encoding this buffered image type.");
+ continue;
+ }
+
+ for(int i=0; i<types.length; i++) {
+ if ("BI_JPEG".equals(types[i])) {
+ // exclude BI_JPEG from automatic test
+ // due to color diffusion effect on the borders.
+ continue;
+ }
+
+ if (canEncodeImage(types[i], specifier, img_type)) {
+ System.out.println("compression type: " + types[i] +
+ " Supported for " + getImageTypeName(img_type));
+ } else {
+ System.out.println("compression type: " + types[i] +
+ " NOT Supported for " + getImageTypeName(img_type));
+ continue;
+ }
+ ImageWriteParam imageWriteParam = getImageWriteParam(writer, types[i]);
+
+ imageWriteParam.setSourceSubsampling(srcXSubsampling,
+ srcYSubsampling,
+ 0, 0);
+ File outputFile = new File("subsampling_test_" +
+ getImageTypeName(img_type) + "__" +
+ types[i] + ".bmp");
+ ImageOutputStream ios =
+ ImageIO.createImageOutputStream(outputFile);
+ writer.setOutput(ios);
+
+ IIOImage iioImg = new IIOImage(image, null, null);
+
+ writer.write(null, iioImg, imageWriteParam);
+
+ ios.flush();
+ ios.close();
+
+ BufferedImage outputImage = ImageIO.read(outputFile);
+ checkTestImage(outputImage);
+ }
+ }
+ }
+
+ private ImageWriteParam getImageWriteParam(ImageWriter writer, String value) {
+ ImageWriteParam imageWriteParam = writer.getDefaultWriteParam();
+ imageWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
+ imageWriteParam.setCompressionType(value);
+ return imageWriteParam;
+ }
+
+
+ private boolean canEncodeImage(String compression,
+ ImageTypeSpecifier imgType, int rawType)
+ {
+ int biType = imgType.getBufferedImageType();
+ if ((!compression.equals("BI_BITFIELDS")) &&
+ ((rawType == BufferedImage.TYPE_USHORT_565_RGB) ||
+ (rawType == TYPE_USHORT_565_BGR)))
+ {
+ return false;
+ }
+
+ int bpp = imgType.getColorModel().getPixelSize();
+ if (compression.equals("BI_RLE4") && bpp != 4) {
+ // only 4bpp images can be encoded as BI_RLE4
+ return false;
+ }
+ if (compression.equals("BI_RLE8") && bpp != 8) {
+ // only 8bpp images can be encoded as BI_RLE8
+ return false;
+ }
+
+ if (compression.equals("BI_PNG") &&
+ ((rawType == TYPE_USHORT_555_GRB) ||
+ (rawType == TYPE_USHORT_555_BGR)))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ private String getImageTypeName(int t) {
+ switch(t) {
+ case BufferedImage.TYPE_INT_RGB:
+ return "TYPE_INT_RGB";
+ case BufferedImage.TYPE_INT_BGR:
+ return "TYPE_INT_BGR";
+ case TYPE_INT_GRB:
+ return "TYPE_INT_GRB";
+ case TYPE_INT_GBR:
+ return "TYPE_INT_GBR";
+ case TYPE_INT_RBG:
+ return "TYPE_INT_RBG";
+ case TYPE_INT_BRG:
+ return "TYPE_INT_BRG";
+ case BufferedImage.TYPE_USHORT_555_RGB:
+ return "TYPE_USHORT_555_RGB";
+ case BufferedImage.TYPE_USHORT_565_RGB:
+ return "TYPE_USHORT_565_RGB";
+ case TYPE_USHORT_555_GRB:
+ return "TYPE_USHORT_555_GRB";
+ case TYPE_USHORT_555_BGR:
+ return "TYPE_USHORT_555_BGR";
+ case TYPE_USHORT_565_BGR:
+ return "TYPE_USHORT_565_BGR";
+ case BufferedImage.TYPE_3BYTE_BGR:
+ return "TYPE_3BYTE_BGR";
+ case TYPE_3BYTE_RGB:
+ return "TYPE_3BYTE_RGB";
+ case TYPE_3BYTE_GRB:
+ return "TYPE_3BYTE_GRB";
+ case BufferedImage.TYPE_BYTE_INDEXED:
+ return "TYPE_BYTE_INDEXED";
+ case TYPE_4BPP_INDEXED:
+ return "TYPE_BYTE_INDEXED (4bpp)";
+ default:
+ throw new IllegalArgumentException("Unknown image type: " + t);
+ }
+ }
+
+ private BufferedImage getTestImage(int type) {
+ BufferedImage dst = null;
+ ColorModel colorModel = null;
+ WritableRaster raster = null;
+ switch(type) {
+ case TYPE_INT_GRB:
+ colorModel = new DirectColorModel(24,
+ 0x0000ff00,
+ 0x00ff0000,
+ 0x000000ff);
+ break;
+ case TYPE_INT_GBR:
+ colorModel = new DirectColorModel(24,
+ 0x000000ff,
+ 0x00ff0000,
+ 0x0000ff00);
+ break;
+ case TYPE_INT_RBG:
+ colorModel = new DirectColorModel(24,
+ 0x00ff0000,
+ 0x000000ff,
+ 0x0000ff00);
+ break;
+ case TYPE_INT_BRG:
+ colorModel = new DirectColorModel(24,
+ 0x0000ff00,
+ 0x000000ff,
+ 0x00ff0000);
+ break;
+ case TYPE_3BYTE_RGB:
+ dst = create3ByteImage(new int[] {8, 8, 8},
+ new int[] {0, 1, 2});
+ break;
+ case TYPE_3BYTE_GRB:
+ dst = create3ByteImage(new int[] {8, 8, 8},
+ new int[] {1, 0, 2});
+ break;
+ case TYPE_USHORT_555_GRB:
+ colorModel = new DirectColorModel(16,
+ 0x03E0,
+ 0x7C00,
+ 0x001F);
+ break;
+ case TYPE_USHORT_555_BGR:
+ colorModel = new DirectColorModel(16,
+ 0x001F,
+ 0x03E0,
+ 0x7C00);
+ break;
+ case TYPE_USHORT_565_BGR:
+ colorModel = new DirectColorModel(16,
+ 0x001F,
+ 0x07E0,
+ 0xf800);
+ break;
+ case TYPE_4BPP_INDEXED:
+ dst = createIndexImage(4);
+ break;
+ default:
+ dst = new BufferedImage(w, h, type);
+ }
+ if (dst == null) {
+ raster = colorModel.createCompatibleWritableRaster(w, h);
+ dst = new BufferedImage(colorModel, raster, false, null);
+ }
+ Graphics2D g = dst.createGraphics();
+ for (int i = 0; i < colors.length; i++) {
+ g.setColor(colors[i]);
+ g.fillRect(i * dx, 0, dx, h);
+ }
+ g.dispose();
+ return dst;
+ }
+
+ private BufferedImage createIndexImage(int bpp) {
+ // calculate palette size
+ int psize = (1 << bpp);
+
+ // prepare palette;
+ byte[] r = new byte[psize];
+ byte[] g = new byte[psize];
+ byte[] b = new byte[psize];
+
+ for (int i = 0; i < colors.length; i++) {
+ r[i] = (byte)(0xff & colors[i].getRed());
+ g[i] = (byte)(0xff & colors[i].getGreen());
+ b[i] = (byte)(0xff & colors[i].getBlue());
+ }
+
+ // now prepare appropriate index clor model
+ IndexColorModel icm = new IndexColorModel(bpp, psize, r, g, b);
+
+ return new BufferedImage(w, h, BufferedImage.TYPE_BYTE_INDEXED, icm);
+ }
+
+ private BufferedImage create3ByteImage(int[] nBits, int[] bOffs) {
+ ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
+ ColorModel colorModel =
+ new ComponentColorModel(cs, nBits,
+ false, false,
+ Transparency.OPAQUE,
+ DataBuffer.TYPE_BYTE);
+ WritableRaster raster =
+ Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
+ w, h,
+ w*3, 3,
+ bOffs, null);
+ return new BufferedImage(colorModel, raster, false, null);
+ }
+
+ private void checkTestImage(BufferedImage dst) {
+ // NB: do not forget about subsampling factor.
+ int x = dx / (2 * srcXSubsampling);
+ int y = h / (2 * srcYSubsampling);
+ System.out.println("Check result: width=" + dst.getWidth() +
+ ", height=" + dst.getHeight());
+ for (int i = 0; i < colors.length; i++) {
+ System.out.println("\tcheck at: " + x + ", " + y);
+ int srcRgb = colors[i].getRGB();
+ int dstRgb = dst.getRGB(x, y);
+ if (srcRgb != dstRgb) {
+ throw new RuntimeException("Test failed due to wrong dst color " +
+ Integer.toHexString(dstRgb) + " at " + x + "," + y +
+ "instead of " + Integer.toHexString(srcRgb));
+ }
+ x += dx / srcXSubsampling;
+ }
+ }
+
+ public static void main(String args[]) throws IOException {
+ BMPSubsamplingTest test = new BMPSubsamplingTest();
+ }
+}
diff --git a/test/javax/imageio/plugins/gif/GifTransparencyTest.java b/test/javax/imageio/plugins/gif/GifTransparencyTest.java
new file mode 100644
index 0000000..4d51ef2
--- /dev/null
+++ b/test/javax/imageio/plugins/gif/GifTransparencyTest.java
@@ -0,0 +1,186 @@
+/*
+ * @test
+ * @bug 6276653 6287936
+ *
+ * @summary Test verifes that Image I/O gif writer correctly handles
+ * image what supports tranclucent transparency type but contains
+ * picture with opaque or bitmask transparecy (i.e. each image pixel
+ * is ether opaque or fully transparent).
+ *
+ * @run main GifTransparencyTest
+ */
+
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.geom.Area;
+import java.awt.geom.RoundRectangle2D;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageWriter;
+import javax.imageio.spi.ImageWriterSpi;
+import javax.swing.JComponent;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+
+
+public class GifTransparencyTest {
+
+ BufferedImage src;
+ BufferedImage dst;
+
+ public GifTransparencyTest() {
+ src = createTestImage();
+ }
+
+ public void doTest() {
+ File pwd = new File(".");
+ try {
+ File f = File.createTempFile("transparency_test_", ".gif", pwd);
+ System.out.println("file: " + f.getCanonicalPath());
+
+ ImageWriter w = ImageIO.getImageWritersByFormatName("GIF").next();
+
+ ImageWriterSpi spi = w.getOriginatingProvider();
+
+ boolean succeed_write = ImageIO.write(src, "gif", f);
+
+ if (!succeed_write) {
+ throw new RuntimeException("Test failed: failed to write src.");
+ }
+
+ dst = ImageIO.read(f);
+
+ checkResult(src, dst);
+
+ } catch (IOException e) {
+ throw new RuntimeException("Test failed.", e);
+ }
+ }
+
+ /*
+ * Failure criteria:
+ * - src and dst have different dimension
+ * - any transparent pixel was lost
+ */
+ protected void checkResult(BufferedImage src, BufferedImage dst) {
+ int w = src.getWidth();
+ int h = src.getHeight();
+
+
+ if (dst.getWidth() != w || dst.getHeight() != h) {
+ throw new RuntimeException("Test failed: wrong result dimension");
+ }
+
+ BufferedImage bg = new BufferedImage(2 * w, h, BufferedImage.TYPE_INT_RGB);
+ Graphics g = bg.createGraphics();
+ g.setColor(Color.white);
+ g.fillRect(0, 0, 2 * w, h);
+
+ g.drawImage(src, 0, 0, null);
+ g.drawImage(dst, w, 0, null);
+
+ g.dispose();
+
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++) {
+ int src_rgb = bg.getRGB(x, y);
+ int dst_rgb = bg.getRGB(x + w, y);
+
+ if (dst_rgb != src_rgb) {
+ throw new RuntimeException("Test failed: wrong color " +
+ Integer.toHexString(dst_rgb) + " at " + x + ", " +
+ y + " (instead of " + Integer.toHexString(src_rgb) +
+ ")");
+ }
+ }
+ }
+ System.out.println("Test passed.");
+ }
+
+ public void show() {
+ JPanel p = new JPanel(new BorderLayout()) {
+ public void paintComponent(Graphics g) {
+ g.setColor(Color.blue);
+ g.fillRect(0, 0, getWidth(), getHeight());
+ }
+ };
+ p.add(new ImageComponent(src), BorderLayout.WEST);
+ if (dst != null) {
+ p.add(new ImageComponent(dst), BorderLayout.EAST);
+ }
+
+ JFrame f = new JFrame("Transparency");
+ f.add(p);
+
+ f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ f.pack();
+ f.setVisible(true);
+ }
+
+ public static class ImageComponent extends JComponent {
+ BufferedImage img;
+
+ public ImageComponent(BufferedImage img) {
+ this.img = img;
+ }
+
+ public Dimension getPreferredSize() {
+ return new Dimension(img.getWidth() + 2, img.getHeight() + 2);
+ }
+
+ public void paintComponent(Graphics g) {
+ g.drawImage(img, 1, 1, this);
+ }
+ }
+
+ protected BufferedImage createTestImage() {
+ BufferedImage img = new BufferedImage(200, 200,
+ BufferedImage.TYPE_INT_ARGB);
+ Graphics g = img.createGraphics();
+
+ g.setColor(Color.red);
+ g.fillRect(50, 50, 100, 100);
+ g.dispose();
+
+ return img;
+ }
+
+ public static class Empty extends GifTransparencyTest {
+ protected BufferedImage createTestImage() {
+ return new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
+ }
+ }
+
+ public static class Opaque extends GifTransparencyTest {
+ protected BufferedImage createTestImage() {
+ BufferedImage img = new BufferedImage(200, 200,
+ BufferedImage.TYPE_INT_ARGB);
+ Graphics g = img.createGraphics();
+ g.setColor(Color.cyan);
+ g.fillRect(0, 0, 200, 200);
+
+ g.setColor(Color.red);
+ g.fillRect(50, 50, 100, 100);
+ g.dispose();
+
+ return img;
+ }
+ }
+
+ public static void main(String[] args) {
+ System.out.println("Test bitmask...");
+ new GifTransparencyTest().doTest();
+
+ System.out.println("Test opaque...");
+ new GifTransparencyTest.Opaque().doTest();
+
+ System.out.println("Test empty...");
+ new GifTransparencyTest.Empty().doTest();
+ }
+}
diff --git a/test/javax/imageio/plugins/jpeg/ConcurrentReadingTest.java b/test/javax/imageio/plugins/jpeg/ConcurrentReadingTest.java
new file mode 100644
index 0000000..b38b6a4
--- /dev/null
+++ b/test/javax/imageio/plugins/jpeg/ConcurrentReadingTest.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6547241
+ * @summary Test verifies that concurrent usage of jpeg reader instance
+ * by number of threads does not cause crash in jpeg library.
+ * @run main ConcurrentReadingTest
+ */
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.RadialGradientPaint;
+import java.awt.geom.Point2D;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.ImageReadParam;
+import javax.imageio.stream.ImageInputStream;
+
+public class ConcurrentReadingTest extends Thread {
+
+ static ImageReader r = null;
+ static File file = new File("IMGP1001.JPG");
+
+ private static final int MAX_THREADS = 50;
+
+ static int completeCount = 0;;
+ static Object lock = new Object();
+
+ public static void main(String[] args) throws Exception {
+ createTestFile();
+
+ ImageInputStream iis = ImageIO.createImageInputStream(file);
+ r = ImageIO.getImageReaders(iis).next();
+ iis.close();
+
+ for (int i = 0; i < MAX_THREADS; i++) {
+ (new ConcurrentReadingTest()).start();
+ }
+
+ // wait for started threads
+ boolean needWait = true;
+ while (needWait) {
+ Thread.sleep(100);
+ synchronized(lock) {
+ needWait = completeCount < MAX_THREADS;
+ }
+ }
+ System.out.println("Test PASSED.");
+ }
+
+ public void run() {
+ try {
+ ImageInputStream iis = ImageIO.createImageInputStream(file);
+ r.setInput(iis);
+ ImageReadParam p = r.getDefaultReadParam();
+ Thread.sleep(70);
+ BufferedImage res = r.read(0, p);
+ Thread.sleep(70);
+ r.reset();
+ } catch (IllegalStateException e) {
+ System.out.println(e);
+ } catch (IOException e) {
+ System.out.println(e);
+ } catch (Throwable e) {
+ // Unexpected exception. Test failed.
+ throw new RuntimeException("Test failed.", e);
+ } finally {
+ synchronized(lock) {
+ completeCount ++;
+ }
+ }
+ }
+
+ private static void createTestFile() {
+ int w = 1280;
+ int h = 1024;
+
+ BufferedImage img = new
+ BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
+ Graphics2D g = img.createGraphics();
+ Color[] colors = { Color.red, Color.green, Color.blue };
+ float[] dist = {0.0f, 0.5f, 1.0f };
+ Point2D center = new Point2D.Float(0.5f * w, 0.5f * h);
+
+ RadialGradientPaint p =
+ new RadialGradientPaint(center, 0.5f * w, dist, colors);
+ g.setPaint(p);
+ g.fillRect(0, 0, w, h);
+ g.dispose();
+
+ try {
+ System.out.println("Create test image " + file.getAbsolutePath());
+ boolean b = ImageIO.write(img, "JPEG", file);
+ if (!b) {
+ throw new RuntimeException("Failed to create test image.");
+ }
+ } catch (IOException e) {
+ throw new RuntimeException("Test failed", e);
+ }
+ }
+}
diff --git a/test/javax/imageio/plugins/jpeg/ConcurrentWritingTest.java b/test/javax/imageio/plugins/jpeg/ConcurrentWritingTest.java
new file mode 100644
index 0000000..62cf0ce
--- /dev/null
+++ b/test/javax/imageio/plugins/jpeg/ConcurrentWritingTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6547241
+ * @summary Test verifies that concurrent usage of jpeg writer instance
+ * by number of threads does not cause crash in jpeg library.
+ * @run main ConcurrentWritingTest
+ */
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.RadialGradientPaint;
+import java.awt.geom.Point2D;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageWriter;
+import javax.imageio.stream.ImageOutputStream;
+
+public class ConcurrentWritingTest extends Thread {
+
+ static ImageWriter w = null;
+ static File pwd = new File(".");
+ static BufferedImage img;
+
+ private static int MAX_THREADS = 50;
+ private static int completeCount = 0;
+ private static Object lock = new Object();
+
+ public static void main(String[] args) throws Exception {
+ img = createTestImage();
+
+ w = ImageIO.getImageWritersByFormatName("JPEG").next();
+
+ for (int i = 0; i < MAX_THREADS; i++) {
+ (new ConcurrentWritingTest()).start();
+ }
+
+ // wait for threads
+ boolean needWait = true;
+ while(needWait) {
+ synchronized(lock) {
+ needWait = completeCount < MAX_THREADS;
+ }
+ }
+ System.out.println("Test PASSED");
+ }
+
+ public void run() {
+ try {
+ File f = File.createTempFile("writer_", ".jpg", pwd);
+ ImageOutputStream ios = ImageIO.createImageOutputStream(f);
+ w.setOutput(ios);
+ Thread.sleep(70);
+ w.write(img);
+ Thread.sleep(70);
+ w.reset();
+ } catch (IllegalStateException e) {
+ System.out.println(e);
+ } catch (IOException e) {
+ System.out.println(e);
+ } catch (Throwable e) {
+ // Unexpected exception. Test failed.
+ throw new RuntimeException("Test failed.", e);
+ } finally {
+ synchronized(lock) {
+ completeCount ++;
+ }
+ }
+ }
+
+ private static BufferedImage createTestImage() {
+ int w = 1024;
+ int h = 768;
+
+ BufferedImage img = new
+ BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
+ Graphics2D g = img.createGraphics();
+ Color[] colors = { Color.red, Color.green, Color.blue };
+ float[] dist = {0.0f, 0.5f, 1.0f };
+ Point2D center = new Point2D.Float(0.5f * w, 0.5f * h);
+
+ RadialGradientPaint p =
+ new RadialGradientPaint(center, 0.5f * w, dist, colors);
+ g.setPaint(p);
+ g.fillRect(0, 0, w, h);
+ g.dispose();
+
+ return img;
+ }
+}
diff --git a/test/javax/imageio/plugins/jpeg/ReadingInterruptionTest.java b/test/javax/imageio/plugins/jpeg/ReadingInterruptionTest.java
new file mode 100644
index 0000000..414dc61
--- /dev/null
+++ b/test/javax/imageio/plugins/jpeg/ReadingInterruptionTest.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6557086 6547241
+ * @summary Test verifies that invocation of reset/abort/dispose methods from
+ * another thread does not cause crash in jpeg library.
+ * @run main ReadingInterruptionTest
+ */
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.RadialGradientPaint;
+import java.awt.geom.Point2D;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.ImageReadParam;
+import javax.imageio.event.IIOReadProgressListener;
+import javax.imageio.stream.ImageInputStream;
+
+
+public class ReadingInterruptionTest implements IIOReadProgressListener {
+
+ public static void main(String[] args) {
+ createTestFile();
+
+ System.out.println("Test abort()....");
+ ReadingInterruptionTest t = new ReadingInterruptionTest(new AbortAction());
+ t.doTest();
+
+ System.out.println("Test reset()....");
+ t = new ReadingInterruptionTest(new ResetAction());
+ t.doTest();
+
+ System.out.println("Test dispose()....");
+ t = new ReadingInterruptionTest(new DisposeAction());
+ t.doTest();
+ }
+
+ protected abstract static class Action implements Runnable {
+ protected ImageReader target;
+
+ public void setTarget(ImageReader target) {
+ this.target = target;
+ }
+
+ public abstract void run();
+ }
+
+ protected static class DisposeAction extends Action {
+ public void run() {
+ try {
+ target.dispose();
+ } catch (IllegalStateException e) {
+ System.out.println("Test PASSED: IllegalStateException was thrown.");
+ } catch (Throwable e) {
+ throw new RuntimeException("Test FAILED.", e);
+ }
+ }
+ }
+
+ protected static class AbortAction extends Action {
+ public void run() {
+ try {
+ target.abort();
+ } catch (IllegalStateException e) {
+ System.out.println("Test PASSED: IllegalStateException was thrown.");
+ } catch (Throwable e) {
+ throw new RuntimeException("Test FAILED.", e);
+ }
+ }
+ }
+
+ protected static class ResetAction extends Action {
+ public void run() {
+ try {
+ target.reset();
+ } catch (IllegalStateException e) {
+ System.out.println("Test PASSED: IllegalStateException was thrown.");
+ } catch (Throwable e) {
+ throw new RuntimeException("Test FAILED.", e);
+ }
+ }
+ }
+
+ static File file = new File("IMGP1001.JPG");
+
+ Action action;
+ ImageInputStream iis;
+ ImageReader reader;
+
+ protected ReadingInterruptionTest(Action action) {
+ this.action = action;
+
+ reader = ImageIO.getImageReadersByFormatName("JPEG").next();
+
+ this.action.setTarget(reader);
+ }
+
+ public void doTest() {
+ try {
+ reader.addIIOReadProgressListener(this);
+ iis = ImageIO.createImageInputStream(file);
+ reader.setInput(iis);
+ ImageReadParam p = reader.getDefaultReadParam();
+ Thread.sleep(70);
+ BufferedImage res = reader.read(0, p);
+ Thread.sleep(70);
+ } catch (Exception e) {
+ /*
+ * we do expect that concurrent attempt to dispose this
+ * instance of image reader will be blocked. So, this image
+ * should be read sucessfuly. Otherwise, something went wrong
+ * and we need to report test failure.
+ */
+ throw new RuntimeException("Test FAILED", e);
+ } finally {
+ /*
+ * it would happen that concurrent invocation of dispose() method
+ * will be successful. Due to race condition it seems to be possible
+ * that dispose operation will be performed after than read() operation
+ * leaveled thread lock. In this case all subsequent calls for reader
+ * methods should results in IllegalStateException. So, we treat
+ * IllegalStateException as success. Everything else means test failure.
+ */
+ try {
+ reader.reset();
+ } catch (IllegalStateException e) {
+ System.out.println("Expected exception was caught: " + e);
+ } catch(Exception e) {
+ throw new RuntimeException("Test FAILED.", e);
+ }
+ }
+ System.out.println("Test PASSED.");
+ }
+
+ // listener medthods
+ public void imageStarted(ImageReader source,
+ int imageIndex) {} ;
+
+ public void imageProgress(ImageReader source,
+ float percentageDone)
+ {
+ if (20f < percentageDone && percentageDone < 80f) {
+ Thread t = new Thread(action);
+ t.start();
+ }
+ };
+
+ public void imageComplete(ImageReader source) {};
+
+
+ public void sequenceStarted(ImageReader source,
+ int minIndex) {};
+
+ public void sequenceComplete(ImageReader source) {};
+
+ public void thumbnailStarted(ImageReader source,
+ int imageIndex,
+ int thumbnailIndex) {};
+
+ public void thumbnailProgress(ImageReader source,
+ float percentageDone) {};
+
+ public void thumbnailComplete(ImageReader source) {};
+
+ public void readAborted(ImageReader source) {};
+
+ private static void createTestFile() {
+ int w = 1280;
+ int h = 1024;
+
+ BufferedImage img = new
+ BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
+ Graphics2D g = img.createGraphics();
+ Color[] colors = { Color.red, Color.green, Color.blue };
+ float[] dist = {0.0f, 0.5f, 1.0f };
+ Point2D center = new Point2D.Float(0.5f * w, 0.5f * h);
+
+ RadialGradientPaint p =
+ new RadialGradientPaint(center, 0.5f * w, dist, colors);
+ g.setPaint(p);
+ g.fillRect(0, 0, w, h);
+ g.dispose();
+
+ try {
+ System.out.println("Create test image " + file.getAbsolutePath());
+ boolean b = ImageIO.write(img, "JPEG", file);
+ if (!b) {
+ throw new RuntimeException("Failed to create test image.");
+ }
+ } catch (IOException e) {
+ throw new RuntimeException("Test failed", e);
+ }
+ }
+}
diff --git a/test/javax/imageio/plugins/jpeg/WritingInterruptionTest.java b/test/javax/imageio/plugins/jpeg/WritingInterruptionTest.java
new file mode 100644
index 0000000..927ecb2
--- /dev/null
+++ b/test/javax/imageio/plugins/jpeg/WritingInterruptionTest.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6557086 6547241
+ * @summary Test verifies that invocation of reset/abort/dispose methods from
+ * another thread does not cause crash in jpeg library.
+ * @run main WritingInterruptionTest
+ */
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.RadialGradientPaint;
+import java.awt.geom.Point2D;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageWriter;
+import javax.imageio.ImageWriteParam;
+import javax.imageio.event.IIOWriteProgressListener;
+import javax.imageio.stream.ImageOutputStream;
+
+
+public class WritingInterruptionTest implements IIOWriteProgressListener {
+
+ static File pwd = new File(".");
+ static BufferedImage img;
+
+ public static void main(String[] args) {
+ img = createTestImage();
+
+ System.out.println("Test abort()....");
+ WritingInterruptionTest t = new WritingInterruptionTest(new AbortAction());
+ t.doTest();
+
+ System.out.println("Test reset()....");
+ t = new WritingInterruptionTest(new ResetAction());
+ t.doTest();
+
+ System.out.println("Test dispose()....");
+ t = new WritingInterruptionTest(new DisposeAction());
+ t.doTest();
+ }
+
+ protected abstract static class Action implements Runnable {
+ protected ImageWriter target;
+
+ public void setTarget(ImageWriter target) {
+ this.target = target;
+ }
+
+ public abstract void run();
+ }
+
+ protected static class DisposeAction extends Action {
+ public void run() {
+ try {
+ target.dispose();
+ } catch (IllegalStateException e) {
+ System.out.println("Test PASSED: IllegalStateException was thrown.");
+ } catch (Throwable e) {
+ throw new RuntimeException("Test FAILED.", e);
+ }
+ }
+ }
+
+ protected static class AbortAction extends Action {
+ public void run() {
+ try {
+ target.abort();
+ } catch (IllegalStateException e) {
+ System.out.println("Test PASSED: IllegalStateException was thrown.");
+ } catch (Throwable e) {
+ throw new RuntimeException("Test FAILED.", e);
+ }
+ }
+ }
+
+ protected static class ResetAction extends Action {
+ public void run() {
+ try {
+ target.reset();
+ } catch (IllegalStateException e) {
+ System.out.println("Test PASSED: IllegalStateException was thrown.");
+ } catch (Throwable e) {
+ throw new RuntimeException("Test FAILED.", e);
+ }
+ }
+ }
+
+
+ Action action;
+ ImageOutputStream ios;
+ ImageWriter w;
+
+ protected WritingInterruptionTest(Action action) {
+ this.action = action;
+
+ w = ImageIO.getImageWritersByFormatName("JPEG").next();
+
+ this.action.setTarget(w);
+ }
+
+ public void doTest() {
+ try {
+ w.addIIOWriteProgressListener(this);
+ File f = File.createTempFile("writer_", ".jpg", pwd);
+ ImageOutputStream ios = ImageIO.createImageOutputStream(f);
+ w.setOutput(ios);
+ Thread.sleep(70);
+ w.write(img);
+ Thread.sleep(70);
+ } catch (Exception e) {
+ /*
+ * we do expect that concurrent attempt to dispose this
+ * instance of image writer will be blocked. So, this image
+ * should be writen sucessfuly. Otherwise, something went wrong
+ * and we need to report test failure.
+ */
+ throw new RuntimeException("Test FAILED", e);
+ } finally {
+ /*
+ * it would happen that concurrent invocation of dispose() method
+ * will be successful. Due to race condition it seems to be possible
+ * that dispose operation will be performed after than write() operation
+ * leaveled thread lock. In this case all subsequent calls for writer
+ * methods should results in IllegalStateException. So, we treat
+ * IllegalStateException as success. Everything else means test failure.
+ */
+ try {
+ w.reset();
+ } catch (IllegalStateException e) {
+ System.out.println("Expected exception was caught: " + e);
+ } catch(Exception e) {
+ throw new RuntimeException("Test FAILED.", e);
+ }
+ }
+ System.out.println("Test PASSED.");
+ }
+
+ // listener medthods
+ public void imageStarted(ImageWriter source,
+ int imageIndex) {} ;
+
+ public void imageProgress(ImageWriter source,
+ float percentageDone)
+ {
+ if (20f < percentageDone && percentageDone < 80f ) {
+ Thread t = new Thread(action);
+ t.start();
+ }
+ };
+
+ public void imageComplete(ImageWriter source) {};
+
+ public void thumbnailStarted(ImageWriter source,
+ int imageIndex,
+ int thumbnailIndex) {};
+
+ public void thumbnailProgress(ImageWriter source,
+ float percentageDone) {};
+
+ public void thumbnailComplete(ImageWriter source) {};
+
+ public void writeAborted(ImageWriter source) {};
+
+
+ private static BufferedImage createTestImage() {
+ int w = 1024;
+ int h = 768;
+
+ BufferedImage img = new
+ BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
+ Graphics2D g = img.createGraphics();
+ Color[] colors = { Color.red, Color.green, Color.blue };
+ float[] dist = {0.0f, 0.5f, 1.0f };
+ Point2D center = new Point2D.Float(0.5f * w, 0.5f * h);
+
+ RadialGradientPaint p =
+ new RadialGradientPaint(center, 0.5f * w, dist, colors);
+ g.setPaint(p);
+ g.fillRect(0, 0, w, h);
+ g.dispose();
+
+ return img;
+ }
+}
diff --git a/test/javax/imageio/plugins/png/GrayPngTest.java b/test/javax/imageio/plugins/png/GrayPngTest.java
new file mode 100644
index 0000000..06790eb
--- /dev/null
+++ b/test/javax/imageio/plugins/png/GrayPngTest.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6557713
+ * @summary Test verifies that PNG image writer correctly handles indexed images with
+ * various types of transparency.
+ *
+ * Test for 4bpp OPAQUE image
+ * @run main GrayPngTest 4 1 3
+ *
+ * Test for 4bpp BITMASK image with transparent pixel 3
+ * @run main GrayPngTest 4 2 3
+ *
+ * Test for 4bpp TRANSLUCENT image
+ * @run main GrayPngTest 4 3 3
+ *
+ * Test for 8bpp OPAQUE image
+ * @run main GrayPngTest 8 1 127
+ *
+ * Test for 8bpp BITMASK image with transparent pixel 127
+ * @run main GrayPngTest 8 2 127
+ *
+ * Test for 8bpp TRANSLUCENT image
+ * @run main GrayPngTest 8 3 127
+ *
+ */
+
+import java.awt.Color;
+import java.awt.Transparency;
+import java.awt.image.BufferedImage;
+import java.awt.image.IndexColorModel;
+import java.awt.image.WritableRaster;
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import javax.imageio.ImageIO;
+
+public class GrayPngTest {
+
+ public static void main(String[] args) throws IOException {
+ /*
+ * Expected argiments:
+ * args[0] - bits per pixel. Supported range: [1, 8]
+ * args[1] - transparency type. Should be one form
+ * java.awt.Transparency type constants.
+ * args[2] - transparent pixel for BITMASK transparency type,
+ * otherwise is ignored.
+ */
+ int bpp = 4;
+ int trans_type = Transparency.BITMASK;
+ int trans_pixel = 3;
+ try {
+ bpp = Integer.parseInt(args[0]);
+ trans_type = Integer.parseInt(args[1]);
+ trans_pixel = Integer.parseInt(args[2]);
+ } catch (NumberFormatException e) {
+ System.out.println("Ignore ncorrect bpp value: " + args[0]);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ System.out.println("Default test argumens.");
+ }
+
+ new GrayPngTest(bpp).doTest(trans_type, trans_pixel);
+ }
+
+
+
+ private BufferedImage getTestImage(int trans_type, int trans_pixel) {
+
+ IndexColorModel icm = null;
+ switch(trans_type) {
+ case Transparency.OPAQUE:
+ icm = new IndexColorModel(bpp, numColors, r, g, b);
+ break;
+ case Transparency.BITMASK:
+ icm = new IndexColorModel(bpp, numColors, r, g, b, trans_pixel);
+ break;
+ case Transparency.TRANSLUCENT:
+ a = Arrays.copyOf(r, r.length);
+ icm = new IndexColorModel(bpp, numColors, r, g, b, a);
+ break;
+ default:
+ throw new RuntimeException("Invalid transparency: " + trans_type);
+ }
+
+ int w = 256 * 2;
+ int h = 200;
+
+ dx = w / (numColors);
+
+ WritableRaster wr = icm.createCompatibleWritableRaster(w, h);
+ for (int i = 0; i < numColors; i ++) {
+ int rx = i * dx;
+
+ int[] samples = new int[h * dx];
+ Arrays.fill(samples, i);
+ wr.setPixels(rx, 0, dx, h, samples);
+ }
+
+ // horizontal line with transparent color
+ int[] samples = new int[w * 10];
+ Arrays.fill(samples, trans_pixel);
+ wr.setPixels(0, h / 2 - 5, w, 10, samples);
+
+ // create index color model
+ return new BufferedImage(icm, wr, false, null);
+ }
+
+ static File pwd = new File(".");
+
+ private BufferedImage src;
+ private BufferedImage dst;
+ private int bpp;
+ private int numColors;
+
+ private int dx;
+
+ private byte[] r;
+ private byte[] g;
+ private byte[] b;
+
+ private byte[] a;
+
+ protected GrayPngTest(int bpp) {
+ if (0 > bpp || bpp > 8) {
+ throw new RuntimeException("Invalid bpp: " + bpp);
+ }
+ this.bpp = bpp;
+ numColors = (1 << bpp);
+ System.out.println("Num colors: " + numColors);
+
+ // create palette
+ r = new byte[numColors];
+ g = new byte[numColors];
+ b = new byte[numColors];
+
+ int dc = 0xff / (numColors - 1);
+ System.out.println("dc = " + dc);
+
+ for (int i = 0; i < numColors; i ++) {
+ byte l = (byte)(i * dc);
+ r[i] = l; g[i] = l; b[i] = l;
+ }
+ }
+
+ public void doTest() throws IOException {
+ for (int i = 0; i < numColors; i++) {
+ doTest(Transparency.BITMASK, i);
+ }
+ }
+
+ public void doTest(int trans_type, int trans_index) throws IOException {
+ src = getTestImage(trans_type, trans_index);
+
+ System.out.println("src: " + src);
+
+ File f = File.createTempFile("gray_png_" + bpp + "bpp_" +
+ trans_type + "tt_" +
+ trans_index + "tp_", ".png", pwd);
+ System.out.println("File: " + f.getAbsolutePath());
+ if (!ImageIO.write(src, "png", f)) {
+ throw new RuntimeException("Writing failed!");
+ };
+
+ try {
+ dst = ImageIO.read(f);
+ System.out.println("dst: " + dst);
+ } catch (Exception e) {
+ throw new RuntimeException("Test FAILED.", e);
+ }
+
+ checkImages();
+ }
+
+ private void checkImages() {
+ for (int i = 0; i < numColors; i++) {
+ int src_rgb = src.getRGB(i * dx, 5);
+ int dst_rgb = dst.getRGB(i * dx, 5);
+
+ // here we check transparency only due to possible colors space
+ // differences (sRGB in indexed source and Gray in gray+alpha destination)
+ if ((0xff000000 & src_rgb) != (0xff000000 & dst_rgb)) {
+ throw new RuntimeException("Test FAILED. Color difference detected: " +
+ Integer.toHexString(dst_rgb) + " instead of " +
+ Integer.toHexString(src_rgb) + " for index " + i);
+
+ }
+ }
+ }
+}
diff --git a/test/javax/imageio/plugins/png/PngOutputTypeTest.java b/test/javax/imageio/plugins/png/PngOutputTypeTest.java
new file mode 100644
index 0000000..15a2988
--- /dev/null
+++ b/test/javax/imageio/plugins/png/PngOutputTypeTest.java
@@ -0,0 +1,250 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6549882
+ * @summary Test verifies that PNG image reader creates buffered image
+ * of standart type for 8 bpp images with color type RGB or RGBAlpha
+ *
+ * @run main PngOutputTypeTest
+ */
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.util.Iterator;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReadParam;
+import javax.imageio.ImageReader;
+import javax.imageio.ImageTypeSpecifier;
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.stream.ImageInputStream;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+public class PngOutputTypeTest {
+
+ public static void main(String[] args) throws IOException {
+
+ new PngOutputTypeTest(BufferedImage.TYPE_INT_RGB).doTest();
+
+ new PngOutputTypeTest(BufferedImage.TYPE_INT_ARGB).doTest();
+
+ }
+
+ ImageInputStream iis;
+
+ ImageReader reader;
+
+ public PngOutputTypeTest(int type) throws IOException {
+ this(createTestImage(type));
+ }
+
+ public PngOutputTypeTest(File f) throws IOException {
+ this(ImageIO.createImageInputStream(f));
+ }
+
+ public PngOutputTypeTest(ImageInputStream iis) throws IOException {
+ this.iis = iis;
+ reader = ImageIO.getImageReaders(iis).next();
+ reader.setInput(iis);
+ }
+
+ BufferedImage def;
+ BufferedImage raw;
+
+ ImageTypeSpecifier raw_type;
+
+ public void doTest() throws IOException {
+ /*
+ * This test verifies that png images with color type RGB or RGBA
+ * are decoded as buffered image of some standard type.
+ *
+ * So we need to be sure that image provided by
+ * user has required color type - RGB or RGBA
+ */
+ if (!checkImageType()) {
+ System.out.println("Test IGNORED!");
+ return;
+ }
+
+ def = reader.read(0);
+ System.out.println("Default image type: " + def.getType());
+ if (def == null || def.getType() == BufferedImage.TYPE_CUSTOM) {
+ throw new RuntimeException("Test FAILED!");
+ }
+
+ raw_type = reader.getRawImageType(0);
+ ImageReadParam param = reader.getDefaultReadParam();
+ param.setDestinationType(raw_type);
+
+ System.out.println("Reading with raw image type...");
+ raw = reader.read(0, param);
+ System.out.println("Type of raw image is " + raw.getType());
+
+ compare(def, raw);
+
+ Iterator<ImageTypeSpecifier> types = reader.getImageTypes(0);
+ while (types.hasNext()) {
+ ImageTypeSpecifier t = types.next();
+ System.out.println("Test type: " + t);
+ param.setDestinationType(t);
+
+ BufferedImage img = reader.read(0, param);
+ System.out.println("Result type: " + img.getType());
+
+ compare(def, img);
+ System.out.println("Done.\n");
+ }
+
+ System.out.println("Test PASSED.");
+ }
+
+ private boolean checkImageType() throws IOException {
+ IIOMetadata md = null;
+ try {
+ md = reader.getImageMetadata(0);
+ } catch (IOException e) {
+ return false;
+ }
+
+ String format = md.getNativeMetadataFormatName();
+
+ Node root = md.getAsTree(format);
+
+ Node ihdr = getNode(root, "IHDR");
+ if (ihdr == null) {
+ throw new RuntimeException("No ihdr node: invalid png image!");
+ }
+
+ String colorType = getAttributeValue(ihdr, "colorType");
+ System.out.println("ColorType: " + colorType);
+ if ("RGB".equals(colorType) || "RGBAlpha".equals(colorType)) {
+ // we shuld chek bitDepth
+ System.out.println("Good color type!");
+ String bitDepthStr = getAttributeValue(ihdr, "bitDepth");
+ System.out.println("bitDepth: " + bitDepthStr);
+ int bitDepth = -1;
+ try {
+ bitDepth = Integer.parseInt(bitDepthStr);
+ } catch (NumberFormatException e) {
+ throw new RuntimeException("Invalid bitDepth!");
+ }
+ if (bitDepth == 8) {
+ /*
+ * This image is RGB or RGBA color type and
+ * 8 bit tepth. so it can be used for test
+ */
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private String getAttributeValue(Node n, String attrname) {
+ NamedNodeMap attrs = n.getAttributes();
+ if (attrs == null) {
+ return null;
+ } else {
+ Node a = attrs.getNamedItem(attrname);
+ if (a == null) {
+ return null;
+ } else {
+ return a.getNodeValue();
+ }
+ }
+ }
+
+ private Node getNode(Node root, String name) {
+ Node n = root;
+ return lookupNode(n, name);
+ }
+
+ private Node lookupNode(Node n, String name) {
+ if (n == null) {
+ return null;
+ }
+ if (name.equals(n.getNodeName())) {
+ return n;
+ } else {
+ // may be next on this level?
+ Node res = lookupNode(n.getNextSibling(), name);
+
+ if (res != null) {
+ return res;
+ } else {
+ /// try children then
+ return lookupNode(n.getFirstChild(), name);
+ }
+ }
+ }
+
+ private static void compare(BufferedImage a, BufferedImage b) {
+ int w = a.getWidth();
+ int h = a.getHeight();
+
+ if (w != b.getWidth() || h != b.getHeight()) {
+ throw new RuntimeException("Test FAILED!");
+ }
+
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++) {
+ if (a.getRGB(x, y) != b.getRGB(x, y)) {
+ throw new RuntimeException("Test FAILED!");
+ }
+ }
+ }
+ }
+
+ static Color[] colors = new Color[] { Color.red, Color.green, Color.blue };
+
+ private static ImageInputStream createTestImage(int type) throws IOException {
+ int w = 100;
+ int h = 100;
+
+ BufferedImage img = new BufferedImage(w, h, type);
+
+ int dx = w / colors.length;
+
+ for (int i = 0; i < colors.length; i++) {
+ for (int x = i *dx; (x < (i + 1) * dx) && (x < w) ; x++) {
+ for (int y = 0; y < h; y++) {
+ img.setRGB(x, y, colors[i].getRGB());
+ }
+ }
+ }
+
+ File pwd = new File(".");
+ File out = File.createTempFile("rgba_", ".png", pwd);
+ System.out.println("Create file: " + out.getAbsolutePath());
+ ImageIO.write(img, "PNG", out);
+ return ImageIO.createImageInputStream(out);
+ }
+}
diff --git a/test/javax/imageio/plugins/png/ShortHistogramTest.java b/test/javax/imageio/plugins/png/ShortHistogramTest.java
new file mode 100644
index 0000000..c535287
--- /dev/null
+++ b/test/javax/imageio/plugins/png/ShortHistogramTest.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6198111
+ * @summary Test verifies that PNG image reader correctly handles
+ * hIST chunk if length of image palette in not power of two.
+ *
+ * @run main ShortHistogramTest 15
+ */
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBuffer;
+import java.awt.image.IndexColorModel;
+import java.awt.image.Raster;
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Random;
+import javax.imageio.IIOImage;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageTypeSpecifier;
+import javax.imageio.ImageWriteParam;
+import javax.imageio.ImageWriter;
+import javax.imageio.metadata.IIOInvalidTreeException;
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.metadata.IIOMetadataNode;
+import javax.imageio.stream.ImageOutputStream;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+public class ShortHistogramTest {
+
+ public static void main(String[] args) throws IOException {
+ int numColors = 15;
+ if (args.length > 0) {
+ try {
+ numColors = Integer.parseInt(args[0]);
+ } catch (NumberFormatException e) {
+ System.out.println("Invalid number of colors: " + args[0]);
+ }
+ }
+ System.out.println("Test number of colors: " + numColors);
+
+ ShortHistogramTest t = new ShortHistogramTest(numColors);
+ t.doTest();
+ }
+
+ int numColors;
+
+ public ShortHistogramTest(int numColors) {
+ this.numColors = numColors;
+ }
+
+ public void doTest() throws IOException {
+ BufferedImage bi = createTestImage(numColors);
+
+ File f = writeImageWithHist(bi);
+ System.out.println("Test file is " + f.getCanonicalPath());
+
+ try {
+ ImageIO.read(f);
+ } catch (IOException e) {
+ throw new RuntimeException("Test FAILED!", e);
+ }
+ System.out.println("Test PASSED!");
+ }
+
+ protected File writeImageWithHist(BufferedImage bi) throws IOException {
+ File f = File.createTempFile("hist_", ".png", new File("."));
+
+ ImageWriter writer = ImageIO.getImageWritersByFormatName("PNG").next();
+
+ ImageOutputStream ios = ImageIO.createImageOutputStream(f);
+ writer.setOutput(ios);
+
+ ImageWriteParam param = writer.getDefaultWriteParam();
+ ImageTypeSpecifier type = new ImageTypeSpecifier(bi);
+
+ IIOMetadata imgMetadata = writer.getDefaultImageMetadata(type, param);
+
+ /* add hIST node to image metadata */
+ imgMetadata = upgradeMetadata(imgMetadata, bi);
+
+ IIOImage iio_img = new IIOImage(bi,
+ null, // no thumbnails
+ imgMetadata);
+
+ writer.write(iio_img);
+ ios.flush();
+ ios.close();
+ return f;
+ }
+
+ private IIOMetadata upgradeMetadata(IIOMetadata src, BufferedImage bi) {
+ String format = src.getNativeMetadataFormatName();
+ System.out.println("Native format: " + format);
+ Node root = src.getAsTree(format);
+
+ // add hIST node
+ Node n = lookupChildNode(root, "hIST");
+ if (n == null) {
+ System.out.println("Appending new hIST node...");
+ Node hIST = gethISTNode(bi);
+ root.appendChild(hIST);
+ }
+
+ System.out.println("Upgraded metadata tree:");
+ dump(root, "");
+
+ System.out.println("Merging metadata...");
+ try {
+ src.mergeTree(format, root);
+ } catch (IIOInvalidTreeException e) {
+ throw new RuntimeException("Test FAILED!", e);
+ }
+ return src;
+ }
+
+ private IIOMetadataNode gethISTNode(BufferedImage bi) {
+ IndexColorModel icm = (IndexColorModel)bi.getColorModel();
+ int mapSize = icm.getMapSize();
+
+ int[] hist = new int[mapSize];
+ Arrays.fill(hist, 0);
+
+ Raster r = bi.getData();
+ for (int y = 0; y < bi.getHeight(); y++) {
+ for (int x = 0; x < bi.getWidth(); x++) {
+ int s = r.getSample(x, y, 0);
+ hist[s] ++;
+ }
+ }
+
+ IIOMetadataNode hIST = new IIOMetadataNode("hIST");
+ for (int i = 0; i < hist.length; i++) {
+ IIOMetadataNode n = new IIOMetadataNode("hISTEntry");
+ n.setAttribute("index", "" + i);
+ n.setAttribute("value", "" + hist[i]);
+ hIST.appendChild(n);
+ }
+
+ return hIST;
+ }
+
+ private static Node lookupChildNode(Node root, String name) {
+ Node n = root.getFirstChild();
+ while (n != null && !name.equals(n.getNodeName())) {
+ n = n.getNextSibling();
+ }
+ return n;
+ }
+
+ private static void dump(Node node, String ident) {
+ if (node == null) {
+ return;
+ }
+
+ System.out.printf("%s%s\n", ident, node.getNodeName());
+
+ // dump node attributes...
+ NamedNodeMap attribs = node.getAttributes();
+ if (attribs != null) {
+ for (int i = 0; i < attribs.getLength(); i++) {
+ Node a = attribs.item(i);
+ System.out.printf("%s %s: %s\n", ident,
+ a.getNodeName(), a.getNodeValue());
+ }
+ }
+ // dump node children...
+ dump(node.getFirstChild(), ident + " ");
+
+ dump(node.getNextSibling(), ident);
+ }
+
+ protected BufferedImage createTestImage(int numColors) {
+
+ IndexColorModel icm = createTestICM(numColors);
+ int w = numColors * 10;
+ int h = 20;
+
+ BufferedImage img = new BufferedImage(w, h,
+ BufferedImage.TYPE_BYTE_INDEXED, icm);
+
+ Graphics2D g = img.createGraphics();
+ for (int i = 0; i < numColors; i++) {
+ int rgb = icm.getRGB(i);
+ //System.out.printf("pixel %d, rgb %x\n", i, rgb);
+ g.setColor(new Color(rgb));
+ g.fillRect(i * 10, 0, w - i * 10, h);
+ }
+ g.dispose();
+
+ return img;
+ }
+
+ protected IndexColorModel createTestICM(int numColors) {
+ int[] palette = createTestPalette(numColors);
+
+ int numBits = getNumBits(numColors);
+
+ IndexColorModel icm = new IndexColorModel(numBits, numColors,
+ palette, 0, false, -1,
+ DataBuffer.TYPE_BYTE);
+ return icm;
+ }
+
+ protected static int getNumBits(int numColors) {
+ if (numColors < 0 || 256 < numColors) {
+ throw new RuntimeException("Unsupported number of colors: " +
+ numColors);
+ }
+
+ int numBits = 1;
+ int limit = 1 << numBits;
+ while (numColors > limit) {
+ numBits++;
+ limit = 1 << numBits;
+ }
+ return numBits;
+ }
+
+ private static Random rnd = new Random();
+
+ protected static int[] createTestPalette(int numColors) {
+ int[] palette = new int[numColors];
+ for (int i = 0; i < numColors; i++) {
+ int r = rnd.nextInt(256);
+ int g = rnd.nextInt(256);
+ int b = rnd.nextInt(256);
+
+ palette[i] = 0xff000000 | (r << 16) | (g << 8) | b;
+ }
+ return palette;
+ }
+}
diff --git a/test/javax/imageio/plugins/shared/BitDepth.java b/test/javax/imageio/plugins/shared/BitDepth.java
new file mode 100644
index 0000000..495e5af
--- /dev/null
+++ b/test/javax/imageio/plugins/shared/BitDepth.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 4413109 4418221 6607198
+ * @run main BitDepth
+ * @summary Checks that the PNG and JPEG writers can handle various
+ * BufferedImage types. An optional list of arguments may be used to
+ * test a different format writer or writers.
+ */
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import javax.imageio.ImageIO;
+
+public class BitDepth {
+
+ public static void main(String[] args) throws IOException {
+ new BitDepth(args);
+ }
+
+ // Check that the PNG writer can write an all-white image correctly
+ private static boolean testPNGByteBinary() throws IOException {
+ int width = 10;
+ int height = 10;
+
+ File f = new File("BlackStripe.png");
+ BufferedImage bi = new BufferedImage(width, height,
+ BufferedImage.TYPE_BYTE_BINARY);
+ Graphics2D g = bi.createGraphics();
+ g.setColor(new Color(255, 255, 255));
+ g.fillRect(0, 0, width, height);
+
+ ImageIO.write(bi, "png", f);
+ BufferedImage bi2 = ImageIO.read(f);
+ if (bi2.getWidth() != width || bi2.getHeight() != height) {
+ System.out.println("Dimensions changed!");
+ return false;
+ }
+
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ int rgb = bi2.getRGB(x, y);
+ if (rgb != 0xffffffff) {
+ System.out.println("Found a non-white pixel!");
+ return false;
+ }
+ }
+ }
+
+ f.delete();
+ return true;
+ }
+
+ private static final int[] biRGBTypes = {
+ BufferedImage.TYPE_INT_RGB,
+ BufferedImage.TYPE_INT_BGR,
+ BufferedImage.TYPE_3BYTE_BGR,
+ BufferedImage.TYPE_USHORT_565_RGB,
+ BufferedImage.TYPE_USHORT_555_RGB
+ };
+
+ private static final int[] biRGBATypes = {
+ BufferedImage.TYPE_INT_ARGB,
+ BufferedImage.TYPE_INT_ARGB_PRE,
+ BufferedImage.TYPE_4BYTE_ABGR,
+ BufferedImage.TYPE_4BYTE_ABGR_PRE
+ };
+
+ private static final int[] biGrayTypes = {
+ BufferedImage.TYPE_BYTE_GRAY,
+ BufferedImage.TYPE_USHORT_GRAY,
+ BufferedImage.TYPE_BYTE_BINARY
+ };
+
+ private static final String[] biTypeNames = {
+ "CUSTOM",
+ "INT_RGB",
+ "INT_ARGB",
+ "INT_ARGB_PRE",
+ "INT_BGR",
+ "3BYTE_BGR",
+ "4BYTE_ABGR",
+ "4BYTE_ABGR_PRE",
+ "USHORT_565_RGB",
+ "USHORT_555_RGB",
+ "BYTE_GRAY",
+ "USHORT_GRAY",
+ "BYTE_BINARY",
+ "BYTE_INDEXED"
+ };
+
+ private int width = 80;
+ private int height = 80;
+ private String[] format = { "png", "jpeg" };
+
+ public BitDepth(String[] args) throws IOException {
+ if (args.length > 0) {
+ format = args;
+ }
+
+ for (int i = 0; i < format.length; i++) {
+ testFormat(format[i]);
+ }
+ }
+
+ private void testFormat(String format) throws IOException {
+ boolean allOK = true;
+
+ for (int i = 0; i < biRGBTypes.length; i++) {
+ int type = biRGBTypes[i];
+ System.out.println("Testing " + format +
+ " writer for type " + biTypeNames[type]);
+ File f = testWriteRGB(format, type);
+ boolean ok = testReadRGB(f);
+ if (ok) {
+ f.delete();
+ }
+ allOK = allOK && ok;
+ }
+
+ if (format.equals("png")) {
+ System.out.println("Testing png writer for black stripe");
+ boolean ok = testPNGByteBinary();
+ allOK = allOK && ok;
+ }
+
+ if (!allOK) {
+ throw new RuntimeException("Test failed");
+ }
+ }
+
+ private File testWriteRGB(String format, int type)
+ throws IOException {
+ BufferedImage bi = new BufferedImage(width, height, type);
+ Graphics2D g = bi.createGraphics();
+
+ Color white = new Color(255, 255, 255);
+ Color red = new Color(255, 0, 0);
+ Color green = new Color(0, 255, 0);
+ Color blue = new Color(0, 0, 255);
+
+ g.setColor(white);
+ g.fillRect(0, 0, width, height);
+ g.setColor(red);
+ g.fillRect(10, 10, 20, 20);
+ g.setColor(green);
+ g.fillRect(30, 30, 20, 20);
+ g.setColor(blue);
+ g.fillRect(50, 50, 20, 20);
+
+ File file = new File("BitDepth_" + biTypeNames[type] + "." + format);
+ try {
+ ImageIO.write(bi, format, file);
+ } catch (RuntimeException re) {
+ System.out.println("Can't write a type "
+ + biTypeNames[type] +
+ " BufferedImage!");
+ }
+
+ return file;
+ }
+
+ private int colorDistance(int color, int r, int g, int b) {
+ int r0 = ((color >> 16) & 0xff) - r;
+ int g0 = ((color >> 8) & 0xff) - g;
+ int b0 = (color & 0xff) - b;
+ return r0*r0 + g0*g0 + b0*b0;
+ }
+
+ private boolean testReadRGB(File file) throws IOException {
+ int[] rgb = new int[3];
+
+ BufferedImage bi = ImageIO.read(file);
+ if (bi == null) {
+ System.out.println("Couldn't read image!");
+ return false;
+ }
+ int r = bi.getRGB(15, 15);
+ if (colorDistance(r, 255, 0, 0) > 20) {
+ System.out.println("Red was distorted!");
+ return false;
+ }
+ int g = bi.getRGB(35, 35);
+ if (colorDistance(g, 0, 255, 0) > 20) {
+ System.out.println("Green was distorted!");
+ return false;
+ }
+ int b = bi.getRGB(55, 55);
+ if (colorDistance(b, 0, 0, 255) > 20) {
+ System.out.println("Blue was distorted!");
+ return false;
+ }
+ int w = bi.getRGB(55, 15);
+ if (colorDistance(w, 255, 255, 255) > 20) {
+ System.out.println("White was distorted!");
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/test/javax/management/ImplementationVersion/ImplVersionCommand.java b/test/javax/management/ImplementationVersion/ImplVersionCommand.java
new file mode 100644
index 0000000..36872ea
--- /dev/null
+++ b/test/javax/management/ImplementationVersion/ImplVersionCommand.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2003-2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ */
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectName;
+
+public class ImplVersionCommand {
+
+ public static void main(String[] args) throws Exception {
+ // Instantiate the MBean server
+ //
+ System.out.println("Create the MBean server");
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ // Get the JMX implementation version from the MBeanServerDelegateMBean
+ //
+ System.out.println("Get the JMX implementation version");
+ ObjectName mbsdName =
+ new ObjectName("JMImplementation:type=MBeanServerDelegate");
+ String mbsdAttribute = "ImplementationVersion";
+ String mbsdVersion = (String) mbs.getAttribute(mbsdName, mbsdAttribute);
+
+ // Display JMX implementation version and JVM implementation version
+ //
+ System.out.println("JMX implementation version = " +
+ mbsdVersion);
+ System.out.println("Java Runtime implementation version = " +
+ args[0]);
+
+ // Check JMX implementation version vs. JVM implementation version
+ //
+ if (Boolean.valueOf(args[1]).booleanValue()) {
+ if (!mbsdVersion.equals(args[0]))
+ throw new IllegalArgumentException(
+ "JMX and Java Runtime implementation versions do not match!");
+ // Test OK!
+ //
+ System.out.println("JMX and Java Runtime implementation " +
+ "versions match!");
+ } else {
+ // Test OK!
+ //
+ System.out.println("JMX and Java Runtime implementation " +
+ "versions do not match because the test " +
+ "is using an unbundled version of JMX!");
+ }
+ System.out.println("Bye! Bye!");
+ }
+}
diff --git a/test/javax/management/ImplementationVersion/ImplVersionReader.java b/test/javax/management/ImplementationVersion/ImplVersionReader.java
new file mode 100644
index 0000000..f50ae4c
--- /dev/null
+++ b/test/javax/management/ImplementationVersion/ImplVersionReader.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ */
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+
+public class ImplVersionReader extends Thread {
+
+ private BufferedReader in;
+ private Process proc;
+
+ public ImplVersionReader(Process p, InputStream is) {
+ proc = p;
+ in = new BufferedReader(new InputStreamReader(is));
+ }
+
+ public void run() {
+ boolean terminate = false;
+ while (!terminate) {
+ try {
+ String trace = in.readLine();
+ if (trace != null) {
+ System.out.println("ImplVersionCommand: " + trace);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ try {
+ proc.exitValue();
+ terminate = true;
+ } catch (IllegalThreadStateException e) {
+ terminate = false;
+ }
+ }
+ }
+}
diff --git a/test/javax/management/ImplementationVersion/ImplVersionTest.java b/test/javax/management/ImplementationVersion/ImplVersionTest.java
new file mode 100644
index 0000000..27a482b
--- /dev/null
+++ b/test/javax/management/ImplementationVersion/ImplVersionTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2003-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4842196
+ * @summary Test that there is no difference between the JMX version and the
+ * JDK version when JMX is bundled into the Java platform and the application
+ * is run with a security manager and the test codebase has the java permission
+ * to read the "java.runtime.version" system property.
+ * @author Luis-Miguel Alventosa
+ * @run clean ImplVersionTest ImplVersionCommand
+ * @run build ImplVersionTest ImplVersionCommand ImplVersionReader
+ * @run main ImplVersionTest
+ */
+
+import java.io.File;
+import java.security.CodeSource;
+import javax.management.MBeanServer;
+
+public class ImplVersionTest {
+
+ public static void main(String[] args) {
+ try {
+ // Get OS name
+ //
+ String osName = System.getProperty("os.name");
+ System.out.println("osName = " + osName);
+ if ("Windows 98".equals(osName)) {
+ // Disable this test on Win98 due to parsing
+ // errors (bad handling of white spaces) when
+ // J2SE is installed under "Program Files".
+ //
+ System.out.println("This test is disabled on Windows 98.");
+ System.out.println("Bye! Bye!");
+ return;
+ }
+ // Get Java Home
+ //
+ String javaHome = System.getProperty("java.home");
+ System.out.println("javaHome = " + javaHome);
+ // Get test src
+ //
+ String testSrc = System.getProperty("test.src");
+ System.out.println("testSrc = " + testSrc);
+ // Get test classes
+ //
+ String testClasses = System.getProperty("test.classes");
+ System.out.println("testClasses = " + testClasses);
+ // Get boot class path
+ //
+ boolean checkVersion = true;
+ String bootClassPath = System.getProperty("sun.boot.class.path");
+ if (bootClassPath != null &&
+ bootClassPath.indexOf("jmxri.jar") != -1)
+ checkVersion = false;
+ String command =
+ javaHome + File.separator + "bin" + File.separator + "java " +
+ " -Xbootclasspath/p:" + bootClassPath +
+ " -classpath " + testClasses +
+ " -Djava.security.manager -Djava.security.policy==" + testSrc +
+ File.separator + "policy -Dtest.classes=" + testClasses +
+ " ImplVersionCommand " +
+ System.getProperty("java.runtime.version") + " " + checkVersion;
+ System.out.println("ImplVersionCommand Exec Command = " +command);
+ Process proc = Runtime.getRuntime().exec(command);
+ new ImplVersionReader(proc, proc.getInputStream()).start();
+ new ImplVersionReader(proc, proc.getErrorStream()).start();
+ int exitValue = proc.waitFor();
+ System.out.println("ImplVersionCommand Exit Value = " +
+ exitValue);
+ if (exitValue != 0) {
+ System.out.println("TEST FAILED: Incorrect exit value " +
+ "from ImplVersionCommand");
+ System.exit(exitValue);
+ }
+ // Test OK!
+ //
+ System.out.println("Bye! Bye!");
+ } catch (Exception e) {
+ System.out.println("Unexpected exception caught = " + e);
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+}
diff --git a/test/javax/management/ImplementationVersion/policy b/test/javax/management/ImplementationVersion/policy
new file mode 100644
index 0000000..1d83b1a
--- /dev/null
+++ b/test/javax/management/ImplementationVersion/policy
@@ -0,0 +1,5 @@
+grant codebase "file:${test.classes}" {
+ permission java.util.PropertyPermission "java.runtime.version", "read";
+ permission javax.management.MBeanServerPermission "createMBeanServer";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#ImplementationVersion[JMImplementation:type=MBeanServerDelegate]", "getAttribute";
+};
diff --git a/test/javax/management/Introspector/AnnotationSecurityTest.java b/test/javax/management/Introspector/AnnotationSecurityTest.java
new file mode 100644
index 0000000..f7d1835
--- /dev/null
+++ b/test/javax/management/Introspector/AnnotationSecurityTest.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test AnnotationSecurityTest.java
+ * @bug 6366543 6370080
+ * @summary Test that having a security manager doesn't trigger a
+ * NotCompliantMBeanException
+ * @author Daniel Fuchs, Yves Joan
+ * @run clean AnnotationSecurityTest Described UnDescribed DescribedMBean
+ * UnDescribedMBean SqeDescriptorKey DescribedMX DescribedMXBean
+ * @run build AnnotationSecurityTest Described UnDescribed DescribedMBean
+ * UnDescribedMBean SqeDescriptorKey DescribedMX DescribedMXBean
+ * @run main/othervm AnnotationSecurityTest
+ */
+// -Djava.security.debug=access,domain,policy
+
+import java.io.File;
+import java.io.IOException;
+
+import java.lang.annotation.Annotation;
+import java.lang.management.ManagementFactory;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
+import java.lang.reflect.UndeclaredThrowableException;
+
+import javax.management.JMException;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+/**
+ *
+ * @author Sun Microsystems, 2005 - All rights reserved.
+ */
+
+public class AnnotationSecurityTest {
+
+ /** Creates a new instance of AnnotationSecurityTest */
+ public AnnotationSecurityTest() {
+ }
+
+ public static void main(String[] argv) {
+ AnnotationSecurityTest test = new AnnotationSecurityTest();
+ test.run();
+ }
+
+
+ public void run() {
+ try {
+ final String testSrc = System.getProperty("test.src");
+ final String codeBase = System.getProperty("test.classes");
+ final String policy = testSrc + File.separator +
+ "AnnotationSecurityTest.policy";
+ final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ final File pf = new File(policy);
+ if (!pf.exists())
+ throw new IOException("policy file not found: " + policy);
+ if (!pf.canRead())
+ throw new IOException("policy file not readable: " + policy);
+
+ System.out.println("Policy="+policy);
+ System.setProperty("java.security.policy",policy);
+ System.setSecurityManager(new SecurityManager());
+
+ // We check that 6370080 is fixed.
+ //
+ try {
+ final Method m1 =
+ DescribedMBean.class.getMethod("getStringProp");
+ final Method m2 =
+ DescribedMBean.class.getMethod("setStringProp",
+ String.class);
+ m1.getAnnotations();
+ m2.getAnnotations();
+ } catch (SecurityException x) {
+ System.err.println("ERROR: 6370080 not fixed.");
+ throw new IllegalStateException("ERROR: 6370080 not fixed.",x);
+ }
+
+ // Do the test: we should be able to register these 3 MBeans....
+ // We now test that the behaviour described in 6366543 does no
+ // longer appears now that 6370080 is fixed.
+ //
+
+ final ObjectName name1 =
+ new ObjectName("defaultDomain:class=UnDescribed");
+ UnDescribed unDescribedMBean = new UnDescribed();
+ System.out.println("\nWe register an MBean where DescriptorKey is " +
+ "not used at all");
+ mbs.registerMBean(unDescribedMBean, name1);
+ System.out.println("\n\tOK - The MBean "
+ + name1 + " is registered = " + mbs.isRegistered(name1));
+
+ final ObjectName name2 =
+ new ObjectName("defaultDomain:class=Described");
+ final Described describedMBean = new Described();
+
+ System.out.println("\nWe register an MBean with exactly the " +
+ "same management"
+ + " interface as above and where DescriptorKey is used.");
+ mbs.registerMBean(describedMBean, name2);
+ System.out.println("\n\tOK - The MBean "
+ + name2 + " is registered = " + mbs.isRegistered(name2));
+
+ final ObjectName name3 =
+ new ObjectName("defaultDomain:class=DescribedMX");
+ final DescribedMX describedMXBean = new DescribedMX();
+
+ System.out.println("\nWe register an MXBean with exactly the " +
+ "same management"
+ + " interface as above and where DescriptorKey is used.");
+ mbs.registerMBean(describedMXBean, name3);
+ System.out.println("\n\tOK - The MXBean "
+ + name3 + " is registered = " + mbs.isRegistered(name3));
+
+ System.out.println("\nAll three MBeans correctly registered...");
+
+
+ // We check that we don't have getAttribute() permission - as
+ // it's been voluntarily omitted from our policy file.
+ // If we don't get the Security Exception there is probably
+ // a security configuration pb...
+ //
+ try {
+ // We don't have getAttribute() permission, so this must fail.
+ System.err.println("Trying getStringProp() - should fail");
+ mbs.getAttribute(name1,"StringProp");
+ System.err.println("ERROR: didn't get expected SecurityException"
+ +"\n\t check security configuration & policy file: "+
+ policy);
+ throw new RuntimeException("getStringProp() did not get a " +
+ "SecurityException!");
+ } catch (SecurityException x) {
+ // OK!
+ System.err.println("getStringProp() - failed");
+ }
+
+ } catch (Exception t) {
+ t.printStackTrace();
+ if (t instanceof RuntimeException)
+ throw (RuntimeException)t;
+ else throw new RuntimeException(t);
+ }
+ }
+
+}
diff --git a/test/javax/management/Introspector/AnnotationSecurityTest.policy b/test/javax/management/Introspector/AnnotationSecurityTest.policy
new file mode 100644
index 0000000..25a59fe
--- /dev/null
+++ b/test/javax/management/Introspector/AnnotationSecurityTest.policy
@@ -0,0 +1,15 @@
+grant {
+ // JMX permissions
+ permission javax.management.MBeanServerPermission "*";
+ // Add permission to create and register 1 specific Described MBean
+ permission javax.management.MBeanPermission "Described#-[defaultDomain:class=Described]", "instantiate";
+ permission javax.management.MBeanPermission "Described#-[defaultDomain:class=Described]", "registerMBean";
+ // Add permission to create and register 1 specific Described MXBean
+ permission javax.management.MBeanPermission "DescribedMX#-[defaultDomain:class=DescribedMX]", "instantiate";
+ permission javax.management.MBeanPermission "DescribedMX#-[defaultDomain:class=DescribedMX]", "registerMBean";
+ // Add permission to create and register 1 specific UnDescribed MBean
+ permission javax.management.MBeanPermission "UnDescribed#-[defaultDomain:class=UnDescribed]", "instantiate";
+ permission javax.management.MBeanPermission "UnDescribed#-[defaultDomain:class=UnDescribed]", "registerMBean";
+ //
+ permission javax.management.MBeanTrustPermission "*";
+};
diff --git a/test/javax/management/Introspector/AnnotationTest.java b/test/javax/management/Introspector/AnnotationTest.java
new file mode 100644
index 0000000..e6d3c10
--- /dev/null
+++ b/test/javax/management/Introspector/AnnotationTest.java
@@ -0,0 +1,445 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6221321 6295867
+ * @summary Test that annotations in Standard MBean interfaces
+ * correctly produce Descriptor entries
+ * @author Eamonn McManus
+ * @run clean AnnotationTest
+ * @run build AnnotationTest
+ * @run main AnnotationTest
+ */
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.*;
+import javax.management.*;
+
+/*
+ This test checks that annotations produce Descriptor entries as
+ specified in javax.management.DescriptorKey. It does two things:
+
+ - An annotation consisting of an int and a String, each with an
+ appropriate @DescriptorKey annotation, is placed on every program
+ element where it can map to a Descriptor, namely:
+
+ . on an MBean interface
+ . on a getter for a read-only attribute
+ . on a setter for a write-only attribute
+ . on the getter but not the setter for a read/write attribute
+ . on the setter but not the getter for a read/write attribute
+ . on both the getter and the setter for a read/write attribute
+ . on an operation
+ . on each parameter of an operation
+ . on a public constructor with no parameters
+ . on a public constructor with a parameter
+ . on the parameter of that public constructor
+ . on all of the above for an MXBean instead of an MBean
+
+ The test checks that in each case the corresponding Descriptor
+ appears in the appropriate place inside the MBean's MBeanInfo.
+
+ - An annotation consisting of enough other types to ensure coverage
+ is placed on a getter. The test checks that the generated
+ MBeanAttributeInfo contains the corresponding Descriptor. The tested
+ types are the following:
+
+ . Class
+ . an enumeration type (java.lang.annotation.RetentionPolicy)
+ . boolean
+ . String[]
+ . Class[]
+ . int[]
+ . an array of enumeration type (RetentionPolicy[])
+ . boolean[]
+ */
+public class AnnotationTest {
+ private static String failed = null;
+
+// @Retention(RetentionPolicy.RUNTIME) @Inherited
+// @Target(ElementType.METHOD)
+// public static @interface DescriptorKey {
+// String value();
+// }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ public static @interface Pair {
+ @DescriptorKey("x")
+ int x();
+ @DescriptorKey("y")
+ String y();
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ public static @interface Full {
+ @DescriptorKey("class")
+ Class classValue();
+ @DescriptorKey("enum")
+ RetentionPolicy enumValue();
+ @DescriptorKey("boolean")
+ boolean booleanValue();
+ @DescriptorKey("stringArray")
+ String[] stringArrayValue();
+ @DescriptorKey("classArray")
+ Class[] classArrayValue();
+ @DescriptorKey("intArray")
+ int[] intArrayValue();
+ @DescriptorKey("enumArray")
+ RetentionPolicy[] enumArrayValue();
+ @DescriptorKey("booleanArray")
+ boolean[] booleanArrayValue();
+ }
+
+ /* We use the annotation @Pair(x = 3, y = "foo") everywhere, and this is
+ the Descriptor that it should produce: */
+ private static Descriptor expectedDescriptor =
+ new ImmutableDescriptor(new String[] {"x", "y"},
+ new Object[] {3, "foo"});
+
+ private static Descriptor expectedFullDescriptor =
+ new ImmutableDescriptor(new String[] {
+ "class", "enum", "boolean", "stringArray",
+ "classArray", "intArray", "enumArray",
+ "booleanArray",
+ },
+ new Object[] {
+ Full.class.getName(),
+ RetentionPolicy.RUNTIME.name(),
+ false,
+ new String[] {"foo", "bar"},
+ new String[] {Full.class.getName()},
+ new int[] {1, 2},
+ new String[] {RetentionPolicy.RUNTIME.name()},
+ new boolean[] {false, true},
+ });
+
+ @Pair(x = 3, y = "foo")
+ public static interface ThingMBean {
+ @Pair(x = 3, y = "foo")
+ @Full(classValue=Full.class,
+ enumValue=RetentionPolicy.RUNTIME,
+ booleanValue=false,
+ stringArrayValue={"foo", "bar"},
+ classArrayValue={Full.class},
+ intArrayValue={1, 2},
+ enumArrayValue={RetentionPolicy.RUNTIME},
+ booleanArrayValue={false, true})
+ int getReadOnly();
+
+ @Pair(x = 3, y = "foo")
+ void setWriteOnly(int x);
+
+ @Pair(x = 3, y = "foo")
+ int getReadWrite1();
+ void setReadWrite1(int x);
+
+ @Pair(x = 3, y = "foo")
+ int getReadWrite2();
+ @Pair(x = 3, y = "foo")
+ void setReadWrite2(int x);
+
+ int getReadWrite3();
+ @Pair(x = 3, y = "foo")
+ void setReadWrite3(int x);
+
+ @Pair(x = 3, y = "foo")
+ int operation(@Pair(x = 3, y = "foo") int p1,
+ @Pair(x = 3, y = "foo") int p2);
+ }
+
+ public static class Thing implements ThingMBean {
+ @Pair(x = 3, y = "foo")
+ public Thing() {}
+
+ @Pair(x = 3, y = "foo")
+ public Thing(@Pair(x = 3, y = "foo") int p1) {}
+
+ public int getReadOnly() {return 0;}
+
+ public void setWriteOnly(int x) {}
+
+ public int getReadWrite1() {return 0;}
+ public void setReadWrite1(int x) {}
+
+ public int getReadWrite2() {return 0;}
+ public void setReadWrite2(int x) {}
+
+ public int getReadWrite3() {return 0;}
+ public void setReadWrite3(int x) {}
+
+ public int operation(int p1, int p2) {return 0;}
+ }
+
+ @Pair(x = 3, y = "foo")
+ public static interface ThingMXBean extends ThingMBean {}
+
+ public static class ThingImpl implements ThingMXBean {
+ @Pair(x = 3, y = "foo")
+ public ThingImpl() {}
+
+ @Pair(x = 3, y = "foo")
+ public ThingImpl(@Pair(x = 3, y = "foo") int p1) {}
+
+ public int getReadOnly() {return 0;}
+
+ public void setWriteOnly(int x) {}
+
+ public int getReadWrite1() {return 0;}
+ public void setReadWrite1(int x) {}
+
+ public int getReadWrite2() {return 0;}
+ public void setReadWrite2(int x) {}
+
+ public int getReadWrite3() {return 0;}
+ public void setReadWrite3(int x) {}
+
+ public int operation(int p1, int p2) {return 0;}
+ }
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("Testing that annotations are correctly " +
+ "reflected in Descriptor entries");
+
+ MBeanServer mbs =
+ java.lang.management.ManagementFactory.getPlatformMBeanServer();
+ ObjectName on = new ObjectName("a:b=c");
+ Thing thing = new Thing();
+ mbs.registerMBean(thing, on);
+ check(mbs, on);
+ mbs.unregisterMBean(on);
+ ThingImpl thingImpl = new ThingImpl();
+ mbs.registerMBean(thingImpl, on);
+ check(mbs, on);
+
+ if (failed == null)
+ System.out.println("Test passed");
+ else if (true)
+ throw new Exception("TEST FAILED: " + failed);
+ else
+ System.out.println("Test disabled until 6221321 implemented");
+ }
+
+ private static void check(MBeanServer mbs, ObjectName on) throws Exception {
+ MBeanInfo mbi = mbs.getMBeanInfo(on);
+
+ // check the MBean itself
+ check(mbi);
+
+ // check attributes
+ MBeanAttributeInfo[] attrs = mbi.getAttributes();
+ for (MBeanAttributeInfo attr : attrs) {
+ check(attr);
+ if (attr.getName().equals("ReadOnly"))
+ check("@Full", attr.getDescriptor(), expectedFullDescriptor);
+ }
+
+ // check operations
+ MBeanOperationInfo[] ops = mbi.getOperations();
+ for (MBeanOperationInfo op : ops) {
+ check(op);
+ check(op.getSignature());
+ }
+
+ MBeanConstructorInfo[] constrs = mbi.getConstructors();
+ for (MBeanConstructorInfo constr : constrs) {
+ check(constr);
+ check(constr.getSignature());
+ }
+ }
+
+ private static void check(DescriptorRead x) {
+ check(x, x.getDescriptor(), expectedDescriptor);
+ }
+
+ private static void check(Object x, Descriptor d, Descriptor expect) {
+ String fail = null;
+ try {
+ Descriptor u = ImmutableDescriptor.union(d, expect);
+ if (!u.equals(d))
+ fail = "should contain " + expect + "; is " + d;
+ } catch (IllegalArgumentException e) {
+ fail = e.getMessage();
+ }
+ if (fail == null) {
+ System.out.println("OK: " + x);
+ } else {
+ failed = "NOT OK: Incorrect descriptor for: " + x;
+ System.out.println(failed);
+ System.out.println("..." + fail);
+ }
+ }
+
+ private static void check(DescriptorRead[] xx) {
+ for (DescriptorRead x : xx)
+ check(x);
+ }
+
+ public static class AnnotatedMBean extends StandardMBean {
+ <T> AnnotatedMBean(T resource, Class<T> interfaceClass, boolean mx) {
+ super(resource, interfaceClass, mx);
+ }
+
+ private static final String[] attrPrefixes = {"get", "set", "is"};
+
+ protected void cacheMBeanInfo(MBeanInfo info) {
+ MBeanAttributeInfo[] attrs = info.getAttributes();
+ MBeanOperationInfo[] ops = info.getOperations();
+
+ for (int i = 0; i < attrs.length; i++) {
+ MBeanAttributeInfo attr = attrs[i];
+ String name = attr.getName();
+ Descriptor d = attr.getDescriptor();
+ Method m;
+ if ((m = getMethod("get" + name)) != null)
+ d = ImmutableDescriptor.union(d, descriptorFor(m));
+ if (attr.getType().equals("boolean") &&
+ (m = getMethod("is" + name)) != null)
+ d = ImmutableDescriptor.union(d, descriptorFor(m));
+ if ((m = getMethod("set" + name, attr)) != null)
+ d = ImmutableDescriptor.union(d, descriptorFor(m));
+ if (!d.equals(attr.getDescriptor())) {
+ attrs[i] =
+ new MBeanAttributeInfo(name, attr.getType(),
+ attr.getDescription(), attr.isReadable(),
+ attr.isWritable(), attr.isIs(), d);
+ }
+ }
+
+ for (int i = 0; i < ops.length; i++) {
+ MBeanOperationInfo op = ops[i];
+ String name = op.getName();
+ Descriptor d = op.getDescriptor();
+ MBeanParameterInfo[] params = op.getSignature();
+ Method m = getMethod(name, params);
+ if (m != null) {
+ d = ImmutableDescriptor.union(d, descriptorFor(m));
+ Annotation[][] annots = m.getParameterAnnotations();
+ for (int pi = 0; pi < params.length; pi++) {
+ MBeanParameterInfo param = params[pi];
+ Descriptor pd =
+ ImmutableDescriptor.union(param.getDescriptor(),
+ descriptorFor(annots[pi]));
+ params[pi] = new MBeanParameterInfo(param.getName(),
+ param.getType(), param.getDescription(), pd);
+ }
+ op = new MBeanOperationInfo(op.getName(),
+ op.getDescription(), params, op.getReturnType(),
+ op.getImpact(), d);
+ if (!ops[i].equals(op))
+ ops[i] = op;
+ }
+ }
+
+ Descriptor id = descriptorFor(getMBeanInterface());
+ info = new MBeanInfo(info.getClassName(), info.getDescription(),
+ attrs, info.getConstructors(), ops, info.getNotifications(),
+ ImmutableDescriptor.union(id, info.getDescriptor()));
+ super.cacheMBeanInfo(info);
+ }
+
+ private Descriptor descriptorFor(AnnotatedElement x) {
+ Annotation[] annots = x.getAnnotations();
+ return descriptorFor(annots);
+ }
+
+ private Descriptor descriptorFor(Annotation[] annots) {
+ if (annots.length == 0)
+ return ImmutableDescriptor.EMPTY_DESCRIPTOR;
+ Map<String, Object> descriptorMap = new HashMap<String, Object>();
+ for (Annotation a : annots) {
+ Class<? extends Annotation> c = a.annotationType();
+ Method[] elements = c.getMethods();
+ for (Method element : elements) {
+ DescriptorKey key =
+ element.getAnnotation(DescriptorKey.class);
+ if (key != null) {
+ String name = key.value();
+ Object value;
+ try {
+ value = element.invoke(a);
+ } catch (Exception e) {
+ // we don't expect this
+ throw new RuntimeException(e);
+ }
+ Object oldValue = descriptorMap.put(name, value);
+ if (oldValue != null && !oldValue.equals(value)) {
+ final String msg =
+ "Inconsistent values for descriptor field " +
+ name + " from annotations: " + value + " :: " +
+ oldValue;
+ throw new IllegalArgumentException(msg);
+ }
+ }
+ }
+ }
+ if (descriptorMap.isEmpty())
+ return ImmutableDescriptor.EMPTY_DESCRIPTOR;
+ else
+ return new ImmutableDescriptor(descriptorMap);
+ }
+
+ private Method getMethod(String name, MBeanFeatureInfo... params) {
+ Class<?> intf = getMBeanInterface();
+ ClassLoader loader = intf.getClassLoader();
+ Class[] classes = new Class[params.length];
+ for (int i = 0; i < params.length; i++) {
+ MBeanFeatureInfo param = params[i];
+ Descriptor d = param.getDescriptor();
+ String type = (String) d.getFieldValue("originalType");
+ if (type == null) {
+ if (param instanceof MBeanAttributeInfo)
+ type = ((MBeanAttributeInfo) param).getType();
+ else
+ type = ((MBeanParameterInfo) param).getType();
+ }
+ Class<?> c = primitives.get(type);
+ if (c == null) {
+ try {
+ c = Class.forName(type, false, loader);
+ } catch (ClassNotFoundException e) {
+ return null;
+ }
+ }
+ classes[i] = c;
+ }
+ try {
+ return intf.getMethod(name, classes);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ private static final Map<String, Class<?>> primitives =
+ new HashMap<String, Class<?>>();
+ static {
+ for (Class<?> c :
+ new Class[] {boolean.class, byte.class, short.class,
+ int.class, long.class, float.class,
+ double.class, char.class, void.class}) {
+ primitives.put(c.getName(), c);
+ }
+ }
+ }
+}
diff --git a/test/javax/management/Introspector/ChangingNotifsTest.java b/test/javax/management/Introspector/ChangingNotifsTest.java
new file mode 100644
index 0000000..515d15c
--- /dev/null
+++ b/test/javax/management/Introspector/ChangingNotifsTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6175517
+ * @summary Check that Standard MBeans can change their MBeanNotificationInfo[]
+ * and MXBeans cannot
+ * @author Eamonn McManus
+ * @run clean ChangingNotifsTest
+ * @run build ChangingNotifsTest
+ * @run main ChangingNotifsTest
+ */
+
+import javax.management.*;
+import java.util.Arrays;
+
+public class ChangingNotifsTest {
+ public static interface EmptyMBean {}
+
+ public static interface EmptyMXBean {}
+
+ public static class Base extends NotificationBroadcasterSupport {
+ @Override
+ public MBeanNotificationInfo[] getNotificationInfo() {
+ MBeanNotificationInfo inf =
+ new MBeanNotificationInfo(new String[0],
+ Integer.toString(++called),
+ "description");
+ return new MBeanNotificationInfo[] {inf};
+ }
+
+ private static int called;
+ }
+
+ public static class Empty extends Base implements EmptyMBean {}
+
+ public static class EmptyMX extends Base implements EmptyMXBean {}
+
+ public static void main(String[] args) throws Exception {
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ ObjectName name = new ObjectName("a:b=c");
+ for (boolean mx : new boolean[] {false, true})
+ test(mbs, name, mx);
+ if (failure != null)
+ throw new Exception(failure);
+ System.out.println("TEST PASSED");
+ }
+
+ private static void test(MBeanServer mbs, ObjectName name, boolean mx)
+ throws Exception {
+ Object mbean = mx ? new EmptyMX() : new Empty();
+ String what = mx ? "MXBean" : "Standard MBean";
+ mbs.registerMBean(mbean, name);
+ try {
+ MBeanInfo mbi = mbs.getMBeanInfo(name);
+ Descriptor d = mbi.getDescriptor();
+ String immut = (String) d.getFieldValue("immutableInfo");
+ boolean immutable = (immut != null && immut.equals("true"));
+ if (immutable != mx) {
+ fail(what + " has immutableInfo=" + immut + ", should be " +
+ mx);
+ return;
+ }
+ MBeanNotificationInfo[] n1 = mbi.getNotifications().clone();
+ mbi = mbs.getMBeanInfo(name);
+ boolean unchanged = Arrays.deepEquals(mbi.getNotifications(), n1);
+ if (unchanged != mx) {
+ fail(what + " notif info " +
+ (unchanged ? "did not change" : "changed"));
+ return;
+ }
+ System.out.println("OK: " + what);
+ } finally {
+ mbs.unregisterMBean(name);
+ }
+ }
+
+ private static void fail(String why) {
+ failure = "FAILED: " + why;
+ System.out.println(failure);
+ }
+
+ private static String failure;
+}
diff --git a/test/javax/management/Introspector/ClassLeakTest.java b/test/javax/management/Introspector/ClassLeakTest.java
new file mode 100644
index 0000000..92f75a5
--- /dev/null
+++ b/test/javax/management/Introspector/ClassLeakTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4909536
+ * @summary Ensure that the Introspector does not retain refs to classes
+ * @author Eamonn McManus
+ * @run clean ClassLeakTest
+ * @run build ClassLeakTest
+ * @run main ClassLeakTest
+ */
+
+import java.lang.ref.WeakReference;
+import java.net.*;
+import java.util.*;
+
+import javax.management.*;
+import javax.management.loading.*;
+
+public class ClassLeakTest {
+ public static void main(String[] args) throws Exception {
+ System.out.println("Testing that registering and unregistering a " +
+ "Standard MBean does not retain a reference to " +
+ "the MBean's class");
+
+ ClassLoader myClassLoader = ClassLeakTest.class.getClassLoader();
+ if (!(myClassLoader instanceof URLClassLoader)) {
+ System.out.println("TEST INVALID: test's class loader is not " +
+ "a URLClassLoader");
+ System.exit(1);
+ }
+
+ URLClassLoader myURLClassLoader = (URLClassLoader) myClassLoader;
+ URL[] urls = myURLClassLoader.getURLs();
+ PrivateMLet mlet = new PrivateMLet(urls, null, false);
+ Class shadowClass = mlet.loadClass(TestMBean.class.getName());
+ if (shadowClass == TestMBean.class) {
+ System.out.println("TEST INVALID: MLet got original " +
+ "TestMBean not shadow");
+ System.exit(1);
+ }
+ 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);
+
+ ClassLoader testLoader = mbs.getClassLoaderFor(testName);
+ if (testLoader != mlet) {
+ System.out.println("TEST INVALID: MBean's class loader is not " +
+ "MLet: " + testLoader);
+ System.exit(1);
+ }
+ testLoader = null;
+
+ MBeanInfo info = mbs.getMBeanInfo(testName);
+ MBeanAttributeInfo[] attrs = info.getAttributes();
+ if (attrs.length != 1 || !attrs[0].getName().equals("A")
+ || !attrs[0].isReadable() || !attrs[0].isWritable()
+ || attrs[0].isIs() || !attrs[0].getType().equals("int")) {
+ System.out.println("TEST FAILED: unexpected MBeanInfo attrs");
+ System.exit(1);
+ }
+ MBeanOperationInfo[] ops = info.getOperations();
+ if (ops.length != 1 || !ops[0].getName().equals("bogus")
+ || ops[0].getSignature().length > 0
+ || ops[0].getImpact() != MBeanOperationInfo.UNKNOWN
+ || !ops[0].getReturnType().equals("void")) {
+ System.out.println("TEST FAILED: unexpected MBeanInfo ops");
+ System.exit(1);
+ }
+ if (info.getConstructors().length != 2) {
+ System.out.println("TEST FAILED: wrong number of constructors " +
+ "in introspected bean: " +
+ Arrays.asList(info.getConstructors()));
+ System.exit(1);
+ }
+ if (!info.getClassName().endsWith("Test")) {
+ System.out.println("TEST FAILED: wrong info class name: " +
+ info.getClassName());
+ System.exit(1);
+ }
+
+ mbs.unregisterMBean(testName);
+ mbs.unregisterMBean(mletName);
+
+ WeakReference mletRef = new WeakReference(mlet);
+ mlet = null;
+
+ System.out.println("MBean 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("Test passed: class loader was GC'd");
+ else {
+ System.out.println("TEST FAILED: class loader was not GC'd");
+ System.exit(1);
+ }
+ }
+
+ public static interface TestMBean {
+ public void bogus();
+ public int getA();
+ public void setA(int a);
+ }
+
+ public static class Test implements TestMBean {
+ public Test() {}
+ public Test(int x) {}
+
+ public void bogus() {}
+ public int getA() {return 0;}
+ public void setA(int a) {}
+ }
+}
diff --git a/test/javax/management/Introspector/Described.java b/test/javax/management/Introspector/Described.java
new file mode 100644
index 0000000..963827f
--- /dev/null
+++ b/test/javax/management/Introspector/Described.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ *
+ * Used by AnnotationSecurityTest.java
+ **/
+import java.beans.ConstructorProperties;
+
+/**
+ * An MBean used by AnnotationSecurityTest.java
+ **/
+public class Described implements DescribedMBean {
+ private String name ;
+
+ @SqeDescriptorKey("NO PARAMETER CONSTRUCTOR Described")
+ public Described() {}
+
+ @SqeDescriptorKey("ONE PARAMETER CONSTRUCTOR Described")
+ @ConstructorProperties({"name", "unused"})
+ public Described(@SqeDescriptorKey("CONSTRUCTOR PARAMETER name")String name,
+ @SqeDescriptorKey("CONSTRUCTOR PARAMETER unused")String unused) {
+ this.name = name ;
+ }
+
+ public String getStringProp() {
+ return this.name;
+ }
+
+ public void setStringProp(String name) {
+ this.name = name;
+ }
+
+ public void doNothing() {}
+
+ public void doNothingParam(String param) {}
+}
diff --git a/test/javax/management/Introspector/DescribedMBean.java b/test/javax/management/Introspector/DescribedMBean.java
new file mode 100644
index 0000000..79f038a
--- /dev/null
+++ b/test/javax/management/Introspector/DescribedMBean.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ *
+ * Used by AnnotationSecurityTest.java
+ **/
+@SqeDescriptorKey("INTERFACE DescribedMBean")
+public interface DescribedMBean {
+
+ @SqeDescriptorKey("ATTRIBUTE StringProp")
+ public String getStringProp();
+
+ @SqeDescriptorKey("ATTRIBUTE StringProp")
+ public void setStringProp(String name);
+
+ @SqeDescriptorKey("OPERATION doNothing")
+ public void doNothing();
+
+ @SqeDescriptorKey("OPERATION doNothingParam")
+ public void doNothingParam(@SqeDescriptorKey("OPERATION PARAMETER name")String name);
+}
diff --git a/test/javax/management/Introspector/DescribedMX.java b/test/javax/management/Introspector/DescribedMX.java
new file mode 100644
index 0000000..e3e04b2
--- /dev/null
+++ b/test/javax/management/Introspector/DescribedMX.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ *
+ * Used by AnnotationSecurityTest.java
+ **/
+import java.beans.ConstructorProperties;
+
+/**
+ * An MXBean used by AnnotationSecurityTest.java
+ **/
+public class DescribedMX implements DescribedMXBean {
+ private String name ;
+
+ @SqeDescriptorKey("NO PARAMETER CONSTRUCTOR DescribedMX")
+ public DescribedMX() {}
+
+ @SqeDescriptorKey("ONE PARAMETER CONSTRUCTOR DescribedMX")
+ @ConstructorProperties({"name", "unused"})
+ public DescribedMX(@SqeDescriptorKey("CONSTRUCTOR PARAMETER name")String name,
+ @SqeDescriptorKey("CONSTRUCTOR PARAMETER unused")String unused) {
+ this.name = name ;
+ }
+
+ public String getStringProp() {
+ return this.name;
+ }
+
+ public void setStringProp(String name) {
+ this.name = name;
+ }
+
+ public void doNothing() {}
+
+ public void doNothingParam(String param) {}
+}
diff --git a/test/javax/management/Introspector/DescribedMXBean.java b/test/javax/management/Introspector/DescribedMXBean.java
new file mode 100644
index 0000000..3694e15
--- /dev/null
+++ b/test/javax/management/Introspector/DescribedMXBean.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ *
+ * Used by AnnotationSecurityTest.java
+ **/
+@SqeDescriptorKey("INTERFACE DescribedMXBean")
+public interface DescribedMXBean {
+
+ @SqeDescriptorKey("ATTRIBUTE StringProp")
+ public String getStringProp();
+
+ @SqeDescriptorKey("ATTRIBUTE StringProp")
+ public void setStringProp(String name);
+
+ @SqeDescriptorKey("OPERATION doNothing")
+ public void doNothing();
+
+ @SqeDescriptorKey("OPERATION doNothingParam")
+ public void doNothingParam(@SqeDescriptorKey("OPERATION PARAMETER name")String name);
+}
diff --git a/test/javax/management/Introspector/DuplicateGetterTest.java b/test/javax/management/Introspector/DuplicateGetterTest.java
new file mode 100644
index 0000000..9aa4e0b
--- /dev/null
+++ b/test/javax/management/Introspector/DuplicateGetterTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6518061
+ * @summary Test that an MBean interface can inherit two methods with
+ * the same signature from two unrelated parent interfaces
+ * @author Eamonn McManus
+ */
+
+import java.util.*;
+import java.lang.reflect.*;
+import javax.management.*;
+
+public class DuplicateGetterTest {
+ public static interface FooMBean {
+ public MBeanNotificationInfo[] getNotificationInfo();
+ }
+
+ public static interface BazMBean {
+ public MBeanNotificationInfo[] getNotificationInfo();
+ }
+
+ public static interface BarMBean extends FooMBean, BazMBean {
+ }
+
+ public static class Bar implements BarMBean {
+ public MBeanNotificationInfo[] getNotificationInfo() {
+ return null;
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("Testing that inheriting the same getter from " +
+ "more than one interface does not cause problems");
+ DynamicMBean mbean =
+ new StandardMBean(new Bar(), BarMBean.class);
+ // Before fix, preceding line threw exception
+ MBeanAttributeInfo[] attrs = mbean.getMBeanInfo().getAttributes();
+ System.out.println("Attributes: " + Arrays.toString(attrs));
+ if (attrs.length != 1)
+ throw new Exception("Wrong number of attributes: " + attrs.length);
+ if (!attrs[0].getName().equals("NotificationInfo"))
+ throw new Exception("Wrong attribute name: " + attrs[0].getName());
+ System.out.println("Test passed");
+ }
+}
diff --git a/test/javax/management/Introspector/FeatureOrderTest.java b/test/javax/management/Introspector/FeatureOrderTest.java
new file mode 100644
index 0000000..53a0c02
--- /dev/null
+++ b/test/javax/management/Introspector/FeatureOrderTest.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6486655
+ * @summary Test that attributes and operations appear in the same order
+ * in MBeanInfo as they did in the Standard MBean or MXBean Interface.
+ * @author Eamonn McManus
+ */
+
+/*
+ * For more background on this test, see:
+ * http://weblogs.java.net/blog/emcmanus/archive/2006/11/notes_on_unspec.html
+ */
+
+import java.lang.management.ManagementFactory;
+import java.lang.reflect.Method;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.StandardMBean;
+
+public class FeatureOrderTest {
+ private static boolean failed;
+
+ public static interface OrderMXBean {
+ public int getMercury();
+
+ public String getVenus();
+ public void setVenus(String x);
+
+ public BigInteger getEarth();
+ public void setEarth(BigInteger x);
+
+ public boolean isMars();
+
+ public double getJupiter();
+
+ public byte getSaturn();
+
+ public short getUranus();
+ public void setUranus(short x);
+
+ public long getNeptune();
+
+ // No more Pluto! Yay!
+
+ public void neptune();
+ public void uranus(int x);
+ public int saturn(int x, int y);
+ public short jupiter(int x, long y, double z);
+ public void mars(boolean x);
+ public BigInteger earth();
+ public double earth(double x); // http://www.imdb.com/title/tt0064519/
+ public String venus();
+ public int mercury();
+ }
+
+ public static interface OrderMBean extends OrderMXBean {}
+
+ public static class OrderImpl implements OrderMXBean {
+ public int getMercury() {
+ return 0;
+ }
+
+ public String getVenus() {
+ return null;
+ }
+
+ public void setVenus(String x) {
+ }
+
+ public BigInteger getEarth() {
+ return null;
+ }
+
+ public void setEarth(BigInteger x) {
+ }
+
+ public boolean isMars() {
+ return true;
+ }
+
+ public double getJupiter() {
+ return 0;
+ }
+
+ public byte getSaturn() {
+ return 0;
+ }
+
+ public short getUranus() {
+ return 0;
+ }
+
+ public void setUranus(short x) {
+ }
+
+ public long getNeptune() {
+ return 0;
+ }
+
+ public void neptune() {
+ }
+
+ public void uranus(int x) {
+ }
+
+ public int saturn(int x, int y) {
+ return 0;
+ }
+
+ public short jupiter(int x, long y, double z) {
+ return 0;
+ }
+
+ public void mars(boolean x) {
+ }
+
+ public BigInteger earth() {
+ return null;
+ }
+
+ public double earth(double x) {
+ return 0;
+ }
+
+ public String venus() {
+ return null;
+ }
+
+ public int mercury() {
+ return 0;
+ }
+ }
+
+ public static class Order extends OrderImpl implements OrderMBean {}
+
+ private static final boolean[] booleans = {false, true};
+
+ public static void main(String[] args) throws Exception {
+ // Build the lists of attributes and operations that we would expect
+ // if they are derived by reflection and preserve the reflection order
+ List<String> expectedAttributeNames = new ArrayList<String>();
+ List<String> expectedOperationNames = new ArrayList<String>();
+ for (Method m : OrderMXBean.class.getMethods()) {
+ String name = m.getName();
+ String attrName = null;
+ if (name.startsWith("get") && !name.equals("get") &&
+ m.getParameterTypes().length == 0 &&
+ m.getReturnType() != void.class)
+ attrName = name.substring(3);
+ else if (name.startsWith("is") && !name.equals("is") &&
+ m.getParameterTypes().length == 0 &&
+ m.getReturnType() == boolean.class)
+ attrName = name.substring(2);
+ else if (name.startsWith("set") && !name.equals("set") &&
+ m.getReturnType() == void.class &&
+ m.getParameterTypes().length == 1)
+ attrName = name.substring(3);
+ if (attrName != null) {
+ if (!expectedAttributeNames.contains(attrName))
+ expectedAttributeNames.add(attrName);
+ } else
+ expectedOperationNames.add(name);
+ }
+
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ for (boolean mxbean : booleans) {
+ for (boolean withStandardMBean : booleans) {
+ String testName = "MXBean: " + mxbean + "; " +
+ "using javax.management.StandardMBean: " +
+ withStandardMBean;
+ System.out.println("Test case: " + testName);
+ Object mbean;
+ if (mxbean) {
+ if (withStandardMBean) {
+ mbean = new StandardMBean(
+ new OrderImpl(), OrderMXBean.class, true);
+ } else
+ mbean = new OrderImpl();
+ } else {
+ if (withStandardMBean)
+ mbean = new StandardMBean(new Order(), OrderMBean.class);
+ else
+ mbean = new Order();
+ }
+ ObjectName name = new ObjectName(
+ ":mxbean=" + mxbean + "," + "withStandardMBean=" +
+ withStandardMBean);
+ mbs.registerMBean(mbean, name);
+
+ /* Make sure we are testing what we think. */
+ MBeanInfo mbi = mbs.getMBeanInfo(name);
+ boolean isWithStandardMBean =
+ mbs.isInstanceOf(name, StandardMBean.class.getName());
+ System.out.println("classname " +mbi.getClassName());
+ String mxbeanField =
+ (String) mbi.getDescriptor().getFieldValue("mxbean");
+ boolean isMXBean = "true".equalsIgnoreCase(mxbeanField);
+
+ if (mxbean != isMXBean)
+ throw new Exception("Test error: MXBean mismatch");
+ if (withStandardMBean != isWithStandardMBean)
+ throw new Exception("Test error: StandardMBean mismatch");
+
+ // Check that order of attributes and operations matches
+ MBeanAttributeInfo[] mbais = mbi.getAttributes();
+ checkEqual(expectedAttributeNames.size(), mbais.length,
+ "number of attributes");
+ List<String> attributeNames = new ArrayList<String>();
+ for (MBeanAttributeInfo mbai : mbais)
+ attributeNames.add(mbai.getName());
+ checkEqual(expectedAttributeNames, attributeNames,
+ "order of attributes");
+
+ MBeanOperationInfo[] mbois = mbi.getOperations();
+ checkEqual(expectedOperationNames.size(), mbois.length,
+ "number of operations");
+ List<String> operationNames = new ArrayList<String>();
+ for (MBeanOperationInfo mboi : mbois)
+ operationNames.add(mboi.getName());
+ checkEqual(expectedOperationNames, operationNames,
+ "order of operations");
+ System.out.println();
+ }
+ }
+
+ if (failed)
+ throw new Exception("TEST FAILED");
+ System.out.println("TEST PASSED");
+ }
+
+ private static void checkEqual(Object expected, Object actual, String what) {
+ if (expected.equals(actual))
+ System.out.println("OK: " + what + " matches");
+ else {
+ System.out.println("FAILED: " + what + " differs:");
+ System.out.println(" expected: " + expected);
+ System.out.println(" actual: " + actual);
+ failed = true;
+ }
+ }
+}
diff --git a/test/javax/management/Introspector/GetMBeanInfoExceptionTest.java b/test/javax/management/Introspector/GetMBeanInfoExceptionTest.java
new file mode 100644
index 0000000..715fb9d
--- /dev/null
+++ b/test/javax/management/Introspector/GetMBeanInfoExceptionTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6281446
+ * @summary Test that the exception thrown by DynamicMBean.getMBeanInfo()
+ * keeps the init cause.
+ * @author Luis-Miguel Alventosa
+ * @run clean GetMBeanInfoExceptionTest
+ * @run build GetMBeanInfoExceptionTest
+ * @run main GetMBeanInfoExceptionTest
+ */
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.DynamicMBean;
+import javax.management.InvalidAttributeValueException;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+
+public class GetMBeanInfoExceptionTest {
+
+ public static class TestDynamicMBean implements DynamicMBean {
+
+ public Object getAttribute(String attribute) throws
+ AttributeNotFoundException,
+ MBeanException,
+ ReflectionException {
+ return null;
+ }
+
+ public void setAttribute(Attribute attribute) throws
+ AttributeNotFoundException,
+ InvalidAttributeValueException,
+ MBeanException,
+ ReflectionException {
+ }
+
+ public AttributeList getAttributes(String[] attributes) {
+ return null;
+ }
+
+ public AttributeList setAttributes(AttributeList attributes) {
+ return null;
+ }
+
+ public Object invoke(String op, Object params[], String sign[]) throws
+ MBeanException,
+ ReflectionException {
+ return null;
+ }
+
+ public MBeanInfo getMBeanInfo() {
+ throw new IllegalArgumentException("GetMBeanInfoExceptionTest");
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ int error = 0;
+
+ // Instantiate the MBean server
+ //
+ System.out.println("Create the MBean server");
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ // Register the MBean
+ //
+ System.out.println("Create a TestDynamicMBean");
+ TestDynamicMBean obj = new TestDynamicMBean();
+ ObjectName n = new ObjectName("d:k=v");
+ try {
+ mbs.registerMBean(obj, n);
+ System.out.println("Didn't get expected NotCompliantMBeanException");
+ error++;
+ } catch (NotCompliantMBeanException e) {
+ boolean found = false;
+ Throwable t = e.getCause();
+ while (t != null) {
+ if (t instanceof IllegalArgumentException &&
+ "GetMBeanInfoExceptionTest".equals(t.getMessage())) {
+ found = true;
+ }
+ t = t.getCause();
+ }
+ if (found) {
+ System.out.println("Found expected IllegalArgumentException");
+ } else {
+ System.out.println("Didn't find expected IllegalArgumentException");
+ error++;
+ }
+ } catch (Exception e) {
+ System.out.println("Got " + e.getClass().getName() +
+ "instead of expected NotCompliantMBeanException");
+ error++;
+ }
+
+ if (error > 0) {
+ System.out.println("Test failed");
+ throw new IllegalArgumentException("Test failed");
+ } else {
+ System.out.println("Test passed");
+ }
+ }
+}
diff --git a/test/javax/management/Introspector/IdenticalMBeanInfoTest.java b/test/javax/management/Introspector/IdenticalMBeanInfoTest.java
new file mode 100644
index 0000000..150d0d7
--- /dev/null
+++ b/test/javax/management/Introspector/IdenticalMBeanInfoTest.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5042004
+ * @summary Check that MBeans with the same class have identical MBeanInfo
+ * unless they are NotificationBroadcasters
+ * @author Eamonn McManus
+ * @run clean IdenticalMBeanInfoTest
+ * @run build IdenticalMBeanInfoTest
+ * @run main IdenticalMBeanInfoTest
+ */
+
+import javax.management.*;
+
+/* What we test here is not required by the spec. It is an
+ optimization that can save a considerable amount of memory when
+ there are many MBeans of the same type. There is no reason why two
+ Standard MBeans of the same type should have different MBeanInfo
+ objects, unless they are NotificationBroadcasters and return
+ different arrays from getNotificationInfo(). Note that two MBeans
+ that share the same MBean interface but are of different classes
+ cannot have the same MBeanInfo because the MBeanInfo includes the
+ implementation class name. */
+public class IdenticalMBeanInfoTest {
+ private static String failure = null;
+
+ public static interface WhatsitMBean {
+ public int getReadOnly();
+ public int getReadWrite();
+ public void setReadWrite(int x);
+ public int op(int x, int y);
+ }
+
+ public static class Whatsit implements WhatsitMBean {
+ public Whatsit() {}
+ public Whatsit(int irrelevant) {}
+
+ public int getReadOnly() { return 0; }
+ public int getReadWrite() { return 0; }
+ public void setReadWrite(int x) {}
+ public int op(int x, int y) { return 0; }
+ }
+
+ public static interface BroadcasterMBean extends WhatsitMBean {
+ }
+
+ public static class Broadcaster extends Whatsit
+ implements BroadcasterMBean, NotificationBroadcaster {
+ private static int nextId = 1;
+ private int id = nextId++;
+
+ public void addNotificationListener(NotificationListener l,
+ NotificationFilter f,
+ Object h) {}
+
+ public void removeNotificationListener(NotificationListener l) {}
+
+ public MBeanNotificationInfo[] getNotificationInfo() {
+ return new MBeanNotificationInfo[] {
+ new MBeanNotificationInfo(new String[] {"type" + id},
+ "something",
+ "a something")
+ };
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ ObjectName on1 = new ObjectName("d:type=Whatsit,number=1");
+ ObjectName on2 = new ObjectName("d:type=Whatsit,number=2");
+ ObjectName on3 = new ObjectName("d:type=Whatsit,number=3");
+ ObjectName on4 = new ObjectName("d:type=Whatsit,number=4");
+ ObjectName on5 = new ObjectName("d:type=Whatsit,number=5");
+
+ mbs.registerMBean(new Whatsit(), on1);
+ mbs.createMBean(Whatsit.class.getName(), on2);
+ DynamicMBean mbean =
+ new StandardMBean(new Whatsit(), WhatsitMBean.class);
+ mbs.registerMBean(mbean, on3);
+ mbs.registerMBean(new Broadcaster(), on4);
+ mbs.createMBean(Broadcaster.class.getName(), on5);
+ MBeanInfo mbi1 = mbs.getMBeanInfo(on1);
+ MBeanInfo mbi2 = mbs.getMBeanInfo(on2);
+ MBeanInfo mbi3 = mbs.getMBeanInfo(on3);
+ MBeanInfo mbi4 = mbs.getMBeanInfo(on4);
+ MBeanInfo mbi5 = mbs.getMBeanInfo(on5);
+
+ if (mbi1 != mbi2) {
+ fail("Two MBeans of the same class should have identical " +
+ "MBeanInfo");
+ }
+
+ if (mbi2 != mbi3) {
+ if (true)
+ System.out.println("IGNORING StandardMBean(...) failure");
+ else
+ fail("Plain Standard MBean should have identical MBeanInfo " +
+ "to StandardMBean(...) with same class as resource");
+ }
+
+ if (mbi4 == mbi5 || mbi4.equals(mbi5)) {
+ fail("Two MBeans of the same class should NOT have identical " +
+ "MBeanInfo if they are NotificationBroadcasters and "+
+ "do not return the same MBeanNotificationInfo[]");
+ }
+
+ if (failure == null) {
+ System.out.println("Test passed");
+ return;
+ }
+
+ throw new Exception("TEST FAILED: " + failure);
+ }
+
+ private static void fail(String why) {
+ System.out.println("FAILURE: " + why);
+ failure = why;
+ }
+}
diff --git a/test/javax/management/Introspector/ImmutableNotificationInfoTest.java b/test/javax/management/Introspector/ImmutableNotificationInfoTest.java
new file mode 100644
index 0000000..7ddbbed
--- /dev/null
+++ b/test/javax/management/Introspector/ImmutableNotificationInfoTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6295859
+ * @summary Check that a StandardMBean has immutableInfo=true if it is
+ * a NotificationBroadcasterSupport that doesn't override getNotificationInfo()
+ * @author Eamonn McManus
+ * @run clean ImmutableNotificationInfoTest
+ * @run build ImmutableNotificationInfoTest
+ * @run main ImmutableNotificationInfoTest
+ */
+import javax.management.Descriptor;
+import javax.management.MBeanInfo;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.NotificationBroadcaster;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+
+public class ImmutableNotificationInfoTest {
+ public interface UserBroadcasterMBean {}
+ public interface NoOverrideNBSMBean {}
+ public interface OverrideNBSMBean {}
+
+ public static class UserBroadcaster
+ implements UserBroadcasterMBean, NotificationBroadcaster {
+ public void removeNotificationListener(NotificationListener listener) {
+ }
+
+ public void addNotificationListener(NotificationListener listener,
+ NotificationFilter filter, Object handback) {
+ }
+
+ public MBeanNotificationInfo[] getNotificationInfo() {
+ return new MBeanNotificationInfo[0];
+ }
+ }
+
+ public static class NoOverrideNBS extends NotificationBroadcasterSupport
+ implements NoOverrideNBSMBean {
+ }
+
+ public static class OverrideNBS extends NotificationBroadcasterSupport
+ implements OverrideNBSMBean {
+ public MBeanNotificationInfo[] getNotificationInfo() {
+ return new MBeanNotificationInfo[0];
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ boolean ok;
+ ok = test(new UserBroadcaster(), false);
+ ok &= test(new NoOverrideNBS(), true);
+ ok &= test(new OverrideNBS(), false);
+ if (!ok)
+ throw new Exception("TEST FAILED: immutability incorrect");
+ }
+
+ private static boolean test(Object mbean, boolean expectImmutable)
+ throws Exception {
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ ObjectName on = new ObjectName("a:b=c");
+ mbs.registerMBean(mbean, on);
+ MBeanInfo mbi = mbs.getMBeanInfo(on);
+ Descriptor d = mbi.getDescriptor();
+ String immutableValue = (String) d.getFieldValue("immutableInfo");
+ boolean immutable = ("true".equals(immutableValue));
+ if (immutable != expectImmutable) {
+ System.out.println("FAILED: " + mbean.getClass().getName() +
+ " -> " + immutableValue);
+ return false;
+ } else {
+ System.out.println("OK: " + mbean.getClass().getName());
+ return true;
+ }
+ }
+}
diff --git a/test/javax/management/Introspector/InvokeGettersTest.java b/test/javax/management/Introspector/InvokeGettersTest.java
new file mode 100644
index 0000000..1866ed1
--- /dev/null
+++ b/test/javax/management/Introspector/InvokeGettersTest.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6317101
+ * @summary Test that the jmx.invoke.getters system property works
+ * @author Eamonn McManus
+ * @run clean InvokeGettersTest
+ * @run build InvokeGettersTest
+ * @run main InvokeGettersTest
+ */
+
+import java.util.Arrays;
+import javax.management.*;
+
+public class InvokeGettersTest {
+ public static interface ThingMBean {
+ public int getWhatsit();
+ public void setWhatsit(int x);
+ public boolean isTrue();
+ }
+
+ public static class Thing implements ThingMBean {
+ public int getWhatsit() {
+ return whatsit;
+ }
+
+ public void setWhatsit(int x) {
+ whatsit = x;
+ }
+
+ public boolean isTrue() {
+ return true;
+ }
+
+ private int whatsit;
+ }
+
+ public static void main(String[] args) throws Exception {
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ ObjectName on = new ObjectName("a:b=c");
+ mbs.registerMBean(new Thing(), on);
+ if (test(mbs, on, false))
+ System.out.println("OK: invoke without jmx.invoke.getters");
+ System.setProperty("jmx.invoke.getters", "true");
+ if (test(mbs, on, true))
+ System.out.println("OK: invoke with jmx.invoke.getters");
+ if (failure == null)
+ System.out.println("TEST PASSED");
+ else
+ throw new Exception("TEST FAILED: " + failure);
+ }
+
+ private static boolean test(MBeanServer mbs, ObjectName on,
+ boolean shouldWork) throws Exception {
+ ++x;
+ mbs.setAttribute(on, new Attribute("Whatsit", x));
+ Integer got = (Integer) mbs.getAttribute(on, "Whatsit");
+ if (got != x)
+ return fail("Set attribute was not got: " + got);
+ ++x;
+ try {
+ mbs.invoke(on, "setWhatsit", new Object[] {x}, new String[] {"int"});
+ if (!shouldWork)
+ return fail("invoke setWhatsit worked but should not have");
+ System.out.println("invoke setWhatsit worked as expected");
+ } catch (ReflectionException e) {
+ if (shouldWork)
+ return fail("invoke setWhatsit did not work but should have");
+ System.out.println("set got expected exception: " + e);
+ }
+ try {
+ got = (Integer) mbs.invoke(on, "getWhatsit", null, null);
+ if (!shouldWork)
+ return fail("invoke getWhatsit worked but should not have");
+ if (got != x)
+ return fail("Set attribute through invoke was not got: " + got);
+ System.out.println("invoke getWhatsit worked as expected");
+ } catch (ReflectionException e) {
+ if (shouldWork)
+ return fail("invoke getWhatsit did not work but should have");
+ System.out.println("get got expected exception: " + e);
+ }
+ try {
+ boolean t = (Boolean) mbs.invoke(on, "isTrue", null, null);
+ if (!shouldWork)
+ return fail("invoke isTrue worked but should not have");
+ if (!t)
+ return fail("isTrue returned false");
+ System.out.println("invoke isTrue worked as expected");
+ } catch (ReflectionException e) {
+ if (shouldWork)
+ return fail("invoke isTrue did not work but should have");
+ else
+ System.out.println("isTrue got expected exception: " + e);
+ }
+
+ // Following cases should fail whether or not jmx.invoke.getters is set
+ final Object[][] badInvokes = {
+ {"isWhatsit", null, null},
+ {"getWhatsit", new Object[] {5}, new String[] {"int"}},
+ {"setWhatsit", new Object[] {false}, new String[] {"boolean"}},
+ {"getTrue", null, null},
+ };
+ boolean ok = true;
+ for (Object[] args : badInvokes) {
+ String name = (String) args[0];
+ Object[] params = (Object[]) args[1];
+ String[] sig = (String[]) args[2];
+ String what =
+ "invoke " + name + (sig == null ? "[]" : Arrays.toString(sig));
+ try {
+ mbs.invoke(on, name, params, sig);
+ ok = fail(what + " worked but should not have");
+ } catch (ReflectionException e) {
+ if (e.getCause() instanceof NoSuchMethodException)
+ System.out.println(what + " failed as expected");
+ else {
+ ok = fail(what + " got exception with wrong nested " +
+ "exception: " + e.getCause());
+ }
+ }
+ }
+
+ return ok;
+ }
+
+ private static boolean fail(String why) {
+ failure = why;
+ System.out.println("FAILED: " + why);
+ return false;
+ }
+
+ private static int x;
+ private static String failure;
+}
diff --git a/test/javax/management/Introspector/IsMethodTest.java b/test/javax/management/Introspector/IsMethodTest.java
new file mode 100644
index 0000000..c8d3446
--- /dev/null
+++ b/test/javax/management/Introspector/IsMethodTest.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4947001 4954369 4954409 4954410
+ * @summary Test that "Boolean isX()" and "int isX()" define operations
+ * @author Eamonn McManus
+ * @run clean IsMethodTest
+ * @run build IsMethodTest
+ * @run main IsMethodTest
+ */
+
+import javax.management.*;
+
+/*
+ This regression test covers a slew of bugs in Standard MBean
+ reflection. Lots of corner cases were incorrect:
+
+ In the MBeanInfo for a Standard MBean:
+ - Boolean isX() defined an attribute as if it were boolean isX()
+ - int isX() defined neither an attribute nor an operation
+
+ When calling MBeanServer.getAttribute:
+ - int get() and void getX() were considered attributes even though they
+ were operations in MBeanInfo
+
+ When calling MBeanServer.invoke:
+ - Boolean isX() could not be called because it was (consistently with
+ MBeanInfo) considered an attribute, not an operation
+*/
+public class IsMethodTest {
+ public static void main(String[] args) throws Exception {
+ System.out.println("Test that Boolean isX() and int isX() both " +
+ "define operations not attributes");
+
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ Object mb = new IsMethod();
+ ObjectName on = new ObjectName("a:b=c");
+ mbs.registerMBean(mb, on);
+ MBeanInfo mbi = mbs.getMBeanInfo(on);
+
+ boolean ok = true;
+
+ MBeanAttributeInfo[] attrs = mbi.getAttributes();
+ if (attrs.length == 0)
+ System.out.println("OK: MBean defines 0 attributes");
+ else {
+ ok = false;
+ System.out.println("TEST FAILS: MBean should define 0 attributes");
+ for (int i = 0; i < attrs.length; i++) {
+ System.out.println(" " + attrs[i].getType() + " " +
+ attrs[i].getName());
+ }
+ }
+
+ MBeanOperationInfo[] ops = mbi.getOperations();
+ if (ops.length == 4)
+ System.out.println("OK: MBean defines 4 operations");
+ else {
+ ok = false;
+ System.out.println("TEST FAILS: MBean should define 4 operations");
+ }
+ for (int i = 0; i < ops.length; i++) {
+ System.out.println(" " + ops[i].getReturnType() + " " +
+ ops[i].getName());
+ }
+
+ final String[] bogusAttrNames = {"", "Lost", "Thingy", "Whatsit"};
+ for (int i = 0; i < bogusAttrNames.length; i++) {
+ final String bogusAttrName = bogusAttrNames[i];
+ try {
+ mbs.getAttribute(on, bogusAttrName);
+ ok = false;
+ System.out.println("TEST FAILS: getAttribute(\"" +
+ bogusAttrName + "\") should not work");
+ } catch (AttributeNotFoundException e) {
+ System.out.println("OK: getAttribute(" + bogusAttrName +
+ ") got exception as expected");
+ }
+ }
+
+ final String[] opNames = {"get", "getLost", "isThingy", "isWhatsit"};
+ for (int i = 0; i < opNames.length; i++) {
+ final String opName = opNames[i];
+ try {
+ mbs.invoke(on, opName, new Object[0], new String[0]);
+ System.out.println("OK: invoke(\"" + opName + "\") worked");
+ } catch (Exception e) {
+ ok = false;
+ System.out.println("TEST FAILS: invoke(" + opName +
+ ") got exception: " + e);
+ }
+ }
+
+ if (ok)
+ System.out.println("Test passed");
+ else {
+ System.out.println("TEST FAILED");
+ System.exit(1);
+ }
+ }
+
+ public static interface IsMethodMBean {
+ public int get();
+ public void getLost();
+ public Boolean isThingy();
+ public int isWhatsit();
+ }
+
+ public static class IsMethod implements IsMethodMBean {
+ public int get() {
+ return 0;
+ }
+
+ public void getLost() {
+ }
+
+ public Boolean isThingy() {
+ return Boolean.TRUE;
+ }
+
+ public int isWhatsit() {
+ return 0;
+ }
+ }
+}
diff --git a/test/javax/management/Introspector/LegacyIntrospectorTest.java b/test/javax/management/Introspector/LegacyIntrospectorTest.java
new file mode 100644
index 0000000..19499dd
--- /dev/null
+++ b/test/javax/management/Introspector/LegacyIntrospectorTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6316460
+ * @summary Test that the legacy com.sun.management.jmx.Introspector
+ * methods work.
+ * @author Eamonn McManus
+ * @run clean LegacyIntrospectorTest
+ * @run build LegacyIntrospectorTest
+ * @run main LegacyIntrospectorTest
+ */
+
+import javax.management.*;
+import com.sun.management.jmx.*;
+
+public class LegacyIntrospectorTest {
+ public static interface TestMBean {
+ public int getWhatever();
+ }
+ public static class Test implements TestMBean {
+ public int getWhatever() {return 0;}
+ }
+
+ @SuppressWarnings("deprecation")
+ public static void main(String[] args) throws Exception {
+ MBeanInfo mbi = Introspector.testCompliance(Test.class);
+ MBeanAttributeInfo mbai = mbi.getAttributes()[0];
+ if (!mbai.getName().equals("Whatever"))
+ throw new Exception("Wrong attribute name: " + mbai.getName());
+ Class c = Introspector.getMBeanInterface(Test.class);
+ if (c != TestMBean.class)
+ throw new Exception("Wrong interface: " + c);
+
+ MBeanServer mbs1 = new MBeanServerImpl();
+ if (!mbs1.getDefaultDomain().equals("DefaultDomain"))
+ throw new Exception("Wrong default domain: " + mbs1.getDefaultDomain());
+
+ MBeanServer mbs2 = new MBeanServerImpl("Foo");
+ if (!mbs2.getDefaultDomain().equals("Foo"))
+ throw new Exception("Wrong default domain: " + mbs2.getDefaultDomain());
+
+ ObjectName delegateName =
+ new ObjectName("JMImplementation:type=MBeanServerDelegate");
+ MBeanInfo delegateInfo = mbs2.getMBeanInfo(delegateName);
+ MBeanInfo refDelegateInfo =
+ MBeanServerFactory.newMBeanServer().getMBeanInfo(delegateName);
+ if (!delegateInfo.equals(refDelegateInfo))
+ throw new Exception("Wrong delegate info from MBeanServerImpl: " +
+ delegateInfo);
+
+ System.out.println("TEST PASSED");
+ }
+}
diff --git a/test/javax/management/Introspector/NotAnMBeanTest.java b/test/javax/management/Introspector/NotAnMBeanTest.java
new file mode 100644
index 0000000..344fb76
--- /dev/null
+++ b/test/javax/management/Introspector/NotAnMBeanTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4914805
+ * @summary Ensure that the right exception is thrown for illegal MBeans
+ * @author Eamonn McManus
+ * @run clean NotAnMBeanTest
+ * @run build NotAnMBeanTest
+ * @run main NotAnMBeanTest
+ */
+
+import javax.management.*;
+
+public class NotAnMBeanTest {
+ public static void main(String[] args) throws Exception {
+ System.out.println("Try to create a java.lang.Integer as an MBean");
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ try {
+ mbs.createMBean("java.lang.Integer", null);
+ System.out.println("TEST FAILS: createMBean of " +
+ "java.lang.Integer succeeded!");
+ System.exit(1);
+ } catch (NotCompliantMBeanException e) {
+ System.out.println("Got expected exception: " + e);
+ System.out.println("Test passed");
+ }
+ }
+}
diff --git a/test/javax/management/Introspector/NotCompliantCauseTest.java b/test/javax/management/Introspector/NotCompliantCauseTest.java
new file mode 100644
index 0000000..c9eb514
--- /dev/null
+++ b/test/javax/management/Introspector/NotCompliantCauseTest.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test NotCompliantCauseTest.java
+ * @bug 6374290
+ * @summary Test that NotCompliantMBeanException has a cause in case of
+ * type mapping problems.
+ * @author Daniel Fuchs, Alexander Shusherov
+ * @run clean NotCompliantCauseTest
+ * @run build NotCompliantCauseTest
+ * @run main NotCompliantCauseTest
+ */
+/*
+ * NotCompliantCauseTest.java
+ *
+ * Created on January 20, 2006, 2:56 PM / dfuchs
+ *
+ */
+
+import java.util.Random;
+import java.util.logging.Logger;
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
+import javax.management.openmbean.OpenDataException;
+
+/**
+ *
+ * @author Sun Microsystems, 2005 - All rights reserved.
+ */
+public class NotCompliantCauseTest {
+
+ /**
+ * A logger for this class.
+ **/
+ private static final Logger LOG =
+ Logger.getLogger(NotCompliantCauseTest.class.getName());
+
+ /**
+ * Creates a new instance of NotCompliantCauseTest
+ */
+ public NotCompliantCauseTest() {
+ }
+
+ /**
+ * Test that NotCompliantMBeanException has a cause in case of
+ * type mapping problems.
+ **/
+ public static void main(String[] args) {
+ NotCompliantCauseTest instance = new NotCompliantCauseTest();
+
+ instance.test1();
+ }
+
+ public static class RuntimeTestException extends RuntimeException {
+ public RuntimeTestException(String msg) {
+ super(msg);
+ }
+ public RuntimeTestException(String msg, Throwable cause) {
+ super(msg,cause);
+ }
+ public RuntimeTestException(Throwable cause) {
+ super(cause);
+ }
+ }
+
+ /**
+ * Test that NotCompliantMBeanException has a cause in case of
+ * type mapping problems.
+ **/
+ void test1() {
+ try {
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ ObjectName oname = new ObjectName("domain:type=test");
+
+ mbs.createMBean(NotCompliant.class.getName(), oname);
+ System.err.println("ERROR: expected " +
+ "NotCompliantMBeanException not thrown");
+ throw new RuntimeTestException("NotCompliantMBeanException not thrown");
+ } catch (RuntimeTestException e) {
+ throw e;
+ } catch (NotCompliantMBeanException e) {
+ Throwable cause = e.getCause();
+ if (cause == null)
+ throw new RuntimeTestException("NotCompliantMBeanException " +
+ "doesn't have any cause.", e);
+ while (cause.getCause() != null) {
+ if (cause instanceof OpenDataException) break;
+ cause = cause.getCause();
+ }
+ if (! (cause instanceof OpenDataException))
+ throw new RuntimeTestException("NotCompliantMBeanException " +
+ "doesn't have expected cause ("+
+ OpenDataException.class.getName()+"): "+cause, e);
+ System.err.println("SUCCESS: Found expected cause: " + cause);
+ } catch (Exception e) {
+ System.err.println("Unexpected exception: " + e);
+ throw new RuntimeException("Unexpected exception: " + e,e);
+ }
+ }
+
+ public interface NotCompliantMXBean {
+ Random returnRandom();
+ }
+
+ public static class NotCompliant implements NotCompliantMXBean {
+ public Random returnRandom() {
+ return new Random();
+ }
+ }
+
+}
diff --git a/test/javax/management/Introspector/SetWrongTypeAttributeTest.java b/test/javax/management/Introspector/SetWrongTypeAttributeTest.java
new file mode 100644
index 0000000..0be985f
--- /dev/null
+++ b/test/javax/management/Introspector/SetWrongTypeAttributeTest.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6324523
+ * @summary Check that setting the wrong type of an attribute in a Standard
+ * MBean or MXBean causes InvalidAttributeValueException
+ * @author Eamonn McManus
+ * @run clean SetWrongTypeAttributeTest
+ * @run build SetWrongTypeAttributeTest
+ * @run main SetWrongTypeAttributeTest
+ */
+
+import java.util.*;
+import javax.management.*;
+
+public class SetWrongTypeAttributeTest {
+ // In this 2D array, the first element of each subarray is an attribute
+ // to do setAttribute on, and the remaining elements are values that
+ // should provoke InvalidAttributeValueException.
+ private static final Object[][] TEST_VALUES = {
+ {"Foo", null, 5, "false", Collections.<String,String>emptyMap()},
+ {"Name", 5, false, Collections.<String,String>emptyMap()},
+ {"Properties", 5, false, Collections.singleton("foo")},
+ };
+
+ public static interface BlahMBean {
+ public boolean isFoo();
+ public void setFoo(boolean foo);
+
+ public String getName();
+ public void setName(String name);
+
+ public Map<String,String> getProperties();
+ public void setProperties(Map<String,String> map);
+ }
+
+ public static interface BlahMXBean {
+ public boolean isFoo();
+ public void setFoo(boolean foo);
+
+ public String getName();
+ public void setName(String name);
+
+ public Map<String,String> getProperties();
+ public void setProperties(Map<String,String> map);
+ }
+
+ public static class BlahBase {
+ public boolean isFoo() {
+ return foo;
+ }
+ public void setFoo(boolean foo) {
+ this.foo = foo;
+ }
+
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Map<String,String> getProperties() {
+ return properties;
+ }
+ public void setProperties(Map<String,String> map) {
+ this.properties = map;
+ }
+
+ private boolean foo;
+ private String name;
+ private Map<String,String> properties;
+ }
+
+ public static class Blah extends BlahBase implements BlahMBean {}
+
+ public static class MXBlah extends BlahBase implements BlahMXBean {}
+
+ public static class StdBlah extends StandardMBean implements BlahMBean {
+ public StdBlah() throws NotCompliantMBeanException {
+ super(BlahMBean.class);
+ }
+
+ public boolean isFoo() {
+ return foo;
+ }
+ public void setFoo(boolean foo) {
+ this.foo = foo;
+ }
+
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Map<String,String> getProperties() {
+ return properties;
+ }
+ public void setProperties(Map<String,String> map) {
+ this.properties = map;
+ }
+
+ private boolean foo;
+ private String name;
+ private Map<String,String> properties;
+ }
+
+ public static class StdMXBlah extends StandardMBean implements BlahMXBean {
+ public StdMXBlah() throws NotCompliantMBeanException {
+ super(BlahMXBean.class, true);
+ }
+
+ public boolean isFoo() {
+ return foo;
+ }
+ public void setFoo(boolean foo) {
+ this.foo = foo;
+ }
+
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Map<String,String> getProperties() {
+ return properties;
+ }
+ public void setProperties(Map<String,String> map) {
+ this.properties = map;
+ }
+
+ private boolean foo;
+ private String name;
+ private Map<String,String> properties;
+ }
+
+ public static void main(String[] args) throws Exception {
+ test("Standard Blah", new Blah());
+ test("StandardMBean implementing Blah", new StdBlah());
+ test("StandardMBean wrapping Blah",
+ new StandardMBean(new Blah(), BlahMBean.class));
+ test("MXBean Blah", new MXBlah());
+ test("StandardMBean implementing MXBean Blah", new StdMXBlah());
+ test("StandardMBean wrapping MXBean Blah",
+ new StandardMBean(new MXBlah(), BlahMXBean.class, true));
+
+ if (failure == null)
+ System.out.println("TEST PASSED");
+ else
+ throw new Exception("TEST FAILED: " + failure);
+ }
+
+ private static void test(String what, Object obj) throws Exception {
+ System.out.println(what + "...");
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ ObjectName on = new ObjectName("a:b=c");
+ mbs.registerMBean(obj, on);
+ for (Object[] testValue : TEST_VALUES) {
+ String attrName = (String) testValue[0];
+ for (int i = 1; i < testValue.length; i++) {
+ Object value = testValue[i];
+ final String doing =
+ "setAttribute(" + attrName + ", " + value + ")";
+ try {
+ mbs.setAttribute(on, new Attribute("Foo", 5));
+ fail(what, doing + " succeeded but should fail!");
+ } catch (InvalidAttributeValueException e) {
+ final String msg =
+ doing + ": OK, got expected " +
+ "InvalidAttributeValueException";
+ System.out.println(msg);
+ } catch (Throwable e) {
+ fail(what, doing + " got wrong exception: " + e);
+ e.printStackTrace(System.out);
+ }
+ }
+ }
+ }
+
+ private static void fail(String what, String msg) {
+ failure = what + ": " + msg;
+ System.out.println("FAILED: " + failure);
+ }
+
+ private static String failure;
+}
diff --git a/test/javax/management/Introspector/SqeDescriptorKey.java b/test/javax/management/Introspector/SqeDescriptorKey.java
new file mode 100644
index 0000000..5b9eca9
--- /dev/null
+++ b/test/javax/management/Introspector/SqeDescriptorKey.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ *
+ * Used by AnnotationSecurityTest.java
+ **/
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import javax.management.DescriptorKey;
+
+/**
+ * An annotation used by AnnotationSecurityTest.java
+ **/
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+public @interface SqeDescriptorKey {
+ @DescriptorKey("sqeDescriptorKey")
+ String value();
+}
diff --git a/test/javax/management/Introspector/UnDescribed.java b/test/javax/management/Introspector/UnDescribed.java
new file mode 100644
index 0000000..fb4e596
--- /dev/null
+++ b/test/javax/management/Introspector/UnDescribed.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ *
+ * Used by AnnotationSecurityTest.java
+ **/
+import java.beans.ConstructorProperties;
+
+/**
+ * An MBean used by AnnotationSecurityTest.java
+ **/
+public class UnDescribed implements UnDescribedMBean {
+ private String name ;
+
+ public UnDescribed() {}
+
+ @ConstructorProperties({"name", "unused"})
+ public UnDescribed(String name, String unused) {
+ this.name = name ;
+ }
+
+ public String getStringProp() {
+ return this.name;
+ }
+
+ public void setStringProp(String name) {
+ this.name = name;
+ }
+
+ public void doNothing() {}
+
+ public void doNothingParam(String param) {}
+}
diff --git a/test/javax/management/Introspector/UnDescribedMBean.java b/test/javax/management/Introspector/UnDescribedMBean.java
new file mode 100644
index 0000000..114cdf1
--- /dev/null
+++ b/test/javax/management/Introspector/UnDescribedMBean.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ *
+ * Used by AnnotationSecurityTest.java
+ **/
+public interface UnDescribedMBean {
+
+ public String getStringProp();
+
+ public void setStringProp(String name);
+
+ public void doNothing();
+
+ public void doNothingParam(String name);
+}
diff --git a/test/javax/management/Introspector/UnregisterMBeanExceptionTest.java b/test/javax/management/Introspector/UnregisterMBeanExceptionTest.java
new file mode 100644
index 0000000..ccb8d5c
--- /dev/null
+++ b/test/javax/management/Introspector/UnregisterMBeanExceptionTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6328682
+ * @summary Test that MBeanServer.unregisterMBean() correctly unregisters
+ * the supplied MBean although DynamicMBean.getMBeanInfo() throws
+ * a runtime exception.
+ * @author Luis-Miguel Alventosa
+ * @run clean UnregisterMBeanExceptionTest
+ * @run build UnregisterMBeanExceptionTest
+ * @run main UnregisterMBeanExceptionTest
+ */
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.DynamicMBean;
+import javax.management.InvalidAttributeValueException;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+
+public class UnregisterMBeanExceptionTest {
+
+ public static class TestDynamicMBean implements DynamicMBean {
+
+ public Object getAttribute(String attribute) throws
+ AttributeNotFoundException,
+ MBeanException,
+ ReflectionException {
+ return null;
+ }
+
+ public void setAttribute(Attribute attribute) throws
+ AttributeNotFoundException,
+ InvalidAttributeValueException,
+ MBeanException,
+ ReflectionException {
+ }
+
+ public AttributeList getAttributes(String[] attributes) {
+ return null;
+ }
+
+ public AttributeList setAttributes(AttributeList attributes) {
+ return null;
+ }
+
+ public Object invoke(String op, Object params[], String sign[]) throws
+ MBeanException,
+ ReflectionException {
+ return null;
+ }
+
+ public MBeanInfo getMBeanInfo() {
+ if (throwException)
+ throw new RuntimeException("UnregisterMBeanExceptionTest");
+ else
+ return new MBeanInfo(this.getClass().getName(), "Test",
+ null, null, null, null);
+ }
+
+ public boolean throwException;
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ // Instantiate the MBean server
+ //
+ System.out.println("Create the MBean server");
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ // Register the MBean
+ //
+ System.out.println("Create a TestDynamicMBean");
+ TestDynamicMBean obj = new TestDynamicMBean();
+ ObjectName n = new ObjectName("d:k=v");
+ System.out.println("Register a TestDynamicMBean");
+ mbs.registerMBean(obj, n);
+ obj.throwException = true;
+ System.out.println("Unregister a TestDynamicMBean");
+ try {
+ mbs.unregisterMBean(n);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Test failed", e);
+ }
+ boolean isRegistered = mbs.isRegistered(n);
+ System.out.println("Is MBean Registered? " + isRegistered);
+
+ if (isRegistered) {
+ throw new IllegalArgumentException(
+ "Test failed: the MBean is still registered");
+ } else {
+ System.out.println("Test passed");
+ }
+ }
+}
diff --git a/test/javax/management/MBeanInfo/EqualExceptionTest.java b/test/javax/management/MBeanInfo/EqualExceptionTest.java
new file mode 100644
index 0000000..fd0ec6d
--- /dev/null
+++ b/test/javax/management/MBeanInfo/EqualExceptionTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5071110
+ * @summary Test whether an null descriptor will cause an NullPointerException.
+ * @author Shanliang JIANG
+ * @run clean EqualExceptionTest
+ * @run build EqualExceptionTest
+ * @run main EqualExceptionTest
+ */
+
+
+import java.io.IOException;
+import javax.management.*;
+
+public class EqualExceptionTest {
+ public static void main(String[] args) throws Exception {
+ System.out.println("<<< Test whether an null descriptor will cause an NullPointerException.");
+
+ MBeanInfo mbi1 = new MBeanInfo("MyClass","",null,null,null,null);
+ MBeanInfo mbi2 = new MBeanInfo("MyClass",null,null,null,null,null);
+ System.out.println("<<< mbi1.equals(mbi2) = "+mbi1.equals(mbi2));
+
+ System.out.println("<<< Test whether an null class name will cause an NullPointerException.");
+ MBeanInfo mbi3 = new MBeanInfo("MyClass","",null,null,null,null);
+ MBeanInfo mbi4 = new MBeanInfo(null,null,null,null,null,null);
+ System.out.println("<<< mbi3.equals(mbi4) = "+mbi3.equals(mbi4));
+
+ }
+}
diff --git a/test/javax/management/MBeanInfo/MBeanInfoEqualsTest.java b/test/javax/management/MBeanInfo/MBeanInfoEqualsTest.java
new file mode 100644
index 0000000..018a22e
--- /dev/null
+++ b/test/javax/management/MBeanInfo/MBeanInfoEqualsTest.java
@@ -0,0 +1,379 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4719923
+ * @summary Test that MBeanInfo.equals works even for mutable subclasses
+ * @author Eamonn McManus
+ * @run clean MBeanInfoEqualsTest
+ * @run build MBeanInfoEqualsTest
+ * @run main MBeanInfoEqualsTest
+ */
+
+/* Test that MBeanInfo and its referenced classes implement the equals
+ and hashCode methods correctly. These classes include some magic
+ to improve performance based on the classes' immutability. The
+ logic checks that any subclasses encountered remain immutable, and
+ falls back on less performant code if not. */
+
+import javax.management.*;
+import java.lang.reflect.*;
+
+public class MBeanInfoEqualsTest {
+ // Class just used for reflection
+ private static class Toy {
+ public Toy() {}
+ public Toy(int a, String b) {}
+ public int getA() {return 0;}
+ public void setA(int a) {}
+ public boolean isB() {return false;}
+ public void setB(boolean b) {}
+ public void run() {}
+ public void blah(int a, String b) {}
+ }
+
+ static final Class toy = Toy.class;
+ static final Constructor con1, con2;
+ static final Method getA, setA, isB, setB, run, blah;
+ static {
+ try {
+ con1 = toy.getConstructor(new Class[] {});
+ con2 = toy.getConstructor(new Class[] {Integer.TYPE,
+ String.class});
+ getA = toy.getMethod("getA", new Class[] {});
+ setA = toy.getMethod("setA", new Class[] {Integer.TYPE});
+ isB = toy.getMethod("isB", new Class[] {});
+ setB = toy.getMethod("setB", new Class[] {Boolean.TYPE});
+ run = toy.getMethod("run", new Class[] {});
+ blah = toy.getMethod("blah", new Class[] {Integer.TYPE,
+ String.class});
+ } catch (Exception e) {
+ throw new Error(e.getMessage());
+ }
+ }
+
+ private static final MBeanAttributeInfo
+ newMBeanAttributeInfo(String name, String description,
+ Method getter, Method setter) {
+ try {
+ return new MBeanAttributeInfo(name, description, getter, setter);
+ } catch (IntrospectionException e) {
+ throw new Error(e.getMessage());
+ }
+ }
+
+ static final MBeanAttributeInfo
+ a1a = new MBeanAttributeInfo("thing", "java.foo.bar", "an attribute",
+ true, true, false),
+ a1b = new MBeanAttributeInfo("thing", "java.foo.bar", "an attribute",
+ true, true, false),
+ a2a = new MBeanAttributeInfo("splob", "java.foo.bar", "an attribute",
+ true, true, false),
+ a2b = new MBeanAttributeInfo(a2a.getName(), a2a.getType(),
+ a2a.getDescription(), a2a.isReadable(),
+ a2a.isWritable(), a2a.isIs()),
+ a3 = new MBeanAttributeInfo("splob", "java.foo.bar", "a whatsit",
+ true, true, false),
+ a4 = new MBeanAttributeInfo("splob", "java.foo.bar", "a whatsit",
+ false, true, false),
+ a5a = newMBeanAttributeInfo("a", "an attribute", getA, setA),
+ a5b = new MBeanAttributeInfo("a", "int", "an attribute",
+ true, true, false),
+ a6a = newMBeanAttributeInfo("a", "an attribute", getA, null),
+ a6b = new MBeanAttributeInfo("a", "int", "an attribute",
+ true, false, false),
+ a7a = newMBeanAttributeInfo("a", "an attribute", null, setA),
+ a7b = new MBeanAttributeInfo("a", "int", "an attribute",
+ false, true, false),
+ a8a = newMBeanAttributeInfo("b", "an attribute", isB, setB),
+ a8b = new MBeanAttributeInfo("b", "boolean", "an attribute",
+ true, true, true),
+ a9a = newMBeanAttributeInfo("b", "an attribute", isB, null),
+ a9b = new MBeanAttributeInfo("b", "boolean", "an attribute",
+ true, false, true);
+
+ static final MBeanParameterInfo
+ p1a = new MBeanParameterInfo("thing", "java.foo.bar", "a parameter"),
+ p1b = new MBeanParameterInfo("thing", "java.foo.bar", "a parameter"),
+ p2 = new MBeanParameterInfo("splob", "java.foo.bar", "a parameter"),
+ p3 = new MBeanParameterInfo("thing", "java.foo.bax", "a parameter"),
+ p4 = new MBeanParameterInfo("thing", "java.foo.bar", "a whatsit");
+
+ static final MBeanConstructorInfo
+ c1a = new MBeanConstructorInfo("a constructor", con1),
+ c1b = new MBeanConstructorInfo(c1a.getName(), "a constructor",
+ new MBeanParameterInfo[0]),
+ c1c = new MBeanConstructorInfo(c1a.getName(), c1a.getDescription(),
+ c1a.getSignature()),
+ c1d = new MBeanConstructorInfo(c1a.getName(), c1a.getDescription(),
+ null),
+ c2a = new MBeanConstructorInfo("another constructor", con2),
+ c2b = new MBeanConstructorInfo(c2a.getName(),
+ c2a.getDescription(),
+ c2a.getSignature()),
+ c3a = new MBeanConstructorInfo("conName", "a constructor",
+ new MBeanParameterInfo[] {p2, p3}),
+ c3b = new MBeanConstructorInfo("conName", "a constructor",
+ new MBeanParameterInfo[] {p2, p3}),
+ c4 = new MBeanConstructorInfo("conName", "a constructor",
+ new MBeanParameterInfo[] {p3, p2}),
+ c5 = new MBeanConstructorInfo("otherName", "a constructor",
+ new MBeanParameterInfo[] {p3, p2}),
+ c6 = new MBeanConstructorInfo("otherName", "another constructor",
+ new MBeanParameterInfo[] {p3, p2});
+
+ static final MBeanOperationInfo
+ o1a = new MBeanOperationInfo("an operation", run),
+ o1b = new MBeanOperationInfo("an operation", run),
+ o1c = new MBeanOperationInfo("run", "an operation",
+ o1a.getSignature(), "void",
+ o1a.getImpact()),
+ o1d = new MBeanOperationInfo("run", "an operation",
+ new MBeanParameterInfo[0], "void",
+ o1a.getImpact()),
+ o1e = new MBeanOperationInfo("run", "an operation",
+ null, "void",
+ o1a.getImpact()),
+ o2a = new MBeanOperationInfo("another operation", blah),
+ o2b = new MBeanOperationInfo(o2a.getName(), o2a.getDescription(),
+ o2a.getSignature(), o2a.getReturnType(),
+ o2a.getImpact());
+
+ static final MBeanNotificationInfo
+ n1a = new MBeanNotificationInfo(new String[] {"a.b", "c.d"},
+ "x.y.z",
+ "a notification info"),
+ n1b = new MBeanNotificationInfo(new String[] {"a.b", "c.d"},
+ "x.y.z",
+ "a notification info"),
+ n2a = new MBeanNotificationInfo(new String[] {"a.b", "c.d"},
+ "x.y.z",
+ "another notification info"),
+ n2b = new MBeanNotificationInfo(n2a.getNotifTypes(),
+ n2a.getName(),
+ n2a.getDescription()),
+ n3 = new MBeanNotificationInfo(new String[] {"a.b", "c.d"},
+ "x.y.zz",
+ "a notification info"),
+ n4 = new MBeanNotificationInfo(new String[] {"c.d", "a.b"},
+ "x.y.z",
+ "a notification info");
+
+ static final MBeanAttributeInfo[]
+ xa1a = {a1a, a2a},
+ xa1b = {a1b, a2b},
+ xa2a = {a2a, a1a};
+
+ static final MBeanConstructorInfo[]
+ xc1a = {c1a, c2a},
+ xc1b = {c1b, c2b},
+ xc2a = {c2a, c1a};
+
+ static final MBeanOperationInfo[]
+ xo1a = {o1a, o2a},
+ xo1b = {o1b, o2b},
+ xo2a = {o2a, o1a};
+
+ static final MBeanNotificationInfo[]
+ xn1a = {n1a, n2a},
+ xn1b = {n1b, n2b},
+ xn2a = {n2a, n1a};
+
+ static final MBeanInfo
+ i1a = new MBeanInfo("a.b.c", "an MBean info", xa1a, xc1a, xo1a, xn1a),
+ i1b = new MBeanInfo("a.b.c", "an MBean info", xa1a, xc1a, xo1a, xn1a),
+ i1c = new MBeanInfo("a.b.c", "an MBean info", xa1b, xc1b, xo1b, xn1b),
+ i1d = new MutableMBeanInfo("a.b.c", "an MBean info", xa1b, xc1b, xo1b,
+ xn1b),
+ i1e = new ImmutableMBeanInfo("a.b.c", "an MBean info", xa1b, xc1b,
+ xo1b, xn1b),
+ i1f = new ImmutableMBeanInfo("a.b.c", "an MBean info", xa1b, xc1b,
+ xo1b, xn1b),
+ i2a = new MBeanInfo("a.b.cc", "an MBean info", xa1a, xc1a, xo1a, xn1a),
+ i2b = new MBeanInfo(i2a.getClassName(), i2a.getDescription(),
+ i2a.getAttributes(), i2a.getConstructors(),
+ i2a.getOperations(), i2a.getNotifications()),
+ i3 = new MBeanInfo("a.b.c", "another MBean info", xa1a, xc1a, xo1a,
+ xn1a),
+ i4 = new MBeanInfo("a.b.c", "an MBean info", xa2a, xc1a, xo1a, xn1a),
+ i5 = new MBeanInfo("a.b.c", "an MBean info", xa1a, xc2a, xo1a, xn1a),
+ i6 = new MBeanInfo("a.b.c", "an MBean info", xa1a, xc1a, xo2a, xn1a),
+ i7 = new MBeanInfo("a.b.c", "an MBean info", xa1a, xc1a, xo1a, xn2a);
+
+ static final Object[][] equivalenceClasses = {
+ {a1a, a1b}, {a2a, a2b}, {a3}, {a4}, {a5a, a5b}, {a6a, a6b}, {a7a, a7b},
+ {a8a, a8b}, {a9a, a9b},
+ {c1a, c1b, c1c, c1d}, {c2a, c2b}, {c3a, c3b}, {c4}, {c5}, {c6},
+ {o1a, o1b, o1c, o1d, o1e}, {o2a, o2b},
+ {p1a, p1b}, {p2}, {p3}, {p4},
+ {n1a, n1b}, {n2a, n2b}, {n3}, {n4},
+ {i1a, i1b, i1c, i1d, i1e, i1f}, {i2a, i2b}, {i3}, {i4}, {i5}, {i6},
+ {i7},
+ };
+
+ private static class ImmutableMBeanInfo extends MBeanInfo {
+ ImmutableMBeanInfo(String className,
+ String description,
+ MBeanAttributeInfo[] attributes,
+ MBeanConstructorInfo[] constructors,
+ MBeanOperationInfo[] operations,
+ MBeanNotificationInfo[] notifications) {
+ super(className, description, attributes, constructors, operations,
+ notifications);
+ }
+ }
+
+ /* This class checks that the MBeanInfo.equals() method really
+ does call getClassName() etc rather than referring to its
+ private fields. */
+ private static class MutableMBeanInfo extends MBeanInfo {
+ private final String className;
+ private final String description;
+ private final MBeanAttributeInfo[] attributes;
+ private final MBeanOperationInfo[] operations;
+ private final MBeanConstructorInfo[] constructors;
+ private final MBeanNotificationInfo[] notifications;
+
+ MutableMBeanInfo(String className,
+ String description,
+ MBeanAttributeInfo[] attributes,
+ MBeanConstructorInfo[] constructors,
+ MBeanOperationInfo[] operations,
+ MBeanNotificationInfo[] notifications) {
+ super("bogus", null, null, null, null, null);
+ this.className = className;
+ this.description = description;
+ this.attributes = attributes;
+ this.constructors = constructors;
+ this.operations = operations;
+ this.notifications = notifications;
+ }
+
+ public String getClassName() {
+ return className;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public MBeanAttributeInfo[] getAttributes() {
+ return attributes;
+ }
+
+ public MBeanOperationInfo[] getOperations() {
+ return operations;
+ }
+
+ public MBeanConstructorInfo[] getConstructors() {
+ return constructors;
+ }
+
+ public MBeanNotificationInfo[] getNotifications() {
+ return notifications;
+ }
+ }
+
+ private static boolean checkEquals(String what, Object[][] equivs) {
+ boolean ok = true;
+ /* The equivs array is an array of equivalence classes. The members
+ of each equivalence class must be equal among themselves.
+ Each member of each equivalence class must be different from
+ each member of each other equivalence class. */
+ for (int ei = 0; ei < equivs.length; ei++) {
+ Object[] ec1 = equivs[ei];
+ ok &= checkSame(what + " equivalence class " + ei, ec1);
+ for (int ej = 0; ej < equivs.length; ej++) {
+ if (ei == ej)
+ continue;
+ Object[] ec2 = equivs[ej];
+ ok &= checkDifferent(what + " equivalence classes " +
+ ei + " and " + ej, ec1, ec2);
+ }
+ }
+ if (ok)
+ System.out.println("equals test for " + what + " passed");
+ return ok;
+ }
+
+ /* We could simplify this test to compare every element with every
+ other and choose whether they are supposed to be the same based
+ on whether they are in the same equivalence class. A bit
+ simpler, but so what. */
+
+ private static boolean checkSame(String what, Object[] equiv) {
+ boolean ok = true;
+ for (int i = 0; i < equiv.length; i++) {
+ final Object o1 = equiv[i];
+ for (int j = 0; j < equiv.length; j++) {
+ final Object o2 = equiv[j];
+ if (!o1.equals(o2)) {
+ System.out.println("equals test: " + what +
+ ": !obj[" + i +
+ "].equals(obj[" + j + "])");
+ System.out.println("..." + o1 + " " + o2);
+ ok = false;
+ }
+ if (o1.hashCode() != o2.hashCode()) {
+ System.out.println("equals test: " + what +
+ ": obj[" + i +
+ "].hashCode() != obj[" + j +
+ "].hashCode()");
+ System.out.println("..." + o1 + " " + o2);
+ ok = false;
+ }
+ }
+ }
+ return ok;
+ }
+
+ private static boolean checkDifferent(String what, Object[] equiv1,
+ Object[] equiv2) {
+ boolean ok = true;
+ for (int i = 0; i < equiv1.length; i++) {
+ final Object o1 = equiv1[i];
+ for (int j = 0; j < equiv2.length; j++) {
+ final Object o2 = equiv2[j];
+ if (o1.equals(o2)) {
+ System.out.println("equals test " + what + ": obj[" +
+ i + "].equals(obj[" + j + "])");
+ System.out.println("..." + o1 + " " + o2);
+ ok = false;
+ }
+ }
+ }
+ return ok;
+ }
+
+ public static void main(String[] args) throws Exception {
+ boolean ok = true;
+ ok &= checkEquals("equivalence", equivalenceClasses);
+ if (ok) {
+ System.out.println("all tests passed");
+ } else {
+ System.out.println("at least one test failed");
+ System.exit(1);
+ }
+ }
+}
diff --git a/test/javax/management/MBeanInfo/NotificationInfoTest.java b/test/javax/management/MBeanInfo/NotificationInfoTest.java
new file mode 100644
index 0000000..2a78e09
--- /dev/null
+++ b/test/javax/management/MBeanInfo/NotificationInfoTest.java
@@ -0,0 +1,314 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5012634
+ * @summary Test that JMX classes use fully-qualified class names
+ * in MBeanNotificationInfo
+ * @author Eamonn McManus
+ * @run clean NotificationInfoTest
+ * @run build NotificationInfoTest
+ * @run main NotificationInfoTest
+ */
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.net.*;
+import java.security.CodeSource;
+import java.util.*;
+import java.util.jar.*;
+import javax.management.*;
+import javax.management.modelmbean.*;
+import javax.management.relation.*;
+
+/*
+ * This test finds all classes in the same code-base as the JMX
+ * classes that look like Standard MBeans, and checks that if they are
+ * NotificationBroadcasters they declare existent notification types.
+ * A class looks like a Standard MBean if both Thing and ThingMBean
+ * classes exist. So for example javax.management.timer.Timer looks
+ * like a Standard MBean because javax.management.timer.TimerMBean
+ * exists. Timer is instanceof NotificationBroadcaster, so we expect
+ * that ((NotificationBroadcaster) timer).getNotificationInfo() will
+ * return an array of MBeanNotificationInfo where each entry has a
+ * getName() that names an existent Java class that is a Notification.
+ *
+ * An MBean is "suspicious" if it is a NotificationBroadcaster but its
+ * MBeanNotificationInfo[] is empty. This is legal, but surprising.
+ *
+ * In order to call getNotificationInfo(), we need an instance of the
+ * class. We attempt to make one by calling a public no-arg
+ * constructor. But the "construct" method below can be extended to
+ * construct specific MBean classes for which the no-arg constructor
+ * doesn't exist.
+ *
+ * The test is obviously not exhaustive, but does catch the cases that
+ * failed in 5012634.
+ */
+public class NotificationInfoTest {
+ // class or object names where the test failed
+ private static final Set/*<String>*/ failed = new TreeSet();
+
+ // class or object names where there were no MBeanNotificationInfo entries
+ private static final Set/*<String>*/ suspicious = new TreeSet();
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("Checking that all known MBeans that are " +
+ "NotificationBroadcasters have sane " +
+ "MBeanInfo.getNotifications()");
+
+ System.out.println("Checking platform MBeans...");
+ checkPlatformMBeans();
+
+ CodeSource cs =
+ javax.management.MBeanServer.class.getProtectionDomain()
+ .getCodeSource();
+ URL codeBase;
+ if (cs == null) {
+ codeBase = new URL("file:" + System.getProperty("java.home") +
+ "/lib/rt.jar");
+ } else
+ codeBase = cs.getLocation();
+
+ System.out.println();
+ System.out.println("Looking for standard MBeans...");
+ String[] classes = findStandardMBeans(codeBase);
+
+ System.out.println("Testing standard MBeans...");
+ for (int i = 0; i < classes.length; i++) {
+ String name = classes[i];
+ Class c;
+ try {
+ c = Class.forName(name);
+ } catch (Throwable e) {
+ System.out.println(name + ": cannot load (not public?): " + e);
+ continue;
+ }
+ if (!NotificationBroadcaster.class.isAssignableFrom(c)) {
+ System.out.println(name + ": not a NotificationBroadcaster");
+ continue;
+ }
+
+ NotificationBroadcaster mbean;
+ Constructor constr;
+ try {
+ constr = c.getConstructor(null);
+ } catch (Exception e) {
+ System.out.println(name + ": no public no-arg constructor: "
+ + e);
+ continue;
+ }
+ try {
+ mbean = (NotificationBroadcaster) constr.newInstance(null);
+ } catch (Exception e) {
+ System.out.println(name + ": no-arg constructor failed: " + e);
+ continue;
+ }
+
+ check(mbean);
+ }
+
+ System.out.println();
+ System.out.println("Testing some explicit cases...");
+
+ check(new RelationService(false));
+ /*
+ We can't do this:
+ check(new RequiredModelMBean());
+ because the Model MBean spec more or less forces us to use the
+ names GENERIC and ATTRIBUTE_CHANGE for its standard notifs.
+ */
+ checkRMIConnectorServer();
+
+ System.out.println();
+ if (!suspicious.isEmpty())
+ System.out.println("SUSPICIOUS CLASSES: " + suspicious);
+
+ if (failed.isEmpty())
+ System.out.println("TEST PASSED");
+ else {
+ System.out.println("TEST FAILED: " + failed);
+ System.exit(1);
+ }
+ }
+
+ private static void check(NotificationBroadcaster mbean)
+ throws Exception {
+ System.out.print(mbean.getClass().getName() + ": ");
+
+ check(mbean.getClass().getName(), mbean.getNotificationInfo());
+ }
+
+ private static void checkPlatformMBeans() throws Exception {
+ Class managementFactory;
+ try {
+ managementFactory =
+ Class.forName("java.lang.management.ManagementFactory");
+ } catch (Exception e) {
+ System.out.println("...no ManagementFactory, assuming pre-Tiger: "
+ + e);
+ return;
+ }
+ Method getPlatformMBeanServer =
+ managementFactory.getMethod("getPlatformMBeanServer", null);
+ MBeanServer mbs = (MBeanServer)
+ getPlatformMBeanServer.invoke(null, null);
+ Set mbeanNames = mbs.queryNames(null, null);
+ for (Iterator it = mbeanNames.iterator(); it.hasNext(); ) {
+ ObjectName name = (ObjectName) it.next();
+ if (!mbs.isInstanceOf(name,
+ NotificationBroadcaster.class.getName())) {
+ System.out.println(name + ": not a NotificationBroadcaster");
+ } else {
+ MBeanInfo mbi = mbs.getMBeanInfo(name);
+ check(name.toString(), mbi.getNotifications());
+ }
+ }
+ }
+
+ private static void checkRMIConnectorServer() throws Exception {
+ Class rmiConnectorServer;
+ try {
+ rmiConnectorServer =
+ Class.forName("javax.management.remote.rmi.RMIConnectorServer");
+ } catch (Exception e) {
+ System.out.println("No RMIConnectorServer class, skipping: " + e);
+ return;
+ }
+ Class jmxServiceURL =
+ Class.forName("javax.management.remote.JMXServiceURL");
+ Constructor jmxServiceURLConstructor =
+ jmxServiceURL.getConstructor(new Class[] {String.class});
+ Object url =
+ jmxServiceURLConstructor.newInstance(new Object[] {
+ "service:jmx:rmi://"
+ });
+ Constructor rmiConnectorServerConstructor =
+ rmiConnectorServer.getConstructor(new Class[] {
+ jmxServiceURL, Map.class
+ });
+ Object connector =
+ rmiConnectorServerConstructor.newInstance(new Object[] {
+ url, null
+ });
+ check((NotificationBroadcaster) connector);
+ }
+
+ private static void check(String what, MBeanNotificationInfo[] mbnis) {
+ System.out.print(what + ": checking notification info: ");
+
+ if (mbnis.length == 0) {
+ System.out.println("NONE (suspicious)");
+ suspicious.add(what);
+ return;
+ }
+
+ // Each MBeanNotificationInfo.getName() should be an existent
+ // Java class that is Notification or a subclass of it
+ for (int j = 0; j < mbnis.length; j++) {
+ String notifClassName = mbnis[j].getName();
+ Class notifClass;
+ try {
+ notifClass = Class.forName(notifClassName);
+ } catch (Exception e) {
+ System.out.print("FAILED(" + notifClassName + ": " + e +
+ ") ");
+ failed.add(what);
+ continue;
+ }
+ if (!Notification.class.isAssignableFrom(notifClass)) {
+ System.out.print("FAILED(" + notifClassName +
+ ": not a Notification) ");
+ failed.add(what);
+ continue;
+ }
+ System.out.print("OK(" + notifClassName + ") ");
+ }
+ System.out.println();
+ }
+
+ private static String[] findStandardMBeans(URL codeBase)
+ throws Exception {
+ Set names;
+ if (codeBase.getProtocol().equalsIgnoreCase("file")
+ && codeBase.toString().endsWith("/"))
+ names = findStandardMBeansFromDir(codeBase);
+ else
+ names = findStandardMBeansFromJar(codeBase);
+
+ Set standardMBeanNames = new TreeSet();
+ for (Iterator it = names.iterator(); it.hasNext(); ) {
+ String name = (String) it.next();
+ if (name.endsWith("MBean")) {
+ String prefix = name.substring(0, name.length() - 5);
+ if (names.contains(prefix))
+ standardMBeanNames.add(prefix);
+ }
+ }
+ return (String[]) standardMBeanNames.toArray(new String[0]);
+ }
+
+ private static Set findStandardMBeansFromJar(URL codeBase)
+ throws Exception {
+ InputStream is = codeBase.openStream();
+ JarInputStream jis = new JarInputStream(is);
+ Set names = new TreeSet();
+ JarEntry entry;
+ while ((entry = jis.getNextJarEntry()) != null) {
+ String name = entry.getName();
+ if (!name.endsWith(".class"))
+ continue;
+ name = name.substring(0, name.length() - 6);
+ name = name.replace('/', '.');
+ names.add(name);
+ }
+ return names;
+ }
+
+ private static Set findStandardMBeansFromDir(URL codeBase)
+ throws Exception {
+ File dir = new File(new URI(codeBase.toString()));
+ Set names = new TreeSet();
+ scanDir(dir, "", names);
+ return names;
+ }
+
+ private static void scanDir(File dir, String prefix, Set names)
+ throws Exception {
+ File[] files = dir.listFiles();
+ if (files == null)
+ return;
+ for (int i = 0; i < files.length; i++) {
+ File f = files[i];
+ String name = f.getName();
+ String p = (prefix.equals("")) ? name : prefix + "." + name;
+ if (f.isDirectory())
+ scanDir(f, p, names);
+ else if (name.endsWith(".class")) {
+ p = p.substring(0, p.length() - 6);
+ names.add(p);
+ }
+ }
+ }
+}
diff --git a/test/javax/management/MBeanInfo/NullInfoArraysTest.java b/test/javax/management/MBeanInfo/NullInfoArraysTest.java
new file mode 100644
index 0000000..db02d49
--- /dev/null
+++ b/test/javax/management/MBeanInfo/NullInfoArraysTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5056248
+ * @summary Test that an MBeanInfo works even if it is deserialized from
+ * an implementation where its array fields can be null.
+ * @author Eamonn McManus
+ * @run clean NullInfoArraysTest
+ * @run build NullInfoArraysTest
+ * @run main NullInfoArraysTest
+ */
+
+import java.io.*;
+import javax.management.*;
+import javax.management.modelmbean.*;
+import javax.management.openmbean.*;
+
+public class NullInfoArraysTest {
+ public static void main(String[] args) throws Exception {
+ if (args.length > 0 && args[0].equals("write"))
+ writeSerializedForms();
+ else
+ testSerializedForms();
+ }
+
+ private static void testSerializedForms() throws Exception {
+ byte[][] serializedMBeanInfos =
+ SerializedMBeanInfo.serializedMBeanInfos;
+ for (int i = 0; i < serializedMBeanInfos.length; i++) {
+ byte[] serializedMBeanInfo = serializedMBeanInfos[i];
+ ByteArrayInputStream bis =
+ new ByteArrayInputStream(serializedMBeanInfo);
+ ObjectInputStream ois = new ObjectInputStream(bis);
+ MBeanInfo mbi = (MBeanInfo) ois.readObject();
+
+ System.out.println("Testing a " +
+ mbi.getClass().getName() + "...");
+
+ if (mbi.getAttributes() == null ||
+ mbi.getOperations() == null ||
+ mbi.getConstructors() == null ||
+ mbi.getNotifications() == null)
+ throw new Exception("At least one getter returned null");
+
+ System.out.println("OK");
+ }
+
+ System.out.println("Test passed");
+ }
+
+ /* This method is intended to be invoked when constructing the
+ test for the first time, with JMX 1.1 RI in the classpath. It
+ constructs the SerializedMBeanInfo.java source file. There is
+ of course a chicken-and-egg problem for compiling: the first
+ time we built this test, we supplied a trivial
+ SerializedMBeanInfo.java with an empty array in the
+ serializedMBeanInfos field. */
+ private static void writeSerializedForms() throws Exception {
+ OutputStream fos = new FileOutputStream("SerializedMBeanInfo.java");
+ PrintWriter w = new PrintWriter(fos);
+ w.println("// Generated by NullInfoArraysTest - do not edit");
+ w.println();
+ w.println("public class SerializedMBeanInfo {");
+ w.println(" public static final byte[][] serializedMBeanInfos = {");
+ writeSerial(w, new MBeanInfo(null, null, null, null, null, null));
+ writeSerial(w, new ModelMBeanInfoSupport(null, null, null, null, null,
+ null, null));
+ writeSerial(w, new OpenMBeanInfoSupport(null, null, null, null, null,
+ null));
+ w.println(" };");
+ w.println("}");
+ w.close();
+ fos.close();
+ System.out.println("Wrote SerializedMBeanInfo.java");
+ }
+
+ private static void writeSerial(PrintWriter w, Object o) throws Exception {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(bos);
+ oos.writeObject(o);
+ oos.close();
+ byte[] bytes = bos.toByteArray();
+ w.print(" {");
+ for (int i = 0; i < bytes.length; i++) {
+ w.print(bytes[i]);
+ w.print(", ");
+ }
+ w.println("},");
+ }
+}
diff --git a/test/javax/management/MBeanInfo/SerializationTest.java b/test/javax/management/MBeanInfo/SerializationTest.java
new file mode 100644
index 0000000..bb6fb33
--- /dev/null
+++ b/test/javax/management/MBeanInfo/SerializationTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6288100
+ * @summary Test the new serialization/deserialization methods.
+ * @author Shanliang JIANG
+ * @run clean SerializationTest
+ * @run build SerializationTest
+ * @run main SerializationTest
+ */
+
+import java.io.*;
+import javax.management.*;
+
+public class SerializationTest {
+ public static void main(String[] args) throws Exception {
+ MBeanFeatureInfo mfi1 = new MBeanFeatureInfo("", "", null);
+ test(mfi1);
+
+ MBeanFeatureInfo mfi2 = new MBeanFeatureInfo("",
+ "",
+ ImmutableDescriptor.EMPTY_DESCRIPTOR);
+ test(mfi2);
+
+ MBeanFeatureInfo mfi3 = new MBeanFeatureInfo("", "",
+ new ImmutableDescriptor(new String[] {"hi"},
+ new Object[] {"ha"}));
+ test(mfi3);
+
+ MBeanInfo mi1 = new MBeanInfo("",
+ "",
+ new MBeanAttributeInfo[]{},
+ new MBeanConstructorInfo[]{},
+ new MBeanOperationInfo[]{},
+ new MBeanNotificationInfo[]{},
+ null);
+
+
+ test(mi1);
+
+ MBeanInfo mi2 = new MBeanInfo("",
+ "",
+ new MBeanAttributeInfo[]{},
+ new MBeanConstructorInfo[]{},
+ new MBeanOperationInfo[]{},
+ new MBeanNotificationInfo[]{},
+ ImmutableDescriptor.EMPTY_DESCRIPTOR);
+
+
+ test(mi2);
+
+ MBeanInfo mi3 = new MBeanInfo("",
+ "",
+ new MBeanAttributeInfo[]{},
+ new MBeanConstructorInfo[]{},
+ new MBeanOperationInfo[]{},
+ new MBeanNotificationInfo[]{},
+ new ImmutableDescriptor(new String[] {"hi"},
+ new Object[] {"ha"}));
+
+
+ test(mi3);
+
+
+ }
+
+ public static void test(Object obj) throws Exception {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(obj);
+
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ObjectInputStream ois = new ObjectInputStream(bais);
+ Object newObj = ois.readObject();
+
+ if (!obj.equals(newObj)) {
+ throw new RuntimeException("Serialization/deserialization failed.");
+ }
+ }
+}
diff --git a/test/javax/management/MBeanInfo/SerializedMBeanInfo.java b/test/javax/management/MBeanInfo/SerializedMBeanInfo.java
new file mode 100644
index 0000000..e6fd262
--- /dev/null
+++ b/test/javax/management/MBeanInfo/SerializedMBeanInfo.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+// Generated by NullInfoArraysTest - do not edit
+
+public class SerializedMBeanInfo {
+ public static final byte[][] serializedMBeanInfos = {
+ {-84, -19, 0, 5, 115, 114, 0, 26, 106, 97, 118, 97, 120, 46, 109, 97, 110, 97, 103, 101, 109, 101, 110, 116, 46, 77, 66, 101, 97, 110, 73, 110, 102, 111, -90, 121, 94, 47, 8, 86, -119, -55, 2, 0, 6, 91, 0, 10, 97, 116, 116, 114, 105, 98, 117, 116, 101, 115, 116, 0, 38, 91, 76, 106, 97, 118, 97, 120, 47, 109, 97, 110, 97, 103, 101, 109, 101, 110, 116, 47, 77, 66, 101, 97, 110, 65, 116, 116, 114, 105, 98, 117, 116, 101, 73, 110, 102, 111, 59, 76, 0, 9, 99, 108, 97, 115, 115, 78, 97, 109, 101, 116, 0, 18, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 91, 0, 12, 99, 111, 110, 115, 116, 114, 117, 99, 116, 111, 114, 115, 116, 0, 40, 91, 76, 106, 97, 118, 97, 120, 47, 109, 97, 110, 97, 103, 101, 109, 101, 110, 116, 47, 77, 66, 101, 97, 110, 67, 111, 110, 115, 116, 114, 117, 99, 116, 111, 114, 73, 110, 102, 111, 59, 76, 0, 11, 100, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 113, 0, 126, 0, 2, 91, 0, 13, 110, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 115, 116, 0, 41, 91, 76, 106, 97, 118, 97, 120, 47, 109, 97, 110, 97, 103, 101, 109, 101, 110, 116, 47, 77, 66, 101, 97, 110, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 73, 110, 102, 111, 59, 91, 0, 10, 111, 112, 101, 114, 97, 116, 105, 111, 110, 115, 116, 0, 38, 91, 76, 106, 97, 118, 97, 120, 47, 109, 97, 110, 97, 103, 101, 109, 101, 110, 116, 47, 77, 66, 101, 97, 110, 79, 112, 101, 114, 97, 116, 105, 111, 110, 73, 110, 102, 111, 59, 120, 112, 112, 112, 112, 112, 112, 112, },
+ {-84, -19, 0, 5, 115, 114, 0, 49, 106, 97, 118, 97, 120, 46, 109, 97, 110, 97, 103, 101, 109, 101, 110, 116, 46, 109, 111, 100, 101, 108, 109, 98, 101, 97, 110, 46, 77, 111, 100, 101, 108, 77, 66, 101, 97, 110, 73, 110, 102, 111, 83, 117, 112, 112, 111, 114, 116, -27, 34, -18, -113, 66, 66, 78, -97, 3, 0, 5, 91, 0, 20, 109, 111, 100, 101, 108, 77, 66, 101, 97, 110, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 116, 0, 38, 91, 76, 106, 97, 118, 97, 120, 47, 109, 97, 110, 97, 103, 101, 109, 101, 110, 116, 47, 77, 66, 101, 97, 110, 65, 116, 116, 114, 105, 98, 117, 116, 101, 73, 110, 102, 111, 59, 91, 0, 22, 109, 111, 100, 101, 108, 77, 66, 101, 97, 110, 67, 111, 110, 115, 116, 114, 117, 99, 116, 111, 114, 115, 116, 0, 40, 91, 76, 106, 97, 118, 97, 120, 47, 109, 97, 110, 97, 103, 101, 109, 101, 110, 116, 47, 77, 66, 101, 97, 110, 67, 111, 110, 115, 116, 114, 117, 99, 116, 111, 114, 73, 110, 102, 111, 59, 76, 0, 20, 109, 111, 100, 101, 108, 77, 66, 101, 97, 110, 68, 101, 115, 99, 114, 105, 112, 116, 111, 114, 116, 0, 29, 76, 106, 97, 118, 97, 120, 47, 109, 97, 110, 97, 103, 101, 109, 101, 110, 116, 47, 68, 101, 115, 99, 114, 105, 112, 116, 111, 114, 59, 91, 0, 23, 109, 111, 100, 101, 108, 77, 66, 101, 97, 110, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 115, 116, 0, 41, 91, 76, 106, 97, 118, 97, 120, 47, 109, 97, 110, 97, 103, 101, 109, 101, 110, 116, 47, 77, 66, 101, 97, 110, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 73, 110, 102, 111, 59, 91, 0, 20, 109, 111, 100, 101, 108, 77, 66, 101, 97, 110, 79, 112, 101, 114, 97, 116, 105, 111, 110, 115, 116, 0, 38, 91, 76, 106, 97, 118, 97, 120, 47, 109, 97, 110, 97, 103, 101, 109, 101, 110, 116, 47, 77, 66, 101, 97, 110, 79, 112, 101, 114, 97, 116, 105, 111, 110, 73, 110, 102, 111, 59, 120, 114, 0, 26, 106, 97, 118, 97, 120, 46, 109, 97, 110, 97, 103, 101, 109, 101, 110, 116, 46, 77, 66, 101, 97, 110, 73, 110, 102, 111, -90, 121, 94, 47, 8, 86, -119, -55, 2, 0, 6, 91, 0, 10, 97, 116, 116, 114, 105, 98, 117, 116, 101, 115, 113, 0, 126, 0, 1, 76, 0, 9, 99, 108, 97, 115, 115, 78, 97, 109, 101, 116, 0, 18, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 91, 0, 12, 99, 111, 110, 115, 116, 114, 117, 99, 116, 111, 114, 115, 113, 0, 126, 0, 2, 76, 0, 11, 100, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 113, 0, 126, 0, 7, 91, 0, 13, 110, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 115, 113, 0, 126, 0, 4, 91, 0, 10, 111, 112, 101, 114, 97, 116, 105, 111, 110, 115, 113, 0, 126, 0, 5, 120, 112, 112, 112, 112, 112, 112, 112, 112, 112, 115, 114, 0, 45, 106, 97, 118, 97, 120, 46, 109, 97, 110, 97, 103, 101, 109, 101, 110, 116, 46, 109, 111, 100, 101, 108, 109, 98, 101, 97, 110, 46, 68, 101, 115, 99, 114, 105, 112, 116, 111, 114, 83, 117, 112, 112, 111, 114, 116, -88, -86, -31, -37, -95, -23, -32, 1, 3, 0, 1, 76, 0, 10, 100, 101, 115, 99, 114, 105, 112, 116, 111, 114, 116, 0, 19, 76, 106, 97, 118, 97, 47, 117, 116, 105, 108, 47, 72, 97, 115, 104, 77, 97, 112, 59, 120, 112, 115, 114, 0, 17, 106, 97, 118, 97, 46, 117, 116, 105, 108, 46, 72, 97, 115, 104, 77, 97, 112, 5, 7, -38, -63, -61, 22, 96, -47, 3, 0, 2, 70, 0, 10, 108, 111, 97, 100, 70, 97, 99, 116, 111, 114, 73, 0, 9, 116, 104, 114, 101, 115, 104, 111, 108, 100, 120, 112, 63, 64, 0, 0, 0, 0, 0, 12, 119, 8, 0, 0, 0, 16, 0, 0, 0, 7, 116, 0, 6, 101, 120, 112, 111, 114, 116, 116, 0, 1, 70, 116, 0, 3, 108, 111, 103, 116, 0, 1, 70, 116, 0, 10, 118, 105, 115, 105, 98, 105, 108, 105, 116, 121, 116, 0, 1, 49, 116, 0, 14, 100, 101, 115, 99, 114, 105, 112, 116, 111, 114, 116, 121, 112, 101, 116, 0, 5, 109, 98, 101, 97, 110, 116, 0, 4, 110, 97, 109, 101, 116, 0, 4, 110, 117, 108, 108, 116, 0, 11, 100, 105, 115, 112, 108, 97, 121, 110, 97, 109, 101, 116, 0, 4, 110, 117, 108, 108, 116, 0, 13, 112, 101, 114, 115, 105, 115, 116, 112, 111, 108, 105, 99, 121, 116, 0, 5, 110, 101, 118, 101, 114, 120, 120, 112, 112, 120, },
+ {-84, -19, 0, 5, 115, 114, 0, 47, 106, 97, 118, 97, 120, 46, 109, 97, 110, 97, 103, 101, 109, 101, 110, 116, 46, 111, 112, 101, 110, 109, 98, 101, 97, 110, 46, 79, 112, 101, 110, 77, 66, 101, 97, 110, 73, 110, 102, 111, 83, 117, 112, 112, 111, 114, 116, 60, 92, 40, -113, 38, 68, 117, 4, 2, 0, 0, 120, 114, 0, 26, 106, 97, 118, 97, 120, 46, 109, 97, 110, 97, 103, 101, 109, 101, 110, 116, 46, 77, 66, 101, 97, 110, 73, 110, 102, 111, -90, 121, 94, 47, 8, 86, -119, -55, 2, 0, 6, 91, 0, 10, 97, 116, 116, 114, 105, 98, 117, 116, 101, 115, 116, 0, 38, 91, 76, 106, 97, 118, 97, 120, 47, 109, 97, 110, 97, 103, 101, 109, 101, 110, 116, 47, 77, 66, 101, 97, 110, 65, 116, 116, 114, 105, 98, 117, 116, 101, 73, 110, 102, 111, 59, 76, 0, 9, 99, 108, 97, 115, 115, 78, 97, 109, 101, 116, 0, 18, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 91, 0, 12, 99, 111, 110, 115, 116, 114, 117, 99, 116, 111, 114, 115, 116, 0, 40, 91, 76, 106, 97, 118, 97, 120, 47, 109, 97, 110, 97, 103, 101, 109, 101, 110, 116, 47, 77, 66, 101, 97, 110, 67, 111, 110, 115, 116, 114, 117, 99, 116, 111, 114, 73, 110, 102, 111, 59, 76, 0, 11, 100, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 113, 0, 126, 0, 3, 91, 0, 13, 110, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 115, 116, 0, 41, 91, 76, 106, 97, 118, 97, 120, 47, 109, 97, 110, 97, 103, 101, 109, 101, 110, 116, 47, 77, 66, 101, 97, 110, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 73, 110, 102, 111, 59, 91, 0, 10, 111, 112, 101, 114, 97, 116, 105, 111, 110, 115, 116, 0, 38, 91, 76, 106, 97, 118, 97, 120, 47, 109, 97, 110, 97, 103, 101, 109, 101, 110, 116, 47, 77, 66, 101, 97, 110, 79, 112, 101, 114, 97, 116, 105, 111, 110, 73, 110, 102, 111, 59, 120, 112, 112, 112, 112, 112, 112, 112, },
+ };
+}
diff --git a/test/javax/management/MBeanInfo/TooManyFooTest.java b/test/javax/management/MBeanInfo/TooManyFooTest.java
new file mode 100644
index 0000000..753a385
--- /dev/null
+++ b/test/javax/management/MBeanInfo/TooManyFooTest.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6398884
+ * @summary Test that a method inherited from two different interfaces
+ * appears only once in MBeanInfo.
+ * @author dfuchs
+ * @run clean TooManyFooTest
+ * @run build TooManyFooTest
+ * @run main TooManyFooTest
+ */
+
+import java.lang.management.ManagementFactory;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Logger;
+import javax.management.Descriptor;
+import javax.management.MBeanInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.StandardMBean;
+import javax.management.openmbean.OpenMBeanOperationInfo;
+
+/**
+ * Class TooManyFooTest
+ * @author Sun Microsystems, 2005 - All rights reserved.
+ */
+public class TooManyFooTest {
+
+ /**
+ * A logger for this class.
+ **/
+ private static final Logger LOG =
+ Logger.getLogger(TooManyFooTest.class.getName());
+
+ public static class NumberHolder {
+ public Integer getNumber() { return 0;}
+ public void setNumber(Integer n) {};
+ }
+ public static class MyNumberHolder extends NumberHolder {
+
+ }
+ public interface Parent1 {
+ public int foo(); // Both in Parent1 and Parent2
+ public Integer barfoo(); // Subtype in Parent1, Super type in Parent2
+ public Long foobar(); // Subtype in Parent1 & MBean, Super type in
+ // Parent2
+ public Number toofoo(); // Subtype in Parent1, Super type in Parent2
+ // Concrete type in MBean
+ public Object toofoofoo(); // Super type in Parent1, Subtype in Parent2,
+ public NumberHolder toobarbar(); // toofoofoo reversed
+ }
+
+ public interface Parent2 {
+ public int foo(); // Both in Parent1 and Parent2
+ public Number barfoo();
+ public Number foobar();
+ public Object toofoo();
+ public NumberHolder toofoofoo();
+ public Object toobarbar();
+ }
+
+ public interface ChildMBean extends Parent1, Parent2 {
+ public Long foobar();
+ public Long toofoo();
+ }
+
+ public interface ChildMXBean extends Parent1, Parent2 {
+ public Long foobar();
+ public Long toofoo();
+ }
+
+ public interface ChildMixMXBean extends ChildMBean, ChildMXBean {
+ }
+
+ public static class Child implements ChildMBean {
+ public int foo() {return 0;}
+ public Long foobar() {return 0L;}
+ public Long toofoo() {return 0L;}
+ public Integer barfoo() {return 0;}
+ public MyNumberHolder toofoofoo() { return null;}
+ public MyNumberHolder toobarbar() { return null;}
+ }
+
+ public static class ChildMix implements ChildMXBean {
+ public int foo() {return 0;}
+ public Long foobar() {return 0L;}
+ public Long toofoo() {return 0L;}
+ public Integer barfoo() {return 0;}
+ public MyNumberHolder toofoofoo() { return null;}
+ public MyNumberHolder toobarbar() { return null;}
+ }
+
+ public static class ChildMixMix extends Child implements ChildMixMXBean {
+ }
+
+
+ /** Creates a new instance of TooManyFooTest */
+ public TooManyFooTest() {
+ }
+
+ private static final int OPCOUNT;
+ private static final Map<String,String> EXPECTED_TYPES;
+ private static final String[][] type_array = {
+ { "foo", int.class.getName() },
+ { "foobar", Long.class.getName()},
+ { "toofoo", Long.class.getName()},
+ { "barfoo", Integer.class.getName()},
+ { "toofoofoo", NumberHolder.class.getName()},
+ { "toobarbar", NumberHolder.class.getName()},
+ };
+ static {
+ try {
+ final Set<String> declared = new HashSet<String>();
+ for (Method m:Child.class.getDeclaredMethods()) {
+ declared.add(m.getName()+Arrays.asList(m.getParameterTypes()));
+ }
+ final Set<String> exposed = new HashSet<String>();
+ for (Method m:ChildMBean.class.getMethods()) {
+ exposed.add(m.getName()+Arrays.asList(m.getParameterTypes()));
+ }
+ declared.retainAll(exposed);
+ OPCOUNT = declared.size();
+ EXPECTED_TYPES = new HashMap<String,String>();
+ for (String[] st:type_array) {
+ EXPECTED_TYPES.put(st[0],st[1]);
+ }
+ } catch (Exception x) {
+ throw new ExceptionInInitializerError(x);
+ }
+ }
+
+ private static void test(Object child, String name, boolean mxbean)
+ throws Exception {
+ final ObjectName childName =
+ new ObjectName("test:type=Child,name="+name);
+ final MBeanServer server =
+ ManagementFactory.getPlatformMBeanServer();
+ server.registerMBean(child,childName);
+ try {
+ final MBeanInfo info = server.getMBeanInfo(childName);
+ System.out.println(name+": " + info.getDescriptor());
+ final int len = info.getOperations().length;
+ if (len == OPCOUNT) {
+ System.out.println(name+": OK, only "+OPCOUNT+
+ " operations here...");
+ } else {
+ final String qual = (len>OPCOUNT)?"many":"few";
+ System.err.println(name+": Too "+qual+" foos! Found "+
+ len+", expected "+OPCOUNT);
+ for (MBeanOperationInfo op : info.getOperations()) {
+ System.err.println("public "+op.getReturnType()+" "+
+ op.getName()+"();");
+ }
+ throw new RuntimeException("Too " + qual +
+ " foos for "+name);
+ }
+
+ final Descriptor d = info.getDescriptor();
+ final String mxstr = String.valueOf(d.getFieldValue("mxbean"));
+ final boolean mxb =
+ (mxstr==null)?false:Boolean.valueOf(mxstr).booleanValue();
+ System.out.println(name+": mxbean="+mxb);
+ if (mxbean && !mxb)
+ throw new AssertionError("MXBean is not OpenMBean?");
+
+ for (MBeanOperationInfo mboi : info.getOperations()) {
+
+ // Sanity check
+ if (mxbean && !mboi.getName().equals("foo")) {
+ // The spec doesn't guarantee that the MBeanOperationInfo
+ // of an MXBean will be an OpenMBeanOperationInfo, and in
+ // some circumstances in our implementation it will not.
+ // However, in thsi tests, for all methods but foo(),
+ // it should.
+ //
+ if (!(mboi instanceof OpenMBeanOperationInfo))
+ throw new AssertionError("Operation "+mboi.getName()+
+ "() is not Open?");
+ }
+
+ final String exp = EXPECTED_TYPES.get(mboi.getName());
+
+ // For MXBeans, we need to compare 'exp' with the original
+ // type - because mboi.getReturnType() returns the OpenType
+ //
+ String type = (String)mboi.getDescriptor().
+ getFieldValue("originalType");
+ if (type == null) type = mboi.getReturnType();
+ if (type.equals(exp)) continue;
+ System.err.println("Bad return type for "+
+ mboi.getName()+"! Found "+type+
+ ", expected "+exp);
+ throw new RuntimeException("Bad return type for "+
+ mboi.getName());
+ }
+ } finally {
+ server.unregisterMBean(childName);
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ final Child child = new Child();
+ test(child,"Child[MBean]",false);
+ final ChildMix childx = new ChildMix();
+ test(childx,"ChildMix[MXBean]",true);
+ final ChildMixMix childmx = new ChildMixMix();
+ test(childmx,"ChildMixMix[MXBean]",false);
+ final StandardMBean schild = new StandardMBean(child,ChildMBean.class);
+ test(schild,"Child[StandarMBean(Child)]",false);
+ final StandardMBean schildx =
+ new StandardMBean(childx,ChildMXBean.class,true);
+ test(schildx,"ChildMix[StandarMXBean(ChildMix)]",true);
+ final StandardMBean schildmx =
+ new StandardMBean(childmx,ChildMixMXBean.class,true);
+ test(schildmx,"ChildMixMix[StandarMXBean(ChildMixMix)]",true);
+ }
+
+}
diff --git a/test/javax/management/MBeanServer/MBeanExceptionTest.java b/test/javax/management/MBeanServer/MBeanExceptionTest.java
new file mode 100644
index 0000000..25260e0
--- /dev/null
+++ b/test/javax/management/MBeanServer/MBeanExceptionTest.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5035217
+ * @summary Test that MBean's RuntimeException is wrapped in
+ * RuntimeMBeanException and (for Standard MBeans) that checked exceptions
+ * are wrapped in MBeanException
+ * @author Eamonn McManus
+ * @compile -source 1.4 MBeanExceptionTest.java
+ * @run main MBeanExceptionTest
+ */
+
+import javax.management.*;
+
+public class MBeanExceptionTest {
+ public static void main(String[] args) throws Exception {
+ System.out.println("Test that if an MBean throws RuntimeException " +
+ "it is wrapped in RuntimeMBeanException,");
+ System.out.println("and if a Standard MBean throws Exception " +
+ "it is wrapped in MBeanException");
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ Object standard = new Except();
+ ObjectName standardName = new ObjectName(":name=Standard MBean");
+ Object standardMBean =
+ new StandardMBean(new Except(), ExceptMBean.class);
+ ObjectName standardMBeanName =
+ new ObjectName(":name=Instance of StandardMBean");
+ Object dynamic = new DynamicExcept();
+ ObjectName dynamicName = new ObjectName(":name=Dynamic MBean");
+ mbs.registerMBean(standard, standardName);
+ mbs.registerMBean(standardMBean, standardMBeanName);
+ mbs.registerMBean(dynamic, dynamicName);
+ int failures = 0;
+ failures += test(mbs, standardName, true);
+ failures += test(mbs, standardMBeanName, true);
+ failures += test(mbs, dynamicName, false);
+ if (failures == 0)
+ System.out.println("Test passed");
+ else {
+ System.out.println("TEST FAILED: " + failures + " failure(s)");
+ System.exit(1);
+ }
+ }
+
+ private static int test(MBeanServer mbs, ObjectName name,
+ boolean testChecked)
+ throws Exception {
+ System.out.println("--------" + name + "--------");
+
+ int failures = 0;
+ final String[] ops = {"getAttribute", "setAttribute", "invoke"};
+ final int GET = 0, SET = 1, INVOKE = 2;
+ final String[] targets = {"UncheckedException", "CheckedException"};
+ final int UNCHECKED = 0, CHECKED = 1;
+
+ for (int i = 0; i < ops.length; i++) {
+ for (int j = 0; j < targets.length; j++) {
+
+ if (j == CHECKED && !testChecked)
+ continue;
+
+ String target = targets[j];
+ String what = ops[i] + "/" + target;
+ System.out.println(what);
+
+ try {
+ switch (i) {
+ case GET:
+ mbs.getAttribute(name, target);
+ break;
+ case SET:
+ mbs.setAttribute(name, new Attribute(target, "x"));
+ break;
+ case INVOKE:
+ mbs.invoke(name, target, null, null);
+ break;
+ default:
+ throw new AssertionError();
+ }
+ System.out.println("failure: " + what + " returned!");
+ failures++;
+ } catch (RuntimeMBeanException e) {
+ if (j == CHECKED) {
+ System.out.println("failure: RuntimeMBeanException " +
+ "when checked expected: " + e);
+ failures++;
+ } else {
+ Throwable cause = e.getCause();
+ if (cause == theUncheckedException)
+ System.out.println("ok: " + what);
+ else {
+ System.out.println("failure: " + what +
+ " wrapped " + cause);
+ failures++;
+ }
+ }
+ } catch (MBeanException e) {
+ if (j == UNCHECKED) {
+ System.out.println("failure: checked exception " +
+ "when unchecked expected: " + e);
+ failures++;
+ } else {
+ Throwable cause = e.getCause();
+ if (cause == theCheckedException)
+ System.out.println("ok: " + what);
+ else {
+ System.out.println("failure: " + what +
+ " wrapped " + cause);
+ failures++;
+ }
+ }
+ } catch (Throwable t) {
+ System.out.println("failure: " + what + " threw: " + t);
+ while ((t = t.getCause()) != null)
+ System.out.println(" ... " + t);
+ failures++;
+ }
+ }
+ }
+
+ return failures;
+ }
+
+ public static interface ExceptMBean {
+ public String getUncheckedException();
+ public void setUncheckedException(String x);
+ public void UncheckedException();
+ public String getCheckedException() throws Exception;
+ public void setCheckedException(String x) throws Exception;
+ public void CheckedException() throws Exception;
+ }
+
+ public static class Except implements ExceptMBean {
+ public String getUncheckedException() {
+ throw theUncheckedException;
+ }
+ public void setUncheckedException(String x) {
+ throw theUncheckedException;
+ }
+ public void UncheckedException() {
+ throw theUncheckedException;
+ }
+ public String getCheckedException() throws Exception {
+ throw theCheckedException;
+ }
+ public void setCheckedException(String x) throws Exception {
+ throw theCheckedException;
+ }
+ public void CheckedException() throws Exception {
+ throw theCheckedException;
+ }
+ }
+
+ public static class DynamicExcept implements DynamicMBean {
+ public Object getAttribute(String attrName)
+ throws MBeanException {
+ if (attrName.equals("UncheckedException"))
+ throw theUncheckedException;
+ else
+ throw new AssertionError();
+ }
+ public void setAttribute(Attribute attr)
+ throws MBeanException {
+ String attrName = attr.getName();
+ if (attrName.equals("UncheckedException"))
+ throw theUncheckedException;
+ else
+ throw new AssertionError();
+ }
+ public Object invoke(String opName, Object[] params, String[] sig)
+ throws MBeanException {
+ assert params == null && sig == null;
+ if (opName.equals("UncheckedException"))
+ throw theUncheckedException;
+ else
+ throw new AssertionError();
+ }
+ public AttributeList getAttributes(String[] names) {
+ assert false;
+ return null;
+ }
+ public AttributeList setAttributes(AttributeList attrs) {
+ assert false;
+ return null;
+ }
+ public MBeanInfo getMBeanInfo() {
+ try {
+ return new StandardMBean(new Except(), ExceptMBean.class)
+ .getMBeanInfo();
+ } catch (Exception e) {
+ assert false;
+ return null;
+ }
+ }
+ }
+
+ private static final Exception theCheckedException =
+ new Exception("The checked exception that should be seen");
+ private static final RuntimeException theUncheckedException =
+ new UnsupportedOperationException("The unchecked exception " +
+ "that should be seen");
+}
diff --git a/test/javax/management/MBeanServer/MBeanServerInvocationHandlerExceptionTest.java b/test/javax/management/MBeanServer/MBeanServerInvocationHandlerExceptionTest.java
new file mode 100644
index 0000000..47af92e
--- /dev/null
+++ b/test/javax/management/MBeanServer/MBeanServerInvocationHandlerExceptionTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5092515
+ * @summary Test how to unwrap a user specific exception
+ * @author Shanliang JIANG
+ * @run clean MBeanServerInvocationHandlerExceptionTest
+ * @run build MBeanServerInvocationHandlerExceptionTest
+ * @run main MBeanServerInvocationHandlerExceptionTest
+ */
+
+
+import java.io.IOException;
+import javax.management.*;
+
+public class MBeanServerInvocationHandlerExceptionTest {
+ public static void main(String[] args) throws Exception {
+ System.out.println(">>> Test how for the MBeanServerInvocationHandler to "+
+ "unwrap a user specific exception.");
+
+ final MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ final ObjectName name = new ObjectName("a:b=c");
+ mbs.registerMBean(new Test(), name);
+ TestMBean proxy = (TestMBean)
+ MBeanServerInvocationHandler.newProxyInstance(mbs,
+ name,
+ TestMBean.class,
+ false);
+
+ // test the method "getter"
+ System.out.println(">>> Test the method getter to get an IOException.");
+ try {
+ proxy.getIOException();
+ } catch (IOException e) {
+ System.out.println(">>> Test passed: got expected exception:");
+ // e.printStackTrace(System.out);
+ } catch (Throwable t) {
+ System.out.println(">>> Test failed: got wrong exception:");
+ t.printStackTrace(System.out);
+
+ throw new RuntimeException("Did not get an expected IOException.");
+ }
+
+ // test the method "setter"
+ System.out.println(">>> Test the method setter to get a RuntimeException.");
+ try {
+ proxy.setRuntimeException("coucou");
+ } catch (UnsupportedOperationException ue) {
+ System.out.println(">>> Test passed: got expected exception:");
+ //ue.printStackTrace(System.out);
+ } catch (Throwable t) {
+ System.out.println(">>> Test failed: got wrong exception:");
+ t.printStackTrace(System.out);
+
+ throw new RuntimeException("Did not get an expected Runtimeexception.");
+ }
+
+ // test the method "invoke"
+ System.out.println(">>> Test the method invoke to get an Error.");
+ try {
+ proxy.invokeError();
+ } catch (AssertionError ae) {
+ System.out.println(">>> Test passed: got expected exception:");
+ //ue.printStackTrace(System.out);
+ } catch (Throwable t) {
+ System.out.println(">>> Test failed: got wrong exception:");
+ t.printStackTrace(System.out);
+
+ throw new RuntimeException("Did not get an expected Error.");
+ }
+ }
+
+ public static interface TestMBean {
+ public Object getIOException() throws IOException;
+
+ public void setRuntimeException(String s) throws RuntimeException;
+
+ public void invokeError() throws Error;
+
+ }
+
+ public static class Test implements TestMBean {
+ public Object getIOException() throws IOException {
+ throw new IOException("oops");
+ }
+
+ public void setRuntimeException(String s) throws RuntimeException {
+ throw new UnsupportedOperationException(s);
+ }
+
+ public void invokeError() throws Error {
+ throw new AssertionError();
+ }
+ }
+}
diff --git a/test/javax/management/MBeanServer/NewMBeanListenerTest.java b/test/javax/management/MBeanServer/NewMBeanListenerTest.java
new file mode 100644
index 0000000..671ff1b
--- /dev/null
+++ b/test/javax/management/MBeanServer/NewMBeanListenerTest.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4757273
+ * @summary Test that registered notification is sent early enough
+ * @author Eamonn McManus
+ * @run clean NewMBeanListenerTest
+ * @run build NewMBeanListenerTest
+ * @run main NewMBeanListenerTest
+ */
+
+import javax.management.*;
+
+/* Tests that you can write a listener for MBean registrations, that
+ * registers another listener on every newly-registered MBean (that is
+ * a NotificationBroadcaster). Provided the newly-registered MBean
+ * waits until its postRegister is called, no notifications will be lost.
+ */
+public class NewMBeanListenerTest {
+ public static void main(String[] args) throws Exception {
+ final MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ final ObjectName delegateName =
+ new ObjectName("JMImplementation:type=MBeanServerDelegate");
+ final CountListener countListener = new CountListener();
+ final NotificationListener addListener = new NotificationListener() {
+ public void handleNotification(Notification n, Object h) {
+ if (!(n instanceof MBeanServerNotification)) {
+ System.out.println("Ignoring delegate notif: " +
+ n.getClass().getName());
+ return;
+ }
+ MBeanServerNotification mbsn = (MBeanServerNotification) n;
+ if (!(mbsn.getType()
+ .equals(MBeanServerNotification
+ .REGISTRATION_NOTIFICATION))) {
+ System.out.println("Ignoring MBeanServer notif: " +
+ mbsn.getType());
+ return;
+ }
+ System.out.println("Got registration notif for " +
+ mbsn.getMBeanName());
+ try {
+ mbs.addNotificationListener(mbsn.getMBeanName(),
+ countListener, null, null);
+ } catch (Exception e) {
+ System.out.println("TEST INCORRECT: addNL failed:");
+ e.printStackTrace(System.out);
+ System.exit(1);
+ }
+ System.out.println("Added notif listener for " +
+ mbsn.getMBeanName());
+ }
+ };
+ System.out.println("Adding registration listener");
+ mbs.addNotificationListener(delegateName, addListener, null, null);
+ final ObjectName broadcasterName = new ObjectName(":type=Broadcaster");
+ System.out.println("Creating Broadcaster MBean");
+ mbs.createMBean(Broadcaster.class.getName(), broadcasterName);
+ if (countListener.getCount() == 1)
+ System.out.println("Got notif as expected");
+ else {
+ System.out.println("TEST FAILED: added listener not called");
+ System.exit(1);
+ }
+ mbs.unregisterMBean(broadcasterName);
+ Broadcaster b = new Broadcaster();
+ System.out.println("Registering Broadcaster MBean");
+ mbs.registerMBean(b, broadcasterName);
+ if (countListener.getCount() == 2)
+ System.out.println("Got notif as expected");
+ else {
+ System.out.println("TEST FAILED: added listener not called");
+ System.exit(1);
+ }
+ System.out.println("Test passed");
+ }
+
+ public static interface BroadcasterMBean {}
+
+ public static class Broadcaster
+ extends NotificationBroadcasterSupport
+ implements BroadcasterMBean, MBeanRegistration {
+
+ public ObjectName preRegister(MBeanServer mbs, ObjectName name) {
+ return name;
+ }
+
+ public void postRegister(Boolean registrationDone) {
+ System.out.println("Broadcaster.postRegister: sending notif");
+ sendNotification(new Notification("x", this, 0L));
+ }
+
+ public void preDeregister() {
+ }
+
+ public void postDeregister() {
+ }
+ }
+
+ private static class CountListener implements NotificationListener {
+ private int count;
+
+ public synchronized void handleNotification(Notification n, Object h) {
+ if (!n.getType().equals("x")) {
+ System.out.println("TEST FAILED: received bogus notif: " + n +
+ " (type=" + n.getType() + ")");
+ System.exit(1);
+ }
+ count++;
+ }
+
+ public synchronized int getCount() {
+ return count;
+ }
+ }
+}
diff --git a/test/javax/management/MBeanServer/NotifDeadlockTest.java b/test/javax/management/MBeanServer/NotifDeadlockTest.java
new file mode 100644
index 0000000..ad3bb88
--- /dev/null
+++ b/test/javax/management/MBeanServer/NotifDeadlockTest.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4757273
+ * @summary Test deadlock in MBeanServerDelegate listeners
+ * @author Eamonn McManus
+ * @run clean NotifDeadlockTest
+ * @run build NotifDeadlockTest
+ * @run main NotifDeadlockTest
+ */
+
+/*
+ * Test deadlock when a listener for an MBeanServerDelegate does a
+ * register or unregister of an MBean. Since such a listener is
+ * triggered by a register or unregister operation, deadlock scenarios
+ * are possible if there are any locks held while the listener is
+ * being dispatched.
+ *
+ * The flow of control looks rather like this:
+ *
+ * Thread 1:
+ * - MBeanServer.createMBean(..., objectName1);
+ * --- MBeanServerDelegate.sendNotification
+ * ----- XListener.handleNotification
+ * ------- create Thread 2
+ * ------- wait for Thread 2 to complete
+ *
+ * Thread 2:
+ * - MBeanServer.createMBean(..., objectName2);
+ * - end Thread 2
+ *
+ * If any locks are held by Thread 1 within createMBean or
+ * sendNotification, then Thread 2 can block waiting for them.
+ * Since Thread 1 is itself waiting for Thread 2, this is a deadlock.
+ *
+ * We test all four combinations of:
+ * (Thread1-create,Thread1-unregister) x (Thread2-create,Thread2-unregister)
+ *
+ * In the JMX 1.1 RI, all four tests fail. In the JMX 1.2 RI, all four
+ * tests should pass.
+ */
+import javax.management.*;
+
+public class NotifDeadlockTest {
+ static ObjectName on1, on2, delName;
+ static {
+ try {
+ on1 = new ObjectName("thing:a=b");
+ on2 = new ObjectName("thing:c=d");
+ delName =
+ new ObjectName("JMImplementation:type=MBeanServerDelegate");
+ } catch (MalformedObjectNameException e) {
+ throw new Error();
+ }
+ }
+ static MBeanServer mbs;
+ static boolean timedOut;
+
+ /* This listener registers or unregisters the MBean called on2
+ when triggered. */
+ private static class XListener implements NotificationListener {
+ private boolean firstTime = true;
+ private final boolean register;
+
+ XListener(boolean register) {
+ this.register = register;
+ }
+
+ public void handleNotification(Notification not, Object handback) {
+ if (firstTime) {
+ firstTime = false;
+ Thread t = new Thread() {
+ public void run() {
+ try {
+ if (register) {
+ mbs.createMBean("javax.management.timer.Timer",
+ on2);
+ System.out.println("Listener created " + on2);
+ } else {
+ mbs.unregisterMBean(on2);
+ System.out.println("Listener removed " + on2);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ };
+ t.start();
+ try {
+ t.join(2000);
+ } catch (InterruptedException e) {
+ e.printStackTrace(); // should not happen
+ }
+ if (t.isAlive()) {
+ System.out.println("FAILURE: Wait timed out: " +
+ "probable deadlock");
+ timedOut = true;
+ }
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ boolean success = true;
+
+ System.out.println("Test 1: in register notif, unregister an MBean");
+ timedOut = false;
+ mbs = MBeanServerFactory.createMBeanServer();
+ mbs.createMBean("javax.management.timer.Timer", on2);
+ mbs.addNotificationListener(delName, new XListener(false), null, null);
+ mbs.createMBean("javax.management.timer.Timer", on1);
+ MBeanServerFactory.releaseMBeanServer(mbs);
+ if (timedOut) {
+ success = false;
+ Thread.sleep(500);
+ // wait for the spawned thread to complete its work, probably
+ }
+ System.out.println("Test 1 completed");
+
+ System.out.println("Test 2: in unregister notif, unregister an MBean");
+ timedOut = false;
+ mbs = MBeanServerFactory.createMBeanServer();
+ mbs.createMBean("javax.management.timer.Timer", on1);
+ mbs.createMBean("javax.management.timer.Timer", on2);
+ mbs.addNotificationListener(delName, new XListener(false), null, null);
+ mbs.unregisterMBean(on1);
+ MBeanServerFactory.releaseMBeanServer(mbs);
+ if (timedOut) {
+ success = false;
+ Thread.sleep(500);
+ // wait for the spawned thread to complete its work, probably
+ }
+ System.out.println("Test 2 completed");
+
+ System.out.println("Test 3: in register notif, register an MBean");
+ timedOut = false;
+ mbs = MBeanServerFactory.createMBeanServer();
+ mbs.addNotificationListener(delName, new XListener(true), null, null);
+ mbs.createMBean("javax.management.timer.Timer", on1);
+ MBeanServerFactory.releaseMBeanServer(mbs);
+ if (timedOut) {
+ success = false;
+ Thread.sleep(500);
+ // wait for the spawned thread to complete its work, probably
+ }
+ System.out.println("Test 3 completed");
+
+ System.out.println("Test 4: in unregister notif, register an MBean");
+ timedOut = false;
+ mbs = MBeanServerFactory.createMBeanServer();
+ mbs.createMBean("javax.management.timer.Timer", on1);
+ mbs.addNotificationListener(delName, new XListener(true), null, null);
+ mbs.unregisterMBean(on1);
+ MBeanServerFactory.releaseMBeanServer(mbs);
+ if (timedOut) {
+ success = false;
+ Thread.sleep(500);
+ // wait for the spawned thread to complete its work, probably
+ }
+ System.out.println("Test 4 completed");
+
+ if (success)
+ System.out.println("Test passed");
+ else {
+ System.out.println("TEST FAILED: at least one subcase failed");
+ System.exit(1);
+ }
+ }
+}
diff --git a/test/javax/management/MBeanServer/PostRegisterDeadlockTest.java b/test/javax/management/MBeanServer/PostRegisterDeadlockTest.java
new file mode 100644
index 0000000..da9f901
--- /dev/null
+++ b/test/javax/management/MBeanServer/PostRegisterDeadlockTest.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6417044
+ * @summary Test deadlock in MBeanRegistration.postRegister method
+ * @author Eamonn McManus, Daniel Fuchs
+ * @run clean PostRegisterDeadlockTest
+ * @run build PostRegisterDeadlockTest
+ * @run main PostRegisterDeadlockTest
+ */
+
+import java.lang.Thread.State;
+import java.util.concurrent.*;
+import javax.management.*;
+
+public class PostRegisterDeadlockTest {
+ public static interface BlibbyMBean {}
+
+ public static class Blibby implements BlibbyMBean, MBeanRegistration {
+ public Blibby(MBeanServer mbs, ObjectName otherName) {
+ this.mbs = mbs;
+ this.otherName = otherName;
+ }
+
+ public ObjectName preRegister(MBeanServer mbs, ObjectName on) {
+ return on;
+ }
+
+ public void preDeregister() {}
+
+ public void postRegister(Boolean done) {
+ // If no other MBean was registered
+ // do nothing.
+ //
+ if (otherName == null) return;
+
+ // Check that we can unregister
+ // other MBean
+ try {
+ Thread t = new Thread() {
+ public void run() {
+ try {
+ try {
+ mbs.unregisterMBean(otherName);
+ } catch (InstanceNotFoundException x) {
+ // Race condition!
+ System.out.println(otherName+
+ " was unregistered by main thread.");
+ }
+ } catch (Throwable e) {
+ e.printStackTrace(System.out);
+ fail(e.toString());
+ }
+ }
+ };
+ t.start();
+ t.join(5000L);
+ if (t.isAlive()) {
+ if (t.getState().equals(State.BLOCKED))
+ fail("Deadlock detected");
+ else
+ fail("Test not conclusive: "+
+ "Thread is alive but not blocked.");
+ }
+ } catch (Throwable e) {
+ e.printStackTrace(System.out);
+ fail(e.toString());
+ }
+ }
+
+ public void postDeregister() {}
+
+ private final MBeanServer mbs;
+ private final ObjectName otherName;
+ }
+
+ public static void main(String[] args) throws Exception {
+ String previous = null;
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ ObjectName on1 = new ObjectName("a:type=Blibby,name=\"1\"");
+ ObjectName on2 = new ObjectName("a:type=Blibby,name=\"2\"");
+
+
+ // Test 1:
+ // 1 MBean is registered with on1
+ // Another MBean is registered with on1, postRegister(FALSE) is
+ // called, and the second MBean attempts to unregister first MBean in
+ // postRegister:
+ // postRegister starts a thread which unregisters the first MBean:
+ // this must not deadlock
+ //
+ System.out.println("\n**** TEST #1 ****\n");
+ System.out.println("Registering Blibby #1 with name: " + on1);
+ mbs.registerMBean(new Blibby(mbs, null), on1);
+ try {
+ System.out.println("Registering Blibby #2 with same name: " + on1);
+ mbs.registerMBean(new Blibby(mbs, on1), on1);
+ } catch (InstanceAlreadyExistsException x) {
+ System.out.println("Received expected exception: " + x);
+ }
+ if (mbs.isRegistered(on1)) {
+ try {
+ mbs.unregisterMBean(on1);
+ if (failure == null)
+ fail(on1+" should have been unregistered");
+ } catch (InstanceNotFoundException x) {
+ // Race condition!
+ System.out.println(on1+" was unregistered by mbean thread.");
+ }
+ } else {
+ System.out.println(on1+" was correctly unregistered.");
+ }
+
+ if (failure == previous)
+ System.out.println("\n**** TEST #1 PASSED ****\n");
+
+ previous = failure;
+
+ // Test 2:
+ // 1 MBean is registered with on1
+ // Another MBean is registered with on2, postRegister(TRUE) is
+ // called, and the second MBean attempts to unregister first MBean in
+ // postRegister:
+ // postRegister starts a thread which unregisters the first MBean:
+ // this must not deadlock
+ //
+ System.out.println("\n**** TEST #2 ****\n");
+ System.out.println("Registering Blibby #1 with name: " + on1);
+ mbs.registerMBean(new Blibby(mbs, null), on1);
+ System.out.println("Registering Blibby #2 with other name: " + on2);
+ mbs.registerMBean(new Blibby(mbs, on1), on2);
+ if (mbs.isRegistered(on1)) {
+ try {
+ mbs.unregisterMBean(on1);
+ if (failure == null)
+ fail(on1+" should have been unregistered");
+ } catch (InstanceNotFoundException x) {
+ // Race condition!
+ System.out.println(on1+" was unregistered by mbean thread.");
+ }
+ } else {
+ System.out.println(on1+" was correctly unregistered.");
+ }
+
+ System.out.println("unregistering "+on2);
+ mbs.unregisterMBean(on2);
+ if (failure == previous)
+ System.out.println("\n**** TEST #2 PASSED ****\n");
+ previous = failure;
+
+ if (failure == null)
+ System.out.println("OK: Test passed");
+ else
+ throw new Exception("TEST FAILED: " + failure);
+ }
+
+ private static void fail(String why) {
+ System.out.println("FAILED: " + why);
+ failure = (failure == null)?why:(failure+",\n"+why);
+ }
+
+ private static volatile String failure;
+}
diff --git a/test/javax/management/MBeanServer/PostRegisterDeadlockTest2.java b/test/javax/management/MBeanServer/PostRegisterDeadlockTest2.java
new file mode 100644
index 0000000..eb0ac49
--- /dev/null
+++ b/test/javax/management/MBeanServer/PostRegisterDeadlockTest2.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6417044
+ * @summary Test that a failing MBean registration does not lead to a deadlock
+ * @author Eamonn McManus
+ * @run main PostRegisterDeadlockTest2
+ */
+
+import javax.management.*;
+
+public class PostRegisterDeadlockTest2 {
+ private static String failed;
+
+ public static interface EmptyMBean {}
+
+ public static class Empty implements EmptyMBean, MBeanRegistration {
+ public ObjectName preRegister(MBeanServer mbs, ObjectName on) {
+ this.mbs = mbs;
+ this.on = on;
+ return on;
+ }
+ public void postRegister(Boolean done) {
+ Thread t = new Thread() {
+ public void run() {
+ if (!mbs.isRegistered(on))
+ failed = "Not registered!";
+ }
+ };
+ t.start();
+ try {
+ t.join(5000L);
+ } catch (InterruptedException e) {
+ failed = "Interrupted: " + e;
+ }
+ if (t.isAlive())
+ failed = "Deadlock detected";
+ }
+ public void preDeregister() {}
+ public void postDeregister() {}
+
+ private MBeanServer mbs;
+ private ObjectName on;
+ }
+
+ public static void main(String[] args) throws Exception {
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ ObjectName on = new ObjectName("a:b=c");
+ mbs.registerMBean(new Empty(), on);
+ try {
+ mbs.registerMBean(new Empty(), on);
+ throw new Exception("FAILED: did not get expected exception");
+ } catch (InstanceAlreadyExistsException e) {
+ System.out.println("OK: got expected exception");
+ }
+ if (failed != null)
+ throw new Exception("FAILED: " + failed);
+ System.out.println("TEST PASSED");
+ }
+}
diff --git a/test/javax/management/MBeanServer/PreDeregisterDeadlockTest.java b/test/javax/management/MBeanServer/PreDeregisterDeadlockTest.java
new file mode 100644
index 0000000..ef4d8bc
--- /dev/null
+++ b/test/javax/management/MBeanServer/PreDeregisterDeadlockTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6318664
+ * @summary Test deadlock in MBeanRegistration.preDeregister method
+ * @author Eamonn McManus
+ * @run clean PreDeregisterDeadlockTest
+ * @run build PreDeregisterDeadlockTest
+ * @run main PreDeregisterDeadlockTest
+ */
+
+import java.util.concurrent.*;
+import javax.management.*;
+
+public class PreDeregisterDeadlockTest {
+ public static interface BlibbyMBean {}
+
+ public static class Blibby implements BlibbyMBean, MBeanRegistration {
+ public Blibby(MBeanServer mbs, ObjectName otherName) {
+ this.mbs = mbs;
+ this.otherName = otherName;
+ }
+
+ public ObjectName preRegister(MBeanServer mbs, ObjectName on) {
+ return on;
+ }
+
+ public void postRegister(Boolean done) {}
+
+ public void preDeregister() {
+ if (otherName == null)
+ return;
+ try {
+ Thread t = new Thread() {
+ public void run() {
+ try {
+ mbs.unregisterMBean(otherName);
+ } catch (Throwable e) {
+ e.printStackTrace(System.out);
+ fail(e.toString());
+ }
+ }
+ };
+ t.start();
+ t.join(5000L);
+ if (t.isAlive())
+ fail("Deadlock detected");
+ } catch (Throwable e) {
+ e.printStackTrace(System.out);
+ fail(e.toString());
+ }
+ }
+
+ public void postDeregister() {}
+
+ private final MBeanServer mbs;
+ private final ObjectName otherName;
+ }
+
+ public static interface BlobbyMBean {}
+
+ public static class Blobby implements BlobbyMBean, MBeanRegistration {
+ public Blobby(MBeanServer mbs, Semaphore semaphore) {
+ this.mbs = mbs;
+ this.semaphore = semaphore;
+ }
+
+ public ObjectName preRegister(MBeanServer mbs, ObjectName on) {
+ this.objectName = on;
+ return on;
+ }
+
+ public void postRegister(Boolean done) {}
+
+ public void preDeregister() throws Exception {
+ Thread t = new Thread() {
+ public void run() {
+ try {
+ mbs.unregisterMBean(objectName);
+ fail("Nested unregister succeeded");
+ } catch (InstanceNotFoundException e) {
+ semaphore.release();
+ } catch (Throwable e) {
+ e.printStackTrace(System.out);
+ fail(e.toString());
+ }
+ }
+ };
+ t.start();
+ // Give the thread a chance to block so we are really
+ // testing parallelism. (On slow machines we might not
+ // really be testing it but we should be covered by our
+ // faster machines.)
+ Thread.sleep(500L);
+ }
+
+ public void postDeregister() {}
+
+ private final MBeanServer mbs;
+ private ObjectName objectName;
+ private final Semaphore semaphore;
+ }
+
+ public static void main(String[] args) throws Exception {
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ ObjectName on1 = new ObjectName("a:type=Blibby,name=\"1\"");
+ ObjectName on2 = new ObjectName("a:type=Blibby,name=\"2\"");
+
+ // Test 1: preDeregister starts a thread which unregisters a
+ // different MBean: this must not deadlock
+ mbs.registerMBean(new Blibby(mbs, on2), on1);
+ mbs.registerMBean(new Blibby(mbs, null), on2);
+ mbs.unregisterMBean(on1);
+
+ // Test 2: preDeregister starts a thread which tries to
+ // unregister the same MBean: this thread should block until
+ // the original thread succeeds in unregistering, then
+ // get an InstanceNotFoundException. We wait for it to
+ // complete here, using the semaphore.
+ Semaphore semaphore = new Semaphore(0);
+ mbs.registerMBean(new Blobby(mbs, semaphore), on1);
+ mbs.unregisterMBean(on1);
+ boolean ok = semaphore.tryAcquire(1, 5, TimeUnit.SECONDS);
+ if (!ok)
+ fail("Second unregister thread did not complete");
+
+ if (failure == null)
+ System.out.println("OK: Test passed");
+ else
+ throw new Exception("TEST FAILED: " + failure);
+ }
+
+ private static void fail(String why) {
+ System.out.println("FAILED: " + why);
+ failure = why;
+ }
+
+ private static volatile String failure;
+}
diff --git a/test/javax/management/MBeanServer/PreRegisterTest.java b/test/javax/management/MBeanServer/PreRegisterTest.java
new file mode 100644
index 0000000..4645c2a
--- /dev/null
+++ b/test/javax/management/MBeanServer/PreRegisterTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4911846
+ * @summary Test that MBeanRegistration can change caller ObjectName
+ * @author Eamonn McManus
+ * @run clean PreRegisterTest
+ * @run build PreRegisterTest
+ * @run main PreRegisterTest
+ */
+
+/* Check that an ObjectName returned by MBeanRegistration.preRegister is
+ the one used, even if createMBean had a different non-null ObjectName. */
+
+import java.util.Set;
+import javax.management.*;
+
+public class PreRegisterTest {
+ static final ObjectName oldName, newName;
+
+ static {
+ try {
+ oldName = new ObjectName("a:type=old");
+ newName = new ObjectName("a:type=new");
+ } catch (MalformedObjectNameException e) {
+ e.printStackTrace();
+ throw new Error();
+ }
+ }
+
+ public static class X implements XMBean, MBeanRegistration {
+ public ObjectName preRegister(MBeanServer mbs, ObjectName name) {
+ return newName;
+ }
+ public void postRegister(Boolean done) {}
+ public void preDeregister() {}
+ public void postDeregister() {}
+ }
+
+ public static interface XMBean {
+ }
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("Testing preRegister ObjectName substitution");
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ mbs.createMBean(X.class.getName(), oldName);
+ Set names = mbs.queryNames(null, null);
+ System.out.println("MBean names after createMBean: " + names);
+ boolean ok = true;
+ if (names.contains(oldName)) {
+ ok = false;
+ System.out.println("TEST FAILS: previous name was used");
+ }
+ if (!names.contains(newName)) {
+ ok = false;
+ System.out.println("TEST FAILS: substitute name was not used");
+ }
+
+ if (ok) {
+ System.out.println("Test passes: ObjectName correctly " +
+ "substituted");
+ } else {
+ System.out.println("TEST FAILS: ObjectName not correctly " +
+ "substituted");
+ System.exit(1);
+ }
+ }
+}
diff --git a/test/javax/management/MBeanServerFactory/ReleaseMBeanServerTest.java b/test/javax/management/MBeanServerFactory/ReleaseMBeanServerTest.java
new file mode 100644
index 0000000..bb958ea
--- /dev/null
+++ b/test/javax/management/MBeanServerFactory/ReleaseMBeanServerTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4955222
+ * @summary Test that the releaseMBeanServer(MBeanServer mbeanServer) method
+ * throws IllegalArgumentException as expected
+ * @author Luis-Miguel Alventosa
+ * @run clean ReleaseMBeanServerTest
+ * @run build ReleaseMBeanServerTest
+ * @run main ReleaseMBeanServerTest
+ */
+
+/* Check that the releaseMBeanServer(MBeanServer mbeanServer) method throws
+ IllegalArgumentException if mbeanServer was not generated by one of the
+ createMBeanServer methods, or if releaseMBeanServer was already called
+ on it. */
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+
+public class ReleaseMBeanServerTest {
+
+ private static final String DOMAIN = "TestDomain";
+
+ public static void main(String[] args) throws Exception {
+
+ System.out.println("--------------------------------------" +
+ "-----------------------------------------");
+ System.out.println("- Testing IllegalArgumentException in " +
+ "MBeanServerFactory.releaseMBeanServer() -");
+ System.out.println("--------------------------------------" +
+ "-----------------------------------------");
+
+ System.out.println("TEST_0: Call releaseMBeanServer() with " +
+ "a null MBeanServer reference.");
+ try {
+ MBeanServerFactory.releaseMBeanServer(null);
+ System.err.println("Didn't get expected IllegalArgumentException!");
+ System.exit(1);
+ } catch (IllegalArgumentException e) {
+ System.out.println("Got expected IllegalArgumentException!");
+ }
+
+ System.out.println("TEST_1: Call releaseMBeanServer() with an " +
+ "MBeanServer reference corresponding to an " +
+ "MBeanServer created using newMBeanServer().");
+ MBeanServer mbs1 = MBeanServerFactory.newMBeanServer();
+ try {
+ MBeanServerFactory.releaseMBeanServer(mbs1);
+ System.err.println("Didn't get expected IllegalArgumentException!");
+ System.exit(1);
+ } catch (IllegalArgumentException e) {
+ System.out.println("Got expected IllegalArgumentException!");
+ }
+
+ System.out.println("TEST_2: Call releaseMBeanServer() with an " +
+ "MBeanServer reference corresponding to an " +
+ "MBeanServer created using newMBeanServer(String).");
+ MBeanServer mbs2 = MBeanServerFactory.newMBeanServer(DOMAIN);
+ try {
+ MBeanServerFactory.releaseMBeanServer(mbs2);
+ System.err.println("Didn't get expected IllegalArgumentException!");
+ System.exit(1);
+ } catch (IllegalArgumentException e) {
+ System.out.println("Got expected IllegalArgumentException!");
+ }
+
+ System.out.println("TEST_3: Call releaseMBeanServer() twice with an " +
+ "MBeanServer reference corresponding to an MBean" +
+ "Server created using createMBeanServer().");
+ MBeanServer mbs3 = MBeanServerFactory.createMBeanServer();
+ MBeanServerFactory.releaseMBeanServer(mbs3);
+ try {
+ MBeanServerFactory.releaseMBeanServer(mbs3);
+ System.err.println("Didn't get expected IllegalArgumentException!");
+ System.exit(1);
+ } catch (IllegalArgumentException e) {
+ System.out.println("Got expected IllegalArgumentException!");
+ }
+
+ System.out.println("TEST_4: Call releaseMBeanServer() twice with an " +
+ "MBeanServer reference corresponding to an MBean" +
+ "Server created using createMBeanServer(String).");
+ MBeanServer mbs4 = MBeanServerFactory.createMBeanServer(DOMAIN);
+ MBeanServerFactory.releaseMBeanServer(mbs4);
+ try {
+ MBeanServerFactory.releaseMBeanServer(mbs4);
+ System.err.println("Didn't get expected IllegalArgumentException!");
+ System.exit(1);
+ } catch (IllegalArgumentException e) {
+ System.out.println("Got expected IllegalArgumentException!");
+ }
+ }
+}
diff --git a/test/javax/management/MustBeValidMBeanInfo/MustBeValidCommand.java b/test/javax/management/MustBeValidMBeanInfo/MustBeValidCommand.java
new file mode 100644
index 0000000..a0b11c5
--- /dev/null
+++ b/test/javax/management/MustBeValidMBeanInfo/MustBeValidCommand.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4874819
+ * @summary Test that MBeanInfo classes no longer throw an
+ * IllegalArgumentException when attribute names, operation names, and
+ * Java type names do not strictly follow the expected Java syntax.
+ * @author Daniel Fuchs
+ * @run clean MustBeValidCommand
+ * @run build MustBeValidCommand
+ * @run main MustBeValidCommand
+ */
+
+import javax.management.MBeanInfo;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanParameterInfo;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanConstructorInfo;
+
+public class MustBeValidCommand {
+
+ private static String[][] attributes = {
+ { "Attribute with valid identifiers",
+ "validType1","validNameAtt1" },
+ { "Attribute with invalid type",
+ "invalid-type", "validNameAtt2" },
+ { "Attribute with invalid name", "valid.type2",
+ "invalid-name-att3" },
+ { "Attribute with invalid name and type",
+ "invalidtype[]","invalid.name.att4" }
+ };
+ private static String[][] constructors = {
+ { "Constructor with valid name",
+ "ValidConstructor1" },
+ { "Constructor with invalid name",
+ "invalid.Constructor2"},
+ { "Constructor with invalid name",
+ "invalid-constructor-3" },
+ { "Constructor with invalid name",
+ "invalid constructor" }
+ };
+ private static String[][] mbeanclasses = {
+ { "MBean with valid class name",
+ "ValidMBeanClass1" },
+ { "MBean with valid class name",
+ "valid.mbean.Class2" },
+ { "MBean with invalid class name",
+ "invalid.MBeanClass3[]"},
+ { "MBean with invalid class name",
+ "invalid-mbean-class-4" },
+ { "MBean with invalid class name",
+ "invalid mbean class 5" }
+ };
+ private static String[][] notificationclasses = {
+ { "Notification with valid class name",
+ "ValidNotificationClass1" },
+ { "Notification with valid class name",
+ "valid.notification.Class2" },
+ { "Notification with invalid class name",
+ "invalid.NotificationClass3[]"},
+ { "Notification with invalid class name",
+ "invalid-notification-class-4" },
+ { "Notification with invalid class name",
+ "invalid notification class 5" }
+ };
+ private static String[][] operations = {
+ { "Operation with valid identifiers",
+ "validType1","validNameOp1" },
+ { "Operation with invalid type",
+ "invalid-type", "validNameOp2" },
+ { "Operation with invalid name", "valid.type2",
+ "invalid-name-op3" },
+ { "Operation with invalid name and type",
+ "invalidtype[]","invalid.name.op4" }
+ };
+ private static String[][] parameters = {
+ { "Parameter with valid identifiers",
+ "validType1","validNamePar1" },
+ { "Parameter with invalid type",
+ "invalid-type", "validNamePar2" },
+ { "Parameter with invalid name", "valid.type2",
+ "invalid-name-par3" },
+ { "Parameter with invalid name and type",
+ "invalidtype[]","invalid.name.par4" }
+ };
+
+ static private MBeanAttributeInfo[] makeAttInfos(String[][] spec) {
+ final MBeanAttributeInfo[] result =
+ new MBeanAttributeInfo[spec.length];
+ for (int i=0;i<result.length;i++) {
+ System.out.println("\tCreate an MBeanAttributeInfo: " +
+ spec[i][0]);
+ final MBeanAttributeInfo item =
+ new MBeanAttributeInfo(spec[i][2],spec[i][1],spec[i][0],
+ true,true,false);
+ result[i]=item;
+ }
+ return result;
+ }
+
+ static private MBeanParameterInfo[] makeParInfos(String[][] spec) {
+ final MBeanParameterInfo[] result =
+ new MBeanParameterInfo[spec.length];
+ for (int i=0;i<result.length;i++) {
+ System.out.println("\tCreate an MBeanParameterInfo: " +
+ spec[i][0]);
+ final MBeanParameterInfo item =
+ new MBeanParameterInfo(spec[i][2],spec[i][1],spec[i][0]);
+ result[i]=item;
+ }
+ return result;
+ }
+
+ static private MBeanOperationInfo[] makeOpInfos(String[][] spec) {
+ final MBeanOperationInfo[] result =
+ new MBeanOperationInfo[spec.length];
+ final MBeanParameterInfo[] pars = makeParInfos(parameters);
+ for (int i=0;i<result.length;i++) {
+ System.out.println("\tCreate an MBeanOperationInfo: " +
+ spec[i][0]);
+ final MBeanOperationInfo item =
+ new MBeanOperationInfo(spec[i][2],spec[i][0],pars,spec[i][1],
+ MBeanOperationInfo.ACTION_INFO);
+ result[i]=item;
+ }
+ return result;
+ }
+
+ static private MBeanConstructorInfo[] makeCtorInfos(String[][] spec) {
+ final MBeanConstructorInfo[] result =
+ new MBeanConstructorInfo[spec.length];
+ final MBeanParameterInfo[] pars = makeParInfos(parameters);
+ for (int i=0;i<result.length;i++) {
+ System.out.println("\tCreate an MBeanConstructorInfo: " +
+ spec[i][0]);
+ final MBeanConstructorInfo item =
+ new MBeanConstructorInfo(spec[i][1],spec[i][0],pars);
+ result[i]=item;
+ }
+ return result;
+ }
+
+ static private MBeanNotificationInfo[] makeNotifInfos(String[][] spec) {
+ final MBeanNotificationInfo[] result =
+ new MBeanNotificationInfo[spec.length];
+ final String[] types = {"valid.type","invalid-type"};
+ for (int i=0;i<result.length;i++) {
+ System.out.println("\tCreate an MBeanNotificationInfo: " +
+ spec[i][0]);
+ final MBeanNotificationInfo item =
+ new MBeanNotificationInfo(types,spec[i][1],spec[i][0]);
+ result[i]=item;
+ }
+ return result;
+ }
+
+ public static void main(String[] args) throws Exception {
+ // Instantiate the MBean server
+ //
+ final MBeanAttributeInfo[] atts = makeAttInfos(attributes);
+ final MBeanConstructorInfo[] ctors = makeCtorInfos(constructors);
+ final MBeanOperationInfo[] ops = makeOpInfos(operations);
+ final MBeanNotificationInfo[] notifs =
+ makeNotifInfos(notificationclasses);
+
+ for (int i=0; i<mbeanclasses.length;i++) {
+ System.out.println("Create an MBeanInfo: " + mbeanclasses[i][0]);
+ final MBeanInfo mbi =
+ new MBeanInfo(mbeanclasses[i][1],mbeanclasses[i][0],
+ atts, ctors, ops, notifs);
+ }
+
+ // Test OK!
+ //
+ System.out.println("All MBeanInfo successfuly created!");
+ System.out.println("Bye! Bye!");
+ }
+}
diff --git a/test/javax/management/MustBeValidMBeanInfo/logging.properties b/test/javax/management/MustBeValidMBeanInfo/logging.properties
new file mode 100644
index 0000000..2f22174
--- /dev/null
+++ b/test/javax/management/MustBeValidMBeanInfo/logging.properties
@@ -0,0 +1,14 @@
+handlers= java.util.logging.ConsoleHandler
+
+.level= INFO
+
+
+java.util.logging.FileHandler.pattern = %h/java%u.log
+java.util.logging.FileHandler.limit = 50000
+java.util.logging.FileHandler.count = 1
+java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
+
+java.util.logging.ConsoleHandler.level = FINEST
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+javax.management.misc.level = FINEST
\ No newline at end of file
diff --git a/test/javax/management/ObjectInstance/MBeanInfoFailTest.java b/test/javax/management/ObjectInstance/MBeanInfoFailTest.java
new file mode 100644
index 0000000..6c986bf
--- /dev/null
+++ b/test/javax/management/ObjectInstance/MBeanInfoFailTest.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5001857
+ * @summary Test queryNames() and queryMBeans() with a buggy DynamicMBean
+ * @author Daniel Fuchs
+ * @run clean MBeanInfoFailTest
+ * @run build MBeanInfoFailTest
+ * @run main MBeanInfoFailTest
+ */
+
+import javax.management.*;
+import java.util.*;
+
+public class MBeanInfoFailTest {
+
+ public static class UnspeakableException extends RuntimeException {
+ public UnspeakableException(String unspeakableMessage) {
+ super(unspeakableMessage);
+ }
+ }
+
+ public interface ThornyDevilMBean {
+ public boolean isDormant();
+ public void setDormant(boolean sleep);
+ }
+
+ public static class ThornyDevil
+ extends StandardMBean implements ThornyDevilMBean {
+ private boolean sleep=true;
+ public ThornyDevil() throws NotCompliantMBeanException {
+ super(ThornyDevilMBean.class);
+ }
+ public boolean isDormant() {
+ return this.sleep;
+ }
+ public void setDormant(boolean sleep) {
+ this.sleep = sleep;
+ }
+ public MBeanInfo getMBeanInfo() {
+ if (isDormant()) return super.getMBeanInfo();
+ throw new UnspeakableException("The Thorny Devil has awoken!");
+ }
+ }
+
+ public static void printInstances(Set instances) {
+ for (Iterator it1 = instances.iterator(); it1.hasNext();) {
+ final ObjectInstance oi = (ObjectInstance)it1.next();
+ final ObjectName on = oi.getObjectName();
+ final String cn = oi.getClassName();
+ System.err.println(String.valueOf(on) + ": class is " + cn);
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("Test queryNames() and queryMBeans() with a "+
+ "buggy DynamicMBean");
+ try {
+ final MBeanServer server = MBeanServerFactory.createMBeanServer();
+
+ final ObjectName troubleKeeper =
+ new ObjectName("ThornyDevil:name=TroubleKeeper");
+ final ObjectName troubleMaker =
+ new ObjectName("ThornyDevil:name=TroubleMaker");
+ final ObjectName thornyPattern =
+ new ObjectName("ThornyDevil:*");
+
+ server.createMBean(ThornyDevil.class.getName(),
+ troubleKeeper);
+ server.createMBean(ThornyDevil.class.getName(),
+ troubleMaker);
+
+ final MBeanInfo info1 = server.getMBeanInfo(troubleKeeper);
+ System.out.println(String.valueOf(troubleKeeper)+" is a " +
+ info1.getClassName());
+ final MBeanInfo info2 = server.getMBeanInfo(troubleMaker);
+ System.out.println(String.valueOf(troubleMaker)+" is a " +
+ info2.getClassName());
+ final Set thorny1 = server.queryNames(thornyPattern,null);
+ if (thorny1.size() != 2) {
+ System.err.println("queryNames(): " +
+ "Expected to find 2 ThornyDevils before" +
+ " trouble started! ");
+ System.err.println("Found "+thorny1.size()+" instead: "+
+ thorny1);
+ System.exit(1);
+ }
+ final Set thornyM1 = server.queryMBeans(thornyPattern,null);
+ if (thornyM1.size() != 2) {
+ System.err.println("queryMBeans(): " +
+ "Expected to find 2 ThornyDevils before" +
+ " trouble started! ");
+ System.err.println("Found "+thornyM1.size()+" instead: ");
+ printInstances(thornyM1);
+ System.exit(2);
+ }
+ for (Iterator it1 = thornyM1.iterator(); it1.hasNext();) {
+ final ObjectInstance oi = (ObjectInstance)it1.next();
+ final ObjectName on = oi.getObjectName();
+ final String cn = oi.getClassName();
+ if (cn == null || !ThornyDevil.class.getName().
+ equals(cn)) {
+ System.err.println("Expected no trouble yet!");
+ System.err.println(String.valueOf(on) + ": class is " +
+ cn);
+ System.exit(3);
+ }
+ System.out.println(String.valueOf(on) + ": class is " + cn);
+ }
+
+ System.out.println("Starting trouble with "+troubleMaker+" ...");
+ ThornyDevilMBean troubleMakerproxy =
+ (ThornyDevilMBean) MBeanServerInvocationHandler.
+ newProxyInstance(server, troubleMaker, ThornyDevilMBean.class,
+ false);
+ troubleMakerproxy.setDormant(false);
+
+ try {
+ final MBeanInfo mbi = server.getMBeanInfo(troubleMaker);
+ System.err.println("No trouble started!: " + mbi);
+ System.exit(2);
+ } catch (Exception x) {
+ if (x.getCause() instanceof UnspeakableException)
+ System.out.println("Trouble started as expected: "
+ + x.getCause());
+ else {
+ System.err.println("Unexpected trouble: " + x.getCause());
+ x.printStackTrace();
+ System.exit(3);
+ }
+ }
+
+ final Set thorny2 = server.queryNames(thornyPattern,null);
+ if (thorny2.size() != 2) {
+ System.err.println("Expected to find 2 ThornyDevils after" +
+ " trouble started! ");
+ System.err.println("Found "+thorny2.size()+" instead: "+
+ thorny2);
+ System.exit(4);
+ }
+
+ final Set thornyM2 = server.queryMBeans(thornyPattern,null);
+ if (thornyM2.size() != 2) {
+ System.err.println("queryMBeans(): " +
+ "Expected to find 2 ThornyDevils after" +
+ " trouble started! ");
+ System.err.println("Found "+thornyM2.size()+" instead: ");
+ printInstances(thornyM2);
+ System.exit(5);
+ }
+ for (Iterator it1 = thornyM2.iterator(); it1.hasNext();) {
+ final ObjectInstance oi = (ObjectInstance)it1.next();
+ final ObjectName on = oi.getObjectName();
+ final String cn = oi.getClassName();
+ if (!on.equals(troubleMaker)) {
+ if (cn == null || !ThornyDevil.class.getName().
+ equals(cn)) {
+ System.err.println("Expected no trouble for " + on);
+ System.err.println(String.valueOf(on) + ": class is " +
+ cn);
+ System.exit(6);
+ }
+ } else {
+ if (cn != null) {
+ System.err.println("Expected trouble for " + on);
+ System.err.println(String.valueOf(on) + ": class is " +
+ cn);
+ System.exit(7);
+ }
+ }
+ System.out.println(String.valueOf(on) + ": class is " + cn);
+ }
+
+ System.out.println("Ahahah! " + troubleMaker +
+ " successfully thwarted!");
+ } catch( Exception x) {
+ System.err.println("Unexpected exception: " + x);
+ x.printStackTrace();
+ System.exit(8);
+ }
+ }
+
+}
diff --git a/test/javax/management/ObjectInstance/ObjectInstanceNullTest.java b/test/javax/management/ObjectInstance/ObjectInstanceNullTest.java
new file mode 100644
index 0000000..fefd00c
--- /dev/null
+++ b/test/javax/management/ObjectInstance/ObjectInstanceNullTest.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5015663
+ * @summary Test ObjectInstance(name,null).hashCode() and .equals()
+ * @author Daniel Fuchs
+ * @run clean ObjectInstanceNullTest
+ * @run build ObjectInstanceNullTest
+ * @run main ObjectInstanceNullTest
+ */
+
+import javax.management.*;
+
+public class ObjectInstanceNullTest {
+
+ public static void testEquals(ObjectInstance n1, ObjectInstance n2) {
+ try {
+ if (!n1.equals(n2) || !n2.equals(n1)) {
+ System.err.println("Equals yields false for: "+
+ "["+n1.getObjectName()+" , "+
+ n1.getClassName()+"] ["+
+ n2.getObjectName()+" , "+
+ n2.getClassName()+"]");
+ System.exit(1);
+ }
+ } catch (Exception x) {
+ System.err.println("Equals failed for: "+
+ "["+n1.getObjectName()+" , "+
+ n1.getClassName()+"] ["+
+ n2.getObjectName()+" , "+
+ n2.getClassName()+"]: " + x);
+ x.printStackTrace();
+ System.exit(2);
+ }
+ try {
+ if (n1.hashCode() != n2.hashCode()) {
+ System.err.println("Different hashCode() for: "+
+ "["+n1.getObjectName()+" , "+
+ n1.getClassName()+"] ["+
+ n2.getObjectName()+" , "+
+ n2.getClassName()+"]");
+ System.exit(3);
+ }
+ } catch (Exception x) {
+ System.err.println("Hashcode failed for: "+
+ "["+n1.getObjectName()+" , "+
+ n1.getClassName()+"] ["+
+ n2.getObjectName()+" , "+
+ n2.getClassName()+"]: " + x);
+ x.printStackTrace();
+ System.exit(4);
+ }
+ }
+
+ public static void testNotEquals(ObjectInstance n1, ObjectInstance n2) {
+ try {
+ if (n1.equals(n2) || n2.equals(n1)) {
+ System.err.println("Equals yields true for: "+
+ "["+n1.getObjectName()+" , "+
+ n1.getClassName()+"] ["+
+ n2.getObjectName()+" , "+
+ n2.getClassName()+"]");
+ System.exit(5);
+ }
+ } catch (Exception x) {
+ System.err.println("!Equals failed for: "+
+ "["+n1.getObjectName()+" , "+
+ n1.getClassName()+"] ["+
+ n2.getObjectName()+" , "+
+ n2.getClassName()+"]: " + x);
+ x.printStackTrace();
+ System.exit(6);
+ }
+ try {
+ if (n1.hashCode() == n2.hashCode()) {
+ System.out.println("Warning: Same hashCode() for: "+
+ "["+n1.getObjectName()+" , "+
+ n1.getClassName()+"] ["+
+ n2.getObjectName()+" , "+
+ n2.getClassName()+"]");
+ }
+ } catch (Exception x) {
+ System.err.println("Hashcode failed for: "+
+ "["+n1.getObjectName()+" , "+
+ n1.getClassName()+"] ["+
+ n2.getObjectName()+" , "+
+ n2.getClassName()+"]: " + x);
+ x.printStackTrace();
+ System.exit(7);
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("Test ObjectInstance(name,null).equals() and " +
+ "ObjectInstance(name,null).hashCode()");
+ try {
+ ObjectName toto1 = new ObjectName("Toto:foo=bar");
+ ObjectName toto2 = new ObjectName("Toto:bar=foo");
+ ObjectName clone1 = new ObjectName("Toto:bar=foo,cloned=yes");
+ ObjectName clone2 = new ObjectName("Toto:cloned=yes,bar=foo");
+ ObjectInstance n1 = new ObjectInstance(toto1,null);
+ ObjectInstance n2 = new ObjectInstance(toto1,null);
+ testEquals(n1,n1);
+ testEquals(n1,n2);
+ ObjectInstance n3 = new ObjectInstance(toto1,"Object");
+ ObjectInstance n4 = new ObjectInstance(toto1,"Object");
+ testEquals(n3,n3);
+ testEquals(n3,n4);
+ testNotEquals(n1,n3);
+ ObjectInstance n5 = new ObjectInstance(toto2,null);
+ ObjectInstance n6 = new ObjectInstance(toto2,"Object");
+ testEquals(n5,n5);
+ testEquals(n6,n6);
+ testNotEquals(n5,n1);
+ testNotEquals(n5,n3);
+ testNotEquals(n6,n1);
+ testNotEquals(n6,n3);
+ testNotEquals(n5,n6);
+ ObjectInstance n7 = new ObjectInstance(clone1,null);
+ ObjectInstance n8 = new ObjectInstance(clone2,null);
+ testEquals(n7,n8);
+ testNotEquals(n7,n1);
+ testNotEquals(n7,n5);
+ ObjectInstance n9 = new ObjectInstance(clone1,"Object");
+ ObjectInstance n10 = new ObjectInstance(clone2,"Object");
+ testEquals(n9,n10);
+ testNotEquals(n9,n1);
+ testNotEquals(n9,n5);
+ testNotEquals(n9,n7);
+ testNotEquals(n9,n8);
+ testNotEquals(n10,n1);
+ testNotEquals(n10,n5);
+ testNotEquals(n10,n7);
+ testNotEquals(n10,n8);
+ } catch( Exception x) {
+ System.err.println("Unexpected exception: " + x);
+ x.printStackTrace();
+ System.exit(8);
+ }
+ }
+
+}
diff --git a/test/javax/management/ObjectInstance/ToStringMethodTest.java b/test/javax/management/ObjectInstance/ToStringMethodTest.java
new file mode 100644
index 0000000..a6695c8
--- /dev/null
+++ b/test/javax/management/ObjectInstance/ToStringMethodTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5080083
+ * @summary Test new added method "toString"
+ * @author Shanliang JIANG
+ * @run clean ToStringMethodTest
+ * @run build ToStringMethodTest
+ * @run main ToStringMethodTest
+ */
+
+import javax.management.*;
+
+public class ToStringMethodTest {
+ public static void main(String[] args) throws Exception {
+
+ // for ObjectInstance class
+ System.out.println(">>> Test on the method \"toString\" of the ObjectInstance class.");
+
+ final ObjectName on = new ObjectName(":key=me");
+ final String className = "Unknown";
+ final ObjectInstance oi = new ObjectInstance(on, className);
+
+ final String expected = className+"["+on.toString()+"]";
+
+ if (!expected.equals(oi.toString())) {
+ throw new RuntimeException("The test failed on the method \"toString\" "+
+ "of the ObjectInstance class, expected to get "+
+ expected+", but got "+oi.toString());
+ }
+
+ // for Attribute class
+ System.out.println(">>> Test on the method \"toString\" of the Attribute class.");
+ final String name = "hahaha";
+ final Object value = new int[0];
+ final String exp = name + " = " + value;
+
+ final Attribute at = new Attribute(name, value);
+
+ if (!exp.equals(at.toString())) {
+ throw new RuntimeException("The test failed on the method \"toString\" "+
+ "of the Attribute class, expected to get "+exp+
+ ", but got "+at.toString());
+ }
+
+ System.out.println(">>> All passed.");
+ }
+}
diff --git a/test/javax/management/ObjectName/ApplyWildcardTest.java b/test/javax/management/ObjectName/ApplyWildcardTest.java
new file mode 100644
index 0000000..b265e7b
--- /dev/null
+++ b/test/javax/management/ObjectName/ApplyWildcardTest.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4716807
+ * @summary Test the ObjectName.apply(ObjectName) method
+ * with wildcards in the key properties value part.
+ * @author Luis-Miguel Alventosa
+ * @run clean ApplyWildcardTest
+ * @run build ApplyWildcardTest
+ * @run main ApplyWildcardTest
+ */
+
+import javax.management.ObjectName;
+
+public class ApplyWildcardTest {
+
+ private static final String positiveTests[][] = {
+ { "d:k=*", "d:k=\"\"" },
+
+ { "d:k=*", "d:k=" },
+ { "d:k=*", "d:k=v" },
+ { "d:k=a*b", "d:k=axyzb" },
+ { "d:k=a*b,*", "d:k=axyzb,k2=v2" },
+ { "d:*,k=a*b", "d:k=axyzb,k2=v2" },
+ { "d:k=?", "d:k=v" },
+ { "d:k=a?b", "d:k=axb" },
+ { "d:k=a?b,*", "d:k=axb,k2=v2" },
+ { "d:*,k=a?b", "d:k=axb,k2=v2" },
+ { "d:k=?*", "d:k=axyzb" },
+ { "d:k=a?bc*d", "d:k=axbcyzd" },
+ { "d:k=a?bc*d,*", "d:k=axbcyzd,k2=v2" },
+ { "d:*,k=a?bc*d", "d:k=axbcyzd,k2=v2" },
+ { "d:k1=?,k2=*", "d:k1=a,k2=ab" },
+ { "d:k1=a?b,k2=c*d", "d:k1=axb,k2=cyzd" },
+ { "d:k1=a?b,k2=c*d,*", "d:k1=axb,k2=cyzd,k3=v3" },
+ { "d:*,k1=a?b,k2=c*d", "d:k1=axb,k2=cyzd,k3=v3" },
+
+ { "d:k=\"*\"", "d:k=\"\"" },
+ { "d:k=\"*\"", "d:k=\"v\"" },
+ { "d:k=\"a*b\"", "d:k=\"axyzb\"" },
+ { "d:k=\"a*b\",*", "d:k=\"axyzb\",k2=\"v2\"" },
+ { "d:*,k=\"a*b\"", "d:k=\"axyzb\",k2=\"v2\"" },
+ { "d:k=\"?\"", "d:k=\"v\"" },
+ { "d:k=\"a?b\"", "d:k=\"axb\"" },
+ { "d:k=\"a?b\",*", "d:k=\"axb\",k2=\"v2\"" },
+ { "d:*,k=\"a?b\"", "d:k=\"axb\",k2=\"v2\"" },
+ { "d:k=\"?*\"", "d:k=\"axyzb\"" },
+ { "d:k=\"a?bc*d\"", "d:k=\"axbcyzd\"" },
+ { "d:k=\"a?bc*d\",*", "d:k=\"axbcyzd\",k2=\"v2\"" },
+ { "d:*,k=\"a?bc*d\"", "d:k=\"axbcyzd\",k2=\"v2\"" },
+ { "d:k1=\"?\",k2=\"*\"", "d:k1=\"a\",k2=\"ab\"" },
+ { "d:k1=\"a?b\",k2=\"c*d\"", "d:k1=\"axb\",k2=\"cyzd\"" },
+ { "d:k1=\"a?b\",k2=\"c*d\",*", "d:k1=\"axb\",k2=\"cyzd\",k3=\"v3\"" },
+ { "d:*,k1=\"a?b\",k2=\"c*d\"", "d:k1=\"axb\",k2=\"cyzd\",k3=\"v3\"" },
+ };
+
+ private static final String negativeTests[][] = {
+ { "d:k=\"*\"", "d:k=" },
+
+ { "d:k=*", "d:k=,k2=" },
+ { "d:k=*", "d:k=v,k2=v2" },
+ { "d:k=a*b", "d:k=axyzbc" },
+ { "d:k=a*b,*", "d:k=axyzbc,k2=v2" },
+ { "d:*,k=a*b", "d:k=axyzbc,k2=v2" },
+ { "d:k=?", "d:k=xyz" },
+ { "d:k=a?b", "d:k=ab" },
+ { "d:k=a?b,*", "d:k=ab,k2=v2" },
+ { "d:*,k=a?b", "d:k=ab,k2=v2" },
+ { "d:k=?*", "d:k=axyzb,k2=v2" },
+ { "d:k=a?bc*d", "d:k=abcd" },
+ { "d:k=a?bc*d,*", "d:k=abcd,k2=v2" },
+ { "d:*,k=a?bc*d", "d:k=abcd,k2=v2" },
+ { "d:k1=?,k2=*", "d:k1=ab,k2=ab" },
+ { "d:k1=a?b,k2=c*d", "d:k1=ab,k2=cd" },
+ { "d:k1=a?b,k2=c*d,*", "d:k1=ab,k2=cd,k3=v3" },
+ { "d:*,k1=a?b,k2=c*d", "d:k1=ab,k2=cd,k3=v3" },
+
+ { "d:k=\"*\"", "d:k=\"\",k2=\"\"" },
+ { "d:k=\"*\"", "d:k=\"v\",k2=\"v2\"" },
+ { "d:k=\"a*b\"", "d:k=\"axyzbc\"" },
+ { "d:k=\"a*b\",*", "d:k=\"axyzbc\",k2=\"v2\"" },
+ { "d:*,k=\"a*b\"", "d:k=\"axyzbc\",k2=\"v2\"" },
+ { "d:k=\"?\"", "d:k=\"xyz\"" },
+ { "d:k=\"a?b\"", "d:k=\"ab\"" },
+ { "d:k=\"a?b\",*", "d:k=\"ab\",k2=\"v2\"" },
+ { "d:*,k=\"a?b\"", "d:k=\"ab\",k2=\"v2\"" },
+ { "d:k=\"?*\"", "d:k=\"axyzb\",k2=\"v2\"" },
+ { "d:k=\"a?bc*d\"", "d:k=\"abcd\"" },
+ { "d:k=\"a?bc*d\",*", "d:k=\"abcd\",k2=\"v2\"" },
+ { "d:*,k=\"a?bc*d\"", "d:k=\"abcd\",k2=\"v2\"" },
+ { "d:k1=\"?\",k2=\"*\"", "d:k1=\"ab\",k2=\"ab\"" },
+ { "d:k1=\"a?b\",k2=\"c*d\"", "d:k1=\"ab\",k2=\"cd\"" },
+ { "d:k1=\"a?b\",k2=\"c*d\",*", "d:k1=\"ab\",k2=\"cd\",k3=\"v3\"" },
+ { "d:*,k1=\"a?b\",k2=\"c*d\"", "d:k1=\"ab\",k2=\"cd\",k3=\"v3\"" },
+ };
+
+ private static int runPositiveTests() {
+ int error = 0;
+ for (int i = 0; i < positiveTests.length; i++) {
+ System.out.println("----------------------------------------------");
+ try {
+ ObjectName on1 = ObjectName.getInstance(positiveTests[i][0]);
+ ObjectName on2 = ObjectName.getInstance(positiveTests[i][1]);
+ System.out.println("\"" + on1 + "\".apply(\"" + on2 + "\")");
+ boolean result = on1.apply(on2);
+ System.out.println("Result = " + result);
+ if (result == false) {
+ error++;
+ System.out.println("Test failed!");
+ } else {
+ System.out.println("Test passed!");
+ }
+ } catch (Exception e) {
+ error++;
+ System.out.println("Got Unexpected Exception = " + e.toString());
+ System.out.println("Test failed!");
+ }
+ System.out.println("----------------------------------------------");
+ }
+ return error;
+ }
+
+ private static int runNegativeTests() {
+ int error = 0;
+ for (int i = 0; i < negativeTests.length; i++) {
+ System.out.println("----------------------------------------------");
+ try {
+ ObjectName on1 = ObjectName.getInstance(negativeTests[i][0]);
+ ObjectName on2 = ObjectName.getInstance(negativeTests[i][1]);
+ System.out.println("\"" + on1 + "\".apply(\"" + on2 + "\")");
+ boolean result = on1.apply(on2);
+ System.out.println("Result = " + result);
+ if (result == true) {
+ error++;
+ System.out.println("Test failed!");
+ } else {
+ System.out.println("Test passed!");
+ }
+ } catch (Exception e) {
+ error++;
+ System.out.println("Got Unexpected Exception = " + e.toString());
+ System.out.println("Test failed!");
+ }
+ System.out.println("----------------------------------------------");
+ }
+ return error;
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ int error = 0;
+
+ // Check null values
+ //
+ System.out.println("----------------------------------------------");
+ System.out.println("Test ObjectName.apply(null)");
+ try {
+ new ObjectName("d:k=v").apply(null);
+ error++;
+ System.out.println("Didn't get expected NullPointerException!");
+ System.out.println("Test failed!");
+ } catch (NullPointerException e) {
+ System.out.println("Got expected exception '" + e.toString() + "'");
+ System.out.println("Test passed!");
+ } catch (Exception e) {
+ error++;
+ System.out.println("Got unexpected exception '" + e.toString() + "'");
+ System.out.println("Test failed!");
+ }
+ System.out.println("----------------------------------------------");
+
+ // Check domain pattern values
+ //
+ System.out.println("----------------------------------------------");
+ System.out.println("Test ObjectName.apply(domain_pattern)");
+ try {
+ if (new ObjectName("d:k=v").apply(new ObjectName("*:k=v"))) {
+ error++;
+ System.out.println("Got 'true' expecting 'false'");
+ System.out.println("Test failed!");
+ } else {
+ System.out.println("Got expected return value 'false'");
+ System.out.println("Test passed!");
+ }
+ } catch (Exception e) {
+ error++;
+ System.out.println("Got unexpected exception = " + e.toString());
+ System.out.println("Test failed!");
+ }
+ System.out.println("----------------------------------------------");
+
+ // Check key property list pattern values
+ //
+ System.out.println("----------------------------------------------");
+ System.out.println("Test ObjectName.apply(key_property_list_pattern)");
+ try {
+ if (new ObjectName("d:k=v").apply(new ObjectName("d:k=v,*"))) {
+ error++;
+ System.out.println("Got 'true' expecting 'false'");
+ System.out.println("Test failed!");
+ } else {
+ System.out.println("Got expected return value 'false'");
+ System.out.println("Test passed!");
+ }
+ } catch (Exception e) {
+ error++;
+ System.out.println("Got unexpected exception = " + e.toString());
+ System.out.println("Test failed!");
+ }
+ System.out.println("----------------------------------------------");
+
+ // Check key property value pattern values
+ //
+ System.out.println("----------------------------------------------");
+ System.out.println("Test ObjectName.apply(key_property_value_pattern)");
+ try {
+ if (new ObjectName("d:k=v").apply(new ObjectName("d:k=*"))) {
+ error++;
+ System.out.println("Got 'true' expecting 'false'");
+ System.out.println("Test failed!");
+ } else {
+ System.out.println("Got expected return value 'false'");
+ System.out.println("Test passed!");
+ }
+ } catch (Exception e) {
+ error++;
+ System.out.println("Got unexpected exception = " + e.toString());
+ System.out.println("Test failed!");
+ }
+ System.out.println("----------------------------------------------");
+
+ error += runPositiveTests();
+ error += runNegativeTests();
+
+ if (error > 0) {
+ final String msg = "Test FAILED! Got " + error + " error(s)";
+ System.out.println(msg);
+ throw new IllegalArgumentException(msg);
+ } else {
+ System.out.println("Test PASSED!");
+ }
+ }
+}
diff --git a/test/javax/management/ObjectName/ComparatorTest.java b/test/javax/management/ObjectName/ComparatorTest.java
new file mode 100644
index 0000000..6f73c3a
--- /dev/null
+++ b/test/javax/management/ObjectName/ComparatorTest.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5036680
+ * @summary Test the ObjectName.compareTo() method.
+ * @author Luis-Miguel Alventosa
+ * @run clean ComparatorTest
+ * @run build ComparatorTest
+ * @run main ComparatorTest
+ */
+
+import javax.management.*;
+
+public class ComparatorTest {
+
+ private static final char LT = '<';
+ private static final char EQ = '=';
+ private static final char GT = '>';
+
+ private static final String tests[][] = {
+ //
+ // domains
+ //
+ { String.valueOf(LT), ":k1=v1", "d:k1=v1" },
+ { String.valueOf(EQ), "d:k1=v1", "d:k1=v1" },
+ { String.valueOf(GT), "d2:k1=v1", "d1:k1=v1" },
+ //
+ // "type=" key property
+ //
+ { String.valueOf(GT), "d:type=a,k1=v1", "d:k1=v1" },
+ { String.valueOf(GT), "d:type=a,k1=v1", "d:type=" },
+ { String.valueOf(GT), "d:type=a,k1=v1", "d:type=,k1=v1" },
+ { String.valueOf(LT), "d:type=a,k1=v1", "d:type=b,k1=v1" },
+ { String.valueOf(LT), "d:type=a,k2=v2", "d:type=b,k1=v1" },
+ //
+ // canonical form
+ //
+ { String.valueOf(EQ), "d:k1=v1,k2=v2", "d:k2=v2,k1=v1" },
+ { String.valueOf(LT), "d:k1=v1,k2=v2", "d:k1=v1,k3=v3" },
+ { String.valueOf(LT), "d:k1=v1,k2=v2", "d:k2=v2,k1=v1,k3=v3" },
+ //
+ // wildcards
+ //
+ { String.valueOf(LT), "d:k1=v1", "d:k1=v1,*" },
+ { String.valueOf(GT), "d:k1=v1,k2=v2", "d:k1=v1,*" },
+ { String.valueOf(GT), "domain:k1=v1", "?:k1=v1" },
+ { String.valueOf(GT), "domain:k1=v1", "*:k1=v1" },
+ { String.valueOf(GT), "domain:k1=v1", "domai?:k1=v1" },
+ { String.valueOf(GT), "domain:k1=v1", "domai*:k1=v1" },
+ { String.valueOf(GT), "domain:k1=v1", "do?ain:k1=v1" },
+ { String.valueOf(GT), "domain:k1=v1", "do*ain:k1=v1" },
+ };
+
+ private static boolean compare(char comparator, String on1, String on2) {
+ boolean ok = false;
+ System.out.println("Test " + on1 + " " + comparator + " " + on2);
+ try {
+ ObjectName o1 = ObjectName.getInstance(on1);
+ ObjectName o2 = ObjectName.getInstance(on2);
+ int result = o1.compareTo(o2);
+ switch (comparator) {
+ case LT:
+ if (result < 0)
+ ok = true;
+ break;
+ case EQ:
+ if (result == 0)
+ ok = true;
+ break;
+ case GT:
+ if (result > 0)
+ ok = true;
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "Test incorrect: case: " + comparator);
+ }
+ } catch (Exception e) {
+ ok = false;
+ System.out.println("Got Unexpected Exception = " + e.toString());
+ }
+ return ok;
+ }
+
+ private static boolean lessThan(String on1, String on2) {
+ return compare(LT, on1, on2);
+ }
+
+ private static boolean equalTo(String on1, String on2) {
+ return compare(EQ, on1, on2);
+ }
+
+ private static boolean greaterThan(String on1, String on2) {
+ return compare(GT, on1, on2);
+ }
+
+ private static int runTest(char comparator, String on1, String on2) {
+ System.out.println("----------------------------------------------");
+ boolean ok = false;
+ boolean lt = lessThan(on1, on2);
+ boolean eq = equalTo(on1, on2);
+ boolean gt = greaterThan(on1, on2);
+ switch (comparator) {
+ case LT:
+ ok = lt && !eq && !gt;
+ System.out.println("Comparison result: LessThan");
+ break;
+ case EQ:
+ ok = !lt && eq && !gt;
+ System.out.println("Comparison result: EqualTo");
+ break;
+ case GT:
+ ok = !lt && !eq && gt;
+ System.out.println("Comparison result: GreaterThan");
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "Test incorrect: case: " + comparator);
+ }
+ if (ok)
+ System.out.println("Test passed!");
+ else
+ System.out.println("Test failed!");
+ System.out.println("----------------------------------------------");
+ return ok ? 0 : 1;
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ int error = 0;
+
+ // Check null values
+ //
+ System.out.println("----------------------------------------------");
+ System.out.println("Test ObjectName.compareTo(null)");
+ try {
+ new ObjectName("d:k=v").compareTo(null);
+ error++;
+ System.out.println("Didn't get expected NullPointerException!");
+ System.out.println("Test failed!");
+ } catch (NullPointerException e) {
+ System.out.println("Got expected exception = " + e.toString());
+ System.out.println("Test passed!");
+ } catch (Exception e) {
+ error++;
+ System.out.println("Got unexpected exception = " + e.toString());
+ System.out.println("Test failed!");
+ }
+ System.out.println("----------------------------------------------");
+
+ // Compare ObjectNames
+ //
+ for (int i = 0; i < tests.length; i++)
+ error += runTest(tests[i][0].charAt(0), tests[i][1], tests[i][2]);
+
+ if (error > 0) {
+ final String msg = "Test FAILED! Got " + error + " error(s)";
+ System.out.println(msg);
+ throw new IllegalArgumentException(msg);
+ } else {
+ System.out.println("Test PASSED!");
+ }
+ }
+}
diff --git a/test/javax/management/ObjectName/DelegateNameWildcardNameTest.java b/test/javax/management/ObjectName/DelegateNameWildcardNameTest.java
new file mode 100644
index 0000000..b2ff04d
--- /dev/null
+++ b/test/javax/management/ObjectName/DelegateNameWildcardNameTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4780400
+ * @summary Test that MBeanServerDelegate.DELEGATE_NAME and ObjectName.WILDCARD
+ * public constants have been initialized properly.
+ * @author Luis-Miguel Alventosa
+ * @run clean DelegateNameWildcardNameTest
+ * @run build DelegateNameWildcardNameTest
+ * @run main DelegateNameWildcardNameTest
+ */
+
+import javax.management.MBeanServerDelegate;
+import javax.management.ObjectName;
+
+public class DelegateNameWildcardNameTest {
+
+ public static void main(String[] args) throws Exception {
+
+ System.out.println(
+ "Test that <MBeanServerDelegate.DELEGATE_NAME> equals " +
+ "<new ObjectName(\"JMImplementation:type=MBeanServerDelegate\")>");
+ final ObjectName delegateName =
+ new ObjectName("JMImplementation:type=MBeanServerDelegate");
+ if (!delegateName.equals(MBeanServerDelegate.DELEGATE_NAME))
+ throw new AssertionError("Unexpected value: " +
+ "MBeanServerDelegate.DELEGATE_NAME = " +
+ MBeanServerDelegate.DELEGATE_NAME);
+ System.out.println("MBeanServerDelegate.DELEGATE_NAME = " +
+ "new ObjectName(\"" + delegateName + "\")");
+
+ System.out.println("Test that <ObjectName.WILDCARD> " +
+ "equals <new ObjectName(\"*:*\")>");
+ final ObjectName wildcardName = new ObjectName("*:*");
+ if (!wildcardName.equals(ObjectName.WILDCARD))
+ throw new AssertionError("Unexpected value: " +
+ "ObjectName.WILDCARD = " +
+ ObjectName.WILDCARD);
+ System.out.println("ObjectName.WILDCARD = " +
+ "new ObjectName(\"" + wildcardName + "\")");
+
+ System.out.println("Test passes: constants were initialized properly");
+ }
+}
diff --git a/test/javax/management/ObjectName/NullEmptyKeyValueTest.java b/test/javax/management/ObjectName/NullEmptyKeyValueTest.java
new file mode 100644
index 0000000..32a732f
--- /dev/null
+++ b/test/javax/management/ObjectName/NullEmptyKeyValueTest.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6229396
+ * @summary Test null/empty key/values in ObjectName constructors.
+ * @author Luis-Miguel Alventosa
+ * @run clean NullEmptyKeyValueTest
+ * @run build NullEmptyKeyValueTest
+ * @run main NullEmptyKeyValueTest
+ */
+
+import java.util.*;
+import javax.management.*;
+
+public class NullEmptyKeyValueTest {
+
+ private static int createObjectName(int i,
+ Class c,
+ String s,
+ String d,
+ String k,
+ String v,
+ Hashtable<String,String> t)
+ throws Exception {
+
+ System.out.println("----------------------------------------------");
+ switch (i) {
+ case 1:
+ System.out.println("ObjectName = " + s);
+ break;
+ case 2:
+ System.out.println("ObjectName.Domain = " + d);
+ System.out.println("ObjectName.Key = " + k);
+ System.out.println("ObjectName.Value = " + v);
+ break;
+ case 3:
+ System.out.println("ObjectName.Domain = " + d);
+ System.out.println("ObjectName.Hashtable = " + t);
+ break;
+ default:
+ throw new Exception("Test incorrect: case: " + i);
+ }
+ int error = 0;
+ ObjectName on = null;
+ try {
+ switch (i) {
+ case 1:
+ on = new ObjectName(s);
+ break;
+ case 2:
+ on = new ObjectName(d, k, v);
+ break;
+ case 3:
+ on = new ObjectName(d, t);
+ break;
+ default:
+ throw new Exception("Test incorrect: case: " + i);
+ }
+ if (c != null) {
+ error++;
+ System.out.println("Got Unexpected ObjectName = " +
+ (on == null ? "null" : on.getCanonicalName()));
+ } else {
+ System.out.println("Got Expected ObjectName = " +
+ (on == null ? "null" : on.getCanonicalName()));
+ }
+ } catch (Exception e) {
+ if (c == null || !c.isInstance(e)) {
+ error++;
+ System.out.println("Got Unexpected Exception = " +
+ e.toString());
+ } else {
+ System.out.println("Got Expected Exception = " +
+ e.toString());
+ }
+ }
+ System.out.println("----------------------------------------------");
+ return error;
+ }
+
+ private static int createObjectName1(Class c,
+ String s)
+ throws Exception {
+ return createObjectName(1, c, s, null, null, null, null);
+ }
+
+ private static int createObjectName2(Class c,
+ String d,
+ String k,
+ String v)
+ throws Exception {
+ return createObjectName(2, c, null, d, k, v, null);
+ }
+
+ private static int createObjectName3(Class c,
+ String d,
+ Hashtable<String,String> t)
+ throws Exception {
+ return createObjectName(3, c, null, d, null, null, t);
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ final Class npec = NullPointerException.class;
+ final Class monec = MalformedObjectNameException.class;
+
+ int error = 0;
+
+ error += createObjectName1(npec, null);
+ error += createObjectName1(null, "d:k=v");
+ error += createObjectName1(null, ":k=v");
+ error += createObjectName1(monec, "d:=v");
+ error += createObjectName1(null, "d:k=");
+ error += createObjectName1(null, "d:k1=,k2=v2");
+ error += createObjectName1(null, "d:k1=v1,k2=");
+
+ error += createObjectName2(npec, null, null, null);
+ error += createObjectName2(null, "d", "k", "v");
+ error += createObjectName2(npec, null, "k", "v");
+ error += createObjectName2(null, "", "k", "v");
+ error += createObjectName2(npec, "d", null, "v");
+ error += createObjectName2(monec, "d", "", "v");
+ error += createObjectName2(npec, "d", "k", null);
+ error += createObjectName2(null, "d", "k", "");
+
+ Hashtable<String,String> h1 = new Hashtable<String,String>();
+ h1.put("k", "v");
+ Hashtable<String,String> h2 = new Hashtable<String,String>();
+ h2.put("", "v");
+ Hashtable<String,String> h3 = new Hashtable<String,String>();
+ h3.put("k", "");
+ Hashtable<String,String> h4 = new Hashtable<String,String>();
+ h4.put("k1", "");
+ h4.put("k2", "v2");
+ Hashtable<String,String> h5 = new Hashtable<String,String>();
+ h5.put("k1", "v1");
+ h5.put("k2", "");
+ error += createObjectName3(npec, null, null);
+ error += createObjectName3(null, "d", h1);
+ error += createObjectName3(npec, null, h1);
+ error += createObjectName3(null, "", h1);
+ error += createObjectName3(monec, "d", h2);
+ error += createObjectName3(null, "d", h3);
+ error += createObjectName3(null, "d", h4);
+ error += createObjectName3(null, "d", h5);
+
+ if (error > 0) {
+ final String msg = "Test FAILED! Got " + error + " error(s)";
+ System.out.println(msg);
+ throw new IllegalArgumentException(msg);
+ } else {
+ System.out.println("Test PASSED!");
+ }
+ }
+}
diff --git a/test/javax/management/ObjectName/ObjectNameGetInstanceTest.java b/test/javax/management/ObjectName/ObjectNameGetInstanceTest.java
new file mode 100644
index 0000000..1f49925
--- /dev/null
+++ b/test/javax/management/ObjectName/ObjectNameGetInstanceTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4894801
+ * @summary Test that ObjectName.getInstance(ObjectName) preserves key order
+ * @author Eamonn McManus
+ * @run clean ObjectNameGetInstanceTest
+ * @run build ObjectNameGetInstanceTest
+ * @run main ObjectNameGetInstanceTest
+ */
+
+import javax.management.*;
+
+public class ObjectNameGetInstanceTest {
+ public static void main(String[] args) throws Exception {
+ System.out.println("Test that ObjectName.getInstance(ObjectName) " +
+ "preserves the order of keys in its input");
+
+ final String nonCanonical = "d:x=y,a=b";
+ ObjectName nice = new ObjectName(nonCanonical);
+
+ // Check that we are in fact using an ObjectName whose canonical
+ // form is not the same as the input
+ if (nice.getCanonicalName().equals(nonCanonical)) {
+ System.err.println("TEST IS BROKEN: INPUT ALREADY CANONICAL");
+ System.exit(1);
+ }
+
+ ObjectName evil = new EvilObjectName(nonCanonical);
+ ObjectName unEvil = ObjectName.getInstance(evil);
+ if (unEvil instanceof EvilObjectName) {
+ System.err.println("FAILS: getInstance did not banish evil");
+ System.exit(1);
+ }
+
+ if (nice.equals(unEvil))
+ System.out.println("Test passes: original key order preserved");
+ else {
+ System.out.println("FAILS: key order changed");
+ System.exit(1);
+ }
+ }
+
+ public static class EvilObjectName extends ObjectName {
+ public EvilObjectName(String s) throws MalformedObjectNameException {
+ super(s);
+ }
+
+ public String getCanonicalName() {
+ return "bogus:canonical=name";
+ }
+ }
+}
diff --git a/test/javax/management/ObjectName/RepositoryWildcardTest.java b/test/javax/management/ObjectName/RepositoryWildcardTest.java
new file mode 100644
index 0000000..a021fb4
--- /dev/null
+++ b/test/javax/management/ObjectName/RepositoryWildcardTest.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4716807
+ * @summary Test if the repository supports correctly the use of
+ * wildcards in the ObjectName key properties value part.
+ * @author Luis-Miguel Alventosa
+ * @run clean RepositoryWildcardTest
+ * @run build RepositoryWildcardTest
+ * @run main RepositoryWildcardTest
+ */
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.TreeSet;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerDelegate;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectName;
+import javax.management.RuntimeOperationsException;
+
+public class RepositoryWildcardTest {
+
+ private static final String classname =
+ "javax.management.monitor.StringMonitor";
+
+ private static int mbeanCreation(MBeanServer mbs, String name)
+ throws Exception {
+ int error = 0;
+ try {
+ System.out.println("Test: createMBean(" + name + ")");
+ mbs.createMBean(classname, ObjectName.getInstance(name));
+ error++;
+ System.out.println("Didn't get expected exception!");
+ System.out.println("Test failed!");
+ } catch (RuntimeOperationsException e) {
+ System.out.println("Got expected exception = " +
+ e.getCause().toString());
+ System.out.println("Test passed!");
+ }
+ return error;
+ }
+
+ private static int mbeanDeletion(MBeanServer mbs, String name)
+ throws Exception {
+ int error = 0;
+ try {
+ System.out.println("Test: unregisterMBean(" + name + ")");
+ mbs.unregisterMBean(ObjectName.getInstance(name));
+ error++;
+ System.out.println("Didn't get expected exception!");
+ System.out.println("Test failed!");
+ } catch (InstanceNotFoundException e) {
+ System.out.println("Got expected exception = " + e.toString());
+ System.out.println("Test passed!");
+ }
+ return error;
+ }
+
+ private static int mbeanQuery(MBeanServer mbs,
+ String name,
+ Set<ObjectName> expectedSet)
+ throws Exception {
+ int error = 0;
+ System.out.println("Test: queryNames(" + name + ")");
+ Set<ObjectName> returnedSet =
+ mbs.queryNames(ObjectName.getInstance(name), null);
+ System.out.println("ReturnedSet = " + new TreeSet(returnedSet));
+ System.out.println("ExpectedSet = " + new TreeSet(expectedSet));
+ if (returnedSet.equals(expectedSet)) {
+ System.out.println("Test passed!");
+ } else {
+ error++;
+ System.out.println("Test failed!");
+ }
+ return error;
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ int error = 0;
+
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+
+ ObjectName[] namesArray = {
+ ObjectName.getInstance("d:k=abc"),
+ ObjectName.getInstance("d:k=abcd"),
+ ObjectName.getInstance("d:k=abcde"),
+ ObjectName.getInstance("d:k=abc,k2=v2"),
+ ObjectName.getInstance("d:k=abcd,k2=v2"),
+ ObjectName.getInstance("d:k=abcde,k2=v2"),
+ ObjectName.getInstance("d:k=\"abc\""),
+ ObjectName.getInstance("d:k=\"abc\",k2=v2"),
+ ObjectName.getInstance("d:p1=v1,p2=v2,p3=v3,p4=v4,p5=v5,p6=v6," +
+ "p7=v7,p8=v8,p9=v9,p10=v10,p11=v11,p12=v12")
+ };
+
+ for (ObjectName name : namesArray)
+ mbs.createMBean(classname, name);
+
+ System.out.println("----------------------------------------------");
+ System.out.println("TEST createMBean WITH PATTERNS");
+ System.out.println("----------------------------------------------");
+
+ error += mbeanCreation(mbs, "d:k=v,*");
+ error += mbeanCreation(mbs, "d:k=*");
+ error += mbeanCreation(mbs, "d:k=a?b");
+ error += mbeanCreation(mbs, "d:k=\"?\"");
+ error += mbeanCreation(mbs, "d:k=\"a*b\"");
+
+ System.out.println("----------------------------------------------");
+ System.out.println("TEST queryNames WITH PATTERNS");
+ System.out.println("----------------------------------------------");
+
+ Set<ObjectName> expectedSet = new HashSet<ObjectName>();
+ for (ObjectName name : namesArray)
+ expectedSet.add(name);
+ expectedSet.add(MBeanServerDelegate.DELEGATE_NAME);
+ Set<ObjectName> returnedSet =
+ mbs.queryNames(ObjectName.getInstance("*:*"), null);
+ error += mbeanQuery(mbs, "*:*", expectedSet);
+
+ expectedSet = new HashSet<ObjectName>();
+ for (ObjectName name : namesArray)
+ expectedSet.add(name);
+ error += mbeanQuery(mbs, "d:*", expectedSet);
+
+ expectedSet = new HashSet<ObjectName>();
+ expectedSet.add(namesArray[0]);
+ expectedSet.add(namesArray[1]);
+ expectedSet.add(namesArray[2]);
+ expectedSet.add(namesArray[6]);
+ error += mbeanQuery(mbs, "d:k=*", expectedSet);
+
+ expectedSet = new HashSet<ObjectName>();
+ expectedSet.add(namesArray[3]);
+ expectedSet.add(namesArray[4]);
+ expectedSet.add(namesArray[5]);
+ expectedSet.add(namesArray[7]);
+ error += mbeanQuery(mbs, "d:k=*,k2=v2", expectedSet);
+
+ expectedSet = new HashSet<ObjectName>();
+ expectedSet.add(namesArray[3]);
+ expectedSet.add(namesArray[4]);
+ expectedSet.add(namesArray[5]);
+ expectedSet.add(namesArray[7]);
+ error += mbeanQuery(mbs, "d:k=*,k2=v?", expectedSet);
+
+ expectedSet = new HashSet<ObjectName>();
+ expectedSet.add(namesArray[3]);
+ expectedSet.add(namesArray[4]);
+ expectedSet.add(namesArray[5]);
+ expectedSet.add(namesArray[7]);
+ error += mbeanQuery(mbs, "d:*,k2=v2", expectedSet);
+
+ expectedSet = new HashSet<ObjectName>();
+ expectedSet.add(namesArray[1]);
+ error += mbeanQuery(mbs, "d:k=ab?d", expectedSet);
+
+ expectedSet = new HashSet<ObjectName>();
+ expectedSet.add(namesArray[1]);
+ expectedSet.add(namesArray[4]);
+ error += mbeanQuery(mbs, "d:k=ab?d,*", expectedSet);
+
+ expectedSet = new HashSet<ObjectName>();
+ expectedSet.add(namesArray[6]);
+ error += mbeanQuery(mbs, "d:k=\"*\"", expectedSet);
+
+ expectedSet = new HashSet<ObjectName>();
+ expectedSet.add(namesArray[7]);
+ error += mbeanQuery(mbs, "d:k=\"*\",k2=v?", expectedSet);
+
+ expectedSet = new HashSet<ObjectName>();
+ expectedSet.add(namesArray[8]);
+ error += mbeanQuery(mbs,
+ "d:p1=v?,p2=v?,p3=v?,p4=v?,p5=v?,p6=v?," +
+ "p7=v?,p8=v?,p9=v?,p10=v??,p11=v??,p12=v??",
+ expectedSet);
+
+ System.out.println("----------------------------------------------");
+ System.out.println("TEST unregisterMBean WITH PATTERNS");
+ System.out.println("----------------------------------------------");
+
+ error += mbeanDeletion(mbs, "d:k=*");
+ error += mbeanDeletion(mbs, "d:k=\"*\"");
+
+ if (error > 0) {
+ final String msg = "Test FAILED! Got " + error + " error(s)";
+ System.out.println(msg);
+ throw new IllegalArgumentException(msg);
+ } else {
+ System.out.println("Test PASSED!");
+ }
+ }
+}
diff --git a/test/javax/management/ObjectName/SerialCompatTest.java b/test/javax/management/ObjectName/SerialCompatTest.java
new file mode 100644
index 0000000..baa748a
--- /dev/null
+++ b/test/javax/management/ObjectName/SerialCompatTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2004-2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6211220
+ * @summary Test that jmx.serial.form=1.0 works for ObjectName
+ * @author Eamonn McManus
+ * @run clean SerialCompatTest
+ * @run build SerialCompatTest
+ * @run main/othervm SerialCompatTest
+ */
+
+import java.io.*;
+import java.util.*;
+import javax.management.ObjectName;
+
+public class SerialCompatTest {
+ public static void main(String[] args) throws Exception {
+ System.setProperty("jmx.serial.form", "1.0");
+
+ /* Check that we really are in jmx.serial.form=1.0 mode.
+ The property is frozen the first time the ObjectName class
+ is referenced so checking that it is set to the correct
+ value now is not enough. */
+ ObjectStreamClass osc = ObjectStreamClass.lookup(ObjectName.class);
+ if (osc.getFields().length != 6) {
+ throw new Exception("Not using old serial form: fields: " +
+ Arrays.asList(osc.getFields()));
+ // new serial form has no fields, uses writeObject
+ }
+
+ ObjectName on = new ObjectName("a:b=c");
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(bos);
+ oos.writeObject(on);
+ oos.close();
+ byte[] bytes = bos.toByteArray();
+ ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
+ ObjectInputStream ois = new ObjectInputStream(bis);
+ ObjectName on1 = (ObjectName) ois.readObject();
+
+ // if the bug is present, these will get NullPointerException
+ for (int i = 0; i <= 11; i++) {
+ try {
+ switch (i) {
+ case 0:
+ check(on1.getDomain().equals("a")); break;
+ case 1:
+ check(on1.getCanonicalName().equals("a:b=c")); break;
+ case 2:
+ check(on1.getKeyPropertyListString().equals("b=c")); break;
+ case 3:
+ check(on1.getCanonicalKeyPropertyListString().equals("b=c"));
+ break;
+ case 4:
+ check(on1.getKeyProperty("b").equals("c")); break;
+ case 5:
+ check(on1.getKeyPropertyList()
+ .equals(Collections.singletonMap("b", "c"))); break;
+ case 6:
+ check(!on1.isDomainPattern()); break;
+ case 7:
+ check(!on1.isPattern()); break;
+ case 8:
+ check(!on1.isPropertyPattern()); break;
+ case 9:
+ check(on1.equals(on)); break;
+ case 10:
+ check(on.equals(on1)); break;
+ case 11:
+ check(on1.apply(on)); break;
+ default:
+ throw new Exception("Test incorrect: case: " + i);
+ }
+ } catch (Exception e) {
+ System.out.println("Test failed with exception:");
+ e.printStackTrace(System.out);
+ failed = true;
+ }
+ }
+
+ if (failed)
+ throw new Exception("Some tests failed");
+ else
+ System.out.println("All tests passed");
+ }
+
+ private static void check(boolean condition) {
+ if (!condition) {
+ new Throwable("Test failed").printStackTrace(System.out);
+ failed = true;
+ }
+ }
+
+ private static boolean failed;
+}
diff --git a/test/javax/management/ObjectName/ValueWildcardTest.java b/test/javax/management/ObjectName/ValueWildcardTest.java
new file mode 100644
index 0000000..95ff14a
--- /dev/null
+++ b/test/javax/management/ObjectName/ValueWildcardTest.java
@@ -0,0 +1,286 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4716807
+ * @summary Test wildcards in ObjectName key properties value part.
+ * @author Luis-Miguel Alventosa
+ * @run clean ValueWildcardTest
+ * @run build ValueWildcardTest
+ * @run main ValueWildcardTest
+ */
+
+import java.util.Hashtable;
+import javax.management.ObjectName;
+
+public class ValueWildcardTest {
+
+ private static int createObjectName(int i,
+ String s,
+ String d,
+ String k,
+ String v,
+ Hashtable<String,String> t,
+ boolean plp,
+ boolean pvp)
+ throws Exception {
+
+ System.out.println("----------------------------------------------");
+ switch (i) {
+ case 1:
+ System.out.println("ObjectName = " + s);
+ break;
+ case 2:
+ System.out.println("ObjectName.Domain = " + d);
+ System.out.println("ObjectName.Key = " + k);
+ System.out.println("ObjectName.Value = " + v);
+ break;
+ case 3:
+ System.out.println("ObjectName.Domain = " + d);
+ System.out.println("ObjectName.Hashtable = " + t);
+ break;
+ default:
+ throw new Exception("Test incorrect: case: " + i);
+ }
+ int error = 0;
+ ObjectName on = null;
+ try {
+ switch (i) {
+ case 1:
+ on = new ObjectName(s);
+ break;
+ case 2:
+ on = new ObjectName(d, k, v);
+ break;
+ case 3:
+ on = new ObjectName(d, t);
+ break;
+ default:
+ throw new Exception("Test incorrect: case: " + i);
+ }
+ System.out.println("Got Expected ObjectName = " +
+ on.getCanonicalName());
+ boolean isPattern = on.isPattern();
+ boolean isDomainPattern = on.isDomainPattern();
+ boolean isPropertyPattern = on.isPropertyPattern();
+ boolean isPropertyListPattern = on.isPropertyListPattern();
+ boolean isPropertyValuePattern = on.isPropertyValuePattern();
+ System.out.println("ObjectName.isPattern = " +
+ isPattern);
+ System.out.println("ObjectName.isDomainPattern = " +
+ isDomainPattern);
+ System.out.println("ObjectName.isPropertyPattern = " +
+ isPropertyPattern);
+ System.out.println("ObjectName.isPropertyListPattern = " +
+ isPropertyListPattern);
+ System.out.println("ObjectName.isPropertyValuePattern = " +
+ isPropertyValuePattern);
+ int error2 = 0;
+ if (isDomainPattern) {
+ error2++;
+ System.out.println("Error: Shouldn't be domain pattern!");
+ }
+ if (!plp && isPropertyListPattern) {
+ error2++;
+ System.out.println("Error: Shouldn't be property list pattern!");
+ }
+ if (!pvp && isPropertyValuePattern) {
+ error2++;
+ System.out.println("Error: Shouldn't be property value pattern!");
+ }
+ if (plp &&
+ !isPattern && !isPropertyPattern && !isPropertyListPattern) {
+ error2++;
+ System.out.println("Error: Should be property list pattern!");
+ }
+ if (pvp &&
+ !isPattern && !isPropertyPattern && !isPropertyValuePattern) {
+ error2++;
+ System.out.println("Error: Should be property value pattern!");
+ }
+ if (error2 > 0) {
+ error++;
+ System.out.println("Test failed!");
+ } else {
+ System.out.println("Test passed!");
+ }
+ } catch (Exception e) {
+ error++;
+ System.out.println("Got Unexpected Exception = " + e.toString());
+ }
+ System.out.println("----------------------------------------------");
+ return error;
+ }
+
+ private static int createObjectName1(String s,
+ boolean plp,
+ boolean pvp)
+ throws Exception {
+ return createObjectName(1, s, null, null, null, null, plp, pvp);
+ }
+
+ private static int createObjectName2(String d,
+ String k,
+ String v,
+ boolean plp,
+ boolean pvp)
+ throws Exception {
+ return createObjectName(2, null, d, k, v, null, plp, pvp);
+ }
+
+ private static int createObjectName3(String d,
+ Hashtable<String,String> t,
+ boolean plp,
+ boolean pvp)
+ throws Exception {
+ return createObjectName(3, null, d, null, null, t, plp, pvp);
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ int error = 0;
+
+ error += createObjectName1("d:k=*", false, true);
+ error += createObjectName1("d:k=a*b", false, true);
+ error += createObjectName1("d:k=a*b,*", true, true);
+ error += createObjectName1("d:*,k=a*b", true, true);
+
+ error += createObjectName1("d:k=?", false, true);
+ error += createObjectName1("d:k=a?b", false, true);
+ error += createObjectName1("d:k=a?b,*", true, true);
+ error += createObjectName1("d:*,k=a?b", true, true);
+
+ error += createObjectName1("d:k=?*", false, true);
+ error += createObjectName1("d:k=a?bc*d", false, true);
+ error += createObjectName1("d:k=a?bc*d,*", true, true);
+ error += createObjectName1("d:*,k=a?bc*d", true, true);
+
+ error += createObjectName1("d:k1=?,k2=*", false, true);
+ error += createObjectName1("d:k1=a?b,k2=c*d", false, true);
+ error += createObjectName1("d:k1=a?b,k2=c*d,*", true, true);
+ error += createObjectName1("d:*,k1=a?b,k2=c*d", true, true);
+
+ error += createObjectName1("d:k=\"*\"", false, true);
+ error += createObjectName1("d:k=\"a*b\"", false, true);
+ error += createObjectName1("d:k=\"a*b\",*", true, true);
+ error += createObjectName1("d:*,k=\"a*b\"", true, true);
+
+ error += createObjectName1("d:k=\"?\"", false, true);
+ error += createObjectName1("d:k=\"a?b\"", false, true);
+ error += createObjectName1("d:k=\"a?b\",*", true, true);
+ error += createObjectName1("d:*,k=\"a?b\"", true, true);
+
+ error += createObjectName1("d:k=\"?*\"", false, true);
+ error += createObjectName1("d:k=\"a?bc*d\"", false, true);
+ error += createObjectName1("d:k=\"a?bc*d\",*", true, true);
+ error += createObjectName1("d:*,k=\"a?bc*d\"", true, true);
+
+ error += createObjectName1("d:k1=\"?\",k2=\"*\"", false, true);
+ error += createObjectName1("d:k1=\"a?b\",k2=\"c*d\"", false, true);
+ error += createObjectName1("d:k1=\"a?b\",k2=\"c*d\",*", true, true);
+ error += createObjectName1("d:*,k1=\"a?b\",k2=\"c*d\"", true, true);
+
+ error += createObjectName2("d", "k", "*", false, true);
+ error += createObjectName2("d", "k", "a*b", false, true);
+ error += createObjectName2("d", "k", "?", false, true);
+ error += createObjectName2("d", "k", "a?b", false, true);
+ error += createObjectName2("d", "k", "?*", false, true);
+ error += createObjectName2("d", "k", "a?bc*d", false, true);
+
+ error += createObjectName2("d", "k", "\"*\"", false, true);
+ error += createObjectName2("d", "k", "\"a*b\"", false, true);
+ error += createObjectName2("d", "k", "\"?\"", false, true);
+ error += createObjectName2("d", "k", "\"a?b\"", false, true);
+ error += createObjectName2("d", "k", "\"?*\"", false, true);
+ error += createObjectName2("d", "k", "\"a?bc*d\"", false, true);
+
+ Hashtable<String,String> h1 = new Hashtable<String,String>();
+ h1.put("k", "*");
+ error += createObjectName3("d", h1, false, true);
+ Hashtable<String,String> h2 = new Hashtable<String,String>();
+ h2.put("k", "a*b");
+ error += createObjectName3("d", h2, false, true);
+
+ Hashtable<String,String> h3 = new Hashtable<String,String>();
+ h3.put("k", "?");
+ error += createObjectName3("d", h3, false, true);
+ Hashtable<String,String> h4 = new Hashtable<String,String>();
+ h4.put("k", "a?b");
+ error += createObjectName3("d", h4, false, true);
+
+ Hashtable<String,String> h5 = new Hashtable<String,String>();
+ h5.put("k", "?*");
+ error += createObjectName3("d", h5, false, true);
+ Hashtable<String,String> h6 = new Hashtable<String,String>();
+ h6.put("k", "a?bc*d");
+ error += createObjectName3("d", h6, false, true);
+
+ Hashtable<String,String> h7 = new Hashtable<String,String>();
+ h7.put("k1", "?");
+ h7.put("k2", "*");
+ error += createObjectName3("d", h7, false, true);
+ Hashtable<String,String> h8 = new Hashtable<String,String>();
+ h8.put("k1", "a?b");
+ h8.put("k2", "c*d");
+ error += createObjectName3("d", h8, false, true);
+
+ Hashtable<String,String> h9 = new Hashtable<String,String>();
+ h9.put("k", "\"*\"");
+ error += createObjectName3("d", h9, false, true);
+ Hashtable<String,String> h10 = new Hashtable<String,String>();
+ h10.put("k", "\"a*b\"");
+ error += createObjectName3("d", h10, false, true);
+
+ Hashtable<String,String> h11 = new Hashtable<String,String>();
+ h11.put("k", "\"?\"");
+ error += createObjectName3("d", h11, false, true);
+ Hashtable<String,String> h12 = new Hashtable<String,String>();
+ h12.put("k", "\"a?b\"");
+ error += createObjectName3("d", h12, false, true);
+
+ Hashtable<String,String> h13 = new Hashtable<String,String>();
+ h13.put("k", "\"?*\"");
+ error += createObjectName3("d", h13, false, true);
+ Hashtable<String,String> h14 = new Hashtable<String,String>();
+ h14.put("k", "\"a?bc*d\"");
+ error += createObjectName3("d", h14, false, true);
+
+ Hashtable<String,String> h15 = new Hashtable<String,String>();
+ h15.put("k1", "\"?\"");
+ h15.put("k2", "\"*\"");
+ error += createObjectName3("d", h15, false, true);
+ Hashtable<String,String> h16 = new Hashtable<String,String>();
+ h16.put("k1", "\"a?b\"");
+ h16.put("k2", "\"c*d\"");
+ error += createObjectName3("d", h16, false, true);
+
+ if (error > 0) {
+ final String msg = "Test FAILED! Got " + error + " error(s)";
+ System.out.println(msg);
+ throw new IllegalArgumentException(msg);
+ } else {
+ System.out.println("Test PASSED!");
+ }
+ }
+}
diff --git a/test/javax/management/descriptor/DefaultDescriptorTest.java b/test/javax/management/descriptor/DefaultDescriptorTest.java
new file mode 100644
index 0000000..ec4ac10
--- /dev/null
+++ b/test/javax/management/descriptor/DefaultDescriptorTest.java
@@ -0,0 +1,327 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6204469
+ * @summary Test that MBean*Info can be constructed with default descriptor
+ * @author Eamonn McManus
+ * @run clean DefaultDescriptorTest
+ * @run build DefaultDescriptorTest
+ * @run main DefaultDescriptorTest
+ */
+
+import java.lang.reflect.*;
+import javax.management.*;
+import javax.management.modelmbean.*;
+import javax.management.openmbean.*;
+
+public class DefaultDescriptorTest {
+ public static void main(String[] args) throws Exception {
+ final Descriptor empty =
+ ImmutableDescriptor.EMPTY_DESCRIPTOR;
+
+ final Class thisClass = DefaultDescriptorTest.class;
+
+ final Method getWhatever = thisClass.getMethod("getWhatever");
+ final Method setWhatever = thisClass.getMethod("setWhatever",
+ int.class);
+ final Method doWhatever = thisClass.getMethod("doWhatever",
+ String.class);
+
+ final Constructor<?> con = thisClass.getConstructor();
+
+ final OpenMBeanParameterInfoSupport ombpi1 =
+ new OpenMBeanParameterInfoSupport("x", "y", SimpleType.STRING);
+ final OpenMBeanParameterInfoSupport ombpi2 =
+ new OpenMBeanParameterInfoSupport("x", "y", SimpleType.STRING,
+ (Descriptor) null);
+ final OpenMBeanParameterInfoSupport ombpi3 =
+ new OpenMBeanParameterInfoSupport("x", "y", SimpleType.STRING,
+ empty);
+ final OpenMBeanParameterInfoSupport ombpi4 =
+ new OpenMBeanParameterInfoSupport("x", "y", SimpleType.STRING,
+ "defaultString");
+ final OpenMBeanParameterInfoSupport ombpi5 =
+ new OpenMBeanParameterInfoSupport("x", "y", SimpleType.INTEGER,
+ null, 3, 5);
+ final OpenMBeanParameterInfoSupport ombpi6 =
+ new OpenMBeanParameterInfoSupport("x", "y", SimpleType.LONG,
+ 53L, new Long[] {28L, 53L});
+
+ final ModelMBeanInfoSupport mmbi1 =
+ new ModelMBeanInfoSupport("yo", "yo", null, null, null, null);
+ final ModelMBeanInfoSupport mmbi2 =
+ new ModelMBeanInfoSupport("yo", "yo", null, null, null, null,
+ (Descriptor) null);
+// final ModelMBeanInfoSupport mmbi3 =
+// new ModelMBeanInfoSupport("yo", "yo", null, null, null, null,
+// empty);
+ // an empty descriptor is currently illegal for MMBIS
+
+ final ModelMBeanAttributeInfo mmbai1 =
+ new ModelMBeanAttributeInfo("yo", "yo", getWhatever, setWhatever);
+ final ModelMBeanAttributeInfo mmbai2 =
+ new ModelMBeanAttributeInfo("yo", "yo", getWhatever, setWhatever,
+ (Descriptor) null);
+ final ModelMBeanAttributeInfo mmbai3 =
+ new ModelMBeanAttributeInfo("yo", "yo", "yo", true, true, false);
+ final ModelMBeanAttributeInfo mmbai4 =
+ new ModelMBeanAttributeInfo("yo", "yo", "yo", true, true, false,
+ (Descriptor) null);
+
+ final ModelMBeanConstructorInfo mmbci1 =
+ new ModelMBeanConstructorInfo("yo", con);
+ final ModelMBeanConstructorInfo mmbci2 =
+ new ModelMBeanConstructorInfo("yo", con, (Descriptor) null);
+ final ModelMBeanConstructorInfo mmbci3 =
+ new ModelMBeanConstructorInfo("yo", "yo", null);
+ final ModelMBeanConstructorInfo mmbci4 =
+ new ModelMBeanConstructorInfo("yo", "yo", null, (Descriptor) null);
+
+ final ModelMBeanNotificationInfo mmbni1 =
+ new ModelMBeanNotificationInfo(new String[] {"x.y.z"}, "yo", "yo");
+ final ModelMBeanNotificationInfo mmbni2 =
+ new ModelMBeanNotificationInfo(new String[] {"x.y.z"}, "yo", "yo",
+ (Descriptor) null);
+
+ final ModelMBeanOperationInfo mmboi1 =
+ new ModelMBeanOperationInfo("yo", doWhatever);
+ final ModelMBeanOperationInfo mmboi2 =
+ new ModelMBeanOperationInfo("yo", doWhatever, (Descriptor) null);
+ final ModelMBeanOperationInfo mmboi3 =
+ new ModelMBeanOperationInfo("yo", "yo", null, "typo",
+ MBeanOperationInfo.ACTION);
+ final ModelMBeanOperationInfo mmboi4 =
+ new ModelMBeanOperationInfo("yo", "yo", null, "typo",
+ MBeanOperationInfo.ACTION,
+ (Descriptor) null);
+
+ final DescriptorRead[] infos = {
+ new MBeanInfo("a.b.c", "blah", null, null, null, null),
+ new MBeanInfo("a.b.c", "blah", null, null, null, null,
+ (Descriptor) null),
+ new MBeanInfo("a.b.c", "blah", null, null, null, null,
+ empty),
+
+ new MBeanAttributeInfo("blah", "blah", getWhatever, setWhatever),
+// Following constructor deleted because Method has implicit Descriptor
+// from annotations
+// new MBeanAttributeInfo("blah", "blah", getWhatever, setWhatever,
+// (Descriptor) null),
+// new MBeanAttributeInfo("blah", "blah", getWhatever, setWhatever,
+// empty),
+
+ new MBeanAttributeInfo("blah", "a.b.c", "blah",
+ true, true, false),
+ new MBeanAttributeInfo("blah", "a.b.c", "blah",
+ true, true, false, (Descriptor) null),
+ new MBeanAttributeInfo("blah", "a.b.c", "blah",
+ true, true, false, empty),
+
+ new MBeanConstructorInfo("blah", con),
+// Following constructor deleted because Constructor has implicit Descriptor
+// from annotations
+// new MBeanConstructorInfo("blah", con, (Descriptor) null),
+// new MBeanConstructorInfo("blah", con, empty),
+
+ new MBeanConstructorInfo("blah", "blah", null),
+ new MBeanConstructorInfo("blah", "blah", null, (Descriptor) null),
+ new MBeanConstructorInfo("blah", "blah", null, empty),
+
+ // this class should be abstract but isn't
+ new MBeanFeatureInfo("blah", "blah"),
+ new MBeanFeatureInfo("blah", "blah", (Descriptor) null),
+ new MBeanFeatureInfo("blah", "blah", empty),
+
+ new MBeanNotificationInfo(new String[] {"a.b.c"}, "blah", "blah"),
+ new MBeanNotificationInfo(new String[] {"a.b.c"}, "blah", "blah",
+ (Descriptor) null),
+ new MBeanNotificationInfo(new String[] {"a.b.c"}, "blah", "blah",
+ empty),
+
+
+ new MBeanOperationInfo("blah", doWhatever),
+// Following constructor deleted because Method has implicit Descriptor
+// from annotations
+// new MBeanOperationInfo("blah", doWhatever, (Descriptor) null),
+// new MBeanOperationInfo("blah", doWhatever, empty),
+
+ new MBeanOperationInfo("blah", "blah", null, "a.b.c",
+ MBeanOperationInfo.ACTION_INFO),
+ new MBeanOperationInfo("blah", "blah", null, "a.b.c",
+ MBeanOperationInfo.ACTION,
+ (Descriptor) null),
+ new MBeanOperationInfo("blah", "blah", null, "a.b.c",
+ MBeanOperationInfo.INFO,
+ empty),
+
+ new MBeanParameterInfo("blah", "a.b.c", "blah"),
+ new MBeanParameterInfo("blah", "a.b.c", "blah", (Descriptor) null),
+ new MBeanParameterInfo("blah", "a.b.c", "blah", empty),
+
+ new OpenMBeanInfoSupport("x", "y", null, null, null, null),
+ new OpenMBeanInfoSupport("x", "y", null, null, null, null,
+ (Descriptor) null),
+ new OpenMBeanInfoSupport("x", "y", null, null, null, null,
+ empty),
+
+ ombpi1,
+ ombpi2,
+ ombpi3,
+ ombpi4,
+ ombpi5,
+ ombpi6,
+
+ new OpenMBeanAttributeInfoSupport("x", "y", SimpleType.STRING,
+ true, true, false),
+ new OpenMBeanAttributeInfoSupport("x", "y", SimpleType.STRING,
+ true, true, false,
+ (Descriptor) null),
+ new OpenMBeanAttributeInfoSupport("x", "y", SimpleType.STRING,
+ true, true, false,
+ empty),
+ new OpenMBeanAttributeInfoSupport("x", "y", SimpleType.STRING,
+ true, true, false,
+ "defaultString"),
+ new OpenMBeanAttributeInfoSupport("x", "y", SimpleType.INTEGER,
+ true, true, false,
+ null, 3, 5),
+ new OpenMBeanAttributeInfoSupport("x", "y", SimpleType.LONG,
+ true, true, false,
+ 53L, new Long[] {28L, 53L}),
+
+ new OpenMBeanConstructorInfoSupport("x", "y",
+ new OpenMBeanParameterInfo[] {
+ ombpi1, ombpi2
+ }),
+ new OpenMBeanConstructorInfoSupport("x", "y",
+ new OpenMBeanParameterInfo[] {
+ ombpi1, ombpi2
+ }, (Descriptor) null),
+ new OpenMBeanConstructorInfoSupport("x", "y",
+ new OpenMBeanParameterInfo[] {
+ ombpi1, ombpi2
+ }, empty),
+
+ new OpenMBeanOperationInfoSupport("x", "y",
+ new OpenMBeanParameterInfo[] {
+ ombpi1, ombpi2
+ }, SimpleType.DATE,
+ MBeanOperationInfo.ACTION),
+ new OpenMBeanOperationInfoSupport("x", "y",
+ new OpenMBeanParameterInfo[] {
+ ombpi1, ombpi2
+ }, SimpleType.DATE,
+ MBeanOperationInfo.ACTION,
+ (Descriptor) null),
+ new OpenMBeanOperationInfoSupport("x", "y",
+ new OpenMBeanParameterInfo[] {
+ ombpi1, ombpi2
+ }, SimpleType.DATE,
+ MBeanOperationInfo.ACTION,
+ empty),
+
+ mmbi1,
+ mmbi2,
+
+ new ModelMBeanInfoSupport(mmbi1),
+ new ModelMBeanInfoSupport(mmbi2),
+
+ (DescriptorRead) mmbi1.clone(),
+ (DescriptorRead) mmbi2.clone(),
+
+ mmbai1,
+ mmbai2,
+ mmbai3,
+ mmbai4,
+
+ new ModelMBeanAttributeInfo(mmbai1),
+ new ModelMBeanAttributeInfo(mmbai2),
+ new ModelMBeanAttributeInfo(mmbai3),
+ new ModelMBeanAttributeInfo(mmbai4),
+
+ (DescriptorRead) mmbai1.clone(),
+ (DescriptorRead) mmbai2.clone(),
+ (DescriptorRead) mmbai3.clone(),
+ (DescriptorRead) mmbai4.clone(),
+
+ mmbci1,
+ mmbci2,
+ mmbci3,
+ mmbci4,
+
+ // Oddly enough there's no public copy constructor for this class
+
+ (DescriptorRead) mmbci1.clone(),
+ (DescriptorRead) mmbci2.clone(),
+ (DescriptorRead) mmbci3.clone(),
+ (DescriptorRead) mmbci4.clone(),
+
+ mmbni1,
+ mmbni2,
+
+ new ModelMBeanNotificationInfo(mmbni1),
+ new ModelMBeanNotificationInfo(mmbni2),
+
+ (DescriptorRead) mmbni1.clone(),
+ (DescriptorRead) mmbni2.clone(),
+
+ mmboi1,
+ mmboi2,
+ mmboi3,
+ mmboi4,
+
+ new ModelMBeanOperationInfo(mmboi1),
+ new ModelMBeanOperationInfo(mmboi2),
+ new ModelMBeanOperationInfo(mmboi3),
+ new ModelMBeanOperationInfo(mmboi4),
+
+ (DescriptorRead) mmboi1.clone(),
+ (DescriptorRead) mmboi2.clone(),
+ (DescriptorRead) mmboi3.clone(),
+ (DescriptorRead) mmboi4.clone(),
+
+ };
+
+ System.out.println("Testing that a default descriptor is always " +
+ "supplied");
+ for (DescriptorRead info : infos) {
+ System.out.println(info);
+ Descriptor d = info.getDescriptor();
+ if (d == null)
+ throw new Exception("getDescriptor returned null: " + info);
+ }
+ System.out.println("Test passed");
+ }
+
+ public int getWhatever() {
+ return 0;
+ }
+
+ public void setWhatever(int x) {
+ }
+
+ public void doWhatever(String x) {
+ }
+}
diff --git a/test/javax/management/descriptor/DescriptorTest.java b/test/javax/management/descriptor/DescriptorTest.java
new file mode 100644
index 0000000..71c1518
--- /dev/null
+++ b/test/javax/management/descriptor/DescriptorTest.java
@@ -0,0 +1,660 @@
+/*
+ * Copyright 2004-2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6204469 6273765
+ * @summary Test various aspects of the Descriptor interface
+ * @author Eamonn McManus
+ * @run clean DescriptorTest
+ * @run build DescriptorTest
+ * @run main DescriptorTest
+ */
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+import javax.management.*;
+
+public class DescriptorTest {
+ private static String failureMessage;
+
+ // Warning: many tests here know the contents of these variables
+ // so if you change them you must change the tests
+ private static final String[] testFieldNames = {
+ "a", "C", "aa", "int", "nul",
+ };
+ private static final Object[] testFieldValues = {
+ "b", "D", "bb", 5, null,
+ };
+ private static final String[] testFieldStrings = {
+ "a=b", "C=D", "aa=bb", "int=(5)", "nul=",
+ };
+
+ public static void main(String[] args) throws Exception {
+ genericTests(ImmutableDescriptor.class);
+ genericTests(javax.management.modelmbean.DescriptorSupport.class);
+ if (failureMessage != null)
+ throw new Exception("TEST FAILED: " + failureMessage);
+ else
+ System.out.println("Test passed");
+ }
+
+ private static void genericTests(Class<? extends Descriptor> descrClass) {
+ System.out.println("--- generic tests for " + descrClass.getName() +
+ " ---");
+ for (Case<Class<? extends Descriptor>, ?, ?> test :
+ genericDescriptorTests)
+ test.run(descrClass);
+ }
+
+ /*
+ Testing has three parts. We take the input parameter, of type P,
+ and give it to the "prepare" method. That returns us a test
+ parameter, of type T. We give that to the "test" method. That
+ in turn returns us a check value, of type C. We give this to the
+ "check" method. If the "check" method returns null, the test passes.
+ If the "check" method returns a string, that string explains the
+ test failure. If any of the methods throws an exception, the
+ test fails.
+ */
+ private static abstract class Case<P, T, C> {
+ Case(String name) {
+ this.name = name;
+ }
+
+ void run(P p) {
+ System.out.println("test: " + name);
+ try {
+ T t = prepare(p);
+ C c = test(t);
+ String failed = check(c);
+ if (failed != null) {
+ System.out.println("FAILED: " + name + ": " + failed);
+ failureMessage = failed;
+ }
+ } catch (Exception e) {
+ System.out.println("FAILED: " + name + ": exception:");
+ e.printStackTrace(System.out);
+ failureMessage = e.toString();
+ }
+ }
+
+ abstract T prepare(P p) throws Exception;
+ abstract C test(T t) throws Exception;
+ abstract String check(C c) throws Exception;
+
+ private final String name;
+ }
+
+ /*
+ Test case where the preparation step consists of constructing an
+ instance of the given Descriptor subclass containing test values,
+ then giving that to the "test" method.
+ */
+ private static abstract class ProtoCase<C>
+ extends Case<Class<? extends Descriptor>, Descriptor, C> {
+
+ ProtoCase(String name) {
+ super(name);
+ }
+
+ Descriptor prepare(Class<? extends Descriptor> descrClass)
+ throws Exception {
+ Constructor<? extends Descriptor> con =
+ descrClass.getConstructor(String[].class, Object[].class);
+ return con.newInstance(testFieldNames, testFieldValues);
+ }
+ }
+
+ /*
+ Test case where the "test" method must return a value of type C
+ which we will compare against the testValue parameter given to
+ the test constructor.
+ */
+ private static abstract class ValueProtoCase<C> extends ProtoCase<C> {
+ ValueProtoCase(String name, C testValue) {
+ super(name);
+ this.testValue = testValue;
+ }
+
+ String check(C c) {
+ final boolean array = (testValue instanceof Object[]);
+ final boolean equal =
+ array ?
+ Arrays.deepEquals((Object[]) testValue, (Object[]) c) :
+ testValue.equals(c);
+ if (equal)
+ return null;
+ return "wrong value: " + string(c) + " should be " +
+ string(testValue);
+ }
+
+ private final C testValue;
+ }
+
+ /*
+ Test case where the dontChange method does some operation on the
+ test Descriptor that is not supposed to change the contents of
+ the Descriptor. This should work for both mutable and immutable
+ Descriptors, since immutable Descriptors are supposed to do
+ nothing (rather than throw an exception) for mutation operations
+ that would not in fact change the contents.
+ */
+ private static abstract class UnchangedCase extends ProtoCase<Descriptor> {
+ UnchangedCase(String name) {
+ super(name);
+ }
+
+ Descriptor test(Descriptor d) {
+ dontChange(d);
+ return d;
+ }
+
+ String check(Descriptor d) {
+ String[] dnames = d.getFieldNames();
+ if (!strings(dnames).equals(strings(testFieldNames)))
+ return "descriptor names changed: " + strings(dnames);
+ Object[] values = d.getFieldValues(testFieldNames);
+ if (values.length != testFieldValues.length)
+ return "getFieldValues: bogus length: " + values.length;
+ for (int i = 0; i < values.length; i++) {
+ Object expected = testFieldValues[i];
+ Object found = values[i];
+ if ((expected == null) ?
+ found != null :
+ !expected.equals(found))
+ return "descriptor value changed: " + testFieldNames[i] +
+ " was " + expected + " now " + found;
+ }
+ return null;
+ }
+
+ abstract void dontChange(Descriptor d);
+ }
+
+ /*
+ Test case where the change(d) method attempts to make some
+ change to the Descriptor d. The behaviour depends on whether
+ the Descriptor is mutable or not. If the Descriptor is
+ immutable, then the change attempt must throw a
+ RuntimeOperationsException wrapping an
+ UnsupportedOperationException. If the Descriptor is mutable,
+ then the change attempt must succeed, and the Descriptor must
+ then look like the fieldsAndValues parameter to the constructor.
+ This is simply an alternating set of field names and corresponding
+ values. So for example if it is
+
+ "a", "b", "x", 5
+
+ that represents a Descriptor with fields "a" and "x" whose
+ corresponding values are "x" and Integer.valueOf(5).
+ */
+ private static abstract class ChangedCase extends ProtoCase<Object> {
+ ChangedCase(String name, Object... fieldsAndValues) {
+ super(name);
+ if (fieldsAndValues.length % 2 != 0)
+ throw new AssertionError("test wrong: odd fieldsAndValues");
+ this.fieldsAndValues = fieldsAndValues;
+ this.immutableTest = new UnsupportedExceptionCase(name) {
+ void provoke(Descriptor d) {
+ ChangedCase.this.change(d);
+ }
+ };
+ }
+
+ Object test(Descriptor d) {
+ if (immutable(d))
+ return immutableTest.test(d);
+ else {
+ change(d);
+ return d;
+ }
+ }
+
+ String check(Object c) {
+ if (c instanceof Exception)
+ return immutableTest.check((Exception) c);
+ else if (!(c instanceof Descriptor)) {
+ return "test returned strange value: " +
+ c.getClass() + ": " + c;
+ } else {
+ Descriptor d = (Descriptor) c;
+ String[] names = new String[fieldsAndValues.length / 2];
+ Object[] expected = new Object[names.length];
+ for (int i = 0; i < fieldsAndValues.length; i += 2) {
+ names[i / 2] = (String) fieldsAndValues[i];
+ expected[i / 2] = fieldsAndValues[i + 1];
+ }
+ String[] foundNames = d.getFieldNames();
+ if (!strings(foundNames).equals(strings(names))) {
+ return "wrong field names after change: found " +
+ strings(foundNames) + ", expected " + strings(names);
+ }
+ Object[] found = d.getFieldValues(names);
+ if (!Arrays.deepEquals(expected, found)) {
+ return "wrong value after change: for fields " +
+ Arrays.asList(names) + " values are " +
+ Arrays.asList(found) + ", should be " +
+ Arrays.asList(expected);
+ }
+ return null;
+ }
+ }
+
+ abstract void change(Descriptor d);
+
+ private final Object[] fieldsAndValues;
+ private final ExceptionCase immutableTest;
+ }
+
+ /*
+ Test case where an operation provoke(d) on the test Descriptor d
+ is supposed to provoke an exception. The exception must be a
+ RuntimeOperationsException wrapping another exception whose type
+ is determined by the exceptionClass() method.
+ */
+ private static abstract class ExceptionCase extends ProtoCase<Exception> {
+
+ ExceptionCase(String name) {
+ super(name);
+ }
+
+ Exception test(Descriptor d) {
+ try {
+ provoke(d);
+ return null;
+ } catch (Exception e) {
+ return e;
+ }
+ }
+
+ String check(Exception e) {
+ if (e == null)
+ return "did not throw exception: " + expected();
+ if (!(e instanceof RuntimeOperationsException)) {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ e.printStackTrace(pw);
+ pw.flush();
+ return "wrong exception: " + expected() + ": found: " + sw;
+ }
+ Throwable cause = e.getCause();
+ if (!exceptionClass().isInstance(cause))
+ return "wrong wrapped exception: " + cause + ": " + expected();
+ return null;
+ }
+
+ String expected() {
+ return "expected " + RuntimeOperationsException.class.getName() +
+ " wrapping " + exceptionClass().getName();
+ }
+
+ abstract Class<? extends Exception> exceptionClass();
+ abstract void provoke(Descriptor d);
+ }
+
+ private static abstract class IllegalExceptionCase extends ExceptionCase {
+ IllegalExceptionCase(String name) {
+ super(name);
+ }
+
+ Class<IllegalArgumentException> exceptionClass() {
+ return IllegalArgumentException.class;
+ }
+ }
+
+ private static abstract class UnsupportedExceptionCase
+ extends ExceptionCase {
+ UnsupportedExceptionCase(String name) {
+ super(name);
+ }
+
+ Class<UnsupportedOperationException> exceptionClass() {
+ return UnsupportedOperationException.class;
+ }
+ }
+
+ /*
+ List of test cases. We will run through these once for
+ ImmutableDescriptor and once for DescriptorSupport.
+
+ Expect a compiler [unchecked] warning for this initialization.
+ Writing
+
+ new Case<Class<? extends Descriptor>, ?, ?>[] = {...}
+
+ would cause a compiler error since you can't have arrays of
+ parameterized types unless all the parameters are just "?".
+ This hack with varargs gives us a compiler warning instead.
+ Writing just:
+
+ new Case<?, ?, ?>[] = {...}
+
+ would compile here, but not where we call test.run, since you
+ cannot pass an object to the run(P) method if P is "?".
+ */
+ private static final Case<Class<? extends Descriptor>, ?, ?>
+ genericDescriptorTests[] = constantArray(
+
+ // TEST VALUES RETURNED BY GETTERS
+
+ new Case<Class<? extends Descriptor>, Descriptor, Object[]>(
+ "getFieldValues on empty Descriptor") {
+ Descriptor prepare(Class<? extends Descriptor> c)
+ throws Exception {
+ Constructor<? extends Descriptor> con =
+ c.getConstructor(String[].class);
+ return con.newInstance(new Object[] {new String[0]});
+ }
+ Object[] test(Descriptor d) {
+ return d.getFieldValues("foo", "bar");
+ }
+ String check(Object[] v) {
+ if (v.length == 2 && v[0] == null && v[1] == null)
+ return null;
+ return "value should be array with null elements: " +
+ Arrays.deepToString(v);
+ }
+ },
+
+ new ValueProtoCase<Set<String>>("getFieldNames",
+ strings(testFieldNames)) {
+ Set<String> test(Descriptor d) {
+ return set(d.getFieldNames());
+ }
+ },
+ new ValueProtoCase<Set<String>>("getFields",
+ strings(testFieldStrings)) {
+ Set<String> test(Descriptor d) {
+ return set(d.getFields());
+ }
+ },
+ new ValueProtoCase<Object>("getFieldValue with exact case", "b") {
+ Object test(Descriptor d) {
+ return d.getFieldValue("a");
+ }
+ },
+ new ValueProtoCase<Object>("getFieldValue with lower case for upper",
+ "D") {
+ Object test(Descriptor d) {
+ return d.getFieldValue("c");
+ }
+ },
+ new ValueProtoCase<Object>("getFieldValue with upper case for lower",
+ "bb") {
+ Object test(Descriptor d) {
+ return d.getFieldValue("AA");
+ }
+ },
+ new ValueProtoCase<Object>("getFieldValue with mixed case for lower",
+ "bb") {
+ Object test(Descriptor d) {
+ return d.getFieldValue("aA");
+ }
+ },
+ new ValueProtoCase<Set<?>>("getFieldValues with null arg",
+ set(testFieldValues)) {
+ Set<?> test(Descriptor d) {
+ return set(d.getFieldValues((String[]) null));
+ }
+ },
+ new ValueProtoCase<Object[]>("getFieldValues with not all values",
+ new Object[] {"b", "D", 5}) {
+ Object[] test(Descriptor d) {
+ return d.getFieldValues("a", "c", "int");
+ }
+ },
+ new ValueProtoCase<Object[]>("getFieldValues with all values " +
+ "lower case",
+ new Object[]{"bb", "D", "b", 5}) {
+ Object[] test(Descriptor d) {
+ return d.getFieldValues("aa", "c", "a", "int");
+ }
+ },
+ new ValueProtoCase<Object[]>("getFieldValues with all values " +
+ "upper case",
+ new Object[] {5, "b", "D", "bb"}) {
+ Object[] test(Descriptor d) {
+ return d.getFieldValues("int", "A", "C", "AA");
+ }
+ },
+ new ValueProtoCase<Object[]>("getFieldValues with null name",
+ new Object[] {null}) {
+ Object[] test(Descriptor d) {
+ return d.getFieldValues((String) null);
+ }
+ },
+ new ValueProtoCase<Object[]>("getFieldValues with empty name",
+ new Object[] {null}) {
+ Object[] test(Descriptor d) {
+ return d.getFieldValues("");
+ }
+ },
+ new ValueProtoCase<Object[]>("getFieldValues with no names",
+ new Object[0]) {
+ Object[] test(Descriptor d) {
+ return d.getFieldValues();
+ }
+ },
+
+ // TEST OPERATIONS THAT DON'T CHANGE THE DESCRIPTOR
+ // Even for immutable descriptors, these are allowed
+
+ new UnchangedCase("removeField with nonexistent field") {
+ void dontChange(Descriptor d) {
+ d.removeField("noddy");
+ }
+ },
+ new UnchangedCase("removeField with null field") {
+ void dontChange(Descriptor d) {
+ d.removeField(null);
+ }
+ },
+ new UnchangedCase("removeField with empty field") {
+ void dontChange(Descriptor d) {
+ d.removeField("");
+ }
+ },
+ new UnchangedCase("setField leaving string unchanged") {
+ void dontChange(Descriptor d) {
+ d.setField("a", "b");
+ }
+ },
+ new UnchangedCase("setField leaving int unchanged") {
+ void dontChange(Descriptor d) {
+ d.setField("int", 5);
+ }
+ },
+ // We do not test whether you can do a setField/s with an
+ // unchanged value but the case of the name different.
+ // From the spec, that should probably be illegal, but
+ // it's such a corner case that we leave it alone.
+
+ new UnchangedCase("setFields with empty arrays") {
+ void dontChange(Descriptor d) {
+ d.setFields(new String[0], new Object[0]);
+ }
+ },
+ new UnchangedCase("setFields with unchanged values") {
+ void dontChange(Descriptor d) {
+ d.setFields(new String[] {"a", "int"},
+ new Object[] {"b", 5});
+ }
+ },
+
+ // TEST OPERATIONS THAT DO CHANGE THE DESCRIPTOR
+ // For immutable descriptors, these should provoke an exception
+
+ new ChangedCase("removeField with exact case",
+ "a", "b", "C", "D", "int", 5, "nul", null) {
+ void change(Descriptor d) {
+ d.removeField("aa");
+ }
+ },
+ new ChangedCase("removeField with upper case for lower",
+ "a", "b", "C", "D", "int", 5, "nul", null) {
+ void change(Descriptor d) {
+ d.removeField("AA");
+ }
+ },
+ new ChangedCase("removeField with lower case for upper",
+ "a", "b", "aa", "bb", "int", 5, "nul", null) {
+ void change(Descriptor d) {
+ d.removeField("c");
+ }
+ },
+ new ChangedCase("setField keeping lower case",
+ "a", "x", "C", "D", "aa", "bb", "int", 5,
+ "nul", null) {
+ void change(Descriptor d) {
+ d.setField("a", "x");
+ }
+ },
+
+ // spec says we should conserve the original case of the field name:
+ new ChangedCase("setField changing lower case to upper",
+ "a", "x", "C", "D", "aa", "bb", "int", 5,
+ "nul", null) {
+ void change(Descriptor d) {
+ d.setField("A", "x");
+ }
+ },
+ new ChangedCase("setField changing upper case to lower",
+ "a", "b", "C", "x", "aa", "bb", "int", 5,
+ "nul", null) {
+ void change(Descriptor d) {
+ d.setField("c", "x");
+ }
+ },
+ new ChangedCase("setField adding new field",
+ "a", "b", "C", "D", "aa", "bb", "int", 5, "xX", "yY",
+ "nul", null) {
+ void change(Descriptor d) {
+ d.setField("xX", "yY");
+ }
+ },
+ new ChangedCase("setField changing type of field",
+ "a", true, "C", "D", "aa", "bb", "int", 5,
+ "nul", null) {
+ void change(Descriptor d) {
+ d.setField("a", true);
+ }
+ },
+ new ChangedCase("setField changing non-null to null",
+ "a", null, "C", "D", "aa", "bb", "int", 5,
+ "nul", null) {
+ void change(Descriptor d) {
+ d.setField("a", null);
+ }
+ },
+ new ChangedCase("setField changing null to non-null",
+ "a", "b", "C", "D", "aa", "bb", "int", 5,
+ "nul", 3.14) {
+ void change(Descriptor d) {
+ d.setField("nul", 3.14);
+ }
+ },
+
+ // TEST EXCEPTION BEHAVIOUR COMMON BETWEEN MUTABLE AND IMMUTABLE
+
+ new IllegalExceptionCase("getFieldValue with null name") {
+ void provoke(Descriptor d) {
+ d.getFieldValue(null);
+ }
+ },
+ new IllegalExceptionCase("getFieldValue with empty name") {
+ void provoke(Descriptor d) {
+ d.getFieldValue("");
+ }
+ },
+ new IllegalExceptionCase("setField with null name") {
+ void provoke(Descriptor d) {
+ d.setField(null, "x");
+ }
+ },
+ new IllegalExceptionCase("setField with empty name") {
+ void provoke(Descriptor d) {
+ d.setField("", "x");
+ }
+ },
+ new IllegalExceptionCase("setFields with null fieldNames") {
+ void provoke(Descriptor d) {
+ d.setFields(null, new Object[] {"X"});
+ }
+ },
+ new IllegalExceptionCase("setFields with null fieldValues") {
+ void provoke(Descriptor d) {
+ d.setFields(new String[] {"X"}, null);
+ }
+ },
+ new IllegalExceptionCase("setFields with null fieldNames and " +
+ "fieldValues") {
+ void provoke(Descriptor d) {
+ d.setFields(null, null);
+ }
+ },
+ new IllegalExceptionCase("setFields with more fieldNames than " +
+ "fieldValues") {
+ void provoke(Descriptor d) {
+ d.setFields(new String[] {"A", "B"}, new String[] {"C"});
+ }
+ },
+ new IllegalExceptionCase("setFields with more fieldValues than " +
+ "fieldNames") {
+ void provoke(Descriptor d) {
+ d.setFields(new String[] {"A"}, new String[] {"B", "C"});
+ }
+ },
+ new IllegalExceptionCase("setFields with null element of fieldNames") {
+ void provoke(Descriptor d) {
+ d.setFields(new String[] {null}, new String[] {"X"});
+ }
+ }
+
+ );
+
+ static <T> T[] constantArray(T... array) {
+ return array;
+ }
+
+ static String string(Object x) {
+ if (x instanceof Object[])
+ return Arrays.asList((Object[]) x).toString();
+ else
+ return String.valueOf(x);
+ }
+
+ static Set<String> strings(String... values) {
+ return new TreeSet<String>(Arrays.asList(values));
+ }
+
+ static <T> Set<T> set(T[] values) {
+ return new HashSet<T>(Arrays.asList(values));
+ }
+
+ static boolean immutable(Descriptor d) {
+ return (d instanceof ImmutableDescriptor);
+ // good enough for our purposes
+ }
+}
diff --git a/test/javax/management/descriptor/EqualsHashCodeTest.java b/test/javax/management/descriptor/EqualsHashCodeTest.java
new file mode 100644
index 0000000..837fb3e
--- /dev/null
+++ b/test/javax/management/descriptor/EqualsHashCodeTest.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6255956
+ * @summary Test equals and hashCode for descriptors
+ * @author Eamonn McManus
+ * @run clean EqualsHashCodeTest
+ * @run build EqualsHashCodeTest
+ * @run main EqualsHashCodeTest
+ */
+
+import java.util.Arrays;
+import javax.management.*;
+import javax.management.modelmbean.DescriptorSupport;
+
+public class EqualsHashCodeTest {
+ public static void main(String[] args) throws Exception {
+ int[] squares = {1, 4, 9, 16};
+ int[] serauqs = {16, 9, 4, 1};
+ int[][] numbers = {squares, serauqs};
+
+ Descriptor sq1 =
+ new ImmutableDescriptor(new String[] {"name", "rank", "squares",
+ "null", "numbers"},
+ new Object[] {"Foo McBar", "lowly",
+ squares.clone(), null,
+ numbers});
+ Descriptor sq2 =
+ new DescriptorSupport(new String[] {"Name", "Rank", "SquareS",
+ "NULL", "NuMbErS"},
+ new Object[] {"Foo McBar", "lowly",
+ squares.clone(), null,
+ numbers});
+ Descriptor sq3 = (Descriptor) sq2.clone();
+ Descriptor sq4 = ImmutableDescriptor.union(sq1, sq2);
+
+ String[] names = sq1.getFieldNames();
+ Object[] values = sq1.getFieldValues((String[]) null);
+ Object[] values2 = sq1.getFieldValues(names);
+ if (!Arrays.deepEquals(values, values2)) {
+ throw new Exception("Arrays not equal: " +
+ Arrays.deepToString(values) + Arrays.deepToString(values2));
+ }
+
+ int expectedHashCode = 0;
+ for (int i = 0; i < names.length; i++) {
+ Object value = values[i];
+ int h;
+ if (value == null)
+ h = 0;
+ else if (value instanceof int[])
+ h = Arrays.hashCode((int[]) value);
+ else if (value instanceof Object[])
+ h = Arrays.deepHashCode((Object[]) value);
+ else
+ h = value.hashCode();
+ expectedHashCode += names[i].toLowerCase().hashCode() ^ h;
+ }
+ for (Descriptor d : new Descriptor[] {sq1, sq2, sq3, sq4}) {
+ System.out.println("Testing hashCode for " +
+ d.getClass().getName() + ": " + d);
+ if (d.hashCode() != expectedHashCode) {
+ throw new Exception("Bad hashCode: expected " +
+ expectedHashCode + ", got " + d.hashCode() +
+ ", for " + d);
+ }
+ }
+
+ int i;
+ for (i = 0; i < names.length; i++) {
+ if (names[i].equals("squares")) {
+ values[i] = serauqs.clone();
+ break;
+ }
+ }
+ if (i >= names.length)
+ throw new Exception("Internal error: no squares name");
+ Descriptor qs1 = new ImmutableDescriptor(names, values);
+ values[i] = serauqs.clone();
+ Descriptor qs2 = new DescriptorSupport(names, values);
+
+ System.out.println("Testing equality...");
+
+ Object[][] equivalenceClasses = {
+ {sq1, sq2, sq3, sq4},
+ {qs1, qs2},
+ };
+ for (Object[] equivClass : equivalenceClasses) {
+ for (Object a : equivClass) {
+ for (Object b : equivClass) {
+ if (!a.equals(b)) {
+ throw new Exception("Should be equal but not: " +
+ a + " :: " + b);
+ }
+ }
+ for (Object[] equivClass2 : equivalenceClasses) {
+ if (equivClass2 == equivClass)
+ continue;
+ for (Object b : equivClass2) {
+ if (a.equals(b)) {
+ throw new Exception("Should not be equal: " +
+ a + " :: " + b);
+ }
+ }
+ }
+ }
+ }
+
+ System.out.println("TEST PASSED");
+ }
+}
diff --git a/test/javax/management/descriptor/ImmutableArrayFieldTest.java b/test/javax/management/descriptor/ImmutableArrayFieldTest.java
new file mode 100644
index 0000000..28d4fb5
--- /dev/null
+++ b/test/javax/management/descriptor/ImmutableArrayFieldTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6299180
+ * @summary Test that immutability of ImmutableDescriptor cannot be
+ * compromised by modifying field values that are arrays.
+ * @author Eamonn McManus
+ * @run clean ImmutableArrayFieldTest
+ * @run build ImmutableArrayFieldTest
+ * @run main ImmutableArrayFieldTest
+ */
+
+import java.util.Arrays;
+import javax.management.ImmutableDescriptor;
+
+public class ImmutableArrayFieldTest {
+ public static void main(String[] args) throws Exception {
+ boolean ok = true;
+ ImmutableDescriptor d = new ImmutableDescriptor(
+ new String[] {
+ "strings", "ints", "booleans",
+ },
+ new Object[] {
+ new String[] {"foo"},
+ new int[] {5},
+ new boolean[] {false},
+ });
+
+ String[] strings = (String[]) d.getFieldValue("strings");
+ strings[0] = "bar";
+ strings = (String[]) d.getFieldValue("strings");
+ if (!strings[0].equals("foo")) {
+ System.out.println("FAILED: modified string array field");
+ ok = false;
+ }
+
+ int[] ints = (int[]) d.getFieldValue("ints");
+ ints[0] = 0;
+ ints = (int[]) d.getFieldValue("ints");
+ if (ints[0] != 5) {
+ System.out.println("FAILED: modified int array field");
+ ok = false;
+ }
+
+ boolean[] bools = (boolean[]) d.getFieldValue("booleans");
+ bools[0] = true;
+ bools = (boolean[]) d.getFieldValue("booleans");
+ if (bools[0]) {
+ System.out.println("FAILED: modified boolean array field");
+ ok = false;
+ }
+
+ Object[] values = d.getFieldValues("strings", "ints", "booleans");
+ ((String[]) values[0])[0] = "bar";
+ ((int[]) values[1])[0] = 0;
+ ((boolean[]) values[2])[0] = true;
+ values = d.getFieldValues("strings", "ints", "booleans");
+ if (!((String[]) values[0])[0].equals("foo") ||
+ ((int[]) values[1])[0] != 5 ||
+ ((boolean[]) values[2])[0]) {
+ System.out.println("FAILED: getFieldValues modifiable: " +
+ Arrays.deepToString(values));
+ }
+
+ if (ok)
+ System.out.println("TEST PASSED");
+ else
+ throw new Exception("Array field values were modifiable");
+ }
+}
diff --git a/test/javax/management/descriptor/ImmutableDescriptorSerialTest.java b/test/javax/management/descriptor/ImmutableDescriptorSerialTest.java
new file mode 100644
index 0000000..4bb0a77
--- /dev/null
+++ b/test/javax/management/descriptor/ImmutableDescriptorSerialTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6204469
+ * @summary Test ImmutableDescriptor serialization.
+ * @author Eamonn McManus
+ * @run clean ImmutableDescriptorSerialTest
+ * @run build ImmutableDescriptorSerialTest
+ * @run main ImmutableDescriptorSerialTest
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import javax.management.Descriptor;
+import javax.management.ImmutableDescriptor;
+
+public class ImmutableDescriptorSerialTest {
+ public static void main(String[] args) throws Exception {
+ System.out.println("Test that ImmutableDescriptor.EMPTY_DESCRIPTOR " +
+ "deserializes identically");
+ if (serialize(ImmutableDescriptor.EMPTY_DESCRIPTOR) !=
+ ImmutableDescriptor.EMPTY_DESCRIPTOR) {
+ throw new Exception("ImmutableDescriptor.EMPTY_DESCRIPTOR did not " +
+ "deserialize identically");
+ }
+ System.out.println("...OK");
+
+ System.out.println("Test that serialization preserves case and " +
+ "that deserialized object is case-insensitive");
+ Descriptor d = new ImmutableDescriptor("a=aval", "B=Bval", "cC=cCval");
+ Descriptor d1 = serialize(d);
+ Set<String> keys = new HashSet(Arrays.asList(d1.getFieldNames()));
+ if (keys.size() != 3 ||
+ !keys.containsAll(Arrays.asList("a", "B", "cC"))) {
+ throw new Exception("Keys don't match: " + keys);
+ }
+ for (String key : keys) {
+ String value = (String) d.getFieldValue(key);
+ for (String t :
+ Arrays.asList(key, key.toLowerCase(), key.toUpperCase())) {
+ String tvalue = (String) d1.getFieldValue(t);
+ if (!tvalue.equals(value)) {
+ throw new Exception("Value of " + key + " for " +
+ "deserialized object does not match: " +
+ tvalue + " should be " + value);
+ }
+ }
+ }
+ System.out.println("...OK");
+ }
+
+ private static <T> T serialize(T x) throws Exception {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ ObjectOutputStream oout = new ObjectOutputStream(bout);
+ oout.writeObject(x);
+ oout.close();
+ byte[] bytes = bout.toByteArray();
+ ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
+ ObjectInputStream oin = new ObjectInputStream(bin);
+ return (T) oin.readObject();
+ }
+}
diff --git a/test/javax/management/descriptor/ImmutableDescriptorSetFieldsTest.java b/test/javax/management/descriptor/ImmutableDescriptorSetFieldsTest.java
new file mode 100644
index 0000000..314b540
--- /dev/null
+++ b/test/javax/management/descriptor/ImmutableDescriptorSetFieldsTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6305139
+ * @summary Check that calling setFields with a field names array with a
+ * null name in it and calling setFields with a field names array with an
+ * empty name in it throw the expected exceptions.
+ * @author Luis-Miguel Alventosa
+ * @run clean ImmutableDescriptorSetFieldsTest
+ * @run build ImmutableDescriptorSetFieldsTest
+ * @run main ImmutableDescriptorSetFieldsTest
+ */
+
+import javax.management.ImmutableDescriptor;
+import javax.management.RuntimeOperationsException;
+
+public class ImmutableDescriptorSetFieldsTest {
+ public static void main(String[] args) throws Exception {
+ boolean ok = true;
+ ImmutableDescriptor d = new ImmutableDescriptor("k=v");
+ try {
+ System.out.println(
+ "Call ImmutableDescriptor.setFields(fieldNames,fieldValues) " +
+ "with empty name in field names array");
+ String fieldNames[] = { "a", "", "c" };
+ Object fieldValues[] = { 1, 2, 3 };
+ d.setFields(fieldNames, fieldValues);
+ System.out.println("Didn't get expected exception");
+ ok = false;
+ } catch (RuntimeOperationsException e) {
+ if (e.getCause() instanceof IllegalArgumentException) {
+ System.out.println("Got expected exception:");
+ ok = true;
+ } else {
+ System.out.println("Got unexpected exception:");
+ ok = false;
+ }
+ e.printStackTrace(System.out);
+ } catch (Exception e) {
+ System.out.println("Got unexpected exception:");
+ ok = false;
+ e.printStackTrace(System.out);
+ }
+ try {
+ System.out.println(
+ "Call ImmutableDescriptor.setFields(fieldNames,fieldValues) " +
+ "with null name in field names array");
+ String fieldNames[] = { "a", null, "c" };
+ Object fieldValues[] = { 1, 2, 3 };
+ d.setFields(fieldNames, fieldValues);
+ System.out.println("Didn't get expected exception");
+ ok = false;
+ } catch (RuntimeOperationsException e) {
+ if (e.getCause() instanceof IllegalArgumentException) {
+ System.out.println("Got expected exception:");
+ ok = true;
+ } else {
+ System.out.println("Got unexpected exception:");
+ ok = false;
+ }
+ e.printStackTrace(System.out);
+ } catch (Exception e) {
+ System.out.println("Got unexpected exception:");
+ ok = false;
+ e.printStackTrace(System.out);
+ }
+ if (ok) {
+ System.out.println("TEST PASSED");
+ } else {
+ System.out.println("TEST FAILED");
+ throw new Exception("Got unexpected exceptions");
+ }
+ }
+}
diff --git a/test/javax/management/descriptor/MBeanInfoInteropTest.java b/test/javax/management/descriptor/MBeanInfoInteropTest.java
new file mode 100644
index 0000000..cdfd597
--- /dev/null
+++ b/test/javax/management/descriptor/MBeanInfoInteropTest.java
@@ -0,0 +1,336 @@
+/*
+ * Copyright 2005-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6204469
+ * @summary Check that descriptors have not broken serial interop.
+ * @author Eamonn McManus
+ * @run clean MBeanInfoInteropTest SerializedInfo
+ * @run build MBeanInfoInteropTest SerializedInfo
+ * @run main MBeanInfoInteropTest SerializedInfo
+ */
+
+/*
+ * When run with just a classname argument ("SerializedInfo" above),
+ * this reads the serialized objects from that class.
+ * When run with the argument "generate" and a classname, say "SerializedInfo",
+ * this creates the class SerializedInfo.java. The idea is to do that on JDK 5.0
+ * then run this test on the latest JDK, or vice versa. The
+ * copy included in this source directory was generated on JDK 5.0
+ * so that we continue to check forward interop (serialize on JDK 5,
+ * deserialize on JDK 6). There is no easy way to automate backward
+ * interop checking.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import javax.management.Descriptor;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanConstructorInfo;
+import javax.management.MBeanInfo;
+import javax.management.MBeanNotificationInfo;
+import static javax.management.MBeanOperationInfo.*;
+import static javax.management.openmbean.SimpleType.INTEGER;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanParameterInfo;
+import javax.management.modelmbean.DescriptorSupport;
+import javax.management.modelmbean.ModelMBeanAttributeInfo;
+import javax.management.modelmbean.ModelMBeanConstructorInfo;
+import javax.management.modelmbean.ModelMBeanInfoSupport;
+import javax.management.modelmbean.ModelMBeanNotificationInfo;
+import javax.management.modelmbean.ModelMBeanOperationInfo;
+import javax.management.openmbean.OpenMBeanAttributeInfo;
+import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
+import javax.management.openmbean.OpenMBeanConstructorInfo;
+import javax.management.openmbean.OpenMBeanConstructorInfoSupport;
+import javax.management.openmbean.OpenMBeanInfoSupport;
+import javax.management.openmbean.OpenMBeanOperationInfo;
+import javax.management.openmbean.OpenMBeanOperationInfoSupport;
+import javax.management.openmbean.OpenMBeanParameterInfo;
+import javax.management.openmbean.OpenMBeanParameterInfoSupport;
+
+public class MBeanInfoInteropTest {
+ public static void main(String[] args) throws Exception {
+ if (args.length == 2 && args[0].equals("generate"))
+ generate(args[1]);
+ else if (args.length == 1)
+ test(args[0]);
+ else {
+ final String usage =
+ "Usage: MBeanInfoInteropTest [generate] ClassName";
+ throw new Exception(usage);
+ }
+ }
+
+ private static void test(String className) throws Exception {
+ Class<?> c = Class.forName(className);
+ Field f = c.getField("BYTES");
+ byte[] bytes = (byte[]) f.get(null);
+ ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
+ ObjectInputStream ois = new ObjectInputStream(bis);
+ boolean matched = true;
+ for (Serializable s : objects) {
+ Object o = ois.readObject();
+ if (!o.equals(s)) {
+ showMismatch(o, s);
+ matched = false;
+ }
+ }
+ if (!matched)
+ throw new Exception("Read objects did not match");
+ System.out.println("Test passed");
+ }
+
+ private static void showMismatch(Object read, Serializable expected)
+ throws Exception {
+ String name = "<unknown>";
+ Field[] fs = MBeanInfoInteropTest.class.getDeclaredFields();
+ for (Field f : fs) {
+ if (!Modifier.isStatic(f.getModifiers()))
+ continue;
+ Object x = f.get(null);
+ if (x == expected) {
+ name = f.getName();
+ break;
+ }
+ }
+ System.out.println("Read object mismatch for field " + name);
+ System.out.println("...read: " + read);
+ System.out.println("...expected: " + expected);
+ }
+
+ private static void generate(String className) throws Exception {
+ System.out.println("Generating " + className + ".java");
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(bos);
+ for (Serializable s : objects)
+ oos.writeObject(s);
+ oos.close();
+ byte[] bytes = bos.toByteArray();
+ PrintWriter pw = new PrintWriter(className + ".java");
+ pw.printf(
+ "// Generated by: MBeanInfoInteropTest generate %s\n" +
+ "import java.io.*;\n" +
+ "public class %s {\n" +
+ "public static final byte[] BYTES = {\n", className, className);
+ for (int i = 0; i < bytes.length; i++) {
+ byte b = bytes[i];
+ pw.printf("%d,", b);
+ if (i % 16 == 15)
+ pw.printf("\n");
+ }
+ pw.printf("\n");
+ pw.printf(
+ "};\n" +
+ "}\n");
+ pw.close();
+ System.out.println("...done");
+ }
+
+ private static MBeanAttributeInfo mbai;
+ private static MBeanParameterInfo mbpi;
+ private static MBeanConstructorInfo mbci1, mbci2;
+ private static MBeanNotificationInfo mbni1, mbni2;
+ private static MBeanOperationInfo mboi1, mboi2;
+ private static MBeanInfo mbi1, mbi2;
+ private static OpenMBeanAttributeInfoSupport ombai1, ombai2, ombai3, ombai4;
+ private static OpenMBeanParameterInfoSupport ombpi1, ombpi2, ombpi3, ombpi4;
+ private static OpenMBeanConstructorInfoSupport ombci1, ombci2;
+ private static OpenMBeanOperationInfoSupport omboi1, omboi2;
+ private static OpenMBeanInfoSupport ombi1, ombi2;
+ private static ModelMBeanAttributeInfo mmbai1, mmbai2;
+ private static ModelMBeanConstructorInfo mmbci1, mmbci2, mmbci3, mmbci4;
+ private static ModelMBeanOperationInfo mmboi1, mmboi2, mmboi3, mmboi4;
+ private static ModelMBeanNotificationInfo mmbni1, mmbni2, mmbni3, mmbni4;
+ private static ModelMBeanInfoSupport mmbi1, mmbi2, mmbi3, mmbi4;
+ private static Serializable[] objects;
+ static {
+ try {
+ init();
+ } catch (Exception e) {
+ throw new IllegalArgumentException("unexpected", e);
+ }
+ }
+ private static void init() throws Exception {
+ mbai =
+ new MBeanAttributeInfo("name", "type", "descr", true, false, false);
+ mbpi =
+ new MBeanParameterInfo("name", "type", "descr");
+ MBeanParameterInfo[] params = new MBeanParameterInfo[] {mbpi};
+ mbci1 =
+ new MBeanConstructorInfo("name", "descr", null);
+ mbci2 =
+ new MBeanConstructorInfo("name", "descr", params);
+ mbni1 =
+ new MBeanNotificationInfo(null, "name", "descr");
+ mbni2 =
+ new MBeanNotificationInfo(new String[] {"type"}, "name", "descr");
+ mboi1 =
+ new MBeanOperationInfo("name", "descr", null, "type", ACTION);
+ mboi2 =
+ new MBeanOperationInfo("name", "descr", params, "type", INFO);
+ mbi1 =
+ new MBeanInfo("class", "descr", null, null, null, null);
+ mbi2 =
+ new MBeanInfo(
+ "class", "descr",
+ new MBeanAttributeInfo[] {mbai},
+ new MBeanConstructorInfo[] {mbci1, mbci2},
+ new MBeanOperationInfo[] {mboi1, mboi2},
+ new MBeanNotificationInfo[] {mbni1, mbni2});
+
+ ombai1 =
+ new OpenMBeanAttributeInfoSupport("name", "descr", INTEGER,
+ true, false, false);
+ ombai2 =
+ new OpenMBeanAttributeInfoSupport("name", "descr", INTEGER,
+ true, false, false, 5);
+ ombai3 =
+ new OpenMBeanAttributeInfoSupport("name", "descr", INTEGER,
+ true, false, false, 5, 1, 6);
+ ombai4 =
+ new OpenMBeanAttributeInfoSupport("name", "descr", INTEGER,
+ true, false, false, 5,
+ new Integer[] {2, 3, 5, 7});
+ ombpi1 =
+ new OpenMBeanParameterInfoSupport("name1", "descr", INTEGER);
+ ombpi2 =
+ new OpenMBeanParameterInfoSupport("name2", "descr", INTEGER, 5);
+ ombpi3 =
+ new OpenMBeanParameterInfoSupport("name3", "descr", INTEGER, 5, 1, 6);
+ ombpi4 =
+ new OpenMBeanParameterInfoSupport("name4", "descr", INTEGER, 5,
+ new Integer[] {2, 3, 5, 7});
+ OpenMBeanParameterInfo[] oparams = {ombpi1, ombpi2, ombpi3, ombpi4};
+ ombci1 =
+ new OpenMBeanConstructorInfoSupport("name", "descr", null);
+ ombci2 =
+ new OpenMBeanConstructorInfoSupport("name", "descr", oparams);
+ omboi1 =
+ new OpenMBeanOperationInfoSupport("name", "descr", null,
+ INTEGER, ACTION);
+ omboi2 =
+ new OpenMBeanOperationInfoSupport("name", "descr", oparams,
+ INTEGER, ACTION);
+ ombi1 =
+ new OpenMBeanInfoSupport("class", "descr", null, null, null, null);
+ ombi2 =
+ new OpenMBeanInfoSupport(
+ "class", "descr",
+ new OpenMBeanAttributeInfo[] {ombai1, ombai2, ombai3, ombai4},
+ new OpenMBeanConstructorInfo[] {ombci1, ombci2},
+ new OpenMBeanOperationInfo[] {omboi1, omboi2},
+ new MBeanNotificationInfo[] {mbni1, mbni2});
+
+ Descriptor attrd = new DescriptorSupport(new String[] {
+ "name=name", "descriptorType=attribute",
+ });
+ mmbai1 =
+ new ModelMBeanAttributeInfo("name", "type", "descr",
+ true, false, false);
+ mmbai2 =
+ new ModelMBeanAttributeInfo("name", "type", "descr",
+ true, false, false, attrd);
+ Descriptor constrd = new DescriptorSupport(new String[] {
+ "name=name", "descriptorType=operation", "role=constructor",
+ });
+ mmbci1 =
+ new ModelMBeanConstructorInfo("name", "descr", null);
+ mmbci2 =
+ new ModelMBeanConstructorInfo("name", "descr", null, constrd);
+ mmbci3 =
+ new ModelMBeanConstructorInfo("name", "descr", params);
+ mmbci4 =
+ new ModelMBeanConstructorInfo("name", "descr", params, constrd);
+ Descriptor operd = new DescriptorSupport(new String[] {
+ "name=name", "descriptorType=operation",
+ });
+ mmboi1 =
+ new ModelMBeanOperationInfo("name", "descr", null, "type", ACTION);
+ mmboi2 =
+ new ModelMBeanOperationInfo("name", "descr", null, "type", ACTION,
+ operd);
+ mmboi3 =
+ new ModelMBeanOperationInfo("name", "descr", params, "type", ACTION);
+ mmboi4 =
+ new ModelMBeanOperationInfo("name", "descr", params, "type", ACTION,
+ operd);
+ Descriptor notifd = new DescriptorSupport(new String[] {
+ "name=name", "descriptorType=notification",
+ });
+ mmbni1 =
+ new ModelMBeanNotificationInfo(null, "name", "descr");
+ mmbni2 =
+ new ModelMBeanNotificationInfo(null, "name", "descr", notifd);
+ mmbni3 =
+ new ModelMBeanNotificationInfo(new String[] {"type"}, "name", "descr");
+ mmbni4 =
+ new ModelMBeanNotificationInfo(new String[] {"type"}, "name",
+ "descr", notifd);
+ Descriptor mbeand = new DescriptorSupport(new String[] {
+ "name=name", "descriptorType=mbean",
+ });
+ mmbi1 =
+ new ModelMBeanInfoSupport("class", "descr", null, null, null, null);
+ mmbi2 =
+ new ModelMBeanInfoSupport("class", "descr", null, null, null, null,
+ mbeand);
+ mmbi3 =
+ new ModelMBeanInfoSupport(
+ "class", "descr",
+ new ModelMBeanAttributeInfo[] {mmbai1, mmbai2},
+ new ModelMBeanConstructorInfo[] {mmbci1, mmbci2, mmbci3, mmbci4},
+ new ModelMBeanOperationInfo[] {mmboi1, mmboi2, mmboi3, mmboi4},
+ new ModelMBeanNotificationInfo[] {mmbni1, mmbni2, mmbni3, mmbni4});
+ mmbi4 =
+ new ModelMBeanInfoSupport(
+ "class", "descr",
+ new ModelMBeanAttributeInfo[] {mmbai1, mmbai2},
+ new ModelMBeanConstructorInfo[] {mmbci1, mmbci2, mmbci3, mmbci4},
+ new ModelMBeanOperationInfo[] {mmboi1, mmboi2, mmboi3, mmboi4},
+ new ModelMBeanNotificationInfo[] {mmbni1, mmbni2, mmbni3, mmbni4},
+ mbeand);
+
+ objects = new Serializable[] {
+ mbai, mbpi, mbci1, mbci2, mbni1, mbni2, mboi1, mboi2, mbi1, mbi2,
+
+ ombai1, ombai2, ombai3, ombai4,
+ ombpi1, ombpi2, ombpi3, ombpi4,
+ ombci1, ombci2,
+ omboi1, omboi2,
+ ombi1, ombi2,
+
+ mmbai1, mmbai2,
+ mmbci1, mmbci2, mmbci3, mmbci4,
+ mmboi1, mmboi2, mmboi3, mmboi4,
+ mmbni1, mmbni2, mmbni3, mmbni4,
+ };
+ }
+}
diff --git a/test/javax/management/descriptor/SerializedInfo.java b/test/javax/management/descriptor/SerializedInfo.java
new file mode 100644
index 0000000..022249a
--- /dev/null
+++ b/test/javax/management/descriptor/SerializedInfo.java
@@ -0,0 +1,381 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+// Generated by: MBeanInfoInteropTest generate SerializedInfo
+import java.io.*;
+public class SerializedInfo {
+public static final byte[] BYTES = {
+-84,-19,0,5,115,114,0,35,106,97,118,97,120,46,109,97,
+110,97,103,101,109,101,110,116,46,77,66,101,97,110,65,116,
+116,114,105,98,117,116,101,73,110,102,111,119,-8,41,59,106,
+41,68,-40,2,0,4,90,0,2,105,115,90,0,6,105,115,
+82,101,97,100,90,0,7,105,115,87,114,105,116,101,76,0,
+13,97,116,116,114,105,98,117,116,101,84,121,112,101,116,0,
+18,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,
+110,103,59,120,114,0,33,106,97,118,97,120,46,109,97,110,
+97,103,101,109,101,110,116,46,77,66,101,97,110,70,101,97,
+116,117,114,101,73,110,102,111,54,-37,117,-36,-62,-63,85,33,
+2,0,2,76,0,11,100,101,115,99,114,105,112,116,105,111,
+110,113,0,126,0,1,76,0,4,110,97,109,101,113,0,126,
+0,1,120,112,116,0,5,100,101,115,99,114,116,0,4,110,
+97,109,101,0,1,0,116,0,4,116,121,112,101,115,114,0,
+35,106,97,118,97,120,46,109,97,110,97,103,101,109,101,110,
+116,46,77,66,101,97,110,80,97,114,97,109,101,116,101,114,
+73,110,102,111,103,37,-11,-84,-39,123,54,2,2,0,1,76,
+0,4,116,121,112,101,113,0,126,0,1,120,113,0,126,0,
+2,113,0,126,0,4,113,0,126,0,5,113,0,126,0,6,
+115,114,0,37,106,97,118,97,120,46,109,97,110,97,103,101,
+109,101,110,116,46,77,66,101,97,110,67,111,110,115,116,114,
+117,99,116,111,114,73,110,102,111,61,-120,-78,120,-103,-60,48,
+75,2,0,1,91,0,9,115,105,103,110,97,116,117,114,101,
+116,0,38,91,76,106,97,118,97,120,47,109,97,110,97,103,
+101,109,101,110,116,47,77,66,101,97,110,80,97,114,97,109,
+101,116,101,114,73,110,102,111,59,120,113,0,126,0,2,113,
+0,126,0,4,113,0,126,0,5,117,114,0,38,91,76,106,
+97,118,97,120,46,109,97,110,97,103,101,109,101,110,116,46,
+77,66,101,97,110,80,97,114,97,109,101,116,101,114,73,110,
+102,111,59,-51,104,101,54,3,-80,-18,54,2,0,0,120,112,
+0,0,0,0,115,113,0,126,0,9,113,0,126,0,4,113,
+0,126,0,5,117,113,0,126,0,12,0,0,0,1,113,0,
+126,0,8,115,114,0,38,106,97,118,97,120,46,109,97,110,
+97,103,101,109,101,110,116,46,77,66,101,97,110,78,111,116,
+105,102,105,99,97,116,105,111,110,73,110,102,111,-54,9,-70,
+-87,-35,115,-3,72,2,0,1,91,0,5,116,121,112,101,115,
+116,0,19,91,76,106,97,118,97,47,108,97,110,103,47,83,
+116,114,105,110,103,59,120,113,0,126,0,2,113,0,126,0,
+4,113,0,126,0,5,117,114,0,19,91,76,106,97,118,97,
+46,108,97,110,103,46,83,116,114,105,110,103,59,-83,-46,86,
+-25,-23,29,123,71,2,0,0,120,112,0,0,0,0,115,113,
+0,126,0,16,113,0,126,0,4,113,0,126,0,5,117,113,
+0,126,0,19,0,0,0,1,113,0,126,0,6,115,114,0,
+35,106,97,118,97,120,46,109,97,110,97,103,101,109,101,110,
+116,46,77,66,101,97,110,79,112,101,114,97,116,105,111,110,
+73,110,102,111,-86,64,71,34,-107,-2,-125,-98,2,0,3,73,
+0,6,105,109,112,97,99,116,91,0,9,115,105,103,110,97,
+116,117,114,101,113,0,126,0,10,76,0,4,116,121,112,101,
+113,0,126,0,1,120,113,0,126,0,2,113,0,126,0,4,
+113,0,126,0,5,0,0,0,1,113,0,126,0,13,113,0,
+126,0,6,115,113,0,126,0,23,113,0,126,0,4,113,0,
+126,0,5,0,0,0,0,117,113,0,126,0,12,0,0,0,
+1,113,0,126,0,8,113,0,126,0,6,115,114,0,26,106,
+97,118,97,120,46,109,97,110,97,103,101,109,101,110,116,46,
+77,66,101,97,110,73,110,102,111,-90,121,94,47,8,86,-119,
+-55,2,0,6,91,0,10,97,116,116,114,105,98,117,116,101,
+115,116,0,38,91,76,106,97,118,97,120,47,109,97,110,97,
+103,101,109,101,110,116,47,77,66,101,97,110,65,116,116,114,
+105,98,117,116,101,73,110,102,111,59,76,0,9,99,108,97,
+115,115,78,97,109,101,113,0,126,0,1,91,0,12,99,111,
+110,115,116,114,117,99,116,111,114,115,116,0,40,91,76,106,
+97,118,97,120,47,109,97,110,97,103,101,109,101,110,116,47,
+77,66,101,97,110,67,111,110,115,116,114,117,99,116,111,114,
+73,110,102,111,59,76,0,11,100,101,115,99,114,105,112,116,
+105,111,110,113,0,126,0,1,91,0,13,110,111,116,105,102,
+105,99,97,116,105,111,110,115,116,0,41,91,76,106,97,118,
+97,120,47,109,97,110,97,103,101,109,101,110,116,47,77,66,
+101,97,110,78,111,116,105,102,105,99,97,116,105,111,110,73,
+110,102,111,59,91,0,10,111,112,101,114,97,116,105,111,110,
+115,116,0,38,91,76,106,97,118,97,120,47,109,97,110,97,
+103,101,109,101,110,116,47,77,66,101,97,110,79,112,101,114,
+97,116,105,111,110,73,110,102,111,59,120,112,117,114,0,38,
+91,76,106,97,118,97,120,46,109,97,110,97,103,101,109,101,
+110,116,46,77,66,101,97,110,65,116,116,114,105,98,117,116,
+101,73,110,102,111,59,59,-9,88,-60,104,-90,1,65,2,0,
+0,120,112,0,0,0,0,116,0,5,99,108,97,115,115,117,
+114,0,40,91,76,106,97,118,97,120,46,109,97,110,97,103,
+101,109,101,110,116,46,77,66,101,97,110,67,111,110,115,116,
+114,117,99,116,111,114,73,110,102,111,59,-76,-72,-63,-118,31,
+123,25,-11,2,0,0,120,112,0,0,0,0,113,0,126,0,
+4,117,114,0,41,91,76,106,97,118,97,120,46,109,97,110,
+97,103,101,109,101,110,116,46,77,66,101,97,110,78,111,116,
+105,102,105,99,97,116,105,111,110,73,110,102,111,59,-123,-122,
+80,111,18,-75,-48,-81,2,0,0,120,112,0,0,0,0,117,
+114,0,38,91,76,106,97,118,97,120,46,109,97,110,97,103,
+101,109,101,110,116,46,77,66,101,97,110,79,112,101,114,97,
+116,105,111,110,73,110,102,111,59,-121,15,108,-94,-29,31,79,
+-117,2,0,0,120,112,0,0,0,0,115,113,0,126,0,27,
+117,113,0,126,0,33,0,0,0,1,113,0,126,0,3,113,
+0,126,0,35,117,113,0,126,0,36,0,0,0,2,113,0,
+126,0,11,113,0,126,0,14,113,0,126,0,4,117,113,0,
+126,0,38,0,0,0,2,113,0,126,0,18,113,0,126,0,
+21,117,113,0,126,0,40,0,0,0,2,113,0,126,0,24,
+113,0,126,0,25,115,114,0,56,106,97,118,97,120,46,109,
+97,110,97,103,101,109,101,110,116,46,111,112,101,110,109,98,
+101,97,110,46,79,112,101,110,77,66,101,97,110,65,116,116,
+114,105,98,117,116,101,73,110,102,111,83,117,112,112,111,114,
+116,-68,116,45,45,-28,-120,-79,7,2,0,5,76,0,12,100,
+101,102,97,117,108,116,86,97,108,117,101,116,0,18,76,106,
+97,118,97,47,108,97,110,103,47,79,98,106,101,99,116,59,
+76,0,11,108,101,103,97,108,86,97,108,117,101,115,116,0,
+15,76,106,97,118,97,47,117,116,105,108,47,83,101,116,59,
+76,0,8,109,97,120,86,97,108,117,101,116,0,22,76,106,
+97,118,97,47,108,97,110,103,47,67,111,109,112,97,114,97,
+98,108,101,59,76,0,8,109,105,110,86,97,108,117,101,113,
+0,126,0,50,76,0,8,111,112,101,110,84,121,112,101,116,
+0,37,76,106,97,118,97,120,47,109,97,110,97,103,101,109,
+101,110,116,47,111,112,101,110,109,98,101,97,110,47,79,112,
+101,110,84,121,112,101,59,120,113,0,126,0,0,113,0,126,
+0,4,113,0,126,0,5,0,1,0,116,0,17,106,97,118,
+97,46,108,97,110,103,46,73,110,116,101,103,101,114,112,112,
+112,112,115,114,0,37,106,97,118,97,120,46,109,97,110,97,
+103,101,109,101,110,116,46,111,112,101,110,109,98,101,97,110,
+46,83,105,109,112,108,101,84,121,112,101,30,-65,79,-8,-36,
+101,120,39,2,0,0,120,114,0,35,106,97,118,97,120,46,
+109,97,110,97,103,101,109,101,110,116,46,111,112,101,110,109,
+98,101,97,110,46,79,112,101,110,84,121,112,101,-128,100,26,
+-111,-23,-22,-34,60,2,0,3,76,0,9,99,108,97,115,115,
+78,97,109,101,113,0,126,0,1,76,0,11,100,101,115,99,
+114,105,112,116,105,111,110,113,0,126,0,1,76,0,8,116,
+121,112,101,78,97,109,101,113,0,126,0,1,120,112,113,0,
+126,0,53,113,0,126,0,53,113,0,126,0,53,115,113,0,
+126,0,47,113,0,126,0,4,113,0,126,0,5,0,1,0,
+113,0,126,0,53,115,114,0,17,106,97,118,97,46,108,97,
+110,103,46,73,110,116,101,103,101,114,18,-30,-96,-92,-9,-127,
+-121,56,2,0,1,73,0,5,118,97,108,117,101,120,114,0,
+16,106,97,118,97,46,108,97,110,103,46,78,117,109,98,101,
+114,-122,-84,-107,29,11,-108,-32,-117,2,0,0,120,112,0,0,
+0,5,112,112,112,113,0,126,0,56,115,113,0,126,0,47,
+113,0,126,0,4,113,0,126,0,5,0,1,0,113,0,126,
+0,53,113,0,126,0,60,112,115,113,0,126,0,58,0,0,
+0,6,115,113,0,126,0,58,0,0,0,1,113,0,126,0,
+56,115,113,0,126,0,47,113,0,126,0,4,113,0,126,0,
+5,0,1,0,113,0,126,0,53,113,0,126,0,60,115,114,
+0,37,106,97,118,97,46,117,116,105,108,46,67,111,108,108,
+101,99,116,105,111,110,115,36,85,110,109,111,100,105,102,105,
+97,98,108,101,83,101,116,-128,29,-110,-47,-113,-101,-128,85,2,
+0,0,120,114,0,44,106,97,118,97,46,117,116,105,108,46,
+67,111,108,108,101,99,116,105,111,110,115,36,85,110,109,111,
+100,105,102,105,97,98,108,101,67,111,108,108,101,99,116,105,
+111,110,25,66,0,-128,-53,94,-9,30,2,0,1,76,0,1,
+99,116,0,22,76,106,97,118,97,47,117,116,105,108,47,67,
+111,108,108,101,99,116,105,111,110,59,120,112,115,114,0,17,
+106,97,118,97,46,117,116,105,108,46,72,97,115,104,83,101,
+116,-70,68,-123,-107,-106,-72,-73,52,3,0,0,120,112,119,12,
+0,0,0,8,63,-128,0,0,0,0,0,4,115,113,0,126,
+0,58,0,0,0,2,115,113,0,126,0,58,0,0,0,3,
+115,113,0,126,0,58,0,0,0,7,113,0,126,0,60,120,
+112,112,113,0,126,0,56,115,114,0,56,106,97,118,97,120,
+46,109,97,110,97,103,101,109,101,110,116,46,111,112,101,110,
+109,98,101,97,110,46,79,112,101,110,77,66,101,97,110,80,
+97,114,97,109,101,116,101,114,73,110,102,111,83,117,112,112,
+111,114,116,-101,-104,14,124,111,-85,-71,-114,2,0,5,76,0,
+12,100,101,102,97,117,108,116,86,97,108,117,101,113,0,126,
+0,48,76,0,11,108,101,103,97,108,86,97,108,117,101,115,
+113,0,126,0,49,76,0,8,109,97,120,86,97,108,117,101,
+113,0,126,0,50,76,0,8,109,105,110,86,97,108,117,101,
+113,0,126,0,50,76,0,8,111,112,101,110,84,121,112,101,
+113,0,126,0,51,120,113,0,126,0,7,113,0,126,0,4,
+116,0,5,110,97,109,101,49,113,0,126,0,53,112,112,112,
+112,113,0,126,0,56,115,113,0,126,0,74,113,0,126,0,
+4,116,0,5,110,97,109,101,50,113,0,126,0,53,113,0,
+126,0,60,112,112,112,113,0,126,0,56,115,113,0,126,0,
+74,113,0,126,0,4,116,0,5,110,97,109,101,51,113,0,
+126,0,53,113,0,126,0,60,112,113,0,126,0,62,113,0,
+126,0,63,113,0,126,0,56,115,113,0,126,0,74,113,0,
+126,0,4,116,0,5,110,97,109,101,52,113,0,126,0,53,
+113,0,126,0,60,115,113,0,126,0,65,115,113,0,126,0,
+69,119,12,0,0,0,8,63,-128,0,0,0,0,0,4,113,
+0,126,0,71,113,0,126,0,72,113,0,126,0,73,113,0,
+126,0,60,120,112,112,113,0,126,0,56,115,114,0,58,106,
+97,118,97,120,46,109,97,110,97,103,101,109,101,110,116,46,
+111,112,101,110,109,98,101,97,110,46,79,112,101,110,77,66,
+101,97,110,67,111,110,115,116,114,117,99,116,111,114,73,110,
+102,111,83,117,112,112,111,114,116,-62,-18,125,-78,-52,102,122,
+-11,2,0,0,120,113,0,126,0,9,113,0,126,0,4,113,
+0,126,0,5,113,0,126,0,13,115,113,0,126,0,85,113,
+0,126,0,4,113,0,126,0,5,117,113,0,126,0,12,0,
+0,0,4,113,0,126,0,75,113,0,126,0,77,113,0,126,
+0,79,113,0,126,0,81,115,114,0,56,106,97,118,97,120,
+46,109,97,110,97,103,101,109,101,110,116,46,111,112,101,110,
+109,98,101,97,110,46,79,112,101,110,77,66,101,97,110,79,
+112,101,114,97,116,105,111,110,73,110,102,111,83,117,112,112,
+111,114,116,69,88,105,115,-56,3,34,22,2,0,1,76,0,
+14,114,101,116,117,114,110,79,112,101,110,84,121,112,101,113,
+0,126,0,51,120,113,0,126,0,23,113,0,126,0,4,113,
+0,126,0,5,0,0,0,1,113,0,126,0,13,113,0,126,
+0,53,113,0,126,0,56,115,113,0,126,0,89,113,0,126,
+0,4,113,0,126,0,5,0,0,0,1,117,113,0,126,0,
+12,0,0,0,4,113,0,126,0,75,113,0,126,0,77,113,
+0,126,0,79,113,0,126,0,81,113,0,126,0,53,113,0,
+126,0,56,115,114,0,47,106,97,118,97,120,46,109,97,110,
+97,103,101,109,101,110,116,46,111,112,101,110,109,98,101,97,
+110,46,79,112,101,110,77,66,101,97,110,73,110,102,111,83,
+117,112,112,111,114,116,60,92,40,-113,38,68,117,4,2,0,
+0,120,113,0,126,0,27,113,0,126,0,34,113,0,126,0,
+35,113,0,126,0,37,113,0,126,0,4,113,0,126,0,39,
+113,0,126,0,41,115,113,0,126,0,93,117,113,0,126,0,
+33,0,0,0,4,113,0,126,0,52,113,0,126,0,57,113,
+0,126,0,61,113,0,126,0,64,113,0,126,0,35,117,113,
+0,126,0,36,0,0,0,2,113,0,126,0,86,113,0,126,
+0,87,113,0,126,0,4,117,113,0,126,0,38,0,0,0,
+2,113,0,126,0,18,113,0,126,0,21,117,113,0,126,0,
+40,0,0,0,2,113,0,126,0,90,113,0,126,0,91,115,
+114,0,51,106,97,118,97,120,46,109,97,110,97,103,101,109,
+101,110,116,46,109,111,100,101,108,109,98,101,97,110,46,77,
+111,100,101,108,77,66,101,97,110,65,116,116,114,105,98,117,
+116,101,73,110,102,111,85,-55,64,-95,-17,14,103,113,3,0,
+1,76,0,14,97,116,116,114,68,101,115,99,114,105,112,116,
+111,114,116,0,29,76,106,97,118,97,120,47,109,97,110,97,
+103,101,109,101,110,116,47,68,101,115,99,114,105,112,116,111,
+114,59,120,113,0,126,0,0,113,0,126,0,4,113,0,126,
+0,5,0,1,0,113,0,126,0,6,115,114,0,45,106,97,
+118,97,120,46,109,97,110,97,103,101,109,101,110,116,46,109,
+111,100,101,108,109,98,101,97,110,46,68,101,115,99,114,105,
+112,116,111,114,83,117,112,112,111,114,116,-88,-86,-31,-37,-95,
+-23,-32,1,3,0,1,76,0,10,100,101,115,99,114,105,112,
+116,111,114,116,0,19,76,106,97,118,97,47,117,116,105,108,
+47,72,97,115,104,77,97,112,59,120,112,115,114,0,17,106,
+97,118,97,46,117,116,105,108,46,72,97,115,104,77,97,112,
+5,7,-38,-63,-61,22,96,-47,3,0,2,70,0,10,108,111,
+97,100,70,97,99,116,111,114,73,0,9,116,104,114,101,115,
+104,111,108,100,120,112,63,64,0,0,0,0,0,12,119,8,
+0,0,0,16,0,0,0,3,116,0,14,100,101,115,99,114,
+105,112,116,111,114,84,121,112,101,116,0,9,97,116,116,114,
+105,98,117,116,101,116,0,4,110,97,109,101,116,0,4,110,
+97,109,101,116,0,11,100,105,115,112,108,97,121,78,97,109,
+101,116,0,4,110,97,109,101,120,120,120,115,113,0,126,0,
+100,113,0,126,0,4,113,0,126,0,5,0,1,0,113,0,
+126,0,6,115,113,0,126,0,103,115,113,0,126,0,106,63,
+64,0,0,0,0,0,12,119,8,0,0,0,16,0,0,0,
+3,116,0,14,100,101,115,99,114,105,112,116,111,114,84,121,
+112,101,116,0,9,97,116,116,114,105,98,117,116,101,116,0,
+4,110,97,109,101,116,0,4,110,97,109,101,116,0,11,100,
+105,115,112,108,97,121,78,97,109,101,113,0,126,0,5,120,
+120,120,115,114,0,53,106,97,118,97,120,46,109,97,110,97,
+103,101,109,101,110,116,46,109,111,100,101,108,109,98,101,97,
+110,46,77,111,100,101,108,77,66,101,97,110,67,111,110,115,
+116,114,117,99,116,111,114,73,110,102,111,53,-101,-14,-109,74,
+32,25,-22,3,0,1,76,0,14,99,111,110,115,68,101,115,
+99,114,105,112,116,111,114,113,0,126,0,101,120,113,0,126,
+0,9,113,0,126,0,4,113,0,126,0,5,113,0,126,0,
+13,115,113,0,126,0,103,115,113,0,126,0,106,63,64,0,
+0,0,0,0,12,119,8,0,0,0,16,0,0,0,4,116,
+0,14,100,101,115,99,114,105,112,116,111,114,84,121,112,101,
+116,0,9,111,112,101,114,97,116,105,111,110,116,0,4,114,
+111,108,101,116,0,11,99,111,110,115,116,114,117,99,116,111,
+114,116,0,11,100,105,115,112,108,97,121,110,97,109,101,116,
+0,4,110,97,109,101,116,0,4,110,97,109,101,116,0,4,
+110,97,109,101,120,120,120,115,113,0,126,0,122,113,0,126,
+0,4,113,0,126,0,5,113,0,126,0,13,115,113,0,126,
+0,103,115,113,0,126,0,106,63,64,0,0,0,0,0,12,
+119,8,0,0,0,16,0,0,0,4,116,0,14,100,101,115,
+99,114,105,112,116,111,114,84,121,112,101,116,0,9,111,112,
+101,114,97,116,105,111,110,116,0,4,114,111,108,101,116,0,
+11,99,111,110,115,116,114,117,99,116,111,114,116,0,4,110,
+97,109,101,116,0,4,110,97,109,101,113,0,126,0,121,113,
+0,126,0,5,120,120,120,115,113,0,126,0,122,113,0,126,
+0,4,113,0,126,0,5,117,113,0,126,0,12,0,0,0,
+1,113,0,126,0,8,115,113,0,126,0,103,115,113,0,126,
+0,106,63,64,0,0,0,0,0,12,119,8,0,0,0,16,
+0,0,0,4,116,0,14,100,101,115,99,114,105,112,116,111,
+114,84,121,112,101,116,0,9,111,112,101,114,97,116,105,111,
+110,116,0,4,114,111,108,101,116,0,11,99,111,110,115,116,
+114,117,99,116,111,114,116,0,11,100,105,115,112,108,97,121,
+110,97,109,101,116,0,4,110,97,109,101,116,0,4,110,97,
+109,101,116,0,4,110,97,109,101,120,120,120,115,113,0,126,
+0,122,113,0,126,0,4,113,0,126,0,5,117,113,0,126,
+0,12,0,0,0,1,113,0,126,0,8,115,113,0,126,0,
+103,115,113,0,126,0,106,63,64,0,0,0,0,0,12,119,
+8,0,0,0,16,0,0,0,4,113,0,126,0,-119,113,0,
+126,0,-118,113,0,126,0,-117,113,0,126,0,-116,113,0,126,
+0,-115,113,0,126,0,-114,113,0,126,0,121,113,0,126,0,
+5,120,120,120,115,114,0,51,106,97,118,97,120,46,109,97,
+110,97,103,101,109,101,110,116,46,109,111,100,101,108,109,98,
+101,97,110,46,77,111,100,101,108,77,66,101,97,110,79,112,
+101,114,97,116,105,111,110,73,110,102,111,90,-88,-19,58,-31,
+-97,23,-31,3,0,1,76,0,19,111,112,101,114,97,116,105,
+111,110,68,101,115,99,114,105,112,116,111,114,113,0,126,0,
+101,120,113,0,126,0,23,113,0,126,0,4,113,0,126,0,
+5,0,0,0,1,113,0,126,0,13,113,0,126,0,6,115,
+113,0,126,0,103,115,113,0,126,0,106,63,64,0,0,0,
+0,0,12,119,8,0,0,0,16,0,0,0,4,116,0,14,
+100,101,115,99,114,105,112,116,111,114,84,121,112,101,116,0,
+9,111,112,101,114,97,116,105,111,110,116,0,4,114,111,108,
+101,116,0,9,111,112,101,114,97,116,105,111,110,116,0,11,
+100,105,115,112,108,97,121,110,97,109,101,116,0,4,110,97,
+109,101,116,0,4,110,97,109,101,116,0,4,110,97,109,101,
+120,120,120,115,113,0,126,0,-97,113,0,126,0,4,113,0,
+126,0,5,0,0,0,1,113,0,126,0,13,113,0,126,0,
+6,115,113,0,126,0,103,115,113,0,126,0,106,63,64,0,
+0,0,0,0,12,119,8,0,0,0,16,0,0,0,4,116,
+0,14,100,101,115,99,114,105,112,116,111,114,84,121,112,101,
+116,0,9,111,112,101,114,97,116,105,111,110,116,0,4,114,
+111,108,101,116,0,9,111,112,101,114,97,116,105,111,110,116,
+0,4,110,97,109,101,116,0,4,110,97,109,101,113,0,126,
+0,121,113,0,126,0,5,120,120,120,115,113,0,126,0,-97,
+113,0,126,0,4,113,0,126,0,5,0,0,0,1,117,113,
+0,126,0,12,0,0,0,1,113,0,126,0,8,113,0,126,
+0,6,115,113,0,126,0,103,115,113,0,126,0,106,63,64,
+0,0,0,0,0,12,119,8,0,0,0,16,0,0,0,4,
+116,0,14,100,101,115,99,114,105,112,116,111,114,84,121,112,
+101,116,0,9,111,112,101,114,97,116,105,111,110,116,0,4,
+114,111,108,101,116,0,9,111,112,101,114,97,116,105,111,110,
+116,0,11,100,105,115,112,108,97,121,110,97,109,101,116,0,
+4,110,97,109,101,116,0,4,110,97,109,101,116,0,4,110,
+97,109,101,120,120,120,115,113,0,126,0,-97,113,0,126,0,
+4,113,0,126,0,5,0,0,0,1,117,113,0,126,0,12,
+0,0,0,1,113,0,126,0,8,113,0,126,0,6,115,113,
+0,126,0,103,115,113,0,126,0,106,63,64,0,0,0,0,
+0,12,119,8,0,0,0,16,0,0,0,4,113,0,126,0,
+-82,113,0,126,0,-81,113,0,126,0,-80,113,0,126,0,-79,
+113,0,126,0,-78,113,0,126,0,-77,113,0,126,0,121,113,
+0,126,0,5,120,120,120,115,114,0,54,106,97,118,97,120,
+46,109,97,110,97,103,101,109,101,110,116,46,109,111,100,101,
+108,109,98,101,97,110,46,77,111,100,101,108,77,66,101,97,
+110,78,111,116,105,102,105,99,97,116,105,111,110,73,110,102,
+111,-104,-85,-96,57,-97,-18,82,91,3,0,1,76,0,22,110,
+111,116,105,102,105,99,97,116,105,111,110,68,101,115,99,114,
+105,112,116,111,114,113,0,126,0,101,120,113,0,126,0,16,
+113,0,126,0,4,113,0,126,0,5,113,0,126,0,20,115,
+113,0,126,0,103,115,113,0,126,0,106,63,64,0,0,0,
+0,0,12,119,8,0,0,0,16,0,0,0,4,116,0,8,
+115,101,118,101,114,105,116,121,116,0,1,54,116,0,14,100,
+101,115,99,114,105,112,116,111,114,84,121,112,101,116,0,12,
+110,111,116,105,102,105,99,97,116,105,111,110,116,0,4,110,
+97,109,101,116,0,4,110,97,109,101,116,0,11,100,105,115,
+112,108,97,121,78,97,109,101,116,0,4,110,97,109,101,120,
+120,120,115,113,0,126,0,-60,113,0,126,0,4,113,0,126,
+0,5,113,0,126,0,20,115,113,0,126,0,103,115,113,0,
+126,0,106,63,64,0,0,0,0,0,12,119,8,0,0,0,
+16,0,0,0,4,116,0,14,100,101,115,99,114,105,112,116,
+111,114,84,121,112,101,116,0,12,110,111,116,105,102,105,99,
+97,116,105,111,110,116,0,8,115,101,118,101,114,105,116,121,
+116,0,1,54,116,0,4,110,97,109,101,116,0,4,110,97,
+109,101,113,0,126,0,121,113,0,126,0,5,120,120,120,115,
+113,0,126,0,-60,113,0,126,0,4,113,0,126,0,5,117,
+113,0,126,0,19,0,0,0,1,113,0,126,0,6,115,113,
+0,126,0,103,115,113,0,126,0,106,63,64,0,0,0,0,
+0,12,119,8,0,0,0,16,0,0,0,4,116,0,8,115,
+101,118,101,114,105,116,121,116,0,1,54,116,0,14,100,101,
+115,99,114,105,112,116,111,114,84,121,112,101,116,0,12,110,
+111,116,105,102,105,99,97,116,105,111,110,116,0,4,110,97,
+109,101,116,0,4,110,97,109,101,116,0,11,100,105,115,112,
+108,97,121,78,97,109,101,116,0,4,110,97,109,101,120,120,
+120,115,113,0,126,0,-60,113,0,126,0,4,113,0,126,0,
+5,117,113,0,126,0,19,0,0,0,1,113,0,126,0,6,
+115,113,0,126,0,103,115,113,0,126,0,106,63,64,0,0,
+0,0,0,12,119,8,0,0,0,16,0,0,0,4,113,0,
+126,0,-45,113,0,126,0,-44,113,0,126,0,-43,113,0,126,
+0,-42,113,0,126,0,-41,113,0,126,0,-40,113,0,126,0,
+121,113,0,126,0,5,120,120,120,
+};
+}
diff --git a/test/javax/management/descriptor/UnionTest.java b/test/javax/management/descriptor/UnionTest.java
new file mode 100644
index 0000000..0137c61
--- /dev/null
+++ b/test/javax/management/descriptor/UnionTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6273752
+ * @summary Test ImmutableDescriptor.union
+ * @author Eamonn McManus
+ * @run clean UnionTest
+ * @run build UnionTest
+ * @run main UnionTest
+ */
+
+import java.util.Collections;
+import javax.management.Descriptor;
+import javax.management.ImmutableDescriptor;
+import static javax.management.ImmutableDescriptor.union;
+import static javax.management.ImmutableDescriptor.EMPTY_DESCRIPTOR;
+import javax.management.modelmbean.DescriptorSupport;
+
+public class UnionTest {
+ public static void main(String[] args) throws Exception {
+ ImmutableDescriptor immutableEmpty = new ImmutableDescriptor();
+ DescriptorSupport mutableEmpty = new DescriptorSupport();
+
+ checkEmpty(union());
+ checkEmpty(union(immutableEmpty));
+ checkEmpty(union(mutableEmpty));
+ checkEmpty(union(EMPTY_DESCRIPTOR, immutableEmpty, mutableEmpty));
+ checkEmpty(union(null, immutableEmpty, null));
+
+ ImmutableDescriptor immutableNumbers =
+ new ImmutableDescriptor(new String[] {"one", "two", "three"},
+ new Object[] {1, 2, 3});
+ final String[] noNames = null;
+ DescriptorSupport mutableNumbers =
+ new DescriptorSupport(immutableNumbers.getFieldNames(),
+ immutableNumbers.getFieldValues(noNames));
+ ImmutableDescriptor immutableOne =
+ new ImmutableDescriptor(Collections.singletonMap("one", 1));
+ DescriptorSupport mutableOne =
+ new DescriptorSupport(new String[] {"one"}, new Object[] {1});
+ ImmutableDescriptor immutableTwo =
+ new ImmutableDescriptor(Collections.singletonMap("two", 2));
+ DescriptorSupport mutableTwo =
+ new DescriptorSupport(new String[] {"two"}, new Object[] {2});
+ ImmutableDescriptor immutableOneTwo =
+ new ImmutableDescriptor(new String[] {"one", "two"},
+ new Object[] {1, 2});
+
+
+ checkEqual(union(immutableNumbers), immutableNumbers);
+ checkEqual(union(immutableNumbers, mutableNumbers), immutableNumbers);
+ checkEqual(union(mutableNumbers, immutableNumbers), immutableNumbers);
+ checkEqual(union(mutableEmpty, immutableEmpty, immutableNumbers,
+ mutableNumbers, immutableOne), immutableNumbers);
+ checkEqual(union(immutableOne, immutableTwo, immutableNumbers),
+ immutableNumbers);
+ checkEquivalent(union(immutableOne, mutableNumbers), immutableNumbers);
+ checkEquivalent(union(immutableOne, immutableTwo), immutableOneTwo);
+ checkEquivalent(union(mutableOne, mutableTwo), immutableOneTwo);
+
+ if (failure != null)
+ throw new Exception("TEST FAILED: " + failure);
+ System.out.println("TEST PASSED");
+ }
+
+ private static void checkEmpty(ImmutableDescriptor d) {
+ if (d != EMPTY_DESCRIPTOR) {
+ failure = "Union of empty descriptors should be " +
+ "ImmutableDescriptor.EMPTY";
+ System.err.println("FAILED: " + failure);
+ Thread.dumpStack();
+ }
+ }
+
+ private static void checkEqual(ImmutableDescriptor d,
+ ImmutableDescriptor e) {
+ if (d != e) {
+ failure = "Union should produce one of its arguments but does not";
+ System.err.println("FAILED: " + failure);
+ Thread.dumpStack();
+ }
+ }
+
+ private static void checkEquivalent(ImmutableDescriptor d,
+ ImmutableDescriptor e) {
+ if (!d.equals(e)) {
+ failure = "Union produced this: " + d + "; but should have " +
+ "produced this: " + e;
+ System.err.println("FAILED: " + failure);
+ Thread.dumpStack();
+ }
+ }
+
+ private static String failure;
+}
diff --git a/test/javax/management/generified/GenericTest.java b/test/javax/management/generified/GenericTest.java
new file mode 100644
index 0000000..bfd30cc
--- /dev/null
+++ b/test/javax/management/generified/GenericTest.java
@@ -0,0 +1,484 @@
+/*
+ * Copyright 2004-2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4847959 6191402
+ * @summary Test newly-generified APIs
+ * @author Eamonn McManus
+ * @run clean GenericTest
+ * @run build GenericTest
+ * @run main GenericTest
+ */
+
+import java.lang.management.ManagementFactory;
+import java.lang.reflect.*;
+import java.util.*;
+import javax.management.*;
+import javax.management.openmbean.*;
+import javax.management.relation.*;
+import javax.management.timer.Timer;
+import javax.management.timer.TimerMBean;
+
+public class GenericTest {
+ private static int failures;
+
+ public static void main(String[] args) throws Exception {
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+
+ // Check we are really using the generified version
+ boolean generic;
+ Method findmbs = MBeanServerFactory.class.getMethod("findMBeanServer",
+ String.class);
+ Type findmbstype = findmbs.getGenericReturnType();
+ if (!(findmbstype instanceof ParameterizedType)) {
+ System.out.println("FAILURE: API NOT GENERIC!");
+ System.out.println(" MBeanServerFactory.findMBeanServer -> " +
+ findmbstype);
+ failures++;
+ generic = false;
+ } else {
+ System.out.println("OK: this API is generic");
+ generic = true;
+ }
+
+ ArrayList<MBeanServer> mbsList1 =
+ MBeanServerFactory.findMBeanServer(null);
+ checked(mbsList1, MBeanServer.class);
+ ArrayList mbsList2 = MBeanServerFactory.findMBeanServer(null);
+ check("ArrayList<MBeanServer> findMBeanServer", mbsList1.size() == 1);
+ check("ArrayList findMBeanServer", mbsList1.equals(mbsList2));
+
+ Set<ObjectName> names1 =
+ checked(mbs.queryNames(null, null), ObjectName.class);
+ Set names2 = mbs.queryNames(null, null);
+ Set<ObjectName> names3 =
+ checked(((MBeanServerConnection) mbs).queryNames(null, null),
+ ObjectName.class);
+ check("Set<ObjectName> MBeanServer.queryNames", names1.size() >= 1);
+ check("Set MBeanServer.queryNames", names2.size() >= 1);
+ check("Set<ObjectName> MBeanServerConnection.queryNames",
+ names3.size() >= 1);
+ check("queryNames sets same",
+ names1.equals(names2) && names2.equals(names3));
+
+ Set<ObjectInstance> mbeans1 =
+ checked(mbs.queryMBeans(null, null), ObjectInstance.class);
+ Set mbeans2 = mbs.queryMBeans(null, null);
+ Set<ObjectInstance> mbeans3 =
+ checked(((MBeanServerConnection) mbs).queryMBeans(null, null),
+ ObjectInstance.class);
+ check("Set<ObjectInstsance> MBeanServer.queryMBeans",
+ mbeans1.size() >= 1);
+ check("Set MBeanServer.queryMBeans", mbeans2.size() >= 1);
+ check("Set<ObjectInstsance> MBeanServerConnection.queryMBeans",
+ mbeans3.size() >= 1);
+ check("queryMBeans sets same",
+ mbeans1.equals(mbeans2) && mbeans2.equals(mbeans3));
+
+
+ AttributeChangeNotificationFilter acnf =
+ new AttributeChangeNotificationFilter();
+ acnf.enableAttribute("foo");
+ Vector<String> acnfs = acnf.getEnabledAttributes();
+ checked(acnfs, String.class);
+ check("Vector<String> AttributeChangeNotificationFilter.getEnabled" +
+ "Attributes", acnfs.equals(Arrays.asList(new String[] {"foo"})));
+
+ if (generic) {
+ Attribute a = new Attribute("foo", "bar");
+ AttributeList al1 = new AttributeList();
+ al1.add(a);
+ AttributeList al2 =
+ new AttributeList(Arrays.asList(new Attribute[] {a}));
+ check("new AttributeList(List<Attribute>)", al1.equals(al2));
+ List<Attribute> al3 = checked(al1.asList(), Attribute.class);
+ al3.remove(a);
+ check("List<Attribute> AttributeList.asList()",
+ al1.equals(al3) && al1.isEmpty());
+ }
+
+ List<ObjectName> namelist1 = new ArrayList<ObjectName>(names1);
+ Role role = new Role("rolename", namelist1);
+ List<ObjectName> namelist2 =
+ checked(role.getRoleValue(), ObjectName.class);
+ check("new Role(String,List<ObjectName>).getRoleValue() -> " +
+ "List<ObjectName>", namelist1.equals(namelist2));
+
+ RoleList rl1 = new RoleList();
+ rl1.add(role);
+ RoleList rl2 = new RoleList(Arrays.asList(new Role[] {role}));
+ check("new RoleList(List<Role>)", rl1.equals(rl2));
+ if (generic) {
+ List<Role> rl3 = checked(rl1.asList(), Role.class);
+ rl3.remove(role);
+ check("List<Role> RoleList.asList()",
+ rl1.equals(rl3) && rl1.isEmpty());
+ }
+
+ RoleUnresolved ru =
+ new RoleUnresolved("rolename", namelist1,
+ RoleStatus.LESS_THAN_MIN_ROLE_DEGREE);
+ List<ObjectName> namelist3 =
+ checked(ru.getRoleValue(), ObjectName.class);
+ check("new RoleUnresolved(...List<ObjectName>...).getRoleValue() -> " +
+ "List<ObjectName>", namelist1.equals(namelist3));
+
+ RoleUnresolvedList rul1 = new RoleUnresolvedList();
+ rul1.add(ru);
+ RoleUnresolvedList rul2 =
+ new RoleUnresolvedList(Arrays.asList(new RoleUnresolved[] {ru}));
+ check("new RoleUnresolvedList(List<RoleUnresolved>", rul1.equals(rul2));
+ if (generic) {
+ List<RoleUnresolved> rul3 =
+ checked(rul1.asList(), RoleUnresolved.class);
+ rul3.remove(ru);
+ check("List<RoleUnresolved> RoleUnresolvedList.asList()",
+ rul1.equals(rul3) && rul1.isEmpty());
+ }
+
+ // This case basically just tests that we can compile this sort of thing
+ OpenMBeanAttributeInfo ombai1 =
+ new OpenMBeanAttributeInfoSupport("a", "a descr",
+ SimpleType.INTEGER,
+ true, true, false);
+ CompositeType ct =
+ new CompositeType("ct", "ct descr", new String[] {"item1"},
+ new String[] {"item1 descr"},
+ new OpenType[] {SimpleType.INTEGER});
+ OpenMBeanAttributeInfo ombai2 =
+ new OpenMBeanAttributeInfoSupport("a", "a descr",
+ ct, true, true, false);
+ TabularType tt =
+ new TabularType("tt", "tt descr", ct, new String[] {"item1"});
+ OpenMBeanAttributeInfo ombai3 =
+ new OpenMBeanAttributeInfoSupport("a", "a descr",
+ tt, true, true, false);
+ ArrayType<String[][]> at =
+ new ArrayType<String[][]>(2, SimpleType.STRING);
+ OpenMBeanAttributeInfo ombai4 =
+ new OpenMBeanAttributeInfoSupport("a", "a descr",
+ at, true, true, false);
+ OpenMBeanAttributeInfo ombai4a =
+ new OpenMBeanAttributeInfoSupport("a", "a descr",
+ (ArrayType) at,
+ true, true, false);
+ OpenMBeanAttributeInfo ombai5 =
+ new OpenMBeanAttributeInfoSupport("a", "a descr",
+ SimpleType.INTEGER,
+ true, true, false,
+ 5, 1, 9);
+ OpenMBeanAttributeInfo ombai6 =
+ new OpenMBeanAttributeInfoSupport("a", "a descr",
+ SimpleType.INTEGER,
+ true, true, false,
+ 5, new Integer[] {1, 5});
+
+ OpenMBeanInfo ombi =
+ new OpenMBeanInfoSupport("a.a", "a.a descr",
+ new OpenMBeanAttributeInfo[] {
+ ombai1, ombai2, ombai3, ombai4,
+ ombai5, ombai6,
+ },
+ null, null, null);
+
+ Map<String,Integer> itemMap =
+ checked(singletonMap("item1", 5),
+ String.class, Integer.class);
+ CompositeData cd =
+ new CompositeDataSupport(ct, itemMap);
+ check("CompositeDataSupport(CompositeType, Map<String,?>",
+ cd.get("item1").equals(5));
+
+ Set<String> ctkeys = checked(ct.keySet(), String.class);
+ check("Set<String> CompositeType.keySet()",
+ ctkeys.equals(singleton("item1")));
+
+ List<String> ttindex = checked(tt.getIndexNames(), String.class);
+ check("Set<String> TabularType.getIndexNames()",
+ ttindex.equals(singletonList("item1")));
+
+ TabularData td = new TabularDataSupport(tt);
+ td.putAll(new CompositeData[] {cd});
+ List<Integer> tdkey = checked(singletonList(5), Integer.class);
+ Set<List<Integer>> tdkeys = checked(singleton(tdkey),
+ (Class<List<Integer>>) tdkey.getClass());
+ Collection<CompositeData> tdvalues = checked(singleton(cd),
+ CompositeData.class);
+ check("Set<List<?>> TabularDataSupport.keySet()",
+ td.keySet().equals(tdkeys));
+ check("Collection<CompositeData> TabularDataSupport.values()",
+ td.values().iterator().next().equals(tdvalues.iterator().next()));
+
+ ObjectName stupidName = new ObjectName("stupid:a=b");
+ mbs.registerMBean(new Stupid(), stupidName);
+ StupidMBean proxy =
+ MBeanServerInvocationHandler.newProxyInstance(mbs,
+ stupidName,
+ StupidMBean.class,
+ false);
+ check("MBeanServerInvocationHandler.newProxyInstance",
+ proxy.getFive() == 5);
+ mbs.unregisterMBean(stupidName);
+
+ mbs.registerMBean(new StandardMBean(new Stupid(), StupidMBean.class),
+ stupidName);
+ check("<T> StandardMBean(T impl, Class<T> intf)",
+ proxy.getFive() == 5);
+
+ // Following is based on the package.html for javax.management.relation
+ // Create the Relation Service MBean
+ ObjectName relSvcName = new ObjectName(":type=RelationService");
+ RelationService relSvcObject = new RelationService(true);
+ mbs.registerMBean(relSvcObject, relSvcName);
+
+ // Create an MBean proxy for easier access to the Relation Service
+ RelationServiceMBean relSvc =
+ MBeanServerInvocationHandler.newProxyInstance(mbs, relSvcName,
+ RelationServiceMBean.class,
+ false);
+
+ // Define the DependsOn relation type
+ RoleInfo[] dependsOnRoles = {
+ new RoleInfo("dependent", Module.class.getName()),
+ new RoleInfo("dependedOn", Module.class.getName())
+ };
+ relSvc.createRelationType("DependsOn", dependsOnRoles);
+
+ // Now define a relation instance "moduleA DependsOn moduleB"
+
+ ObjectName moduleA = new ObjectName(":type=Module,name=A");
+ ObjectName moduleB = new ObjectName(":type=Module,name=B");
+
+ // Following two lines added to example:
+ mbs.registerMBean(new Module(), moduleA);
+ mbs.registerMBean(new Module(), moduleB);
+
+ Role dependent = new Role("dependent", singletonList(moduleA));
+ Role dependedOn = new Role("dependedOn", singletonList(moduleB));
+ Role[] roleArray = {dependent, dependedOn};
+ RoleList roles = new RoleList(Arrays.asList(roleArray));
+ relSvc.createRelation("A-DependsOn-B", "DependsOn", roles);
+
+ // Query the Relation Service to find what modules moduleA depends on
+ Map<ObjectName,List<String>> dependentAMap =
+ relSvc.findAssociatedMBeans(moduleA, "DependsOn", "dependent");
+ Set<ObjectName> dependentASet = dependentAMap.keySet();
+ dependentASet = checked(dependentASet, ObjectName.class);
+ // Set of ObjectName containing moduleB
+ check("Map<ObjectName,List<String>> RelationService.findAssociatedMBeans",
+ dependentAMap.size() == 1 &&
+ dependentASet.equals(singleton(moduleB)));
+
+ Map<String,List<String>> refRels =
+ relSvc.findReferencingRelations(moduleA, "DependsOn", "dependent");
+ List<String> refRoles =
+ checked(refRels.get("A-DependsOn-B"), String.class);
+ check("Map<String,List<String>> RelationService.findReferencingRelations",
+ refRoles.equals(singletonList("dependent")));
+
+ List<String> relsOfType = relSvc.findRelationsOfType("DependsOn");
+ relsOfType = checked(relsOfType, String.class);
+ check("List<String> RelationService.findRelationsOfType",
+ relsOfType.equals(singletonList("A-DependsOn-B")));
+
+ List<String> allRelIds = relSvc.getAllRelationIds();
+ allRelIds = checked(allRelIds, String.class);
+ check("List<String> RelationService.getAllRelationIds()",
+ allRelIds.equals(singletonList("A-DependsOn-B")));
+
+ List<String> allRelTypes = relSvc.getAllRelationTypeNames();
+ allRelTypes = checked(allRelTypes, String.class);
+ check("List<String> RelationService.getAllRelationTypeNames",
+ allRelTypes.equals(singletonList("DependsOn")));
+
+ Map<ObjectName,List<String>> refdMBeans =
+ relSvc.getReferencedMBeans("A-DependsOn-B");
+ check("Map<ObjectName,List<String>> RelationService.getReferencedMBeans",
+ refdMBeans.get(moduleA).equals(singletonList("dependent")) &&
+ refdMBeans.get(moduleB).equals(singletonList("dependedOn")));
+
+ List<ObjectName> roleContents =
+ checked(relSvc.getRole("A-DependsOn-B", "dependent"),
+ ObjectName.class);
+ check("List<ObjectName> RelationService.getRole",
+ roleContents.equals(singletonList(moduleA)));
+
+ RoleInfo roleInfoDependent =
+ relSvc.getRoleInfo("DependsOn", "dependent");
+ RoleInfo roleInfoDependedOn =
+ relSvc.getRoleInfo("DependsOn", "dependedOn");
+ List<RoleInfo> expectedRoleInfos =
+ Arrays.asList(new RoleInfo[] {roleInfoDependent, roleInfoDependedOn});
+ List<RoleInfo> roleInfos =
+ checked(relSvc.getRoleInfos("DependsOn"), RoleInfo.class);
+ check("List<RoleInfo> RelationService.getRoleInfos",
+ equalListContents(expectedRoleInfos, roleInfos));
+
+ RelationType relType =
+ new RelationTypeSupport("DependsOn", dependsOnRoles);
+ List<RoleInfo> relTypeRoleInfos =
+ checked(relType.getRoleInfos(), RoleInfo.class);
+ // Since there's no RoleInfo.equals and since the RelationTypeSupport
+ // constructor clones the RoleInfos passed to it, it's tricky to
+ // test equality here so we check type and size and have done with it
+ check("List<RoleInfo> RelationType.getRoleInfos",
+ relTypeRoleInfos.size() == 2);
+
+ MBeanServerNotificationFilter mbsnf =
+ new MBeanServerNotificationFilter();
+ mbsnf.enableObjectName(moduleA);
+ check("Vector<ObjectName> MBeanServerNotificationFilter." +
+ "getEnabledObjectNames",
+ mbsnf.getEnabledObjectNames().equals(Arrays.asList(moduleA)));
+ mbsnf.enableAllObjectNames();
+ mbsnf.disableObjectName(moduleB);
+ check("Vector<ObjectName> MBeanServerNotificationFilter." +
+ "getDisabledObjectNames",
+ mbsnf.getDisabledObjectNames().equals(Arrays.asList(moduleB)));
+
+ RelationService unusedRelSvc = new RelationService(false);
+ RelationNotification rn1 =
+ new RelationNotification(RelationNotification.RELATION_MBEAN_REMOVAL,
+ unusedRelSvc, 0L, 0L, "yo!",
+ "A-DependsOn-B", "DependsOn", null,
+ singletonList(moduleA));
+ List<ObjectName> toUnreg =
+ checked(rn1.getMBeansToUnregister(), ObjectName.class);
+ check("List<ObjectName> RelationNotification.getMBeansToUnregister",
+ toUnreg.equals(singletonList(moduleA)));
+
+ RelationNotification rn2 =
+ new RelationNotification(RelationNotification.RELATION_MBEAN_UPDATE,
+ unusedRelSvc, 0L, 0L, "yo!",
+ "A-DependsOn-B", "DependsOn", null,
+ "dependent", singletonList(moduleA),
+ singletonList(moduleB));
+ check("List<ObjectName> RelationNotification.getOldRoleValue",
+ checked(rn2.getOldRoleValue(), ObjectName.class)
+ .equals(singletonList(moduleB)));
+ check("List<ObjectName> RelationNotification.getNewRoleValue",
+ checked(rn2.getNewRoleValue(), ObjectName.class)
+ .equals(singletonList(moduleA)));
+
+ ObjectName timerName = new ObjectName(":type=timer");
+ mbs.registerMBean(new Timer(), timerName);
+ TimerMBean timer =
+ MBeanServerInvocationHandler.newProxyInstance(mbs,
+ timerName,
+ TimerMBean.class,
+ false);
+ Date doomsday = new Date(Long.MAX_VALUE);
+ int timer1 = timer.addNotification("one", "one", null, doomsday);
+ int timer2 = timer.addNotification("two", "two", null, doomsday);
+ Vector<Integer> idsOne = timer.getNotificationIDs("one");
+ check("Vector<Integer> TimerMBean.getNotificationIDs",
+ idsOne.equals(singletonList(timer1)));
+ Vector<Integer> allIds = timer.getAllNotificationIDs();
+ check("Vector<Integer> TimerMBean.getAllNotificationIDs",
+ equalListContents(allIds,
+ Arrays.asList(new Integer[]{timer1, timer2})));
+
+ // ADD NEW TEST CASES ABOVE THIS COMMENT
+
+ if (failures == 0)
+ System.out.println("All tests passed");
+ else {
+ System.out.println("TEST FAILURES: " + failures);
+ System.exit(1);
+ }
+
+ // DO NOT ADD NEW TEST CASES HERE, ADD THEM ABOVE THE PREVIOUS COMMENT
+ }
+
+ public static interface StupidMBean {
+ public int getFive();
+ }
+
+ public static class Stupid implements StupidMBean {
+ public int getFive() {
+ return 5;
+ }
+ }
+
+ public static class Module extends StandardMBean implements StupidMBean {
+ public Module() throws NotCompliantMBeanException {
+ super(StupidMBean.class);
+ }
+
+ public int getFive() {
+ return 5;
+ }
+ }
+
+ private static <E> List<E> singletonList(E value) {
+ return Collections.singletonList(value);
+ }
+
+ private static <E> Set<E> singleton(E value) {
+ return Collections.singleton(value);
+ }
+
+ private static <K,V> Map<K,V> singletonMap(K key, V value) {
+ return Collections.singletonMap(key, value);
+ }
+
+ private static <E> List<E> checked(List<E> c, Class<E> type) {
+ List<E> unchecked = new ArrayList<E>();
+ List<E> checked = Collections.checkedList(unchecked, type);
+ checked.addAll(c);
+ return Collections.checkedList(c, type);
+ }
+
+ private static <E> Set<E> checked(Set<E> c, Class<E> type) {
+ Set<E> unchecked = new HashSet<E>();
+ Set<E> checked = Collections.checkedSet(unchecked, type);
+ checked.addAll(c);
+ return Collections.checkedSet(c, type);
+ }
+
+ private static <K,V> Map<K,V> checked(Map<K,V> m,
+ Class<K> keyType,
+ Class<V> valueType) {
+ Map<K,V> unchecked = new HashMap<K,V>();
+ Map<K,V> checked = Collections.checkedMap(unchecked, keyType, valueType);
+ checked.putAll(m);
+ return Collections.checkedMap(m, keyType, valueType);
+ }
+
+ /* The fact that we have to call this method is a clear signal that
+ * the API says List where it means Set.
+ */
+ private static <E> boolean equalListContents(List<E> l1, List<E> l2) {
+ return new HashSet<E>(l1).equals(new HashSet<E>(l2));
+ }
+
+ private static void check(String what, boolean cond) {
+ if (cond)
+ System.out.println("OK: " + what);
+ else {
+ System.out.println("FAILED: " + what);
+ failures++;
+ }
+ }
+}
diff --git a/test/javax/management/generified/ListTypeCheckTest.java b/test/javax/management/generified/ListTypeCheckTest.java
new file mode 100644
index 0000000..8ed5458
--- /dev/null
+++ b/test/javax/management/generified/ListTypeCheckTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6250772
+ * @summary Test that *List objects are checked after asList is called.
+ * @author Eamonn McManus
+ * @run clean ListTypeCheckTest
+ * @run build ListTypeCheckTest
+ * @run main ListTypeCheckTest
+ */
+
+import java.lang.reflect.*;
+import java.util.*;
+import javax.management.*;
+import javax.management.relation.*;
+
+/* For compatibility reasons, the classes AttributeList, RoleList,
+ * and RoleUnresolvedList all extend ArrayList<Object> even though
+ * logically they should extend ArrayList<Attribute> etc. They are
+ * all specified to have a method asList() with return type
+ * List<Attribute> etc, and to refuse to add any object other than
+ * an Attribute etc once this method has been called, but not before.
+ */
+public class ListTypeCheckTest {
+ public static void main(String[] args) throws Exception {
+ Class[] classes = {
+ AttributeList.class, RoleList.class, RoleUnresolvedList.class,
+ };
+ for (Class c : classes)
+ test((Class<? extends ArrayList>) c);
+ }
+
+ private static void test(Class<? extends ArrayList> c) throws Exception {
+ System.out.println("Testing " + c.getName());
+ ArrayList al = c.newInstance();
+ test(al);
+ }
+
+ private static void test(ArrayList al) throws Exception {
+ test(al, true);
+ al.clear();
+ Method m = al.getClass().getMethod("asList");
+ m.invoke(al);
+ test(al, false);
+ }
+
+ private static void test(ArrayList al, boolean allowsBogus) throws Exception {
+ for (int i = 0; i < 5; i++) {
+ try {
+ switch (i) {
+ case 0:
+ al.add("yo");
+ break;
+ case 1:
+ al.add(0, "yo");
+ break;
+ case 2:
+ al.addAll(Arrays.asList("foo", "bar"));
+ break;
+ case 3:
+ al.addAll(0, Arrays.asList("foo", "bar"));
+ break;
+ case 4:
+ al.set(0, "foo");
+ break;
+ default:
+ throw new Exception("test wrong");
+ }
+ if (!allowsBogus)
+ throw new Exception("op allowed but should fail");
+ } catch (IllegalArgumentException e) {
+ if (allowsBogus)
+ throw new Exception("got exception but should not", e);
+ }
+ }
+ }
+}
diff --git a/test/javax/management/loading/ArrayClassTest.java b/test/javax/management/loading/ArrayClassTest.java
new file mode 100644
index 0000000..6601806
--- /dev/null
+++ b/test/javax/management/loading/ArrayClassTest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4974913
+ * @summary Test that array classes can be found in signatures always
+ * and can be deserialized by the deprecated MBeanServer.deserialize method
+ * @author Eamonn McManus
+ * @run clean ArrayClassTest
+ * @run build ArrayClassTest
+ * @run main ArrayClassTest
+ */
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.net.*;
+import javax.management.*;
+import javax.management.loading.*;
+
+public class ArrayClassTest {
+ public static void main(String[] args) throws Exception {
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ /* If this test isn't loaded by a URLClassLoader we will get
+ a ClassCastException here, which is good because it means
+ this test isn't valid. */
+ URLClassLoader testLoader =
+ (URLClassLoader) ArrayClassTest.class.getClassLoader();
+
+ // Create an MLet that can load the same class names but
+ // will produce different results.
+ ClassLoader loader = new SpyLoader(testLoader.getURLs());
+ ObjectName loaderName = new ObjectName("test:type=SpyLoader");
+ mbs.registerMBean(loader, loaderName);
+
+ ObjectName testName = new ObjectName("test:type=Test");
+ mbs.createMBean(Test.class.getName(), testName, loaderName,
+ new Object[1], new String[] {X[].class.getName()});
+ ClassLoader checkLoader = mbs.getClassLoaderFor(testName);
+ if (checkLoader != loader)
+ throw new AssertionError("Wrong loader: " + checkLoader);
+
+ mbs.invoke(testName, "ignore", new Object[1],
+ new String[] {Y[].class.getName()});
+
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ ObjectOutputStream oout = new ObjectOutputStream(bout);
+ oout.writeObject(new Z[0]);
+ oout.close();
+ byte[] bytes = bout.toByteArray();
+ ObjectInputStream oin = mbs.deserialize(testName, bytes);
+ Object zarray = oin.readObject();
+ String failed = null;
+ if (zarray instanceof Z[])
+ failed = "read back a real Z[]";
+ else if (!zarray.getClass().getName().equals(Z[].class.getName())) {
+ failed = "returned object of wrong type: " +
+ zarray.getClass().getName();
+ } else if (Array.getLength(zarray) != 0)
+ failed = "returned array of wrong size: " + Array.getLength(zarray);
+ if (failed != null) {
+ System.out.println("TEST FAILED: " + failed);
+ System.exit(1);
+ }
+
+ System.out.println("Test passed");
+ }
+
+ public static interface TestMBean {
+ public void ignore(Y[] ignored);
+ }
+
+ public static class Test implements TestMBean {
+ public Test(X[] ignored) {}
+ public void ignore(Y[] ignored) {}
+ }
+
+ public static class X {}
+ public static class Y {}
+ public static class Z implements Serializable {}
+
+ public static interface SpyLoaderMBean {}
+
+ /* We originally had this extend MLet but for some reason that
+ stopped the bug from happening. Some side-effect of registering
+ the MLet in the MBean server caused it not to fail when asked
+ to load Z[]. */
+ public static class SpyLoader extends URLClassLoader
+ implements SpyLoaderMBean, PrivateClassLoader {
+ public SpyLoader(URL[] urls) {
+ // important that the parent classloader be null!
+ // otherwise we can pick up classes from the classpath
+ super(urls, null);
+ }
+
+ /*
+ public Class loadClass(String name) throws ClassNotFoundException {
+ System.out.println("loadClass: " + name);
+ return super.loadClass(name);
+ }
+
+ public Class loadClass(String name, boolean resolve)
+ throws ClassNotFoundException {
+ System.out.println("loadClass: " + name + ", " + resolve);
+ return super.loadClass(name, resolve);
+ }
+ */
+
+ public Class findClass(String name) throws ClassNotFoundException {
+ System.out.println("findClass: " + name);
+ if (false)
+ new Throwable().printStackTrace(System.out);
+ Class c = super.findClass(name);
+ System.out.println(" -> " + name + " (" + c.getClassLoader() + ")");
+ return c;
+ }
+ }
+}
diff --git a/test/javax/management/loading/DocumentRootTest.java b/test/javax/management/loading/DocumentRootTest.java
new file mode 100644
index 0000000..b707895
--- /dev/null
+++ b/test/javax/management/loading/DocumentRootTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6500139
+ * @summary Test parsing error when the mlet file is
+ * located in the web server's document root.
+ * @author Luis-Miguel Alventosa
+ * @run clean DocumentRootTest
+ * @run build DocumentRootTest
+ * @run main DocumentRootTest
+ */
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import javax.management.loading.MLetContent;
+
+public class DocumentRootTest {
+ public static int test(URL documentBase, URL codeBase) {
+ int error = 0;
+ MLetContent mc = new MLetContent(
+ documentBase,
+ new HashMap<String,String>(),
+ new ArrayList<String>(),
+ new ArrayList<String>());
+ System.out.println("\nACTUAL DOCUMENT BASE = " + mc.getDocumentBase());
+ System.out.println("EXPECTED DOCUMENT BASE = " + documentBase);
+ if (!documentBase.equals(mc.getDocumentBase())) {
+ System.out.println("ERROR: Wrong document base");
+ error++;
+ };
+ System.out.println("ACTUAL CODEBASE = " + mc.getCodeBase());
+ System.out.println("EXPECTED CODEBASE = " + codeBase);
+ if (!codeBase.equals(mc.getCodeBase())) {
+ System.out.println("ERROR: Wrong code base");
+ error++;
+ };
+ return error;
+ }
+ public static void main(String[] args) throws Exception {
+ int error = 0;
+ error += test(new URL("file:/mlet.txt"), new URL("file:/"));
+ error += test(new URL("http://localhost/mlet.txt"), new URL("http://localhost/"));
+ if (error > 0) {
+ System.out.println("\nTest FAILED!\n");
+ throw new IllegalArgumentException("Test FAILED!");
+ } else {
+ System.out.println("\nTest PASSED!\n");
+ }
+ }
+}
diff --git a/test/javax/management/loading/GetMBeansFromURLTest.java b/test/javax/management/loading/GetMBeansFromURLTest.java
new file mode 100644
index 0000000..5e42f57
--- /dev/null
+++ b/test/javax/management/loading/GetMBeansFromURLTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5018593
+ * @summary Test that calling getMBeansFromURL(url) with a bogus URL on a
+ * given MLet instance throws a ServiceNotFoundException exception
+ * with a non null cause.
+ * @author Luis-Miguel Alventosa
+ * @run clean GetMBeansFromURLTest
+ * @run build GetMBeansFromURLTest
+ * @run main GetMBeansFromURLTest
+ */
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectName;
+import javax.management.ServiceNotFoundException;
+import javax.management.loading.MLet;
+
+public class GetMBeansFromURLTest {
+
+ public static void main(String[] args) throws Exception {
+
+ boolean error = false;
+
+ // Instantiate the MBean server
+ //
+ System.out.println("Create the MBean server");
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ // Instantiate an MLet
+ //
+ System.out.println("Create the MLet");
+ MLet mlet = new MLet();
+
+ // Register the MLet MBean with the MBeanServer
+ //
+ System.out.println("Register the MLet MBean");
+ ObjectName mletObjectName = new ObjectName("Test:type=MLet");
+ mbs.registerMBean(mlet, mletObjectName);
+
+ // Call getMBeansFromURL
+ //
+ System.out.println("Call mlet.getMBeansFromURL(<url>)");
+ try {
+ mlet.getMBeansFromURL("bogus://whatever");
+ System.out.println("TEST FAILED: Expected " +
+ ServiceNotFoundException.class +
+ " exception not thrown.");
+ error = true;
+ } catch (ServiceNotFoundException e) {
+ if (e.getCause() == null) {
+ System.out.println("TEST FAILED: Got null cause in " +
+ ServiceNotFoundException.class +
+ " exception.");
+ error = true;
+ } else {
+ System.out.println("TEST PASSED: Got non-null cause in " +
+ ServiceNotFoundException.class +
+ " exception.");
+ error = false;
+ }
+ e.printStackTrace(System.out);
+ }
+
+ // Unregister the MLet MBean
+ //
+ System.out.println("Unregister the MLet MBean");
+ mbs.unregisterMBean(mletObjectName);
+
+ // Release MBean server
+ //
+ System.out.println("Release the MBean server");
+ MBeanServerFactory.releaseMBeanServer(mbs);
+
+ // End Test
+ //
+ System.out.println("Bye! Bye!");
+ if (error) System.exit(1);
+ }
+}
diff --git a/test/javax/management/loading/LibraryLoader/LibraryLoaderTest.java b/test/javax/management/loading/LibraryLoader/LibraryLoaderTest.java
new file mode 100644
index 0000000..5a0e105
--- /dev/null
+++ b/test/javax/management/loading/LibraryLoader/LibraryLoaderTest.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4969756
+ * @summary Test that the same native library coming from the same jar file can
+ * be loaded twice by two different MLets on the same JVM without conflict.
+ * @author Luis-Miguel Alventosa
+ * @run clean LibraryLoaderTest
+ * @run build LibraryLoaderTest
+ * @run main LibraryLoaderTest
+ */
+
+import java.io.File;
+import java.util.Set;
+import javax.management.Attribute;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+
+public class LibraryLoaderTest {
+
+ private static final String mletInfo[][] = {
+ {"testDomain:type=MLet,index=0", "UseNativeLib0.html"},
+ {"testDomain:type=MLet,index=1", "UseNativeLib1.html"}
+ };
+
+ public static void main (String args[]) {
+
+ String osName = System.getProperty("os.name");
+ System.out.println("os.name=" + osName);
+ String osArch = System.getProperty("os.arch");
+ System.out.println("os.name=" + osArch);
+
+ // Check for supported platforms:
+ //
+ // Solaris/SPARC and Windows/x86
+ //
+ if ((!(osName.equals("SunOS") && osArch.equals("sparc"))) &&
+ (!(osName.startsWith("Windows") && osArch.equals("x86")))) {
+ System.out.println(
+ "This test runs only on Solaris/SPARC and Windows/x86 platforms");
+ System.out.println("Bye! Bye!");
+ return;
+ }
+
+ String libPath = System.getProperty("java.library.path");
+ System.out.println("java.library.path=" + libPath);
+ String testSrc = System.getProperty("test.src");
+ System.out.println("test.src=" + testSrc);
+ String workingDir = System.getProperty("user.dir");
+ System.out.println("user.dir=" + workingDir);
+
+ String urlCodebase;
+ if (testSrc.startsWith("/")) {
+ urlCodebase =
+ "file:" + testSrc.replace(File.separatorChar, '/') + "/";
+ } else {
+ urlCodebase =
+ "file:/" + testSrc.replace(File.separatorChar, '/') + "/";
+ }
+
+ try {
+ // Create MBeanServer
+ //
+ MBeanServer server = MBeanServerFactory.newMBeanServer();
+
+ // Create MLet instances and call getRandom on the loaded MBeans
+ //
+ for (int i = 0; i < mletInfo.length; i++) {
+ // Create ObjectName for MLet
+ //
+ ObjectName mlet = new ObjectName(mletInfo[i][0]);
+ server.createMBean("javax.management.loading.MLet", mlet);
+ System.out.println("MLet = " + mlet);
+
+ // Display old library directory and set it to test.classes
+ //
+ String libraryDirectory =
+ (String) server.getAttribute(mlet, "LibraryDirectory");
+ System.out.println("Old Library Directory = " +
+ libraryDirectory);
+ Attribute attribute =
+ new Attribute("LibraryDirectory", workingDir);
+ server.setAttribute(mlet, attribute);
+ libraryDirectory =
+ (String) server.getAttribute(mlet, "LibraryDirectory");
+ System.out.println("New Library Directory = " +
+ libraryDirectory);
+
+ // Get MBeans from URL
+ //
+ String mletURL = urlCodebase + mletInfo[i][1];
+ System.out.println("MLet URL = " + mletURL);
+ Object[] params = new Object[] { mletURL };
+ String[] signature = new String[] {"java.lang.String"};
+ Object res[] = ((Set) server.invoke(mlet,
+ "getMBeansFromURL",
+ params,
+ signature)).toArray();
+
+ // Iterate through all the loaded MBeans
+ //
+ for (int j = 0; j < res.length; j++) {
+ // Now ensure none of the returned objects is a Throwable
+ //
+ if (res[j] instanceof Throwable) {
+ ((Throwable) res[j]).printStackTrace(System.out);
+ System.out.println("Failed to load the MBean #" + j +
+ ". The shown Throwable was caught.");
+ System.exit(1);
+ }
+
+ // On each of the loaded MBeans, try to invoke their
+ // native operation
+ //
+ Object result = null;
+ try {
+ ObjectName mbean =
+ ((ObjectInstance) res[j]).getObjectName();
+ result = server.getAttribute(mbean, "Random");
+ System.out.println("MBean #" + j + " = " + mbean);
+ System.out.println("Random number = " + result);
+ } catch (ReflectionException e) {
+ e.getTargetException().printStackTrace(System.out);
+ System.out.println("A ReflectionException, wrapping " +
+ "the shown exception, occured when" +
+ " attempting to invoke a native " +
+ "library based operation.");
+ System.exit(1);
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace(System.out);
+ System.out.println(e.getMessage());
+ System.out.println("Unexpected error");
+ System.exit(1);
+ }
+ System.out.println("Bye! Bye!");
+ }
+}
diff --git a/test/javax/management/loading/LibraryLoader/UseNativeLib0.html b/test/javax/management/loading/LibraryLoader/UseNativeLib0.html
new file mode 100644
index 0000000..7632303
--- /dev/null
+++ b/test/javax/management/loading/LibraryLoader/UseNativeLib0.html
@@ -0,0 +1,19 @@
+<HTML>
+<MLET
+ CODE = "UseNativeLib.class"
+ ARCHIVE = "native.jar"
+ NAME = "mletTests:type=nativeLibLoading,index=0.0"
+>
+</MLET>
+<MLET
+ CODE = "UseNativeLib.class"
+ ARCHIVE = "native.jar"
+ NAME = "mletTests:type=nativeLibLoading,index=0.1"
+>
+</MLET>
+<BODY>
+
+Test MLet.
+
+</BODY>
+</HTML>
diff --git a/test/javax/management/loading/LibraryLoader/UseNativeLib1.html b/test/javax/management/loading/LibraryLoader/UseNativeLib1.html
new file mode 100644
index 0000000..e089fbc
--- /dev/null
+++ b/test/javax/management/loading/LibraryLoader/UseNativeLib1.html
@@ -0,0 +1,19 @@
+<HTML>
+<MLET
+ CODE = "UseNativeLib.class"
+ ARCHIVE = "native.jar"
+ NAME = "mletTests:type=nativeLibLoading,index=1.0"
+>
+</MLET>
+<MLET
+ CODE = "UseNativeLib.class"
+ ARCHIVE = "native.jar"
+ NAME = "mletTests:type=nativeLibLoading,index=1.1"
+>
+</MLET>
+<BODY>
+
+Test MLet.
+
+</BODY>
+</HTML>
diff --git a/test/javax/management/loading/LibraryLoader/jar_src/RandomGen.c b/test/javax/management/loading/LibraryLoader/jar_src/RandomGen.c
new file mode 100644
index 0000000..1cb7121
--- /dev/null
+++ b/test/javax/management/loading/LibraryLoader/jar_src/RandomGen.c
@@ -0,0 +1,15 @@
+#include <jni.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+JNIEXPORT jint JNICALL Java_UseNativeLib_getRandom(JNIEnv *env, jobject obj) {
+ return rand();
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/test/javax/management/loading/LibraryLoader/jar_src/RandomGen.h b/test/javax/management/loading/LibraryLoader/jar_src/RandomGen.h
new file mode 100644
index 0000000..33e2028
--- /dev/null
+++ b/test/javax/management/loading/LibraryLoader/jar_src/RandomGen.h
@@ -0,0 +1,15 @@
+#include <jni.h>
+
+#ifndef RandomGen
+#define RandomGen
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+JNIEXPORT jint JNICALL Java_RandomGen_getRandom
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/test/javax/management/loading/LibraryLoader/jar_src/UseNativeLib.java b/test/javax/management/loading/LibraryLoader/jar_src/UseNativeLib.java
new file mode 100644
index 0000000..9d00af7
--- /dev/null
+++ b/test/javax/management/loading/LibraryLoader/jar_src/UseNativeLib.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+public class UseNativeLib implements java.io.Serializable, UseNativeLibMBean {
+
+ public native int getRandom();
+
+ static {
+ try {
+ System.loadLibrary("genrandom");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/test/javax/management/loading/LibraryLoader/jar_src/UseNativeLibMBean.java b/test/javax/management/loading/LibraryLoader/jar_src/UseNativeLibMBean.java
new file mode 100644
index 0000000..d78b5d0
--- /dev/null
+++ b/test/javax/management/loading/LibraryLoader/jar_src/UseNativeLibMBean.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+public interface UseNativeLibMBean {
+ public int getRandom();
+}
diff --git a/test/javax/management/loading/LibraryLoader/native.jar b/test/javax/management/loading/LibraryLoader/native.jar
new file mode 100644
index 0000000..7d8f1d3
--- /dev/null
+++ b/test/javax/management/loading/LibraryLoader/native.jar
Binary files differ
diff --git a/test/javax/management/loading/MLetCLR/MLetCommand.java b/test/javax/management/loading/MLetCLR/MLetCommand.java
new file mode 100644
index 0000000..52dca1d
--- /dev/null
+++ b/test/javax/management/loading/MLetCLR/MLetCommand.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4836468
+ * @summary Test that the getClassLoaderRepository permission is not necessary
+ * for the test codebase as it is executed by the MLet code using
+ * doPrivileged.
+ * @author Luis-Miguel Alventosa
+ * @run clean MLetCommand
+ * @run build MLetCommand
+ * @run main/othervm/policy=policy MLetCommand
+ */
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectName;
+import java.io.File;
+
+public class MLetCommand {
+
+ public static void main(String[] args) throws Exception {
+ if (System.getSecurityManager() == null)
+ throw new IllegalStateException("No security manager installed!");
+
+ System.out.println("java.security.policy=" +
+ System.getProperty("java.security.policy"));
+
+ // Instantiate the MBean server
+ //
+ System.out.println("Create the MBean server");
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ // Register the MLetMBean
+ //
+ System.out.println("Create MLet MBean");
+ ObjectName mlet = new ObjectName("MLetTest:name=MLetMBean");
+ mbs.createMBean("javax.management.loading.MLet", mlet);
+ // Test OK!
+ //
+ System.out.println("Bye! Bye!");
+ }
+}
diff --git a/test/javax/management/loading/MLetCLR/policy b/test/javax/management/loading/MLetCLR/policy
new file mode 100644
index 0000000..4cabfd3
--- /dev/null
+++ b/test/javax/management/loading/MLetCLR/policy
@@ -0,0 +1,8 @@
+
+grant {
+ permission java.util.PropertyPermission "*", "read";
+ permission javax.management.MBeanServerPermission "createMBeanServer";
+ permission javax.management.MBeanPermission "javax.management.loading.MLet#-[-]", "instantiate";
+ permission javax.management.MBeanPermission "javax.management.loading.MLet#-[MLetTest:name=MLetMBean]", "registerMBean";
+ permission java.lang.RuntimePermission "createClassLoader";
+};
diff --git a/test/javax/management/loading/MLetContentTest.java b/test/javax/management/loading/MLetContentTest.java
new file mode 100644
index 0000000..6fefe4e
--- /dev/null
+++ b/test/javax/management/loading/MLetContentTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4796780
+ * @summary The class MLetContentTest becomes public
+ * @author Shanliang JIANG
+ * @run clean MLetContentTest
+ * @run build MLetContentTest
+ * @run main MLetContentTest
+ */
+
+import java.util.*;
+import java.net.*;
+
+import javax.management.loading.*;
+
+public class MLetContentTest {
+ public static void main(String[] args) throws Exception {
+ System.out.println(">>> General test for the public class MLetContent.");
+
+ Map<String,String> attributes = new HashMap();
+ attributes.put("archive", archive);
+ attributes.put("Archive", "hahaha");
+
+ attributes.put("code", code);
+ attributes.put("codE", "hihi");
+
+ attributes.put("object", object);
+ attributes.put("obJect", "toto");
+
+ attributes.put("name", name);
+ attributes.put("NAME", "titi");
+
+ attributes.put("version", version);
+ attributes.put("VeRsIoN", "tttt");
+
+ List<String> types = new ArrayList();
+ types.add("my type");
+
+ List<String> values = new ArrayList();
+ values.add("my values");
+
+ URL url = new URL(baseUrl+myfile);
+ MLetContent content = new MLetContent(url, attributes, types, values);
+
+ if (!attributes.equals(content.getAttributes())) {
+ throw new RuntimeException("The user specific attributes are changed.");
+ }
+
+ if (!url.equals(content.getDocumentBase())) {
+ throw new RuntimeException("The user specific document bas is changed.");
+ }
+
+ if (!archive.equals(content.getJarFiles())) {
+ throw new RuntimeException("The user specific archive files are changed.");
+ }
+
+ if (!code.equals(content.getCode())) {
+ throw new RuntimeException("The user specific code is changed.");
+ }
+
+ if (!object.equals(content.getSerializedObject())) {
+ throw new RuntimeException("The user specific object is changed.");
+ }
+
+ if (!name.equals(content.getName())) {
+ throw new RuntimeException("The user specific name is changed.");
+ }
+
+ if (!version.equals(content.getVersion())) {
+ throw new RuntimeException("The user specific version is changed.");
+ }
+
+ if (!types.equals(content.getParameterTypes())) {
+ throw new RuntimeException("The user specific types are changed.");
+ }
+
+ if (!values.equals(content.getParameterValues())) {
+ throw new RuntimeException("The user specific values are changed.");
+ }
+
+ if (!baseUrl.equals(content.getCodeBase().toString())) {
+ throw new RuntimeException("The user specific base url are changed.");
+ }
+
+ url = new URL(baseUrl);
+ attributes.put("codebase", codebase);
+ content = new MLetContent(url, attributes, types, values);
+
+ if (!content.getCodeBase().toString().equals(baseUrl+codebase)) {
+ throw new RuntimeException("The user specific base url are changed.");
+ }
+
+ final MyMLet myMlet = new MyMLet();
+
+ if (myMlet.check(null, null, null, content) != content.getCodeBase()) {
+ throw new RuntimeException("Failed to overrid the protected methed check");
+ }
+
+ System.out.println(">>> The test is well passed.");
+ }
+
+ private static class MyMLet extends MLet {
+ public URL check(String version,
+ URL codebase,
+ String jarfile,
+ MLetContent content) {
+ return content.getCodeBase();
+ }
+ }
+
+ private static final String archive = "my jarfile";
+ private static final String code = "my code";
+ private static final String object = "my object";
+ private static final String name = "my name";
+ private static final String version = "my version";
+
+ private static final String myfile = "My file";
+ private static final String baseUrl = "file:/tmp/test/";
+
+ private final static String codebase = "my code base/";
+}
diff --git a/test/javax/management/loading/ParserInfiniteLoopTest.java b/test/javax/management/loading/ParserInfiniteLoopTest.java
new file mode 100644
index 0000000..45de5c4
--- /dev/null
+++ b/test/javax/management/loading/ParserInfiniteLoopTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5042364
+ * @summary Malformed MLet text file causes infinite loop in parser.
+ * The MLetParser goes into an infinite loop when a tag is not
+ * terminated with the corresponding '>' and an opening '<' for
+ * the subsequent tag is encountered.
+ * @author Luis-Miguel Alventosa
+ * @run clean ParserInfiniteLoopTest
+ * @run build ParserInfiniteLoopTest
+ * @run main/othervm/timeout=5 ParserInfiniteLoopTest mlet1.html
+ * @run main/othervm/timeout=5 ParserInfiniteLoopTest mlet2.html
+ * @run main/othervm/timeout=5 ParserInfiniteLoopTest mlet3.html
+ */
+
+import java.io.File;
+import java.io.IOException;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectName;
+import javax.management.ServiceNotFoundException;
+import javax.management.loading.MLet;
+
+public class ParserInfiniteLoopTest {
+
+ public static void main(String[] args) throws Exception {
+
+ boolean error = false;
+
+ // Instantiate the MBean server
+ //
+ System.out.println("Create the MBean server");
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ // Instantiate an MLet
+ //
+ System.out.println("Create the MLet");
+ MLet mlet = new MLet();
+
+ // Register the MLet MBean with the MBeanServer
+ //
+ System.out.println("Register the MLet MBean");
+ ObjectName mletObjectName = new ObjectName("Test:type=MLet");
+ mbs.registerMBean(mlet, mletObjectName);
+
+ // Call getMBeansFromURL
+ //
+ System.out.println("Call mlet.getMBeansFromURL(<url>)");
+ String testSrc = System.getProperty("test.src");
+ System.out.println("test.src = " + testSrc);
+ String urlCodebase;
+ if (testSrc.startsWith("/")) {
+ urlCodebase =
+ "file:" + testSrc.replace(File.separatorChar, '/') + "/";
+ } else {
+ urlCodebase =
+ "file:/" + testSrc.replace(File.separatorChar, '/') + "/";
+ }
+ String mletFile = urlCodebase + args[0];
+ System.out.println("MLet File = " + mletFile);
+ try {
+ mlet.getMBeansFromURL(mletFile);
+ System.out.println(
+ "TEST FAILED: Expected ServiceNotFoundException not thrown");
+ error = true;
+ } catch (ServiceNotFoundException e) {
+ if (e.getCause() == null) {
+ System.out.println("TEST FAILED: Got unexpected null cause " +
+ "in ServiceNotFoundException");
+ error = true;
+ } else if (!(e.getCause() instanceof IOException)) {
+ System.out.println("TEST FAILED: Got unexpected non-null " +
+ "cause in ServiceNotFoundException");
+ error = true;
+ } else {
+ System.out.println("TEST PASSED: Got expected non-null " +
+ "cause in ServiceNotFoundException");
+ error = false;
+ }
+ e.printStackTrace(System.out);
+ }
+
+ // Unregister the MLet MBean
+ //
+ System.out.println("Unregister the MLet MBean");
+ mbs.unregisterMBean(mletObjectName);
+
+ // Release MBean server
+ //
+ System.out.println("Release the MBean server");
+ MBeanServerFactory.releaseMBeanServer(mbs);
+
+ // End Test
+ //
+ System.out.println("Bye! Bye!");
+ if (error) System.exit(1);
+ }
+}
diff --git a/test/javax/management/loading/SystemClassLoaderTest.java b/test/javax/management/loading/SystemClassLoaderTest.java
new file mode 100644
index 0000000..7422c2c
--- /dev/null
+++ b/test/javax/management/loading/SystemClassLoaderTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4839389
+ * @summary Test that a class can load MBeans from its class loader
+ * (at least if it is the system class loader)
+ * @author Eamonn McManus
+ * @run clean SystemClassLoaderTest
+ * @run build SystemClassLoaderTest
+ * @run main SystemClassLoaderTest
+ */
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectName;
+
+/* Test that we can load an MBean using createMBean(className, objectName)
+ even if the class of the MBean is not known to the JMX class loader. */
+public class SystemClassLoaderTest {
+
+ public static void main(String[] args) throws Exception {
+ // Instantiate the MBean server
+ //
+ System.out.println("Create the MBean server");
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ ClassLoader mbsClassLoader = mbs.getClass().getClassLoader();
+
+ String testClassName = Test.class.getName();
+
+ // Check that the MBeanServer class loader does not know our test class
+ try {
+ Class.forName(testClassName, true, mbsClassLoader);
+ System.out.println("TEST IS INVALID: MBEANSERVER'S CLASS LOADER " +
+ "KNOWS OUR TEST CLASS");
+ System.exit(1);
+ } catch (ClassNotFoundException e) {
+ // As required
+ }
+
+ // Register the MBean
+ //
+ System.out.println("Create MBean from this class");
+ ObjectName objectName = new ObjectName("whatever:type=whatever");
+ mbs.createMBean(testClassName, objectName);
+ // Test OK!
+ //
+ System.out.println("Bye! Bye!");
+ }
+
+ public static class Test implements TestMBean {
+ public Test() {}
+ }
+
+ public static interface TestMBean {}
+}
diff --git a/test/javax/management/loading/mlet1.html b/test/javax/management/loading/mlet1.html
new file mode 100644
index 0000000..c2a33c0
--- /dev/null
+++ b/test/javax/management/loading/mlet1.html
@@ -0,0 +1,2 @@
+<MLET CODE=HelloWorld ARCHIVE="helloworld.jar"
+</MLET>
diff --git a/test/javax/management/loading/mlet2.html b/test/javax/management/loading/mlet2.html
new file mode 100644
index 0000000..041a2af
--- /dev/null
+++ b/test/javax/management/loading/mlet2.html
@@ -0,0 +1,2 @@
+<MLET CODE=HelloWorld ARCHIVE="helloworld.jar">
+</MLET
diff --git a/test/javax/management/loading/mlet3.html b/test/javax/management/loading/mlet3.html
new file mode 100644
index 0000000..32f1977
--- /dev/null
+++ b/test/javax/management/loading/mlet3.html
@@ -0,0 +1,3 @@
+<MLET CODE=HelloWorld ARCHIVE="helloworld.jar">
+<ARG TYPE=argumentType VALUE=value
+</MLET>
diff --git a/test/javax/management/modelmbean/AddAttributeChangeNotificationListenerTest.java b/test/javax/management/modelmbean/AddAttributeChangeNotificationListenerTest.java
new file mode 100644
index 0000000..0025aab
--- /dev/null
+++ b/test/javax/management/modelmbean/AddAttributeChangeNotificationListenerTest.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5043762
+ * @summary Attribute existence check fails if
+ * RequiredModelMBean.addAttributeChangeNotificationListener
+ * is called with a non-existent attribute name and there are
+ * no other attributes.
+ * @author Yves Joan
+ * @author Eamonn McManus
+ * @run clean AddAttributeChangeNotificationListenerTest
+ * @run build AddAttributeChangeNotificationListenerTest
+ * @run main AddAttributeChangeNotificationListenerTest
+ */
+
+import java.lang.reflect.Method;
+import javax.management.AttributeChangeNotification;
+import javax.management.MBeanException;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.RuntimeOperationsException;
+import javax.management.modelmbean.*;
+
+/**
+ * We do invoke addAttributeChangeNotificationListener to add
+ * a listener on an attribute not defined in the ModelMBeanInfo
+ * of the RequiredModelMBean instance used.
+ */
+public class AddAttributeChangeNotificationListenerTest {
+
+ public static void main(String args[] ) {
+ AddAttributeChangeNotificationListenerTest test =
+ new AddAttributeChangeNotificationListenerTest();
+
+ try {
+ test.run(args);
+ } catch(Exception e) {
+ System.out.println("FAIL");
+ e.printStackTrace();
+ System.exit(1);
+ }
+
+ System.out.println("PASS");
+ }
+
+ private void run( String[] args) throws Exception {
+ int errCount = 0;
+ String testName = "AddAttributeChangeNotificationListenerTest0001";
+ ObjectName modelMBeanObjectName = null;
+ ModelMBeanInfo modelMBeanInfo = null;
+ MBeanServer mbeanserver = MBeanServerFactory.newMBeanServer();
+ String modelMBeanName = "RequiredModelMBean";
+ String modelMBeanClassName =
+ "javax.management.modelmbean.RequiredModelMBean";
+
+ modelMBeanObjectName =
+ new ObjectName("AddAttributeChangeNotificationListenerTest:type=" +
+ modelMBeanName);
+
+ System.out.println("Build a ModelMBeanInfo without attribute State");
+ modelMBeanInfo = createModelMBeanInfo();
+
+ System.out.println("Create and register a RequiredModelMBean " +
+ "with that MBeanInfo");
+ Object[] params = { modelMBeanInfo };
+ String[] sig = { "javax.management.modelmbean.ModelMBeanInfo" };
+ mbeanserver.createMBean(modelMBeanClassName,
+ modelMBeanObjectName,
+ params,
+ sig);
+
+ ModelMBeanListener aListener = new ModelMBeanListener();
+
+ // add an attribute change listener
+ System.out.println("Add an attribute change listener for State");
+ try {
+ mbeanserver.invoke(modelMBeanObjectName,
+ "addAttributeChangeNotificationListener",
+ (new Object[] {aListener, "State", null}),
+ (new String[] {"javax.management.NotificationListener",
+ "java.lang.String",
+ "java.lang.Object"}));
+ System.out.println("NOK: Did not get expected " +
+ "RuntimeOperationsException");
+ errCount++;
+ } catch (Exception e) {
+ if (e instanceof MBeanException)
+ e = ((MBeanException) e).getTargetException();
+ if (e instanceof RuntimeOperationsException) {
+ RuntimeOperationsException roe =
+ (RuntimeOperationsException) e;
+ Exception target = roe.getTargetException();
+ System.out.println("OK: Got expected RuntimeOperationsException");
+
+ if ( target instanceof IllegalArgumentException ) {
+ System.out.println("OK: Got expected " +
+ "wrapped IllegalArgumentException");
+ } else {
+ System.out.println("NOK: Got wrapped "
+ + target
+ + " as we expect IllegalArgumentException");
+ errCount++;
+ }
+ } else {
+ System.out.println("NOK: Got "
+ + e
+ + " as we expect RuntimeOperationsException");
+ errCount++;
+ }
+ }
+
+ if ( errCount != 0 )
+ throw new Exception(errCount
+ + " error(s) occured");
+ }
+
+ /**
+ * Returns a ModelMBeanInfo with two operations:
+ * setManagedResource
+ * addAttributeChangeNotificationListener
+ */
+ private ModelMBeanInfo createModelMBeanInfo() throws Exception {
+ // operation setManagedResource
+ String descriptionOp1Set = "ManagedResource description setter";
+ Class[] paramsSet1 = {Class.forName("java.lang.Object"),
+ Class.forName("java.lang.String")};
+ Method oper1Set =
+ RequiredModelMBean.class.getMethod("setManagedResource",
+ paramsSet1);
+ ModelMBeanOperationInfo operation1Set =
+ new ModelMBeanOperationInfo(descriptionOp1Set,
+ oper1Set);
+
+ // operation addAttributeChangeNotificationListener
+ String descriptionop2Set =
+ "addAttributeChangeNotificationListener description";
+ Class [] paramsSet2 =
+ {Class.forName("javax.management.NotificationListener"),
+ Class.forName("java.lang.String"),
+ Class.forName("java.lang.Object")};
+ Method oper2Set =
+ RequiredModelMBean.class.getMethod(
+ "addAttributeChangeNotificationListener",
+ paramsSet2);
+ ModelMBeanOperationInfo operation2Set =
+ new ModelMBeanOperationInfo(descriptionop2Set,
+ oper2Set);
+
+ // define ModelMBeanInfo
+ String className = "ModelMBeansInfo";
+ String descriptionmodel = "Model MBean Test";
+ ModelMBeanAttributeInfo[] attributes = null;
+ ModelMBeanOperationInfo[] operations = {
+ operation1Set,
+ operation2Set
+ };
+ ModelMBeanNotificationInfo[] notifications = null;
+ ModelMBeanConstructorInfo[] constructors = null;
+
+ ModelMBeanInfoSupport modelMBeanInfo =
+ new ModelMBeanInfoSupport(className,
+ descriptionmodel,
+ attributes,
+ constructors,
+ operations,
+ notifications);
+ return modelMBeanInfo;
+ }
+
+ public static class ModelMBeanListener implements NotificationListener {
+
+ public ModelMBeanListener() {
+ tally = 0;
+ }
+
+ public void handleNotification(Notification acn, Object handback) {
+ tally++;
+ }
+
+ public int getCount() {
+ return tally;
+ }
+
+ public int setCount(int newTally) {
+ tally = newTally;
+ return tally;
+ }
+
+ private int tally = 0;
+
+ }
+}
diff --git a/test/javax/management/modelmbean/DefaultDescriptorFieldTest.java b/test/javax/management/modelmbean/DefaultDescriptorFieldTest.java
new file mode 100644
index 0000000..52eedee
--- /dev/null
+++ b/test/javax/management/modelmbean/DefaultDescriptorFieldTest.java
@@ -0,0 +1,354 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6252592 4967755
+ * @summary Check that default fields are correctly added to Descriptors
+ * and that input Descriptors are never modified
+ * @author Lars Westergren
+ */
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import javax.management.Descriptor;
+import javax.management.IntrospectionException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanConstructorInfo;
+import javax.management.MBeanException;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.RuntimeOperationsException;
+import javax.management.modelmbean.DescriptorSupport;
+import javax.management.modelmbean.ModelMBeanAttributeInfo;
+import javax.management.modelmbean.ModelMBeanConstructorInfo;
+import javax.management.modelmbean.ModelMBeanInfo;
+import javax.management.modelmbean.ModelMBeanInfoSupport;
+import javax.management.modelmbean.ModelMBeanNotificationInfo;
+import javax.management.modelmbean.ModelMBeanOperationInfo;
+
+/**
+ * Junit tests for bugs:
+ * 6252592 Provide for the user mandatory fields missing in Descriptor given
+ * to Model*Info constructors
+ * 4967755 ModelMBeanAttributeInfo constructor modifies its Descriptor argument
+ *
+ * @author Lars Westergren
+ */
+public class DefaultDescriptorFieldTest /*extends TestCase*/ {
+ public static void main(String[] args) throws Exception {
+ boolean fail = false;
+ Object test = new DefaultDescriptorFieldTest("Test");
+ for (Method m : DefaultDescriptorFieldTest.class.getMethods()) {
+ if (m.getName().startsWith("test") &&
+ m.getParameterTypes().length == 0) {
+ System.out.println("Testing " + m.getName());
+ try {
+ m.invoke(test);
+ } catch (InvocationTargetException e) {
+ fail = true;
+ Throwable t = e.getCause();
+ System.out.println("FAILED: exception: " + t);
+ t.printStackTrace(System.out);
+ }
+ }
+ }
+ if (fail)
+ throw new Exception("TEST FAILED");
+ }
+
+ //No check WHICH constructor is reflected, at least when the classes tested are constructed,
+ //so I just use first one that came to mind.
+ final Constructor[] constArr = String.class.getConstructors();
+ final Constructor dummyConstructor = constArr[0];
+
+
+ Method getMethod = null;
+
+ /** Creates a new instance of MBeanTest */
+ public DefaultDescriptorFieldTest(final String name) {
+ try {
+ getMethod = String.class.getMethod("toString");
+ } catch (SecurityException ex) {
+ ex.printStackTrace();
+ } catch (NoSuchMethodException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ /**
+ * Test instantiating the 5 different classes with a null
+ * Descriptor, and also setting a null descriptor after.
+ * Expected: Default Descriptors created.
+ */
+ public void testNullDescriptors()
+ throws IntrospectionException, MBeanException {
+ final ModelMBeanConstructorInfo constInfo =
+ new ModelMBeanConstructorInfo("Dummy", dummyConstructor, null);
+ constInfo.setDescriptor(null);
+ ModelMBeanAttributeInfo attInfo =
+ new ModelMBeanAttributeInfo("dummyAttInfoName", "dummyAttInfoDesc", getMethod, null, null);
+ attInfo.setDescriptor(null);
+ ModelMBeanNotificationInfo notInfo =
+ new ModelMBeanNotificationInfo(null, "notificationClassName", "daName", null);
+ notInfo.setDescriptor(null);
+ ModelMBeanOperationInfo opInfo =
+ new ModelMBeanOperationInfo("test", getMethod, null);
+ opInfo.setDescriptor(null);
+ ModelMBeanInfoSupport infoSupport =
+ new ModelMBeanInfoSupport(new DummyModelMBeanInfo());
+ infoSupport.setDescriptor(null,null);
+ infoSupport.setDescriptor(null, "mbean");
+ }
+
+ /**
+ * Test instantiating and setting a Descriptor without the "name",
+ * "descriptorType" or "role" fields. This also tests whether the
+ * Descriptor is cloned before default values are set, since
+ * default values for one class will be incorrect for the next.
+ * Expected: Descriptor should be cloned, missing default values should be
+ * set
+ */
+ public void testFieldlessDescriptor()
+ throws IntrospectionException, MBeanException {
+ Descriptor theNamelessOne = new DescriptorSupport();
+ final ModelMBeanConstructorInfo constInfo =
+ new ModelMBeanConstructorInfo("Dummy", dummyConstructor, theNamelessOne);
+ constInfo.setDescriptor(theNamelessOne);
+ ModelMBeanAttributeInfo attInfo =
+ new ModelMBeanAttributeInfo("dummyAttInfoName", "dummyAttInfoDesc", getMethod, null, theNamelessOne);
+ attInfo.setDescriptor(theNamelessOne);
+ ModelMBeanNotificationInfo notInfo =
+ new ModelMBeanNotificationInfo(null, "notificationClassName", "daName", theNamelessOne);
+ notInfo.setDescriptor(theNamelessOne);
+ ModelMBeanOperationInfo opInfo =
+ new ModelMBeanOperationInfo("test", getMethod, theNamelessOne);
+ opInfo.setDescriptor(theNamelessOne);
+ ModelMBeanInfoSupport infoSupport = new ModelMBeanInfoSupport(new DummyModelMBeanInfo());
+ infoSupport.setDescriptor(theNamelessOne, null);
+ infoSupport.setDescriptor(theNamelessOne, "mbean");
+ }
+
+
+ /**
+ * Creates an empty DescriptorSupport and then test that ModelMBeanConstructorInfo accepts
+ * the correct fields in validation one by one.
+ */
+ public void testCorrectConstructorDescriptors()
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+ Descriptor cDesc = new DescriptorSupport(new String[0],new String[0]);
+ final ModelMBeanConstructorInfo constInfo =
+ new ModelMBeanConstructorInfo("Dummy", dummyConstructor, cDesc);
+ assertFalse(fieldRefuted(constInfo, cDesc, "name" , "java.lang.String"));
+ assertFalse(fieldRefuted(constInfo, cDesc, "role" , "constructor"));
+ assertFalse(fieldRefuted(constInfo, cDesc, "descriptorType" , "operation"));
+ }
+
+ /**
+ * Test that ModelMBeanConstructorInfo refutes incorrect fields in validation one by one.
+ */
+ public void testIncorrectConstructorDescriptors()
+ throws NoSuchMethodException, IllegalAccessException {
+ Descriptor cDesc = new DescriptorSupport(
+ new String[] {"getMethod", "setMethod", "role", "Class", "name", "descriptorType"},
+ new String[] {"dummyGetMethod", "dummySetMethod", "constructor", "dummyClass", "java.lang.String", "operation"});
+ final ModelMBeanConstructorInfo constInfo = new ModelMBeanConstructorInfo("Dummy", dummyConstructor, cDesc);
+ assertTrue(fieldRefuted(constInfo, cDesc, "name" , "blah"));
+ assertTrue(fieldRefuted(constInfo, cDesc, "descriptorType", "mbean"));
+ assertTrue(fieldRefuted(constInfo, cDesc, "descriptorType", "notification"));
+ assertTrue(fieldRefuted(constInfo, cDesc, "descriptorType", "constructor"));
+ assertTrue(fieldRefuted(constInfo, cDesc, "role", "operation"));
+ }
+
+ public void testCorrectAttributeDescriptors()
+ throws IntrospectionException, NoSuchMethodException, IllegalAccessException {
+ Descriptor aDesc = new DescriptorSupport(new String[0],new String[0]);
+ final ModelMBeanAttributeInfo attInfo = new ModelMBeanAttributeInfo("dummyAttInfoName", "dummyAttInfoDesc", getMethod, null, null);
+ assertFalse(fieldRefuted(attInfo, aDesc, "name" , "dummyAttInfoName"));
+ assertFalse(fieldRefuted(attInfo, aDesc, "descriptorType" , "attribute"));
+ }
+
+ public void testIncorrectAttributeDescriptors()
+ throws IntrospectionException, NoSuchMethodException, IllegalAccessException {
+ Descriptor aDesc = new DescriptorSupport();
+ final ModelMBeanAttributeInfo attInfo = new ModelMBeanAttributeInfo("dummyAttInfoName", "dummyAttInfoDesc", getMethod, null, null);
+ assertTrue(fieldRefuted(attInfo, aDesc, "name" , "blah"));
+ assertTrue(fieldRefuted(attInfo, aDesc, "descriptorType" , "constructor"));
+ assertTrue(fieldRefuted(attInfo, aDesc, "descriptorType" , "notification"));
+ }
+
+ public void testCorrectNotificationDescriptors()
+ throws NoSuchMethodException, IllegalAccessException {
+ Descriptor nDesc = new DescriptorSupport();
+ final ModelMBeanNotificationInfo nInfo = new ModelMBeanNotificationInfo(null, "notificationClassName", "daName", nDesc);
+ assertFalse(fieldRefuted(nInfo, nDesc, "name" , "notificationClassName"));
+ assertFalse(fieldRefuted(nInfo, nDesc, "descriptorType" , "notification"));
+ }
+
+ public void testIncorrectNotificationDescriptors()
+ throws NoSuchMethodException, IllegalAccessException {
+ Descriptor nDesc = new DescriptorSupport();
+ final ModelMBeanNotificationInfo nInfo = new ModelMBeanNotificationInfo(null, "notificationClassName", "daName", nDesc);
+ assertTrue(fieldRefuted(nInfo, nDesc, "name" , "blah"));
+ assertTrue(fieldRefuted(nInfo, nDesc, "descriptorType" , "constructor"));
+ assertTrue(fieldRefuted(nInfo, nDesc, "descriptorType" , "operation"));
+ }
+
+ public void testCorrectOperationDescriptors()
+ throws NoSuchMethodException, IllegalAccessException {
+ Descriptor opDesc = new DescriptorSupport();
+ final ModelMBeanOperationInfo opInfo = new ModelMBeanOperationInfo("test", "readable description", null, "type", 1, opDesc);
+ assertFalse(fieldRefuted(opInfo, opDesc, "name" , "test"));
+ assertFalse(fieldRefuted(opInfo, opDesc, "descriptorType" , "operation"));
+ assertFalse(fieldRefuted(opInfo, opDesc, "role" , "operation"));
+ assertFalse(fieldRefuted(opInfo, opDesc, "role" , "getter"));
+ assertFalse(fieldRefuted(opInfo, opDesc, "role" , "setter"));
+ }
+
+ public void testIncorrectOperationDescriptors()
+ throws NoSuchMethodException, IllegalAccessException {
+ Descriptor opDesc = new DescriptorSupport();
+ final ModelMBeanOperationInfo opInfo = new ModelMBeanOperationInfo("test", "readable description", null, "type", 1, opDesc);
+ assertTrue(fieldRefuted(opInfo, opDesc, "name" , "DENIED!!"));
+ assertTrue(fieldRefuted(opInfo, opDesc, "descriptorType" , "constructor"));
+ assertTrue(fieldRefuted(opInfo, opDesc, "descriptorType" , "attribute"));
+ assertTrue(fieldRefuted(opInfo, opDesc, "descriptorType" , "notification"));
+ assertTrue(fieldRefuted(opInfo, opDesc, "descriptorType" , "x"));
+ }
+
+ //TODO also test ModelMBeanInfoSupport perhaps. Slightly more difficult to set up and test.
+
+ /**
+ * Clones descriptor, sets a new value in the clone and tries to apply clone to
+ * reflected Model*Info object method. The new field should be refuted if it
+ * is a bad value.
+ */
+ //I like java, but this is one case where duck typing would have been slightly easier I think. :)
+ private boolean fieldRefuted(Object mbeanInfo, Descriptor desc, String fieldName, String newValue)
+ throws NoSuchMethodException, IllegalAccessException {
+ Method setDescMethod = mbeanInfo.getClass().getMethod("setDescriptor", Descriptor.class);
+ Descriptor newDesc = (Descriptor)desc.clone();
+ boolean refused = false;
+ newDesc.setField(fieldName, newValue);
+ try {
+ setDescMethod.invoke(mbeanInfo, newDesc);
+ } catch (InvocationTargetException ex) {
+ //If we get classcast exception, someone passed in a bad object to reflection.
+ //Perhaps an unnecessary check, this cast?
+ RuntimeOperationsException rex = (RuntimeOperationsException)ex.getTargetException();
+ refused = true;
+ }
+ return refused;
+ }
+
+ /**
+ * Dummy class used to create test objects. May not be needed.
+ */
+ private class DummyModelMBeanInfo implements ModelMBeanInfo {
+ public Descriptor[] getDescriptors(String inDescriptorType)
+ throws MBeanException, RuntimeOperationsException {
+ return null;
+ }
+
+ public void setDescriptors(Descriptor[] inDescriptors)
+ throws MBeanException, RuntimeOperationsException {
+
+ }
+
+ public Descriptor getDescriptor(String inDescriptorName, String inDescriptorType)
+ throws MBeanException, RuntimeOperationsException {
+ return null;
+ }
+
+ public void setDescriptor(Descriptor inDescriptor, String inDescriptorType)
+ throws MBeanException, RuntimeOperationsException {
+
+ }
+
+ public Descriptor getMBeanDescriptor()
+ throws MBeanException, RuntimeOperationsException {
+ return null;
+ }
+
+ public void setMBeanDescriptor(Descriptor inDescriptor)
+ throws MBeanException, RuntimeOperationsException {
+
+ }
+
+ public ModelMBeanAttributeInfo getAttribute(String inName)
+ throws MBeanException, RuntimeOperationsException {
+ return null;
+ }
+
+ public ModelMBeanOperationInfo getOperation(String inName)
+ throws MBeanException, RuntimeOperationsException {
+ return null;
+ }
+
+ public ModelMBeanNotificationInfo getNotification(String inName)
+ throws MBeanException, RuntimeOperationsException {
+ return null;
+ }
+
+ public MBeanAttributeInfo[] getAttributes() {
+ return null;
+ }
+
+ public String getClassName() {
+ return "AnonMBeanInfoImpl";
+ }
+
+ public MBeanConstructorInfo[] getConstructors() {
+ return null;
+ }
+
+ public String getDescription() {
+ return null;
+ }
+
+ public MBeanNotificationInfo[] getNotifications() {
+ return null;
+ }
+
+ public MBeanOperationInfo[] getOperations() {
+ return null;
+ }
+
+ public Object clone() {
+ return null;
+
+ }
+
+ }
+
+ private static void assertFalse(boolean x) {
+ assertTrue(!x);
+ }
+
+ private static void assertTrue(boolean x) {
+ if (!x)
+ throw new AssertionError("Assertion failed");
+ }
+
+}
diff --git a/test/javax/management/modelmbean/DescriptorSupportSerialTest.java b/test/javax/management/modelmbean/DescriptorSupportSerialTest.java
new file mode 100644
index 0000000..6734cb2
--- /dev/null
+++ b/test/javax/management/modelmbean/DescriptorSupportSerialTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6332962
+ * @summary Test that DescriptorSupport does not serialize targetObject
+ * @author Eamonn McManus
+ * @run clean DescriptorSupportSerialTest
+ * @run build DescriptorSupportSerialTest
+ * @run main DescriptorSupportSerialTest
+ */
+
+import java.lang.reflect.Method;
+import javax.management.*;
+import javax.management.remote.*;
+import javax.management.modelmbean.*;
+
+public class DescriptorSupportSerialTest {
+ public static void main(String[] args) throws Exception {
+ if (java.io.Serializable.class.isAssignableFrom(Thread.class))
+ throw new Exception("TEST BAD: Thread is Serializable!");
+ Method getName = Thread.class.getMethod("getName");
+ Descriptor d = new DescriptorSupport();
+ d.setField("name", "getName");
+ d.setField("descriptorType", "operation");
+ d.setField("TARGETObject", Thread.currentThread());
+ d.setField("foo", "bar");
+ ModelMBeanOperationInfo getNameInfo =
+ new ModelMBeanOperationInfo("Get name", getName, d);
+ ModelMBeanInfo mmbi =
+ new ModelMBeanInfoSupport(Thread.class.getName(),
+ "Thread!",
+ null, // no attributes
+ null, // no constructors
+ new ModelMBeanOperationInfo[] {getNameInfo},
+ null); // no notifications
+ ModelMBean mmb = new RequiredModelMBean(mmbi);
+
+ ObjectName on = new ObjectName("d:type=Thread");
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ mbs.registerMBean(mmb, on);
+
+ 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();
+
+ try {
+ test(mbsc, on);
+ System.out.println("TEST PASSED");
+ } finally {
+ cc.close();
+ cs.stop();
+ }
+ }
+
+ private static void test(MBeanServerConnection mbsc, ObjectName on)
+ throws Exception {
+ ModelMBeanInfo mmbi2 = (ModelMBeanInfo) mbsc.getMBeanInfo(on);
+ // previous line will fail if serialization includes targetObject
+
+ Descriptor d2 = mmbi2.getDescriptor("getName", "operation");
+ if (!"bar".equals(d2.getFieldValue("foo")))
+ throw new Exception("TEST FAILED: bad descriptor: " + d2);
+
+ String name = (String) mbsc.invoke(on, "getName", null, null);
+ String thisName = Thread.currentThread().getName();
+ if (!thisName.equals(name)) {
+ throw new Exception("TEST FAILED: wrong thread name: " +
+ name + " should be " + thisName);
+ }
+ }
+}
diff --git a/test/javax/management/modelmbean/DescriptorSupportTest.java b/test/javax/management/modelmbean/DescriptorSupportTest.java
new file mode 100644
index 0000000..1efeeb1
--- /dev/null
+++ b/test/javax/management/modelmbean/DescriptorSupportTest.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright 2003-2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4883712 4869006 4894856 5016685
+ * @summary Test that DescriptorSupport correctly validates fields
+ * @author Eamonn McManus
+ * @run clean DescriptorSupportTest
+ * @run build DescriptorSupportTest
+ * @run main DescriptorSupportTest
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import javax.management.Descriptor;
+import javax.management.RuntimeOperationsException;
+import javax.management.modelmbean.DescriptorSupport;
+import javax.management.modelmbean.ModelMBeanInfo;
+import javax.management.modelmbean.ModelMBeanInfoSupport;
+
+public class DescriptorSupportTest {
+ private static final Object[] goodFields = {
+ "value", "",
+ "severity", "0",
+ "severity", "6",
+ };
+
+ private static final Object[] badFields = {
+ "name", null,
+ "name", "",
+ "descriptorType", null,
+ "descriptorType", "",
+ "setMethod", null,
+ "getMethod", null,
+ "role", null,
+ "class", null,
+ "visibility", null,
+ "visibility", new Integer(0),
+ "visibility", "0",
+ "visibility", new Integer(5),
+ "visibility", "5",
+ "severity", null,
+ "severity", new Integer(-1),
+ "severity", "-1",
+ "severity", new Integer(7),
+ "severity", "7",
+ "persistPolicy", null,
+ "persistPolicy", "bogusPersistPolicy",
+ "persistPeriod", null,
+ "persistPeriod", "not a number",
+ "currencyTimeLimit", null,
+ "currencyTimeLimit", "not a number",
+ "lastUpdatedTimeStamp", null,
+ "lastUpdatedTimeStamp", "not a number",
+ "lastReturnedTimeStamp", null,
+ "lastReturnedTimeStamp", "not a number",
+ "log", null,
+ "log", "not T or F or true or false",
+ "log", new Object[0],
+ };
+
+
+ public static void main(String[] args) throws Exception {
+ boolean ok = true;
+
+ System.out.println("Checking that name and descriptorType are " +
+ "mandatory");
+ // Try omitting name and/or descriptorType
+ for (int i = 0; i < 3; i++) {
+ final boolean addName = ((i & 1) != 0);
+ final boolean addDescriptorType = ((i & 2) != 0);
+ final List fields = new ArrayList();
+ if (addName)
+ fields.add("name=something");
+ if (addDescriptorType)
+ fields.add("descriptorType=something-else");
+ final String[] fs = (String[]) fields.toArray(new String[0]);
+ final String what =
+ "DescriptorSupport with " +
+ (addName ? "" : "no ") + "name and " +
+ (addDescriptorType ? "" : "no ") + "descriptorType";
+ DescriptorSupport ds = new DescriptorSupport(fs);
+ if (ds.isValid()) {
+ System.out.println("INCORRECTLY ACCEPTED: " + what);
+ ok = false;
+ } else
+ System.out.println("OK: rejected " + what);
+ }
+
+ for (int pass = 0; pass < 2; pass++) {
+ boolean shouldAccept = (pass == 0);
+ System.out.println("Trying out " +
+ (shouldAccept ? "correct" : "bogus") +
+ " DescriptorSupport fields");
+ Object[] fields = shouldAccept ? goodFields : badFields;
+ for (int i = 0; i < fields.length; i += 2) {
+ String[] names = {"name", "descriptorType"};
+ String[] values = {"some-name", "some-type"};
+ DescriptorSupport d = new DescriptorSupport(names, values);
+ final String name = (String) fields[i];
+ final Object value = fields[i + 1];
+ final String valueS =
+ (value instanceof String) ? ("\"" + value + "\"") :
+ (value == null) ? "null" : value.toString();
+ final String what =
+ "DescriptorSupport with " + name + " = " + valueS;
+ try {
+ d.setField(name, value);
+ if (shouldAccept)
+ System.out.println("OK: accepted " + what);
+ else {
+ System.out.println("INCORRECTLY ACCEPTED: " + what);
+ ok = false;
+ }
+ } catch (RuntimeOperationsException e) {
+ if (shouldAccept) {
+ System.out.println("INCORRECTLY REJECTED: " + what +
+ ": " + e);
+ ok = false;
+ } else {
+ System.out.println("OK: rejected " + what);
+ // OK: this is what should happen
+ }
+ } catch (Exception e) {
+ System.out.println("WRONG EXCEPTION: " + what + ": " + e);
+ ok = false;
+ }
+ }
+ }
+
+ // 4894856: ModelMBeanInfoSupport.setDescriptor(d, "mbean") fails
+ System.out.println("Checking that setDescriptor(d, \"mbean\") works");
+ ModelMBeanInfo mmbi =
+ new ModelMBeanInfoSupport("x", "descr", null, null, null, null);
+ Descriptor d = mmbi.getDescriptor("x", "mbean");
+ try {
+ mmbi.setDescriptor(d, "mbean");
+ } catch (Exception e) {
+ System.out.println("Unexpected exception:");
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+
+ // 5016685: DescriptorSupport forces field names to lower case
+ System.out.println("Checking that field name case is ignored " +
+ "but preserved");
+ ok &= caseTest(new DescriptorSupport(new String[] {"NAME=blah"}),
+ "DescriptorSupport(String[])");
+ ok &= caseTest(new DescriptorSupport(new String[] {"NAME"},
+ new String[] {"blah"}),
+ "DescriptorSupport(String[], Object[])");
+ DescriptorSupport d1 = new DescriptorSupport();
+ d1.setField("NAME", "blah");
+ ok &= caseTest(d1, "DescriptorSupport.setField");
+ d1 = new DescriptorSupport(new String[] {"NAME=blah"});
+ ok &= caseTest(new DescriptorSupport(d1),
+ "DescriptorSupport(Descriptor)");
+ d1 = new DescriptorSupport(new String[] {"NAME=blah"});
+ ok &= caseTest(new DescriptorSupport(d1.toXMLString()),
+ "DescriptorSupport(String)");
+ d1 = new DescriptorSupport(new String[] {"NAME=blah"});
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(bos);
+ oos.writeObject(d1);
+ oos.close();
+ bos.close();
+ ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
+ ObjectInputStream ois = new ObjectInputStream(bis);
+ d1 = (DescriptorSupport) ois.readObject();
+ ok &= caseTest(d1, "serialized DescriptorSupport");
+
+ if (ok)
+ System.out.println("Test passed");
+ else {
+ System.out.println("TEST FAILED");
+ System.exit(1);
+ }
+ }
+
+ private static boolean caseTest(Descriptor d, String what) {
+ boolean ok = true;
+
+ System.out.println("..." + what);
+
+ String[] names = d.getFieldNames();
+ if (names.length != 1 || !names[0].equals("NAME")) {
+ ok = false;
+ System.out.println("...getFieldNames() fails: " +
+ Arrays.asList(names));
+ }
+
+ String[] fields = d.getFields();
+ if (fields.length != 1 || !fields[0].equals("NAME=blah")) {
+ ok = false;
+ System.out.println("...getFields() fails: " +
+ Arrays.asList(fields));
+ }
+
+ Object value = d.getFieldValue("namE");
+ if (!"blah".equals(value)) {
+ ok = false;
+ System.out.println("...getFieldValue(\"namE\") fails: " + value);
+ }
+
+ Object[] values = d.getFieldValues(new String[] {"namE"});
+ if (values.length != 1 || !"blah".equals(values[0])) {
+ ok = false;
+ System.out.println("...getFieldValues({\"namE\"}) fails: " +
+ Arrays.asList(values));
+ }
+
+ d.setField("namE", "newblah");
+ Object newblah = d.getFieldValue("Name");
+ if (!"newblah".equals(newblah)) {
+ ok = false;
+ System.out.println("...setField value not returned: " + newblah);
+ }
+
+ d.setFields(new String[] {"NaMe"}, new Object[] {"newerblah"});
+ Object newerblah = d.getFieldValue("naMe");
+ if (!"newerblah".equals(newerblah)) {
+ ok = false;
+ System.out.println("...setFields value not returned: " +
+ newerblah);
+ }
+
+ Descriptor d1 = (Descriptor) d.clone();
+ newerblah = d1.getFieldValue("NAMe");
+ if (!"newerblah".equals(newerblah)) {
+ ok = false;
+ System.out.println("...clone incorrect: " + newerblah);
+ }
+
+ d.removeField("NAme");
+ names = d.getFieldNames();
+ if (names.length != 0) {
+ ok = false;
+ System.out.println("...removeField failed: " +
+ Arrays.asList(names));
+ }
+
+ if (ok)
+ System.out.println("...succeeded");
+
+ return ok;
+ }
+}
diff --git a/test/javax/management/modelmbean/DescriptorSupportXMLTest.java b/test/javax/management/modelmbean/DescriptorSupportXMLTest.java
new file mode 100644
index 0000000..398033c
--- /dev/null
+++ b/test/javax/management/modelmbean/DescriptorSupportXMLTest.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4957393
+ * @summary Test that DescriptorSupport.toXMLString() can be used to
+ * reconstruct an equivalent DescriptorSupport
+ * @author Eamonn McManus
+ * @run clean DescriptorSupportXMLTest
+ * @run build DescriptorSupportXMLTest
+ * @run main DescriptorSupportXMLTest
+ */
+
+import java.util.Arrays;
+
+import javax.management.RuntimeOperationsException;
+import javax.management.modelmbean.DescriptorSupport;
+
+public class DescriptorSupportXMLTest {
+ public static void main(String[] args) throws Exception {
+ System.out.println("Testing that DescriptorSupport.toXMLString() " +
+ "can be used to reconstruct an equivalent " +
+ "DescriptorSupport");
+ int failed = 0;
+
+ final Object[] testValues = {
+ // Values that should be encodable.
+ "",
+ "ok",
+ "null",
+ "(open",
+ "close)",
+ "(parens)",
+ "quote\"quote",
+ "a description with several words",
+ "magic&\"\\<> \r\t\n\f;&;magic",
+ "<descriptor>&&&</descriptor>",
+ "<descriptor>&&&</blahblahblah>",
+ null,
+ new Integer(10),
+ Boolean.TRUE,
+ new Float(1.0f),
+
+ // Values that are not encodable: it is important that we throw
+ // an exception during encoding rather than waiting until decode
+ // time to discover the problem. These classes are not encodable
+ // because they don't have a (String) constructor.
+ new Character('!'),
+ new java.util.HashMap(),
+ };
+
+ for (int i = 0; i < testValues.length; i++) {
+ final Object v = testValues[i];
+ final String what =
+ (v == null) ? "null" :
+ (v.getClass().getName() + "{" + v + "}");
+
+ final DescriptorSupport in =
+ new DescriptorSupport(new String[] {"bloo"}, new Object[] {v});
+
+ final String xml;
+ try {
+ xml = in.toXMLString();
+ } catch (RuntimeOperationsException e) {
+ final Throwable cause = e.getCause();
+ if (cause instanceof IllegalArgumentException) {
+ System.out.println("OK: " + what + ": got a " +
+ "RuntimeOperationsException wrapping " +
+ "an IllegalArgumentException: " +
+ cause.getMessage());
+ } else {
+ final String causeString =
+ (cause == null) ? "null" : cause.getClass().getName();
+ System.out.println("FAILED: " + what + ": got a " +
+ "RuntimeOperationException wrapping " +
+ causeString);
+ failed++;
+ }
+ continue;
+ }
+
+ System.out.println("Encoded " + what + " as " + xml);
+
+ final DescriptorSupport out;
+ try {
+ out = new DescriptorSupport(xml);
+ } catch (Exception e) {
+ System.out.println("FAILED: " + what + ": got an exception:");
+ e.printStackTrace(System.out);
+ failed++;
+ continue;
+ }
+
+ final String[] names = out.getFieldNames();
+ if (names.length != 1 || !"bloo".equals(names[0])) {
+ System.out.println("FAILED: decoded names wrong: " +
+ Arrays.asList(names));
+ failed++;
+ continue;
+ }
+
+ final Object[] values = out.getFieldValues(names);
+ if (values.length != 1) {
+ System.out.println("FAILED: wrong number of values: " +
+ Arrays.asList(values));
+ failed++;
+ continue;
+ }
+
+ final Object outValue = values[0];
+
+ if (v == null) {
+ if (outValue == null)
+ System.out.println("OK: decoded null value");
+ else {
+ System.out.println("FAILED: decoded null value as " +
+ outValue.getClass().getName() + "{" +
+ outValue + "}");
+ failed++;
+ }
+ continue;
+ }
+
+ if (outValue == null) {
+ System.out.println("FAILED: decoded non-null value as null");
+ failed++;
+ continue;
+ }
+
+ if (v.getClass() != outValue.getClass()) {
+ System.out.println("FAILED: decoded value has class " +
+ outValue.getClass().getName() + "{" +
+ outValue + "}");
+ failed++;
+ continue;
+ }
+
+ if (v.equals(outValue))
+ System.out.println("OK: decoded value is equal to original");
+ else {
+ System.out.println("FAILED: decoded value is different: {" +
+ outValue + "}");
+ failed++;
+ }
+ }
+
+ if (failed == 0)
+ System.out.println("OK: all tests passed");
+ else {
+ System.out.println("TEST FAILED: fail count: " + failed);
+ System.exit(1);
+ }
+ }
+}
diff --git a/test/javax/management/modelmbean/ExoticTargetTypeTest.java b/test/javax/management/modelmbean/ExoticTargetTypeTest.java
new file mode 100644
index 0000000..a3d69be
--- /dev/null
+++ b/test/javax/management/modelmbean/ExoticTargetTypeTest.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4954062
+ * @summary Test that a custom ModelMBean implementation can have custom
+ * targetType values in its ModelMBeanOperationInfo descriptors.
+ * @author Eamonn McManus
+ * @run clean ExoticTargetTypeTest
+ * @run build ExoticTargetTypeTest
+ * @run main ExoticTargetTypeTest
+ */
+
+import javax.management.*;
+import javax.management.modelmbean.*;
+
+public class ExoticTargetTypeTest {
+ public static void main(String[] args) throws Exception {
+ System.out.println("Testing that ModelMBeanOperationInfo can contain" +
+ " a nonstandard targetType provided that the " +
+ "ModelMBean understands it");
+
+ boolean ok = true;
+
+ final Descriptor noddyDescr =
+ new DescriptorSupport(new String[] {
+ "name=noddy",
+ "descriptorType=operation",
+ "role=operation",
+ "targetType=noddy",
+ });
+ final ModelMBeanOperationInfo opInfo =
+ new ModelMBeanOperationInfo("noddy",
+ "noddy description",
+ new MBeanParameterInfo[0],
+ "void",
+ ModelMBeanOperationInfo.ACTION,
+ noddyDescr);
+ final ModelMBeanInfo mmbInfo =
+ new ModelMBeanInfoSupport(ExoticModelMBean.class.getName(),
+ "Noddy ModelMBean description",
+ null, null,
+ new ModelMBeanOperationInfo[] {opInfo},
+ null);
+
+ System.out.println("Testing nonstandard ModelMBean with nonstandard " +
+ "ModelMBeanOperationInfo...");
+ final ExoticModelMBean exoticMMB = new ExoticModelMBean(mmbInfo);
+ try {
+ test(exoticMMB);
+ if (exoticMMB.noddyCalled)
+ System.out.println("...OK");
+ else {
+ System.out.println("...TEST FAILS: invoke worked but did " +
+ "not invoke method?!");
+ ok = false;
+ }
+ } catch (Exception e) {
+ System.out.println("...TEST FAILS: exception:");
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+
+ System.out.println("Testing standard ModelMBean with nonstandard " +
+ "ModelMBeanOperationInfo...");
+ final ModelMBean standardMMB = new RequiredModelMBean(mmbInfo);
+ // RequiredModelMBean's constructor could legitimately throw
+ // an exception here because of the nonstandard descriptor.
+ // If some day it does, we will have to update this test.
+ try {
+ test(standardMMB);
+ System.out.println("...TEST FAILS: invoke worked but should not");
+ ok = false;
+ } catch (MBeanException e) {
+ Throwable cause = e.getCause();
+ if (cause instanceof InvalidTargetObjectTypeException) {
+ System.out.println("...OK: got exception MBeanException/" +
+ "InvalidTargetObjectTypeException: " +
+ cause.getMessage());
+ } else {
+ System.out.println("...TEST FAILS: got MBeanException with " +
+ "wrong cause: " + cause);
+ ok = false;
+ }
+ } catch (Exception e) {
+ System.out.println("...TEST FAILS: exception:");
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+
+ if (ok)
+ System.out.println("Test passed");
+ else {
+ System.out.println("TEST FAILED");
+ System.exit(1);
+ }
+ }
+
+ private static void test(ModelMBean mmb) throws Exception {
+ final MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ final ObjectName name = new ObjectName("d:k=v");
+ mbs.registerMBean(mmb, name);
+ try {
+ mbs.invoke(name, "noddy", null, null);
+ } finally {
+ mbs.unregisterMBean(name);
+ }
+ }
+
+ public static class ExoticModelMBean extends RequiredModelMBean {
+ public ExoticModelMBean(ModelMBeanInfo mmbInfo) throws MBeanException {
+ super();
+ this.mmbInfo = mmbInfo;
+ }
+
+ public Object invoke(String opName, Object[] opArgs, String[] sig)
+ throws MBeanException, ReflectionException {
+ if (opName.equals("noddy")) {
+ noddyCalled = true;
+ return null;
+ } else
+ throw new IllegalArgumentException("Not noddy: " + opName);
+ }
+
+ private boolean noddyCalled;
+ private final ModelMBeanInfo mmbInfo;
+ }
+}
diff --git a/test/javax/management/modelmbean/InfoSupportTest.java b/test/javax/management/modelmbean/InfoSupportTest.java
new file mode 100644
index 0000000..ebf921f
--- /dev/null
+++ b/test/javax/management/modelmbean/InfoSupportTest.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4967769 4980655 4980668 4981214
+ * @summary Test that ModelMBeanInfoSupport.setDescriptor rejects
+ * null descriptor, that empty arrays are handled correctly,
+ * that getDescriptors("mbean") works, and that default values for
+ * MBean descriptors are correctly assigned.
+ * @author Eamonn McManus
+ * @run clean InfoSupportTest
+ * @run build InfoSupportTest
+ * @run main InfoSupportTest
+ */
+
+import java.util.*;
+import javax.management.Descriptor;
+import javax.management.RuntimeOperationsException;
+import javax.management.modelmbean.*;
+
+public class InfoSupportTest {
+ public static void main(String[] args) throws Exception {
+ boolean ok = true;
+
+ ok &= testSetDescriptorNull();
+ ok &= testEmptyArrayParameters();
+ ok &= testGetDescriptorsForMBean();
+
+ if (ok)
+ System.out.println("Test passed");
+ else {
+ System.out.println("TEST FAILED");
+ System.exit(1);
+ }
+ }
+
+ private static boolean testSetDescriptorNull() {
+ System.out.println("Testing that " +
+ "ModelMBeanInfoSupport.setDescriptor(null, \"x\")" +
+ " throws an exception");
+
+ ModelMBeanAttributeInfo mmbai =
+ new ModelMBeanAttributeInfo("attribute",
+ "java.lang.String",
+ "an attribute",
+ true, true, false);
+ ModelMBeanInfo mmbi =
+ new ModelMBeanInfoSupport("bogus.class.name",
+ "an MBean",
+ new ModelMBeanAttributeInfo[] {mmbai},
+ null, null, null);
+ try {
+ mmbi.setDescriptor(null, "attribute");
+ } catch (RuntimeOperationsException e) {
+ if (e.getTargetException() instanceof IllegalArgumentException) {
+ System.out.println("Test passes: got a " +
+ "RuntimeOperationsException wrapping an " +
+ "IllegalArgumentException");
+ return true;
+ } else {
+ System.out.println("TEST FAILS: wrong exception:");
+ e.printStackTrace(System.out);
+ return false;
+ }
+ } catch (Exception e) {
+ System.out.println("TEST FAILS: wrong exception:");
+ e.printStackTrace(System.out);
+ return false;
+ }
+
+ System.out.println("TEST FAILS: exception not thrown");
+ return false;
+ }
+
+ private static boolean testEmptyArrayParameters()
+ throws Exception {
+
+ System.out.println("Test that empty and null array parameters " +
+ "produce the right type from getters");
+
+ boolean ok = true;
+
+ ModelMBeanInfoSupport mmbi;
+
+ mmbi =
+ new ModelMBeanInfoSupport("bogus.class.name", "description",
+ null, null, null, null);
+ ok &= checkMMBI(mmbi, "null parameters, no descriptor");
+
+ mmbi =
+ new ModelMBeanInfoSupport("bogus.class.name", "description",
+ null, null, null, null, null);
+ ok &= checkMMBI(mmbi, "null parameters, null descriptor");
+
+ mmbi =
+ new ModelMBeanInfoSupport("bogus.class.name", "description",
+ new ModelMBeanAttributeInfo[0],
+ new ModelMBeanConstructorInfo[0],
+ new ModelMBeanOperationInfo[0],
+ new ModelMBeanNotificationInfo[0]);
+ ok &= checkMMBI(mmbi, "empty parameters, no descriptor");
+
+ mmbi =
+ new ModelMBeanInfoSupport("bogus.class.name", "description",
+ new ModelMBeanAttributeInfo[0],
+ new ModelMBeanConstructorInfo[0],
+ new ModelMBeanOperationInfo[0],
+ new ModelMBeanNotificationInfo[0],
+ null);
+ ok &= checkMMBI(mmbi, "empty parameters, null descriptor");
+
+ return ok;
+ }
+
+ private static boolean checkMMBI(ModelMBeanInfoSupport mmbi, String what)
+ throws Exception {
+ String bad = "";
+
+ if (!(mmbi.getAttributes() instanceof ModelMBeanAttributeInfo[]))
+ bad += " attributes";
+ if (!(mmbi.getConstructors() instanceof ModelMBeanConstructorInfo[]))
+ bad += " constructors";
+ if (!(mmbi.getOperations() instanceof ModelMBeanOperationInfo[]))
+ bad += " operations";
+ if (!(mmbi.getNotifications() instanceof ModelMBeanNotificationInfo[]))
+ bad += " notifications";
+
+ if (bad.equals("")) {
+ System.out.println("..." + what + ": OK");
+ return true;
+ } else {
+ System.out.println("..." + what + ": FAILS for:" + bad);
+ return false;
+ }
+ }
+
+ private static boolean testGetDescriptorsForMBean()
+ throws Exception {
+ System.out.println("Test getDescriptors(\"mbean\")");
+
+ boolean ok = true;
+
+ ModelMBeanInfo mmbi;
+ Descriptor[] mbeanDescrs;
+
+ mmbi = new ModelMBeanInfoSupport("bogus.class.name", "description",
+ null, null, null, null);
+ try {
+ mbeanDescrs = mmbi.getDescriptors("mbean");
+ if (mbeanDescrs.length == 1 && mbeanDescrs[0] != null)
+ System.out.println("...default MBean descriptor: OK");
+ else {
+ System.out.println("...default MBean descriptor: bad array: " +
+ Arrays.asList(mbeanDescrs));
+ ok = false;
+ }
+ } catch (Exception e) {
+ System.out.println("...default MBean descriptor: got exception:");
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+
+ String[] fields = new String[] {"descriptorType", "name"};
+ String[] values = new String[] {"mbean", "whatsit"};
+ String[] defaultFields = new String[] {
+ "displayName", "persistPolicy", "log", "visibility",
+ };
+ String[] defaultValues = new String[] {
+ "bogus.class.name", "never", "F", "1",
+ };
+ Descriptor d = new DescriptorSupport(fields, values);
+
+ mmbi = new ModelMBeanInfoSupport("bogus.class.name", "description",
+ null, null, null, null, d);
+ try {
+ mbeanDescrs = mmbi.getDescriptors("mbean");
+ } catch (Exception e) {
+ System.out.println("...explicit MBean descriptor: got exception:");
+ e.printStackTrace(System.out);
+ mbeanDescrs = new Descriptor[] {mmbi.getMBeanDescriptor()};
+ }
+
+ if (mbeanDescrs.length == 1) {
+ Descriptor dd = mbeanDescrs[0];
+ boolean thisok = true;
+
+ // Check that the fields we supplied survived in the copy
+ // and were not changed in the original
+ for (int i = 0; i < fields.length; i++) {
+ String field = fields[i];
+ String value;
+ value = (String) dd.getFieldValue(field);
+ if (!values[i].equals(value)) {
+ System.out.println("...explicit MBean descriptor: " +
+ "value of " + field + " mutated: " +
+ value);
+ thisok = false;
+ }
+ value = (String) d.getFieldValue(field);
+ if (!values[i].equals(value)) {
+ System.out.println("...explicit MBean descriptor: " +
+ "value of " + field + " changed in " +
+ "original: " + value);
+ thisok = false;
+ }
+ }
+
+ // Check that the default fields were added
+ for (int i = 0; i < defaultFields.length; i++) {
+ String field = defaultFields[i];
+ String value = (String) dd.getFieldValue(field);
+ if (!defaultValues[i].equals(value)) {
+ System.out.println("...explicit MBean descriptor: " +
+ "default value of " + field +
+ " wrong: " + value + " should be " +
+ defaultValues[i]);
+ thisok = false;
+ }
+ }
+
+ // Check that the original did not acquire new fields
+ if (d.getFieldNames().length != fields.length) {
+ Collection c = new TreeSet(Arrays.asList(d.getFieldNames()));
+ c.removeAll(Arrays.asList(fields));
+ System.out.println("...explicit MBean descriptor: " +
+ "acquired new fields: " + c);
+ thisok = false;
+ }
+
+ if (thisok)
+ System.out.println("...explicit MBean descriptor: OK");
+ else
+ ok = false;
+ } else {
+ System.out.println("...explicit MBean descriptor: bad array: " +
+ Arrays.asList(mbeanDescrs));
+ ok = false;
+ }
+
+ return ok;
+ }
+}
diff --git a/test/javax/management/modelmbean/ModelMBeanInfoSupport/GetAllDescriptorsTest.java b/test/javax/management/modelmbean/ModelMBeanInfoSupport/GetAllDescriptorsTest.java
new file mode 100644
index 0000000..32d1a8d
--- /dev/null
+++ b/test/javax/management/modelmbean/ModelMBeanInfoSupport/GetAllDescriptorsTest.java
@@ -0,0 +1,312 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6337061
+ * @summary Test that ModelMBeanInfoSupport.getDescriptors(null) also
+ * returns the MBean's descriptor.
+ * @author Eamonn McManus, Daniel Fuchs
+ * @run clean GetAllDescriptorsTest
+ * @run build GetAllDescriptorsTest
+ * @run main/othervm/policy=policy GetAllDescriptorsTest
+ */
+
+import java.lang.reflect.*;
+import java.util.*;
+import javax.management.*;
+import javax.management.modelmbean.*;
+
+public class GetAllDescriptorsTest {
+
+ public static class Resource {
+ public int getNumber() {
+ return number;
+ }
+
+ public void setNumber(int n) {
+ number = n;
+ }
+
+ public int addOne(int x) {
+ return x + 1;
+ }
+
+ public Object[] getArray() {
+ return (Object[]) array.clone();
+ }
+
+ // doesn't look like an attribute so not seen by caching logic
+ public void tweakArray(Object[] array) {
+ this.array = (Object[]) array.clone();
+ }
+
+ private int number = 1234;
+ private Object[] array = {"hello", "world"};
+ }
+
+ public static void main(String[] args) {
+ int errorCount = 0;
+ for (int i = 0; i < NTESTS; i++) {
+ try {
+ System.out.println("Test " + i + ":");
+ test(i);
+ } catch (Throwable e) {
+ errorCount++;
+ boolean first = true;
+ do {
+ System.err.println(first ? "Exception:" : "Caused by:");
+ first = false;
+ e.printStackTrace();
+ Throwable nexte;
+ nexte = e.getCause();
+ if (nexte == null) { // old JMX
+ if (e instanceof MBeanException)
+ nexte = ((MBeanException) e).getTargetException();
+ }
+ e = nexte;
+ } while (e != null);
+ }
+ }
+ if (errorCount == 0) {
+ System.out.println("All ModelMBean tests successfuly passed");
+ System.out.println("Bye! Bye!");
+ // JTReg doesn't like System.exit(0);
+ return;
+ } else {
+ System.err.println("ERROR: " + errorCount + " tests failed");
+ System.exit(errorCount);
+ }
+
+ }
+
+ private static void test(int testno) throws Exception {
+ // com.sun.jmx.trace.TraceImplementation.init(2);
+ Resource resource = new Resource();
+ Class resourceClass = Resource.class;
+ Class rmmbClass = RequiredModelMBean.class;
+ Method setManagedResource =
+ rmmbClass.getMethod("setManagedResource",
+ new Class[] {Object.class,
+ String.class});
+ Method sendNotification =
+ rmmbClass.getMethod("sendNotification",
+ new Class[] {Notification.class});
+ Method addAttributeChangeNL =
+ rmmbClass.getMethod("addAttributeChangeNotificationListener",
+ new Class[] {NotificationListener.class,
+ String.class,
+ Object.class});
+ Method getArray = resourceClass.getMethod("getArray", new Class[0]);
+ Method getNumber = resourceClass.getMethod("getNumber", new Class[0]);
+ Method setNumber =
+ resourceClass.getMethod("setNumber", new Class[] {Integer.TYPE});
+ Method tweakArray =
+ resourceClass.getMethod("tweakArray",
+ new Class[] {Object[].class});
+ Method addOne =
+ resourceClass.getMethod("addOne", new Class[] {Integer.TYPE});
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ ObjectName on = new ObjectName("a:b=c");
+ Descriptor attrDescr = new DescriptorSupport();
+ attrDescr.setField("name", "Array");
+ attrDescr.setField("descriptorType", "attribute");
+ attrDescr.setField("getMethod", "getArray");
+ ModelMBeanAttributeInfo attrInfo =
+ new ModelMBeanAttributeInfo("Array", "array attr", getArray,
+ null, attrDescr);
+ Descriptor attrDescr2 = new DescriptorSupport();
+ attrDescr2.setField("name", "Number");
+ attrDescr2.setField("descriptorType", "attribute");
+ attrDescr2.setField("getMethod", "getNumber");
+ attrDescr2.setField("setMethod", "setNumber");
+ ModelMBeanAttributeInfo attrInfo2 =
+ new ModelMBeanAttributeInfo("Number", "number attr", getNumber,
+ setNumber, attrDescr2);
+ Descriptor attrDescr3 = new DescriptorSupport();
+ attrDescr3.setField("name", "Local");
+ attrDescr3.setField("descriptorType", "attribute");
+ attrDescr3.setField("currencyTimeLimit", "" + Integer.MAX_VALUE);
+ ModelMBeanAttributeInfo attrInfo3 =
+ new ModelMBeanAttributeInfo("Local", "java.lang.String",
+ "local attr", true, true, false,
+ attrDescr3);
+ Descriptor attrDescr4 = new DescriptorSupport();
+ attrDescr4.setField("name", "Local2");
+ attrDescr4.setField("descriptorType", "attribute");
+ ModelMBeanAttributeInfo attrInfo4 =
+ new ModelMBeanAttributeInfo("Local2", "java.lang.String",
+ "local attr 2", true, true, false,
+ attrDescr4);
+ ModelMBeanAttributeInfo[] attrs =
+ new ModelMBeanAttributeInfo[] {attrInfo, attrInfo2, attrInfo3,
+ attrInfo4};
+ ModelMBeanOperationInfo operInfo =
+ new ModelMBeanOperationInfo("getArray descr", getArray);
+ ModelMBeanOperationInfo operInfo2 =
+ new ModelMBeanOperationInfo("getNumber descr", getNumber);
+ ModelMBeanOperationInfo operInfo3 =
+ new ModelMBeanOperationInfo("addOne descr", addOne);
+ ModelMBeanOperationInfo operInfo4 =
+ new ModelMBeanOperationInfo("setNumber descr", setNumber);
+ ModelMBeanOperationInfo operInfo5 =
+ new ModelMBeanOperationInfo("tweakArray descr", tweakArray);
+ ModelMBeanOperationInfo operInfoSetManagedResource =
+ new ModelMBeanOperationInfo("setManagedResource descr",
+ setManagedResource);
+ ModelMBeanOperationInfo operInfoSendNotification =
+ new ModelMBeanOperationInfo("sendNotification descr",
+ sendNotification);
+ ModelMBeanOperationInfo operInfoAddAttributeChangeNL =
+ new ModelMBeanOperationInfo("AddAttributeChangeNL descr",
+ addAttributeChangeNL);
+ ModelMBeanOperationInfo[] opers =
+ new ModelMBeanOperationInfo[] {operInfo, operInfo2, operInfo3,
+ operInfo4, operInfo5,
+ operInfoSetManagedResource,
+ operInfoSendNotification,
+ operInfoAddAttributeChangeNL};
+ ModelMBeanInfo info =
+ new ModelMBeanInfoSupport(Resource.class.getName(),
+ "Resourcish resource",
+ attrs, null, opers, null,
+ null);
+ mbs.createMBean(RequiredModelMBean.class.getName(),
+ on,
+ new Object[] {info},
+ new String[] {ModelMBeanInfo.class.getName()});
+ mbs.invoke(on, "setManagedResource",
+ new Object[] {resource, "objectReference"},
+ new String[] {"java.lang.Object", "java.lang.String"});
+ switch (testno) {
+ case 0: {
+ /* Check getDescriptors("") on original MBeanInfo */
+ final Descriptor[] desc = info.getDescriptors("");
+ checkDescriptors(info,desc,"info.getDescriptors(\"\")");
+ break;
+ }
+ case 1: {
+ /* Check getDescriptors(null) on original MBeanInfo */
+ final Descriptor[] desc = info.getDescriptors(null);
+ checkDescriptors(info,desc,"info.getDescriptors(null)");
+ break;
+ }
+ case 2: {
+ /* Check getDescriptors("") on retrieved MBeanInfo */
+ final MBeanInfo mbi = mbs.getMBeanInfo(on);
+ final ModelMBeanInfo model = (ModelMBeanInfo)mbi;
+ final Descriptor[] desc = model.getDescriptors("");
+ checkDescriptors(info,desc,"model.getDescriptors(\"\")");
+ break;
+ }
+ case 3: {
+ /* Check getDescriptors(null) on retrieved MBeanInfo */
+ final MBeanInfo mbi = mbs.getMBeanInfo(on);
+ final ModelMBeanInfo model = (ModelMBeanInfo)mbi;
+ final Descriptor[] desc = model.getDescriptors(null);
+ checkDescriptors(info,desc,"model.getDescriptors(null)");
+ break;
+ }
+ default:
+ System.err.println("UNKNOWN TEST NUMBER " + testno);
+ break;
+ }
+ }
+
+ /* Removes descriptor from the list and returns it. Returns {@code null}
+ if descriptor is not found */
+ private static Descriptor remove(ArrayList<Descriptor> list,
+ Descriptor item) {
+ if (list.remove(item)) return item;
+ else return null;
+ }
+
+ /* Check that all descriptors have been returned */
+ private static void checkDescriptors(ModelMBeanInfo modelMBeanInfo,
+ Descriptor[] descriptors, String string) {
+ int errCount = 0;
+ final ArrayList<Descriptor> list =
+ new ArrayList<Descriptor>(descriptors.length);
+ list.addAll(Arrays.asList(descriptors));
+ System.out.println("Got " + list.size() + " descriptors for "+string);
+
+ // checks that MBean's descriptor is returned.
+ //
+ final Descriptor mbd = ((MBeanInfo)modelMBeanInfo).getDescriptor();
+ if (!mbd.equals(remove(list,mbd))) {
+ System.err.println("modelMBeanInfo.getDescriptor(): not found");
+ errCount++;
+ }
+
+ // checks that MBean's attributes descriptors are returned.
+ //
+ final MBeanAttributeInfo[] attrs = modelMBeanInfo.getAttributes();
+ for (MBeanAttributeInfo att : attrs) {
+ final Descriptor ad = att.getDescriptor();
+ final String name = att.getName();
+ if (!ad.equals(remove(list,ad))) {
+ System.err.println("attInfo.getDescriptor(): not found for "+
+ name);
+ errCount++;
+ }
+ }
+
+ // checks that MBean's operations descriptors are returned.
+ //
+ final MBeanOperationInfo[] ops = modelMBeanInfo.getOperations();
+ for (MBeanOperationInfo op : ops) {
+ final Descriptor od = op.getDescriptor();
+ final String name = op.getName();
+ if (!od.equals(remove(list,od))) {
+ System.err.println("opInfo.getDescriptor(): not found for "+
+ name);
+ errCount++;
+ }
+ }
+
+ // checks that MBean's notifications descriptors are returned.
+ //
+ final MBeanNotificationInfo[] ntfs = modelMBeanInfo.getNotifications();
+ for (MBeanNotificationInfo ntf : ntfs) {
+ final Descriptor nd = ntf.getDescriptor();
+ final String name = ntf.getName();
+ if (!nd.equals(remove(list,nd))) {
+ System.err.println("notifInfo.getDescriptor(): not found for "+
+ name);
+ errCount++;
+ }
+ }
+ if (errCount > 0) {
+ throw new RuntimeException(string+": failed with "+errCount+
+ " errors");
+ } else if (list.size() != 0) {
+ // Check that there are no additional descriptors
+ //
+ throw new RuntimeException(string+
+ ": Unexpected remaining descriptors: "+list);
+ } else System.out.println(string+": PASSED");
+ }
+
+ private static final int NTESTS = 4;
+
+}
diff --git a/test/javax/management/modelmbean/ModelMBeanInfoSupport/logging.properties b/test/javax/management/modelmbean/ModelMBeanInfoSupport/logging.properties
new file mode 100644
index 0000000..46fc30c
--- /dev/null
+++ b/test/javax/management/modelmbean/ModelMBeanInfoSupport/logging.properties
@@ -0,0 +1,15 @@
+handlers= java.util.logging.ConsoleHandler
+
+.level= INFO
+
+
+java.util.logging.FileHandler.pattern = %h/java%u.log
+java.util.logging.FileHandler.limit = 50000
+java.util.logging.FileHandler.count = 1
+java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
+
+java.util.logging.ConsoleHandler.level = FINEST
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+javax.management.misc.level = FINEST
+
diff --git a/test/javax/management/modelmbean/ModelMBeanInfoSupport/policy b/test/javax/management/modelmbean/ModelMBeanInfoSupport/policy
new file mode 100644
index 0000000..ac5336c
--- /dev/null
+++ b/test/javax/management/modelmbean/ModelMBeanInfoSupport/policy
@@ -0,0 +1,14 @@
+grant {
+ permission javax.management.MBeanServerPermission "createMBeanServer";
+ permission javax.management.MBeanPermission "javax.management.modelmbean.RequiredModelMBean#-[-]", "instantiate";
+ permission javax.management.MBeanPermission "javax.management.modelmbean.RequiredModelMBean#-[*:*]", "registerMBean";
+ permission javax.management.MBeanPermission "javax.management.modelmbean.RequiredModelMBean#*[*:*]", "getAttribute";
+ permission javax.management.MBeanPermission "javax.management.modelmbean.RequiredModelMBean#*[*:*]", "setAttribute";
+ permission javax.management.MBeanPermission "javax.management.modelmbean.RequiredModelMBean#*[*:*]", "invoke";
+ permission javax.management.MBeanPermission "GetAllDescriptorsTest$Resource#-[*:*]", "registerMBean";
+ permission javax.management.MBeanPermission "GetAllDescriptorsTest$Resource#*[*:*]", "invoke";
+ permission javax.management.MBeanPermission "GetAllDescriptorsTest$Resource#*[*:*]", "getAttribute";
+ permission javax.management.MBeanPermission "GetAllDescriptorsTest$Resource#*[*:*]", "setAttribute";
+ permission javax.management.MBeanPermission "GetAllDescriptorsTest$Resource#*[*:*]", "getMBeanInfo";
+
+};
diff --git a/test/javax/management/modelmbean/OnUnregisterTest.java b/test/javax/management/modelmbean/OnUnregisterTest.java
new file mode 100644
index 0000000..7d9af83
--- /dev/null
+++ b/test/javax/management/modelmbean/OnUnregisterTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6175387
+ * @summary Check that OnUnregister is an allowed value for persistPolicy
+ * in ModelMBeanAttributeInfo
+ * @author Eamonn McManus
+ * @run clean OnUnregisterTest
+ * @run build OnUnregisterTest
+ * @run main OnUnregisterTest
+ */
+
+// Since our RequiredModelMBean implementation doesn't support
+// persistence, it doesn't have any behaviour for OnUnregister, so we
+// can't test that. We can only test that the value is allowed.
+
+// In versions of the API prior to the addition of OnUnregister, the
+// attempt to construct a DescriptorSupport with persistPolicy=OnUnregister
+// will throw an exception.
+
+// The OnUnregister value is not case-sensitive, and we test that.
+
+import javax.management.*;
+import javax.management.modelmbean.*;
+
+public class OnUnregisterTest {
+ public static void main(String[] args) throws Exception {
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ ObjectName on = new ObjectName("a:b=c");
+
+ DescriptorSupport desc;
+ ModelMBeanAttributeInfo mmbai;
+ ModelMBeanInfo mmbi;
+ ModelMBean mmb;
+
+ desc = new DescriptorSupport("name=foo",
+ "descriptorType=attribute",
+ "persistPolicy=OnUnregister");
+ mmbai = new ModelMBeanAttributeInfo("foo", "int", "a foo",
+ true, true, false, desc);
+ mmbi = new ModelMBeanInfoSupport("a.b.c", "description",
+ new ModelMBeanAttributeInfo[] {mmbai},
+ null, null, null);
+ mmb = new RequiredModelMBean(mmbi);
+
+ mbs.registerMBean(mmb, on);
+ mbs.unregisterMBean(on);
+
+ desc = new DescriptorSupport("name=foo", "descriptorType=attribute");
+ mmbai = new ModelMBeanAttributeInfo("foo", "int", "a foo",
+ true, true, false, desc);
+ desc = new DescriptorSupport("name=bar",
+ "descriptorType=mbean",
+ "persistPolicy=onUnregister");
+ mmbi = new ModelMBeanInfoSupport("a.b.c", "description",
+ new ModelMBeanAttributeInfo[] {mmbai},
+ null, null, null, desc);
+ mmb = new RequiredModelMBean(mmbi);
+ mbs.registerMBean(mmb, on);
+ mbs.unregisterMBean(on);
+ }
+}
diff --git a/test/javax/management/modelmbean/RequiredModelMBeanGetAttributeTest.java b/test/javax/management/modelmbean/RequiredModelMBeanGetAttributeTest.java
new file mode 100644
index 0000000..c38aaf6
--- /dev/null
+++ b/test/javax/management/modelmbean/RequiredModelMBeanGetAttributeTest.java
@@ -0,0 +1,405 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5043245
+ * @summary Test the following in RequiredModelMBean.getAttribute():
+ * The declared type of the attribute is the String returned by
+ * ModelMBeanAttributeInfo.getType(). A value is compatible
+ * with this type if one of the following is true:
+ * - the value is null;
+ * - the declared name is a primitive type name (such as "int")
+ * and the value is an instance of the corresponding wrapper
+ * type (such as java.lang.Integer);
+ * - the name of the value's class is identical to the declared name;
+ * - the declared name can be loaded by the value's class loader and
+ * produces a class to which the value can be assigned.
+ * @author Luis-Miguel Alventosa
+ * @run clean RequiredModelMBeanGetAttributeTest
+ * @run build RequiredModelMBeanGetAttributeTest
+ * @run main RequiredModelMBeanGetAttributeTest
+ */
+
+import java.lang.reflect.Method;
+import java.util.Hashtable;
+import java.util.Map;
+import javax.management.Descriptor;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectName;
+import javax.management.modelmbean.DescriptorSupport;
+import javax.management.modelmbean.ModelMBean;
+import javax.management.modelmbean.ModelMBeanAttributeInfo;
+import javax.management.modelmbean.ModelMBeanInfo;
+import javax.management.modelmbean.ModelMBeanInfoSupport;
+import javax.management.modelmbean.ModelMBeanOperationInfo;
+import javax.management.modelmbean.RequiredModelMBean;
+
+public class RequiredModelMBeanGetAttributeTest {
+
+ public static void main(String[] args) throws Exception {
+
+ boolean ok = true;
+
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ // Resource methods
+
+ Method nullGetter =
+ Resource.class.getMethod("getNull", (Class[]) null);
+ Method integerGetter =
+ Resource.class.getMethod("getInteger", (Class[]) null);
+ Method hashtableGetter =
+ Resource.class.getMethod("getHashtable", (Class[]) null);
+ Method mapGetter =
+ Resource.class.getMethod("getMap", (Class[]) null);
+
+ // ModelMBeanOperationInfo
+
+ Descriptor nullOperationDescriptor =
+ new DescriptorSupport(new String[] {
+ "name=getNull",
+ "descriptorType=operation",
+ "role=getter"
+ });
+ ModelMBeanOperationInfo nullOperationInfo =
+ new ModelMBeanOperationInfo("Null attribute",
+ nullGetter,
+ nullOperationDescriptor);
+
+ Descriptor integerOperationDescriptor =
+ new DescriptorSupport(new String[] {
+ "name=getInteger",
+ "descriptorType=operation",
+ "role=getter"
+ });
+ ModelMBeanOperationInfo integerOperationInfo =
+ new ModelMBeanOperationInfo("Integer attribute",
+ integerGetter,
+ integerOperationDescriptor);
+
+ Descriptor hashtableOperationDescriptor =
+ new DescriptorSupport(new String[] {
+ "name=getHashtable",
+ "descriptorType=operation",
+ "role=getter"
+ });
+ ModelMBeanOperationInfo hashtableOperationInfo =
+ new ModelMBeanOperationInfo("Hashtable attribute",
+ hashtableGetter,
+ hashtableOperationDescriptor);
+
+ Descriptor mapOperationDescriptor =
+ new DescriptorSupport(new String[] {
+ "name=getMap",
+ "descriptorType=operation",
+ "role=getter"
+ });
+ ModelMBeanOperationInfo mapOperationInfo =
+ new ModelMBeanOperationInfo("Map attribute",
+ mapGetter,
+ mapOperationDescriptor);
+
+ // ModelMBeanAttributeInfo
+
+ Descriptor nullAttributeDescriptor =
+ new DescriptorSupport(new String[] {
+ "name=Null",
+ "descriptorType=attribute",
+ "getMethod=getNull"
+ });
+ ModelMBeanAttributeInfo nullAttributeInfo =
+ new ModelMBeanAttributeInfo("Null",
+ "java.lang.Object",
+ "Null attribute",
+ true,
+ false,
+ false,
+ nullAttributeDescriptor);
+
+ Descriptor integerAttributeDescriptor =
+ new DescriptorSupport(new String[] {
+ "name=Integer",
+ "descriptorType=attribute",
+ "getMethod=getInteger"
+ });
+ ModelMBeanAttributeInfo integerAttributeInfo =
+ new ModelMBeanAttributeInfo("Integer",
+ "int",
+ "Integer attribute",
+ true,
+ false,
+ false,
+ integerAttributeDescriptor);
+
+ Descriptor hashtableAttributeDescriptor =
+ new DescriptorSupport(new String[] {
+ "name=Hashtable",
+ "descriptorType=attribute",
+ "getMethod=getHashtable"
+ });
+ ModelMBeanAttributeInfo hashtableAttributeInfo =
+ new ModelMBeanAttributeInfo("Hashtable",
+ "java.util.Hashtable",
+ "Hashtable attribute",
+ true,
+ false,
+ false,
+ hashtableAttributeDescriptor);
+
+ Descriptor mapAttributeDescriptor =
+ new DescriptorSupport(new String[] {
+ "name=Map",
+ "descriptorType=attribute",
+ "getMethod=getMap"
+ });
+ ModelMBeanAttributeInfo mapAttributeInfo =
+ new ModelMBeanAttributeInfo("Map",
+ "java.util.Map",
+ "Map attribute",
+ true,
+ false,
+ false,
+ mapAttributeDescriptor);
+
+ Descriptor null2AttributeDescriptor =
+ new DescriptorSupport(new String[] {
+ "name=Null2",
+ "descriptorType=attribute"
+ });
+ null2AttributeDescriptor.setField("default", null);
+ ModelMBeanAttributeInfo null2AttributeInfo =
+ new ModelMBeanAttributeInfo("Null2",
+ "java.lang.Object",
+ "Null2 attribute",
+ true,
+ false,
+ false,
+ null2AttributeDescriptor);
+
+ Descriptor integer2AttributeDescriptor =
+ new DescriptorSupport(new String[] {
+ "name=Integer2",
+ "descriptorType=attribute"
+ });
+ integer2AttributeDescriptor.setField("default", 10);
+ ModelMBeanAttributeInfo integer2AttributeInfo =
+ new ModelMBeanAttributeInfo("Integer2",
+ "int",
+ "Integer2 attribute",
+ true,
+ false,
+ false,
+ integer2AttributeDescriptor);
+
+ Descriptor hashtable2AttributeDescriptor =
+ new DescriptorSupport(new String[] {
+ "name=Hashtable2",
+ "descriptorType=attribute"
+ });
+ hashtable2AttributeDescriptor.setField("default", new Hashtable());
+ ModelMBeanAttributeInfo hashtable2AttributeInfo =
+ new ModelMBeanAttributeInfo("Hashtable2",
+ "java.util.Hashtable",
+ "Hashtable2 attribute",
+ true,
+ false,
+ false,
+ hashtable2AttributeDescriptor);
+
+ Descriptor map2AttributeDescriptor =
+ new DescriptorSupport(new String[] {
+ "name=Map2",
+ "descriptorType=attribute"
+ });
+ map2AttributeDescriptor.setField("default", new Hashtable());
+ ModelMBeanAttributeInfo map2AttributeInfo =
+ new ModelMBeanAttributeInfo("Map2",
+ "java.util.Map",
+ "Map2 attribute",
+ true,
+ false,
+ false,
+ map2AttributeDescriptor);
+
+ // ModelMBeanInfo
+
+ ModelMBeanInfo mmbi = new ModelMBeanInfoSupport(
+ Resource.class.getName(),
+ "Resource MBean",
+ new ModelMBeanAttributeInfo[] { nullAttributeInfo,
+ integerAttributeInfo,
+ hashtableAttributeInfo,
+ mapAttributeInfo,
+ null2AttributeInfo,
+ integer2AttributeInfo,
+ hashtable2AttributeInfo,
+ map2AttributeInfo },
+ null,
+ new ModelMBeanOperationInfo[] { nullOperationInfo,
+ integerOperationInfo,
+ hashtableOperationInfo,
+ mapOperationInfo },
+ null);
+
+ // RequiredModelMBean
+
+ ModelMBean mmb = new RequiredModelMBean(mmbi);
+ mmb.setManagedResource(resource, "ObjectReference");
+ ObjectName mmbName = new ObjectName(":type=ResourceMBean");
+ mbs.registerMBean(mmb, mmbName);
+
+ // Run tests
+
+ System.out.println("\nTesting that we can call getNull()... ");
+ try {
+ Object o = mbs.getAttribute(mmbName, "Null");
+ System.out.println("getNull() = " + o);
+ System.out.println("Attribute's declared type = java.lang.Object");
+ System.out.println("Returned value's type = null");
+ } catch (Exception e) {
+ System.out.println("TEST FAILED: Caught exception:");
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+
+ System.out.println("\nTesting that we can call getInteger()... ");
+ try {
+ Integer i = (Integer) mbs.getAttribute(mmbName, "Integer");
+ System.out.println("getInteger() = " + i);
+ System.out.println("Attribute's declared type = int");
+ System.out.println("Returned value's type = " +
+ i.getClass().getName());
+ } catch (Exception e) {
+ System.out.println("TEST FAILED: Caught exception:");
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+
+ System.out.println("\nTesting that we can call getHashtable()... ");
+ try {
+ Hashtable h = (Hashtable) mbs.getAttribute(mmbName, "Hashtable");
+ System.out.println("getHashtable() = " + h);
+ System.out.println("Attribute's declared type = " +
+ "java.util.Hashtable");
+ System.out.println("Returned value's type = " +
+ h.getClass().getName());
+ } catch (Exception e) {
+ System.out.println("TEST FAILED: Caught exception:");
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+
+ System.out.println("\nTesting that we can call getMap()... ");
+ try {
+ Map m = (Map) mbs.getAttribute(mmbName, "Map");
+ System.out.println("getMap() = " + m);
+ System.out.println("Attribute's declared type = " +
+ "java.util.Map");
+ System.out.println("Returned value's type = " +
+ m.getClass().getName());
+ } catch (Exception e) {
+ System.out.println("TEST FAILED: Caught exception:");
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+
+ System.out.println("\nTesting that we can call getNull2()... ");
+ try {
+ Object o = mbs.getAttribute(mmbName, "Null2");
+ System.out.println("getNull2() = " + o);
+ System.out.println("Attribute's declared type = java.lang.Object");
+ System.out.println("Returned value's type = null");
+ } catch (Exception e) {
+ System.out.println("TEST FAILED: Caught exception:");
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+
+ System.out.println("\nTesting that we can call getInteger2()... ");
+ try {
+ Integer i = (Integer) mbs.getAttribute(mmbName, "Integer2");
+ System.out.println("getInteger2() = " + i);
+ System.out.println("Attribute's declared type = int");
+ System.out.println("Returned value's type = " +
+ i.getClass().getName());
+ } catch (Exception e) {
+ System.out.println("TEST FAILED: Caught exception:");
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+
+ System.out.println("\nTesting that we can call getHashtable2()... ");
+ try {
+ Hashtable h = (Hashtable) mbs.getAttribute(mmbName, "Hashtable2");
+ System.out.println("getHashtable2() = " + h);
+ System.out.println("Attribute's declared type = " +
+ "java.util.Hashtable");
+ System.out.println("Returned value's type = " +
+ h.getClass().getName());
+ } catch (Exception e) {
+ System.out.println("TEST FAILED: Caught exception:");
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+
+ System.out.println("\nTesting that we can call getMap2()... ");
+ try {
+ Map m = (Map) mbs.getAttribute(mmbName, "Map2");
+ System.out.println("getMap2() = " + m);
+ System.out.println("Attribute's declared type = " +
+ "java.util.Map");
+ System.out.println("Returned value's type = " +
+ m.getClass().getName());
+ } catch (Exception e) {
+ System.out.println("TEST FAILED: Caught exception:");
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+
+ if (ok)
+ System.out.println("\nTest passed.\n");
+ else {
+ System.out.println("\nTest failed.\n");
+ System.exit(1);
+ }
+ }
+
+ public static class Resource {
+ public Object getNull() {
+ return null;
+ }
+ public int getInteger() {
+ return 10;
+ }
+ public Hashtable getHashtable() {
+ return new Hashtable();
+ }
+ public Map getMap() {
+ return new Hashtable();
+ }
+ }
+
+ private static Resource resource = new Resource();
+}
diff --git a/test/javax/management/modelmbean/RequiredModelMBeanMethodTest.java b/test/javax/management/modelmbean/RequiredModelMBeanMethodTest.java
new file mode 100644
index 0000000..f5e4e5b
--- /dev/null
+++ b/test/javax/management/modelmbean/RequiredModelMBeanMethodTest.java
@@ -0,0 +1,340 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4950756
+ * @summary Test that RequiredModelMBean.invoke will not invoke methods
+ * from the RequiredModelMBean class itself if they are not in the
+ * ModelMBeanInfo
+ * @author Eamonn McManus
+ * @run clean RequiredModelMBeanMethodTest
+ * @run build RequiredModelMBeanMethodTest
+ * @run main RequiredModelMBeanMethodTest
+ */
+
+import java.lang.reflect.*;
+import javax.management.*;
+import javax.management.modelmbean.*;
+
+/*
+ * We do the same test with a number of different operations:
+ *
+ * - A plain operation that is directed to the managed resource in the
+ * usual way. We give it some parameters so we can test that the
+ * class loading logic for signature parameters is reasonable.
+ *
+ * - An operation (removeNotificationListener) that is directed to the
+ * RequiredModelMBean itself. We use this particular operation because
+ * it will throw an exception, which allows us to check that it did in
+ * fact execute.
+ *
+ * - An operation (load()) that has the same signature as a
+ * RequiredModelMBean operation but is directed to the resource
+ * because of a "class" field in the descriptor.
+ *
+ * - An operation (store()) that has the same signature as a
+ * RequiredModelMBean operation but is directed to the resource
+ * because of a "targetObject" field in the descriptor.
+ *
+ * In each case we check that the operation does not work if it is not
+ * in the ModelMBeanInfo, and does work if it is.
+ */
+public class RequiredModelMBeanMethodTest {
+ public static void main(String[] args) throws Exception {
+ boolean ok = true;
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ Descriptor tralalaDescriptor =
+ new DescriptorSupport(new String[] {
+ "name=tralala",
+ "descriptorType=operation",
+ "role=operation",
+ "targetType=ObjectReference",
+ });
+ Method tralalaMethod =
+ Resource.class.getMethod("tralala",
+ new Class[] {int.class, Resource.class});
+ ModelMBeanOperationInfo tralalaInfo =
+ new ModelMBeanOperationInfo("tralala descr", tralalaMethod,
+ tralalaDescriptor);
+
+ Method remACNLMethod =
+ RequiredModelMBean.class.getMethod("removeAttributeChangeNotificationListener",
+ new Class[] {
+ NotificationListener.class,
+ String.class
+ });
+ ModelMBeanOperationInfo remACNLInfo =
+ new ModelMBeanOperationInfo("remACNL descr", remACNLMethod);
+
+ Descriptor loadDescriptor =
+ new DescriptorSupport(new String[] {
+ "name=load",
+ "descriptorType=operation",
+ "role=operation",
+ "targetType=ObjectReference",
+ "class=" + Resource.class.getName(),
+ });
+ ModelMBeanOperationInfo loadInfo =
+ new ModelMBeanOperationInfo("load", "load descr",
+ new MBeanParameterInfo[0],
+ "void", ModelMBeanOperationInfo.ACTION,
+ loadDescriptor);
+
+ Descriptor storeDescriptor =
+ new DescriptorSupport(new String[] {
+ "name=store",
+ "descriptorType=operation",
+ "role=operation",
+ "targetType=ObjectReference",
+ });
+ storeDescriptor.setField("targetObject", resource);
+ ModelMBeanOperationInfo storeInfo =
+ new ModelMBeanOperationInfo("store", "store descr",
+ new MBeanParameterInfo[0],
+ "void", ModelMBeanOperationInfo.ACTION,
+ storeDescriptor);
+
+ ModelMBeanInfo emptyMMBI =
+ new ModelMBeanInfoSupport(Resource.class.getName(),
+ "empty descr",
+ null, null, null, null);
+ ModelMBean emptyMMB = new RequiredModelMBean(emptyMMBI);
+ emptyMMB.setManagedResource(resource, "ObjectReference");
+ ObjectName emptyMMBName = new ObjectName("test:type=Empty");
+ mbs.registerMBean(emptyMMB, emptyMMBName);
+
+ System.out.println("Testing that we cannot call methods not in the " +
+ "ModelMBeanInfo");
+ try {
+ boolean thisok = test(mbs, emptyMMBName, false);
+ if (thisok)
+ System.out.println("...OK");
+ else
+ ok = false;
+ } catch (Exception e) {
+ System.out.println("TEST FAILED: Caught exception:");
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+
+ ModelMBeanOperationInfo[] opInfos = {
+ tralalaInfo, remACNLInfo, loadInfo, storeInfo,
+ };
+ ModelMBeanInfo fullMMBI =
+ new ModelMBeanInfoSupport(Resource.class.getName(),
+ "full descr",
+ null, null, opInfos, null);
+ ModelMBean fullMMB = new RequiredModelMBean(fullMMBI);
+ fullMMB.setManagedResource(resource, "ObjectReference");
+ ObjectName fullMMBName = new ObjectName("test:type=Full");
+ mbs.registerMBean(fullMMB, fullMMBName);
+
+
+ System.out.println();
+ System.out.println("Testing that we can call methods in the " +
+ "ModelMBeanInfo");
+ System.out.println(" and that \"class\" or \"targetObject\" in " +
+ "descriptor directs methods to resource");
+ try {
+ boolean thisok = test(mbs, fullMMBName, true);
+ if (thisok)
+ System.out.println("...OK");
+ else
+ ok = false;
+ } catch (Exception e) {
+ System.out.println("TEST FAILED: Caught exception:");
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+
+ if (ok) {
+ if (!resource.loadCalled || !resource.storeCalled) {
+ System.out.println("TEST FAILED: not called:" +
+ (resource.loadCalled ? "" : " load") +
+ (resource.storeCalled ? "" : " store"));
+ ok = false;
+ }
+ }
+
+ // Test the invoke("class.method") form
+ if (ok) {
+ System.out.println("Testing invoke(\"class.method\")");
+ resource.loadCalled = false;
+ mbs.invoke(fullMMBName, Resource.class.getName() + ".load",
+ null, null);
+ if (!resource.loadCalled) {
+ System.out.println("TEST FAILED: load not called");
+ ok = false;
+ }
+ try {
+ mbs.invoke(fullMMBName,
+ RequiredModelMBean.class.getName() +
+ ".removeAttributeChangeNotificationListener",
+ new Object[] {boringListener, null},
+ new String[] {
+ NotificationListener.class.getName(),
+ String.class.getName(),
+ });
+ System.out.println("TEST FAILED: removeNotificationListener" +
+ " returned successfully but " +
+ "should not have");
+ ok = false;
+ } catch (MBeanException e) {
+ final Exception target = e.getTargetException();
+ if (target instanceof ListenerNotFoundException) {
+ // OK: there is no such listener
+ } else
+ throw e;
+ }
+ }
+
+ if (ok)
+ System.out.println("Test passed");
+ else {
+ System.out.println("TEST FAILED");
+ System.exit(1);
+ }
+ }
+
+ private static boolean test(MBeanServer mbs, ObjectName name,
+ boolean shouldWork)
+ throws Exception {
+
+ boolean ok = true;
+
+ final String[] names = {
+ "tralala",
+ "removeAttributeChangeNotificationListener",
+ "load",
+ "store",
+ };
+
+ for (int i = 0; i < 4; i++) {
+ boolean thisok = true;
+ try {
+ switch (i) {
+ case 0:
+ String tralala = (String)
+ mbs.invoke(name, names[i],
+ new Object[] {new Integer(5), resource},
+ new String[] {"int",
+ Resource.class.getName()});
+ if (!"tralala".equals(tralala)) {
+ System.out.println("TEST FAILED: tralala returned: " +
+ tralala);
+ thisok = false;
+ }
+ break;
+ case 1:
+ try {
+ mbs.invoke(name,
+ names[i],
+ new Object[] {boringListener, null},
+ new String[] {
+ NotificationListener.class.getName(),
+ String.class.getName(),
+ });
+ System.out.println("TEST FAILED: " + names[i] +
+ " returned successfully but " +
+ "should not have");
+ thisok = false;
+ } catch (MBeanException e) {
+ final Exception target = e.getTargetException();
+ if (target instanceof ListenerNotFoundException) {
+ // OK: there is no such listener
+ } else
+ throw e;
+ }
+ break;
+ case 2:
+ case 3:
+ mbs.invoke(name,
+ names[i],
+ new Object[0],
+ new String[0]);
+ break;
+ default:
+ throw new AssertionError();
+ }
+
+ thisok = shouldWork;
+ if (!shouldWork) {
+ System.out.println("TEST FAILED: " + names[i] +
+ " worked but should not");
+ }
+ } catch (MBeanException e) {
+ if (shouldWork) {
+ System.out.println("TEST FAILED: " + names[i] + ": " + e);
+ e.printStackTrace(System.out);
+ thisok = false;
+ } else {
+ Exception target = e.getTargetException();
+ if (!(target instanceof ServiceNotFoundException)) {
+ System.out.println("TEST FAILED: " + names[i] +
+ ": wrong exception: " + target);
+ thisok = false;
+ }
+ }
+ } catch (Exception e) {
+ System.out.println("TEST FAILED: " + names[i] + ": " + e);
+ e.printStackTrace(System.out);
+ thisok = false;
+ }
+
+ if (thisok)
+ System.out.println("OK: " + names[i]);
+ else
+ ok = false;
+ }
+
+ return ok;
+ }
+
+ public static class Resource {
+ public String tralala(int x, Resource y) {
+ if (x != 5 || y != this)
+ return "wrong params: " + x + " " + y;
+ return "tralala";
+ }
+
+ public void load() {
+ loadCalled = true;
+ }
+
+ public void store() {
+ storeCalled = true;
+ }
+
+ boolean loadCalled, storeCalled;
+ }
+
+ private static Resource resource = new Resource();
+
+ private static NotificationListener boringListener =
+ new NotificationListener() {
+ public void handleNotification(Notification n, Object h) {
+ }
+ };
+}
diff --git a/test/javax/management/modelmbean/RequiredModelMBeanSetAttributeTest.java b/test/javax/management/modelmbean/RequiredModelMBeanSetAttributeTest.java
new file mode 100644
index 0000000..d8ab4be
--- /dev/null
+++ b/test/javax/management/modelmbean/RequiredModelMBeanSetAttributeTest.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4997033
+ * @summary Test the following in RequiredModelMBean.setAttribute():
+ * MBeanException wrapping a ServiceNotFoundException is thrown is setAttribute
+ * called but no setMethod field has been provided.
+ * @author Jean-Francois Denise
+ * @run clean RequiredModelMBeanSetAttributeTest
+ * @run build RequiredModelMBeanSetAttributeTest
+ * @run main RequiredModelMBeanSetAttributeTest
+ */
+
+import javax.management.Descriptor;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectName;
+import javax.management.Attribute;
+import javax.management.MBeanException;
+import javax.management.ServiceNotFoundException;
+import javax.management.modelmbean.DescriptorSupport;
+import javax.management.modelmbean.ModelMBean;
+import javax.management.modelmbean.ModelMBeanAttributeInfo;
+import javax.management.modelmbean.ModelMBeanInfo;
+import javax.management.modelmbean.ModelMBeanInfoSupport;
+import javax.management.modelmbean.ModelMBeanOperationInfo;
+import javax.management.modelmbean.RequiredModelMBean;
+
+public class RequiredModelMBeanSetAttributeTest {
+
+ public static void main(String[] args) throws Exception {
+
+ boolean ok = true;
+
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ // ModelMBeanAttributeInfo
+
+ Descriptor somethingAttributeDescriptor =
+ new DescriptorSupport(new String[] {
+ "name=Something",
+ "descriptorType=attribute",
+ "getMethod=getSomething"
+ });
+ ModelMBeanAttributeInfo somethingAttributeInfo =
+ new ModelMBeanAttributeInfo("Something",
+ "java.lang.String",
+ "Something attribute",
+ true,
+ true,
+ false,
+ somethingAttributeDescriptor);
+
+ Descriptor somethingCachedAttributeDescriptor =
+ new DescriptorSupport(new String[] {
+ "name=SomethingCached",
+ "descriptorType=attribute",
+ "getMethod=getSomethingCached",
+ "currencyTimeLimit=5000"
+ });
+ ModelMBeanAttributeInfo somethingCachedAttributeInfo =
+ new ModelMBeanAttributeInfo("SomethingCached",
+ "java.lang.String",
+ "Something cached attribute",
+ true,
+ true,
+ false,
+ somethingCachedAttributeDescriptor);
+ // ModelMBeanInfo
+
+ ModelMBeanInfo mmbi = new ModelMBeanInfoSupport(
+ Resource.class.getName(),
+ "Resource MBean",
+ new ModelMBeanAttributeInfo[] { somethingAttributeInfo, somethingCachedAttributeInfo },
+ null,
+ new ModelMBeanOperationInfo[] {},
+ null);
+
+ // RequiredModelMBean
+
+ ModelMBean mmb = new RequiredModelMBean(mmbi);
+ mmb.setManagedResource(resource, "ObjectReference");
+ ObjectName mmbName = new ObjectName(":type=ResourceMBean");
+ mbs.registerMBean(mmb, mmbName);
+
+ // Run tests
+
+ System.out.println("\nTest that we receive ServiceNotFoundException");
+ try {
+ Attribute attr = new Attribute("Something", "Some string");
+ mbs.setAttribute(mmbName, attr);
+ System.out.println("TEST FAILED: Didn't caught exception");
+ ok = false;
+ } catch(MBeanException mbex) {
+ Exception e = mbex.getTargetException();
+ if(e == null || !(e instanceof ServiceNotFoundException)) {
+ System.out.println("TEST FAILED: Caught wrong exception:" + e);
+ ok = false;
+ } else
+ System.out.println("Received expected ServiceNotFoundException");
+
+ } catch (Exception e) {
+ System.out.println("TEST FAILED: Caught wrong exception: " + e);
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+
+ //Now check that when caching is enabled, setAttribute is working
+ System.out.println("\nTest that we are not receiving ServiceNotFoundException");
+ try {
+ Attribute attr = new Attribute("SomethingCached", "Some string");
+ mbs.setAttribute(mmbName, attr);
+ System.out.println("No exception thrown");
+ } catch (Exception e) {
+ System.out.println("TEST FAILED: Caught an exception: " + e);
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+
+ if (ok)
+ System.out.println("Test passed");
+ else {
+ System.out.println("TEST FAILED");
+ throw new Exception("TEST FAILED");
+ }
+ }
+
+ public static class Resource {
+ public String getSomething() {
+ return "Something value";
+ }
+ public String getSomethingCached() {
+ return "Something cached value";
+ }
+ }
+
+ private static Resource resource = new Resource();
+}
diff --git a/test/javax/management/modelmbean/SimpleModelMBean/SimpleModelMBeanCommand.java b/test/javax/management/modelmbean/SimpleModelMBean/SimpleModelMBeanCommand.java
new file mode 100644
index 0000000..fec301e
--- /dev/null
+++ b/test/javax/management/modelmbean/SimpleModelMBean/SimpleModelMBeanCommand.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4874819
+ * @summary Test that MBeanInfo classes no longer throw an
+ * IllegalArgumentException when attribute names, operation names, and
+ * Java type names do not strictly follow the expected Java syntax.
+ * @author Eamonn McManus, Daniel Fuchs
+ * @run clean SimpleModelMBeanCommand
+ * @run build SimpleModelMBeanCommand
+ * @run main/othervm/policy=policy SimpleModelMBeanCommand
+ */
+
+import java.lang.reflect.*;
+import java.util.*;
+import javax.management.*;
+import javax.management.modelmbean.*;
+
+public class SimpleModelMBeanCommand {
+
+ public static class Resource {
+ public int getNumber() {
+ return number;
+ }
+
+ public void setNumber(int n) {
+ number = n;
+ }
+
+ public int addOne(int x) {
+ return x + 1;
+ }
+
+ public Object[] getArray() {
+ return (Object[]) array.clone();
+ }
+
+ // doesn't look like an attribute so not seen by caching logic
+ public void tweakArray(Object[] array) {
+ this.array = (Object[]) array.clone();
+ }
+
+ private int number = 1234;
+ private Object[] array = {"hello", "world"};
+ }
+
+ public static void main(String[] args) {
+ int errorCount = 0;
+ for (int i = 0; i < NTESTS; i++) {
+ try {
+ System.out.println("Test " + i + ":");
+ test(i);
+ } catch (Throwable e) {
+ errorCount++;
+ boolean first = true;
+ do {
+ System.err.println(first ? "Exception:" : "Caused by:");
+ first = false;
+ e.printStackTrace();
+ Throwable nexte;
+ nexte = e.getCause();
+ if (nexte == null) { // old JMX
+ if (e instanceof MBeanException)
+ nexte = ((MBeanException) e).getTargetException();
+ }
+ e = nexte;
+ } while (e != null);
+ }
+ }
+ if (errorCount == 0) {
+ System.out.println("All ModelMBean tests successfuly passed");
+ System.out.println("Bye! Bye!");
+ // JTReg doesn't like System.exit(0);
+ return;
+ } else {
+ System.err.println("ERROR: " + errorCount + " tests failed");
+ System.exit(errorCount);
+ }
+
+ }
+
+ private static void test(int testno) throws Exception {
+ // com.sun.jmx.trace.TraceImplementation.init(2);
+ Resource resource = new Resource();
+ Class resourceClass = Resource.class;
+ Class rmmbClass = RequiredModelMBean.class;
+ Method setManagedResource =
+ rmmbClass.getMethod("setManagedResource",
+ new Class[] {Object.class,
+ String.class});
+ Method sendNotification =
+ rmmbClass.getMethod("sendNotification",
+ new Class[] {Notification.class});
+ Method addAttributeChangeNL =
+ rmmbClass.getMethod("addAttributeChangeNotificationListener",
+ new Class[] {NotificationListener.class,
+ String.class,
+ Object.class});
+ Method getArray = resourceClass.getMethod("getArray", new Class[0]);
+ Method getNumber = resourceClass.getMethod("getNumber", new Class[0]);
+ Method setNumber =
+ resourceClass.getMethod("setNumber", new Class[] {Integer.TYPE});
+ Method tweakArray =
+ resourceClass.getMethod("tweakArray",
+ new Class[] {Object[].class});
+ Method addOne =
+ resourceClass.getMethod("addOne", new Class[] {Integer.TYPE});
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ ObjectName on = new ObjectName("a:b=c");
+ Descriptor attrDescr = new DescriptorSupport();
+ attrDescr.setField("name", "Array");
+ attrDescr.setField("descriptorType", "attribute");
+ attrDescr.setField("getMethod", "getArray");
+ ModelMBeanAttributeInfo attrInfo =
+ new ModelMBeanAttributeInfo("Array", "array attr", getArray,
+ null, attrDescr);
+ Descriptor attrDescr2 = new DescriptorSupport();
+ attrDescr2.setField("name", "Number");
+ attrDescr2.setField("descriptorType", "attribute");
+ attrDescr2.setField("getMethod", "getNumber");
+ attrDescr2.setField("setMethod", "setNumber");
+ ModelMBeanAttributeInfo attrInfo2 =
+ new ModelMBeanAttributeInfo("Number", "number attr", getNumber,
+ setNumber, attrDescr2);
+ Descriptor attrDescr3 = new DescriptorSupport();
+ attrDescr3.setField("name", "Local");
+ attrDescr3.setField("descriptorType", "attribute");
+ attrDescr3.setField("currencyTimeLimit", "" + Integer.MAX_VALUE);
+ ModelMBeanAttributeInfo attrInfo3 =
+ new ModelMBeanAttributeInfo("Local", "java.lang.String",
+ "local attr", true, true, false,
+ attrDescr3);
+ Descriptor attrDescr4 = new DescriptorSupport();
+ attrDescr4.setField("name", "Local2");
+ attrDescr4.setField("descriptorType", "attribute");
+ ModelMBeanAttributeInfo attrInfo4 =
+ new ModelMBeanAttributeInfo("Local2", "java.lang.String",
+ "local attr 2", true, true, false,
+ attrDescr4);
+ ModelMBeanAttributeInfo[] attrs =
+ new ModelMBeanAttributeInfo[] {attrInfo, attrInfo2, attrInfo3,
+ attrInfo4};
+ ModelMBeanOperationInfo operInfo =
+ new ModelMBeanOperationInfo("getArray descr", getArray);
+ ModelMBeanOperationInfo operInfo2 =
+ new ModelMBeanOperationInfo("getNumber descr", getNumber);
+ ModelMBeanOperationInfo operInfo3 =
+ new ModelMBeanOperationInfo("addOne descr", addOne);
+ ModelMBeanOperationInfo operInfo4 =
+ new ModelMBeanOperationInfo("setNumber descr", setNumber);
+ ModelMBeanOperationInfo operInfo5 =
+ new ModelMBeanOperationInfo("tweakArray descr", tweakArray);
+ ModelMBeanOperationInfo operInfoSetManagedResource =
+ new ModelMBeanOperationInfo("setManagedResource descr",
+ setManagedResource);
+ ModelMBeanOperationInfo operInfoSendNotification =
+ new ModelMBeanOperationInfo("sendNotification descr",
+ sendNotification);
+ ModelMBeanOperationInfo operInfoAddAttributeChangeNL =
+ new ModelMBeanOperationInfo("AddAttributeChangeNL descr",
+ addAttributeChangeNL);
+ ModelMBeanOperationInfo[] opers =
+ new ModelMBeanOperationInfo[] {operInfo, operInfo2, operInfo3,
+ operInfo4, operInfo5,
+ operInfoSetManagedResource,
+ operInfoSendNotification,
+ operInfoAddAttributeChangeNL};
+ ModelMBeanInfo info =
+ new ModelMBeanInfoSupport(Resource.class.getName(),
+ "Resourcish resource",
+ attrs, null, opers, null,
+ null);
+ mbs.createMBean(RequiredModelMBean.class.getName(),
+ on,
+ new Object[] {info},
+ new String[] {ModelMBeanInfo.class.getName()});
+ mbs.invoke(on, "setManagedResource",
+ new Object[] {resource, "objectReference"},
+ new String[] {"java.lang.Object", "java.lang.String"});
+ switch (testno) {
+ case 0:
+ /* Check that we can get an attribute of type Object[] */
+ Object[] objs = (Object[]) mbs.getAttribute(on, "Array");
+ for (int i = 0; i < objs.length; i++)
+ System.out.println(objs[i]);
+ break;
+ case 1:
+ /* Check that we can get an attribute of type int */
+ Integer n = (Integer) mbs.getAttribute(on, "Number");
+ System.out.println(n);
+ break;
+ case 2:
+ /* Check that we can call an operation that returns int */
+ Integer n1 =
+ (Integer) mbs.invoke(on, "addOne",
+ new Integer[] {new Integer(1233)},
+ new String[] {"int"});
+ System.out.println(n1);
+ break;
+ case 3:
+ /* Check that we don't get an exception if you sendNotification
+ without any listeners. */
+ Notification notif = new Notification("type", "source", 123L);
+ mbs.invoke(on, "sendNotification", new Object[] {notif},
+ new String[] {"javax.management.Notification"});
+ System.out.println("Successfully sent notification");
+ break;
+ case 4:
+ /* Check that we can call addAttributeChangeNotificationListener
+ with null attribute. */
+ NotificationListener listener = new NotificationListener() {
+ public void handleNotification(Notification notif,
+ Object handback) {
+ System.out.println("Got notif: " + notif +
+ " with handback: " + handback);
+ }
+ };
+ mbs.invoke(on, "addAttributeChangeNotificationListener",
+ new Object[] {listener, null, "the-handback"},
+ new String[] {
+ "javax.management.NotificationListener",
+ "java.lang.String",
+ "java.lang.Object",
+ });
+ mbs.setAttribute(on, new Attribute("Number", new Integer(4321)));
+ System.out.println("Attribute value now: " +
+ mbs.getAttribute(on, "Number"));
+ break;
+ case 5:
+ /* Check that the default caching behaviour is not to cache. */
+ Object[] firstGot = (Object[]) mbs.getAttribute(on, "Array");
+ System.out.println("First got: " + Arrays.asList(firstGot));
+ ModelMBeanInfo mmbi = (ModelMBeanInfo) mbs.getMBeanInfo(on);
+ System.out.println(mmbi.getDescriptor("Array", "attribute"));
+ mbs.invoke(on, "tweakArray", new Object[] {new Object[] {"x"}},
+ new String[] {Object[].class.getName()});
+ Object[] secondGot = (Object[]) mbs.getAttribute(on, "Array");
+ System.out.println("Second got: " + Arrays.asList(secondGot));
+ if (secondGot.length != 1)
+ throw new Exception("Got value: " + Arrays.asList(secondGot));
+ break;
+ case 6:
+ /* Check that attributes without getters or setters work.
+ The value is stored in the descriptor. This test includes
+ an explicit currencyTimeLimit attribute. */
+ mbs.setAttribute(on, new Attribute("Local", "string value"));
+ ModelMBeanInfo mmbi2 = (ModelMBeanInfo) mbs.getMBeanInfo(on);
+ System.out.println(mmbi2.getDescriptor("Local", "attribute"));
+ Object gotback = mbs.getAttribute(on, "Local");
+ if (!"string value".equals(gotback))
+ throw new Exception("Got value: " + gotback);
+ break;
+ case 7:
+ /* Check that attributes without getters or setters work.
+ The value is stored in the descriptor. This test does
+ not have an explicit currencyTimeLimit attribute. */
+ mbs.setAttribute(on, new Attribute("Local2", "thing value"));
+ ModelMBeanInfo mmbi3 = (ModelMBeanInfo) mbs.getMBeanInfo(on);
+ System.out.println(mmbi3.getDescriptor("Local2", "attribute"));
+ Object gotback2 = mbs.getAttribute(on, "Local2");
+ if (!"thing value".equals(gotback2))
+ throw new Exception("Got value: " + gotback2);
+ break;
+ default:
+ System.err.println("UNKNOWN TEST NUMBER " + testno);
+ break;
+ }
+ }
+
+ private static final int NTESTS = 8;
+
+}
diff --git a/test/javax/management/modelmbean/SimpleModelMBean/logging.properties b/test/javax/management/modelmbean/SimpleModelMBean/logging.properties
new file mode 100644
index 0000000..2f22174
--- /dev/null
+++ b/test/javax/management/modelmbean/SimpleModelMBean/logging.properties
@@ -0,0 +1,14 @@
+handlers= java.util.logging.ConsoleHandler
+
+.level= INFO
+
+
+java.util.logging.FileHandler.pattern = %h/java%u.log
+java.util.logging.FileHandler.limit = 50000
+java.util.logging.FileHandler.count = 1
+java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
+
+java.util.logging.ConsoleHandler.level = FINEST
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+javax.management.misc.level = FINEST
\ No newline at end of file
diff --git a/test/javax/management/modelmbean/SimpleModelMBean/policy b/test/javax/management/modelmbean/SimpleModelMBean/policy
new file mode 100644
index 0000000..221dc5e
--- /dev/null
+++ b/test/javax/management/modelmbean/SimpleModelMBean/policy
@@ -0,0 +1,14 @@
+grant {
+ permission javax.management.MBeanServerPermission "createMBeanServer";
+ permission javax.management.MBeanPermission "javax.management.modelmbean.RequiredModelMBean#-[-]", "instantiate";
+ permission javax.management.MBeanPermission "javax.management.modelmbean.RequiredModelMBean#-[*:*]", "registerMBean";
+ permission javax.management.MBeanPermission "javax.management.modelmbean.RequiredModelMBean#*[*:*]", "getAttribute";
+ permission javax.management.MBeanPermission "javax.management.modelmbean.RequiredModelMBean#*[*:*]", "setAttribute";
+ permission javax.management.MBeanPermission "javax.management.modelmbean.RequiredModelMBean#*[*:*]", "invoke";
+ permission javax.management.MBeanPermission "SimpleModelMBeanCommand$Resource#-[*:*]", "registerMBean";
+ permission javax.management.MBeanPermission "SimpleModelMBeanCommand$Resource#*[*:*]", "invoke";
+ permission javax.management.MBeanPermission "SimpleModelMBeanCommand$Resource#*[*:*]", "getAttribute";
+ permission javax.management.MBeanPermission "SimpleModelMBeanCommand$Resource#*[*:*]", "setAttribute";
+ permission javax.management.MBeanPermission "SimpleModelMBeanCommand$Resource#*[*:*]", "getMBeanInfo";
+
+};
diff --git a/test/javax/management/modelmbean/UnserializableTargetObjectTest.java b/test/javax/management/modelmbean/UnserializableTargetObjectTest.java
new file mode 100644
index 0000000..43b3096
--- /dev/null
+++ b/test/javax/management/modelmbean/UnserializableTargetObjectTest.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6332962
+ * @summary Test that a RequiredModelMBean operation can have a targetObject
+ * that is not serializable
+ * @author Eamonn McManus
+ * @run clean UnserializableTargetObjectTest
+ * @run build UnserializableTargetObjectTest
+ * @run main UnserializableTargetObjectTest
+ */
+
+/* This test and DescriptorSupportSerialTest basically cover the same thing.
+ I wrote them at different times and forgot that I had written the earlier
+ one. However the coverage is slightly different so I'm keeping both. */
+
+import java.lang.reflect.Method;
+import javax.management.Attribute;
+import javax.management.Descriptor;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectName;
+import javax.management.modelmbean.DescriptorSupport;
+import javax.management.modelmbean.ModelMBean;
+import javax.management.modelmbean.ModelMBeanAttributeInfo;
+import javax.management.modelmbean.ModelMBeanInfo;
+import javax.management.modelmbean.ModelMBeanInfoSupport;
+import javax.management.modelmbean.ModelMBeanOperationInfo;
+import javax.management.modelmbean.RequiredModelMBean;
+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 UnserializableTargetObjectTest {
+ public static class Resource { // not serializable!
+ int count;
+ int operationCount;
+
+ public void operation() {
+ operationCount++;
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ public void setCount(int count) {
+ this.count = count;
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ ObjectName name = new ObjectName("a:b=c");
+ Resource resource1 = new Resource();
+ Resource resource2 = new Resource();
+ Resource resource3 = new Resource();
+ Method operationMethod = Resource.class.getMethod("operation");
+ Method getCountMethod = Resource.class.getMethod("getCount");
+ Method setCountMethod = Resource.class.getMethod("setCount", int.class);
+ Descriptor operationDescriptor =
+ new DescriptorSupport(new String[] {
+ "descriptorType", "name", "targetObject"
+ }, new Object[] {
+ "operation", "operation", resource1
+ });
+ Descriptor getCountDescriptor =
+ new DescriptorSupport(new String[] {
+ "descriptorType", "name", "targetObject"
+ }, new Object[] {
+ "operation", "getCount", resource2
+ });
+ Descriptor setCountDescriptor =
+ new DescriptorSupport(new String[] {
+ "descriptorType", "name", "targetObject"
+ }, new Object[] {
+ "operation", "setCount", resource2
+ });
+ Descriptor countDescriptor =
+ new DescriptorSupport(new String[] {
+ "descriptorType", "name", "getMethod", "setMethod"
+ }, new Object[] {
+ "attribute", "Count", "getCount", "setCount"
+ });
+ ModelMBeanOperationInfo operationInfo =
+ new ModelMBeanOperationInfo("operation description",
+ operationMethod, operationDescriptor);
+ ModelMBeanOperationInfo getCountInfo =
+ new ModelMBeanOperationInfo("getCount description",
+ getCountMethod, getCountDescriptor);
+ ModelMBeanOperationInfo setCountInfo =
+ new ModelMBeanOperationInfo("setCount description",
+ setCountMethod, setCountDescriptor);
+ ModelMBeanAttributeInfo countInfo =
+ new ModelMBeanAttributeInfo("Count", "Count description",
+ getCountMethod, setCountMethod,
+ countDescriptor);
+ ModelMBeanInfo mmbi =
+ new ModelMBeanInfoSupport(Resource.class.getName(),
+ "ModelMBean to test targetObject",
+ new ModelMBeanAttributeInfo[] {countInfo},
+ null, // no constructors
+ new ModelMBeanOperationInfo[] {
+ operationInfo, getCountInfo, setCountInfo
+ },
+ null); // no notifications
+ ModelMBean mmb = new RequiredModelMBean(mmbi);
+ mmb.setManagedResource(resource3, "ObjectReference");
+ mbs.registerMBean(mmb, name);
+ mbs.invoke(name, "operation", null, null);
+ mbs.setAttribute(name, new Attribute("Count", 53));
+ if (resource1.operationCount != 1)
+ throw new Exception("operationCount: " + resource1.operationCount);
+ if (resource2.count != 53)
+ throw new Exception("count: " + resource2.count);
+ int got = (Integer) mbs.getAttribute(name, "Count");
+ if (got != 53)
+ throw new Exception("got count: " + got);
+
+ 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();
+ ModelMBeanInfo rmmbi = (ModelMBeanInfo) mbsc.getMBeanInfo(name);
+ // Above gets NotSerializableException if resource included in
+ // serialized form
+ cc.close();
+ cs.stop();
+ System.out.println("TEST PASSED");
+ }
+}
diff --git a/test/javax/management/monitor/AttributeArbitraryDataTypeTest.java b/test/javax/management/monitor/AttributeArbitraryDataTypeTest.java
new file mode 100644
index 0000000..ee52aee
--- /dev/null
+++ b/test/javax/management/monitor/AttributeArbitraryDataTypeTest.java
@@ -0,0 +1,744 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6222961
+ * @summary Test that the counter/gauge/string monitors
+ * support attributes of arbitrary data types.
+ * @author Luis-Miguel Alventosa
+ * @run clean AttributeArbitraryDataTypeTest
+ * @run build AttributeArbitraryDataTypeTest
+ * @run main AttributeArbitraryDataTypeTest
+ */
+
+import java.beans.IntrospectionException;
+import java.beans.PropertyDescriptor;
+import java.beans.SimpleBeanInfo;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.monitor.CounterMonitor;
+import javax.management.monitor.GaugeMonitor;
+import javax.management.monitor.MonitorNotification;
+import javax.management.monitor.StringMonitor;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+
+public class AttributeArbitraryDataTypeTest implements NotificationListener {
+
+ // Flag to notify that a message has been received
+ private boolean counterMessageReceived = false;
+ private boolean gaugeMessageReceived = false;
+ private boolean stringMessageReceived = false;
+
+ // Match enum
+ public enum Match { do_not_match_0,
+ do_not_match_1,
+ do_not_match_2,
+ do_match_now };
+
+ // MatchBeanInfo class
+ public static class MatchBeanInfo extends SimpleBeanInfo {
+ public PropertyDescriptor[] getPropertyDescriptors() {
+ try {
+ return new PropertyDescriptor[] {
+ new PropertyDescriptor("name", Match.class, "name", null) };
+ } catch (IntrospectionException e ) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+ }
+
+ // ComplexAttribute class
+ public class ComplexAttribute {
+
+ public Integer getIntegerAttribute() {
+ return i;
+ }
+
+ public void setIntegerAttribute(Integer i) {
+ this.i = i;
+ }
+
+ public Double getDoubleAttribute() {
+ return d;
+ }
+
+ public void setDoubleAttribute(Double d) {
+ this.d = d;
+ }
+
+ public String getStringAttribute() {
+ return s;
+ }
+
+ public void setStringAttribute(String s) {
+ this.s = s;
+ }
+
+ public Integer[] getArrayAttribute() {
+ return a;
+ }
+
+ public void setArrayAttribute(Integer[] a) {
+ this.a = a;
+ }
+
+ public Match getEnumAttribute() {
+ return e;
+ }
+
+ public void setEnumAttribute(Match e) {
+ this.e = e;
+ }
+
+ private Integer i;
+ private Double d;
+ private String s;
+ private Integer[] a;
+ private Match e;
+ }
+
+ // MBean class
+ public class ObservedObject implements ObservedObjectMBean {
+
+ // Simple type buried in complex getter
+ //
+ public ComplexAttribute getComplexAttribute() {
+ return ca;
+ }
+
+ public void setComplexAttribute(ComplexAttribute ca) {
+ this.ca = ca;
+ }
+
+ private ComplexAttribute ca = null;
+
+ // Simple type buried in CompositeData
+ //
+ public CompositeData getCompositeDataAttribute()
+ throws OpenDataException {
+ CompositeType ct = new CompositeType("CompositeDataAttribute",
+ "Composite Data Attribute",
+ itemNames,
+ itemDescriptions,
+ itemTypes);
+ Object itemValues[] = { ia, da, sa };
+ return new CompositeDataSupport(ct, itemNames, itemValues);
+ }
+
+ public Integer ia;
+ public Double da;
+ public String sa;
+
+ private String itemNames[] = { "IntegerAttribute",
+ "DoubleAttribute",
+ "StringAttribute" };
+ private String itemDescriptions[] = { "Integer Attribute",
+ "Double Attribute",
+ "String Attribute" };
+ private OpenType itemTypes[] = { SimpleType.INTEGER,
+ SimpleType.DOUBLE,
+ SimpleType.STRING };
+ }
+
+ // MBean interface
+ public interface ObservedObjectMBean {
+ public ComplexAttribute getComplexAttribute();
+ public void setComplexAttribute(ComplexAttribute ca);
+ public CompositeData getCompositeDataAttribute()
+ throws OpenDataException;
+ }
+
+ // Notification handler
+ public void handleNotification(Notification notification,
+ Object handback) {
+ MonitorNotification n = (MonitorNotification) notification;
+ echo("\tInside handleNotification...");
+ String type = n.getType();
+ try {
+ if (type.equals(MonitorNotification.
+ THRESHOLD_VALUE_EXCEEDED)) {
+ echo("\t\t" + n.getObservedAttribute() +
+ " has reached or exceeded the threshold");
+ echo("\t\tDerived Gauge = " + n.getDerivedGauge());
+ echo("\t\tTrigger = " + n.getTrigger());
+ counterMessageReceived = true;
+ } else if (type.equals(MonitorNotification.
+ THRESHOLD_HIGH_VALUE_EXCEEDED)) {
+ echo("\t\t" + n.getObservedAttribute() +
+ " has reached or exceeded the high threshold");
+ echo("\t\tDerived Gauge = " + n.getDerivedGauge());
+ echo("\t\tTrigger = " + n.getTrigger());
+ gaugeMessageReceived = true;
+ } else if (type.equals(MonitorNotification.
+ STRING_TO_COMPARE_VALUE_MATCHED)) {
+ echo("\t\t" + n.getObservedAttribute() +
+ " matches the string-to-compare value");
+ echo("\t\tDerived Gauge = " + n.getDerivedGauge());
+ echo("\t\tTrigger = " + n.getTrigger());
+ stringMessageReceived = true;
+ } else {
+ echo("\t\tSkipping notification of type: " + type);
+ }
+ } catch (Exception e) {
+ echo("\tError in handleNotification!");
+ e.printStackTrace(System.out);
+ }
+ }
+
+ /**
+ * Update the counter and check for notifications
+ */
+ public int counterMonitorNotification(int testCase)
+ throws Exception {
+
+ counterMessageReceived = false;
+ CounterMonitor counterMonitor = null;
+ try {
+ MBeanServer server = MBeanServerFactory.newMBeanServer();
+
+ String domain = server.getDefaultDomain();
+
+ // Create a new CounterMonitor MBean and add it to the MBeanServer.
+ //
+ echo(">>> CREATE a new CounterMonitor MBean");
+ ObjectName counterMonitorName = new ObjectName(
+ domain + ":type=" + CounterMonitor.class.getName());
+ counterMonitor = new CounterMonitor();
+ server.registerMBean(counterMonitor, counterMonitorName);
+
+ echo(">>> ADD a listener to the CounterMonitor");
+ counterMonitor.addNotificationListener(this, null, null);
+
+ //
+ // MANAGEMENT OF A STANDARD MBEAN
+ //
+
+ echo(">>> CREATE a new ObservedObject MBean");
+
+ ObjectName obsObjName =
+ ObjectName.getInstance(domain + ":type=ObservedObject");
+ ObservedObject obsObj = new ObservedObject();
+ ComplexAttribute ca = new ComplexAttribute();
+ switch (testCase) {
+ case 1:
+ obsObj.ia = 0;
+ break;
+ case 2:
+ ca.setIntegerAttribute(0);
+ obsObj.setComplexAttribute(ca);
+ break;
+ case 3:
+ ca.setArrayAttribute(new Integer[0]);
+ obsObj.setComplexAttribute(ca);
+ break;
+ }
+ server.registerMBean(obsObj, obsObjName);
+
+ echo(">>> SET the attributes of the CounterMonitor:");
+
+ counterMonitor.addObservedObject(obsObjName);
+ echo("\tATTRIBUTE \"ObservedObject\" = " + obsObjName);
+
+ switch (testCase) {
+ case 1:
+ counterMonitor.setObservedAttribute(
+ "CompositeDataAttribute.IntegerAttribute");
+ echo("\tATTRIBUTE \"ObservedAttribute\" = " +
+ "CompositeDataAttribute.IntegerAttribute");
+ break;
+ case 2:
+ counterMonitor.setObservedAttribute(
+ "ComplexAttribute.integerAttribute");
+ echo("\tATTRIBUTE \"ObservedAttribute\" = " +
+ "ComplexAttribute.integerAttribute");
+ break;
+ case 3:
+ counterMonitor.setObservedAttribute(
+ "ComplexAttribute.arrayAttribute.length");
+ echo("\tATTRIBUTE \"ObservedAttribute\" = " +
+ "ComplexAttribute.arrayAttribute.length");
+ break;
+ }
+
+ counterMonitor.setNotify(true);
+ echo("\tATTRIBUTE \"NotifyFlag\" = true");
+
+ Integer threshold = 2;
+ counterMonitor.setInitThreshold(threshold);
+ echo("\tATTRIBUTE \"Threshold\" = " + threshold);
+
+ int granularityperiod = 500;
+ counterMonitor.setGranularityPeriod(granularityperiod);
+ echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
+
+ echo(">>> START the CounterMonitor");
+ counterMonitor.start();
+
+ // Wait for granularity period (multiplied by 2 for sure)
+ //
+ Thread.sleep(granularityperiod * 2);
+
+ switch (testCase) {
+ case 1:
+ obsObj.ia = 1;
+ break;
+ case 2:
+ ca.setIntegerAttribute(1);
+ break;
+ case 3:
+ ca.setArrayAttribute(new Integer[1]);
+ break;
+ }
+
+ // Wait for granularity period (multiplied by 2 for sure)
+ //
+ Thread.sleep(granularityperiod * 2);
+
+ switch (testCase) {
+ case 1:
+ obsObj.ia = 2;
+ break;
+ case 2:
+ ca.setIntegerAttribute(2);
+ break;
+ case 3:
+ ca.setArrayAttribute(new Integer[2]);
+ break;
+ }
+
+ // Wait for granularity period (multiplied by 2 for sure)
+ //
+ Thread.sleep(granularityperiod * 2);
+
+ switch (testCase) {
+ case 1:
+ obsObj.ia = 3;
+ break;
+ case 2:
+ ca.setIntegerAttribute(3);
+ break;
+ case 3:
+ ca.setArrayAttribute(new Integer[3]);
+ break;
+ }
+
+ // Check if notification was received
+ //
+ if (counterMessageReceived) {
+ echo("\tOK: CounterMonitor notification received");
+ } else {
+ echo("\tKO: CounterMonitor notification missed or not emitted");
+ return 1;
+ }
+ } finally {
+ if (counterMonitor != null)
+ counterMonitor.stop();
+ }
+
+ return 0;
+ }
+
+ /**
+ * Update the gauge and check for notifications
+ */
+ public int gaugeMonitorNotification(int testCase)
+ throws Exception {
+
+ gaugeMessageReceived = false;
+ GaugeMonitor gaugeMonitor = null;
+ try {
+ MBeanServer server = MBeanServerFactory.newMBeanServer();
+
+ String domain = server.getDefaultDomain();
+
+ // Create a new GaugeMonitor MBean and add it to the MBeanServer.
+ //
+ echo(">>> CREATE a new GaugeMonitor MBean");
+ ObjectName gaugeMonitorName = new ObjectName(
+ domain + ":type=" + GaugeMonitor.class.getName());
+ gaugeMonitor = new GaugeMonitor();
+ server.registerMBean(gaugeMonitor, gaugeMonitorName);
+
+ echo(">>> ADD a listener to the GaugeMonitor");
+ gaugeMonitor.addNotificationListener(this, null, null);
+
+ //
+ // MANAGEMENT OF A STANDARD MBEAN
+ //
+
+ echo(">>> CREATE a new ObservedObject MBean");
+
+ ObjectName obsObjName =
+ ObjectName.getInstance(domain + ":type=ObservedObject");
+ ObservedObject obsObj = new ObservedObject();
+ ComplexAttribute ca = new ComplexAttribute();
+ switch (testCase) {
+ case 1:
+ obsObj.da = 0.0;
+ break;
+ case 2:
+ ca.setDoubleAttribute(0.0);
+ obsObj.setComplexAttribute(ca);
+ break;
+ case 3:
+ ca.setArrayAttribute(new Integer[0]);
+ obsObj.setComplexAttribute(ca);
+ break;
+ }
+ server.registerMBean(obsObj, obsObjName);
+
+ echo(">>> SET the attributes of the GaugeMonitor:");
+
+ gaugeMonitor.addObservedObject(obsObjName);
+ echo("\tATTRIBUTE \"ObservedObject\" = " + obsObjName);
+
+ switch (testCase) {
+ case 1:
+ gaugeMonitor.setObservedAttribute(
+ "CompositeDataAttribute.DoubleAttribute");
+ echo("\tATTRIBUTE \"ObservedAttribute\" = " +
+ "CompositeDataAttribute.DoubleAttribute");
+ break;
+ case 2:
+ gaugeMonitor.setObservedAttribute(
+ "ComplexAttribute.doubleAttribute");
+ echo("\tATTRIBUTE \"ObservedAttribute\" = " +
+ "ComplexAttribute.doubleAttribute");
+ break;
+ case 3:
+ gaugeMonitor.setObservedAttribute(
+ "ComplexAttribute.arrayAttribute.length");
+ echo("\tATTRIBUTE \"ObservedAttribute\" = " +
+ "ComplexAttribute.arrayAttribute.length");
+ break;
+ }
+
+ gaugeMonitor.setNotifyLow(false);
+ gaugeMonitor.setNotifyHigh(true);
+ echo("\tATTRIBUTE \"Notify Low Flag\" = false");
+ echo("\tATTRIBUTE \"Notify High Flag\" = true");
+
+ switch (testCase) {
+ case 1:
+ case 2:
+ Double highThresholdD = 3.0, lowThresholdD = 2.5;
+ gaugeMonitor.setThresholds(highThresholdD, lowThresholdD);
+ echo("\tATTRIBUTE \"Low Threshold\" = " + lowThresholdD);
+ echo("\tATTRIBUTE \"High Threshold\" = " + highThresholdD);
+ break;
+ case 3:
+ Integer highThreshold = 2, lowThreshold = 1;
+ gaugeMonitor.setThresholds(highThreshold, lowThreshold);
+ echo("\tATTRIBUTE \"Low Threshold\" = " + lowThreshold);
+ echo("\tATTRIBUTE \"High Threshold\" = " + highThreshold);
+ break;
+ }
+
+ int granularityperiod = 500;
+ gaugeMonitor.setGranularityPeriod(granularityperiod);
+ echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
+
+ echo(">>> START the GaugeMonitor");
+ gaugeMonitor.start();
+
+ // Wait for granularity period (multiplied by 2 for sure)
+ //
+ Thread.sleep(granularityperiod * 2);
+
+ switch (testCase) {
+ case 1:
+ obsObj.da = 2.0;
+ break;
+ case 2:
+ ca.setDoubleAttribute(2.0);
+ break;
+ case 3:
+ ca.setArrayAttribute(new Integer[2]);
+ break;
+ }
+
+ // Wait for granularity period (multiplied by 2 for sure)
+ //
+ Thread.sleep(granularityperiod * 2);
+
+ switch (testCase) {
+ case 1:
+ obsObj.da = 4.0;
+ break;
+ case 2:
+ ca.setDoubleAttribute(4.0);
+ break;
+ case 3:
+ ca.setArrayAttribute(new Integer[4]);
+ break;
+ }
+
+ // Wait for granularity period (multiplied by 2 for sure)
+ //
+ Thread.sleep(granularityperiod * 2);
+
+ switch (testCase) {
+ case 1:
+ obsObj.da = 6.0;
+ break;
+ case 2:
+ ca.setDoubleAttribute(6.0);
+ break;
+ case 3:
+ ca.setArrayAttribute(new Integer[6]);
+ break;
+ }
+
+ // Check if notification was received
+ //
+ if (gaugeMessageReceived) {
+ echo("\tOK: GaugeMonitor notification received");
+ } else {
+ echo("\tKO: GaugeMonitor notification missed or not emitted");
+ return 1;
+ }
+ } finally {
+ if (gaugeMonitor != null)
+ gaugeMonitor.stop();
+ }
+
+ return 0;
+ }
+
+ /**
+ * Update the string and check for notifications
+ */
+ public int stringMonitorNotification(int testCase)
+ throws Exception {
+
+ stringMessageReceived = false;
+ StringMonitor stringMonitor = null;
+ try {
+ MBeanServer server = MBeanServerFactory.newMBeanServer();
+
+ String domain = server.getDefaultDomain();
+
+ // Create a new StringMonitor MBean and add it to the MBeanServer.
+ //
+ echo(">>> CREATE a new StringMonitor MBean");
+ ObjectName stringMonitorName = new ObjectName(
+ domain + ":type=" + StringMonitor.class.getName());
+ stringMonitor = new StringMonitor();
+ server.registerMBean(stringMonitor, stringMonitorName);
+
+ echo(">>> ADD a listener to the StringMonitor");
+ stringMonitor.addNotificationListener(this, null, null);
+
+ //
+ // MANAGEMENT OF A STANDARD MBEAN
+ //
+
+ echo(">>> CREATE a new ObservedObject MBean");
+
+ ObjectName obsObjName =
+ ObjectName.getInstance(domain + ":type=ObservedObject");
+ ObservedObject obsObj = new ObservedObject();
+ ComplexAttribute ca = new ComplexAttribute();
+ switch (testCase) {
+ case 1:
+ obsObj.sa = "do_not_match_0";
+ break;
+ case 2:
+ ca.setStringAttribute("do_not_match_0");
+ obsObj.setComplexAttribute(ca);
+ break;
+ case 3:
+ ca.setEnumAttribute(Match.do_not_match_0);
+ obsObj.setComplexAttribute(ca);
+ break;
+ }
+ server.registerMBean(obsObj, obsObjName);
+
+ echo(">>> SET the attributes of the StringMonitor:");
+
+ stringMonitor.addObservedObject(obsObjName);
+ echo("\tATTRIBUTE \"ObservedObject\" = " + obsObjName);
+
+ switch (testCase) {
+ case 1:
+ stringMonitor.setObservedAttribute(
+ "CompositeDataAttribute.StringAttribute");
+ echo("\tATTRIBUTE \"ObservedAttribute\" = " +
+ "CompositeDataAttribute.StringAttribute");
+ break;
+ case 2:
+ stringMonitor.setObservedAttribute(
+ "ComplexAttribute.stringAttribute");
+ echo("\tATTRIBUTE \"ObservedAttribute\" = " +
+ "ComplexAttribute.stringAttribute");
+ break;
+ case 3:
+ stringMonitor.setObservedAttribute(
+ "ComplexAttribute.enumAttribute.name");
+ echo("\tATTRIBUTE \"ObservedAttribute\" = " +
+ "ComplexAttribute.enumAttribute.name");
+ break;
+ }
+
+ stringMonitor.setNotifyMatch(true);
+ echo("\tATTRIBUTE \"NotifyMatch\" = true");
+
+ stringMonitor.setNotifyDiffer(false);
+ echo("\tATTRIBUTE \"NotifyDiffer\" = false");
+
+ stringMonitor.setStringToCompare("do_match_now");
+ echo("\tATTRIBUTE \"StringToCompare\" = \"do_match_now\"");
+
+ int granularityperiod = 500;
+ stringMonitor.setGranularityPeriod(granularityperiod);
+ echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
+
+ echo(">>> START the StringMonitor");
+ stringMonitor.start();
+
+ // Wait for granularity period (multiplied by 2 for sure)
+ //
+ Thread.sleep(granularityperiod * 2);
+
+ switch (testCase) {
+ case 1:
+ obsObj.sa = "do_not_match_1";
+ break;
+ case 2:
+ ca.setStringAttribute("do_not_match_1");
+ break;
+ case 3:
+ ca.setEnumAttribute(Match.do_not_match_1);
+ break;
+ }
+
+ // Wait for granularity period (multiplied by 2 for sure)
+ //
+ Thread.sleep(granularityperiod * 2);
+
+ switch (testCase) {
+ case 1:
+ obsObj.sa = "do_match_now";
+ break;
+ case 2:
+ ca.setStringAttribute("do_match_now");
+ break;
+ case 3:
+ ca.setEnumAttribute(Match.do_match_now);
+ break;
+ }
+
+ // Wait for granularity period (multiplied by 2 for sure)
+ //
+ Thread.sleep(granularityperiod * 2);
+
+ switch (testCase) {
+ case 1:
+ obsObj.sa = "do_not_match_2";
+ break;
+ case 2:
+ ca.setStringAttribute("do_not_match_2");
+ break;
+ case 3:
+ ca.setEnumAttribute(Match.do_not_match_2);
+ break;
+ }
+
+ // Check if notification was received
+ //
+ if (stringMessageReceived) {
+ echo("\tOK: StringMonitor notification received");
+ } else {
+ echo("\tKO: StringMonitor notification missed or not emitted");
+ return 1;
+ }
+ } finally {
+ if (stringMonitor != null)
+ stringMonitor.stop();
+ }
+
+ return 0;
+ }
+
+ /**
+ * Test the monitor notifications.
+ */
+ public int monitorNotifications() throws Exception {
+ echo(">>> ----------------------------------------");
+ int error = counterMonitorNotification(1);
+ echo(">>> ----------------------------------------");
+ error += counterMonitorNotification(2);
+ echo(">>> ----------------------------------------");
+ error += counterMonitorNotification(3);
+ echo(">>> ----------------------------------------");
+ error += gaugeMonitorNotification(1);
+ echo(">>> ----------------------------------------");
+ error += gaugeMonitorNotification(2);
+ echo(">>> ----------------------------------------");
+ error += gaugeMonitorNotification(3);
+ echo(">>> ----------------------------------------");
+ error += stringMonitorNotification(1);
+ echo(">>> ----------------------------------------");
+ error += stringMonitorNotification(2);
+ echo(">>> ----------------------------------------");
+ error += stringMonitorNotification(3);
+ echo(">>> ----------------------------------------");
+ return error;
+ }
+
+ /*
+ * Print message
+ */
+ private static void echo(String message) {
+ System.out.println(message);
+ }
+
+ /*
+ * Standalone entry point.
+ *
+ * Run the test and report to stdout.
+ */
+ public static void main (String args[]) throws Exception {
+ AttributeArbitraryDataTypeTest test =
+ new AttributeArbitraryDataTypeTest();
+ int error = test.monitorNotifications();
+ if (error > 0) {
+ echo(">>> Unhappy Bye, Bye!");
+ throw new IllegalStateException("Test FAILED: Didn't get all " +
+ "the notifications that were " +
+ "expected by the test!");
+ } else {
+ echo(">>> Happy Bye, Bye!");
+ }
+ }
+}
diff --git a/test/javax/management/monitor/CounterMonitorDeadlockTest.java b/test/javax/management/monitor/CounterMonitorDeadlockTest.java
new file mode 100644
index 0000000..352c264
--- /dev/null
+++ b/test/javax/management/monitor/CounterMonitorDeadlockTest.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6303187
+ * @summary Test that no locks are held when a monitor attribute is sampled
+ * or notif delivered.
+ * @author Eamonn McManus
+ * @run clean CounterMonitorDeadlockTest
+ * @run build CounterMonitorDeadlockTest
+ * @run main CounterMonitorDeadlockTest 1
+ * @run main CounterMonitorDeadlockTest 2
+ * @run main CounterMonitorDeadlockTest 3
+ * @run main CounterMonitorDeadlockTest 4
+ */
+
+import java.lang.management.ManagementFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.management.Attribute;
+import javax.management.JMX;
+import javax.management.MBeanServer;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.monitor.CounterMonitor;
+import javax.management.monitor.CounterMonitorMBean;
+
+public class CounterMonitorDeadlockTest {
+
+ public static void main(String[] args) throws Exception {
+ if (args.length != 1)
+ throw new Exception("Arg should be test number");
+ int testNo = Integer.parseInt(args[0]) - 1;
+ TestCase test = testCases[testNo];
+ System.out.println("Test: " + test.getDescription());
+ test.run();
+ System.out.println("Test passed");
+ }
+
+ private static enum When {IN_GET_ATTRIBUTE, IN_NOTIFY};
+
+ private static abstract class TestCase {
+ TestCase(String description, When when) {
+ this.description = description;
+ this.when = when;
+ }
+
+ void run() throws Exception {
+ final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ final ObjectName observedName = new ObjectName("a:b=c");
+ final ObjectName monitorName = new ObjectName("a:type=Monitor");
+ mbs.registerMBean(new CounterMonitor(), monitorName);
+ final CounterMonitorMBean monitorProxy =
+ JMX.newMBeanProxy(mbs, monitorName, CounterMonitorMBean.class);
+ final TestMBean observedProxy =
+ JMX.newMBeanProxy(mbs, observedName, TestMBean.class);
+
+ final Runnable sensitiveThing = new Runnable() {
+ public void run() {
+ doSensitiveThing(monitorProxy, observedName);
+ }
+ };
+
+ final Runnable nothing = new Runnable() {
+ public void run() {}
+ };
+
+ final Runnable withinGetAttribute =
+ (when == When.IN_GET_ATTRIBUTE) ? sensitiveThing : nothing;
+
+ mbs.registerMBean(new Test(withinGetAttribute), observedName);
+ monitorProxy.addObservedObject(observedName);
+ monitorProxy.setObservedAttribute("Thing");
+ monitorProxy.setInitThreshold(100);
+ monitorProxy.setGranularityPeriod(10L); // 10 ms
+ monitorProxy.setNotify(true);
+ monitorProxy.start();
+
+ final int initGetCount = observedProxy.getGetCount();
+ int getCount = initGetCount;
+ for (int i = 0; i < 500; i++) { // 500 * 10 = 5 seconds
+ getCount = observedProxy.getGetCount();
+ if (getCount != initGetCount)
+ break;
+ Thread.sleep(10);
+ }
+ if (getCount <= initGetCount)
+ throw new Exception("Test failed: presumable deadlock");
+ // This won't show up as a deadlock in CTRL-\ or in
+ // ThreadMXBean.findDeadlockedThreads(), because they don't
+ // see that thread A is waiting for thread B (B.join()), and
+ // thread B is waiting for a lock held by thread A
+
+ // Now we know the monitor has observed the initial value,
+ // so if we want to test notify behaviour we can trigger by
+ // exceeding the threshold.
+ if (when == When.IN_NOTIFY) {
+ final AtomicInteger notifCount = new AtomicInteger();
+ final NotificationListener listener = new NotificationListener() {
+ public void handleNotification(Notification n, Object h) {
+ Thread t = new Thread(sensitiveThing);
+ t.start();
+ try {
+ t.join();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ notifCount.incrementAndGet();
+ }
+ };
+ mbs.addNotificationListener(monitorName, listener, null, null);
+ observedProxy.setThing(1000);
+ for (int i = 0; i < 500 && notifCount.get() == 0; i++)
+ Thread.sleep(10);
+ if (notifCount.get() == 0)
+ throw new Exception("Test failed: presumable deadlock");
+ }
+
+ }
+
+ abstract void doSensitiveThing(CounterMonitorMBean monitorProxy,
+ ObjectName observedName);
+
+ String getDescription() {
+ return description;
+ }
+
+ private final String description;
+ private final When when;
+ }
+
+ private static final TestCase[] testCases = {
+ new TestCase("Remove monitored MBean within monitored getAttribute",
+ When.IN_GET_ATTRIBUTE) {
+ @Override
+ void doSensitiveThing(CounterMonitorMBean monitorProxy,
+ ObjectName observedName) {
+ monitorProxy.removeObservedObject(observedName);
+ }
+ },
+ new TestCase("Stop monitor within monitored getAttribute",
+ When.IN_GET_ATTRIBUTE) {
+ @Override
+ void doSensitiveThing(CounterMonitorMBean monitorProxy,
+ ObjectName observedName) {
+ monitorProxy.stop();
+ }
+ },
+ new TestCase("Remove monitored MBean within threshold listener",
+ When.IN_NOTIFY) {
+ @Override
+ void doSensitiveThing(CounterMonitorMBean monitorProxy,
+ ObjectName observedName) {
+ monitorProxy.removeObservedObject(observedName);
+ }
+ },
+ new TestCase("Stop monitor within threshold listener",
+ When.IN_NOTIFY) {
+ @Override
+ void doSensitiveThing(CounterMonitorMBean monitorProxy,
+ ObjectName observedName) {
+ monitorProxy.stop();
+ }
+ },
+ };
+
+ public static interface TestMBean {
+ public int getThing();
+ public void setThing(int thing);
+ public int getGetCount();
+ }
+
+ public static class Test implements TestMBean {
+ public Test(Runnable runWithinGetAttribute) {
+ this.runWithinGetAttribute = runWithinGetAttribute;
+ }
+
+ public int getThing() {
+ Thread t = new Thread(runWithinGetAttribute);
+ t.start();
+ try {
+ t.join();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ getCount++;
+ return thing;
+ }
+
+ public void setThing(int thing) {
+ this.thing = thing;
+ }
+
+ public int getGetCount() {
+ return getCount;
+ }
+
+ private final Runnable runWithinGetAttribute;
+ private volatile int getCount;
+ private volatile int thing;
+ }
+}
diff --git a/test/javax/management/monitor/CounterMonitorInitThresholdTest.java b/test/javax/management/monitor/CounterMonitorInitThresholdTest.java
new file mode 100644
index 0000000..d76247f
--- /dev/null
+++ b/test/javax/management/monitor/CounterMonitorInitThresholdTest.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6333528
+ * @summary Check that the initial threshold is properly used by the observed
+ * objects added before the counter monitor is started as well as by
+ * the observed objects which are added once the monitor is started.
+ * @author Luis-Miguel Alventosa
+ * @run clean CounterMonitorInitThresholdTest
+ * @run build CounterMonitorInitThresholdTest
+ * @run main CounterMonitorInitThresholdTest
+ */
+
+import java.lang.management.ManagementFactory;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.Notification;
+import javax.management.NotificationEmitter;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.monitor.CounterMonitor;
+import javax.management.monitor.CounterMonitorMBean;
+import javax.management.monitor.MonitorNotification;
+
+public class CounterMonitorInitThresholdTest {
+
+ public interface TestMBean {
+ public int getCounter();
+ public void setCounter(int count);
+ }
+
+ public static class Test implements TestMBean {
+ public int getCounter() {
+ return count;
+ }
+ public void setCounter(int count) {
+ this.count = count;
+ }
+ private int count = 0;
+ }
+
+ public static class Listener implements NotificationListener {
+ public void handleNotification(Notification n, Object hb) {
+ System.out.println("\tReceived notification: " + n.getType());
+ if (n instanceof MonitorNotification) {
+ MonitorNotification mn = (MonitorNotification) n;
+ System.out.println("\tSource: " +
+ mn.getSource());
+ System.out.println("\tType: " +
+ mn.getType());
+ System.out.println("\tTimeStamp: " +
+ mn.getTimeStamp());
+ System.out.println("\tObservedObject: " +
+ mn.getObservedObject());
+ System.out.println("\tObservedAttribute: " +
+ mn.getObservedAttribute());
+ System.out.println("\tDerivedGauge: " +
+ mn.getDerivedGauge());
+ System.out.println("\tTrigger: " +
+ mn.getTrigger());
+ }
+ }
+ }
+
+ public static void runTest() throws Exception {
+ // Retrieve the platform MBean server
+ //
+ System.out.println("\nRetrieve the platform MBean server");
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ String domain = mbs.getDefaultDomain();
+
+ // Create and register TestMBeans
+ //
+ ObjectName name1 =
+ new ObjectName(domain +
+ ":type=" + Test.class.getName() +
+ ",name=1");
+ mbs.createMBean(Test.class.getName(), name1);
+ TestMBean mbean1 = (TestMBean)
+ MBeanServerInvocationHandler.newProxyInstance(
+ mbs, name1, TestMBean.class, false);
+ ObjectName name2 =
+ new ObjectName(domain +
+ ":type=" + Test.class.getName() +
+ ",name=2");
+ mbs.createMBean(Test.class.getName(), name2);
+ TestMBean mbean2 = (TestMBean)
+ MBeanServerInvocationHandler.newProxyInstance(
+ mbs, name2, TestMBean.class, false);
+
+ // Create and register CounterMonitorMBean
+ //
+ ObjectName cmn =
+ new ObjectName(domain +
+ ":type=" + CounterMonitor.class.getName());
+ CounterMonitor m = new CounterMonitor();
+ mbs.registerMBean(m, cmn);
+ CounterMonitorMBean cm = (CounterMonitorMBean)
+ MBeanServerInvocationHandler.newProxyInstance(
+ mbs, cmn, CounterMonitorMBean.class, true);
+ ((NotificationEmitter) cm).addNotificationListener(
+ new Listener(), null, null);
+ cm.setObservedAttribute("Counter");
+ cm.setGranularityPeriod(100);
+ cm.setInitThreshold(3);
+ cm.setNotify(true);
+
+ // Add observed object name1
+ //
+ System.out.println("\nObservedObject \"" + name1 +
+ "\" registered before starting the monitor");
+ cm.addObservedObject(name1);
+
+ // Start the monitor
+ //
+ System.out.println("\nStart monitoring...");
+ cm.start();
+
+ // Play with counter for name1
+ //
+ System.out.println("\nTest ObservedObject \"" + name1 + "\"");
+ for (int i = 0; i < 4; i++) {
+ mbean1.setCounter(i);
+ System.out.println("\nCounter = " + mbean1.getCounter());
+ Thread.sleep(300);
+ Number thresholdValue = cm.getThreshold(name1);
+ System.out.println("Threshold = " + thresholdValue);
+ if (thresholdValue.intValue() != 3) {
+ System.out.println("Wrong threshold! Current value = " +
+ thresholdValue + " Expected value = 3");
+ System.out.println("\nStop monitoring...");
+ cm.stop();
+ throw new IllegalArgumentException("wrong threshold");
+ }
+ Thread.sleep(300);
+ }
+
+ // Add observed object name2
+ //
+ System.out.println("\nObservedObject \"" + name2 +
+ "\" registered after starting the monitor");
+ cm.addObservedObject(name2);
+
+ // Play with counter for name2
+ //
+ System.out.println("\nTest ObservedObject \"" + name2 + "\"");
+ for (int i = 0; i < 4; i++) {
+ mbean2.setCounter(i);
+ System.out.println("\nCounter = " + mbean2.getCounter());
+ Thread.sleep(300);
+ Number thresholdValue = cm.getThreshold(name2);
+ System.out.println("Threshold = " + thresholdValue);
+ if (thresholdValue.intValue() != 3) {
+ System.out.println("Wrong threshold! Current value = " +
+ thresholdValue + " Expected value = 3");
+ System.out.println("\nStop monitoring...");
+ cm.stop();
+ throw new IllegalArgumentException("wrong threshold");
+ }
+ Thread.sleep(300);
+ }
+
+ // Stop the monitor
+ //
+ System.out.println("\nStop monitoring...");
+ cm.stop();
+ }
+
+ public static void main(String[] args) throws Exception {
+ runTest();
+ }
+}
diff --git a/test/javax/management/monitor/CounterMonitorTest.java b/test/javax/management/monitor/CounterMonitorTest.java
new file mode 100644
index 0000000..b22f9ed
--- /dev/null
+++ b/test/javax/management/monitor/CounterMonitorTest.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4981829
+ * @summary Test that the counter monitor, when running in difference mode,
+ * emits a notification every time the threshold is exceeded.
+ * @author Luis-Miguel Alventosa
+ * @run clean CounterMonitorTest
+ * @run build CounterMonitorTest
+ * @run main CounterMonitorTest
+ */
+
+import javax.management.*;
+import javax.management.monitor.*;
+
+public class CounterMonitorTest implements NotificationListener {
+
+ // threshold number
+ private Number threshold = new Integer(2);
+
+ // modulus number
+ private Number modulus = new Integer(7);
+
+ // offset number
+ private int offset = 0;
+
+ // difference mode flag
+ private boolean differenceModeFlag = true;
+
+ // notify flag
+ private boolean notifyFlag = true;
+
+ // granularity period
+ private int granularityperiod = 500;
+
+ // counter values
+ private int[] values = new int[] {4, 6, 9, 11};
+
+ // time to wait for notification (in seconds)
+ private int timeout = 5;
+
+ // flag to notify that a message has been received
+ private volatile boolean messageReceived = false;
+
+ // MBean class
+ public class StdObservedObject implements StdObservedObjectMBean {
+ public Object getNbObjects() {
+ return count;
+ }
+ public void setNbObjects(Object n) {
+ count = n;
+ }
+ private Object count= null;
+ }
+
+ // MBean interface
+ public interface StdObservedObjectMBean {
+ public Object getNbObjects();
+ public void setNbObjects(Object n);
+ }
+
+ // Notification handler
+ public void handleNotification(Notification notification,
+ Object handback) {
+ MonitorNotification n = (MonitorNotification) notification;
+ echo("\tInside handleNotification...");
+ String type = n.getType();
+ try {
+ if (type.equals(MonitorNotification.THRESHOLD_VALUE_EXCEEDED)) {
+ echo("\t\t" + n.getObservedAttribute() +
+ " has reached or exceeded the threshold");
+ echo("\t\tDerived Gauge = " + n.getDerivedGauge());
+ messageReceived = true;
+ synchronized (this) {
+ notifyAll();
+ }
+ } else {
+ echo("\t\tSkipping notification of type: " + type);
+ }
+ } catch (Exception e) {
+ echo("\tError in handleNotification!");
+ e.printStackTrace(System.out);
+ }
+ }
+
+ /**
+ * Update the counter and check for notifications
+ */
+ public void thresholdNotification() throws Exception {
+
+ CounterMonitor counterMonitor = new CounterMonitor();
+ try {
+ MBeanServer server = MBeanServerFactory.newMBeanServer();
+
+ String domain = server.getDefaultDomain();
+
+ // Create a new CounterMonitor MBean and add it to the MBeanServer.
+ //
+ echo(">>> CREATE a new CounterMonitor MBean");
+ ObjectName counterMonitorName = new ObjectName(
+ domain + ":type=" + CounterMonitor.class.getName());
+ server.registerMBean(counterMonitor, counterMonitorName);
+
+ echo(">>> ADD a listener to the CounterMonitor");
+ counterMonitor.addNotificationListener(this, null, null);
+
+ //
+ // MANAGEMENT OF A STANDARD MBEAN
+ //
+
+ echo(">>> CREATE a new StdObservedObject MBean");
+
+ ObjectName stdObsObjName =
+ new ObjectName(domain + ":type=StdObservedObject");
+ StdObservedObject stdObsObj = new StdObservedObject();
+ server.registerMBean(stdObsObj, stdObsObjName);
+
+ echo(">>> SET the attributes of the CounterMonitor:");
+
+ counterMonitor.addObservedObject(stdObsObjName);
+ echo("\tATTRIBUTE \"ObservedObject\" = " + stdObsObjName);
+
+ counterMonitor.setObservedAttribute("NbObjects");
+ echo("\tATTRIBUTE \"ObservedAttribute\" = NbObjects");
+
+ counterMonitor.setNotify(notifyFlag);
+ echo("\tATTRIBUTE \"Notify\" = " + notifyFlag);
+
+ counterMonitor.setInitThreshold(threshold);
+ echo("\tATTRIBUTE \"Threshold\" = " + threshold);
+
+ counterMonitor.setGranularityPeriod(granularityperiod);
+ echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
+
+ counterMonitor.setModulus(modulus);
+ echo("\tATTRIBUTE \"Modulus\" = " + modulus);
+
+ counterMonitor.setDifferenceMode(differenceModeFlag);
+ echo("\tATTRIBUTE \"DifferenceMode\" = " + differenceModeFlag);
+
+ echo(">>> START the CounterMonitor");
+ counterMonitor.start();
+
+ // Set initial value
+ //
+ Integer data = new Integer(0);
+ echo(">>> Set data = " + data.intValue());
+
+ Attribute attrib = new Attribute("NbObjects", data);
+ server.setAttribute(stdObsObjName, attrib);
+
+ // Wait for granularity period (multiplied by 2 for sure)
+ //
+ Thread.sleep(granularityperiod * 2);
+
+ // Loop through the values
+ //
+ for (int i = 0; i < values.length; i++) {
+ data = new Integer(values[i]);
+ echo(">>> Set data = " + data.intValue());
+
+ attrib = new Attribute("NbObjects", data);
+ server.setAttribute(stdObsObjName, attrib);
+
+ echo("\tdoWait in Counter Monitor");
+ doWait();
+
+ // Check if notification was received
+ //
+ if (messageReceived) {
+ echo("\tOKAY: Notification received");
+ } else {
+ echo("\tError: notification missed or not emitted");
+ throw new IllegalStateException("Notification lost");
+ }
+ messageReceived = false;
+ }
+ } finally {
+ counterMonitor.stop();
+ }
+
+ echo(">>> Bye! Bye!");
+ }
+
+ /*
+ * Wait until timeout reached
+ */
+ void doWait() {
+ for (int i = 0; i < timeout; i++) {
+ echo("\tdoWait: Waiting for " + timeout + " seconds. " +
+ "i = " + i + ", messageReceived = " + messageReceived);
+ if (messageReceived) {
+ break;
+ }
+ try {
+ synchronized (this) {
+ wait(1000);
+ }
+ } catch (InterruptedException e) {
+ // OK: Ignore...
+ }
+ }
+ }
+
+ /*
+ * Print message
+ */
+ void echo(String message) {
+ System.out.println(message);
+ }
+
+ /*
+ * Standalone entry point.
+ *
+ * Run the test and report to stdout.
+ */
+ public static void main (String args[]) throws Exception {
+ CounterMonitorTest test = new CounterMonitorTest();
+ test.thresholdNotification();
+ }
+}
diff --git a/test/javax/management/monitor/CounterMonitorThresholdTest.java b/test/javax/management/monitor/CounterMonitorThresholdTest.java
new file mode 100644
index 0000000..ffcfcb3
--- /dev/null
+++ b/test/javax/management/monitor/CounterMonitorThresholdTest.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6229368
+ * @summary Wrong threshold value in CounterMonitor with offset and modulus.
+ * @author Luis-Miguel Alventosa
+ * @run clean CounterMonitorThresholdTest
+ * @run build CounterMonitorThresholdTest
+ * @run main CounterMonitorThresholdTest
+ */
+
+import java.lang.management.ManagementFactory;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.Notification;
+import javax.management.NotificationEmitter;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.monitor.CounterMonitor;
+import javax.management.monitor.CounterMonitorMBean;
+import javax.management.monitor.MonitorNotification;
+
+public class CounterMonitorThresholdTest {
+
+ // Offset = 1
+ private static int counter1[] = { 0, 1, 2, 3, 4, 4, 5, 5, 0, 1, 2, 3, 4, 5, 0, 1 };
+ private static int derivedGauge1[] = { 0, 1, 2, 3, 4, 4, 5, 5, 0, 1, 2, 3, 4, 5, 0, 1 };
+ private static int threshold1[] = { 1, 2, 3, 4, 5, 5, 1, 1, 1, 2, 3, 4, 5, 1, 1, 2 };
+
+ // Offset = 3
+ private static int counter2[] = { 0, 1, 2, 3, 3, 4, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1 };
+ private static int derivedGauge2[] = { 0, 1, 2, 3, 3, 4, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1 };
+ private static int threshold2[] = { 1, 4, 4, 4, 4, 1, 1, 1, 1, 4, 4, 4, 1, 1, 1, 4 };
+
+ public interface TestMBean {
+ public int getCounter();
+ public void setCounter(int count);
+ }
+
+ public static class Test implements TestMBean {
+ public int getCounter() {
+ return count;
+ }
+ public void setCounter(int count) {
+ this.count = count;
+ }
+ private int count = 0;
+ }
+
+ public static class Listener implements NotificationListener {
+ public void handleNotification(Notification n, Object hb) {
+ System.out.println("\tReceived notification: " + n.getType());
+ if (n instanceof MonitorNotification) {
+ MonitorNotification mn = (MonitorNotification) n;
+ System.out.println("\tSource: " +
+ mn.getSource());
+ System.out.println("\tType: " +
+ mn.getType());
+ System.out.println("\tTimeStamp: " +
+ mn.getTimeStamp());
+ System.out.println("\tObservedObject: " +
+ mn.getObservedObject());
+ System.out.println("\tObservedAttribute: " +
+ mn.getObservedAttribute());
+ System.out.println("\tDerivedGauge: " +
+ mn.getDerivedGauge());
+ System.out.println("\tTrigger: " +
+ mn.getTrigger());
+ }
+ }
+ }
+
+ public static void runTest(int offset,
+ int counter[],
+ int derivedGauge[],
+ int threshold[]) throws Exception {
+ // Retrieve the platform MBean server
+ //
+ System.out.println("\nRetrieve the platform MBean server");
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ String domain = mbs.getDefaultDomain();
+
+ // Create and register TestMBean
+ //
+ ObjectName name =
+ new ObjectName(domain +
+ ":type=" + Test.class.getName() +
+ ",offset=" + offset);
+ mbs.createMBean(Test.class.getName(), name);
+ TestMBean mbean = (TestMBean)
+ MBeanServerInvocationHandler.newProxyInstance(
+ mbs, name, TestMBean.class, false);
+
+ // Create and register CounterMonitorMBean
+ //
+ ObjectName cmn =
+ new ObjectName(domain +
+ ":type=" + CounterMonitor.class.getName() +
+ ",offset=" + offset);
+ CounterMonitor m = new CounterMonitor();
+ mbs.registerMBean(m, cmn);
+ CounterMonitorMBean cm = (CounterMonitorMBean)
+ MBeanServerInvocationHandler.newProxyInstance(
+ mbs, cmn, CounterMonitorMBean.class, true);
+ ((NotificationEmitter) cm).addNotificationListener(
+ new Listener(), null, null);
+ cm.addObservedObject(name);
+ cm.setObservedAttribute("Counter");
+ cm.setGranularityPeriod(100);
+ cm.setInitThreshold(1);
+ cm.setOffset(offset);
+ cm.setModulus(5);
+ cm.setNotify(true);
+
+ // Start the monitor
+ //
+ System.out.println("\nStart monitoring...");
+ cm.start();
+
+ // Play with counter
+ //
+ for (int i = 0; i < counter.length; i++) {
+ mbean.setCounter(counter[i]);
+ System.out.println("\nCounter = " + mbean.getCounter());
+ Thread.sleep(300);
+ Integer derivedGaugeValue = (Integer) cm.getDerivedGauge(name);
+ System.out.println("Derived Gauge = " + derivedGaugeValue);
+ if (derivedGaugeValue.intValue() != derivedGauge[i]) {
+ System.out.println("Wrong derived gauge! Current value = " +
+ derivedGaugeValue + " Expected value = " + derivedGauge[i]);
+ System.out.println("\nStop monitoring...");
+ cm.stop();
+ throw new IllegalArgumentException("wrong derived gauge");
+ }
+ Number thresholdValue = cm.getThreshold(name);
+ System.out.println("Threshold = " + thresholdValue);
+ if (thresholdValue.intValue() != threshold[i]) {
+ System.out.println("Wrong threshold! Current value = " +
+ thresholdValue + " Expected value = " + threshold[i]);
+ System.out.println("\nStop monitoring...");
+ cm.stop();
+ throw new IllegalArgumentException("wrong threshold");
+ }
+ Thread.sleep(300);
+ }
+
+ // Stop the monitor
+ //
+ System.out.println("\nStop monitoring...");
+ cm.stop();
+ }
+
+ public static void main(String[] args) throws Exception {
+ runTest(1, counter1, derivedGauge1, threshold1);
+ runTest(3, counter2, derivedGauge2, threshold2);
+ }
+}
diff --git a/test/javax/management/monitor/GaugeMonitorDeadlockTest.java b/test/javax/management/monitor/GaugeMonitorDeadlockTest.java
new file mode 100644
index 0000000..46fd7c2
--- /dev/null
+++ b/test/javax/management/monitor/GaugeMonitorDeadlockTest.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2005-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6303187
+ * @summary Test that no locks are held when a monitor attribute is sampled
+ * or notif delivered.
+ * @author Eamonn McManus
+ * @run clean GaugeMonitorDeadlockTest
+ * @run build GaugeMonitorDeadlockTest
+ * @run main GaugeMonitorDeadlockTest 1
+ * @run main GaugeMonitorDeadlockTest 2
+ * @run main GaugeMonitorDeadlockTest 3
+ * @run main GaugeMonitorDeadlockTest 4
+ */
+
+import java.lang.management.ManagementFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.management.Attribute;
+import javax.management.JMX;
+import javax.management.MBeanServer;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.monitor.GaugeMonitor;
+import javax.management.monitor.GaugeMonitorMBean;
+
+public class GaugeMonitorDeadlockTest {
+
+ public static void main(String[] args) throws Exception {
+ if (args.length != 1)
+ throw new Exception("Arg should be test number");
+ int testNo = Integer.parseInt(args[0]) - 1;
+ TestCase test = testCases[testNo];
+ System.out.println("Test: " + test.getDescription());
+ test.run();
+ System.out.println("Test passed");
+ }
+
+ private static enum When {IN_GET_ATTRIBUTE, IN_NOTIFY};
+
+ private static abstract class TestCase {
+ TestCase(String description, When when) {
+ this.description = description;
+ this.when = when;
+ }
+
+ void run() throws Exception {
+ final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ final ObjectName observedName = new ObjectName("a:b=c");
+ final ObjectName monitorName = new ObjectName("a:type=Monitor");
+ mbs.registerMBean(new GaugeMonitor(), monitorName);
+ final GaugeMonitorMBean monitorProxy =
+ JMX.newMBeanProxy(mbs, monitorName, GaugeMonitorMBean.class);
+ final TestMBean observedProxy =
+ JMX.newMBeanProxy(mbs, observedName, TestMBean.class);
+
+ final Runnable sensitiveThing = new Runnable() {
+ public void run() {
+ doSensitiveThing(monitorProxy, observedName);
+ }
+ };
+
+ final Runnable nothing = new Runnable() {
+ public void run() {}
+ };
+
+ final Runnable withinGetAttribute =
+ (when == When.IN_GET_ATTRIBUTE) ? sensitiveThing : nothing;
+
+ mbs.registerMBean(new Test(withinGetAttribute), observedName);
+ monitorProxy.addObservedObject(observedName);
+ monitorProxy.setObservedAttribute("Thing");
+ monitorProxy.setThresholds(105, 100);
+ monitorProxy.setGranularityPeriod(10L); // 10 ms
+ monitorProxy.setNotifyHigh(true);
+ monitorProxy.setNotifyLow(true);
+ monitorProxy.start();
+
+ final int initGetCount = observedProxy.getGetCount();
+ int getCount = initGetCount;
+ for (int i = 0; i < 2000; i++) { // 2000 * 10 = 20 seconds
+ getCount = observedProxy.getGetCount();
+ if (getCount != initGetCount)
+ break;
+ Thread.sleep(10);
+ }
+ if (getCount <= initGetCount)
+ throw new Exception("Test failed: presumable deadlock");
+ // This won't show up as a deadlock in CTRL-\ or in
+ // ThreadMXBean.findDeadlockedThreads(), because they don't
+ // see that thread A is waiting for thread B (B.join()), and
+ // thread B is waiting for a lock held by thread A
+
+ // Now we know the monitor has observed the initial value,
+ // so if we want to test notify behaviour we can trigger by
+ // exceeding the threshold.
+ if (when == When.IN_NOTIFY) {
+ final AtomicInteger notifCount = new AtomicInteger();
+ final NotificationListener listener = new NotificationListener() {
+ public void handleNotification(Notification n, Object h) {
+ Thread t = new Thread(sensitiveThing);
+ t.start();
+ try {
+ t.join();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ notifCount.incrementAndGet();
+ }
+ };
+ mbs.addNotificationListener(monitorName, listener, null, null);
+ observedProxy.setThing(1000);
+ for (int i = 0; i < 2000 && notifCount.get() == 0; i++)
+ Thread.sleep(10);
+ if (notifCount.get() == 0)
+ throw new Exception("Test failed: presumable deadlock");
+ }
+
+ }
+
+ abstract void doSensitiveThing(GaugeMonitorMBean monitorProxy,
+ ObjectName observedName);
+
+ String getDescription() {
+ return description;
+ }
+
+ private final String description;
+ private final When when;
+ }
+
+ private static final TestCase[] testCases = {
+ new TestCase("Remove monitored MBean within monitored getAttribute",
+ When.IN_GET_ATTRIBUTE) {
+ @Override
+ void doSensitiveThing(GaugeMonitorMBean monitorProxy,
+ ObjectName observedName) {
+ monitorProxy.removeObservedObject(observedName);
+ }
+ },
+ new TestCase("Stop monitor within monitored getAttribute",
+ When.IN_GET_ATTRIBUTE) {
+ @Override
+ void doSensitiveThing(GaugeMonitorMBean monitorProxy,
+ ObjectName observedName) {
+ monitorProxy.stop();
+ }
+ },
+ new TestCase("Remove monitored MBean within threshold listener",
+ When.IN_NOTIFY) {
+ @Override
+ void doSensitiveThing(GaugeMonitorMBean monitorProxy,
+ ObjectName observedName) {
+ monitorProxy.removeObservedObject(observedName);
+ }
+ },
+ new TestCase("Stop monitor within threshold listener",
+ When.IN_NOTIFY) {
+ @Override
+ void doSensitiveThing(GaugeMonitorMBean monitorProxy,
+ ObjectName observedName) {
+ monitorProxy.stop();
+ }
+ },
+ };
+
+ public static interface TestMBean {
+ public int getThing();
+ public void setThing(int thing);
+ public int getGetCount();
+ }
+
+ public static class Test implements TestMBean {
+ public Test(Runnable runWithinGetAttribute) {
+ this.runWithinGetAttribute = runWithinGetAttribute;
+ }
+
+ public int getThing() {
+ Thread t = new Thread(runWithinGetAttribute);
+ t.start();
+ try {
+ t.join();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ getCount++;
+ return thing;
+ }
+
+ public void setThing(int thing) {
+ this.thing = thing;
+ }
+
+ public int getGetCount() {
+ return getCount;
+ }
+
+ private final Runnable runWithinGetAttribute;
+ private volatile int getCount;
+ private volatile int thing;
+ }
+}
diff --git a/test/javax/management/monitor/MBeanServerBuilderImpl.java b/test/javax/management/monitor/MBeanServerBuilderImpl.java
new file mode 100644
index 0000000..357331a
--- /dev/null
+++ b/test/javax/management/monitor/MBeanServerBuilderImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ */
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerBuilder;
+import javax.management.MBeanServerDelegate;
+import javax.management.remote.MBeanServerForwarder;
+
+/**
+ * MBeanServerBuilder that returns an MBeanServer which
+ * throws a RuntimeException in the getAttribute method.
+ */
+public class MBeanServerBuilderImpl extends MBeanServerBuilder {
+
+ private final MBeanServerBuilder inner;
+
+ public MBeanServerBuilderImpl() {
+ inner = new MBeanServerBuilder();
+ }
+
+ public MBeanServer newMBeanServer(String defaultDomain,
+ MBeanServer outer,
+ MBeanServerDelegate delegate) {
+ final MBeanServerForwarder mbsf =
+ MBeanServerForwarderInvocationHandler.newProxyInstance();
+
+ final MBeanServer innerMBeanServer =
+ inner.newMBeanServer(defaultDomain,
+ (outer == null ? mbsf : outer),
+ delegate);
+
+ mbsf.setMBeanServer(innerMBeanServer);
+ return mbsf;
+ }
+}
diff --git a/test/javax/management/monitor/MBeanServerForwarderInvocationHandler.java b/test/javax/management/monitor/MBeanServerForwarderInvocationHandler.java
new file mode 100644
index 0000000..22bf40b
--- /dev/null
+++ b/test/javax/management/monitor/MBeanServerForwarderInvocationHandler.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ */
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import javax.management.MBeanServer;
+import javax.management.remote.MBeanServerForwarder;
+
+public class MBeanServerForwarderInvocationHandler
+ implements InvocationHandler {
+
+ public static MBeanServerForwarder newProxyInstance() {
+
+ final InvocationHandler handler =
+ new MBeanServerForwarderInvocationHandler();
+
+ final Class[] interfaces =
+ new Class[] {MBeanServerForwarder.class};
+
+ Object proxy = Proxy.newProxyInstance(
+ MBeanServerForwarder.class.getClassLoader(),
+ interfaces,
+ handler);
+
+ return MBeanServerForwarder.class.cast(proxy);
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args)
+ throws Throwable {
+
+ final String methodName = method.getName();
+
+ if (methodName.equals("getMBeanServer")) {
+ return mbs;
+ }
+
+ if (methodName.equals("setMBeanServer")) {
+ if (args[0] == null)
+ throw new IllegalArgumentException("Null MBeanServer");
+ if (mbs != null)
+ throw new IllegalArgumentException("MBeanServer object " +
+ "already initialized");
+ mbs = (MBeanServer) args[0];
+ return null;
+ }
+
+ if (methodName.equals("getAttribute") && exception != null) {
+ throw exception;
+ }
+
+ return method.invoke(mbs, args);
+ }
+
+ public void setGetAttributeException(Exception exception) {
+ this.exception = exception;
+ }
+
+ private Exception exception;
+ private MBeanServer mbs;
+}
diff --git a/test/javax/management/monitor/MultiMonitorTest.java b/test/javax/management/monitor/MultiMonitorTest.java
new file mode 100644
index 0000000..4594c5d
--- /dev/null
+++ b/test/javax/management/monitor/MultiMonitorTest.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4984057
+ * @summary Test that monitors can sample a large number of attributes
+ * @author Eamonn McManus
+ * @run clean MultiMonitorTest
+ * @run build MultiMonitorTest
+ * @run main MultiMonitorTest
+ */
+
+import java.util.*;
+import javax.management.*;
+import javax.management.monitor.*;
+
+/* We create N MBeans and three monitors, one for each different
+ monitor type. Each monitor monitors a single attribute in each of
+ the N MBeans. We arrange for the trigger condition to be
+ satisfied, so the listener we register on each monitor should get N
+ notifications. */
+public class MultiMonitorTest {
+ static final int N = 100;
+ static final ObjectName[] mbeanNames = new ObjectName[N];
+ static final Monitored[] monitored = new Monitored[N];
+ static final int COUNTER_THRESHOLD = 1000;
+ static final int OVER_COUNTER_THRESHOLD = 2000;
+ static final double GAUGE_THRESHOLD = 1000.0;
+ static final double OVER_GAUGE_THRESHOLD = 2000.0;
+ static final String STRING_TO_COMPARE = "chou";
+ static final String DIFFERENT_STRING = "chevre";
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("Test that monitors can sample a large " +
+ "number of attributes");
+
+ final MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ for (int i = 0; i < N; i++) {
+ mbeanNames[i] = new ObjectName(":type=Monitored,instance=" + i);
+ monitored[i] = new Monitored();
+ mbs.registerMBean(monitored[i], mbeanNames[i]);
+ }
+ final ObjectName counterMonitor =
+ new ObjectName(":type=CounterMonitor");
+ final ObjectName gaugeMonitor =
+ new ObjectName(":type=GaugeMonitor");
+ final ObjectName stringMonitor =
+ new ObjectName(":type=StringMonitor");
+ final ObjectName[] monitorNames =
+ new ObjectName[] {counterMonitor, gaugeMonitor, stringMonitor};
+ final String[] attrNames =
+ new String[] {"CounterValue", "GaugeValue", "StringValue"};
+ mbs.createMBean(CounterMonitor.class.getName(), counterMonitor);
+ mbs.createMBean(GaugeMonitor.class.getName(), gaugeMonitor);
+ mbs.createMBean(StringMonitor.class.getName(), stringMonitor);
+ final CounterMonitorMBean counterProxy = (CounterMonitorMBean)
+ MBeanServerInvocationHandler
+ .newProxyInstance(mbs, counterMonitor, CounterMonitorMBean.class,
+ false);
+ final GaugeMonitorMBean gaugeProxy = (GaugeMonitorMBean)
+ MBeanServerInvocationHandler
+ .newProxyInstance(mbs, gaugeMonitor, GaugeMonitorMBean.class,
+ false);
+ final StringMonitorMBean stringProxy = (StringMonitorMBean)
+ MBeanServerInvocationHandler
+ .newProxyInstance(mbs, stringMonitor, StringMonitorMBean.class,
+ false);
+ final MonitorMBean[] proxies = new MonitorMBean[] {
+ counterProxy, gaugeProxy, stringProxy,
+ };
+ for (int i = 0; i < 3; i++) {
+ proxies[i].setGranularityPeriod(1);
+ proxies[i].setObservedAttribute(attrNames[i]);
+ for (int j = 0; j < N; j++)
+ proxies[i].addObservedObject(mbeanNames[j]);
+ }
+
+ final CountListener[] listeners = new CountListener[] {
+ new CountListener(), new CountListener(), new CountListener()
+ };
+ for (int i = 0; i < 3; i++) {
+ mbs.addNotificationListener(monitorNames[i], listeners[i],
+ null, null);
+ }
+
+ counterProxy.setInitThreshold(new Integer(COUNTER_THRESHOLD));
+ counterProxy.setNotify(true);
+ gaugeProxy.setThresholds(new Double(GAUGE_THRESHOLD), new Double(0.0));
+ gaugeProxy.setNotifyHigh(true);
+ stringProxy.setStringToCompare(STRING_TO_COMPARE);
+ stringProxy.setNotifyDiffer(true);
+
+ // A couple of granularity periods to detect bad behaviour
+ Thread.sleep(2);
+
+ if (!listenersAreAll(0, listeners)) {
+ System.out.println("TEST FAILED: listeners not all 0");
+ System.exit(1);
+ }
+
+ for (int i = 0; i < 3; i++)
+ proxies[i].start();
+
+ long startTime = System.currentTimeMillis();
+ while (!listenersAreAll(N, listeners)
+ && System.currentTimeMillis() < startTime + 5000)
+ Thread.sleep(1);
+
+ // More time for bad behaviour
+ Thread.sleep(1000);
+
+ if (!listenersAreAll(N, listeners)) {
+ System.out.print("TEST FAILED: listener counts wrong:");
+ for (int i = 0; i < listeners.length; i++)
+ System.out.print(" " + listeners[i].getCount());
+ System.out.println();
+ System.exit(1);
+ }
+
+ for (int i = 0; i < 3; i++) {
+ proxies[i].stop();
+ for (int j = 0; j < N; j++)
+ proxies[i].removeObservedObject(mbeanNames[j]);
+ ObjectName[] observed = proxies[i].getObservedObjects();
+ if (observed.length != 0) {
+ System.out.println("TEST FAILED: not all observed objects " +
+ "removed: " + Arrays.asList(observed));
+ System.exit(1);
+ }
+ }
+
+ System.out.println("Test passed");
+ }
+
+ public static interface MonitoredMBean {
+ public int getCounterValue();
+ public double getGaugeValue();
+ public String getStringValue();
+ }
+
+ public static class Monitored implements MonitoredMBean {
+ /* We give a small random number of normal readings (possibly
+ zero) before giving a reading that provokes a
+ notification. */
+ private int okCounter = randomInt(5);
+ private int okGauge = randomInt(5);
+ private int okString = randomInt(5);
+
+ public synchronized int getCounterValue() {
+ if (--okCounter >= 0)
+ return 0;
+ else
+ return OVER_COUNTER_THRESHOLD;
+ }
+
+ public synchronized double getGaugeValue() {
+ if (--okGauge >= 0)
+ return 0.0;
+ else
+ return OVER_GAUGE_THRESHOLD;
+ }
+
+ public synchronized String getStringValue() {
+ if (--okString >= 0)
+ return STRING_TO_COMPARE;
+ else
+ return DIFFERENT_STRING;
+ }
+ }
+
+ public static class CountListener implements NotificationListener {
+ private int count;
+
+ public synchronized void handleNotification(Notification n, Object h) {
+ if (!(n instanceof MonitorNotification)) {
+ System.out.println("TEST FAILED: bad notif: " +
+ n.getClass().getName());
+ System.exit(1);
+ }
+ if (n.getType().indexOf("error") >= 0) {
+ System.out.println("TEST FAILED: error notif: " + n.getType());
+ System.exit(1);
+ }
+ count++;
+ }
+
+ public synchronized int getCount() {
+ return count;
+ }
+ }
+
+ private static boolean listenersAreAll(int n, CountListener[] listeners) {
+ for (int i = 0; i < listeners.length; i++) {
+ if (listeners[i].getCount() != n)
+ return false;
+ }
+ return true;
+ }
+
+ private static final Random random = new Random();
+ static synchronized int randomInt(int n) {
+ return random.nextInt(n);
+ }
+}
diff --git a/test/javax/management/monitor/NonComparableAttributeValueTest.java b/test/javax/management/monitor/NonComparableAttributeValueTest.java
new file mode 100644
index 0000000..ca12156
--- /dev/null
+++ b/test/javax/management/monitor/NonComparableAttributeValueTest.java
@@ -0,0 +1,353 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6273541
+ * @summary Test that the counter/gauge/string monitors emit a
+ * jmx.monitor.error.type notification when the attribute
+ * being monitored returns a non comparable value.
+ * @author Luis-Miguel Alventosa
+ * @run clean NonComparableAttributeValueTest
+ * @run build NonComparableAttributeValueTest
+ * @run main NonComparableAttributeValueTest
+ */
+
+import javax.management.*;
+import javax.management.monitor.*;
+
+public class NonComparableAttributeValueTest implements NotificationListener {
+
+ // Flag to notify that a message has been received
+ private boolean messageReceived = false;
+
+ // MBean class
+ public class ObservedObject implements ObservedObjectMBean {
+ public Object getIntegerAttribute() {
+ return new Object();
+ }
+ public Object getStringAttribute() {
+ return new Object();
+ }
+ }
+
+ // MBean interface
+ public interface ObservedObjectMBean {
+ public Object getIntegerAttribute();
+ public Object getStringAttribute();
+ }
+
+ // Notification handler
+ public void handleNotification(Notification notification,
+ Object handback) {
+ MonitorNotification n = (MonitorNotification) notification;
+ echo("\tInside handleNotification...");
+ String type = n.getType();
+ try {
+ if (type.equals(
+ MonitorNotification.OBSERVED_ATTRIBUTE_TYPE_ERROR)) {
+ echo("\t\t" + n.getObservedAttribute() + " is null");
+ echo("\t\tDerived Gauge = " + n.getDerivedGauge());
+ echo("\t\tTrigger = " + n.getTrigger());
+ messageReceived = true;
+ } else {
+ echo("\t\tSkipping notification of type: " + type);
+ }
+ } catch (Exception e) {
+ echo("\tError in handleNotification!");
+ e.printStackTrace(System.out);
+ }
+ }
+
+ /**
+ * Update the counter and check for notifications
+ */
+ public int counterMonitorNotification() throws Exception {
+
+ CounterMonitor counterMonitor = null;
+ try {
+ MBeanServer server = MBeanServerFactory.newMBeanServer();
+
+ String domain = server.getDefaultDomain();
+
+ // Create a new CounterMonitor MBean and add it to the MBeanServer.
+ //
+ echo(">>> CREATE a new CounterMonitor MBean");
+ ObjectName counterMonitorName = new ObjectName(
+ domain + ":type=" + CounterMonitor.class.getName());
+ counterMonitor = new CounterMonitor();
+ server.registerMBean(counterMonitor, counterMonitorName);
+
+ echo(">>> ADD a listener to the CounterMonitor");
+ counterMonitor.addNotificationListener(this, null, null);
+
+ //
+ // MANAGEMENT OF A STANDARD MBEAN
+ //
+
+ echo(">>> CREATE a new ObservedObject MBean");
+
+ ObjectName obsObjName =
+ ObjectName.getInstance(domain + ":type=ObservedObject");
+ ObservedObject obsObj = new ObservedObject();
+ server.registerMBean(obsObj, obsObjName);
+
+ echo(">>> SET the attributes of the CounterMonitor:");
+
+ counterMonitor.addObservedObject(obsObjName);
+ echo("\tATTRIBUTE \"ObservedObject\" = " + obsObjName);
+
+ counterMonitor.setObservedAttribute("IntegerAttribute");
+ echo("\tATTRIBUTE \"ObservedAttribute\" = IntegerAttribute");
+
+ counterMonitor.setNotify(true);
+ echo("\tATTRIBUTE \"NotifyFlag\" = true");
+
+ Integer threshold = 2;
+ counterMonitor.setInitThreshold(threshold);
+ echo("\tATTRIBUTE \"Threshold\" = " + threshold);
+
+ int granularityperiod = 500;
+ counterMonitor.setGranularityPeriod(granularityperiod);
+ echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
+
+ echo(">>> START the CounterMonitor");
+ counterMonitor.start();
+
+ // Wait for granularity period (multiplied by 2 for sure)
+ //
+ Thread.sleep(granularityperiod * 2);
+
+ // Check if notification was received
+ //
+ if (messageReceived) {
+ echo("\tOK: CounterMonitor notification received");
+ } else {
+ echo("\tKO: CounterMonitor notification missed or not emitted");
+ return 1;
+ }
+ } finally {
+ if (counterMonitor != null)
+ counterMonitor.stop();
+ }
+
+ return 0;
+ }
+
+ /**
+ * Update the gauge and check for notifications
+ */
+ public int gaugeMonitorNotification() throws Exception {
+
+ GaugeMonitor gaugeMonitor = null;
+ try {
+ MBeanServer server = MBeanServerFactory.newMBeanServer();
+
+ String domain = server.getDefaultDomain();
+
+ // Create a new GaugeMonitor MBean and add it to the MBeanServer.
+ //
+ echo(">>> CREATE a new GaugeMonitor MBean");
+ ObjectName gaugeMonitorName = new ObjectName(
+ domain + ":type=" + GaugeMonitor.class.getName());
+ gaugeMonitor = new GaugeMonitor();
+ server.registerMBean(gaugeMonitor, gaugeMonitorName);
+
+ echo(">>> ADD a listener to the GaugeMonitor");
+ gaugeMonitor.addNotificationListener(this, null, null);
+
+ //
+ // MANAGEMENT OF A STANDARD MBEAN
+ //
+
+ echo(">>> CREATE a new ObservedObject MBean");
+
+ ObjectName obsObjName =
+ ObjectName.getInstance(domain + ":type=ObservedObject");
+ ObservedObject obsObj = new ObservedObject();
+ server.registerMBean(obsObj, obsObjName);
+
+ echo(">>> SET the attributes of the GaugeMonitor:");
+
+ gaugeMonitor.addObservedObject(obsObjName);
+ echo("\tATTRIBUTE \"ObservedObject\" = " + obsObjName);
+
+ gaugeMonitor.setObservedAttribute("IntegerAttribute");
+ echo("\tATTRIBUTE \"ObservedAttribute\" = IntegerAttribute");
+
+ gaugeMonitor.setNotifyLow(false);
+ gaugeMonitor.setNotifyHigh(true);
+ echo("\tATTRIBUTE \"Notify Low Flag\" = false");
+ echo("\tATTRIBUTE \"Notify High Flag\" = true");
+
+ Double highThreshold = 3.0, lowThreshold = 2.5;
+ gaugeMonitor.setThresholds(highThreshold, lowThreshold);
+ echo("\tATTRIBUTE \"Low Threshold\" = " + lowThreshold);
+ echo("\tATTRIBUTE \"High Threshold\" = " + highThreshold);
+
+ int granularityperiod = 500;
+ gaugeMonitor.setGranularityPeriod(granularityperiod);
+ echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
+
+ echo(">>> START the GaugeMonitor");
+ gaugeMonitor.start();
+
+ // Wait for granularity period (multiplied by 2 for sure)
+ //
+ Thread.sleep(granularityperiod * 2);
+
+ // Check if notification was received
+ //
+ if (messageReceived) {
+ echo("\tOK: GaugeMonitor notification received");
+ } else {
+ echo("\tKO: GaugeMonitor notification missed or not emitted");
+ return 1;
+ }
+ } finally {
+ if (gaugeMonitor != null)
+ gaugeMonitor.stop();
+ }
+
+ return 0;
+ }
+
+ /**
+ * Update the string and check for notifications
+ */
+ public int stringMonitorNotification() throws Exception {
+
+ StringMonitor stringMonitor = null;
+ try {
+ MBeanServer server = MBeanServerFactory.newMBeanServer();
+
+ String domain = server.getDefaultDomain();
+
+ // Create a new StringMonitor MBean and add it to the MBeanServer.
+ //
+ echo(">>> CREATE a new StringMonitor MBean");
+ ObjectName stringMonitorName = new ObjectName(
+ domain + ":type=" + StringMonitor.class.getName());
+ stringMonitor = new StringMonitor();
+ server.registerMBean(stringMonitor, stringMonitorName);
+
+ echo(">>> ADD a listener to the StringMonitor");
+ stringMonitor.addNotificationListener(this, null, null);
+
+ //
+ // MANAGEMENT OF A STANDARD MBEAN
+ //
+
+ echo(">>> CREATE a new ObservedObject MBean");
+
+ ObjectName obsObjName =
+ ObjectName.getInstance(domain + ":type=ObservedObject");
+ ObservedObject obsObj = new ObservedObject();
+ server.registerMBean(obsObj, obsObjName);
+
+ echo(">>> SET the attributes of the StringMonitor:");
+
+ stringMonitor.addObservedObject(obsObjName);
+ echo("\tATTRIBUTE \"ObservedObject\" = " + obsObjName);
+
+ stringMonitor.setObservedAttribute("StringAttribute");
+ echo("\tATTRIBUTE \"ObservedAttribute\" = StringAttribute");
+
+ stringMonitor.setNotifyMatch(true);
+ echo("\tATTRIBUTE \"NotifyMatch\" = true");
+
+ stringMonitor.setNotifyDiffer(false);
+ echo("\tATTRIBUTE \"NotifyDiffer\" = false");
+
+ stringMonitor.setStringToCompare("do_match_now");
+ echo("\tATTRIBUTE \"StringToCompare\" = \"do_match_now\"");
+
+ int granularityperiod = 500;
+ stringMonitor.setGranularityPeriod(granularityperiod);
+ echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
+
+ echo(">>> START the StringMonitor");
+ stringMonitor.start();
+
+ // Wait for granularity period (multiplied by 2 for sure)
+ //
+ Thread.sleep(granularityperiod * 2);
+
+ // Check if notification was received
+ //
+ if (messageReceived) {
+ echo("\tOK: StringMonitor notification received");
+ } else {
+ echo("\tKO: StringMonitor notification missed or not emitted");
+ return 1;
+ }
+ } finally {
+ if (stringMonitor != null)
+ stringMonitor.stop();
+ }
+
+ return 0;
+ }
+
+ /**
+ * Test the monitor notifications.
+ */
+ public int monitorNotifications() throws Exception {
+ echo(">>> ----------------------------------------");
+ messageReceived = false;
+ int error = counterMonitorNotification();
+ echo(">>> ----------------------------------------");
+ messageReceived = false;
+ error += gaugeMonitorNotification();
+ echo(">>> ----------------------------------------");
+ messageReceived = false;
+ error += stringMonitorNotification();
+ echo(">>> ----------------------------------------");
+ return error;
+ }
+
+ /*
+ * Print message
+ */
+ private static void echo(String message) {
+ System.out.println(message);
+ }
+
+ /*
+ * Standalone entry point.
+ *
+ * Run the test and report to stdout.
+ */
+ public static void main (String args[]) throws Exception {
+ NonComparableAttributeValueTest test = new NonComparableAttributeValueTest();
+ int error = test.monitorNotifications();
+ if (error > 0) {
+ echo(">>> Unhappy Bye, Bye!");
+ throw new IllegalStateException("Test FAILED: Didn't get all " +
+ "the notifications that were " +
+ "expected by the test!");
+ } else {
+ echo(">>> Happy Bye, Bye!");
+ }
+ }
+}
diff --git a/test/javax/management/monitor/NullAttributeValueTest.java b/test/javax/management/monitor/NullAttributeValueTest.java
new file mode 100644
index 0000000..ae67650
--- /dev/null
+++ b/test/javax/management/monitor/NullAttributeValueTest.java
@@ -0,0 +1,353 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6200031
+ * @summary Test that the counter/gauge/string monitors emit a
+ * jmx.monitor.error.type notification when the attribute
+ * being monitored returns a null value.
+ * @author Luis-Miguel Alventosa
+ * @run clean NullAttributeValueTest
+ * @run build NullAttributeValueTest
+ * @run main NullAttributeValueTest
+ */
+
+import javax.management.*;
+import javax.management.monitor.*;
+
+public class NullAttributeValueTest implements NotificationListener {
+
+ // Flag to notify that a message has been received
+ private boolean messageReceived = false;
+
+ // MBean class
+ public class ObservedObject implements ObservedObjectMBean {
+ public Integer getIntegerAttribute() {
+ return null;
+ }
+ public String getStringAttribute() {
+ return null;
+ }
+ }
+
+ // MBean interface
+ public interface ObservedObjectMBean {
+ public Integer getIntegerAttribute();
+ public String getStringAttribute();
+ }
+
+ // Notification handler
+ public void handleNotification(Notification notification,
+ Object handback) {
+ MonitorNotification n = (MonitorNotification) notification;
+ echo("\tInside handleNotification...");
+ String type = n.getType();
+ try {
+ if (type.equals(
+ MonitorNotification.OBSERVED_ATTRIBUTE_TYPE_ERROR)) {
+ echo("\t\t" + n.getObservedAttribute() + " is null");
+ echo("\t\tDerived Gauge = " + n.getDerivedGauge());
+ echo("\t\tTrigger = " + n.getTrigger());
+ messageReceived = true;
+ } else {
+ echo("\t\tSkipping notification of type: " + type);
+ }
+ } catch (Exception e) {
+ echo("\tError in handleNotification!");
+ e.printStackTrace(System.out);
+ }
+ }
+
+ /**
+ * Update the counter and check for notifications
+ */
+ public int counterMonitorNotification() throws Exception {
+
+ CounterMonitor counterMonitor = null;
+ try {
+ MBeanServer server = MBeanServerFactory.newMBeanServer();
+
+ String domain = server.getDefaultDomain();
+
+ // Create a new CounterMonitor MBean and add it to the MBeanServer.
+ //
+ echo(">>> CREATE a new CounterMonitor MBean");
+ ObjectName counterMonitorName = new ObjectName(
+ domain + ":type=" + CounterMonitor.class.getName());
+ counterMonitor = new CounterMonitor();
+ server.registerMBean(counterMonitor, counterMonitorName);
+
+ echo(">>> ADD a listener to the CounterMonitor");
+ counterMonitor.addNotificationListener(this, null, null);
+
+ //
+ // MANAGEMENT OF A STANDARD MBEAN
+ //
+
+ echo(">>> CREATE a new ObservedObject MBean");
+
+ ObjectName obsObjName =
+ ObjectName.getInstance(domain + ":type=ObservedObject");
+ ObservedObject obsObj = new ObservedObject();
+ server.registerMBean(obsObj, obsObjName);
+
+ echo(">>> SET the attributes of the CounterMonitor:");
+
+ counterMonitor.addObservedObject(obsObjName);
+ echo("\tATTRIBUTE \"ObservedObject\" = " + obsObjName);
+
+ counterMonitor.setObservedAttribute("IntegerAttribute");
+ echo("\tATTRIBUTE \"ObservedAttribute\" = IntegerAttribute");
+
+ counterMonitor.setNotify(true);
+ echo("\tATTRIBUTE \"NotifyFlag\" = true");
+
+ Integer threshold = 2;
+ counterMonitor.setInitThreshold(threshold);
+ echo("\tATTRIBUTE \"Threshold\" = " + threshold);
+
+ int granularityperiod = 500;
+ counterMonitor.setGranularityPeriod(granularityperiod);
+ echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
+
+ echo(">>> START the CounterMonitor");
+ counterMonitor.start();
+
+ // Wait for granularity period (multiplied by 2 for sure)
+ //
+ Thread.sleep(granularityperiod * 2);
+
+ // Check if notification was received
+ //
+ if (messageReceived) {
+ echo("\tOK: CounterMonitor notification received");
+ } else {
+ echo("\tKO: CounterMonitor notification missed or not emitted");
+ return 1;
+ }
+ } finally {
+ if (counterMonitor != null)
+ counterMonitor.stop();
+ }
+
+ return 0;
+ }
+
+ /**
+ * Update the gauge and check for notifications
+ */
+ public int gaugeMonitorNotification() throws Exception {
+
+ GaugeMonitor gaugeMonitor = null;
+ try {
+ MBeanServer server = MBeanServerFactory.newMBeanServer();
+
+ String domain = server.getDefaultDomain();
+
+ // Create a new GaugeMonitor MBean and add it to the MBeanServer.
+ //
+ echo(">>> CREATE a new GaugeMonitor MBean");
+ ObjectName gaugeMonitorName = new ObjectName(
+ domain + ":type=" + GaugeMonitor.class.getName());
+ gaugeMonitor = new GaugeMonitor();
+ server.registerMBean(gaugeMonitor, gaugeMonitorName);
+
+ echo(">>> ADD a listener to the GaugeMonitor");
+ gaugeMonitor.addNotificationListener(this, null, null);
+
+ //
+ // MANAGEMENT OF A STANDARD MBEAN
+ //
+
+ echo(">>> CREATE a new ObservedObject MBean");
+
+ ObjectName obsObjName =
+ ObjectName.getInstance(domain + ":type=ObservedObject");
+ ObservedObject obsObj = new ObservedObject();
+ server.registerMBean(obsObj, obsObjName);
+
+ echo(">>> SET the attributes of the GaugeMonitor:");
+
+ gaugeMonitor.addObservedObject(obsObjName);
+ echo("\tATTRIBUTE \"ObservedObject\" = " + obsObjName);
+
+ gaugeMonitor.setObservedAttribute("IntegerAttribute");
+ echo("\tATTRIBUTE \"ObservedAttribute\" = IntegerAttribute");
+
+ gaugeMonitor.setNotifyLow(false);
+ gaugeMonitor.setNotifyHigh(true);
+ echo("\tATTRIBUTE \"Notify Low Flag\" = false");
+ echo("\tATTRIBUTE \"Notify High Flag\" = true");
+
+ Double highThreshold = 3.0, lowThreshold = 2.5;
+ gaugeMonitor.setThresholds(highThreshold, lowThreshold);
+ echo("\tATTRIBUTE \"Low Threshold\" = " + lowThreshold);
+ echo("\tATTRIBUTE \"High Threshold\" = " + highThreshold);
+
+ int granularityperiod = 500;
+ gaugeMonitor.setGranularityPeriod(granularityperiod);
+ echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
+
+ echo(">>> START the GaugeMonitor");
+ gaugeMonitor.start();
+
+ // Wait for granularity period (multiplied by 2 for sure)
+ //
+ Thread.sleep(granularityperiod * 2);
+
+ // Check if notification was received
+ //
+ if (messageReceived) {
+ echo("\tOK: GaugeMonitor notification received");
+ } else {
+ echo("\tKO: GaugeMonitor notification missed or not emitted");
+ return 1;
+ }
+ } finally {
+ if (gaugeMonitor != null)
+ gaugeMonitor.stop();
+ }
+
+ return 0;
+ }
+
+ /**
+ * Update the string and check for notifications
+ */
+ public int stringMonitorNotification() throws Exception {
+
+ StringMonitor stringMonitor = null;
+ try {
+ MBeanServer server = MBeanServerFactory.newMBeanServer();
+
+ String domain = server.getDefaultDomain();
+
+ // Create a new StringMonitor MBean and add it to the MBeanServer.
+ //
+ echo(">>> CREATE a new StringMonitor MBean");
+ ObjectName stringMonitorName = new ObjectName(
+ domain + ":type=" + StringMonitor.class.getName());
+ stringMonitor = new StringMonitor();
+ server.registerMBean(stringMonitor, stringMonitorName);
+
+ echo(">>> ADD a listener to the StringMonitor");
+ stringMonitor.addNotificationListener(this, null, null);
+
+ //
+ // MANAGEMENT OF A STANDARD MBEAN
+ //
+
+ echo(">>> CREATE a new ObservedObject MBean");
+
+ ObjectName obsObjName =
+ ObjectName.getInstance(domain + ":type=ObservedObject");
+ ObservedObject obsObj = new ObservedObject();
+ server.registerMBean(obsObj, obsObjName);
+
+ echo(">>> SET the attributes of the StringMonitor:");
+
+ stringMonitor.addObservedObject(obsObjName);
+ echo("\tATTRIBUTE \"ObservedObject\" = " + obsObjName);
+
+ stringMonitor.setObservedAttribute("StringAttribute");
+ echo("\tATTRIBUTE \"ObservedAttribute\" = StringAttribute");
+
+ stringMonitor.setNotifyMatch(true);
+ echo("\tATTRIBUTE \"NotifyMatch\" = true");
+
+ stringMonitor.setNotifyDiffer(false);
+ echo("\tATTRIBUTE \"NotifyDiffer\" = false");
+
+ stringMonitor.setStringToCompare("do_match_now");
+ echo("\tATTRIBUTE \"StringToCompare\" = \"do_match_now\"");
+
+ int granularityperiod = 500;
+ stringMonitor.setGranularityPeriod(granularityperiod);
+ echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
+
+ echo(">>> START the StringMonitor");
+ stringMonitor.start();
+
+ // Wait for granularity period (multiplied by 2 for sure)
+ //
+ Thread.sleep(granularityperiod * 2);
+
+ // Check if notification was received
+ //
+ if (messageReceived) {
+ echo("\tOK: StringMonitor notification received");
+ } else {
+ echo("\tKO: StringMonitor notification missed or not emitted");
+ return 1;
+ }
+ } finally {
+ if (stringMonitor != null)
+ stringMonitor.stop();
+ }
+
+ return 0;
+ }
+
+ /**
+ * Test the monitor notifications.
+ */
+ public int monitorNotifications() throws Exception {
+ echo(">>> ----------------------------------------");
+ messageReceived = false;
+ int error = counterMonitorNotification();
+ echo(">>> ----------------------------------------");
+ messageReceived = false;
+ error += gaugeMonitorNotification();
+ echo(">>> ----------------------------------------");
+ messageReceived = false;
+ error += stringMonitorNotification();
+ echo(">>> ----------------------------------------");
+ return error;
+ }
+
+ /*
+ * Print message
+ */
+ private static void echo(String message) {
+ System.out.println(message);
+ }
+
+ /*
+ * Standalone entry point.
+ *
+ * Run the test and report to stdout.
+ */
+ public static void main (String args[]) throws Exception {
+ NullAttributeValueTest test = new NullAttributeValueTest();
+ int error = test.monitorNotifications();
+ if (error > 0) {
+ echo(">>> Unhappy Bye, Bye!");
+ throw new IllegalStateException("Test FAILED: Didn't get all " +
+ "the notifications that were " +
+ "expected by the test!");
+ } else {
+ echo(">>> Happy Bye, Bye!");
+ }
+ }
+}
diff --git a/test/javax/management/monitor/ReflectionExceptionTest.java b/test/javax/management/monitor/ReflectionExceptionTest.java
new file mode 100644
index 0000000..c0a9ec9
--- /dev/null
+++ b/test/javax/management/monitor/ReflectionExceptionTest.java
@@ -0,0 +1,358 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6205072
+ * @summary Test that the jmx.monitor.error.runtime monitor notification
+ * is emitted when getAttribute throws ReflectionException.
+ * @author Luis-Miguel Alventosa
+ * @run clean ReflectionExceptionTest MBeanServerBuilderImpl
+ * MBeanServerForwarderInvocationHandler
+ * @run build ReflectionExceptionTest MBeanServerBuilderImpl
+ * MBeanServerForwarderInvocationHandler
+ * @run main ReflectionExceptionTest
+ */
+
+import java.lang.reflect.Proxy;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+import javax.management.monitor.CounterMonitor;
+import javax.management.monitor.GaugeMonitor;
+import javax.management.monitor.MonitorNotification;
+import javax.management.monitor.StringMonitor;
+
+public class ReflectionExceptionTest implements NotificationListener {
+
+ // MBean class
+ public class ObservedObject implements ObservedObjectMBean {
+ public Integer getIntegerAttribute() {
+ return i;
+ }
+ public void setIntegerAttribute(Integer i) {
+ this.i = i;
+ }
+ public String getStringAttribute() {
+ return s;
+ }
+ public void setStringAttribute(String s) {
+ this.s = s;
+ }
+ private Integer i = 1;
+ private String s = "dummy";
+ }
+
+ // MBean interface
+ public interface ObservedObjectMBean {
+ public Integer getIntegerAttribute();
+ public void setIntegerAttribute(Integer i);
+ public String getStringAttribute();
+ public void setStringAttribute(String s);
+ }
+
+ // Notification handler
+ public void handleNotification(Notification notification, Object handback) {
+ echo(">>> Received notification: " + notification);
+ if (notification instanceof MonitorNotification) {
+ String type = notification.getType();
+ if (type.equals(MonitorNotification.RUNTIME_ERROR)) {
+ MonitorNotification mn = (MonitorNotification) notification;
+ echo("\tType: " + mn.getType());
+ echo("\tTimeStamp: " + mn.getTimeStamp());
+ echo("\tObservedObject: " + mn.getObservedObject());
+ echo("\tObservedAttribute: " + mn.getObservedAttribute());
+ echo("\tDerivedGauge: " + mn.getDerivedGauge());
+ echo("\tTrigger: " + mn.getTrigger());
+ messageReceived = true;
+ }
+ }
+ }
+
+ /**
+ * Update the counter and check for notifications
+ */
+ public int counterMonitorNotification() throws Exception {
+
+ CounterMonitor counterMonitor = new CounterMonitor();
+ try {
+ // Create a new CounterMonitor MBean and add it to the MBeanServer.
+ //
+ echo(">>> CREATE a new CounterMonitor MBean");
+ ObjectName counterMonitorName = new ObjectName(
+ domain + ":type=" + CounterMonitor.class.getName());
+ server.registerMBean(counterMonitor, counterMonitorName);
+
+ echo(">>> ADD a listener to the CounterMonitor");
+ counterMonitor.addNotificationListener(this, null, null);
+
+ //
+ // MANAGEMENT OF A STANDARD MBEAN
+ //
+
+ echo(">>> SET the attributes of the CounterMonitor:");
+
+ counterMonitor.addObservedObject(obsObjName);
+ echo("\tATTRIBUTE \"ObservedObject\" = " + obsObjName);
+
+ counterMonitor.setObservedAttribute("IntegerAttribute");
+ echo("\tATTRIBUTE \"ObservedAttribute\" = IntegerAttribute");
+
+ counterMonitor.setNotify(false);
+ echo("\tATTRIBUTE \"NotifyFlag\" = false");
+
+ Integer threshold = 2;
+ counterMonitor.setInitThreshold(threshold);
+ echo("\tATTRIBUTE \"Threshold\" = " + threshold);
+
+ int granularityperiod = 500;
+ counterMonitor.setGranularityPeriod(granularityperiod);
+ echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
+
+ echo(">>> START the CounterMonitor");
+ counterMonitor.start();
+
+ // Wait for granularity period (multiplied by 2 for sure)
+ //
+ Thread.sleep(granularityperiod * 2);
+
+ // Check if notification was received
+ //
+ if (messageReceived) {
+ echo("\tOK: CounterMonitor got RUNTIME_ERROR notification!");
+ } else {
+ echo("\tKO: CounterMonitor did not get " +
+ "RUNTIME_ERROR notification!");
+ return 1;
+ }
+ } finally {
+ messageReceived = false;
+ if (counterMonitor != null)
+ counterMonitor.stop();
+ }
+
+ return 0;
+ }
+
+ /**
+ * Update the gauge and check for notifications
+ */
+ public int gaugeMonitorNotification() throws Exception {
+
+ GaugeMonitor gaugeMonitor = new GaugeMonitor();
+ try {
+ // Create a new GaugeMonitor MBean and add it to the MBeanServer.
+ //
+ echo(">>> CREATE a new GaugeMonitor MBean");
+ ObjectName gaugeMonitorName = new ObjectName(
+ domain + ":type=" + GaugeMonitor.class.getName());
+ server.registerMBean(gaugeMonitor, gaugeMonitorName);
+
+ echo(">>> ADD a listener to the GaugeMonitor");
+ gaugeMonitor.addNotificationListener(this, null, null);
+
+ //
+ // MANAGEMENT OF A STANDARD MBEAN
+ //
+
+ echo(">>> SET the attributes of the GaugeMonitor:");
+
+ gaugeMonitor.addObservedObject(obsObjName);
+ echo("\tATTRIBUTE \"ObservedObject\" = " + obsObjName);
+
+ gaugeMonitor.setObservedAttribute("IntegerAttribute");
+ echo("\tATTRIBUTE \"ObservedAttribute\" = IntegerAttribute");
+
+ gaugeMonitor.setNotifyLow(false);
+ gaugeMonitor.setNotifyHigh(false);
+ echo("\tATTRIBUTE \"Notify Low Flag\" = false");
+ echo("\tATTRIBUTE \"Notify High Flag\" = false");
+
+ Integer highThreshold = 3, lowThreshold = 2;
+ gaugeMonitor.setThresholds(highThreshold, lowThreshold);
+ echo("\tATTRIBUTE \"Low Threshold\" = " + lowThreshold);
+ echo("\tATTRIBUTE \"High Threshold\" = " + highThreshold);
+
+ int granularityperiod = 500;
+ gaugeMonitor.setGranularityPeriod(granularityperiod);
+ echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
+
+ echo(">>> START the GaugeMonitor");
+ gaugeMonitor.start();
+
+ // Wait for granularity period (multiplied by 2 for sure)
+ //
+ Thread.sleep(granularityperiod * 2);
+
+ // Check if notification was received
+ //
+ if (messageReceived) {
+ echo("\tOK: GaugeMonitor got RUNTIME_ERROR notification!");
+ } else {
+ echo("\tKO: GaugeMonitor did not get " +
+ "RUNTIME_ERROR notification!");
+ return 1;
+ }
+ } finally {
+ messageReceived = false;
+ if (gaugeMonitor != null)
+ gaugeMonitor.stop();
+ }
+
+ return 0;
+ }
+
+ /**
+ * Update the string and check for notifications
+ */
+ public int stringMonitorNotification() throws Exception {
+
+ StringMonitor stringMonitor = new StringMonitor();
+ try {
+ // Create a new StringMonitor MBean and add it to the MBeanServer.
+ //
+ echo(">>> CREATE a new StringMonitor MBean");
+ ObjectName stringMonitorName = new ObjectName(
+ domain + ":type=" + StringMonitor.class.getName());
+ server.registerMBean(stringMonitor, stringMonitorName);
+
+ echo(">>> ADD a listener to the StringMonitor");
+ stringMonitor.addNotificationListener(this, null, null);
+
+ //
+ // MANAGEMENT OF A STANDARD MBEAN
+ //
+
+ echo(">>> SET the attributes of the StringMonitor:");
+
+ stringMonitor.addObservedObject(obsObjName);
+ echo("\tATTRIBUTE \"ObservedObject\" = " + obsObjName);
+
+ stringMonitor.setObservedAttribute("StringAttribute");
+ echo("\tATTRIBUTE \"ObservedAttribute\" = StringAttribute");
+
+ stringMonitor.setNotifyMatch(false);
+ echo("\tATTRIBUTE \"NotifyMatch\" = false");
+
+ stringMonitor.setNotifyDiffer(false);
+ echo("\tATTRIBUTE \"NotifyDiffer\" = false");
+
+ stringMonitor.setStringToCompare("dummy");
+ echo("\tATTRIBUTE \"StringToCompare\" = \"dummy\"");
+
+ int granularityperiod = 500;
+ stringMonitor.setGranularityPeriod(granularityperiod);
+ echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
+
+ echo(">>> START the StringMonitor");
+ stringMonitor.start();
+
+ // Wait for granularity period (multiplied by 2 for sure)
+ //
+ Thread.sleep(granularityperiod * 2);
+
+ // Check if notification was received
+ //
+ if (messageReceived) {
+ echo("\tOK: StringMonitor got RUNTIME_ERROR notification!");
+ } else {
+ echo("\tKO: StringMonitor did not get " +
+ "RUNTIME_ERROR notification!");
+ return 1;
+ }
+ } finally {
+ messageReceived = false;
+ if (stringMonitor != null)
+ stringMonitor.stop();
+ }
+
+ return 0;
+ }
+
+ /**
+ * Test the monitor notifications.
+ */
+ public int monitorNotifications() throws Exception {
+
+ server = MBeanServerFactory.newMBeanServer();
+
+ MBeanServerForwarderInvocationHandler mbsfih =
+ (MBeanServerForwarderInvocationHandler)
+ Proxy.getInvocationHandler(server);
+
+ mbsfih.setGetAttributeException(
+ new ReflectionException(new RuntimeException(),
+ "Test ReflectionException"));
+
+ domain = server.getDefaultDomain();
+
+ obsObjName = ObjectName.getInstance(domain + ":type=ObservedObject");
+ server.registerMBean(new ObservedObject(), obsObjName);
+
+ echo(">>> ----------------------------------------");
+ int error = counterMonitorNotification();
+ echo(">>> ----------------------------------------");
+ error += gaugeMonitorNotification();
+ echo(">>> ----------------------------------------");
+ error += stringMonitorNotification();
+ echo(">>> ----------------------------------------");
+ return error;
+ }
+
+ /*
+ * Print message
+ */
+ private static void echo(String message) {
+ System.out.println(message);
+ }
+
+ /*
+ * Standalone entry point.
+ *
+ * Run the test and report to stdout.
+ */
+ public static void main (String args[]) throws Exception {
+ System.setProperty("javax.management.builder.initial",
+ MBeanServerBuilderImpl.class.getName());
+ ReflectionExceptionTest test = new ReflectionExceptionTest();
+ int error = test.monitorNotifications();
+ if (error > 0) {
+ echo(">>> Unhappy Bye, Bye!");
+ throw new IllegalStateException("Test FAILED: Didn't get all " +
+ "the notifications that were " +
+ "expected by the test!");
+ } else {
+ echo(">>> Happy Bye, Bye!");
+ }
+ }
+
+ // Flag to notify that a message has been received
+ private boolean messageReceived = false;
+
+ private MBeanServer server;
+ private ObjectName obsObjName;
+ private String domain;
+}
diff --git a/test/javax/management/monitor/RuntimeExceptionTest.java b/test/javax/management/monitor/RuntimeExceptionTest.java
new file mode 100644
index 0000000..c652e60
--- /dev/null
+++ b/test/javax/management/monitor/RuntimeExceptionTest.java
@@ -0,0 +1,356 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6200391
+ * @summary Test that the jmx.monitor.error.runtime monitor notification
+ * is emitted when getAttribute throws RuntimeException.
+ * @author Luis-Miguel Alventosa
+ * @run clean RuntimeExceptionTest MBeanServerBuilderImpl
+ * MBeanServerForwarderInvocationHandler
+ * @run build RuntimeExceptionTest MBeanServerBuilderImpl
+ * MBeanServerForwarderInvocationHandler
+ * @run main RuntimeExceptionTest
+ */
+
+import java.lang.reflect.Proxy;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.monitor.CounterMonitor;
+import javax.management.monitor.GaugeMonitor;
+import javax.management.monitor.MonitorNotification;
+import javax.management.monitor.StringMonitor;
+
+public class RuntimeExceptionTest implements NotificationListener {
+
+ // MBean class
+ public class ObservedObject implements ObservedObjectMBean {
+ public Integer getIntegerAttribute() {
+ return i;
+ }
+ public void setIntegerAttribute(Integer i) {
+ this.i = i;
+ }
+ public String getStringAttribute() {
+ return s;
+ }
+ public void setStringAttribute(String s) {
+ this.s = s;
+ }
+ private Integer i = 1;
+ private String s = "dummy";
+ }
+
+ // MBean interface
+ public interface ObservedObjectMBean {
+ public Integer getIntegerAttribute();
+ public void setIntegerAttribute(Integer i);
+ public String getStringAttribute();
+ public void setStringAttribute(String s);
+ }
+
+ // Notification handler
+ public void handleNotification(Notification notification, Object handback) {
+ echo(">>> Received notification: " + notification);
+ if (notification instanceof MonitorNotification) {
+ String type = notification.getType();
+ if (type.equals(MonitorNotification.RUNTIME_ERROR)) {
+ MonitorNotification mn = (MonitorNotification) notification;
+ echo("\tType: " + mn.getType());
+ echo("\tTimeStamp: " + mn.getTimeStamp());
+ echo("\tObservedObject: " + mn.getObservedObject());
+ echo("\tObservedAttribute: " + mn.getObservedAttribute());
+ echo("\tDerivedGauge: " + mn.getDerivedGauge());
+ echo("\tTrigger: " + mn.getTrigger());
+ messageReceived = true;
+ }
+ }
+ }
+
+ /**
+ * Update the counter and check for notifications
+ */
+ public int counterMonitorNotification() throws Exception {
+
+ CounterMonitor counterMonitor = new CounterMonitor();
+ try {
+ // Create a new CounterMonitor MBean and add it to the MBeanServer.
+ //
+ echo(">>> CREATE a new CounterMonitor MBean");
+ ObjectName counterMonitorName = new ObjectName(
+ domain + ":type=" + CounterMonitor.class.getName());
+ server.registerMBean(counterMonitor, counterMonitorName);
+
+ echo(">>> ADD a listener to the CounterMonitor");
+ counterMonitor.addNotificationListener(this, null, null);
+
+ //
+ // MANAGEMENT OF A STANDARD MBEAN
+ //
+
+ echo(">>> SET the attributes of the CounterMonitor:");
+
+ counterMonitor.addObservedObject(obsObjName);
+ echo("\tATTRIBUTE \"ObservedObject\" = " + obsObjName);
+
+ counterMonitor.setObservedAttribute("IntegerAttribute");
+ echo("\tATTRIBUTE \"ObservedAttribute\" = IntegerAttribute");
+
+ counterMonitor.setNotify(false);
+ echo("\tATTRIBUTE \"NotifyFlag\" = false");
+
+ Integer threshold = 2;
+ counterMonitor.setInitThreshold(threshold);
+ echo("\tATTRIBUTE \"Threshold\" = " + threshold);
+
+ int granularityperiod = 500;
+ counterMonitor.setGranularityPeriod(granularityperiod);
+ echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
+
+ echo(">>> START the CounterMonitor");
+ counterMonitor.start();
+
+ // Wait for granularity period (multiplied by 2 for sure)
+ //
+ Thread.sleep(granularityperiod * 2);
+
+ // Check if notification was received
+ //
+ if (messageReceived) {
+ echo("\tOK: CounterMonitor got RUNTIME_ERROR notification!");
+ } else {
+ echo("\tKO: CounterMonitor did not get " +
+ "RUNTIME_ERROR notification!");
+ return 1;
+ }
+ } finally {
+ messageReceived = false;
+ if (counterMonitor != null)
+ counterMonitor.stop();
+ }
+
+ return 0;
+ }
+
+ /**
+ * Update the gauge and check for notifications
+ */
+ public int gaugeMonitorNotification() throws Exception {
+
+ GaugeMonitor gaugeMonitor = new GaugeMonitor();
+ try {
+ // Create a new GaugeMonitor MBean and add it to the MBeanServer.
+ //
+ echo(">>> CREATE a new GaugeMonitor MBean");
+ ObjectName gaugeMonitorName = new ObjectName(
+ domain + ":type=" + GaugeMonitor.class.getName());
+ server.registerMBean(gaugeMonitor, gaugeMonitorName);
+
+ echo(">>> ADD a listener to the GaugeMonitor");
+ gaugeMonitor.addNotificationListener(this, null, null);
+
+ //
+ // MANAGEMENT OF A STANDARD MBEAN
+ //
+
+ echo(">>> SET the attributes of the GaugeMonitor:");
+
+ gaugeMonitor.addObservedObject(obsObjName);
+ echo("\tATTRIBUTE \"ObservedObject\" = " + obsObjName);
+
+ gaugeMonitor.setObservedAttribute("IntegerAttribute");
+ echo("\tATTRIBUTE \"ObservedAttribute\" = IntegerAttribute");
+
+ gaugeMonitor.setNotifyLow(false);
+ gaugeMonitor.setNotifyHigh(false);
+ echo("\tATTRIBUTE \"Notify Low Flag\" = false");
+ echo("\tATTRIBUTE \"Notify High Flag\" = false");
+
+ Integer highThreshold = 3, lowThreshold = 2;
+ gaugeMonitor.setThresholds(highThreshold, lowThreshold);
+ echo("\tATTRIBUTE \"Low Threshold\" = " + lowThreshold);
+ echo("\tATTRIBUTE \"High Threshold\" = " + highThreshold);
+
+ int granularityperiod = 500;
+ gaugeMonitor.setGranularityPeriod(granularityperiod);
+ echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
+
+ echo(">>> START the GaugeMonitor");
+ gaugeMonitor.start();
+
+ // Wait for granularity period (multiplied by 2 for sure)
+ //
+ Thread.sleep(granularityperiod * 2);
+
+ // Check if notification was received
+ //
+ if (messageReceived) {
+ echo("\tOK: GaugeMonitor got RUNTIME_ERROR notification!");
+ } else {
+ echo("\tKO: GaugeMonitor did not get " +
+ "RUNTIME_ERROR notification!");
+ return 1;
+ }
+ } finally {
+ messageReceived = false;
+ if (gaugeMonitor != null)
+ gaugeMonitor.stop();
+ }
+
+ return 0;
+ }
+
+ /**
+ * Update the string and check for notifications
+ */
+ public int stringMonitorNotification() throws Exception {
+
+ StringMonitor stringMonitor = new StringMonitor();
+ try {
+ // Create a new StringMonitor MBean and add it to the MBeanServer.
+ //
+ echo(">>> CREATE a new StringMonitor MBean");
+ ObjectName stringMonitorName = new ObjectName(
+ domain + ":type=" + StringMonitor.class.getName());
+ server.registerMBean(stringMonitor, stringMonitorName);
+
+ echo(">>> ADD a listener to the StringMonitor");
+ stringMonitor.addNotificationListener(this, null, null);
+
+ //
+ // MANAGEMENT OF A STANDARD MBEAN
+ //
+
+ echo(">>> SET the attributes of the StringMonitor:");
+
+ stringMonitor.addObservedObject(obsObjName);
+ echo("\tATTRIBUTE \"ObservedObject\" = " + obsObjName);
+
+ stringMonitor.setObservedAttribute("StringAttribute");
+ echo("\tATTRIBUTE \"ObservedAttribute\" = StringAttribute");
+
+ stringMonitor.setNotifyMatch(false);
+ echo("\tATTRIBUTE \"NotifyMatch\" = false");
+
+ stringMonitor.setNotifyDiffer(false);
+ echo("\tATTRIBUTE \"NotifyDiffer\" = false");
+
+ stringMonitor.setStringToCompare("dummy");
+ echo("\tATTRIBUTE \"StringToCompare\" = \"dummy\"");
+
+ int granularityperiod = 500;
+ stringMonitor.setGranularityPeriod(granularityperiod);
+ echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
+
+ echo(">>> START the StringMonitor");
+ stringMonitor.start();
+
+ // Wait for granularity period (multiplied by 2 for sure)
+ //
+ Thread.sleep(granularityperiod * 2);
+
+ // Check if notification was received
+ //
+ if (messageReceived) {
+ echo("\tOK: StringMonitor got RUNTIME_ERROR notification!");
+ } else {
+ echo("\tKO: StringMonitor did not get " +
+ "RUNTIME_ERROR notification!");
+ return 1;
+ }
+ } finally {
+ messageReceived = false;
+ if (stringMonitor != null)
+ stringMonitor.stop();
+ }
+
+ return 0;
+ }
+
+ /**
+ * Test the monitor notifications.
+ */
+ public int monitorNotifications() throws Exception {
+
+ server = MBeanServerFactory.newMBeanServer();
+
+ MBeanServerForwarderInvocationHandler mbsfih =
+ (MBeanServerForwarderInvocationHandler)
+ Proxy.getInvocationHandler(server);
+
+ mbsfih.setGetAttributeException(
+ new RuntimeException("Test RuntimeException"));
+
+ domain = server.getDefaultDomain();
+
+ obsObjName = ObjectName.getInstance(domain + ":type=ObservedObject");
+ server.registerMBean(new ObservedObject(), obsObjName);
+
+ echo(">>> ----------------------------------------");
+ int error = counterMonitorNotification();
+ echo(">>> ----------------------------------------");
+ error += gaugeMonitorNotification();
+ echo(">>> ----------------------------------------");
+ error += stringMonitorNotification();
+ echo(">>> ----------------------------------------");
+ return error;
+ }
+
+ /*
+ * Print message
+ */
+ private static void echo(String message) {
+ System.out.println(message);
+ }
+
+ /*
+ * Standalone entry point.
+ *
+ * Run the test and report to stdout.
+ */
+ public static void main (String args[]) throws Exception {
+ System.setProperty("javax.management.builder.initial",
+ MBeanServerBuilderImpl.class.getName());
+ RuntimeExceptionTest test = new RuntimeExceptionTest();
+ int error = test.monitorNotifications();
+ if (error > 0) {
+ echo(">>> Unhappy Bye, Bye!");
+ throw new IllegalStateException("Test FAILED: Didn't get all " +
+ "the notifications that were " +
+ "expected by the test!");
+ } else {
+ echo(">>> Happy Bye, Bye!");
+ }
+ }
+
+ // Flag to notify that a message has been received
+ private boolean messageReceived = false;
+
+ private MBeanServer server;
+ private ObjectName obsObjName;
+ private String domain;
+}
diff --git a/test/javax/management/monitor/StartStopTest.java b/test/javax/management/monitor/StartStopTest.java
new file mode 100644
index 0000000..d168131
--- /dev/null
+++ b/test/javax/management/monitor/StartStopTest.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6222826
+ * @summary Test that tasks are cancelled properly when
+ * monitors are started and stopped in a loop.
+ * @author Luis-Miguel Alventosa
+ * @run clean StartStopTest
+ * @run build StartStopTest
+ * @run main/othervm/timeout=300 StartStopTest 1
+ * @run main/othervm/timeout=300 StartStopTest 2
+ * @run main/othervm/timeout=300 StartStopTest 3
+ * @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=5 StartStopTest 1
+ * @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=5 StartStopTest 2
+ * @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=5 StartStopTest 3
+ * @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=-5 StartStopTest 1
+ * @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=-5 StartStopTest 2
+ * @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=-5 StartStopTest 3
+ */
+
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.monitor.CounterMonitor;
+import javax.management.monitor.GaugeMonitor;
+import javax.management.monitor.Monitor;
+import javax.management.monitor.MonitorNotification;
+import javax.management.monitor.StringMonitor;
+
+public class StartStopTest {
+
+ static int maxPoolSize;
+ static final AtomicInteger counter = new AtomicInteger();
+
+ // MBean class
+ public class ObservedObject implements ObservedObjectMBean {
+ public boolean called = false;
+ public Integer getInteger() {
+ task("Integer");
+ return 0;
+ }
+ public Double getDouble() {
+ task("Double");
+ return 0.0;
+ }
+ public String getString() {
+ task("String");
+ return "";
+ }
+ private void task(String prop) {
+ called = true;
+ final int c = counter.incrementAndGet();
+ echo("\tTASK [" + c + "] in get" + prop);
+ }
+ }
+
+ // MBean interface
+ public interface ObservedObjectMBean {
+ public Integer getInteger();
+ public Double getDouble();
+ public String getString();
+ }
+
+ /**
+ * Run test
+ */
+ public int runTest(int monitorType) throws Exception {
+
+ int nTasks = maxPoolSize + 2;
+ ObjectName[] mbeanNames = new ObjectName[nTasks];
+ ObservedObject[] monitored = new ObservedObject[nTasks];
+ ObjectName[] monitorNames = new ObjectName[nTasks];
+ Monitor[] monitor = new Monitor[nTasks];
+ String[] attributes = { "Integer", "Double", "String" };
+
+ try {
+ echo(">>> CREATE MBeanServer");
+ MBeanServer server = MBeanServerFactory.newMBeanServer();
+
+ String domain = server.getDefaultDomain();
+
+ for (int i = 0; i < nTasks; i++) {
+ mbeanNames[i] =
+ new ObjectName(":type=ObservedObject,instance=" + (i + 1));
+ monitored[i] = new ObservedObject();
+ echo(">>> CREATE ObservedObject = " + mbeanNames[i].toString());
+ server.registerMBean(monitored[i], mbeanNames[i]);
+ switch (monitorType) {
+ case 1:
+ monitorNames[i] = new ObjectName(":type=CounterMonitor," +
+ "instance=" + (i + 1));
+ monitor[i] = new CounterMonitor();
+ break;
+ case 2:
+ monitorNames[i] = new ObjectName(":type=GaugeMonitor," +
+ "instance=" + (i + 1));
+ monitor[i] = new GaugeMonitor();
+ break;
+ case 3:
+ monitorNames[i] = new ObjectName(":type=StringMonitor," +
+ "instance=" + (i + 1));
+ monitor[i] = new StringMonitor();
+ break;
+ default:
+ echo("Unsupported monitor type");
+ return 1;
+ }
+ echo(">>> CREATE Monitor = " + monitorNames[i].toString());
+ server.registerMBean(monitor[i], monitorNames[i]);
+ monitor[i].addObservedObject(mbeanNames[i]);
+ monitor[i].setObservedAttribute(attributes[monitorType-1]);
+ monitor[i].setGranularityPeriod(50);
+ }
+
+ for (int j = 0; j < 2; j++) {
+ echo(">>> Start MONITORS");
+ for (int i = 0; i < nTasks; i++)
+ monitor[i].start();
+ echo(">>> MONITORS started");
+ Thread.sleep(500);
+ echo(">>> Check FLAGS true");
+ for (int i = 0; i < nTasks; i++)
+ if (!monitored[i].called) {
+ echo("KO: At least one attribute was not called");
+ return 1;
+ }
+ echo(">>> FLAGS checked true");
+ echo(">>> Stop MONITORS");
+ for (int i = 0; i < nTasks; i++)
+ monitor[i].stop();
+ echo(">>> MONITORS stopped");
+ Thread.sleep(500);
+ echo(">>> Set FLAGS to false");
+ for (int i = 0; i < nTasks; i++)
+ monitored[i].called = false;
+ echo(">>> FLAGS set to false");
+ echo(">>> Check FLAGS remain false");
+ for (int i = 0; i < nTasks; i++)
+ if (monitored[i].called) {
+ echo("KO: At least one attribute " +
+ "continued to get called");
+ return 1;
+ }
+ echo(">>> FLAGS checked false");
+ }
+ } finally {
+ for (int i = 0; i < nTasks; i++)
+ if (monitor[i] != null)
+ monitor[i].stop();
+ }
+
+ return 0;
+ }
+
+ /*
+ * Print message
+ */
+ private static void echo(String message) {
+ System.out.println(message);
+ }
+
+ /*
+ * Standalone entry point.
+ *
+ * Run the test and report to stdout.
+ */
+ public static void main (String args[]) throws Exception {
+ Integer size = Integer.getInteger("jmx.x.monitor.maximum.pool.size");
+ if (size == null) {
+ maxPoolSize = 10;
+ echo(">>> MAXIMUM POOL SIZE = 10 [default value]");
+ } else {
+ maxPoolSize = size.intValue() < 1 ? 1 : size.intValue();
+ echo(">>> MAXIMUM POOL SIZE = " + maxPoolSize);
+ }
+ StartStopTest test = new StartStopTest();
+ int error = test.runTest(Integer.parseInt(args[0]));
+ if (error > 0) {
+ echo(">>> Unhappy Bye, Bye!");
+ throw new IllegalStateException(
+ "Test FAILED: Unexpected Maximum Pool Size Overflow!");
+ } else {
+ echo(">>> Happy Bye, Bye!");
+ }
+ }
+}
diff --git a/test/javax/management/monitor/StringMonitorDeadlockTest.java b/test/javax/management/monitor/StringMonitorDeadlockTest.java
new file mode 100644
index 0000000..e059705
--- /dev/null
+++ b/test/javax/management/monitor/StringMonitorDeadlockTest.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6303187
+ * @summary Test that no locks are held when a monitor attribute is sampled
+ * or notif delivered.
+ * @author Eamonn McManus
+ * @run clean StringMonitorDeadlockTest
+ * @run build StringMonitorDeadlockTest
+ * @run main StringMonitorDeadlockTest 1
+ * @run main StringMonitorDeadlockTest 2
+ * @run main StringMonitorDeadlockTest 3
+ * @run main StringMonitorDeadlockTest 4
+ */
+
+import java.lang.management.ManagementFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.management.Attribute;
+import javax.management.JMX;
+import javax.management.MBeanServer;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.monitor.StringMonitor;
+import javax.management.monitor.StringMonitorMBean;
+
+public class StringMonitorDeadlockTest {
+
+ public static void main(String[] args) throws Exception {
+ if (args.length != 1)
+ throw new Exception("Arg should be test number");
+ int testNo = Integer.parseInt(args[0]) - 1;
+ TestCase test = testCases[testNo];
+ System.out.println("Test: " + test.getDescription());
+ test.run();
+ System.out.println("Test passed");
+ }
+
+ private static enum When {IN_GET_ATTRIBUTE, IN_NOTIFY};
+
+ private static abstract class TestCase {
+ TestCase(String description, When when) {
+ this.description = description;
+ this.when = when;
+ }
+
+ void run() throws Exception {
+ final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ final ObjectName observedName = new ObjectName("a:b=c");
+ final ObjectName monitorName = new ObjectName("a:type=Monitor");
+ mbs.registerMBean(new StringMonitor(), monitorName);
+ final StringMonitorMBean monitorProxy =
+ JMX.newMBeanProxy(mbs, monitorName, StringMonitorMBean.class);
+ final TestMBean observedProxy =
+ JMX.newMBeanProxy(mbs, observedName, TestMBean.class);
+
+ final Runnable sensitiveThing = new Runnable() {
+ public void run() {
+ doSensitiveThing(monitorProxy, observedName);
+ }
+ };
+
+ final Runnable nothing = new Runnable() {
+ public void run() {}
+ };
+
+ final Runnable withinGetAttribute =
+ (when == When.IN_GET_ATTRIBUTE) ? sensitiveThing : nothing;
+
+ mbs.registerMBean(new Test(withinGetAttribute), observedName);
+ monitorProxy.addObservedObject(observedName);
+ monitorProxy.setObservedAttribute("Thing");
+ monitorProxy.setStringToCompare("old");
+ monitorProxy.setGranularityPeriod(10L); // 10 ms
+ monitorProxy.setNotifyDiffer(true);
+ monitorProxy.start();
+
+ final int initGetCount = observedProxy.getGetCount();
+ int getCount = initGetCount;
+ for (int i = 0; i < 500; i++) { // 500 * 10 = 5 seconds
+ getCount = observedProxy.getGetCount();
+ if (getCount != initGetCount)
+ break;
+ Thread.sleep(10);
+ }
+ if (getCount <= initGetCount)
+ throw new Exception("Test failed: presumable deadlock");
+ // This won't show up as a deadlock in CTRL-\ or in
+ // ThreadMXBean.findDeadlockedThreads(), because they don't
+ // see that thread A is waiting for thread B (B.join()), and
+ // thread B is waiting for a lock held by thread A
+
+ // Now we know the monitor has observed the initial value,
+ // so if we want to test notify behaviour we can trigger by
+ // exceeding the threshold.
+ if (when == When.IN_NOTIFY) {
+ final AtomicInteger notifCount = new AtomicInteger();
+ final NotificationListener listener = new NotificationListener() {
+ public void handleNotification(Notification n, Object h) {
+ Thread t = new Thread(sensitiveThing);
+ t.start();
+ try {
+ t.join();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ notifCount.incrementAndGet();
+ }
+ };
+ mbs.addNotificationListener(monitorName, listener, null, null);
+ observedProxy.setThing("new");
+ for (int i = 0; i < 500 && notifCount.get() == 0; i++)
+ Thread.sleep(10);
+ if (notifCount.get() == 0)
+ throw new Exception("Test failed: presumable deadlock");
+ }
+
+ }
+
+ abstract void doSensitiveThing(StringMonitorMBean monitorProxy,
+ ObjectName observedName);
+
+ String getDescription() {
+ return description;
+ }
+
+ private final String description;
+ private final When when;
+ }
+
+ private static final TestCase[] testCases = {
+ new TestCase("Remove monitored MBean within monitored getAttribute",
+ When.IN_GET_ATTRIBUTE) {
+ @Override
+ void doSensitiveThing(StringMonitorMBean monitorProxy,
+ ObjectName observedName) {
+ monitorProxy.removeObservedObject(observedName);
+ }
+ },
+ new TestCase("Stop monitor within monitored getAttribute",
+ When.IN_GET_ATTRIBUTE) {
+ @Override
+ void doSensitiveThing(StringMonitorMBean monitorProxy,
+ ObjectName observedName) {
+ monitorProxy.stop();
+ }
+ },
+ new TestCase("Remove monitored MBean within threshold listener",
+ When.IN_NOTIFY) {
+ @Override
+ void doSensitiveThing(StringMonitorMBean monitorProxy,
+ ObjectName observedName) {
+ monitorProxy.removeObservedObject(observedName);
+ }
+ },
+ new TestCase("Stop monitor within threshold listener",
+ When.IN_NOTIFY) {
+ @Override
+ void doSensitiveThing(StringMonitorMBean monitorProxy,
+ ObjectName observedName) {
+ monitorProxy.stop();
+ }
+ },
+ };
+
+ public static interface TestMBean {
+ public String getThing();
+ public void setThing(String thing);
+ public int getGetCount();
+ }
+
+ public static class Test implements TestMBean {
+ public Test(Runnable runWithinGetAttribute) {
+ this.runWithinGetAttribute = runWithinGetAttribute;
+ }
+
+ public String getThing() {
+ Thread t = new Thread(runWithinGetAttribute);
+ t.start();
+ try {
+ t.join();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ getCount++;
+ return thing;
+ }
+
+ public void setThing(String thing) {
+ this.thing = thing;
+ }
+
+ public int getGetCount() {
+ return getCount;
+ }
+
+ private final Runnable runWithinGetAttribute;
+ private volatile int getCount;
+ private volatile String thing;
+ }
+}
diff --git a/test/javax/management/monitor/ThreadPoolAccTest.java b/test/javax/management/monitor/ThreadPoolAccTest.java
new file mode 100644
index 0000000..9e58007
--- /dev/null
+++ b/test/javax/management/monitor/ThreadPoolAccTest.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6222826
+ * @summary Test that each thread in the thread pool runs
+ * in the context of the monitor.start() caller.
+ * @author Luis-Miguel Alventosa
+ * @run clean ThreadPoolAccTest
+ * @run build ThreadPoolAccTest
+ * @run main ThreadPoolAccTest
+ */
+
+import java.security.AccessController;
+import java.security.Principal;
+import java.security.PrivilegedAction;
+import java.util.Set;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectName;
+import javax.management.monitor.CounterMonitor;
+import javax.management.monitor.GaugeMonitor;
+import javax.management.monitor.Monitor;
+import javax.management.monitor.StringMonitor;
+import javax.management.remote.JMXPrincipal;
+import javax.security.auth.Subject;
+
+public class ThreadPoolAccTest {
+
+ // MBean class
+ public class ObservedObject implements ObservedObjectMBean {
+ public String principal;
+ public Integer getInteger() {
+ setPrincipal();
+ return 0;
+ }
+ public Double getDouble() {
+ setPrincipal();
+ return 0.0;
+ }
+ public String getString() {
+ setPrincipal();
+ return "";
+ }
+ private void setPrincipal() {
+ Subject subject = Subject.getSubject(AccessController.getContext());
+ Set principals = subject.getPrincipals(JMXPrincipal.class);
+ principal = ((Principal) principals.iterator().next()).getName();
+ }
+ }
+
+ // MBean interface
+ public interface ObservedObjectMBean {
+ public Integer getInteger();
+ public Double getDouble();
+ public String getString();
+ }
+
+ /**
+ * Run test
+ */
+ public int runTest() throws Exception {
+
+ ObjectName[] mbeanNames = new ObjectName[6];
+ ObservedObject[] monitored = new ObservedObject[6];
+ ObjectName[] monitorNames = new ObjectName[6];
+ Monitor[] monitor = new Monitor[6];
+ String[] principals = { "role1", "role2" };
+ String[] attributes = { "Integer", "Double", "String" };
+
+ try {
+ echo(">>> CREATE MBeanServer");
+ MBeanServer server = MBeanServerFactory.newMBeanServer();
+
+ String domain = server.getDefaultDomain();
+
+ for (int i = 0; i < 6; i++) {
+ mbeanNames[i] =
+ new ObjectName(":type=ObservedObject,instance=" + i);
+ monitored[i] = new ObservedObject();
+ echo(">>> CREATE ObservedObject = " + mbeanNames[i].toString());
+ server.registerMBean(monitored[i], mbeanNames[i]);
+
+ switch (i) {
+ case 0:
+ case 3:
+ monitorNames[i] =
+ new ObjectName(":type=CounterMonitor,instance=" + i);
+ monitor[i] = new CounterMonitor();
+ break;
+ case 1:
+ case 4:
+ monitorNames[i] =
+ new ObjectName(":type=GaugeMonitor,instance=" + i);
+ monitor[i] = new GaugeMonitor();
+ break;
+ case 2:
+ case 5:
+ monitorNames[i] =
+ new ObjectName(":type=StringMonitor,instance=" + i);
+ monitor[i] = new StringMonitor();
+ break;
+ }
+
+ echo(">>> CREATE Monitor = " + monitorNames[i].toString());
+ server.registerMBean(monitor[i], monitorNames[i]);
+ monitor[i].addObservedObject(mbeanNames[i]);
+ monitor[i].setObservedAttribute(attributes[i % 3]);
+ monitor[i].setGranularityPeriod(500);
+ final Monitor m = monitor[i];
+ Subject subject = new Subject();
+ echo(">>> RUN Principal = " + principals[i / 3]);
+ subject.getPrincipals().add(new JMXPrincipal(principals[i / 3]));
+ PrivilegedAction action = new PrivilegedAction() {
+ public Object run() {
+ m.start();
+ return null;
+ }
+ };
+ Subject.doAs(subject, action);
+ }
+
+ // Wait for all tasks to be submitted
+ //
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ echo("I fell asleep but someone woke me up");
+ return 1;
+ }
+
+ // Check if task principal is correct
+ //
+ for (int i = 0; i < 6; i++) {
+ echo(">>> Monitor = " + monitorNames[i]);
+ echo(">>> ObservedObject = " +
+ monitor[i].getObservedObject());
+ echo(">>> ObservedAttribute = " +
+ monitor[i].getObservedAttribute());
+ echo(">>> Principal = " + monitored[i].principal);
+ if (monitored[i].principal.equals(principals[i / 3])) {
+ echo("\tOK: Got Expected Principal");
+ } else {
+ echo("\tKO: Got Unexpected Principal");
+ return 1;
+ }
+ }
+ } finally {
+ for (int i = 0; i < 6; i++)
+ if (monitor[i] != null)
+ monitor[i].stop();
+ }
+
+ return 0;
+ }
+
+ /*
+ * Print message
+ */
+ private static void echo(String message) {
+ System.out.println(message);
+ }
+
+ /*
+ * Standalone entry point.
+ *
+ * Run the test and report to stdout.
+ */
+ public static void main (String args[]) throws Exception {
+ ThreadPoolAccTest test = new ThreadPoolAccTest();
+ int error = test.runTest();
+ if (error > 0) {
+ echo(">>> Unhappy Bye, Bye!");
+ throw new IllegalStateException(
+ "Test FAILED: Monitor task ran on wrong security context!");
+ } else {
+ echo(">>> Happy Bye, Bye!");
+ }
+ }
+}
diff --git a/test/javax/management/monitor/ThreadPoolTest.java b/test/javax/management/monitor/ThreadPoolTest.java
new file mode 100644
index 0000000..dcb82d6
--- /dev/null
+++ b/test/javax/management/monitor/ThreadPoolTest.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2005-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6222826 6379712
+ * @summary Test that all monitors will be well started when sharing
+ * a single thread pool.
+ * @author Luis-Miguel Alventosa
+ * @run clean ThreadPoolTest
+ * @run build ThreadPoolTest
+ * @run main/othervm/timeout=300 ThreadPoolTest 1
+ * @run main/othervm/timeout=300 ThreadPoolTest 2
+ * @run main/othervm/timeout=300 ThreadPoolTest 3
+ * @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=5 ThreadPoolTest 1
+ * @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=5 ThreadPoolTest 2
+ * @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=5 ThreadPoolTest 3
+ * @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=-5 ThreadPoolTest 1
+ * @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=-5 ThreadPoolTest 2
+ * @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=-5 ThreadPoolTest 3
+ */
+
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.monitor.CounterMonitor;
+import javax.management.monitor.GaugeMonitor;
+import javax.management.monitor.Monitor;
+import javax.management.monitor.MonitorNotification;
+import javax.management.monitor.StringMonitor;
+
+public class ThreadPoolTest {
+
+ static int maxPoolSize;
+ static int nTasks;
+ private static Waiter waiter;
+
+ static final long MAX_WAITING_TIME = 10000;
+
+ // MBean class
+ public class ObservedObject implements ObservedObjectMBean {
+ private boolean called = false;
+ public Integer getInteger() {
+ inform("getInteger()");
+ return 0;
+ }
+ public Double getDouble() {
+ inform("getDouble()");
+ return 0.0;
+ }
+ public String getString() {
+ inform("getString()");
+ return "";
+ }
+ private void inform(String prop) {
+ synchronized(waiter) {
+ if (!called) {
+ called = true;
+ waiter.count();
+ }
+ }
+
+ echo(">>> TASK "+prop+" is called.");
+ }
+ }
+
+ // MBean interface
+ public interface ObservedObjectMBean {
+ public Integer getInteger();
+ public Double getDouble();
+ public String getString();
+ }
+
+ /**
+ * Run test
+ */
+ public int runTest(int monitorType) throws Exception {
+
+
+ ObjectName[] mbeanNames = new ObjectName[nTasks];
+ ObservedObject[] monitored = new ObservedObject[nTasks];
+ ObjectName[] monitorNames = new ObjectName[nTasks];
+ Monitor[] monitor = new Monitor[nTasks];
+ String[] attributes = { "Integer", "Double", "String" };
+
+ try {
+ echo(">>> CREATE MBeanServer");
+ MBeanServer server = MBeanServerFactory.newMBeanServer();
+
+ String domain = server.getDefaultDomain();
+
+ for (int i = 0; i < nTasks; i++) {
+ mbeanNames[i] =
+ new ObjectName(":type=ObservedObject,instance=" + (i + 1));
+ monitored[i] = new ObservedObject();
+ echo(">>> CREATE ObservedObject = " + mbeanNames[i].toString());
+ server.registerMBean(monitored[i], mbeanNames[i]);
+ switch (monitorType) {
+ case 1:
+ monitorNames[i] = new ObjectName(":type=CounterMonitor," +
+ "instance=" + (i + 1));
+ monitor[i] = new CounterMonitor();
+ break;
+ case 2:
+ monitorNames[i] = new ObjectName(":type=GaugeMonitor," +
+ "instance=" + (i + 1));
+ monitor[i] = new GaugeMonitor();
+ break;
+ case 3:
+ monitorNames[i] = new ObjectName(":type=StringMonitor," +
+ "instance=" + (i + 1));
+ monitor[i] = new StringMonitor();
+ break;
+ default:
+ echo("Unsupported monitor type");
+ return 1;
+ }
+ echo(">>> CREATE Monitor = " + monitorNames[i].toString());
+ server.registerMBean(monitor[i], monitorNames[i]);
+ monitor[i].addObservedObject(mbeanNames[i]);
+ monitor[i].setObservedAttribute(attributes[monitorType-1]);
+ monitor[i].setGranularityPeriod(50);
+ monitor[i].start();
+ }
+
+ if (!waiter.waiting(MAX_WAITING_TIME)) {
+ echo("Error, not all "+nTasks+" monitor tasks are called after "
+ +MAX_WAITING_TIME);
+ return 1;
+ }
+ } finally {
+ for (int i = 0; i < nTasks; i++)
+ if (monitor[i] != null)
+ monitor[i].stop();
+ }
+
+ echo("All "+nTasks+" monitors are called.");
+ return 0;
+ }
+
+ /*
+ * Print message
+ */
+ private static void echo(String message) {
+ System.out.println(message);
+ }
+
+ /*
+ * Standalone entry point.
+ *
+ * Run the test and report to stdout.
+ */
+ public static void main (String args[]) throws Exception {
+ Integer size = Integer.getInteger("jmx.x.monitor.maximum.pool.size");
+ if (size == null) {
+ maxPoolSize = 10;
+ echo(">>> MAXIMUM POOL SIZE = 10 [default value]");
+ } else {
+ maxPoolSize = size.intValue() < 1 ? 1 : size.intValue();
+ echo(">>> MAXIMUM POOL SIZE = " + maxPoolSize);
+ }
+
+ nTasks = maxPoolSize + 2;
+ waiter = new Waiter(nTasks);
+ ThreadPoolTest test = new ThreadPoolTest();
+
+ int error = test.runTest(Integer.parseInt(args[0]));
+ if (error > 0) {
+ echo(">>> Unhappy Bye, Bye!");
+ throw new IllegalStateException(
+ "Test FAILED: Unexpected Maximum Pool Size Overflow!");
+ } else {
+ echo(">>> Happy Bye, Bye!");
+ }
+ }
+
+ private static class Waiter {
+ public Waiter(int waitedNB) {
+ this.waitedNB = waitedNB;
+ }
+
+ public void count() {
+ synchronized(this) {
+ counted++;
+
+ if (counted == waitedNB) {
+ this.notifyAll();
+ }
+ }
+ }
+
+ public boolean waiting(long timeout) {
+ final long startTime = System.currentTimeMillis();
+ long toWait = timeout;
+
+ synchronized(this) {
+ while(counted < waitedNB && toWait > 0) {
+ try {
+ this.wait(toWait);
+ } catch (InterruptedException ire) {
+ break;
+ }
+
+ toWait = timeout -
+ (System.currentTimeMillis() - startTime);
+ }
+ }
+
+ return counted == waitedNB;
+ }
+
+ private int waitedNB;
+ private int counted = 0;
+ }
+}
diff --git a/test/javax/management/mxbean/AmbiguousConstructorTest.java b/test/javax/management/mxbean/AmbiguousConstructorTest.java
new file mode 100644
index 0000000..20ac695
--- /dev/null
+++ b/test/javax/management/mxbean/AmbiguousConstructorTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2005-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6175517 6278707
+ * @summary Test that ambiguous ConstructorProperties annotations are detected.
+ * @author Eamonn McManus
+ * @run clean AmbiguousConstructorTest
+ * @run build AmbiguousConstructorTest
+ * @run main AmbiguousConstructorTest
+ */
+
+import java.beans.ConstructorProperties;
+import java.io.InvalidObjectException;
+import javax.management.*;
+
+public class AmbiguousConstructorTest {
+ public static void main(String[] args) throws Exception {
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+
+ System.out.println("Unambiguous case:");
+ ObjectName unambigName = new ObjectName("d:type=Unambiguous");
+ mbs.registerMBean(new UnambiguousImpl(), unambigName);
+ System.out.println("...OK");
+
+ System.out.println("Ambiguous case:");
+ ObjectName ambigName = new ObjectName("d:type=Ambiguous");
+ boolean exception = false;
+ try {
+ mbs.registerMBean(new AmbiguousImpl(), ambigName);
+ } catch (Exception e) {
+ // TODO - check for the specific exception we should get.
+ // Currently exception happens in preRegister so we have
+ // RuntimeMBeanException -> IllegalArgumentException ->
+ // InvalidObjectException, where the IllegalArgumentException
+ // is thrown by MXSupport.MBeanDispatcher.visitAttribute when
+ // it calls ConvertingMethod.checkCallFromOpen
+ System.out.println("...OK, got expected exception:");
+ e.printStackTrace(System.out);
+ exception = true;
+ }
+ if (!exception) {
+ System.out.println("TEST FAILED: expected exception, got none");
+ throw new Exception("Did not get expected exception");
+ }
+
+ System.out.println("TEST PASSED");
+ }
+
+ public static class Unambiguous {
+ public byte getA() {return 0;}
+ public short getB() {return 0;}
+ public int getC() {return 0;}
+ public long getD() {return 0;}
+
+ @ConstructorProperties({"a", "b"})
+ public Unambiguous(byte a, short b) {}
+
+ @ConstructorProperties({"b", "c"})
+ public Unambiguous(short b, int c) {}
+
+ @ConstructorProperties({"a", "b", "c"})
+ public Unambiguous(byte a, short b, int c) {}
+ }
+
+ public static class Ambiguous {
+ public byte getA() {return 0;}
+ public short getB() {return 0;}
+ public int getC() {return 0;}
+ public long getD() {return 0;}
+
+ @ConstructorProperties({"a", "b"})
+ public Ambiguous(byte a, short b) {}
+
+ @ConstructorProperties({"b", "c"})
+ public Ambiguous(short b, int c) {}
+
+ @ConstructorProperties({"a", "b", "c", "d"})
+ public Ambiguous(byte a, short b, int c, long d) {}
+ }
+
+ public static interface UnambiguousMXBean {
+ public void setUnambiguous(Unambiguous x);
+ }
+
+ public static class UnambiguousImpl implements UnambiguousMXBean {
+ public void setUnambiguous(Unambiguous x) {}
+ }
+
+ public static interface AmbiguousMXBean {
+ public void setAmbiguous(Ambiguous x);
+ }
+
+ public static class AmbiguousImpl implements AmbiguousMXBean {
+ public void setAmbiguous(Ambiguous x) {}
+ }
+}
diff --git a/test/javax/management/mxbean/GenericArrayTypeTest.java b/test/javax/management/mxbean/GenericArrayTypeTest.java
new file mode 100644
index 0000000..b99ba96
--- /dev/null
+++ b/test/javax/management/mxbean/GenericArrayTypeTest.java
@@ -0,0 +1,362 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6292705
+ * @summary Test support for arrays in parameterized types.
+ * @author Luis-Miguel Alventosa
+ * @run clean GenericArrayTypeTest
+ * @run build GenericArrayTypeTest
+ * @run main GenericArrayTypeTest
+ */
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.MonitorInfo;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.management.JMX;
+import javax.management.MBeanServer;
+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 GenericArrayTypeTest {
+
+ public interface TestMXBean {
+
+ public String[] getT1();
+ public void setT1(String[] v);
+
+ public MonitorInfo[] getT2();
+ public void setT2(MonitorInfo[] v);
+
+ public Map<String,String[]> getT3();
+ public void setT3(Map<String,String[]> v);
+
+ public Map<String,MonitorInfo[]> getT4();
+ public void setT4(Map<String,MonitorInfo[]> v);
+
+ public Set<String[]> getT5();
+ public void setT5(Set<String[]> v);
+
+ public Set<MonitorInfo[]> getT6();
+ public void setT6(Set<MonitorInfo[]> v);
+
+ public List<String[]> getT7();
+ public void setT7(List<String[]> v);
+
+ public List<MonitorInfo[]> getT8();
+ public void setT8(List<MonitorInfo[]> v);
+
+ public Set<List<String[]>> getT9();
+ public void setT9(Set<List<String[]>> v);
+
+ public Set<List<MonitorInfo[]>> getT10();
+ public void setT10(Set<List<MonitorInfo[]>> v);
+
+ public Map<String,Set<List<String[]>>> getT11();
+ public void setT11(Map<String,Set<List<String[]>>> v);
+
+ public Map<String,Set<List<MonitorInfo[]>>> getT12();
+ public void setT12(Map<String,Set<List<MonitorInfo[]>>> v);
+ }
+
+ public static class Test implements TestMXBean {
+
+ public String[] getT1() {
+ return t1;
+ }
+ public void setT1(String[] v) {
+ t1 = v;
+ }
+ private String[] t1;
+
+ public MonitorInfo[] getT2() {
+ return t2;
+ }
+ public void setT2(MonitorInfo[] v) {
+ t2 = v;
+ }
+ private MonitorInfo[] t2;
+
+ public Map<String,String[]> getT3() {
+ return t3;
+ }
+ public void setT3(Map<String,String[]> v) {
+ t3 = v;
+ }
+ private Map<String,String[]> t3;
+
+ public Map<String,MonitorInfo[]> getT4() {
+ return t4;
+ }
+ public void setT4(Map<String,MonitorInfo[]> v) {
+ t4 = v;
+ }
+ private Map<String,MonitorInfo[]> t4;
+
+ public Set<String[]> getT5() {
+ return t5;
+ }
+ public void setT5(Set<String[]> v) {
+ t5 = v;
+ }
+ private Set<String[]> t5;
+
+ public Set<MonitorInfo[]> getT6() {
+ return t6;
+ }
+ public void setT6(Set<MonitorInfo[]> v) {
+ t6 = v;
+ }
+ private Set<MonitorInfo[]> t6;
+
+ public List<String[]> getT7() {
+ return t7;
+ }
+ public void setT7(List<String[]> v) {
+ t7 = v;
+ }
+ private List<String[]> t7;
+
+ public List<MonitorInfo[]> getT8() {
+ return t8;
+ }
+ public void setT8(List<MonitorInfo[]> v) {
+ t8 = v;
+ }
+ private List<MonitorInfo[]> t8;
+
+ public Set<List<String[]>> getT9() {
+ return t9;
+ }
+ public void setT9(Set<List<String[]>> v) {
+ t9 = v;
+ }
+ private Set<List<String[]>> t9;
+
+ public Set<List<MonitorInfo[]>> getT10() {
+ return t10;
+ }
+ public void setT10(Set<List<MonitorInfo[]>> v) {
+ t10 = v;
+ }
+ private Set<List<MonitorInfo[]>> t10;
+
+ public Map<String,Set<List<String[]>>> getT11() {
+ return t11;
+ }
+ public void setT11(Map<String,Set<List<String[]>>> v) {
+ t11 = v;
+ }
+ private Map<String,Set<List<String[]>>> t11;
+
+ public Map<String,Set<List<MonitorInfo[]>>> getT12() {
+ return t12;
+ }
+ public void setT12(Map<String,Set<List<MonitorInfo[]>>> v) {
+ t12 = v;
+ }
+ private Map<String,Set<List<MonitorInfo[]>>> t12;
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ int error = 0;
+ JMXConnector cc = null;
+ JMXConnectorServer cs = null;
+
+ try {
+ // Instantiate the MBean server
+ //
+ echo("\n>>> Create the MBean server");
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+
+ // Get default domain
+ //
+ echo("\n>>> Get the MBean server's default domain");
+ String domain = mbs.getDefaultDomain();
+ echo("\tDefault Domain = " + domain);
+
+ // Register TestMXBean
+ //
+ echo("\n>>> Register TestMXBean");
+ ObjectName name =
+ ObjectName.getInstance(domain + ":type=" + TestMXBean.class);
+ mbs.createMBean(Test.class.getName(), name);
+
+ // Create an RMI connector server
+ //
+ echo("\n>>> Create an RMI connector server");
+ JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://");
+ cs =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
+
+ // Start the RMI connector server
+ //
+ echo("\n>>> Start the RMI connector server");
+ cs.start();
+
+ // Create an RMI connector client
+ //
+ echo("\n>>> Create an RMI connector client");
+ cc = JMXConnectorFactory.connect(cs.getAddress(), null);
+ MBeanServerConnection mbsc = cc.getMBeanServerConnection();
+
+ // Create TestMXBean proxy
+ //
+ echo("\n>>> Create the TestMXBean proxy");
+ TestMXBean test = JMX.newMXBeanProxy(mbsc, name, TestMXBean.class);
+
+ // Play with proxy getters and setters
+ //
+ echo("\n>>> Play with proxy getters and setters");
+ String[] t1 = new String[] { "t1" };
+ MonitorInfo[] t2 = new MonitorInfo[] {
+ new MonitorInfo("dummy", 0, 0,
+ new StackTraceElement("dummy", "dummy", "dummy", 0)) };
+ Map<String,String[]> t3 = new HashMap<String,String[]>();
+ t3.put("key", t1);
+ Map<String,MonitorInfo[]> t4 = new HashMap<String,MonitorInfo[]>();
+ t4.put("key", t2);
+ Set<String[]> t5 = new HashSet<String[]>();
+ t5.add(t1);
+ Set<MonitorInfo[]> t6 = new HashSet<MonitorInfo[]>();
+ t6.add(t2);
+ List<String[]> t7 = new ArrayList<String[]>();
+ t7.add(t1);
+ List<MonitorInfo[]> t8 = new ArrayList<MonitorInfo[]>();
+ t8.add(t2);
+ Set<List<String[]>> t9 = new HashSet<List<String[]>>();
+ t9.add(t7);
+ Set<List<MonitorInfo[]>> t10 = new HashSet<List<MonitorInfo[]>>();
+ t10.add(t8);
+ Map<String,Set<List<String[]>>> t11 = new HashMap<String,Set<List<String[]>>>();
+ t11.put("key", t9);
+ Map<String,Set<List<MonitorInfo[]>>> t12 = new HashMap<String,Set<List<MonitorInfo[]>>>();
+ t12.put("key", t10);
+
+ test.setT1(t1);
+ test.setT2(t2);
+ test.setT3(t3);
+ test.setT4(t4);
+ test.setT5(t5);
+ test.setT6(t6);
+ test.setT7(t7);
+ test.setT8(t8);
+ test.setT9(t9);
+ test.setT10(t10);
+ test.setT11(t11);
+ test.setT12(t12);
+
+ String r;
+ String e1 = "t1";
+ String e2 = "dummy";
+ echo("\tT1 = " + test.getT1());
+ r = ((String[])test.getT1())[0];
+ echo("\tR1 = " + r);
+ if (!e1.equals(r)) error++;
+ echo("\tT2 = " + test.getT2());
+ r = ((MonitorInfo[])test.getT2())[0].getClassName();
+ echo("\tR2 = " + r);
+ if (!e2.equals(r)) error++;
+ echo("\tT3 = " + test.getT3());
+ r = ((String[])((Map<String,String[]>)test.getT3()).get("key"))[0];
+ echo("\tR3 = " + r);
+ if (!e1.equals(r)) error++;
+ echo("\tT4 = " + test.getT4());
+ r = ((MonitorInfo[])((Map<String,MonitorInfo[]>)test.getT4()).get("key"))[0].getClassName();
+ echo("\tR4 = " + r);
+ if (!e2.equals(r)) error++;
+ echo("\tT5 = " + test.getT5());
+ r = ((String[])((Set<String[]>)test.getT5()).iterator().next())[0];
+ echo("\tR5 = " + r);
+ if (!e1.equals(r)) error++;
+ echo("\tT6 = " + test.getT6());
+ r = ((MonitorInfo[])((Set<MonitorInfo[]>)test.getT6()).iterator().next())[0].getClassName();
+ echo("\tR6 = " + r);
+ if (!e2.equals(r)) error++;
+ echo("\tT7 = " + test.getT7());
+ r = ((String[])((List<String[]>)test.getT7()).get(0))[0];
+ echo("\tR7 = " + r);
+ if (!e1.equals(r)) error++;
+ echo("\tT8 = " + test.getT8());
+ r = ((MonitorInfo[])((List<MonitorInfo[]>)test.getT8()).get(0))[0].getClassName();
+ echo("\tR8 = " + r);
+ if (!e2.equals(r)) error++;
+ echo("\tT9 = " + test.getT9());
+ r = ((String[])((List<String[]>)((Set<List<String[]>>)test.getT9()).iterator().next()).get(0))[0];
+ echo("\tR9 = " + r);
+ if (!e1.equals(r)) error++;
+ echo("\tT10 = " + test.getT10());
+ r = ((MonitorInfo[])((List<MonitorInfo[]>)((Set<List<MonitorInfo[]>>)test.getT10()).iterator().next()).get(0))[0].getClassName();
+ echo("\tR10 = " + r);
+ if (!e2.equals(r)) error++;
+ echo("\tT11 = " + test.getT11());
+ r = ((String[])((List<String[]>)((Set<List<String[]>>)((Map<String,Set<List<String[]>>>)test.getT11()).get("key")).iterator().next()).get(0))[0];
+ echo("\tR11 = " + r);
+ if (!e1.equals(r)) error++;
+ echo("\tT12 = " + test.getT12());
+ r = ((MonitorInfo[])((List<MonitorInfo[]>)((Set<List<MonitorInfo[]>>)((Map<String,Set<List<MonitorInfo[]>>>)test.getT12()).get("key")).iterator().next()).get(0))[0].getClassName();
+ echo("\tR12 = " + r);
+ if (!e2.equals(r)) error++;
+ } catch (Exception e) {
+ e.printStackTrace(System.out);
+ error++;
+ } finally {
+ // Close client
+ //
+ echo("\n>>> Close the RMI connector client");
+ if (cc != null)
+ cc.close();
+
+ // Stop server
+ //
+ echo("\n>>> Stop the RMI connector server");
+ if (cs != null)
+ cs.stop();
+
+ echo("\n>>> Bye! Bye!");
+ }
+
+ if (error > 0) {
+ echo("\nTest failed! " + error + " errors.\n");
+ throw new IllegalArgumentException("Test failed");
+ } else {
+ echo("\nTest passed!\n");
+ }
+ }
+
+ private static void echo(String msg) {
+ System.out.println(msg);
+ }
+}
diff --git a/test/javax/management/mxbean/GenericTypeTest.java b/test/javax/management/mxbean/GenericTypeTest.java
new file mode 100644
index 0000000..a0fc66d
--- /dev/null
+++ b/test/javax/management/mxbean/GenericTypeTest.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6376416 6406447
+ * @summary Test use of generic types in MXBeans (mostly illegal).
+ * @author Eamonn McManus
+ * @run main GenericTypeTest
+ */
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.*;
+import javax.management.*;
+
+public class GenericTypeTest {
+ public static class Gen<T> {
+ public T getThing() {
+ return null;
+ }
+ }
+
+ // Illegal MXBeans:
+
+ public static interface GenTMXBean {
+ public <T> Gen<T> getFoo();
+ }
+
+ public static interface GenStringMXBean {
+ public Gen<String> getFoo();
+ }
+
+ public static class GenMethod {
+ public <T> Gen<T> getWhatever() {
+ return null;
+ }
+ }
+
+ public static interface GenMethodMXBean {
+ public GenMethod getFoo();
+ }
+
+ public static interface TypeVarMXBean {
+ public <T> List<T> getFoo();
+ }
+
+ private static final Class<?>[] illegalMXBeans = {
+ GenTMXBean.class, GenStringMXBean.class, GenMethodMXBean.class,
+ TypeVarMXBean.class,
+ };
+
+ // Legal MXBeans:
+
+// Not currently supported (see 6406447):
+// public static class ConcreteNoOverride extends Gen<String> {}
+//
+// public static interface ConcreteNoOverrideMXBean {
+// public ConcreteNoOverride getFoo();
+// }
+
+ public static class ConcreteOverride extends Gen<String> {
+ @Override
+ public String getThing() {
+ return super.getThing();
+ }
+ }
+
+ public static interface ConcreteOverrideMXBean {
+ public ConcreteOverride getFoo();
+ }
+
+ private static final Class<?>[] legalMXBeans = {
+ /*ConcreteNoOverrideMXBean.class,*/ ConcreteOverrideMXBean.class,
+ };
+
+ private static class NullInvocationHandler implements InvocationHandler {
+ public Object invoke(Object proxy, Method method, Object[] args)
+ throws Throwable {
+ return null;
+ }
+ }
+ private static final InvocationHandler nullInvocationHandler =
+ new NullInvocationHandler();
+
+ private static <T> T makeNullMXBean(Class<T> intf) throws Exception {
+ return intf.cast(Proxy.newProxyInstance(intf.getClassLoader(),
+ new Class<?>[] {intf},
+ nullInvocationHandler));
+ }
+
+ private static String failure;
+
+ public static void main(String[] args) throws Exception {
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ for (boolean legal : new boolean[] {false, true}) {
+ Class<?>[] intfs = legal ? legalMXBeans : illegalMXBeans;
+ for (Class<?> intf : intfs) {
+ String intfName = intf.getName();
+ System.out.println("Testing " + intfName);
+ Object mxbean = makeNullMXBean(intf);
+ ObjectName name = new ObjectName("test:type=" + intfName);
+ try {
+ mbs.registerMBean(mxbean, name);
+ if (!legal)
+ fail("Registering " + intfName + " should not succeed");
+ } catch (NotCompliantMBeanException e) {
+ if (legal)
+ failX("Registering " + intfName + " should succeed", e);
+ } catch (Exception e) {
+ if (legal)
+ failX("Registering " + intfName + " should succeed", e);
+ else {
+ failX("Registering " + intfName + " should produce " +
+ "NotCompliantMBeanException", e);
+ }
+ }
+ }
+ }
+ if (failure != null)
+ throw new Exception("TEST FAILED: " + failure);
+ System.out.println("Test passed");
+ }
+
+ private static void fail(String msg) {
+ System.out.println("FAILED: " + msg);
+ failure = msg;
+ }
+
+ private static void failX(String msg, Throwable x) {
+ fail(msg + ": " + x);
+ x.printStackTrace(System.out);
+ }
+}
diff --git a/test/javax/management/mxbean/InvalidMXBeanRegistrationTest.java b/test/javax/management/mxbean/InvalidMXBeanRegistrationTest.java
new file mode 100644
index 0000000..b414823
--- /dev/null
+++ b/test/javax/management/mxbean/InvalidMXBeanRegistrationTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6333554
+ * @summary Ensure the registration of an invalid MXBean
+ * throws NotCompliantMBeanException.
+ * @author Luis-Miguel Alventosa
+ * @run clean InvalidMXBeanRegistrationTest
+ * @run build InvalidMXBeanRegistrationTest
+ * @run main InvalidMXBeanRegistrationTest
+ */
+
+import javax.management.*;
+
+public class InvalidMXBeanRegistrationTest {
+
+ // JMX compliant MXBean interface
+ //
+ @MXBean(true)
+ public interface Compliant1 {}
+
+ // JMX compliant MXBean interface
+ //
+ public interface Compliant2MXBean {}
+
+ // JMX non-compliant MXBean (NotCompliantMBeanException must be thrown)
+ //
+ public static class Compliant implements Compliant1, Compliant2MXBean {}
+
+ public static void main(String[] args) throws Exception {
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ ObjectName on = new ObjectName("a:b=c");
+ Compliant mxbean = new Compliant();
+ boolean ok;
+ try {
+ mbs.registerMBean(mxbean, on);
+ System.out.println("Didn't get expected NotCompliantMBeanException");
+ ok = false;
+ } catch (NotCompliantMBeanException e) {
+ System.out.println("Got expected exception: " + e);
+ ok = true;
+ } catch (Exception e) {
+ System.out.println("Got unexpected exception: " + e);
+ ok = false;
+ }
+ if (ok)
+ System.out.println("Test PASSED");
+ else {
+ System.out.println("Test FAILED");
+ }
+ }
+}
diff --git a/test/javax/management/mxbean/LeakTest.java b/test/javax/management/mxbean/LeakTest.java
new file mode 100644
index 0000000..f9248da
--- /dev/null
+++ b/test/javax/management/mxbean/LeakTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @bug 6482247
+ * @summary Test that creating MXBeans does not introduce memory leaks.
+ * @author Eamonn McManus
+ * @run build LeakTest
+ * @run main LeakTest
+ */
+
+/* In this test we create a ClassLoader, then use it to load and run another
+ * jtreg test. When the other test has completed, we wait for the ClassLoader
+ * to be garbage-collected. If it has not been gc'd after a reasonable
+ * amount of time, then something is keeping a reference to the ClassLoader,
+ * which implies a memory leak.
+ *
+ * This test can be applied to any jtreg test, not just the MXBean tests.
+ */
+
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+
+public class LeakTest {
+ /* Ideally we would include MXBeanTest in the list of tests, since it
+ * has fairly complete coverage. However, the ClassLoader fails to be
+ * gc'd when we do that, and I am unable to figure out why. Examining
+ * a heap dump shows only weak references to the ClassLoader. I suspect
+ * something is wrong in the internals of the reflection classes, used
+ * quite heavily by MXBeanTest.
+ */
+// private static Class<?>[] otherTests = {MXBeanTest.class};
+
+ private static Class<?>[] otherTests = {RandomMXBeanTest.class};
+
+ // This class just makes it easier for us to spot our loader in heap dumps
+ private static class ShadowClassLoader extends URLClassLoader {
+ ShadowClassLoader(URL[] urls, ClassLoader parent) {
+ super(urls, parent);
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("Testing that no references are held to ClassLoaders " +
+ "by caches in the MXBean infrastructure");
+ for (Class<?> testClass : otherTests)
+ test(testClass);
+ if (failure != null)
+ throw new Exception("CLASSLOADER LEAK TEST FAILED: " + failure);
+ System.out.println("CLASSLOADER LEAK TEST PASSED");
+ if (args.length > 0) {
+ System.out.println("Waiting for input");
+ System.in.read();
+ }
+ }
+
+ private static void test(Class<?> originalTestClass) throws Exception {
+ System.out.println();
+ System.out.println("TESTING " + originalTestClass.getName());
+ WeakReference<ClassLoader> wr = testShadow(originalTestClass);
+ System.out.println("Test passed, waiting for ClassLoader to disappear");
+ long deadline = System.currentTimeMillis() + 20*1000;
+ Reference<? extends ClassLoader> ref;
+ while (wr.get() != null && System.currentTimeMillis() < deadline) {
+ System.gc();
+ Thread.sleep(100);
+ }
+ if (wr.get() != null)
+ fail(originalTestClass.getName() + " kept ClassLoader reference");
+ }
+
+ private static WeakReference<ClassLoader>
+ testShadow(Class<?> originalTestClass) throws Exception {
+ URLClassLoader originalLoader =
+ (URLClassLoader) originalTestClass.getClassLoader();
+ URL[] urls = originalLoader.getURLs();
+ URLClassLoader shadowLoader =
+ new ShadowClassLoader(urls, originalLoader.getParent());
+ System.out.println("Shadow loader is " + shadowLoader);
+ String className = originalTestClass.getName();
+ Class<?> testClass = Class.forName(className, false, shadowLoader);
+ if (testClass.getClassLoader() != shadowLoader) {
+ throw new IllegalArgumentException("Loader didn't work: " +
+ testClass.getClassLoader() + " != " + shadowLoader);
+ }
+ Method main = testClass.getMethod("main", String[].class);
+ main.invoke(null, (Object) new String[0]);
+ return new WeakReference<ClassLoader>(shadowLoader);
+ }
+
+ private static void fail(String why) {
+ System.out.println("FAILED: " + why);
+ failure = why;
+ }
+
+ private static String failure;
+}
diff --git a/test/javax/management/mxbean/MBeanOperationInfoTest.java b/test/javax/management/mxbean/MBeanOperationInfoTest.java
new file mode 100644
index 0000000..cff6668
--- /dev/null
+++ b/test/javax/management/mxbean/MBeanOperationInfoTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6359948
+ * @summary Check that MXBean operations have the expected ReturnType in MBeanOperationInfo
+ * @author Luis-Miguel Alventosa
+ * @run clean MBeanOperationInfoTest
+ * @run build MBeanOperationInfoTest
+ * @run main MBeanOperationInfoTest
+ */
+
+import java.lang.management.*;
+import javax.management.*;
+import javax.management.openmbean.*;
+
+public class MBeanOperationInfoTest {
+ private static final String[][] returnTypes = {
+ { "dumpAllThreads(boolean,boolean)", "[Ljavax.management.openmbean.CompositeData;" },
+ { "findDeadlockedThreads()", "[J" },
+ { "findMonitorDeadlockedThreads()", "[J" },
+ { "getThreadInfo(long)","javax.management.openmbean.CompositeData"},
+ { "getThreadInfo(long,int)","javax.management.openmbean.CompositeData"},
+ { "getThreadInfo([J)","[Ljavax.management.openmbean.CompositeData;"},
+ { "getThreadInfo([J,int)","[Ljavax.management.openmbean.CompositeData;"},
+ { "getThreadInfo([J,boolean,boolean)","[Ljavax.management.openmbean.CompositeData;"},
+ { "getThreadCpuTime(long)","long"},
+ { "getThreadUserTime(long)","long"},
+ { "resetPeakThreadCount()","void"},
+ };
+ public static void main(String[] args) throws Exception {
+ int error = 0;
+ int tested = 0;
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ ObjectName on = new ObjectName(ManagementFactory.THREAD_MXBEAN_NAME);
+ MBeanInfo mbi = mbs.getMBeanInfo(on);
+ MBeanOperationInfo[] ops = mbi.getOperations();
+ for (MBeanOperationInfo op : ops) {
+ String name = op.getName();
+ String rt = op.getReturnType();
+ StringBuilder sb = new StringBuilder();
+ sb.append(name + "(");
+ for (MBeanParameterInfo param : op.getSignature()) {
+ sb.append(param.getType() + ",");
+ }
+ int comma = sb.lastIndexOf(",");
+ if (comma == -1) {
+ sb.append(")");
+ } else {
+ sb.replace(comma, comma + 1, ")");
+ }
+ System.out.println("\nNAME = " + sb.toString() + "\nRETURN TYPE = " + rt);
+ for (String[] rts : returnTypes) {
+ if (sb.toString().equals(rts[0])) {
+ if (rt.equals(rts[1])) {
+ System.out.println("OK");
+ tested++;
+ } else {
+ System.out.println("KO: EXPECTED RETURN TYPE = " + rts[1]);
+ error++;
+ }
+ }
+ }
+ }
+ if (error > 0) {
+ System.out.println("\nTEST FAILED");
+ throw new Exception("TEST FAILED: " + error + " wrong return types");
+ } else if (tested != returnTypes.length) {
+ System.out.println("\nTEST FAILED");
+ throw new Exception("TEST FAILED: " + tested + " cases tested, " +
+ returnTypes.length + " expected");
+ } else {
+ System.out.println("\nTEST PASSED");
+ }
+ }
+}
diff --git a/test/javax/management/mxbean/MXBeanAnnotationTest.java b/test/javax/management/mxbean/MXBeanAnnotationTest.java
new file mode 100644
index 0000000..7971f03
--- /dev/null
+++ b/test/javax/management/mxbean/MXBeanAnnotationTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6316491
+ * @summary Check that the MXBean annotation works as advertised
+ * @author Eamonn McManus
+ * @run clean MXBeanAnnotationTest
+ * @run build MXBeanAnnotationTest
+ * @run main MXBeanAnnotationTest
+ */
+
+import javax.management.*;
+
+public class MXBeanAnnotationTest {
+ @MXBean
+ public static interface Empty {}
+
+ public static class EmptyImpl implements Empty {}
+
+ @MXBean(false)
+ public static interface NotMXBean {}
+
+ public static class NotImpl implements NotMXBean {}
+
+ public static void main(String[] args) throws Exception {
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ ObjectName on = new ObjectName("a:b=c");
+
+ // Test empty interface
+
+ try {
+ mbs.registerMBean(new EmptyImpl(), on);
+ boolean ok = checkMXBean(mbs.getMBeanInfo(on), true,
+ "empty MXBean interface");
+ mbs.unregisterMBean(on);
+ if (ok)
+ System.out.println("OK: empty MXBean interface");
+ } catch (Exception e) {
+ failure = "MXBean with empty interface got exception: " + e;
+ System.out.println("FAILED: " + failure);
+ e.printStackTrace(System.out);
+ }
+
+ // Test @MXBean(false)
+
+ try {
+ mbs.registerMBean(new NotImpl(), on);
+ failure = "Registered a non-Standard MBean with @MXBean(false)";
+ System.out.println("FAILED: " + failure);
+ } catch (NotCompliantMBeanException e) {
+ System.out.println("OK: non-Standard MBean with @MXBean(false) " +
+ "rejected");
+ }
+
+ if (failure == null)
+ System.out.println("TEST PASSED");
+ else
+ throw new Exception("TEST FAILED: " + failure);
+ }
+
+ private static boolean checkMXBean(MBeanInfo mbi, boolean expected,
+ String what) {
+ Descriptor d = mbi.getDescriptor();
+ String mxbean = (String) d.getFieldValue("mxbean");
+ boolean is = (mxbean != null && mxbean.equals("true"));
+ if (is == expected)
+ return true;
+ else {
+ failure = "MBean should " + (expected ? "" : "not ") +
+ "have mxbean=true: " + d;
+ return false;
+ }
+ }
+
+ private static String failure;
+}
diff --git a/test/javax/management/mxbean/MXBeanFlagTest.java b/test/javax/management/mxbean/MXBeanFlagTest.java
new file mode 100644
index 0000000..0f4a68a
--- /dev/null
+++ b/test/javax/management/mxbean/MXBeanFlagTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6335337
+ * @summary Test correctness of mxbean flag in descriptor.
+ * @author Luis-Miguel Alventosa
+ * @run clean MXBeanFlagTest
+ * @run build MXBeanFlagTest
+ * @run main MXBeanFlagTest
+ */
+
+import javax.management.*;
+
+public class MXBeanFlagTest {
+
+ public interface Compliant1MXBean {}
+ public static class Compliant1 implements Compliant1MXBean {}
+
+ public interface Compliant2MXBean {}
+ public static class Compliant2 implements Compliant2MXBean {}
+
+ public interface Compliant3MBean {}
+ public static class Compliant3 implements Compliant3MBean {}
+
+ public interface Compliant4MBean {}
+ public static class Compliant4 implements Compliant4MBean {}
+
+ public static void main(String[] args) throws Exception {
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ ObjectName on1 = new ObjectName(":type=Compliant1");
+ ObjectName on2 = new ObjectName(":type=Compliant2");
+ ObjectName on3 = new ObjectName(":type=Compliant3");
+ ObjectName on4 = new ObjectName(":type=Compliant4");
+ Compliant1 compliant1 = new Compliant1();
+ StandardMBean compliant2 =
+ new StandardMBean(new Compliant2(), Compliant2MXBean.class, true);
+ Compliant3 compliant3 = new Compliant3();
+ StandardMBean compliant4 =
+ new StandardMBean(new Compliant4(), Compliant4MBean.class, false);
+ mbs.registerMBean(compliant1, on1);
+ mbs.registerMBean(compliant2, on2);
+ mbs.registerMBean(compliant3, on3);
+ mbs.registerMBean(compliant4, on4);
+ String flag1 = (String)
+ mbs.getMBeanInfo(on1).getDescriptor().getFieldValue("mxbean");
+ String flag2 = (String)
+ mbs.getMBeanInfo(on2).getDescriptor().getFieldValue("mxbean");
+ String flag3 = (String)
+ mbs.getMBeanInfo(on3).getDescriptor().getFieldValue("mxbean");
+ String flag4 = (String)
+ mbs.getMBeanInfo(on4).getDescriptor().getFieldValue("mxbean");
+ System.out.println("MXBean compliant1:\n" +
+ "\t[Expected: mxbean=true] [Got: mxbean=" + flag1 + "]");
+ System.out.println("MXBean compliant2:\n" +
+ "\t[Expected: mxbean=true] [Got: mxbean=" + flag2 + "]");
+ System.out.println("Standard MBean compliant3:\n" +
+ "\t[Expected: mxbean=false] [Got: mxbean=" + flag3 + "]");
+ System.out.println("Standard MBean compliant4:\n" +
+ "\t[Expected: mxbean=false] [Got: mxbean=" + flag4 + "]");
+ if (flag1 != null && flag1.equals("true") &&
+ flag2 != null && flag2.equals("true") &&
+ flag3 != null && flag3.equals("false") &&
+ flag4 != null && flag4.equals("false"))
+ System.out.println("Test PASSED");
+ else {
+ System.out.println("Test FAILED");
+ throw new Exception("invalid flags");
+ }
+ }
+}
diff --git a/test/javax/management/mxbean/MXBeanPreRegisterTest.java b/test/javax/management/mxbean/MXBeanPreRegisterTest.java
new file mode 100644
index 0000000..ffaa3f5
--- /dev/null
+++ b/test/javax/management/mxbean/MXBeanPreRegisterTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6175517
+ * @summary Ensure that preRegister etc are called, but not when wrapped
+ * by the class StandardMBean
+ * @author Eamonn McManus
+ * @run clean MXBeanPreRegisterTest
+ * @run build MXBeanPreRegisterTest
+ * @run main MXBeanPreRegisterTest
+ */
+
+import javax.management.*;
+
+public class MXBeanPreRegisterTest {
+ public static interface EmptyMBean {}
+
+ public static interface EmptyMXBean extends EmptyMBean {}
+
+ public static class Base implements MBeanRegistration {
+ public ObjectName preRegister(MBeanServer mbs, ObjectName n) {
+ count++;
+ return n;
+ }
+
+ public void postRegister(Boolean done) {
+ count++;
+ }
+
+ public void preDeregister() {
+ count++;
+ }
+
+ public void postDeregister() {
+ count++;
+ }
+
+ int count;
+ }
+
+ public static class Empty extends Base implements EmptyMBean {}
+
+ public static class EmptyMX extends Base implements EmptyMXBean {}
+
+ public static void main(String[] args) throws Exception {
+ for (boolean mx : new boolean[] {false, true})
+ for (boolean wrapped : new boolean[] {false, true})
+ test(mx, wrapped);
+ if (failure != null)
+ throw new Exception("TEST FAILED: " + failure);
+ System.out.println("TEST PASSED");
+ }
+
+ private static void test(boolean mx, boolean wrapped) throws Exception {
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ ObjectName on = new ObjectName("a:b=c");
+ Base mbean = mx ? new EmptyMX() : new Empty();
+ Object reg = wrapped ? new StandardMBean(mbean, null, mx) : mbean;
+ mbs.registerMBean(reg, on);
+ mbs.unregisterMBean(on);
+ String testDescr =
+ (mx ? "MXBean" : "Standard MBean") +
+ (wrapped ? " wrapped in StandardMBean class should not" :
+ " should") +
+ " call MBeanRegistration methods";
+ boolean ok = mbean.count == (wrapped ? 0 : 4);
+ if (ok)
+ System.out.println("OK: " + testDescr);
+ else {
+ failure = testDescr;
+ System.out.println("FAILED: " + failure);
+ }
+ }
+
+ private static String failure;
+}
diff --git a/test/javax/management/mxbean/MXBeanRefTest.java b/test/javax/management/mxbean/MXBeanRefTest.java
new file mode 100644
index 0000000..ae85a8b
--- /dev/null
+++ b/test/javax/management/mxbean/MXBeanRefTest.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6296433 6283873
+ * @summary Test that inter-MXBean references work as expected.
+ * @author Eamonn McManus
+ * @run clean MXBeanRefTest
+ * @run build MXBeanRefTest
+ * @run main MXBeanRefTest
+ */
+
+import java.lang.reflect.Proxy;
+import java.lang.reflect.UndeclaredThrowableException;
+import javax.management.Attribute;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.JMX;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerDelegate;
+import javax.management.MBeanServerFactory;
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.ObjectName;
+import javax.management.openmbean.OpenDataException;
+
+public class MXBeanRefTest {
+ public static void main(String[] args) throws Exception {
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ ObjectName productName = new ObjectName("d:type=Product,n=1");
+ ObjectName product2Name = new ObjectName("d:type=Product,n=2");
+ ObjectName moduleName = new ObjectName("d:type=Module");
+ mbs.registerMBean(product, productName);
+ mbs.registerMBean(product2, product2Name);
+ mbs.registerMBean(module, moduleName);
+ ModuleMXBean moduleProxy =
+ JMX.newMXBeanProxy(mbs, moduleName, ModuleMXBean.class);
+
+ ObjectName on;
+ on = (ObjectName) mbs.getAttribute(moduleName, "Product");
+ check("ObjectName attribute value", on.equals(productName));
+
+ ProductMXBean productProxy = moduleProxy.getProduct();
+ MBeanServerInvocationHandler mbsih = (MBeanServerInvocationHandler)
+ Proxy.getInvocationHandler(productProxy);
+ check("ObjectName in proxy", mbsih.getObjectName().equals(productName));
+
+ mbs.setAttribute(moduleName, new Attribute("Product", product2Name));
+ ProductMXBean product2Proxy = module.getProduct();
+ mbsih = (MBeanServerInvocationHandler)
+ Proxy.getInvocationHandler(product2Proxy);
+ check("Proxy after setAttribute",
+ mbsih.getObjectName().equals(product2Name));
+
+ moduleProxy.setProduct(productProxy);
+ ProductMXBean productProxyAgain = module.getProduct();
+ mbsih = (MBeanServerInvocationHandler)
+ Proxy.getInvocationHandler(productProxyAgain);
+ check("Proxy after proxied set",
+ mbsih.getObjectName().equals(productName));
+
+ MBeanServer mbs2 = MBeanServerFactory.createMBeanServer();
+ ProductMXBean productProxy2 =
+ JMX.newMXBeanProxy(mbs2, productName, ProductMXBean.class);
+ try {
+ moduleProxy.setProduct(productProxy2);
+ check("Proxy for wrong MBeanServer worked but shouldn't", false);
+ } catch (Exception e) {
+ if (e instanceof UndeclaredThrowableException &&
+ e.getCause() instanceof OpenDataException)
+ check("Proxy for wrong MBeanServer correctly rejected", true);
+ else {
+ e.printStackTrace(System.out);
+ check("Proxy for wrong MBeanServer got wrong exception", false);
+ }
+ }
+
+ // Test 6283873
+ ObjectName dup = new ObjectName("a:b=c");
+ mbs.registerMBean(new MBeanServerDelegate(), dup);
+ try {
+ mbs.registerMBean(new ProductImpl(), dup);
+ check("Duplicate register succeeded but should fail", false);
+ } catch (InstanceAlreadyExistsException e) {
+ check("Got correct exception from duplicate name", true);
+ } catch (Exception e) {
+ e.printStackTrace(System.out);
+ check("Got wrong exception from duplicate name", false);
+ }
+
+ if (failure != null)
+ throw new Exception("TEST FAILED: " + failure);
+ System.out.println("TEST PASSED");
+ }
+
+ private static void check(String what, boolean ok) {
+ if (ok)
+ System.out.println("OK: " + what);
+ else {
+ System.out.println("FAILED: " + what);
+ failure = what;
+ }
+ }
+
+ public static interface ProductMXBean {
+ ModuleMXBean[] getModules();
+ }
+
+ public static interface ModuleMXBean {
+ ProductMXBean getProduct();
+ void setProduct(ProductMXBean p);
+ }
+
+ public static class ProductImpl implements ProductMXBean {
+ public ModuleMXBean[] getModules() {
+ return modules;
+ }
+ }
+
+ public static class ModuleImpl implements ModuleMXBean {
+ public ModuleImpl(ProductMXBean p) {
+ setProduct(p);
+ }
+
+ public ProductMXBean getProduct() {
+ return prod;
+ }
+
+ public void setProduct(ProductMXBean p) {
+ this.prod = p;
+ }
+
+ private ProductMXBean prod;
+ }
+
+ private static final ProductMXBean product = new ProductImpl();
+ private static final ProductMXBean product2 = new ProductImpl();
+ private static final ModuleMXBean module = new ModuleImpl(product);
+ private static final ModuleMXBean[] modules = new ModuleMXBean[] {module};
+ private static String failure;
+}
diff --git a/test/javax/management/mxbean/MXBeanTest.java b/test/javax/management/mxbean/MXBeanTest.java
new file mode 100644
index 0000000..9abcf57
--- /dev/null
+++ b/test/javax/management/mxbean/MXBeanTest.java
@@ -0,0 +1,707 @@
+/*
+ * Copyright 2005-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6175517 6278707 6318827 6305746 6392303
+ * @summary General MXBean test.
+ * @author Eamonn McManus
+ * @run clean MXBeanTest MerlinMXBean TigerMXBean
+ * @run build MXBeanTest MerlinMXBean TigerMXBean
+ * @run main MXBeanTest
+ */
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import javax.management.Attribute;
+import javax.management.JMX;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanParameterInfo;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerFactory;
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.ObjectName;
+import javax.management.StandardMBean;
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataInvocationHandler;
+import javax.management.openmbean.OpenMBeanAttributeInfo;
+import javax.management.openmbean.OpenMBeanInfo;
+import javax.management.openmbean.OpenMBeanOperationInfo;
+import javax.management.openmbean.OpenMBeanParameterInfo;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularType;
+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 MXBeanTest {
+ public static void main(String[] args) throws Exception {
+ testInterface(MerlinMXBean.class, false);
+ testInterface(TigerMXBean.class, false);
+ testInterface(MerlinMXBean.class, true);
+ testInterface(TigerMXBean.class, true);
+ testExplicitMXBean();
+ testSubclassMXBean();
+ testIndirectMXBean();
+
+ if (failures == 0)
+ System.out.println("Test passed");
+ else {
+ System.out.println("TEST FAILURES: " + failures);
+ System.exit(1);
+ }
+ }
+
+ private static int failures = 0;
+
+ public static interface ExplicitMXBean {
+ public int[] getInts();
+ }
+ public static class Explicit implements ExplicitMXBean {
+ public int[] getInts() {
+ return new int[] {1, 2, 3};
+ }
+ }
+ public static class Subclass
+ extends StandardMBean
+ implements ExplicitMXBean {
+ public Subclass() {
+ super(ExplicitMXBean.class, true);
+ }
+
+ public int[] getInts() {
+ return new int[] {1, 2, 3};
+ }
+ }
+ public static interface IndirectInterface extends ExplicitMXBean {}
+ public static class Indirect implements IndirectInterface {
+ public int[] getInts() {
+ return new int[] {1, 2, 3};
+ }
+ }
+
+ private static void testExplicitMXBean() throws Exception {
+ System.out.println("Explicit MXBean test...");
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ ObjectName on = new ObjectName("test:type=Explicit");
+ Explicit explicit = new Explicit();
+ mbs.registerMBean(explicit, on);
+ testMXBean(mbs, on);
+ }
+
+ private static void testSubclassMXBean() throws Exception {
+ System.out.println("Subclass MXBean test...");
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ ObjectName on = new ObjectName("test:type=Subclass");
+ Subclass subclass = new Subclass();
+ mbs.registerMBean(subclass, on);
+ testMXBean(mbs, on);
+ }
+
+ private static void testIndirectMXBean() throws Exception {
+ System.out.println("Indirect MXBean test...");
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ ObjectName on = new ObjectName("test:type=Indirect");
+ Indirect indirect = new Indirect();
+ mbs.registerMBean(indirect, on);
+ testMXBean(mbs, on);
+ }
+
+ private static void testMXBean(MBeanServer mbs, ObjectName on)
+ throws Exception {
+ MBeanInfo mbi = mbs.getMBeanInfo(on);
+ MBeanAttributeInfo[] attrs = mbi.getAttributes();
+ int nattrs = attrs.length;
+ if (mbi.getAttributes().length != 1)
+ failure("wrong number of attributes: " + attrs);
+ else {
+ MBeanAttributeInfo mbai = attrs[0];
+ if (mbai.getName().equals("Ints")
+ && mbai.isReadable() && !mbai.isWritable()
+ && mbai.getDescriptor().getFieldValue("openType")
+ .equals(new ArrayType(SimpleType.INTEGER, true))
+ && attrs[0].getType().equals("[I"))
+ success("MBeanAttributeInfo");
+ else
+ failure("MBeanAttributeInfo: " + mbai);
+ }
+
+ int[] ints = (int[]) mbs.getAttribute(on, "Ints");
+ if (equal(ints, new int[] {1, 2, 3}, null))
+ success("getAttribute");
+ else
+ failure("getAttribute: " + Arrays.toString(ints));
+
+ ExplicitMXBean proxy =
+ JMX.newMXBeanProxy(mbs, on, ExplicitMXBean.class);
+ int[] pints = proxy.getInts();
+ if (equal(pints, new int[] {1, 2, 3}, null))
+ success("getAttribute through proxy");
+ else
+ failure("getAttribute through proxy: " + Arrays.toString(pints));
+ }
+
+ private static class NamedMXBeans extends HashMap<ObjectName, Object> {
+ private static final long serialVersionUID = 0;
+
+ NamedMXBeans(MBeanServerConnection mbsc) {
+ this.mbsc = mbsc;
+ }
+
+ MBeanServerConnection getMBeanServerConnection() {
+ return mbsc;
+ }
+
+ private final MBeanServerConnection mbsc;
+ }
+
+ /* This is the core of the test. Given the MXBean interface c, we
+ make an MXBean object that implements that interface by
+ constructing a dynamic proxy. If the interface defines an
+ attribute Foo (with getFoo and setFoo methods), then it must
+ also contain a field (constant) Foo of the same type, and a
+ field (constant) FooType that is an OpenType. The field Foo is
+ a reference value for this case. We check that the attribute
+ does indeed have the given OpenType. The dynamically-created
+ MXBean will return the reference value from the getFoo()
+ method, and we check that that value survives the mapping to
+ open values and back when the attribute is accessed through an
+ MXBean proxy. The MXBean will also check in its setFoo method
+ that the value being set is equal to the reference value, which
+ tests that the mapping and unmapping also works in the other
+ direction. The interface should define an operation opFoo with
+ two parameters and a return value all of the same type as the
+ attribute. The MXBean will check that the two parameters are
+ equal to the reference value, and will return that value. The
+ test checks that calling the operation through an MXBean proxy
+ returns the reference value, again after mapping to and back
+ from open values.
+
+ If any field (constant) in the MXBean interface has a name that
+ ends with ObjectName, say FooObjectName, then its value must be
+ a String containing an ObjectName value. There must be a field
+ (constant) called Foo that is a valid MXBean, and that MXBean
+ will be registered in the MBean Server with the given name before
+ the test starts. This enables us to test that inter-MXBean
+ references are correctly converted to ObjectNames and back.
+ */
+ private static <T> void testInterface(Class<T> c, boolean nullTest)
+ throws Exception {
+
+ System.out.println("Testing " + c.getName() +
+ (nullTest ? " for null values" : "") + "...");
+
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+
+ 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();
+
+ NamedMXBeans namedMXBeans = new NamedMXBeans(mbsc);
+ InvocationHandler ih =
+ nullTest ? new MXBeanNullImplInvocationHandler(c, namedMXBeans) :
+ new MXBeanImplInvocationHandler(c, namedMXBeans);
+ T impl = c.cast(Proxy.newProxyInstance(c.getClassLoader(),
+ new Class[] {c},
+ ih));
+ ObjectName on = new ObjectName("test:type=" + c.getName());
+ mbs.registerMBean(impl, on);
+
+ System.out.println("Register any MXBeans...");
+
+ Field[] fields = c.getFields();
+ for (Field field : fields) {
+ String n = field.getName();
+ if (n.endsWith("ObjectName")) {
+ String objectNameString = (String) field.get(null);
+ String base = n.substring(0, n.length() - 10);
+ Field f = c.getField(base);
+ Object mxbean = f.get(null);
+ ObjectName objectName =
+ ObjectName.getInstance(objectNameString);
+ mbs.registerMBean(mxbean, objectName);
+ namedMXBeans.put(objectName, mxbean);
+ }
+ }
+
+ try {
+ testInterface(c, mbsc, on, namedMXBeans, nullTest);
+ } finally {
+ try {
+ cc.close();
+ } finally {
+ cs.stop();
+ }
+ }
+ }
+
+ private static <T> void testInterface(Class<T> c,
+ MBeanServerConnection mbsc,
+ ObjectName on,
+ NamedMXBeans namedMXBeans,
+ boolean nullTest)
+ throws Exception {
+
+ System.out.println("Type check...");
+
+ MBeanInfo mbi = mbsc.getMBeanInfo(on);
+ MBeanAttributeInfo[] mbais = mbi.getAttributes();
+ for (int i = 0; i < mbais.length; i++) {
+ MBeanAttributeInfo mbai = mbais[i];
+ String name = mbai.getName();
+ Field typeField = c.getField(name + "Type");
+ OpenType typeValue = (OpenType) typeField.get(null);
+ OpenType openType =
+ (OpenType) mbai.getDescriptor().getFieldValue("openType");
+ if (typeValue.equals(openType))
+ success("attribute " + name);
+ else {
+ final String msg =
+ "Wrong type attribute " + name + ": " +
+ openType + " should be " + typeValue;
+ failure(msg);
+ }
+ }
+
+ MBeanOperationInfo[] mbois = mbi.getOperations();
+ for (int i = 0; i < mbois.length; i++) {
+ MBeanOperationInfo mboi = mbois[i];
+ String oname = mboi.getName();
+ if (!oname.startsWith("op"))
+ throw new Error();
+ OpenType retType =
+ (OpenType) mboi.getDescriptor().getFieldValue("openType");
+ MBeanParameterInfo[] params = mboi.getSignature();
+ MBeanParameterInfo p1i = params[0];
+ MBeanParameterInfo p2i = params[1];
+ OpenType p1Type =
+ (OpenType) p1i.getDescriptor().getFieldValue("openType");
+ OpenType p2Type =
+ (OpenType) p2i.getDescriptor().getFieldValue("openType");
+ if (!retType.equals(p1Type) || !p1Type.equals(p2Type)) {
+ final String msg =
+ "Parameter and return open types should all be same " +
+ "but are not: " + retType + " " + oname + "(" + p1Type +
+ ", " + p2Type + ")";
+ failure(msg);
+ continue;
+ }
+ String name = oname.substring(2);
+ Field typeField = c.getField(name + "Type");
+ OpenType typeValue = (OpenType) typeField.get(null);
+ if (typeValue.equals(retType))
+ success("operation " + oname);
+ else {
+ final String msg =
+ "Wrong type operation " + oname + ": " +
+ retType + " should be " + typeValue;
+ failure(msg);
+ }
+ }
+
+
+ System.out.println("Mapping check...");
+
+ Object proxy =
+ JMX.newMXBeanProxy(mbsc, on, c);
+
+ Method[] methods = c.getMethods();
+ for (int i = 0; i < methods.length; i++) {
+ final Method method = methods[i];
+ if (method.getDeclaringClass() != c)
+ continue; // skip hashCode() etc inherited from Object
+ final String mname = method.getName();
+ final int what = getType(method);
+ final String name = getName(method);
+ final Field refField = c.getField(name);
+ if (nullTest && refField.getType().isPrimitive())
+ continue;
+ final Field openTypeField = c.getField(name + "Type");
+ final OpenType openType = (OpenType) openTypeField.get(null);
+ final Object refValue = nullTest ? null : refField.get(null);
+ Object setValue = refValue;
+ try {
+ Field onField = c.getField(name + "ObjectName");
+ String refName = (String) onField.get(null);
+ ObjectName refObjName = ObjectName.getInstance(refName);
+ Class<?> mxbeanInterface = refField.getType();
+ setValue = nullTest ? null :
+ JMX.newMXBeanProxy(mbsc, refObjName, mxbeanInterface);
+ } catch (Exception e) {
+ // no xObjectName field, setValue == refValue
+ }
+ boolean ok = true;
+ try {
+ switch (what) {
+ case GET:
+ final Object gotOpen = mbsc.getAttribute(on, name);
+ if (nullTest) {
+ if (gotOpen != null) {
+ failure(mname + " got non-null value " +
+ gotOpen);
+ ok = false;
+ }
+ } else if (!openType.isValue(gotOpen)) {
+ if (gotOpen instanceof TabularData) {
+ // detail the mismatch
+ TabularData gotTabular = (TabularData) gotOpen;
+ compareTabularType((TabularType) openType,
+ gotTabular.getTabularType());
+ }
+ failure(mname + " got open data " + gotOpen +
+ " not valid for open type " + openType);
+ ok = false;
+ }
+ final Object got = method.invoke(proxy, (Object[]) null);
+ if (!equal(refValue, got, namedMXBeans)) {
+ failure(mname + " got " + string(got) +
+ ", should be " + string(refValue));
+ ok = false;
+ }
+ break;
+
+ case SET:
+ method.invoke(proxy, new Object[] {setValue});
+ break;
+
+ case OP:
+ final Object opped =
+ method.invoke(proxy, new Object[] {setValue, setValue});
+ if (!equal(refValue, opped, namedMXBeans)) {
+ failure(
+ mname + " got " + string(opped) +
+ ", should be " + string(refValue)
+ );
+ ok = false;
+ }
+ break;
+
+ default:
+ throw new Error();
+ }
+
+ if (ok)
+ success(mname);
+
+ } catch (Exception e) {
+ failure(mname, e);
+ }
+ }
+ }
+
+
+ private static void success(String what) {
+ System.out.println("OK: " + what);
+ }
+
+ private static void failure(String what) {
+ System.out.println("FAILED: " + what);
+ failures++;
+ }
+
+ private static void failure(String what, Exception e) {
+ System.out.println("FAILED WITH EXCEPTION: " + what);
+ e.printStackTrace(System.out);
+ failures++;
+ }
+
+ private static class MXBeanImplInvocationHandler
+ implements InvocationHandler {
+ MXBeanImplInvocationHandler(Class intf, NamedMXBeans namedMXBeans) {
+ this.intf = intf;
+ this.namedMXBeans = namedMXBeans;
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args)
+ throws Throwable {
+ final String mname = method.getName();
+ final int what = getType(method);
+ final String name = getName(method);
+ final Field refField = intf.getField(name);
+ final Object refValue = getRefValue(refField);
+
+ switch (what) {
+ case GET:
+ assert args == null;
+ return refValue;
+
+ case SET:
+ assert args.length == 1;
+ Object setValue = args[0];
+ if (!equal(refValue, setValue, namedMXBeans)) {
+ final String msg =
+ mname + "(" + string(setValue) +
+ ") does not match ref: " + string(refValue);
+ throw new IllegalArgumentException(msg);
+ }
+ return null;
+
+ case OP:
+ assert args.length == 2;
+ Object arg1 = args[0];
+ Object arg2 = args[1];
+ if (!equal(arg1, arg2, namedMXBeans)) {
+ final String msg =
+ mname + "(" + string(arg1) + ", " + string(arg2) +
+ "): args not equal";
+ throw new IllegalArgumentException(msg);
+ }
+ if (!equal(refValue, arg1, namedMXBeans)) {
+ final String msg =
+ mname + "(" + string(arg1) + ", " + string(arg2) +
+ "): args do not match ref: " + string(refValue);
+ throw new IllegalArgumentException(msg);
+ }
+ return refValue;
+ default:
+ throw new Error();
+ }
+ }
+
+ Object getRefValue(Field refField) throws Exception {
+ return refField.get(null);
+ }
+
+ private final Class intf;
+ private final NamedMXBeans namedMXBeans;
+ }
+
+ private static class MXBeanNullImplInvocationHandler
+ extends MXBeanImplInvocationHandler {
+ MXBeanNullImplInvocationHandler(Class intf, NamedMXBeans namedMXBeans) {
+ super(intf, namedMXBeans);
+ }
+
+ @Override
+ Object getRefValue(Field refField) throws Exception {
+ Class<?> type = refField.getType();
+ if (type.isPrimitive())
+ return super.getRefValue(refField);
+ else
+ return null;
+ }
+ }
+
+
+ private static final String[] prefixes = {
+ "get", "set", "op",
+ };
+ private static final int GET = 0, SET = 1, OP = 2;
+
+ private static String getName(Method m) {
+ return getName(m.getName());
+ }
+
+ private static String getName(String n) {
+ for (int i = 0; i < prefixes.length; i++) {
+ if (n.startsWith(prefixes[i]))
+ return n.substring(prefixes[i].length());
+ }
+ throw new Error();
+ }
+
+ private static int getType(Method m) {
+ return getType(m.getName());
+ }
+
+ private static int getType(String n) {
+ for (int i = 0; i < prefixes.length; i++) {
+ if (n.startsWith(prefixes[i]))
+ return i;
+ }
+ throw new Error();
+ }
+
+ static boolean equal(Object o1, Object o2, NamedMXBeans namedMXBeans) {
+ if (o1 == o2)
+ return true;
+ if (o1 == null || o2 == null)
+ return false;
+ if (o1.getClass().isArray()) {
+ if (!o2.getClass().isArray())
+ return false;
+ return deepEqual(o1, o2, namedMXBeans);
+ }
+ if (o1 instanceof CompositeData && o2 instanceof CompositeData) {
+ return compositeDataEqual((CompositeData) o1, (CompositeData) o2,
+ namedMXBeans);
+ }
+ if (Proxy.isProxyClass(o1.getClass())) {
+ if (Proxy.isProxyClass(o2.getClass()))
+ return proxyEqual(o1, o2, namedMXBeans);
+ InvocationHandler ih = Proxy.getInvocationHandler(o1);
+// if (ih instanceof MXBeanInvocationHandler) {
+// return proxyEqualsObject((MXBeanInvocationHandler) ih,
+// o2, namedMXBeans);
+ if (ih instanceof MBeanServerInvocationHandler) {
+ return true;
+ } else if (ih instanceof CompositeDataInvocationHandler) {
+ return o2.equals(o1);
+ // We assume the other object has a reasonable equals method
+ }
+ } else if (Proxy.isProxyClass(o2.getClass()))
+ return equal(o2, o1, namedMXBeans);
+ return o1.equals(o2);
+ }
+
+ // We'd use Arrays.deepEquals except we want the test to work on 1.4
+ // Note this code assumes no selfreferential arrays
+ // (as does Arrays.deepEquals)
+ private static boolean deepEqual(Object a1, Object a2,
+ NamedMXBeans namedMXBeans) {
+ int len = Array.getLength(a1);
+ if (len != Array.getLength(a2))
+ return false;
+ for (int i = 0; i < len; i++) {
+ Object e1 = Array.get(a1, i);
+ Object e2 = Array.get(a2, i);
+ if (!equal(e1, e2, namedMXBeans))
+ return false;
+ }
+ return true;
+ }
+
+ // This is needed to work around a bug (5095277)
+ // in CompositeDataSupport.equals
+ private static boolean compositeDataEqual(CompositeData cd1,
+ CompositeData cd2,
+ NamedMXBeans namedMXBeans) {
+ if (cd1 == cd2)
+ return true;
+ if (!cd1.getCompositeType().equals(cd2.getCompositeType()))
+ return false;
+ Collection v1 = cd1.values();
+ Collection v2 = cd2.values();
+ if (v1.size() != v2.size())
+ return false; // should not happen
+ for (Iterator i1 = v1.iterator(), i2 = v2.iterator();
+ i1.hasNext(); ) {
+ if (!equal(i1.next(), i2.next(), namedMXBeans))
+ return false;
+ }
+ return true;
+ }
+
+ // Also needed for 5095277
+ private static boolean proxyEqual(Object proxy1, Object proxy2,
+ NamedMXBeans namedMXBeans) {
+ if (proxy1.getClass() != proxy2.getClass())
+ return proxy1.equals(proxy2);
+ InvocationHandler ih1 = Proxy.getInvocationHandler(proxy1);
+ InvocationHandler ih2 = Proxy.getInvocationHandler(proxy2);
+ if (!(ih1 instanceof CompositeDataInvocationHandler)
+ || !(ih2 instanceof CompositeDataInvocationHandler))
+ return proxy1.equals(proxy2);
+ CompositeData cd1 =
+ ((CompositeDataInvocationHandler) ih1).getCompositeData();
+ CompositeData cd2 =
+ ((CompositeDataInvocationHandler) ih2).getCompositeData();
+ return compositeDataEqual(cd1, cd2, namedMXBeans);
+ }
+
+// private static boolean proxyEqualsObject(MXBeanInvocationHandler ih,
+// Object o,
+// NamedMXBeans namedMXBeans) {
+// if (namedMXBeans.getMBeanServerConnection() !=
+// ih.getMBeanServerConnection())
+// return false;
+//
+// ObjectName on = ih.getObjectName();
+// Object named = namedMXBeans.get(on);
+// if (named == null)
+// return false;
+// return (o == named && ih.getMXBeanInterface().isInstance(named));
+// }
+
+ /* I wanted to call this method toString(Object), but oddly enough
+ this meant that I couldn't call it from the inner class
+ MXBeanImplInvocationHandler, because the inherited Object.toString()
+ prevented that. Surprising behaviour. */
+ static String string(Object o) {
+ if (o == null)
+ return "null";
+ if (o instanceof String)
+ return '"' + (String) o + '"';
+ if (o instanceof Collection)
+ return deepToString((Collection) o);
+ if (o.getClass().isArray())
+ return deepToString(o);
+ return o.toString();
+ }
+
+ private static String deepToString(Object o) {
+ StringBuffer buf = new StringBuffer();
+ buf.append("[");
+ int len = Array.getLength(o);
+ for (int i = 0; i < len; i++) {
+ if (i > 0)
+ buf.append(", ");
+ Object e = Array.get(o, i);
+ buf.append(string(e));
+ }
+ buf.append("]");
+ return buf.toString();
+ }
+
+ private static String deepToString(Collection c) {
+ return deepToString(c.toArray());
+ }
+
+ private static void compareTabularType(TabularType t1, TabularType t2) {
+ if (t1.equals(t2)) {
+ System.out.println("same tabular type");
+ return;
+ }
+ if (t1.getClassName().equals(t2.getClassName()))
+ System.out.println("same class name");
+ if (t1.getDescription().equals(t2.getDescription()))
+ System.out.println("same description");
+ else {
+ System.out.println("t1 description: " + t1.getDescription());
+ System.out.println("t2 description: " + t2.getDescription());
+ }
+ if (t1.getIndexNames().equals(t2.getIndexNames()))
+ System.out.println("same index names");
+ if (t1.getRowType().equals(t2.getRowType()))
+ System.out.println("same row type");
+ }
+}
diff --git a/test/javax/management/mxbean/MerlinMXBean.java b/test/javax/management/mxbean/MerlinMXBean.java
new file mode 100644
index 0000000..3e41bf4
--- /dev/null
+++ b/test/javax/management/mxbean/MerlinMXBean.java
@@ -0,0 +1,457 @@
+/*
+ * Copyright 2005-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import java.util.Arrays;
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeDataView;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+
+public interface MerlinMXBean {
+
+ int PInt = 59;
+ SimpleType PIntType = SimpleType.INTEGER;
+ int getPInt();
+ void setPInt(int x);
+ int opPInt(int x, int y);
+
+ long PLong = Long.MAX_VALUE;
+ SimpleType PLongType = SimpleType.LONG;
+ long getPLong();
+ void setPLong(long x);
+ long opPLong(long x, long y);
+
+ short PShort = 55;
+ SimpleType PShortType = SimpleType.SHORT;
+ short getPShort();
+ void setPShort(short x);
+ short opPShort(short x, short y);
+
+ byte PByte = 13;
+ SimpleType PByteType = SimpleType.BYTE;
+ byte getPByte();
+ void setPByte(byte x);
+ byte opPByte(byte x, byte y);
+
+ char PChar = 'x';
+ SimpleType PCharType = SimpleType.CHARACTER;
+ char getPChar();
+ void setPChar(char x);
+ char opPChar(char x, char y);
+
+ float PFloat = 1.3f;
+ SimpleType PFloatType = SimpleType.FLOAT;
+ float getPFloat();
+ void setPFloat(float x);
+ float opPFloat(float x, float y);
+
+ double PDouble = Double.MAX_VALUE;
+ SimpleType PDoubleType = SimpleType.DOUBLE;
+ double getPDouble();
+ void setPDouble(double x);
+ double opPDouble(double x, double y);
+
+ boolean PBoolean = true;
+ SimpleType PBooleanType = SimpleType.BOOLEAN;
+ boolean getPBoolean();
+ void setPBoolean(boolean x);
+ boolean opPBoolean(boolean x, boolean y);
+
+ Integer WInteger = new Integer(59);
+ SimpleType WIntegerType = SimpleType.INTEGER;
+ Integer getWInteger();
+ void setWInteger(Integer x);
+ Integer opWInteger(Integer x, Integer y);
+
+ Long WLong = new Long(Long.MAX_VALUE);
+ SimpleType WLongType = SimpleType.LONG;
+ Long getWLong();
+ void setWLong(Long x);
+ Long opWLong(Long x, Long y);
+
+ Short WShort = new Short(Short.MAX_VALUE);
+ SimpleType WShortType = SimpleType.SHORT;
+ Short getWShort();
+ void setWShort(Short x);
+ Short opWShort(Short x, Short y);
+
+ Byte WByte = new Byte(Byte.MAX_VALUE);
+ SimpleType WByteType = SimpleType.BYTE;
+ Byte getWByte();
+ void setWByte(Byte x);
+ Byte opWByte(Byte x, Byte y);
+
+ Character WCharacter = new Character('x');
+ SimpleType WCharacterType = SimpleType.CHARACTER;
+ Character getWCharacter();
+ void setWCharacter(Character x);
+ Character opWCharacter(Character x, Character y);
+
+ Float WFloat = new Float(1.3f);
+ SimpleType WFloatType = SimpleType.FLOAT;
+ Float getWFloat();
+ void setWFloat(Float x);
+ Float opWFloat(Float x, Float y);
+
+ Double WDouble = new Double(Double.MAX_VALUE);
+ SimpleType WDoubleType = SimpleType.DOUBLE;
+ Double getWDouble();
+ void setWDouble(Double x);
+ Double opWDouble(Double x, Double y);
+
+ Boolean WBoolean = Boolean.TRUE;
+ SimpleType WBooleanType = SimpleType.BOOLEAN;
+ Boolean getWBoolean();
+ void setWBoolean(Boolean x);
+ Boolean opWBoolean(Boolean x, Boolean y);
+
+ int[] PIntA = {2, 3, 5, 7, 11, 13};
+ ArrayType PIntAType = ArrayTypeMaker.make(SimpleType.INTEGER, true);
+ int[] getPIntA();
+ void setPIntA(int[] x);
+ int[] opPIntA(int[] x, int[] y);
+
+ int[][] PInt2D = {{1, 2}, {3, 4}};
+ ArrayType PInt2DType = ArrayTypeMaker.make(1, PIntAType);
+ int[][] getPInt2D();
+ void setPInt2D(int[][] x);
+ int[][] opPInt2D(int[][] x, int[][] y);
+
+ Integer[] WIntA = {new Integer(3), new Integer(5)};
+ ArrayType WIntAType = ArrayTypeMaker.make(1, SimpleType.INTEGER);
+ Integer[] getWIntA();
+ void setWIntA(Integer[] x);
+ Integer[] opWIntA(Integer[] x, Integer[] y);
+
+ Integer[][] WInt2D = {{new Integer(3)}, {new Integer(5)}};
+ ArrayType WInt2DType = ArrayTypeMaker.make(2, SimpleType.INTEGER);
+ Integer[][] getWInt2D();
+ void setWInt2D(Integer[][] x);
+ Integer[][] opWInt2D(Integer[][] x, Integer[][] y);
+
+ String XString = "yo!";
+ SimpleType XStringType = SimpleType.STRING;
+ String getXString();
+ void setXString(String x);
+ String opXString(String x, String y);
+
+ String[] XStringA = {"hello", "world"};
+ ArrayType XStringAType = ArrayTypeMaker.make(1, SimpleType.STRING);
+ String[] getXStringA();
+ void setXStringA(String[] x);
+ String[] opXStringA(String[] x, String[] y);
+
+ int[] NoInts = {};
+ ArrayType NoIntsType = ArrayTypeMaker.make(SimpleType.INTEGER, true);
+ int[] getNoInts();
+ void setNoInts(int[] x);
+ int[] opNoInts(int[] x, int[] y);
+
+ GetSetBean GetSet = GetSetBean.make(5, "x", new String[] {"a", "b"});
+ CompositeType GetSetType =
+ CompositeTypeMaker.make(GetSetBean.class.getName(),
+ GetSetBean.class.getName(),
+ new String[] {"int", "string", "stringArray"},
+ new String[] {"int", "string", "stringArray"},
+ new OpenType[] {
+ SimpleType.INTEGER,
+ SimpleType.STRING,
+ ArrayTypeMaker.make(1, SimpleType.STRING),
+ });
+ GetSetBean getGetSet();
+ void setGetSet(GetSetBean bean);
+ GetSetBean opGetSet(GetSetBean x, GetSetBean y);
+
+ GetterInterface Interface = new GetterInterface() {
+ public boolean isWhatsit() {
+ return true;
+ }
+
+ public int[] getInts() {
+ return new int[] {1};
+ }
+
+ public String[] getStrings() {
+ return new String[] {"x"};
+ }
+
+ public GetSetBean getGetSet() {
+ return GetSetBean.make(3, "a", new String[] {"b"});
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof GetterInterface))
+ return false;
+ GetterInterface i = (GetterInterface) o;
+ return isWhatsit() == i.isWhatsit() &&
+ Arrays.equals(getInts(), i.getInts()) &&
+ Arrays.equals(getStrings(), i.getStrings()) &&
+ getGetSet().equals(i.getGetSet());
+ }
+ };
+ CompositeType InterfaceType =
+ CompositeTypeMaker.make(GetterInterface.class.getName(),
+ GetterInterface.class.getName(),
+ new String[] {
+ "ints", "getSet", "strings", "whatsit",
+ },
+ new String[] {
+ "ints", "getSet", "strings", "whatsit",
+ },
+ new OpenType[] {
+ ArrayTypeMaker.make(SimpleType.INTEGER, true),
+ GetSetType,
+ ArrayTypeMaker.make(1, SimpleType.STRING),
+ SimpleType.BOOLEAN,
+ });
+ GetterInterface getInterface();
+ void setInterface(GetterInterface i);
+ GetterInterface opInterface(GetterInterface x, GetterInterface y);
+
+ /* Testing that we can use a public no-arg constructor plus a setter
+ * for every getter to reconstruct this object. Note that the
+ * constructor-guessing logic is no longer valid for this class,
+ * so if we can reconstruct it it must be because of the setters.
+ */
+ public static class GetSetBean {
+ public GetSetBean() {
+ this(0, null, null);
+ }
+
+ private GetSetBean(int Int, String string, String[] stringArray) {
+ this.Int = Int;
+ this.string = string;
+ this.stringArray = stringArray;
+ }
+
+ public static GetSetBean
+ make(int Int, String string, String[] stringArray) {
+ GetSetBean b = new GetSetBean(Int, string, stringArray);
+ return b;
+ }
+
+ public int getInt() {
+ return Int;
+ }
+
+ public String getString() {
+ return this.string;
+ }
+
+ public String[] getStringArray() {
+ return this.stringArray;
+ }
+
+ public void setInt(int x) {
+ this.Int = x;
+ }
+
+ public void setString(String string) {
+ this.string = string;
+ }
+
+ public void setStringArray(String[] stringArray) {
+ this.stringArray = stringArray;
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof GetSetBean))
+ return false;
+ GetSetBean b = (GetSetBean) o;
+ return (b.Int == Int &&
+ b.string.equals(string) &&
+ Arrays.equals(b.stringArray, stringArray));
+ }
+
+ String string;
+ String[] stringArray;
+ int Int;
+ }
+
+ public static interface GetterInterface {
+ public String[] getStrings();
+ public int[] getInts();
+ public boolean isWhatsit();
+ public GetSetBean getGetSet();
+
+ // We uselessly mention the public methods inherited from Object because
+ // they should not prevent the interface from being translatable.
+ // We could consider encoding the result of hashCode() and toString()
+ // on the original object that implements this interface into the
+ // generated CompositeData and referencing that in the proxy, but
+ // that seems ambitious for now. Doing it only if hashCode() and/or
+ // toString() are mentioned in the interface is a possibility but
+ // a rather abstruse one.
+ public boolean equals(Object o);
+ public int hashCode();
+ public String toString();
+ }
+
+ public static class ArrayTypeMaker {
+ static ArrayType make(int dims, OpenType baseType) {
+ try {
+ return new ArrayType(dims, baseType);
+ } catch (OpenDataException e) {
+ throw new Error(e);
+ }
+ }
+
+ static ArrayType make(SimpleType baseType, boolean primitiveArray) {
+ try {
+ return new ArrayType(baseType, primitiveArray);
+ } catch (OpenDataException e) {
+ throw new Error(e);
+ }
+ }
+ }
+
+ public static class CompositeTypeMaker {
+ static CompositeType make(String className,
+ String description,
+ String[] itemNames,
+ String[] itemDescriptions,
+ OpenType[] itemTypes) {
+ try {
+ return new CompositeType(className,
+ description,
+ itemNames,
+ itemDescriptions,
+ itemTypes);
+ } catch (OpenDataException e) {
+ throw new Error(e);
+ }
+ }
+ }
+
+ public static interface GraphMXBean {
+ public NodeMXBean[] getNodes();
+ }
+
+ public static class Graph implements GraphMXBean {
+ public Graph(Node... nodes) {
+ for (Node node : nodes)
+ node.setGraph(this);
+ this.nodes = nodes;
+ }
+
+ public NodeMXBean[] getNodes() {
+ return nodes;
+ }
+
+ private final Node[] nodes;
+ }
+
+ public static interface NodeMXBean {
+ public String getName();
+ public GraphMXBean getGraph();
+ }
+
+ public static class Node implements NodeMXBean {
+ public Node(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public GraphMXBean getGraph() {
+ return graph;
+ }
+
+ public void setGraph(Graph graph) {
+ this.graph = graph;
+ }
+
+ private final String name;
+ private Graph graph;
+ }
+
+ SimpleType GraphType = SimpleType.OBJECTNAME;
+ GraphMXBean getGraph();
+ void setGraph(GraphMXBean g);
+ GraphMXBean opGraph(GraphMXBean x, GraphMXBean y);
+ String GraphObjectName = "test:type=GraphMXBean";
+ String NodeAObjectName = "test:type=NodeMXBean,name=a";
+ String NodeBObjectName = "test:type=NodeMXBean,name=b";
+ Node NodeA = new Node("a");
+ Node NodeB = new Node("b");
+ GraphMXBean Graph = new Graph(NodeA, NodeB);
+
+ public static class ExoticCompositeData implements CompositeDataView {
+ private ExoticCompositeData(String whatsit) {
+ this.whatsit = whatsit;
+ }
+
+ public static ExoticCompositeData from(CompositeData cd) {
+ String whatsit = (String) cd.get("whatsit");
+ if (!whatsit.startsWith("!"))
+ throw new IllegalArgumentException(whatsit);
+ return new ExoticCompositeData(whatsit.substring(1));
+ }
+
+ public CompositeData toCompositeData(CompositeType ct) {
+ try {
+ return new CompositeDataSupport(ct, new String[] {"whatsit"},
+ new String[] {"!" + whatsit});
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public String getWhatsit() {
+ return whatsit;
+ }
+
+ public boolean equals(Object o) {
+ return ((o instanceof ExoticCompositeData) &&
+ ((ExoticCompositeData) o).whatsit.equals(whatsit));
+ }
+
+ private final String whatsit;
+
+ public static final CompositeType type;
+ static {
+ try {
+ type =
+ new CompositeType(ExoticCompositeData.class.getName(),
+ ExoticCompositeData.class.getName(),
+ new String[] {"whatsit"},
+ new String[] {"whatsit"},
+ new OpenType[] {SimpleType.STRING});
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ CompositeType ExoticType = ExoticCompositeData.type;
+ ExoticCompositeData getExotic();
+ void setExotic(ExoticCompositeData ecd);
+ ExoticCompositeData opExotic(ExoticCompositeData ecd1,
+ ExoticCompositeData ecd2);
+ ExoticCompositeData Exotic = new ExoticCompositeData("foo");
+}
diff --git a/test/javax/management/mxbean/MiscTest.java b/test/javax/management/mxbean/MiscTest.java
new file mode 100644
index 0000000..17cad8a
--- /dev/null
+++ b/test/javax/management/mxbean/MiscTest.java
@@ -0,0 +1,738 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6175517 6304996
+ * @summary General MXBean test: createMBean, registerMBean, immutableInfo,
+ * interfaceClassName, openType, originalType, StandardMBean,
+ * StandardEmitterMBean.
+ * @author Luis-Miguel Alventosa
+ * @run clean MiscTest
+ * @run build MiscTest
+ * @run main MiscTest
+ */
+
+import java.io.*;
+import java.lang.management.*;
+import javax.management.*;
+import javax.management.openmbean.*;
+
+public class MiscTest {
+
+ private static final MBeanNotificationInfo notifs[] =
+ new MBeanNotificationInfo[] {
+ new MBeanNotificationInfo(
+ new String[] {AttributeChangeNotification.ATTRIBUTE_CHANGE},
+ AttributeChangeNotification.class.getName(),
+ "This notification is emitted when the reset() method is called.")
+ };
+
+ private static Class<?> testClasses[] = {
+ Test11.class, Test12.class,
+ Test21.class, Test22.class,
+ Test31.class, Test32.class,
+ Test33.class, Test34.class,
+ Test41.class, Test42.class,
+ Test43.class, Test44.class,
+ };
+
+ private static Class<?> testIntfs[] = {
+ Test11MBean.class, Test12MBean.class,
+ Test21MXBean.class, Test22MXBean.class,
+ Test31SMB.class, Test32SMB.class,
+ Test33SMB.class, Test34SMB.class,
+ Test41SMX.class, Test42SMX.class,
+ Test43SMX.class, Test44SMX.class,
+ };
+
+ public interface SuperInterface {
+ public String getState();
+ public void setState(String s);
+ public int getNbChanges();
+ public void reset();
+ public void close(boolean force);
+ public MemoryUsage getMemoryUsage();
+ }
+
+ public static class BaseTest {
+
+ public String getState() {
+ return state;
+ }
+
+ public void setState(String s) {
+ state = s;
+ nbChanges++;
+ }
+
+ public int getNbChanges() {
+ return nbChanges;
+ }
+
+ public void reset() {
+ state = "initial state";
+ nbChanges = 0;
+ nbResets++;
+ }
+
+ public String getName() {
+ return "name";
+ }
+
+ public void setName(String s) {
+ }
+
+ public void close(boolean force) {
+ }
+
+ public MemoryUsage getMemoryUsage() {
+ return new MemoryUsage(10, 20, 30, 40);
+ }
+
+ public int getNbResets() {
+ return nbResets;
+ }
+
+ private String state = "initial state";
+ private int nbChanges = 0;
+ private int nbResets = 0;
+ }
+
+ public static class BaseEmitterTest
+ extends NotificationBroadcasterSupport {
+
+ public String getState() {
+ return state;
+ }
+
+ public void setState(String s) {
+ state = s;
+ nbChanges++;
+ }
+
+ public int getNbChanges() {
+ return nbChanges;
+ }
+
+ public void reset() {
+ state = "initial state";
+ nbChanges = 0;
+ nbResets++;
+ }
+
+ public String getName() {
+ return "name";
+ }
+
+ public void setName(String s) {
+ }
+
+ public void close(boolean force) {
+ }
+
+ public MemoryUsage getMemoryUsage() {
+ return new MemoryUsage(10, 20, 30, 40);
+ }
+
+ public int getNbResets() {
+ return nbResets;
+ }
+
+ public MBeanNotificationInfo[] getNotificationInfo() {
+ return notifs;
+ }
+
+ private String state = "initial state";
+ private int nbChanges = 0;
+ private int nbResets = 0;
+ }
+
+ public static interface Test11MBean extends SuperInterface {
+ }
+
+ public static interface Test12MBean extends SuperInterface {
+ }
+
+ public static interface Test21MXBean extends SuperInterface {
+ }
+
+ public static interface Test22MXBean extends SuperInterface {
+ }
+
+ public static interface Test31SMB extends SuperInterface {
+ }
+
+ public static interface Test32SMB extends SuperInterface {
+ }
+
+ public static interface Test33SMB extends SuperInterface {
+ }
+
+ public static interface Test34SMB extends SuperInterface {
+ }
+
+ public static interface Test41SMX extends SuperInterface {
+ }
+
+ public static interface Test42SMX extends SuperInterface {
+ }
+
+ public static interface Test43SMX extends SuperInterface {
+ }
+
+ public static interface Test44SMX extends SuperInterface {
+ }
+
+ public static class Test11 extends BaseTest
+ implements Test11MBean {
+ }
+
+ public static class Test12 extends BaseEmitterTest
+ implements Test12MBean {
+ }
+
+ public static class Test21 extends BaseTest
+ implements Test21MXBean {
+ }
+
+ public static class Test22 extends BaseEmitterTest
+ implements Test22MXBean {
+ }
+
+ public static class Test31 extends BaseTest
+ implements Test31SMB {
+ }
+
+ public static class Test32 extends BaseEmitterTest
+ implements Test32SMB {
+ }
+
+ public static class Test33 extends StandardMBean
+ implements Test33SMB {
+
+ public Test33() {
+ super(Test33SMB.class, false);
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public void setState(String s) {
+ state = s;
+ nbChanges++;
+ }
+
+ public int getNbChanges() {
+ return nbChanges;
+ }
+
+ public void reset() {
+ state = "initial state";
+ nbChanges = 0;
+ nbResets++;
+ }
+
+ public String getName() {
+ return "name";
+ }
+
+ public void setName(String s) {
+ }
+
+ public void close(boolean force) {
+ }
+
+ public MemoryUsage getMemoryUsage() {
+ return new MemoryUsage(10, 20, 30, 40);
+ }
+
+ public int getNbResets() {
+ return nbResets;
+ }
+
+ private String state = "initial state";
+ private int nbChanges = 0;
+ private int nbResets = 0;
+ }
+
+ public static class Test34 extends StandardEmitterMBean
+ implements Test34SMB {
+
+ public Test34() {
+ super(Test34SMB.class, false,
+ new NotificationBroadcasterSupport(notifs));
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public void setState(String s) {
+ state = s;
+ nbChanges++;
+ }
+
+ public int getNbChanges() {
+ return nbChanges;
+ }
+
+ public void reset() {
+ state = "initial state";
+ nbChanges = 0;
+ nbResets++;
+ }
+
+ public String getName() {
+ return "name";
+ }
+
+ public void setName(String s) {
+ }
+
+ public void close(boolean force) {
+ }
+
+ public MemoryUsage getMemoryUsage() {
+ return new MemoryUsage(10, 20, 30, 40);
+ }
+
+ public int getNbResets() {
+ return nbResets;
+ }
+
+ private String state = "initial state";
+ private int nbChanges = 0;
+ private int nbResets = 0;
+ }
+
+ public static class Test41 extends BaseTest
+ implements Test41SMX {
+ }
+
+ public static class Test42 extends BaseEmitterTest
+ implements Test42SMX {
+ }
+
+ public static class Test43 extends StandardMBean
+ implements Test43SMX {
+
+ public Test43() {
+ super(Test43SMX.class, true);
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public void setState(String s) {
+ state = s;
+ nbChanges++;
+ }
+
+ public int getNbChanges() {
+ return nbChanges;
+ }
+
+ public void reset() {
+ state = "initial state";
+ nbChanges = 0;
+ nbResets++;
+ }
+
+ public String getName() {
+ return "name";
+ }
+
+ public void setName(String s) {
+ }
+
+ public void close(boolean force) {
+ }
+
+ public MemoryUsage getMemoryUsage() {
+ return new MemoryUsage(10, 20, 30, 40);
+ }
+
+ public int getNbResets() {
+ return nbResets;
+ }
+
+ private String state = "initial state";
+ private int nbChanges = 0;
+ private int nbResets = 0;
+ }
+
+ public static class Test44 extends StandardEmitterMBean
+ implements Test44SMX {
+
+ public Test44() {
+ super(Test44SMX.class, true,
+ new NotificationBroadcasterSupport(notifs));
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public void setState(String s) {
+ state = s;
+ nbChanges++;
+ }
+
+ public int getNbChanges() {
+ return nbChanges;
+ }
+
+ public void reset() {
+ state = "initial state";
+ nbChanges = 0;
+ nbResets++;
+ }
+
+ public String getName() {
+ return "name";
+ }
+
+ public void setName(String s) {
+ }
+
+ public void close(boolean force) {
+ }
+
+ public MemoryUsage getMemoryUsage() {
+ return new MemoryUsage(10, 20, 30, 40);
+ }
+
+ public int getNbResets() {
+ return nbResets;
+ }
+
+ private String state = "initial state";
+ private int nbChanges = 0;
+ private int nbResets = 0;
+ }
+
+ public static void main(String[] args) throws Exception {
+ // Instantiate the MBean server
+ //
+ echo("\n>>> Create the MBean server");
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+
+ // Get default domain
+ //
+ echo("\n>>> Get the MBean server's default domain");
+ String domain = mbs.getDefaultDomain();
+ echo("\tDefault Domain = " + domain);
+
+ for (int i = 0; i < testClasses.length; i++) {
+ // Create and register the Test MBean
+ //
+ String cn = testClasses[i].getName();
+ String ons = domain + ":type=" + cn;
+ echo("\n>>> Create the " + cn +
+ " MBean within the MBeanServer");
+ echo("\tObjectName = " + ons);
+ ObjectName on = ObjectName.getInstance(ons);
+ if (testClasses[i] == Test31.class ||
+ testClasses[i] == Test41.class) {
+ StandardMBean s = new StandardMBean(
+ testClasses[i].newInstance(),
+ (Class) testIntfs[i],
+ testClasses[i] == Test41.class);
+ mbs.registerMBean(s, on);
+ } else if (testClasses[i] == Test32.class ||
+ testClasses[i] == Test42.class) {
+ Object o = testClasses[i].newInstance();
+ StandardEmitterMBean s = new StandardEmitterMBean(
+ o,
+ (Class) testIntfs[i],
+ testClasses[i] == Test42.class,
+ (NotificationEmitter) o);
+ mbs.registerMBean(s, on);
+ } else {
+ mbs.createMBean(cn, on);
+ }
+
+ // Check notifs
+ //
+ MBeanInfo mbi = mbs.getMBeanInfo(on);
+ MBeanNotificationInfo mbni[] = mbi.getNotifications();
+ if (i % 2 == 0) {
+ if (mbni.length != 0) {
+ throw new IllegalArgumentException(
+ "Should not be a NotificationEmitter");
+ }
+ } else {
+ if (mbni.length != 1) {
+ throw new IllegalArgumentException(
+ "Should not a NotificationEmitter with one notification");
+ }
+ }
+ // Manage the Test MBean
+ //
+ manageMBean(mbs, on, cn);
+ }
+ }
+
+ private static void manageMBean(MBeanServer mbs,
+ ObjectName on,
+ String cn)
+ throws Exception {
+
+ echo("\n>>> Manage the " + cn +
+ " MBean using its attributes ");
+ echo(" and operations exposed for management");
+
+ // Get attribute values
+ printAttributes(mbs, on);
+
+ // Change State attribute
+ echo("\n Setting State attribute to value \"new state\"...");
+ Attribute stateAttribute = new Attribute("State","new state");
+ mbs.setAttribute(on, stateAttribute);
+
+ // Get attribute values
+ printAttributes(mbs, on);
+
+ // Invoking reset operation
+ echo("\n Invoking reset operation...");
+ mbs.invoke(on, "reset", null, null);
+
+ // Invoking close operation
+ echo("\n Invoking close operation...");
+ String type = on.getKeyProperty("type");
+ String signature[] = {"boolean"};
+ mbs.invoke(on, "close", new Object[] {true}, signature);
+
+ // Get attribute values
+ printAttributes(mbs, on);
+
+ // Create proxy
+ if (type.equals(Test11.class.getName())) {
+ Test11MBean p = JMX.newMBeanProxy(mbs,
+ on,
+ Test11MBean.class);
+ // Get attribute values
+ echo("\n Getting attribute values through proxies:");
+ echo("\tState = \"" + p.getState() + "\"");
+ echo("\tNbChanges = " + p.getNbChanges());
+ echo("\tMemoryUsage = " + p.getMemoryUsage());
+ checkDescriptor(mbs, on, "true", Test11MBean.class.getName());
+ } else if (type.equals(Test12.class.getName())) {
+ Test12MBean p = JMX.newMBeanProxy(mbs,
+ on,
+ Test12MBean.class,
+ true);
+ // Get attribute values
+ echo("\n Getting attribute values through proxies:");
+ echo("\tState = \"" + p.getState() + "\"");
+ echo("\tNbChanges = " + p.getNbChanges());
+ echo("\tMemoryUsage = " + p.getMemoryUsage());
+ checkDescriptor(mbs, on, "false", Test12MBean.class.getName());
+ } else if (type.equals(Test21.class.getName())) {
+ Test21MXBean p = JMX.newMXBeanProxy(mbs,
+ on,
+ Test21MXBean.class);
+ // Get attribute values
+ echo("\n Getting attribute values through proxies:");
+ echo("\tState = \"" + p.getState() + "\"");
+ echo("\tNbChanges = " + p.getNbChanges());
+ echo("\tMemoryUsage = " + p.getMemoryUsage());
+ checkDescriptor(mbs, on, "true", Test21MXBean.class.getName());
+ } else if (type.equals(Test22.class.getName())) {
+ Test22MXBean p = JMX.newMXBeanProxy(mbs,
+ on,
+ Test22MXBean.class,
+ true);
+ // Get attribute values
+ echo("\n Getting attribute values through proxies:");
+ echo("\tState = \"" + p.getState() + "\"");
+ echo("\tNbChanges = " + p.getNbChanges());
+ echo("\tMemoryUsage = " + p.getMemoryUsage());
+ checkDescriptor(mbs, on, "true", Test22MXBean.class.getName());
+ } else if (type.equals(Test31.class.getName())) {
+ Test31SMB p = JMX.newMBeanProxy(mbs,
+ on,
+ Test31SMB.class);
+ // Get attribute values
+ echo("\n Getting attribute values through proxies:");
+ echo("\tState = \"" + p.getState() + "\"");
+ echo("\tNbChanges = " + p.getNbChanges());
+ echo("\tMemoryUsage = " + p.getMemoryUsage());
+ checkDescriptor(mbs, on, "true", Test31SMB.class.getName());
+ } else if (type.equals(Test32.class.getName())) {
+ Test32SMB p = JMX.newMBeanProxy(mbs,
+ on,
+ Test32SMB.class,
+ true);
+ // Get attribute values
+ echo("\n Getting attribute values through proxies:");
+ echo("\tState = \"" + p.getState() + "\"");
+ echo("\tNbChanges = " + p.getNbChanges());
+ echo("\tMemoryUsage = " + p.getMemoryUsage());
+ checkDescriptor(mbs, on, "true", Test32SMB.class.getName());
+ } else if (type.equals(Test33.class.getName())) {
+ Test33SMB p = JMX.newMBeanProxy(mbs,
+ on,
+ Test33SMB.class,
+ true);
+ // Get attribute values
+ echo("\n Getting attribute values through proxies:");
+ echo("\tState = \"" + p.getState() + "\"");
+ echo("\tNbChanges = " + p.getNbChanges());
+ echo("\tMemoryUsage = " + p.getMemoryUsage());
+ checkDescriptor(mbs, on, "true", Test33SMB.class.getName());
+ } else if (type.equals(Test34.class.getName())) {
+ Test34SMB p = JMX.newMBeanProxy(mbs,
+ on,
+ Test34SMB.class,
+ true);
+ // Get attribute values
+ echo("\n Getting attribute values through proxies:");
+ echo("\tState = \"" + p.getState() + "\"");
+ echo("\tNbChanges = " + p.getNbChanges());
+ echo("\tMemoryUsage = " + p.getMemoryUsage());
+ checkDescriptor(mbs, on, "true", Test34SMB.class.getName());
+ } else if (type.equals(Test41.class.getName())) {
+ Test41SMX p = JMX.newMXBeanProxy(mbs,
+ on,
+ Test41SMX.class);
+ // Get attribute values
+ echo("\n Getting attribute values through proxies:");
+ echo("\tState = \"" + p.getState() + "\"");
+ echo("\tNbChanges = " + p.getNbChanges());
+ echo("\tMemoryUsage = " + p.getMemoryUsage());
+ checkDescriptor(mbs, on, "true", Test41SMX.class.getName());
+ } else if (type.equals(Test42.class.getName())) {
+ Test42SMX p = JMX.newMXBeanProxy(mbs,
+ on,
+ Test42SMX.class,
+ true);
+ // Get attribute values
+ echo("\n Getting attribute values through proxies:");
+ echo("\tState = \"" + p.getState() + "\"");
+ echo("\tNbChanges = " + p.getNbChanges());
+ echo("\tMemoryUsage = " + p.getMemoryUsage());
+ checkDescriptor(mbs, on, "true", Test42SMX.class.getName());
+ } else if (type.equals(Test43.class.getName())) {
+ Test43SMX p = JMX.newMXBeanProxy(mbs,
+ on,
+ Test43SMX.class);
+ // Get attribute values
+ echo("\n Getting attribute values through proxies:");
+ echo("\tState = \"" + p.getState() + "\"");
+ echo("\tNbChanges = " + p.getNbChanges());
+ echo("\tMemoryUsage = " + p.getMemoryUsage());
+ checkDescriptor(mbs, on, "true", Test43SMX.class.getName());
+ } else if (type.equals(Test44.class.getName())) {
+ Test44SMX p = JMX.newMXBeanProxy(mbs,
+ on,
+ Test44SMX.class,
+ true);
+ // Get attribute values
+ echo("\n Getting attribute values through proxies:");
+ echo("\tState = \"" + p.getState() + "\"");
+ echo("\tNbChanges = " + p.getNbChanges());
+ echo("\tMemoryUsage = " + p.getMemoryUsage());
+ checkDescriptor(mbs, on, "true", Test44SMX.class.getName());
+ } else {
+ throw new IllegalArgumentException("Invalid MBean type");
+ }
+ }
+
+ private static void printAttributes(MBeanServer mbs,
+ ObjectName on)
+ throws Exception {
+ echo("\n Getting attribute values:");
+ String state = (String) mbs.getAttribute(on, "State");
+ Integer nbChanges = (Integer) mbs.getAttribute(on,"NbChanges");
+ echo("\tState = \"" + state + "\"");
+ echo("\tNbChanges = " + nbChanges);
+ String type = on.getKeyProperty("type");
+ if (type.indexOf("Test2") != -1 || type.indexOf("Test4") != -1) {
+ CompositeData memoryUsage =
+ (CompositeData) mbs.getAttribute(on, "MemoryUsage");
+ echo("\tMemoryUsage = " + memoryUsage);
+ } else {
+ MemoryUsage memoryUsage =
+ (MemoryUsage) mbs.getAttribute(on, "MemoryUsage");
+ echo("\tMemoryUsage = " + memoryUsage);
+ }
+ }
+
+ public static void checkDescriptor(MBeanServer mbs,
+ ObjectName on,
+ String immutable,
+ String intf)
+ throws Exception {
+
+ MBeanInfo mbi = mbs.getMBeanInfo(on);
+
+ Descriptor d = mbi.getDescriptor();
+ if (d == null || d.getFieldNames().length == 0)
+ throw new IllegalArgumentException("Empty descriptor");
+ if (!d.getFieldValue("immutableInfo").equals(immutable)) {
+ final String msg =
+ "Bad descriptor: expected immutableInfo=" + immutable + ": " + d;
+ throw new IllegalArgumentException(msg);
+ }
+ if (!d.getFieldValue("interfaceClassName").equals(intf)) {
+ final String msg =
+ "Bad descriptor: expected interfaceClassName=" + intf + ": " + d;
+ throw new IllegalArgumentException(msg);
+ }
+
+ if (intf.indexOf("MX") != -1) {
+ MBeanAttributeInfo attrs[] = mbi.getAttributes();
+ if (attrs == null || attrs.length == 0)
+ throw new IllegalArgumentException("No attributes");
+ boolean nbChangesFound = false;
+ for (MBeanAttributeInfo attr : attrs) {
+ if (attr.getName().equals("NbChanges")) {
+ nbChangesFound = true;
+ Descriptor ad = attr.getDescriptor();
+ OpenType<?> opty = (OpenType<?>)
+ ad.getFieldValue("openType");
+ if (!opty.equals(SimpleType.INTEGER)) {
+ throw new IllegalArgumentException("Open type should " +
+ "be INTEGER: " + opty);
+ }
+ String orty =
+ (String) ad.getFieldValue("originalType");
+ if (!orty.equals(Integer.TYPE.getName())) {
+ throw new IllegalArgumentException("Orig type should " +
+ "be int: " + orty);
+ }
+ }
+ }
+ if (!nbChangesFound)
+ throw new IllegalArgumentException("Did not find NbChanges");
+ }
+ }
+
+ private static void echo(String msg) {
+ System.out.println(msg);
+ }
+}
diff --git a/test/javax/management/mxbean/OperationImpactTest.java b/test/javax/management/mxbean/OperationImpactTest.java
new file mode 100644
index 0000000..836f459
--- /dev/null
+++ b/test/javax/management/mxbean/OperationImpactTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6320104
+ * @summary Check that MXBean operations have impact UNKNOWN.
+ * @author Eamonn McManus
+ * @run clean OperationImpactTest
+ * @run build OperationImpactTest
+ * @run main OperationImpactTest
+ */
+
+import javax.management.*;
+import javax.management.openmbean.*;
+
+public class OperationImpactTest {
+ public static interface ThingMXBean {
+ void thing();
+ }
+ public static class Thing implements ThingMXBean {
+ public void thing() {}
+ }
+
+ public static void main(String[] args) throws Exception {
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ ObjectName on = new ObjectName("a:b=c");
+ Thing thing = new Thing();
+ mbs.registerMBean(thing, on);
+ MBeanInfo mbi = mbs.getMBeanInfo(on);
+ MBeanOperationInfo[] ops = mbi.getOperations();
+ if (ops.length != 1)
+ throw new Exception("TEST FAILED: several ops: " + mbi);
+ MBeanOperationInfo op = ops[0];
+ if (!op.getName().equals("thing"))
+ throw new Exception("TEST FAILED: wrong op name: " + op);
+ if (op.getImpact() != MBeanOperationInfo.UNKNOWN)
+ throw new Exception("TEST FAILED: wrong impact: " + op);
+
+ // Also check that constructing an OpenMBeanOperationInfo with an
+ // UNKNOWN impact works
+ op = new OpenMBeanOperationInfoSupport("name", "descr", null,
+ SimpleType.VOID,
+ MBeanOperationInfo.UNKNOWN);
+ if (op.getImpact() != MBeanOperationInfo.UNKNOWN)
+ throw new Exception("TEST FAILED: wrong impact: " + op);
+
+ System.out.println("TEST PASSED");
+ }
+}
diff --git a/test/javax/management/mxbean/OverloadTest.java b/test/javax/management/mxbean/OverloadTest.java
new file mode 100644
index 0000000..eeb7d62
--- /dev/null
+++ b/test/javax/management/mxbean/OverloadTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6175517
+ * @summary Test that MXBean interfaces can contain overloaded methods
+ * @author Eamonn McManus
+ * @run clean OverloadTest
+ * @run build OverloadTest
+ * @run main OverloadTest
+ */
+
+import java.lang.management.*;
+import javax.management.*;
+
+public class OverloadTest {
+ public static void main(String[] args) throws Exception {
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ ObjectName on = new ObjectName("a:b=c");
+ OverloadMXBean overloadImpl = new OverloadImpl();
+ mbs.registerMBean(overloadImpl, on);
+ OverloadMXBean p = JMX.newMXBeanProxy(mbs, on, OverloadMXBean.class);
+ check(p.notOverloaded(5), "notOverloaded");
+ check(p.overloaded(), "overloaded()");
+ check(p.overloaded(5), "overloaded(int)");
+ check(p.overloaded("x"), "overloaded(String)");
+ check(p.overloaded(36, 64), "overloaded(int, int)");
+
+// ObjectName threadingName = new ObjectName("java.lang:type=Threading");
+// ThreadMXBean t =
+// JMX.newMXBeanProxy(mbs, threadingName, ThreadMXBean.class);
+// long[] ids = t.getAllThreadIds();
+// ThreadInfo ti = t.getThreadInfo(ids[0]);
+
+ if (failure != null)
+ throw new Exception(failure);
+
+ }
+
+ private static void check(String got, String expect) {
+ if (!expect.equals(got)) {
+ failure = "FAILED: got \"" + got + "\", expected \"" + expect + "\"";
+ System.out.println(failure);
+ }
+ }
+
+ public static interface OverloadMXBean {
+ String notOverloaded(int x);
+ String overloaded();
+ String overloaded(int x);
+ String overloaded(String x);
+ String overloaded(int x, int y);
+ }
+
+ public static class OverloadImpl implements OverloadMXBean {
+ public String notOverloaded(int x) {
+ return "notOverloaded";
+ }
+
+ public String overloaded() {
+ return "overloaded()";
+ }
+
+ public String overloaded(int x) {
+ return "overloaded(int)";
+ }
+
+ public String overloaded(String x) {
+ return "overloaded(String)";
+ }
+
+ public String overloaded(int x, int y) {
+ return "overloaded(int, int)";
+ }
+ }
+
+ private static String failure;
+}
diff --git a/test/javax/management/mxbean/PreRegisterNameTest.java b/test/javax/management/mxbean/PreRegisterNameTest.java
new file mode 100644
index 0000000..af08b3b
--- /dev/null
+++ b/test/javax/management/mxbean/PreRegisterNameTest.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6448042
+ * @summary Test that MXBeans can define their own names in preRegister
+ * @author Eamonn McManus
+ */
+
+import java.lang.management.ManagementFactory;
+import java.lang.reflect.Constructor;
+import javax.management.MBeanRegistration;
+import javax.management.MBeanServer;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+import javax.management.StandardMBean;
+
+/*
+ * Test that an MXBean can decide its name by returning a value from
+ * the preRegister method. Also test the same thing for Standard MBeans
+ * for good measure.
+ */
+public class PreRegisterNameTest {
+ public static interface SpumeMXBean {}
+
+ public static class Spume implements SpumeMXBean, MBeanRegistration {
+ private ObjectName realName;
+
+ public Spume(ObjectName realName) {
+ this.realName = realName;
+ }
+
+ public void preDeregister() throws Exception {
+ }
+
+ public void postDeregister() {
+ }
+
+ public void postRegister(Boolean registrationDone) {
+ }
+
+ public ObjectName preRegister(MBeanServer server, ObjectName name) {
+ return realName;
+ }
+ }
+
+ public static interface ThingMBean {
+ public boolean getNoddy();
+ }
+
+ public static class Thing implements ThingMBean, MBeanRegistration {
+ private ObjectName realName;
+
+ public Thing(ObjectName realName) {
+ this.realName = realName;
+ }
+
+ public ObjectName preRegister(MBeanServer mbs, ObjectName name) {
+ return realName;
+ }
+
+ public void postRegister(Boolean done) {}
+
+ public void preDeregister() {}
+
+ public void postDeregister() {}
+
+ public boolean getNoddy() {
+ return true;
+ }
+ }
+
+ public static class XThing extends StandardMBean implements ThingMBean {
+ private ObjectName realName;
+
+ public XThing(ObjectName realName) {
+ super(ThingMBean.class, false);
+ this.realName = realName;
+ }
+
+ @Override
+ public ObjectName preRegister(MBeanServer server, ObjectName name) {
+ return realName;
+ }
+
+ public boolean getNoddy() {
+ return false;
+ }
+ }
+
+ public static class XSpume extends StandardMBean implements SpumeMXBean {
+ private ObjectName realName;
+
+ public XSpume(ObjectName realName) {
+ super(SpumeMXBean.class, true);
+ this.realName = realName;
+ }
+
+ @Override
+ public ObjectName preRegister(MBeanServer server, ObjectName name)
+ throws Exception {
+ super.preRegister(server, realName);
+ return realName;
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ for (Class<?> c : new Class<?>[] {
+ Spume.class, Thing.class, XSpume.class, XThing.class
+ }) {
+ for (ObjectName n : new ObjectName[] {null, new ObjectName("a:b=c")}) {
+ System.out.println("Class " + c.getName() + " with name " + n +
+ "...");
+ ObjectName realName = new ObjectName("a:type=" + c.getName());
+ Constructor<?> constr = c.getConstructor(ObjectName.class);
+ Object mbean = constr.newInstance(realName);
+ ObjectInstance oi;
+ String what =
+ "Registering MBean of type " + c.getName() + " under name " +
+ "<" + n + ">: ";
+ try {
+ oi = mbs.registerMBean(mbean, n);
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(what + " got " + e);
+ continue;
+ }
+ ObjectName registeredName = oi.getObjectName();
+ if (!registeredName.equals(realName))
+ fail(what + " registered as " + registeredName);
+ if (!mbs.isRegistered(realName)) {
+ fail(what + " not registered as expected");
+ }
+ mbs.unregisterMBean(registeredName);
+ }
+ }
+ System.err.flush();
+ if (failures == 0)
+ System.out.println("TEST PASSED");
+ else
+ throw new Exception("TEST FAILED: " + failure);
+ }
+
+ private static void fail(String msg) {
+ System.err.println("FAILED: " + msg);
+ failure = msg;
+ failures++;
+ }
+
+ private static int failures;
+ private static String failure;
+}
diff --git a/test/javax/management/mxbean/PropertyNamesTest.java b/test/javax/management/mxbean/PropertyNamesTest.java
new file mode 100644
index 0000000..568f3f0
--- /dev/null
+++ b/test/javax/management/mxbean/PropertyNamesTest.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2005-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6175517
+ * @summary Test the PropertyNames annotation with MXBeans
+ * @author Eamonn McManus
+ * @run clean PropertyNamesTest
+ * @run build PropertyNamesTest
+ * @run main PropertyNamesTest
+ */
+
+import java.beans.ConstructorProperties;
+import java.util.Collections;
+import java.util.List;
+import javax.management.JMX;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectName;
+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 PropertyNamesTest {
+ public static void main(String[] args) throws Exception {
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ ObjectName pointName = new ObjectName("a:type=Point");
+ PointMXBean pointmx = new PointImpl();
+ mbs.registerMBean(pointmx, pointName);
+ Point point = new Point(1, 2);
+ PointMXBean pointproxy =
+ JMX.newMXBeanProxy(mbs, pointName, PointMXBean.class);
+ Point point1 = pointproxy.identity(point);
+ if (point1.getX() != point.getX() || point1.getY() != point.getY())
+ throw new Exception("Point doesn't match");
+ System.out.println("Point test passed");
+
+ ObjectName evolveName = new ObjectName("a:type=Evolve");
+ EvolveMXBean evolvemx = new EvolveImpl();
+ mbs.registerMBean(evolvemx, evolveName);
+ Evolve evolve =
+ new Evolve(59, "tralala", Collections.singletonList("tiddly"));
+ EvolveMXBean evolveProxy =
+ JMX.newMXBeanProxy(mbs, evolveName, EvolveMXBean.class);
+ Evolve evolve1 = evolveProxy.identity(evolve);
+ if (evolve1.getOldInt() != evolve.getOldInt()
+ || !evolve1.getNewString().equals(evolve.getNewString())
+ || !evolve1.getNewerList().equals(evolve.getNewerList()))
+ throw new Exception("Evolve doesn't match");
+ System.out.println("Evolve test passed");
+
+ ObjectName evolvedName = new ObjectName("a:type=Evolved");
+ EvolveMXBean evolvedmx = new EvolveImpl();
+ mbs.registerMBean(evolvedmx, evolvedName);
+ CompositeType evolvedType =
+ new CompositeType("Evolved", "descr", new String[] {"oldInt"},
+ new String[] {"oldInt descr"},
+ new OpenType[] {SimpleType.INTEGER});
+ CompositeData evolvedData =
+ new CompositeDataSupport(evolvedType, new String[] {"oldInt"},
+ new Object[] {5});
+ CompositeData evolved1 = (CompositeData)
+ mbs.invoke(evolvedName, "identity", new Object[] {evolvedData},
+ new String[] {CompositeData.class.getName()});
+ if ((Integer) evolved1.get("oldInt") != 5
+ || !evolved1.get("newString").equals("defaultString")
+ || ((String[]) evolved1.get("newerList")).length != 0)
+ throw new Exception("Evolved doesn't match: " + evolved1);
+ System.out.println("Evolved test passed");
+ }
+
+ public static class Point {
+ @ConstructorProperties({"x", "y"})
+ public Point(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ public int getY() {
+ return y;
+ }
+
+ public int getX() {
+ return x;
+ }
+
+ private final int x, y;
+ }
+
+ public static interface PointMXBean {
+ Point identity(Point x);
+ }
+
+ public static class PointImpl implements PointMXBean {
+ public Point identity(Point x) {
+ return x;
+ }
+ }
+
+ public static class Evolve {
+ @ConstructorProperties({"oldInt"})
+ public Evolve(int oldInt) {
+ this(oldInt, "defaultString");
+ }
+
+ @ConstructorProperties({"oldInt", "newString"})
+ public Evolve(int oldInt, String newString) {
+ this(oldInt, newString, Collections.<String>emptyList());
+ }
+
+ @ConstructorProperties({"oldInt", "newString", "newerList"})
+ public Evolve(int oldInt, String newString, List<String> newerList) {
+ this.oldInt = oldInt;
+ this.newString = newString;
+ this.newerList = newerList;
+ }
+
+ public int getOldInt() {
+ return oldInt;
+ }
+
+ public String getNewString() {
+ return newString;
+ }
+
+ public List<String> getNewerList() {
+ return newerList;
+ }
+
+ private final int oldInt;
+ private final String newString;
+ private final List<String> newerList;
+ }
+
+ public static interface EvolveMXBean {
+ Evolve identity(Evolve x);
+ }
+
+ public static class EvolveImpl implements EvolveMXBean {
+ public Evolve identity(Evolve x) {
+ return x;
+ }
+ }
+}
diff --git a/test/javax/management/mxbean/RandomMXBeanTest.java b/test/javax/management/mxbean/RandomMXBeanTest.java
new file mode 100644
index 0000000..9bd3571
--- /dev/null
+++ b/test/javax/management/mxbean/RandomMXBeanTest.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* This test essentially duplicates the functionality of MXBeanTest.java.
+ * See LeakTest.java for an explanation.
+ */
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.HashMap;
+import java.util.Map;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.JMX;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
+
+public class RandomMXBeanTest {
+ public static interface StupidMXBean {
+ public int ZERO = Integer.parseInt("0");
+ public int getZero();
+ public int identity(int x);
+ }
+
+ public static class StupidImpl implements StupidMXBean {
+ public int getZero() {
+ return 0;
+ }
+
+ public int identity(int x) {
+ return x;
+ }
+ }
+
+ public static interface ReferMXBean {
+ public StupidMXBean getStupid();
+ }
+
+ public static class ReferImpl implements ReferMXBean {
+ private final StupidMXBean stupid;
+
+ ReferImpl(StupidMXBean stupid) {
+ this.stupid = stupid;
+ }
+
+ public StupidMXBean getStupid() {
+ return stupid;
+ }
+ }
+
+ private static class WrapInvocationHandler implements InvocationHandler {
+ private final Object wrapped;
+
+ WrapInvocationHandler(Object wrapped) {
+ this.wrapped = wrapped;
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args)
+ throws Throwable {
+ return method.invoke(wrapped, args);
+ }
+ }
+
+ private static class DullInvocationHandler implements InvocationHandler {
+ private static Map<Class<?>, Object> zeroMap =
+ new HashMap<Class<?>, Object>();
+ static {
+ zeroMap.put(byte.class, (byte) 0);
+ zeroMap.put(int.class, 0);
+ zeroMap.put(short.class, (short) 0);
+ zeroMap.put(long.class, 0L);
+ zeroMap.put(float.class, 0F);
+ zeroMap.put(double.class, 0.0);
+ zeroMap.put(boolean.class, false);
+ zeroMap.put(char.class, '\0');
+ }
+
+ public static Object zeroFor(Class<?> c) {
+ if (c.isPrimitive())
+ return zeroMap.get(c);
+ else
+ return null;
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args)
+ throws Throwable {
+ Class<?> retType = method.getReturnType();
+ if (!retType.isPrimitive())
+ return null;
+ return zeroMap.get(retType);
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ ObjectName name = new ObjectName("a:b=c");
+ StupidMXBean stupid = new StupidImpl();
+ mbs.registerMBean(stupid, name);
+ ObjectName referName = new ObjectName("a:c=d");
+ mbs.registerMBean(new ReferImpl(stupid), referName);
+ System.out.println(mbs.getMBeanInfo(name));
+ StupidMXBean stupid2 = (StupidMXBean)
+ Proxy.newProxyInstance(StupidMXBean.class.getClassLoader(),
+ new Class<?>[] {StupidMXBean.class},
+ new WrapInvocationHandler(stupid));
+ ObjectName stupidName2 = new ObjectName("a:d=e");
+ mbs.registerMBean(stupid2, stupidName2);
+ Field zero = StupidMXBean.class.getField("ZERO");
+ System.out.println("Zero field = " + zero.get(null));
+ test(mbs, MerlinMXBean.class);
+ test(mbs, TigerMXBean.class);
+
+ StupidMXBean proxy = JMX.newMXBeanProxy(mbs, name, StupidMXBean.class);
+ System.out.println("Zero = " + proxy.getZero());
+ System.out.println("One = " + proxy.identity(1));
+ ReferMXBean referProxy =
+ JMX.newMXBeanProxy(mbs, referName, ReferMXBean.class);
+ StupidMXBean stupidProxy2 = referProxy.getStupid();
+ System.out.println("Same proxy: " + (proxy == stupidProxy2));
+ Method[] methods = StupidMXBean.class.getMethods();
+ for (Method method : methods) {
+ if (method.getParameterTypes().length == 0)
+ method.invoke(proxy, new Object[0]);
+ }
+ }
+
+ private static <T> void test(MBeanServer mbs, Class<T> c) throws Exception {
+ System.out.println("Testing " + c.getName());
+ T merlin = c.cast(
+ Proxy.newProxyInstance(c.getClassLoader(),
+ new Class<?>[] {c},
+ new DullInvocationHandler()));
+ ObjectName merlinName = new ObjectName("a:type=" + c.getName());
+ mbs.registerMBean(merlin, merlinName);
+ System.out.println(mbs.getMBeanInfo(merlinName));
+ T merlinProxy = JMX.newMXBeanProxy(mbs, merlinName, c);
+ Method[] merlinMethods = c.getMethods();
+ for (Method m : merlinMethods) {
+ Class<?>[] types = m.getParameterTypes();
+ Object[] params = new Object[types.length];
+ for (int i = 0; i < types.length; i++)
+ params[i] = DullInvocationHandler.zeroFor(types[i]);
+ System.out.println("Invoking " + m.getName());
+ m.invoke(merlinProxy, (Object[]) params);
+ }
+ }
+}
diff --git a/test/javax/management/mxbean/StandardMBeanOverrideTest.java b/test/javax/management/mxbean/StandardMBeanOverrideTest.java
new file mode 100644
index 0000000..3c785c4
--- /dev/null
+++ b/test/javax/management/mxbean/StandardMBeanOverrideTest.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6283045
+ * @summary Test the correctness of immutableInfo field in MBeanInfo descriptor
+ * when overriding the methods cacheMBeanInfo, getCachedMBeanInfo,
+ * getMBeanInfo and getNotificationInfo in StandardMBean and
+ * StandardEmitterMBean.
+ * @author Luis-Miguel Alventosa
+ * @run clean StandardMBeanOverrideTest
+ * @run build StandardMBeanOverrideTest
+ * @run main StandardMBeanOverrideTest
+ */
+
+import java.io.*;
+import java.lang.management.*;
+import javax.management.*;
+import javax.management.openmbean.*;
+
+public class StandardMBeanOverrideTest {
+
+ private static Object testInstances[] = {
+ new TestClass0(false),
+ new TestClass1(false),
+ new TestClass2(false),
+ new TestClass3(false),
+ new TestClass4(false),
+ new TestClass5(false),
+ new TestClass6(false),
+ new TestClass7(false),
+ new TestClass8(false),
+ new TestClass9(false),
+ new TestClass0(true),
+ new TestClass1(true),
+ new TestClass2(true),
+ new TestClass3(true),
+ new TestClass4(true),
+ new TestClass5(true),
+ new TestClass6(true),
+ new TestClass7(true),
+ new TestClass8(true),
+ new TestClass9(true),
+ };
+
+ public interface ImmutableInfo {
+ }
+
+ public interface NonImmutableInfo {
+ }
+
+ public interface TestInterface {
+ }
+
+ public static class TestClass0
+ extends StandardMBean
+ implements TestInterface, ImmutableInfo {
+ public TestClass0(boolean mxbean) {
+ super(TestInterface.class, mxbean);
+ }
+ }
+
+ public static class TestClass1
+ extends StandardMBean
+ implements TestInterface, NonImmutableInfo {
+ public TestClass1(boolean mxbean) {
+ super(TestInterface.class, mxbean);
+ }
+ protected void cacheMBeanInfo(MBeanInfo info) {
+ super.cacheMBeanInfo(info);
+ }
+ }
+
+ public static class TestClass2
+ extends StandardMBean
+ implements TestInterface, NonImmutableInfo {
+ public TestClass2(boolean mxbean) {
+ super(TestInterface.class, mxbean);
+ }
+ protected MBeanInfo getCachedMBeanInfo() {
+ return super.getCachedMBeanInfo();
+ }
+ }
+
+ public static class TestClass3
+ extends StandardMBean
+ implements TestInterface, NonImmutableInfo {
+ public TestClass3(boolean mxbean) {
+ super(TestInterface.class, mxbean);
+ }
+ public MBeanInfo getMBeanInfo() {
+ return super.getMBeanInfo();
+ }
+ }
+
+ public static class TestClass4
+ extends StandardMBean
+ implements TestInterface, ImmutableInfo {
+ public TestClass4(boolean mxbean) {
+ super(TestInterface.class, mxbean);
+ }
+ public MBeanNotificationInfo[] getNotificationInfo() {
+ return new MBeanNotificationInfo[0];
+ }
+ }
+
+ public static class TestClass5
+ extends StandardEmitterMBean
+ implements TestInterface, ImmutableInfo {
+ public TestClass5(boolean mxbean) {
+ super(TestInterface.class, mxbean,
+ new NotificationBroadcasterSupport());
+ }
+ }
+
+ public static class TestClass6
+ extends StandardEmitterMBean
+ implements TestInterface, NonImmutableInfo {
+ public TestClass6(boolean mxbean) {
+ super(TestInterface.class, mxbean,
+ new NotificationBroadcasterSupport());
+ }
+ protected void cacheMBeanInfo(MBeanInfo info) {
+ super.cacheMBeanInfo(info);
+ }
+ }
+
+ public static class TestClass7
+ extends StandardEmitterMBean
+ implements TestInterface, NonImmutableInfo {
+ public TestClass7(boolean mxbean) {
+ super(TestInterface.class, mxbean,
+ new NotificationBroadcasterSupport());
+ }
+ protected MBeanInfo getCachedMBeanInfo() {
+ return super.getCachedMBeanInfo();
+ }
+ }
+
+ public static class TestClass8
+ extends StandardEmitterMBean
+ implements TestInterface, NonImmutableInfo {
+ public TestClass8(boolean mxbean) {
+ super(TestInterface.class, mxbean,
+ new NotificationBroadcasterSupport());
+ }
+ public MBeanInfo getMBeanInfo() {
+ return super.getMBeanInfo();
+ }
+ }
+
+ public static class TestClass9
+ extends StandardEmitterMBean
+ implements TestInterface, NonImmutableInfo {
+ public TestClass9(boolean mxbean) {
+ super(TestInterface.class, mxbean,
+ new NotificationBroadcasterSupport());
+ }
+ public MBeanNotificationInfo[] getNotificationInfo() {
+ return new MBeanNotificationInfo[0];
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ int error = 0;
+
+ // Instantiate the MBean server
+ //
+ echo("\n>>> Create the MBean server");
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+
+ // Get default domain
+ //
+ echo("\n>>> Get the MBean server's default domain");
+ String domain = mbs.getDefaultDomain();
+ echo("\tDefault Domain = " + domain);
+
+ for (int i = 0; i < testInstances.length; i++) {
+ // Create and register the TestClass MBean
+ //
+ String cn = testInstances[i].getClass().getName();
+ String ons = domain + ":type=" + cn + ",name=" + i;
+ echo("\n>>> Create the " + cn +
+ " MBean within the MBeanServer");
+ echo("\tObjectName = " + ons);
+ ObjectName on = ObjectName.getInstance(ons);
+ mbs.registerMBean(testInstances[i], on);
+
+ // Check immutableInfo field in descriptor
+ //
+ MBeanInfo mbi = mbs.getMBeanInfo(on);
+ Descriptor d = mbi.getDescriptor();
+ echo("MBeanInfo descriptor = " + d);
+ if (d == null || d.getFieldNames().length == 0) {
+ error++;
+ echo("Descriptor is null or empty");
+ continue;
+ }
+ if (testInstances[i] instanceof ImmutableInfo) {
+ if ("true".equals(d.getFieldValue("immutableInfo"))) {
+ echo("OK: immutableInfo field is true");
+ } else {
+ echo("KO: immutableInfo field should be true");
+ error++;
+ }
+ continue;
+ }
+ if (testInstances[i] instanceof NonImmutableInfo) {
+ if ("false".equals(d.getFieldValue("immutableInfo"))) {
+ echo("OK: immutableInfo field is false");
+ } else {
+ echo("KO: immutableInfo field should be false");
+ error++;
+ }
+ continue;
+ }
+ }
+
+ if (error > 0) {
+ echo("\nTest failed! " + error + " errors.\n");
+ throw new IllegalArgumentException("Test failed");
+ } else {
+ echo("\nTest passed!\n");
+ }
+ }
+
+ private static void echo(String msg) {
+ System.out.println(msg);
+ }
+}
diff --git a/test/javax/management/mxbean/ThreadMXBeanTest.java b/test/javax/management/mxbean/ThreadMXBeanTest.java
new file mode 100644
index 0000000..2f79d8a
--- /dev/null
+++ b/test/javax/management/mxbean/ThreadMXBeanTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6305746
+ * @summary Test that the null values returned by the ThreadMXBean work.
+ * @author Eamonn McManus
+ * @run clean ThreadMXBeanTest
+ * @run build ThreadMXBeanTest
+ * @run main ThreadMXBeanTest
+ */
+
+import java.lang.management.*;
+import java.util.*;
+import javax.management.*;
+
+public class ThreadMXBeanTest {
+ public static void main(String[] args) throws Exception {
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ ThreadMXBean tmb = ManagementFactory.getThreadMXBean();
+ StandardMBean smb = new StandardMBean(tmb, ThreadMXBean.class, true);
+ ObjectName on = new ObjectName("a:type=ThreadMXBean");
+ mbs.registerMBean(smb, on);
+ ThreadMXBean proxy = JMX.newMXBeanProxy(mbs, on, ThreadMXBean.class);
+ long[] ids1 = proxy.getAllThreadIds();
+
+ // Add some random ids to the list so we'll get back null ThreadInfo
+ long[] ids2 = Arrays.copyOf(ids1, ids1.length + 10);
+ Random r = new Random();
+ for (int i = ids1.length; i < ids2.length; i++)
+ ids2[i] = Math.abs(r.nextLong());
+ // Following line produces an exception if null values not handled
+ ThreadInfo[] info = proxy.getThreadInfo(ids2);
+ boolean sawNull = false;
+ for (ThreadInfo ti : info) {
+ if (ti == null)
+ sawNull = true;
+ }
+ if (!sawNull)
+ throw new Exception("No null value in returned array");
+ System.out.println("TEST PASSED");
+ }
+}
diff --git a/test/javax/management/mxbean/TigerMXBean.java b/test/javax/management/mxbean/TigerMXBean.java
new file mode 100644
index 0000000..f4f652c
--- /dev/null
+++ b/test/javax/management/mxbean/TigerMXBean.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2005-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import java.beans.ConstructorProperties;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularType;
+
+public interface TigerMXBean {
+
+ class Point {
+ @ConstructorProperties({"x", "y"})
+ public Point(double x, double y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof Point))
+ return false;
+ Point p = (Point) o;
+ return p.x == x && p.y == y;
+ }
+
+ public int hashCode() {
+ return new Double(x).hashCode() ^ new Double(y).hashCode();
+ }
+
+ public double getX() {return x;}
+ public double getY() {return y;}
+ private final double x, y;
+ }
+
+ Point Point = new Point(1.5, 2.5);
+ CompositeType PointType = MerlinMXBean.CompositeTypeMaker.make(
+ Point.class.getName(),
+ Point.class.getName(),
+ new String[] {"x", "y"},
+ new String[] {"x", "y"},
+ new OpenType[] {SimpleType.DOUBLE, SimpleType.DOUBLE});
+ Point getPoint();
+ void setPoint(Point x);
+ Point opPoint(Point x, Point y);
+
+ enum Tuiseal {AINMNEACH, GAIRMEACH, GINIDEACH, TABHARTHACH}
+ Tuiseal Enum = Tuiseal.GINIDEACH;
+ SimpleType EnumType = SimpleType.STRING;
+ Tuiseal getEnum();
+ void setEnum(Tuiseal x);
+ Tuiseal opEnum(Tuiseal x, Tuiseal y);
+
+ List<String> StringList = Arrays.asList(new String[] {"a", "b", "x"});
+ ArrayType StringListType =
+ MerlinMXBean.ArrayTypeMaker.make(1, SimpleType.STRING);
+ List<String> getStringList();
+ void setStringList(List<String> x);
+ List<String> opStringList(List<String> x, List<String> y);
+
+ Set<String> StringSet = new HashSet(StringList);
+ ArrayType StringSetType = StringListType;
+ Set<String> getStringSet();
+ void setStringSet(Set<String> x);
+ Set<String> opStringSet(Set<String> x, Set<String> y);
+
+ SortedSet<String> SortedStringSet = new TreeSet(StringList);
+ ArrayType SortedStringSetType = StringListType;
+ SortedSet<String> getSortedStringSet();
+ void setSortedStringSet(SortedSet<String> x);
+ SortedSet<String> opSortedStringSet(SortedSet<String> x,
+ SortedSet<String> y);
+
+ Map<String,List<String>> XMap = Collections.singletonMap("yo", StringList);
+ String XMapTypeName =
+ "java.util.Map<java.lang.String, java.util.List<java.lang.String>>";
+ CompositeType XMapRowType = MerlinMXBean.CompositeTypeMaker.make(
+ XMapTypeName, XMapTypeName,
+ new String[] {"key", "value"},
+ new String[] {"key", "value"},
+ new OpenType[] {SimpleType.STRING, StringListType});
+ TabularType XMapType =
+ TabularTypeMaker.make(XMapTypeName, XMapTypeName, XMapRowType,
+ new String[] {"key"});
+ Map<String,List<String>> getXMap();
+ void setXMap(Map<String,List<String>> x);
+ Map<String,List<String>> opXMap(Map<String,List<String>> x,
+ Map<String,List<String>> y);
+
+ SortedMap<String,String> XSortedMap =
+ new TreeMap(Collections.singletonMap("foo", "bar"));
+ String XSortedMapTypeName =
+ "java.util.SortedMap<java.lang.String, java.lang.String>";
+ CompositeType XSortedMapRowType = MerlinMXBean.CompositeTypeMaker.make(
+ XSortedMapTypeName, XSortedMapTypeName,
+ new String[] {"key", "value"},
+ new String[] {"key", "value"},
+ new OpenType[] {SimpleType.STRING, SimpleType.STRING});
+ TabularType XSortedMapType =
+ TabularTypeMaker.make(XSortedMapTypeName, XSortedMapTypeName,
+ XSortedMapRowType, new String[] {"key"});
+ SortedMap<String,String> getXSortedMap();
+ void setXSortedMap(SortedMap<String,String> x);
+ SortedMap<String,String> opXSortedMap(SortedMap<String,String> x,
+ SortedMap<String,String> y);
+
+ // For bug 6319960, try constructing Set and Map with non-Comparable
+
+ Set<Point> PointSet = new HashSet(Collections.singleton(Point));
+ ArrayType PointSetType =
+ MerlinMXBean.ArrayTypeMaker.make(1, PointType);
+ Set<Point> getPointSet();
+ void setPointSet(Set<Point> x);
+ Set<Point> opPointSet(Set<Point> x, Set<Point> y);
+
+ Map<Point,Point> PointMap = Collections.singletonMap(Point, Point);
+ String PointMapTypeName =
+ "java.util.Map<" + Point.class.getName() + ", " +
+ Point.class.getName() + ">";
+ CompositeType PointMapRowType = MerlinMXBean.CompositeTypeMaker.make(
+ PointMapTypeName, PointMapTypeName,
+ new String[] {"key", "value"},
+ new String[] {"key", "value"},
+ new OpenType[] {PointType, PointType});
+ TabularType PointMapType =
+ TabularTypeMaker.make(PointMapTypeName, PointMapTypeName,
+ PointMapRowType, new String[] {"key"});
+ Map<Point,Point> getPointMap();
+ void setPointMap(Map<Point,Point> x);
+ Map<Point,Point> opPointMap(Map<Point,Point> x, Map<Point,Point> y);
+
+ static class TabularTypeMaker {
+ static TabularType make(String typeName, String description,
+ CompositeType rowType, String[] indexNames) {
+ try {
+ return new TabularType(typeName, description, rowType,
+ indexNames);
+ } catch (OpenDataException e) {
+ throw new Error(e);
+ }
+ }
+ }
+}
diff --git a/test/javax/management/notification/BroadcasterSupportDeadlockTest.java b/test/javax/management/notification/BroadcasterSupportDeadlockTest.java
new file mode 100644
index 0000000..80be087
--- /dev/null
+++ b/test/javax/management/notification/BroadcasterSupportDeadlockTest.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2004-2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5093922 2120055
+ * @summary Test that NotificationBroadcasterSupport can be subclassed
+ * and used with synchronized(this) without causing deadlock
+ * @author Eamonn McManus
+ * @run clean BroadcasterSupportDeadlockTest
+ * @run build BroadcasterSupportDeadlockTest
+ * @run main BroadcasterSupportDeadlockTest
+ */
+
+import java.lang.management.*;
+import java.util.concurrent.*;
+import javax.management.*;
+
+public class BroadcasterSupportDeadlockTest {
+ public static void main(String[] args) throws Exception {
+ try {
+ Class.forName(ManagementFactory.class.getName());
+ } catch (Throwable t) {
+ System.out.println("TEST CANNOT RUN: needs JDK 5 at least");
+ return;
+ }
+
+ final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ final BroadcasterMBean mbean = new Broadcaster();
+ final ObjectName name = new ObjectName("test:type=Broadcaster");
+ mbs.registerMBean(mbean, name);
+
+ ThreadMXBean threads = ManagementFactory.getThreadMXBean();
+ threads.setThreadContentionMonitoringEnabled(true);
+
+ final Semaphore semaphore = new Semaphore(0);
+
+ // Thread 1 - block the Broadcaster
+ Thread t1 = new Thread() {
+ public void run() {
+ try {
+ mbs.invoke(name, "block",
+ new Object[] {semaphore},
+ new String[] {Semaphore.class.getName()});
+ } catch (Exception e) {
+ e.printStackTrace(System.out);
+ } finally {
+ System.out.println("TEST INCORRECT: block returned");
+ System.exit(1);
+ }
+ }
+ };
+ t1.setDaemon(true);
+ t1.start();
+
+ /* Wait for Thread 1 to be doing Object.wait(). It's very
+ difficult to synchronize properly here so we wait for the
+ semaphore, then wait a little longer for the mbs.invoke to
+ run, then just in case that isn't enough, we wait for the
+ thread to be in WAITING state. This isn't foolproof,
+ because the machine could be very slow and the
+ Thread.getState() could find the thread in WAITING state
+ due to some operation it does on its way to the one we're
+ interested in. */
+ semaphore.acquire();
+ Thread.sleep(100);
+ while (t1.getState() != Thread.State.WAITING)
+ Thread.sleep(1);
+
+ // Thread 2 - try to add a listener
+ final NotificationListener listener = new NotificationListener() {
+ public void handleNotification(Notification n, Object h) {}
+ };
+ Thread t2 = new Thread() {
+ public void run() {
+ try {
+ mbs.addNotificationListener(name, listener, null, null);
+ } catch (Exception e) {
+ System.out.println("TEST INCORRECT: addNL failed:");
+ e.printStackTrace(System.out);
+ }
+ }
+ };
+ t2.setDaemon(true);
+ t2.start();
+
+ /* Wait for Thread 2 to be blocked on the monitor or to
+ succeed. */
+ Thread.sleep(100);
+
+ for (int i = 0; i < 1000/*ms*/; i++) {
+ t2.join(1/*ms*/);
+ switch (t2.getState()) {
+ case TERMINATED:
+ System.out.println("TEST PASSED");
+ return;
+ case BLOCKED:
+ java.util.Map<Thread,StackTraceElement[]> traces =
+ Thread.getAllStackTraces();
+ showStackTrace("Thread 1", traces.get(t1));
+ showStackTrace("Thread 2", traces.get(t2));
+ System.out.println("TEST FAILED: deadlock");
+ System.exit(1);
+ break;
+ default:
+ break;
+ }
+ }
+
+ System.out.println("TEST FAILED BUT DID NOT NOTICE DEADLOCK");
+ Thread.sleep(10000);
+ System.exit(1);
+ }
+
+ private static void showStackTrace(String title,
+ StackTraceElement[] stack) {
+ System.out.println("---" + title + "---");
+ if (stack == null)
+ System.out.println("<no stack trace???>");
+ else {
+ for (StackTraceElement elmt : stack)
+ System.out.println(" " + elmt);
+ }
+ System.out.println();
+ }
+
+ public static interface BroadcasterMBean {
+ public void block(Semaphore semaphore);
+ }
+
+ public static class Broadcaster
+ extends NotificationBroadcasterSupport
+ implements BroadcasterMBean {
+ public synchronized void block(Semaphore semaphore) {
+ Object lock = new Object();
+ synchronized (lock) {
+ try {
+ // Let the caller know that it can now wait for us to
+ // hit the WAITING state
+ semaphore.release();
+ lock.wait(); // block forever
+ } catch (InterruptedException e) {
+ System.out.println("TEST INCORRECT: lock interrupted:");
+ e.printStackTrace(System.out);
+ System.exit(1);
+ }
+ }
+ }
+ }
+}
diff --git a/test/javax/management/notification/FilterExceptionTest.java b/test/javax/management/notification/FilterExceptionTest.java
new file mode 100644
index 0000000..eb2d09a
--- /dev/null
+++ b/test/javax/management/notification/FilterExceptionTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6244855 6244863
+ * @summary Exception thrown by NotificationFilter should be ignored
+ * @author Shanliang JIANG
+ * @run clean FilterExceptionTest
+ * @run build FilterExceptionTest
+ * @run main FilterExceptionTest
+ */
+
+import javax.management.*;
+
+public class FilterExceptionTest {
+ public static Exception listenerException;
+
+ public static void main(String[] args) throws Exception {
+ System.out.println(
+ ">>> FilterExceptionTest-main: test on an exception thrown by NotificationFilter.");
+
+ FilterExceptionTest.listenerException = null;
+
+ NotificationFilter filter = new NotificationFilter() {
+ public boolean isNotificationEnabled(Notification notification) {
+
+ System.out.println(">>> FilterExceptionTest-filter: throws exception.");
+
+ throw new RuntimeException("For test");
+ }
+ };
+
+ NotificationListener listener = new NotificationListener() {
+ public void handleNotification(Notification n, Object hb) {
+ FilterExceptionTest.listenerException =
+ new Exception("The listener received unexpected notif.");
+ }
+ };
+
+ NotificationBroadcasterSupport broadcaster = new NotificationBroadcasterSupport();
+ broadcaster.addNotificationListener(listener, filter, null);
+
+ broadcaster.sendNotification(new Notification("", "", 1L));
+
+ if (FilterExceptionTest.listenerException != null) {
+ throw FilterExceptionTest.listenerException;
+ }
+
+ System.out.println(">>> FilterExceptionTest-main: Done.");
+ }
+}
diff --git a/test/javax/management/notification/NotifExecutorTest.java b/test/javax/management/notification/NotifExecutorTest.java
new file mode 100644
index 0000000..2a23718
--- /dev/null
+++ b/test/javax/management/notification/NotifExecutorTest.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4661545
+ * @summary Tests to use an executor to send notifications.
+ * @author Shanliang JIANG
+ * @run clean NotifExecutorTest
+ * @run build NotifExecutorTest
+ * @run main NotifExecutorTest
+ */
+
+// java imports
+//
+import java.io.IOException;
+import java.util.concurrent.*;
+
+// JMX imports
+//
+import javax.management.*;
+import javax.management.remote.*;
+
+public class NotifExecutorTest {
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("Tests to use an executor to send notifications.");
+
+ final MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ final ObjectName mbean = new ObjectName ("Default:name=NotificationEmitter");
+ final MyListener myLister = new MyListener();
+ final NotificationListener nullListener = new NotificationListener() {
+ public void handleNotification(Notification n, Object hb) {
+ // nothing
+ }
+ };
+ final Object[] params = new Object[] {new Integer(nb)};
+ final String[] signatures = new String[] {"java.lang.Integer"};
+
+ // test with null executor
+ System.out.println(">>> Test with a null executor.");
+ mbs.registerMBean(new NotificationEmitter(null), mbean);
+
+ mbs.addNotificationListener(mbean, myLister, null, null);
+ mbs.addNotificationListener(mbean, nullListener, null, null);
+
+ mbs.invoke(mbean, "sendNotifications", params, signatures);
+ check(nb, 0);
+
+ mbs.unregisterMBean(mbean);
+
+ // test with an executor
+ System.out.println(">>> Test with a executor.");
+ mbs.registerMBean(new NotificationEmitter(
+ new NotifExecutorTest.MyExecutor()), mbean);
+ mbs.addNotificationListener(mbean, myLister, null, null);
+ mbs.addNotificationListener(mbean, nullListener, null, null);
+
+ mbs.invoke(mbean, "sendNotifications", params, signatures);
+
+ check(nb, nb*2);
+
+ // test without listener
+ System.out.println(">>> Test without listener.");
+
+ mbs.removeNotificationListener(mbean, myLister);
+ mbs.removeNotificationListener(mbean, nullListener);
+
+ mbs.invoke(mbean, "sendNotifications", params, signatures);
+ check(0, 0);
+ }
+
+ private static void check(int notifs, int called) throws Exception {
+ // Waiting...
+ synchronized (lock) {
+ for (int i = 0; i < 10; i++) {
+ if (receivedNotifs < notifs) {
+ lock.wait(1000);
+ }
+ }
+ }
+
+ // Waiting again to ensure no more notifs
+ //
+ Thread.sleep(1000);
+
+ // checking
+ synchronized (lock) {
+ if (receivedNotifs != notifs) {
+ throw new RuntimeException("The listener expected to receive " +
+ notifs + " notifs, but got " + receivedNotifs);
+ } else {
+ System.out.println(">>> The listener recieved as expected: "+receivedNotifs);
+ }
+
+ if (calledTimes != called) {
+ throw new RuntimeException("The notif executor should be called " +
+ called + " times, but got " + calledTimes);
+ } else {
+ System.out.println(">>> The executor was called as expected: "+calledTimes);
+ }
+ }
+
+ // clean
+ receivedNotifs = 0;
+ calledTimes = 0;
+ }
+
+
+ //--------------------------
+ // private classes
+ //--------------------------
+ private static class MyListener implements NotificationListener {
+ public void handleNotification(Notification notif, Object handback) {
+ synchronized(lock) {
+ if(++receivedNotifs >= nb) {
+ lock.notifyAll();
+ }
+ }
+ }
+ }
+
+ public static class NotificationEmitter
+ extends NotificationBroadcasterSupport
+ implements NotificationEmitterMBean {
+
+ public NotificationEmitter(Executor executor) {
+ super(executor);
+ }
+
+ /**
+ * Send a Notification object with the specified times.
+ * The sequence number will be from zero to times-1.
+ *
+ * @param nb The number of notifications to send
+ */
+ public void sendNotifications(Integer nb) {
+ System.out.println(">>> NotificationEmitter: asked to send " +
+ "notifications: " + nb);
+
+ Notification notif;
+ for (int i = 1; i <= nb.intValue(); i++) {
+ notif = new Notification(null, this, ++seqno);
+ super.sendNotification(notif);
+ }
+ }
+ }
+
+ public interface NotificationEmitterMBean {
+ public void sendNotifications(Integer nb);
+ }
+
+ public static class MyExecutor extends ThreadPoolExecutor {
+ public MyExecutor() {
+ super(1, 1, 1L, TimeUnit.MILLISECONDS,
+ new ArrayBlockingQueue(nb*5));
+ }
+
+ public synchronized void execute(Runnable job) {
+ synchronized(lock) {
+ calledTimes++;
+ }
+
+ super.execute(job);
+ }
+ }
+
+ private static int nb = 10;
+ private static int receivedNotifs = 0;
+ private static int[] lock = new int[0];
+ private static volatile long seqno;
+
+ private static int calledTimes = 0;
+}
diff --git a/test/javax/management/notification/NotifInfoTest.java b/test/javax/management/notification/NotifInfoTest.java
new file mode 100644
index 0000000..e1f66c3
--- /dev/null
+++ b/test/javax/management/notification/NotifInfoTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4506105 6303698
+ * @summary NotificationBroadcasterSupport should have a ctor with MBeanNotificationInfo[]
+ * @author Shanliang JIANG
+ * @run clean NotifInfoTest
+ * @run build NotifInfoTest
+ * @run main NotifInfoTest
+ */
+
+import java.util.Arrays;
+import javax.management.*;
+
+public class NotifInfoTest {
+ public static void main(String[] args) throws Exception {
+ final MBeanNotificationInfo info1 =
+ new MBeanNotificationInfo(new String[] {"t11", "t12"}, "n1", null);
+
+ final MBeanNotificationInfo info2 =
+ new MBeanNotificationInfo(new String[] {"t21", "t22"}, "n2", null);
+
+ final MBeanNotificationInfo[] mninfo1 =
+ new MBeanNotificationInfo[] {info1, info2};
+
+ final MBeanNotificationInfo[] mninfo2 = new MBeanNotificationInfo[] {info1, info2};
+
+ final NotificationBroadcasterSupport support1 = new NotificationBroadcasterSupport(mninfo1);
+ final NotificationBroadcasterSupport support2 = new NotificationBroadcasterSupport(null, mninfo1);
+
+ if (!Arrays.deepEquals(mninfo2, support1.getNotificationInfo()) ||
+ !Arrays.deepEquals(mninfo2, support2.getNotificationInfo())) {
+ throw new RuntimeException("Not got expected MBeanNotificationInfo!");
+ }
+
+ // Ensure evil code can't change the array
+ MBeanNotificationInfo[] mninfo3 = support1.getNotificationInfo();
+ mninfo3[0] = null;
+ mninfo3[1] = null;
+ if (!Arrays.deepEquals(mninfo2, support1.getNotificationInfo()))
+ throw new RuntimeException("Caller changed info array!");
+ }
+}
diff --git a/test/javax/management/openmbean/ArrayTypeTest.java b/test/javax/management/openmbean/ArrayTypeTest.java
new file mode 100644
index 0000000..9eb3e97
--- /dev/null
+++ b/test/javax/management/openmbean/ArrayTypeTest.java
@@ -0,0 +1,378 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5045358
+ * @summary Test that Open MBeans support arrays of primitive types.
+ * @author Luis-Miguel Alventosa
+ * @run clean ArrayTypeTest
+ * @run build ArrayTypeTest
+ * @run main ArrayTypeTest
+ */
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import javax.management.ObjectName;
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.SimpleType;
+
+public class ArrayTypeTest {
+
+ private static final String toStringResult[] = {
+ "javax.management.openmbean.ArrayType(name=[[Ljava.lang.String;,dimension=2,elementType=javax.management.openmbean.SimpleType(name=java.lang.String),primitiveArray=false)",
+ "javax.management.openmbean.ArrayType(name=[I,dimension=1,elementType=javax.management.openmbean.SimpleType(name=java.lang.Integer),primitiveArray=true)",
+ "javax.management.openmbean.ArrayType(name=[Ljava.lang.Integer;,dimension=1,elementType=javax.management.openmbean.SimpleType(name=java.lang.Integer),primitiveArray=false)",
+ "javax.management.openmbean.ArrayType(name=[[[[I,dimension=4,elementType=javax.management.openmbean.SimpleType(name=java.lang.Integer),primitiveArray=true)",
+ "javax.management.openmbean.ArrayType(name=[[[[Ljava.lang.Integer;,dimension=4,elementType=javax.management.openmbean.SimpleType(name=java.lang.Integer),primitiveArray=false)",
+ "javax.management.openmbean.ArrayType(name=[Ljava.lang.String;,dimension=1,elementType=javax.management.openmbean.SimpleType(name=java.lang.String),primitiveArray=false)",
+ "OpenDataException",
+ "javax.management.openmbean.ArrayType(name=[Ljava.lang.Integer;,dimension=1,elementType=javax.management.openmbean.SimpleType(name=java.lang.Integer),primitiveArray=false)",
+ "javax.management.openmbean.ArrayType(name=[[Ljava.lang.Integer;,dimension=2,elementType=javax.management.openmbean.SimpleType(name=java.lang.Integer),primitiveArray=false)",
+ "javax.management.openmbean.ArrayType(name=[[I,dimension=2,elementType=javax.management.openmbean.SimpleType(name=java.lang.Integer),primitiveArray=true)",
+ "javax.management.openmbean.ArrayType(name=[[[I,dimension=3,elementType=javax.management.openmbean.SimpleType(name=java.lang.Integer),primitiveArray=true)",
+ "javax.management.openmbean.ArrayType(name=[F,dimension=1,elementType=javax.management.openmbean.SimpleType(name=java.lang.Float),primitiveArray=true)",
+ "javax.management.openmbean.ArrayType(name=[[F,dimension=2,elementType=javax.management.openmbean.SimpleType(name=java.lang.Float),primitiveArray=true)",
+ "javax.management.openmbean.ArrayType(name=[Ljavax.management.ObjectName;,dimension=1,elementType=javax.management.openmbean.SimpleType(name=javax.management.ObjectName),primitiveArray=false)",
+ "javax.management.openmbean.ArrayType(name=[[Ljavax.management.ObjectName;,dimension=2,elementType=javax.management.openmbean.SimpleType(name=javax.management.ObjectName),primitiveArray=false)",
+ "javax.management.openmbean.ArrayType(name=[[[Ljava.lang.String;,dimension=3,elementType=javax.management.openmbean.SimpleType(name=java.lang.String),primitiveArray=false)",
+ "javax.management.openmbean.ArrayType(name=[[[Ljava.lang.String;,dimension=3,elementType=javax.management.openmbean.SimpleType(name=java.lang.String),primitiveArray=false)",
+ "javax.management.openmbean.ArrayType(name=[I,dimension=1,elementType=javax.management.openmbean.SimpleType(name=java.lang.Integer),primitiveArray=true)",
+ "javax.management.openmbean.ArrayType(name=[[Z,dimension=2,elementType=javax.management.openmbean.SimpleType(name=java.lang.Boolean),primitiveArray=true)",
+ "javax.management.openmbean.ArrayType(name=[Ljava.lang.Long;,dimension=1,elementType=javax.management.openmbean.SimpleType(name=java.lang.Long),primitiveArray=false)",
+ "javax.management.openmbean.ArrayType(name=[Ljava.lang.Double;,dimension=1,elementType=javax.management.openmbean.SimpleType(name=java.lang.Double),primitiveArray=false)",
+ };
+
+ private static int checkResult(int i, ArrayType a) {
+ if (a.toString().equals(toStringResult[i])) {
+ System.out.println("Test passed!");
+ return 0;
+ } else {
+ System.out.println("Test failed!");
+ return 1;
+ }
+ }
+
+ private static int checkGetters(ArrayType a,
+ String className,
+ String description,
+ String typeName,
+ boolean isArray,
+ boolean isPrimitiveArray,
+ int dimension) {
+ int error = 0;
+ if (a.getClassName().equals(className)) {
+ System.out.println("\tArrayType.getClassName() OK!");
+ } else {
+ System.out.println("\tArrayType.getClassName() KO!");
+ System.out.println("\t\t---> expecting " + className);
+ error++;
+ }
+ if (a.getDescription().equals(description)) {
+ System.out.println("\tArrayType.getDescription() OK!");
+ } else {
+ System.out.println("\tArrayType.getDescription() KO!");
+ System.out.println("\t\t---> expecting " + description);
+ error++;
+ }
+ if (a.getTypeName().equals(typeName)) {
+ System.out.println("\tArrayType.getTypeName() OK!");
+ } else {
+ System.out.println("\tArrayType.getTypeName() KO!");
+ System.out.println("\t\t---> expecting " + typeName);
+ error++;
+ }
+ if (a.isArray() == isArray) {
+ System.out.println("\tArrayType.isArray() OK!");
+ } else {
+ System.out.println("\tArrayType.isArray() KO!");
+ System.out.println("\t\t---> expecting " + isArray);
+ error++;
+ }
+ if (a.isPrimitiveArray() == isPrimitiveArray) {
+ System.out.println("\tArrayType.isPrimitiveArray() OK!");
+ } else {
+ System.out.println("\tArrayType.isPrimitiveArray() KO!");
+ System.out.println("\t\t---> expecting " + isPrimitiveArray);
+ error++;
+ }
+ if (a.getDimension() == dimension) {
+ System.out.println("\tArrayType.getDimension() OK!");
+ } else {
+ System.out.println("\tArrayType.getDimension() KO!");
+ System.out.println("\t\t---> expecting " + dimension);
+ error++;
+ }
+
+ if (error > 0) {
+ System.out.println("Test failed!");
+ return 1;
+ } else {
+ System.out.println("Test passed!");
+ return 0;
+ }
+ }
+
+ private static void printArrayType(ArrayType a) {
+ System.out.println("\tArrayType.getClassName() = " + a.getClassName());
+ System.out.println("\tArrayType.getDescription() = " + a.getDescription());
+ System.out.println("\tArrayType.getTypeName() = " + a.getTypeName());
+ System.out.println("\tArrayType.isArray() = " + a.isArray());
+ System.out.println("\tArrayType.isPrimitiveArray() = " + a.isPrimitiveArray());
+ System.out.println("\tArrayType.getDimension() = " + a.getDimension());
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ System.out.println("\nTest that Open MBeans support arrays of primitive types.");
+
+ int index = 0;
+ int error = 0;
+
+ //
+ // Constructor tests
+ //
+ System.out.println("\n>>> Constructor tests");
+
+ System.out.println("\nArrayType<String[][]> a1 = new ArrayType<String[][]>(2, SimpleType.STRING)");
+ ArrayType<String[][]> a1 = new ArrayType<String[][]>(2, SimpleType.STRING);
+ printArrayType(a1);
+ error += checkResult(index++, a1);
+
+ System.out.println("\nArrayType<int[]> a2 = new ArrayType<int[]>(SimpleType.INTEGER, true)");
+ ArrayType<int[]> a2 = new ArrayType<int[]>(SimpleType.INTEGER, true);
+ printArrayType(a2);
+ error += checkResult(index++, a2);
+
+ System.out.println("\nArrayType<Integer[]> a3 = new ArrayType<Integer[]>(SimpleType.INTEGER, false)");
+ ArrayType<Integer[]> a3 = new ArrayType<Integer[]>(SimpleType.INTEGER, false);
+ printArrayType(a3);
+ error += checkResult(index++, a3);
+
+ System.out.println("\nArrayType<int[][][][]> a4 = new ArrayType<int[][][][]>(3, a2)");
+ ArrayType<int[][][][]> a4 = new ArrayType<int[][][][]>(3, a2);
+ printArrayType(a4);
+ error += checkResult(index++, a4);
+
+ System.out.println("\nArrayType<Integer[][][][]> a5 = new ArrayType<Integer[][][][]>(3, a3)");
+ ArrayType<Integer[][][][]> a5 = new ArrayType<Integer[][][][]>(3, a3);
+ printArrayType(a5);
+ error += checkResult(index++, a5);
+
+ System.out.println("\nArrayType<String[]> a6 = new ArrayType<String[]>(SimpleType.STRING, false)");
+ ArrayType<String[]> a6 = new ArrayType<String[]>(SimpleType.STRING, false);
+ printArrayType(a6);
+ error += checkResult(index++, a6);
+
+ System.out.println("\nArrayType<String[]> a7 = new ArrayType<String[]>(SimpleType.STRING, true)");
+ index++; // skip this dummy entry in the toStringResult array
+ try {
+ ArrayType<String[]> a7 =
+ new ArrayType<String[]>(SimpleType.STRING, true);
+ System.out.println("\tDid not get expected OpenDataException!");
+ System.out.println("Test failed!");
+ error++;
+ } catch (OpenDataException e) {
+ System.out.println("\tGot expected OpenDataException: " + e);
+ System.out.println("Test passed!");
+ }
+
+ //
+ // Factory tests
+ //
+ System.out.println("\n>>> Factory tests");
+
+ System.out.println("\nArrayType<Integer[]> a8 = ArrayType.getArrayType(SimpleType.INTEGER)");
+ ArrayType<Integer[]> a8 = ArrayType.getArrayType(SimpleType.INTEGER);
+ printArrayType(a8);
+ error += checkResult(index++, a8);
+
+ System.out.println("\nArrayType<Integer[][]> a9 = ArrayType.getArrayType(a8)");
+ ArrayType<Integer[][]> a9 = ArrayType.getArrayType(a8);
+ printArrayType(a9);
+ error += checkResult(index++, a9);
+
+ System.out.println("\nArrayType<int[][]> a10 = ArrayType.getPrimitiveArrayType(int[][].class)");
+ ArrayType<int[][]> a10 = ArrayType.getPrimitiveArrayType(int[][].class);
+ printArrayType(a10);
+ error += checkResult(index++, a10);
+
+ System.out.println("\nArrayType<int[][][]> a11 = ArrayType.getArrayType(a10)");
+ ArrayType<int[][][]> a11 = ArrayType.getArrayType(a10);
+ printArrayType(a11);
+ error += checkResult(index++, a11);
+
+ System.out.println("\nArrayType<float[]> a12 = ArrayType.getPrimitiveArrayType(float[].class)");
+ ArrayType<float[]> a12 = ArrayType.getPrimitiveArrayType(float[].class);
+ printArrayType(a12);
+ error += checkResult(index++, a12);
+
+ System.out.println("\nArrayType<float[][]> a13 = ArrayType.getArrayType(a12)");
+ ArrayType<float[][]> a13 = ArrayType.getArrayType(a12);
+ printArrayType(a13);
+ error += checkResult(index++, a13);
+
+ System.out.println("\nArrayType<ObjectName[]> a14 = ArrayType.getArrayType(SimpleType.OBJECTNAME)");
+ ArrayType<ObjectName[]> a14 = ArrayType.getArrayType(SimpleType.OBJECTNAME);
+ printArrayType(a14);
+ error += checkResult(index++, a14);
+
+ System.out.println("\nArrayType<ObjectName[][]> a15 = ArrayType.getArrayType(a14)");
+ ArrayType<ObjectName[][]> a15 = ArrayType.getArrayType(a14);
+ printArrayType(a15);
+ error += checkResult(index++, a15);
+
+ System.out.println("\nArrayType<String[][][]> a16 = new ArrayType<String[][][]>(3, SimpleType.STRING)");
+ ArrayType<String[][][]> a16 = new ArrayType<String[][][]>(3, SimpleType.STRING);
+ printArrayType(a16);
+ error += checkResult(index++, a16);
+
+ System.out.println("\nArrayType<String[]> a17 = new ArrayType<String[]>(1, SimpleType.STRING)");
+ System.out.println("ArrayType<String[][]> a18 = new ArrayType<String[][]>(1, a17)");
+ System.out.println("ArrayType<String[][][]> a19 = new ArrayType<String[][][]>(1, a18)");
+ ArrayType<String[]> a17 = new ArrayType<String[]>(1, SimpleType.STRING);
+ ArrayType<String[][]> a18 = new ArrayType<String[][]>(1, a17);
+ ArrayType<String[][][]> a19 = new ArrayType<String[][][]>(1, a18);
+ printArrayType(a19);
+ error += checkResult(index++, a19);
+
+ //
+ // Serialization tests
+ //
+ System.out.println("\n>>> Serialization tests\n");
+
+ ArrayType<int[]> i1 = ArrayType.getPrimitiveArrayType(int[].class);
+ ArrayType<int[]> i2 = null;
+
+ ArrayType<boolean[][]> b1 = ArrayType.getPrimitiveArrayType(boolean[][].class);
+ ArrayType<boolean[][]> b2 = null;
+
+ ArrayType<Long[]> l1 = ArrayType.getArrayType(SimpleType.LONG);
+ ArrayType<Long[]> l2 = null;
+
+ ArrayType<Double[]> d1 = ArrayType.getArrayType(SimpleType.DOUBLE);
+ ArrayType<Double[]> d2 = null;
+
+ // serialize the objects
+ try {
+ FileOutputStream fo = new FileOutputStream("serial.tmp");
+ ObjectOutputStream so = new ObjectOutputStream(fo);
+ System.out.println("Serialize ArrayType<int[]> i1 = ArrayType.getPrimitiveArrayType(int[].class)");
+ so.writeObject(i1);
+ System.out.println("Serialize ArrayType<boolean[][]> b1 = ArrayType.getPrimitiveArrayType(boolean[][].class)");
+ so.writeObject(b1);
+ System.out.println("Serialize ArrayType<Long[]> l1 = ArrayType.getArrayType(SimpleType.LONG)");
+ so.writeObject(l1);
+ System.out.println("Serialize ArrayType<Double[]> d1 = ArrayType.getArrayType(SimpleType.DOUBLE)");
+ so.writeObject(d1);
+ so.flush();
+ } catch (Exception e) {
+ System.out.println(e);
+ System.exit(1);
+ }
+
+ // deserialize the objects
+ try {
+ FileInputStream fi = new FileInputStream("serial.tmp");
+ ObjectInputStream si = new ObjectInputStream(fi);
+ System.out.println("Deserialize ArrayType<int[]> i1 = ArrayType.getPrimitiveArrayType(int[].class)");
+ i2 = (ArrayType<int[]>) si.readObject();
+ System.out.println("Deserialize ArrayType<boolean[][]> b1 = ArrayType.getPrimitiveArrayType(boolean[][].class)");
+ b2 = (ArrayType<boolean[][]>) si.readObject();
+ System.out.println("Deserialize ArrayType<Long[]> l1 = ArrayType.getArrayType(SimpleType.LONG)");
+ l2 = (ArrayType<Long[]>) si.readObject();
+ System.out.println("Deserialize ArrayType<Double[]> d1 = ArrayType.getArrayType(SimpleType.DOUBLE)");
+ d2 = (ArrayType<Double[]>) si.readObject();
+ } catch (Exception e) {
+ System.out.println(e);
+ System.exit(1);
+ }
+
+ if (i1.toString().equals(toStringResult[index++]) &&
+ i1.toString().equals(i2.toString())) {
+ System.out.println("Test passed for ArrayType<int[]> i1 = ArrayType.getPrimitiveArrayType(int[].class)");
+ } else {
+ System.out.println("Test failed for ArrayType<int[]> i1 = ArrayType.getPrimitiveArrayType(int[].class)");
+ error++;
+ }
+ if (b1.toString().equals(toStringResult[index++]) &&
+ b1.toString().equals(b2.toString())) {
+ System.out.println("Test passed for ArrayType<boolean[][]> b1 = ArrayType.getPrimitiveArrayType(boolean[][].class)");
+ } else {
+ System.out.println("Test failed for ArrayType<boolean[][]> b1 = ArrayType.getPrimitiveArrayType(boolean[][].class)");
+ error++;
+ }
+ if (l1.toString().equals(toStringResult[index++]) &&
+ l1.toString().equals(l2.toString())) {
+ System.out.println("Test passed for ArrayType<Long[]> l1 = ArrayType.getArrayType(SimpleType.LONG)");
+ } else {
+ System.out.println("Test failed for ArrayType<Long[]> l1 = ArrayType.getArrayType(SimpleType.LONG)");
+ error++;
+ }
+ if (d1.toString().equals(toStringResult[index++]) &&
+ d1.toString().equals(d2.toString())) {
+ System.out.println("Test passed for ArrayType<Double[]> d1 = ArrayType.getArrayType(SimpleType.DOUBLE)");
+ } else {
+ System.out.println("Test failed for ArrayType<Double[]> d1 = ArrayType.getArrayType(SimpleType.DOUBLE)");
+ error++;
+ }
+
+ //
+ // Test getters
+ //
+ System.out.println("\n>>> Getter tests");
+
+ System.out.println("\nArrayType<Integer[][]> g1 = new ArrayType<Integer[][]>(2, SimpleType.INTEGER)");
+ ArrayType<Integer[][]> g1 = new ArrayType<Integer[][]>(2, SimpleType.INTEGER);
+ printArrayType(g1);
+ error += checkGetters(g1,
+ "[[Ljava.lang.Integer;",
+ "2-dimension array of java.lang.Integer",
+ "[[Ljava.lang.Integer;",
+ true,
+ false,
+ 2);
+
+ System.out.println("\nArrayType<int[][]> g2 = ArrayType.getPrimitiveArrayType(int[][].class)");
+ ArrayType<int[][]> g2 = ArrayType.getPrimitiveArrayType(int[][].class);
+ printArrayType(g2);
+ error += checkGetters(g2,
+ "[[I",
+ "2-dimension array of int",
+ "[[I",
+ true,
+ true,
+ 2);
+
+ if (error > 0) {
+ final String msg = "\nTest FAILED! Got " + error + " error(s)";
+ System.out.println(msg);
+ throw new IllegalArgumentException(msg);
+ } else {
+ System.out.println("\nTest PASSED!");
+ }
+ }
+}
diff --git a/test/javax/management/openmbean/BadConstraintTest.java b/test/javax/management/openmbean/BadConstraintTest.java
new file mode 100644
index 0000000..d902601
--- /dev/null
+++ b/test/javax/management/openmbean/BadConstraintTest.java
@@ -0,0 +1,430 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6204469
+ * @summary Test that Open MBean attributes and parameters cannot have
+ * illegal constraints like min greater than max
+ * @author Eamonn McManus
+ * @run clean BadConstraintTest
+ * @run build BadConstraintTest
+ * @run main BadConstraintTest
+ */
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+import javax.management.*;
+import javax.management.openmbean.*;
+
+public class BadConstraintTest {
+ private static String failure;
+
+ public static void main(String[] args) throws Exception {
+ genericTests();
+ descriptorTests();
+
+ if (failure == null)
+ System.out.println("Test passed");
+ else
+ throw new Exception("TEST FAILED: " + failure);
+ }
+
+ private static void genericTests() throws Exception {
+ for (Object[] test : tests) {
+ if (test.length != 5) {
+ throw new Exception("Test element has wrong length: " +
+ toString(test));
+ }
+
+ OpenType<?> openType = (OpenType<?>) test[0];
+ Object defaultValue = test[1];
+ Comparable<?> minValue = (Comparable<?>) test[2];
+ Comparable<?> maxValue = (Comparable<?>) test[3];
+ Object[] legalValues = (Object[]) test[4];
+
+ System.out.println("test: openType=" + openType +
+ "; defaultValue=" + defaultValue +
+ "; minValue=" + minValue +
+ "; maxValue=" + maxValue +
+ "; legalValues=" + toString(legalValues));
+
+ genericTest(openType, defaultValue, minValue, maxValue,
+ legalValues);
+ }
+ }
+
+ private static void descriptorTests() throws Exception {
+ for (Object[][] test : descriptorTests) {
+ if (test.length != 2) {
+ throw new Exception("Test element has wrong length: " +
+ toString(test));
+ }
+
+ if (test[0].length != 1) {
+ throw new Exception("Test element should have one OpenType: " +
+ toString(test[0]));
+ }
+
+ OpenType<?> openType = (OpenType<?>) test[0][0];
+ Descriptor d = descriptor(test[1]);
+
+ System.out.println("test: openType=" + openType +
+ "; descriptor=" + d);
+
+ descriptorTest(openType, d);
+ }
+ }
+
+ /* Tests that apply to both the Descriptor and the non-Descriptor
+ constructors. We invoke the non-Descriptor constructors by
+ reflection, then we make the corresponding Descriptor and call
+ the descriptorTest with it. */
+ private static void genericTest(OpenType<?> openType,
+ Object defaultValue,
+ Comparable<?> minValue,
+ Comparable<?> maxValue,
+ Object[] legalValues)
+ throws Exception {
+
+ if (minValue == null && maxValue == null && legalValues == null) {
+ if (defaultValue == null)
+ throw new Exception("What am I testing?");
+ Class[] params1 = new Class[] {
+ String.class, String.class, OpenType.class,
+ boolean.class, boolean.class, boolean.class,
+ Object.class
+ };
+ Constructor<OpenMBeanAttributeInfoSupport> c1 =
+ OpenMBeanAttributeInfoSupport.class.getConstructor(params1);
+ Class[] params2 = new Class[] {
+ String.class, String.class, OpenType.class,
+ Object.class
+ };
+ Constructor<OpenMBeanParameterInfoSupport> c2 =
+ OpenMBeanParameterInfoSupport.class.getConstructor(params2);
+ ode(c1, "name", "descr", openType, true, true, false, defaultValue);
+ ode(c2, "name", "descr", openType, defaultValue);
+ descriptorTest(openType,
+ descriptor("defaultValue", defaultValue));
+ descriptorTest(openType,
+ descriptor("defaultValue", string(defaultValue)));
+ }
+
+ if (legalValues == null) {
+ Class[] params1 = new Class[] {
+ String.class, String.class, OpenType.class,
+ boolean.class, boolean.class, boolean.class,
+ Object.class, Comparable.class, Comparable.class
+ };
+ Constructor<OpenMBeanAttributeInfoSupport> c1 =
+ OpenMBeanAttributeInfoSupport.class.getConstructor(params1);
+ Class[] params2 = new Class[] {
+ String.class, String.class, OpenType.class,
+ Object.class, Comparable.class, Comparable.class
+ };
+ Constructor<OpenMBeanParameterInfoSupport> c2 =
+ OpenMBeanParameterInfoSupport.class.getConstructor(params2);
+ ode(c1, "name", "descr", openType, true, true, false, defaultValue,
+ minValue, maxValue);
+ ode(c2, "name", "descr", openType, defaultValue,
+ minValue, maxValue);
+ descriptorTest(openType,
+ descriptor("defaultValue", defaultValue,
+ "minValue", minValue,
+ "maxValue", maxValue));
+ descriptorTest(openType,
+ descriptor("defaultValue", string(defaultValue),
+ "minValue", string(minValue),
+ "maxValue", string(maxValue)));
+ }
+
+ if (legalValues != null) {
+ Class[] params1 = new Class[] {
+ String.class, String.class, OpenType.class,
+ boolean.class, boolean.class, boolean.class,
+ Object.class, Object[].class
+ };
+ Constructor<OpenMBeanAttributeInfoSupport> c1 =
+ OpenMBeanAttributeInfoSupport.class.getConstructor(params1);
+ Class[] params2 = new Class[] {
+ String.class, String.class, OpenType.class,
+ Object.class, Object[].class
+ };
+ Constructor<OpenMBeanParameterInfoSupport> c2 =
+ OpenMBeanParameterInfoSupport.class.getConstructor(params2);
+ ode(c1, "name", "descr", openType, true, true, false, defaultValue,
+ legalValues);
+ ode(c2, "name", "descr", openType, defaultValue,
+ legalValues);
+ descriptorTest(openType,
+ descriptor("defaultValue", defaultValue,
+ "legalValues", legalValues));
+ descriptorTest(openType,
+ descriptor("defaultValue", defaultValue,
+ "legalValues", arraySet(legalValues)));
+ Set<String> strings = new HashSet<String>();
+ for (Object x : legalValues)
+ strings.add(x.toString());
+ descriptorTest(openType,
+ descriptor("defaultValue", defaultValue,
+ "legalValues", strings));
+ descriptorTest(openType,
+ descriptor("defaultValue", defaultValue,
+ "legalValues",
+ strings.toArray(new String[0])));
+ }
+ }
+
+ private static void descriptorTest(OpenType<?> openType, Descriptor d)
+ throws Exception {
+ Class[] params1 = new Class[] {
+ String.class, String.class, OpenType.class,
+ boolean.class, boolean.class, boolean.class,
+ Descriptor.class
+ };
+ Constructor<OpenMBeanAttributeInfoSupport> c1 =
+ OpenMBeanAttributeInfoSupport.class.getConstructor(params1);
+ Class[] params2 = new Class[] {
+ String.class, String.class, OpenType.class,
+ Descriptor.class
+ };
+ Constructor<OpenMBeanParameterInfoSupport> c2 =
+ OpenMBeanParameterInfoSupport.class.getConstructor(params2);
+ iae(c1, "name", "descr", openType, true, true, false, d);
+ iae(c2, "name", "descr", openType, d);
+ }
+
+ /* Check that the given constructor invocation gets an
+ IllegalArgumentException. */
+ private static void iae(Constructor<?> con, Object... params) {
+ checkException(IllegalArgumentException.class, con, params);
+ }
+
+ /* Check that the given constructor invocation gets an
+ OpenDataException. */
+ private static void ode(Constructor<?> con, Object... params) {
+ checkException(OpenDataException.class, con, params);
+ }
+
+ private static void checkException(Class<? extends Exception> exc,
+ Constructor<?> con, Object[] params) {
+ try {
+ con.newInstance(params);
+ fail("Constructor succeeded but should have got " + exc.getName() +
+ " with params " + Arrays.deepToString(params));
+ } catch (InvocationTargetException e) {
+ Throwable cause = e.getCause();
+ if (exc.isInstance(cause))
+ return;
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ cause.printStackTrace(pw);
+ pw.close();
+ fail("Constructor should have got " + exc.getName() +
+ " with params " + Arrays.deepToString(params) + ": " + sw);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Reflection failed", e);
+ }
+ }
+
+ private static void fail(String why) {
+ System.out.println("FAILED: " + why);
+ failure = why;
+ }
+
+ private static Descriptor descriptor(Object... entries) {
+ if (entries.length % 2 != 0)
+ throw new RuntimeException("Odd length descriptor entries");
+ String[] names = new String[entries.length / 2];
+ Object[] values = new Object[entries.length / 2];
+ for (int i = 0; i < entries.length; i += 2) {
+ names[i / 2] = (String) entries[i];
+ values[i / 2] = entries[i + 1];
+ }
+ return new ImmutableDescriptor(names, values);
+ }
+
+ private static <T> Set<T> arraySet(T[] array) {
+ return new HashSet<T>(Arrays.asList(array));
+ }
+
+ private static String toString(Object x) {
+ if (x == null)
+ return "null";
+ else if (x.getClass().isArray()) {
+ StringBuilder sb = new StringBuilder("[");
+ int len = Array.getLength(x);
+ for (int i = 0; i < len; i++) {
+ if (i > 0)
+ sb.append(", ");
+ sb.append(toString(Array.get(x, i)));
+ }
+ sb.append("]");
+ return sb.toString();
+ } else
+ return x.toString();
+ }
+
+ private static String string(Object x) {
+ if (x == null)
+ return null;
+ return toString(x);
+ }
+
+ private static final OpenType<?>
+ ostring = SimpleType.STRING,
+ oint = SimpleType.INTEGER,
+ obool = SimpleType.BOOLEAN,
+ olong = SimpleType.LONG,
+ obyte = SimpleType.BYTE,
+ ofloat = SimpleType.FLOAT,
+ odouble = SimpleType.DOUBLE,
+ ostringarray, ostringarray2;
+ private static final CompositeType ocomposite;
+ private static final CompositeData compositeData, compositeData2;
+ static {
+ try {
+ ostringarray = new ArrayType<String[]>(1, ostring);
+ ostringarray2 = new ArrayType<String[][]>(2, ostring);
+ ocomposite =
+ new CompositeType("name", "descr",
+ new String[] {"s", "i"},
+ new String[] {"sdesc", "idesc"},
+ new OpenType[] {ostring, oint});
+ compositeData =
+ new CompositeDataSupport(ocomposite,
+ new String[] {"s", "i"},
+ new Object[] {"foo", 23});
+ compositeData2 =
+ new CompositeDataSupport(ocomposite,
+ new String[] {"s", "i"},
+ new Object[] {"bar", -23});
+ } catch (OpenDataException e) { // damn checked exceptions...
+ throw new IllegalArgumentException(e.toString(), e);
+ }
+ }
+
+ private static final Descriptor
+ nullD = null,
+ emptyD = ImmutableDescriptor.EMPTY_DESCRIPTOR;
+
+ /* Each element of this array contains five Objects:
+ - OpenType;
+ - defaultValue;
+ - minValue;
+ - maxValue;
+ - legalValues. The objects are used to construct tests cases
+ where all possible constructors that make sense for that
+ combination of values are invoked, and all are checked to ensure
+ that they throw the right exception. */
+ private static final Object[][] tests = {
+
+ // Values must be of appropriate type
+
+ {oint, "oops", null, null, null},
+ {oint, Long.MAX_VALUE, null, null, null},
+ {oint, null, "oops", null, null},
+ {oint, "oops", 3, null, null},
+ {oint, 3, "oops", null, null},
+ {oint, null, null, "oops", null},
+ {oint, null, 3, "oops", null},
+ {oint, null, 3, false, null},
+ {oint, null, null, null, new String[] {"x"}},
+ {oint, null, null, null, new Object[] {"x"}},
+ {oint, null, null, null, new Object[] {3, "x"}},
+
+ // If defaultValue is present then it must satisfy the constraints
+ // defined by legalValues, minValue, or maxValue when any of
+ // these is also present
+
+ {oint, 3, 4, null, null},
+ {oint, 3, null, 2, null},
+ {oint, 3, null, null, new Integer[] {2, 4}},
+
+ // If minValue and maxValue are both present then minValue must
+ // not be greater than maxValue
+
+ {ostring, null, "z", "a", null},
+ {oint, null, 3, 2, null},
+
+ // We don't support default values or legal sets for arrays (yet)
+
+ {ostringarray, new String[] {"x"}, null, null, null},
+ {ostringarray, null, null, null, new String[][]{new String[] {"x"}}},
+ };
+
+ /* The tests here can only be expressed via Descriptors because an
+ attempt to invoke one of the non-Descriptor constructors with
+ the implied parameters would not compile (or would fail at the
+ reflection stage when reflection is being used).
+
+ Each element of this array contains two subarrays. The first
+ is an array of OpenTypes that must contain exactly one element.
+ The second is an array of alternating field names and field
+ values that will be used to construct a Descriptor that is supposed
+ to fail when given to an OpenMBean*Info constructor with the given
+ OpenType. */
+ private static final Object[][][] descriptorTests = {
+
+ // Values must be of appropriate type
+
+ {{oint},
+ {"minValue", 25L}},
+
+ {{oint},
+ {"minValue", new Object()}}, // not even Comparable
+ {{oint},
+ {"maxValue", new Object()}}, // not even Comparable
+ {{oint},
+ {"defaultValue", 3,
+ "minValue", new Object()}},
+ {{oint},
+ {"defaultValue", 3,
+ "maxValue", new Object()}},
+
+ {{oint},
+ {"legalValues", new int[] {3}}}, // should be new Integer[] to work
+ {{oint},
+ {"legalValues", 3}},
+
+ // If legalValues is present then neither minValue nor maxValue
+ // must be present
+
+ {{oint},
+ {"minValue", 3, "legalValues", new Integer[] {3, 4}}},
+ {{oint},
+ {"maxValue", 3, "legalValues", new Integer[] {2, 3}}},
+ {{oint},
+ {"defaultValue", 3, "minValue", 3, "legalValues", new Integer[] {3}}},
+
+ // We don't support min or max arrays (what would they mean?)
+
+ {{ostringarray},
+ {"minValue", new String[] {"x"}}},
+ {{ostringarray},
+ {"maxValue", new String[] {"x"}}},
+
+ };
+}
diff --git a/test/javax/management/openmbean/ConstraintTest.java b/test/javax/management/openmbean/ConstraintTest.java
new file mode 100644
index 0000000..6848cd5
--- /dev/null
+++ b/test/javax/management/openmbean/ConstraintTest.java
@@ -0,0 +1,532 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6204469
+ * @summary Test that Open MBean attributes and parameters check constraints
+ * @author Eamonn McManus
+ * @run clean ConstraintTest
+ * @run build ConstraintTest
+ * @run main ConstraintTest
+ */
+
+import java.util.*;
+import javax.management.*;
+import javax.management.openmbean.*;
+
+public class ConstraintTest {
+ private static String failure;
+
+ public static void main(String[] args) throws Exception {
+ for (Object[][] test : tests) {
+ if (test.length != 4) {
+ throw new Exception("Test element has wrong length: " +
+ Arrays.deepToString(test));
+ }
+
+ if (test[0].length != 4) {
+ throw new Exception("Test constraints should have size 4: " +
+ Arrays.deepToString(test[0]));
+ }
+ Object defaultValue = test[0][0];
+ Comparable<?> minValue = (Comparable<?>) test[0][1];
+ Comparable<?> maxValue = (Comparable<?>) test[0][2];
+ Object[] legalValues = (Object[]) test[0][3];
+ System.out.println("test: defaultValue=" + defaultValue +
+ "; minValue=" + minValue +
+ "; maxValue=" + maxValue +
+ "; legalValues=" +
+ Arrays.deepToString(legalValues));
+
+ if (test[1].length != 1) {
+ throw new Exception("OpenType list should have size 1: " +
+ Arrays.deepToString(test[1]));
+ }
+ OpenType<?> openType = (OpenType<?>) test[1][0];
+
+ Object[] valid = test[2];
+ Object[] invalid = test[3];
+
+ System.out.println("...valid=" + Arrays.deepToString(valid));
+ System.out.println("...invalid=" + Arrays.deepToString(invalid));
+
+ test(openType, defaultValue, minValue, maxValue, legalValues,
+ valid, invalid);
+ }
+
+ if (failure == null)
+ System.out.println("Test passed");
+ else
+ throw new Exception("TEST FAILED: " + failure);
+ }
+
+ private static <T> void test(OpenType<T> openType, Object defaultValue,
+ Comparable<?> minValue,
+ Comparable<?> maxValue, Object[] legalValues,
+ Object[] valid, Object[] invalid)
+ throws Exception {
+ /* This hack is needed to avoid grief from the parameter checking
+ in the OpenMBean*InfoSupport constructors. Since they are defined
+ to check that the defaultValue etc are of the same type as the
+ OpenType<T>, there is no way to pass a defaultValue etc when
+ the type is OpenType<?>. So either you have to write plain
+ OpenType, and get unchecked warnings for every constructor
+ invocation, or you do this, and get the unchecked warnings just
+ here. */
+ test1(openType, (T) defaultValue, (Comparable<T>) minValue,
+ (Comparable<T>) maxValue, (T[]) legalValues, valid, invalid);
+ }
+
+ private static <T> void test1(OpenType<T> openType, T defaultValue,
+ Comparable<T> minValue,
+ Comparable<T> maxValue, T[] legalValues,
+ Object[] valid, Object[] invalid)
+ throws Exception {
+
+ if (legalValues != null && (minValue != null || maxValue != null))
+ throw new Exception("Test case has both legals and min/max");
+
+ if (defaultValue == null && minValue == null && maxValue == null &&
+ legalValues == null) {
+ test(new OpenMBeanAttributeInfoSupport("name", "descr", openType,
+ true, true, false),
+ valid, invalid);
+ test(new OpenMBeanAttributeInfoSupport("name", "descr", openType,
+ true, true, false, nullD),
+ valid, invalid);
+ test(new OpenMBeanAttributeInfoSupport("name", "descr", openType,
+ true, true, false, emptyD),
+ valid, invalid);
+ test(new OpenMBeanParameterInfoSupport("name", "descr", openType),
+ valid, invalid);
+ test(new OpenMBeanParameterInfoSupport("name", "descr", openType,
+ nullD),
+ valid, invalid);
+ test(new OpenMBeanParameterInfoSupport("name", "descr", openType,
+ emptyD),
+ valid, invalid);
+ }
+
+ if (minValue == null && maxValue == null && legalValues == null) {
+ Descriptor d = descriptor("defaultValue", defaultValue);
+ test(new OpenMBeanAttributeInfoSupport("blah", "descr", openType,
+ true, true, false, d),
+ valid, invalid);
+ test(new OpenMBeanAttributeInfoSupport("blah", "descr",
+ openType, true, true,
+ false, defaultValue),
+ valid, invalid);
+ test(new OpenMBeanParameterInfoSupport("blah", "descr", openType,
+ d),
+ valid, invalid);
+ test(new OpenMBeanParameterInfoSupport("blah", "descr", openType,
+ defaultValue),
+ valid, invalid);
+ }
+
+ if (legalValues == null) {
+ Descriptor d = descriptor("defaultValue", defaultValue,
+ "minValue", minValue,
+ "maxValue", maxValue);
+ test(new OpenMBeanAttributeInfoSupport("name", "descr", openType,
+ true, true, false, d),
+ valid, invalid);
+ test(new OpenMBeanAttributeInfoSupport("name", "descr", openType,
+ true, true, false,
+ defaultValue,
+ minValue, maxValue),
+ valid, invalid);
+ test(new OpenMBeanParameterInfoSupport("name", "descr", openType,
+ d),
+ valid, invalid);
+ test(new OpenMBeanParameterInfoSupport("name", "descr", openType,
+ defaultValue,
+ minValue, maxValue),
+ valid, invalid);
+ }
+
+ if (minValue == null && maxValue == null) {
+ // Legal values in descriptor can be either an array or a set
+ Descriptor d1 = descriptor("defaultValue", defaultValue,
+ "legalValues", legalValues);
+ Descriptor d2;
+ if (legalValues == null)
+ d2 = d1;
+ else {
+ d2 = descriptor("defaultValue", defaultValue,
+ "legalValues", arraySet(legalValues));
+ }
+ test(new OpenMBeanAttributeInfoSupport("name", "descr", openType,
+ true, true, false, d1),
+ valid, invalid);
+ test(new OpenMBeanAttributeInfoSupport("name", "descr", openType,
+ true, true, false, d2),
+ valid, invalid);
+ test(new OpenMBeanAttributeInfoSupport("name", "descr", openType,
+ true, true, false,
+ defaultValue, legalValues),
+ valid, invalid);
+ test(new OpenMBeanParameterInfoSupport("name", "descr", openType,
+ d1),
+ valid, invalid);
+ test(new OpenMBeanParameterInfoSupport("name", "descr", openType,
+ d2),
+ valid, invalid);
+ test(new OpenMBeanParameterInfoSupport("name", "descr", openType,
+ defaultValue, legalValues),
+ valid, invalid);
+ }
+ }
+
+ /* Test one of the objects. Note that OpenMBeanAttributeInfo
+ extends OpenMBeanParameterInfo, so OpenMBeanAttributeInfoSupport
+ is-an OpenMBeanParameterInfo. */
+ private static void test(OpenMBeanParameterInfo info,
+ Object[] valid, Object[] invalid) {
+ test1(info, valid, invalid);
+
+ // Check that the constraints can be specified as strings
+ // rather than objects
+ if (info.getOpenType() instanceof SimpleType<?>) {
+ Descriptor d = ((DescriptorRead) info).getDescriptor();
+ String[] names = d.getFieldNames();
+ Object[] values = d.getFieldValues(names);
+ for (int i = 0; i < values.length; i++) {
+ if (values[i] == null)
+ continue;
+ if (names[i].equals("legalValues")) {
+ Collection<?> legals;
+ if (values[i] instanceof Collection<?>)
+ legals = (Collection<?>) values[i];
+ else
+ legals = Arrays.asList((Object[]) values[i]);
+ List<String> strings = new ArrayList<String>();
+ for (Object legal : legals)
+ strings.add(legal.toString());
+ values[i] = strings.toArray(new String[0]);
+ } else if (!(values[i] instanceof OpenType<?>))
+ values[i] = values[i].toString();
+ }
+ d = new ImmutableDescriptor(names, values);
+ OpenType<?> ot = info.getOpenType();
+ if (info instanceof OpenMBeanAttributeInfo) {
+ OpenMBeanAttributeInfo ai = (OpenMBeanAttributeInfo) info;
+ info = new OpenMBeanAttributeInfoSupport(info.getName(),
+ info.getDescription(),
+ info.getOpenType(),
+ ai.isReadable(),
+ ai.isWritable(),
+ ai.isIs(),
+ d);
+ } else {
+ info = new OpenMBeanParameterInfoSupport(info.getName(),
+ info.getDescription(),
+ info.getOpenType(),
+ d);
+ }
+ test1(info, valid, invalid);
+ }
+ }
+
+ private static void test1(OpenMBeanParameterInfo info,
+ Object[] valid, Object[] invalid) {
+
+ for (Object x : valid) {
+ if (!info.isValue(x)) {
+ fail("Object should be valid but is not: " + x + " for: " +
+ info);
+ }
+ }
+
+ for (Object x : invalid) {
+ if (info.isValue(x)) {
+ fail("Object should not be valid but is: " + x + " for: " +
+ info);
+ }
+ }
+
+ /* If you specify e.g. minValue in a descriptor, then we arrange
+ for getMinValue() to return the same value, and if you specify
+ a minValue as a constructor parameter then we arrange for the
+ descriptor to have a minValue entry. Check that these values
+ do in fact match. */
+
+ Descriptor d = ((DescriptorRead) info).getDescriptor();
+
+ checkSameValue("defaultValue", info.getDefaultValue(),
+ d.getFieldValue("defaultValue"));
+ checkSameValue("minValue", info.getMinValue(),
+ d.getFieldValue("minValue"));
+ checkSameValue("maxValue", info.getMaxValue(),
+ d.getFieldValue("maxValue"));
+ checkSameValues("legalValues", info.getLegalValues(),
+ d.getFieldValue("legalValues"));
+ }
+
+ private static void checkSameValue(String what, Object getterValue,
+ Object descriptorValue) {
+ if (getterValue == null) {
+ if (descriptorValue != null) {
+ fail("Getter returned null but descriptor has entry for " +
+ what + ": " + descriptorValue);
+ }
+ } else if (descriptorValue == null) {
+ fail("Getter returned value but descriptor has no entry for " +
+ what + ": " + getterValue);
+ } else if (!getterValue.equals(descriptorValue) &&
+ !getterValue.toString().equals(descriptorValue)) {
+ fail("For " + what + " getter returned " + getterValue +
+ " but descriptor entry is " + descriptorValue);
+ }
+ }
+
+ private static void checkSameValues(String what, Set<?> getterValues,
+ Object descriptorValues) {
+ if (getterValues == null) {
+ if (descriptorValues != null) {
+ fail("Getter returned null but descriptor has entry for " +
+ what + ": " + descriptorValues);
+ }
+ } else if (descriptorValues == null) {
+ fail("Getter returned value but descriptor has no entry for " +
+ what + ": " + getterValues);
+ } else {
+ Set<?> descriptorValueSet;
+ if (descriptorValues instanceof Set<?>)
+ descriptorValueSet = (Set<?>) descriptorValues;
+ else
+ descriptorValueSet = arraySet((Object[]) descriptorValues);
+ boolean same = true;
+ if (getterValues.size() != descriptorValueSet.size())
+ same = false;
+ else {
+ for (Object x : getterValues) {
+ if (!descriptorValueSet.contains(x)
+ && !descriptorValueSet.contains(x.toString())) {
+ same = false;
+ break;
+ }
+ }
+ }
+ if (!same) {
+ fail("For " + what + " getter returned " + getterValues +
+ " but descriptor entry is " + descriptorValueSet);
+ }
+ }
+ }
+
+ private static void fail(String why) {
+ System.out.println("FAILED: " + why);
+ failure = why;
+ }
+
+ private static Descriptor descriptor(Object... entries) {
+ if (entries.length % 2 != 0)
+ throw new RuntimeException("Odd length descriptor entries");
+ String[] names = new String[entries.length / 2];
+ Object[] values = new Object[entries.length / 2];
+ for (int i = 0; i < entries.length; i += 2) {
+ names[i / 2] = (String) entries[i];
+ values[i / 2] = entries[i + 1];
+ }
+ return new ImmutableDescriptor(names, values);
+ }
+
+ private static <T> Set<T> arraySet(T[] array) {
+ return new HashSet<T>(Arrays.asList(array));
+ }
+
+ private static final OpenType<?>
+ ostring = SimpleType.STRING,
+ oint = SimpleType.INTEGER,
+ obool = SimpleType.BOOLEAN,
+ olong = SimpleType.LONG,
+ obyte = SimpleType.BYTE,
+ ofloat = SimpleType.FLOAT,
+ odouble = SimpleType.DOUBLE,
+ ostringarray, ostringarray2;
+ private static final CompositeType ocomposite;
+ private static final CompositeData compositeData, compositeData2;
+ static {
+ try {
+ ostringarray = new ArrayType<String[]>(1, ostring);
+ ostringarray2 = new ArrayType<String[][]>(2, ostring);
+ ocomposite =
+ new CompositeType("name", "descr",
+ new String[] {"s", "i"},
+ new String[] {"sdesc", "idesc"},
+ new OpenType[] {ostring, oint});
+ compositeData =
+ new CompositeDataSupport(ocomposite,
+ new String[] {"s", "i"},
+ new Object[] {"foo", 23});
+ compositeData2 =
+ new CompositeDataSupport(ocomposite,
+ new String[] {"s", "i"},
+ new Object[] {"bar", -23});
+ } catch (OpenDataException e) { // damn checked exceptions...
+ throw new IllegalArgumentException(e.toString(), e);
+ }
+ }
+
+ private static final Descriptor
+ nullD = null,
+ emptyD = ImmutableDescriptor.EMPTY_DESCRIPTOR;
+
+ /* The elements of this array are grouped as follows. Each
+ element contains four Object[]s. The first one is a set of
+ four values: default value, min value, max value, legal values
+ (an Object[]), some of which can be null. These will be used
+ to derive the OpenMBean*Info values to be tested. The second
+ is an array with one element that is the OpenType that will be
+ given to the constructors of the OpenMBean*Infos. The third
+ element is a set of values that should be valid according to
+ the constraints in the OpenMBean*Info. The fourth is a set of
+ values that should be invalid according to those
+ constraints. */
+ private static final Object[][][] tests = {
+
+ // Test cases when there are no constraints
+ // Validity checking is limited to type of object
+
+ {{null, null, null, null},
+ {oint},
+ {-1, 0, 1, Integer.MAX_VALUE, Integer.MIN_VALUE},
+ {null, "noddy", 1.3, false, 3L, Long.MAX_VALUE, emptyD,
+ new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},
+
+ {{null, null, null, null},
+ {obool},
+ {true, false},
+ {null, "noddy", 1.3, 3, 3L, Long.MAX_VALUE, emptyD,
+ new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},
+
+ {{null, null, null, null},
+ {ostring},
+ {"", "yes!"},
+ {null, 1.3, 3, false, 3L, Long.MAX_VALUE, emptyD,
+ new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},
+
+ {{null, null, null, null},
+ {obyte},
+ {Byte.MIN_VALUE, Byte.MAX_VALUE, (byte) 0},
+ {null, "noddy", 1.3, 3, false, 3L, Long.MAX_VALUE, emptyD,
+ new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},
+
+ {{null, null, null, null},
+ {ostringarray},
+ {new String[0], new String[] {"hello", "world"}},
+ {null, "noddy", 1.3, 3, false, 3L, Long.MAX_VALUE, emptyD,
+ new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},
+
+ {{null, null, null, null},
+ {ostringarray2},
+ {new String[0][0], new String[][] {{"hello", "world"},
+ {"goodbye", "cruel", "world"}}},
+ {null, "noddy", 1.3, 3, false, 3L, Long.MAX_VALUE, emptyD,
+ new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},
+
+ {{null, null, null, null},
+ {ocomposite},
+ {compositeData, compositeData2},
+ {null, "noddy", 1.3, 3, false, 3L, Long.MAX_VALUE, emptyD,
+ new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},
+
+ // Test cases where there is a default value, so null is allowed
+
+ {{23, null, null, null},
+ {oint},
+ {null, -1, 0, 1, Integer.MAX_VALUE, Integer.MIN_VALUE},
+ {"noddy", 1.3, false, 3L, Long.MAX_VALUE, emptyD,
+ new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},
+
+ {{true, null, null, null},
+ {obool},
+ {null, true, false},
+ {"noddy", 1.3, 3, 3L, Long.MAX_VALUE, emptyD,
+ new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},
+
+ {{"foo", null, null, null},
+ {ostring},
+ {null, "", "yes!"},
+ {1.3, 3, false, 3L, Long.MAX_VALUE, emptyD,
+ new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},
+
+ {{(byte) 23, null, null, null},
+ {obyte},
+ {null, Byte.MIN_VALUE, Byte.MAX_VALUE, (byte) 0},
+ {"noddy", 1.3, 3, false, 3L, Long.MAX_VALUE, emptyD,
+ new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},
+
+ {{compositeData, null, null, null},
+ {ocomposite},
+ {null, compositeData, compositeData2},
+ {"noddy", 1.3, 3, false, 3L, Long.MAX_VALUE, emptyD,
+ new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},
+
+ // Test cases where there is a min and/or max, with or without default
+
+ {{23, 0, 50, null},
+ {oint},
+ {null, 0, 25, 50},
+ {"noddy", -1, 51, Integer.MIN_VALUE, Integer.MAX_VALUE, 25L}},
+
+ {{null, 0, 50, null},
+ {oint},
+ {0, 25, 50},
+ {null, "noddy", -1, 51, Integer.MIN_VALUE, Integer.MAX_VALUE, 25L}},
+
+ {{null, 0, null, null},
+ {oint},
+ {0, 25, 50, Integer.MAX_VALUE},
+ {null, "noddy", -1, Integer.MIN_VALUE, 25L}},
+
+ {{null, null, 50, null},
+ {oint},
+ {Integer.MIN_VALUE, -1, 0, 25, 50},
+ {null, "noddy", 51, Integer.MAX_VALUE, 25L}},
+
+ {{"go", "a", "z~", null},
+ {ostring},
+ {null, "a", "z~", "zzzz", "z!"},
+ {"A", "~", "", -1}},
+
+ // Test cases where there is a set of legal values
+
+ {{23, null, null, new Integer[] {2, 3, 5, 7, 11, 13, 17, 23}},
+ {oint},
+ {null, 2, 11, 23},
+ {"noddy", -1, 1, 51, Integer.MIN_VALUE, Integer.MAX_VALUE, 25L}},
+
+ {{null, null, null, new CompositeData[] {compositeData}},
+ {ocomposite},
+ {compositeData},
+ {null, compositeData2, "noddy"}},
+
+ {{null, null, null, new Long[0]},
+ {olong},
+ {}, // constraint is impossible to satisfy!
+ {null, 23L, "x", 23}},
+ };
+}
diff --git a/test/javax/management/openmbean/EqualsTest.java b/test/javax/management/openmbean/EqualsTest.java
new file mode 100644
index 0000000..996f20c
--- /dev/null
+++ b/test/javax/management/openmbean/EqualsTest.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5072174
+ * @summary Test CompositeDataSupport.equals with ArrayType
+ * @author Shanliang JIANG
+ * @run clean EqualsTest
+ * @run build EqualsTest
+ * @run main EqualsTest
+ */
+
+import javax.management.ObjectName;
+import javax.management.openmbean.*;
+
+public class EqualsTest {
+
+ /*
+ * Print message
+ */
+ private static void echo(String message) {
+ System.out.println(message);
+ }
+
+ /**
+ * Main
+ */
+ public static void main(String[] args) throws Exception {
+ echo("=-=-= Test CompositeDataSupport.equals() with ArrayType =-=-=");
+
+ echo(">>> Two SimpleTypes with different descriptions");
+ CompositeType ct1 = new CompositeType(
+ "MyType",
+ "for test",
+ new String[] {"a", "b"},
+ new String[] {"a_desc", "b_desc"},
+ new OpenType[] {SimpleType.BOOLEAN,SimpleType.STRING});
+
+ CompositeType ct2 = new CompositeType(
+ "MyType",
+ "for test",
+ new String[] {"a", "b"},
+ new String[] {"aa_desc", "bb_desc"},
+ new OpenType[] {SimpleType.BOOLEAN, SimpleType.STRING});
+
+ if (!ct1.equals(ct2)) {
+ throw new RuntimeException("CompositeType.equals fails!");
+ }
+ if (ct1.hashCode() != ct2.hashCode()) {
+ throw new RuntimeException("CompositeType.hashCode fails!");
+ }
+
+ echo(">>> Two SimpleTypes with equal values");
+ CompositeData compositeData0 = new CompositeDataSupport(
+ ct1,
+ new String[] {"a", "b"},
+ new Object[] {new Boolean(true), ""});
+
+ CompositeData compositeData1 = new CompositeDataSupport(
+ ct2,
+ new String[] {"a", "b"},
+ new Object[] {new Boolean(true), ""});
+
+ if (!compositeData0.equals(compositeData1)) {
+ throw new RuntimeException("CompositeDataSupport.equals fails!");
+ }
+ if (compositeData0.hashCode() != compositeData1.hashCode()) {
+ throw new RuntimeException("CompositeDataSupport.hashCode fails!");
+ }
+
+ echo(">>> Two ArrayTypes with different references");
+ CompositeType ct3 = new CompositeType(
+ "MyType",
+ "for test",
+ new String[] {"a"},
+ new String[] {"a_desc"},
+ new OpenType[] {new ArrayType(1, SimpleType.STRING)});
+
+ CompositeData compositeData2 = new CompositeDataSupport(
+ ct3,
+ new String[] {"a"},
+ new Object[] {new String[] {"x", "y"}});
+
+ CompositeData compositeData3 = new CompositeDataSupport(
+ ct3,
+ new String[] {"a"},
+ new Object[] {new String[] {"x", "y"}});
+
+ if (!compositeData2.equals(compositeData3)) {
+ throw new RuntimeException("CompositeDataSupport.equals fails!");
+ }
+ if (compositeData2.hashCode() != compositeData3.hashCode()) {
+ throw new RuntimeException("CompositeDataSupport.hashCode fails!");
+ }
+
+ echo(">>> Two ArrayTypes with different values");
+ CompositeData compositeData4 = new CompositeDataSupport(
+ ct3,
+ new String[] {"a"},
+ new Object[] {new String[] {"x", "y", "x"}});
+
+ if (compositeData2.equals(compositeData4)) {
+ throw new RuntimeException("CompositeDataSupport.equals fails!");
+ }
+
+ echo(">>> Two 2-dimension ArrayTypes with equal values");
+ CompositeType ct4 = new CompositeType(
+ "MyType",
+ "for test",
+ new String[] {"a"},
+ new String[] {"a_desc"},
+ new OpenType[] {new ArrayType(2, SimpleType.OBJECTNAME)});
+
+ final String s = "t:t=t";
+ CompositeData compositeData5 = new CompositeDataSupport(
+ ct4,
+ new String[] {"a"},
+ new Object[] {
+ new ObjectName[][] {
+ new ObjectName[] {
+ new ObjectName(s), new ObjectName(s)
+ },
+ new ObjectName[] {
+ new ObjectName(s), new ObjectName(s)
+ }
+ }
+ });
+
+ CompositeData compositeData6 = new CompositeDataSupport(
+ ct4,
+ new String[] {"a"},
+ new Object[] {
+ new ObjectName[][] {
+ new ObjectName[] {
+ new ObjectName(s), new ObjectName(s)
+ },
+ new ObjectName[] {
+ new ObjectName(s), new ObjectName(s)
+ }
+ }
+ });
+
+ if (!compositeData5.equals(compositeData6)) {
+ throw new RuntimeException("CompositeDataSupport.equals fails!");
+ }
+ if (compositeData5.hashCode() != compositeData6.hashCode()) {
+ throw new RuntimeException("CompositeDataSupport.hashCode fails!");
+ }
+
+ echo(">>> Two primitive ArrayTypes with different descriptions");
+ CompositeType ct5 = new CompositeType(
+ "MyType",
+ "for test",
+ new String[] {"a", "b"},
+ new String[] {"a_desc", "b_desc"},
+ new OpenType[] {
+ SimpleType.BOOLEAN,
+ ArrayType.getPrimitiveArrayType(short[].class)
+ });
+
+ CompositeType ct6 = new CompositeType(
+ "MyType",
+ "for test",
+ new String[] {"a", "b"},
+ new String[] {"aa_desc", "bb_desc"},
+ new OpenType[] {
+ SimpleType.BOOLEAN,
+ ArrayType.getPrimitiveArrayType(short[].class)
+ });
+
+ if (!ct5.equals(ct6)) {
+ throw new RuntimeException("CompositeType.equals fails!");
+ }
+ if (ct5.hashCode() != ct6.hashCode()) {
+ throw new RuntimeException("CompositeType.hashCode fails!");
+ }
+
+ echo(">>> Two primitive ArrayTypes with different references");
+ CompositeType ct7 = new CompositeType(
+ "MyType",
+ "for test",
+ new String[] {"a"},
+ new String[] {"a_desc"},
+ new OpenType[] {
+ ArrayType.getPrimitiveArrayType(int[].class)
+ });
+
+ CompositeData compositeData7 = new CompositeDataSupport(
+ ct7,
+ new String[] {"a"},
+ new Object[] {new int[] {1, 2}});
+
+ CompositeData compositeData8 = new CompositeDataSupport(
+ ct7,
+ new String[] {"a"},
+ new Object[] {new int[] {1, 2}});
+
+ if (!compositeData7.equals(compositeData8)) {
+ throw new RuntimeException("CompositeDataSupport.equals fails!");
+ }
+ if (compositeData7.hashCode() != compositeData8.hashCode()) {
+ throw new RuntimeException("CompositeDataSupport.hashCode fails!");
+ }
+
+ echo(">>> Two primitive ArrayTypes with different values");
+ CompositeData compositeData9 = new CompositeDataSupport(
+ ct7,
+ new String[] {"a"},
+ new Object[] {new int[] {1, 2, 3}});
+
+ if (compositeData7.equals(compositeData9)) {
+ throw new RuntimeException("CompositeDataSupport.equals fails!");
+ }
+
+ echo(">>> Two 2-dimension primitive ArrayTypes with equal values");
+ CompositeType ct8 = new CompositeType(
+ "MyType",
+ "for test",
+ new String[] {"a"},
+ new String[] {"a_desc"},
+ new OpenType[] {
+ ArrayType.getPrimitiveArrayType(boolean[][].class)
+ });
+
+ CompositeData compositeData10 = new CompositeDataSupport(
+ ct8,
+ new String[] {"a"},
+ new Object[] {new boolean[][]
+ {new boolean[] {true, true},
+ new boolean[] {true, true}}});
+
+ CompositeData compositeData11 = new CompositeDataSupport(
+ ct8,
+ new String[] {"a"},
+ new Object[] {new boolean[][]
+ {new boolean[] {true, true},
+ new boolean[] {true, true}}});
+
+ if (!compositeData10.equals(compositeData11)) {
+ throw new RuntimeException("CompositeDataSupport.equals fails!");
+ }
+ if (compositeData10.hashCode() != compositeData11.hashCode()) {
+ throw new RuntimeException("CompositeDataSupport.hashCode fails!");
+ }
+ }
+}
diff --git a/test/javax/management/openmbean/IsValueTest.java b/test/javax/management/openmbean/IsValueTest.java
new file mode 100644
index 0000000..237fdc1
--- /dev/null
+++ b/test/javax/management/openmbean/IsValueTest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5072004
+ * @summary Test new rules for isValue
+ * @author Eamonn McManus
+ */
+
+import javax.management.openmbean.*;
+
+public class IsValueTest {
+ private static String failed;
+
+ public static void main(String[] args) throws Exception {
+ CompositeType ctOld =
+ new CompositeType("same.type.name", "old",
+ new String[] {"int", "string"},
+ new String[] {"an int", "a string"},
+ new OpenType[] {SimpleType.INTEGER, SimpleType.STRING});
+ CompositeType ctNew =
+ new CompositeType("same.type.name", "new",
+ new String[] {"int", "int2", "string"},
+ new String[] {"an int", "another int", "a string"},
+ new OpenType[] {SimpleType.INTEGER, SimpleType.INTEGER, SimpleType.STRING});
+ CompositeData cdOld =
+ new CompositeDataSupport(ctOld,
+ new String[] {"string", "int"},
+ new Object[] {"bar", 17});
+ CompositeData cdNew =
+ new CompositeDataSupport(ctNew,
+ new String[] {"int2", "int", "string"},
+ new Object[] {4, 3, "foo"});
+
+ // Check that adding fields doesn't make isValue return false
+ check(ctOld.isValue(cdNew), "isValue: " + ctOld + "[" + cdNew + "]");
+
+ // Check that removing fields does make isValue return false
+ check(!ctNew.isValue(cdOld), "isValue: " + ctNew + "[" + cdOld + "]");
+
+ // Check that we can add a contained CompositeData with extra fields
+ // inside another CompositeData
+ CompositeType ctWrapOld =
+ new CompositeType("wrapper", "wrapper",
+ new String[] {"wrapped"},
+ new String[] {"wrapped"},
+ new OpenType[] {ctOld});
+ try {
+ new CompositeDataSupport(ctWrapOld,
+ new String[] {"wrapped"},
+ new Object[] {cdNew});
+ check(true, "CompositeDataSupport containing CompositeDataSupport");
+ } catch (Exception e) {
+ e.printStackTrace(System.out);
+ check(false, "CompositeDataSupport containing CompositeDataSupport: " + e);
+ }
+
+ // ...but not the contrary
+ CompositeType ctWrapNew =
+ new CompositeType("wrapper", "wrapper",
+ new String[] {"wrapped"},
+ new String[] {"wrapped"},
+ new OpenType[] {ctNew});
+ try {
+ new CompositeDataSupport(ctWrapNew,
+ new String[] {"wrapped"},
+ new Object[] {cdOld});
+ check(false, "CompositeDataSupport containing old did not get exception");
+ } catch (OpenDataException e) {
+ check(true, "CompositeDataSupport containing old got expected exception: " + e);
+ }
+
+ // Check that a TabularData can get an extended CompositeData row
+ TabularType ttOld =
+ new TabularType("tabular", "tabular", ctOld, new String[] {"int"});
+ TabularData tdOld =
+ new TabularDataSupport(ttOld);
+ try {
+ tdOld.put(cdNew);
+ check(true, "TabularDataSupport adding extended CompositeData");
+ } catch (Exception e) {
+ e.printStackTrace(System.out);
+ check(false, "TabularDataSupport adding extended CompositeData: " + e);
+ }
+
+ // Check that an extended TabularData can be put into a CompositeData
+ TabularType ttNew =
+ new TabularType("tabular", "tabular", ctNew, new String[] {"int"});
+ TabularData tdNew =
+ new TabularDataSupport(ttNew);
+ CompositeType cttWrap =
+ new CompositeType("wrapTT", "wrapTT",
+ new String[] {"wrapped"},
+ new String[] {"wrapped"},
+ new OpenType[] {ttOld});
+ try {
+ new CompositeDataSupport(cttWrap,
+ new String[] {"wrapped"},
+ new Object[] {tdNew});
+ check(true, "CompositeDataSupport adding extended TabularData");
+ } catch (Exception e) {
+ e.printStackTrace(System.out);
+ check(false, "CompositeDataSupport adding extended TabularData: " + e);
+ }
+
+ if (failed != null)
+ throw new Exception("TEST FAILED: " + failed);
+ }
+
+ private static void check(boolean value, String what) {
+ if (value)
+ System.out.println("OK: " + what);
+ else {
+ failed = what;
+ System.out.println("FAILED: " + what);
+ }
+ }
+}
diff --git a/test/javax/management/openmbean/MBeanFeatureInfoSerialStore.java b/test/javax/management/openmbean/MBeanFeatureInfoSerialStore.java
new file mode 100644
index 0000000..8f0d348
--- /dev/null
+++ b/test/javax/management/openmbean/MBeanFeatureInfoSerialStore.java
@@ -0,0 +1,1100 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * build @BUILD_TAG_PLACEHOLDER@
+ *
+ * @COPYRIGHT_MINI_LEGAL_NOTICE_PLACEHOLDER@
+ */
+/*
+ * MBeanFeatureInfoSerialStore
+ *
+ * Generated on December 9, 2005 by dfuchs
+ * with JRE: Sun Microsystems Inc. 1.5.0_05
+ *
+ */
+
+
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.MBeanFeatureInfo;
+
+/**
+ * The class MBeanFeatureInfoSerialStore is a static store of MBeanFeatureInfo instances
+ * serialized with java version 1.5.0_05.
+ * It is used to check serial compatibility with later version of the
+ * JDK.
+ **/
+public class MBeanFeatureInfoSerialStore {
+
+ // The serial object store.
+ //
+ private static final Map<String,byte[]> map =
+ new HashMap<String,byte[]>();
+ static {
+ // initialization of serial store
+ // floatAttr: javax.management.openmbean.OpenMBeanAttributeInfoSupport
+ //
+ {
+ final byte[] bytes = new byte[] {
+ -84,-19,0,5,115,114,0,56,106,97,
+ 118,97,120,46,109,97,110,97,103,101,
+ 109,101,110,116,46,111,112,101,110,109,
+ 98,101,97,110,46,79,112,101,110,77,
+ 66,101,97,110,65,116,116,114,105,98,
+ 117,116,101,73,110,102,111,83,117,112,
+ 112,111,114,116,-68,116,45,45,-28,-120,
+ -79,7,2,0,5,76,0,12,100,101,
+ 102,97,117,108,116,86,97,108,117,101,
+ 116,0,18,76,106,97,118,97,47,108,
+ 97,110,103,47,79,98,106,101,99,116,
+ 59,76,0,11,108,101,103,97,108,86,
+ 97,108,117,101,115,116,0,15,76,106,
+ 97,118,97,47,117,116,105,108,47,83,
+ 101,116,59,76,0,8,109,97,120,86,
+ 97,108,117,101,116,0,22,76,106,97,
+ 118,97,47,108,97,110,103,47,67,111,
+ 109,112,97,114,97,98,108,101,59,76,
+ 0,8,109,105,110,86,97,108,117,101,
+ 113,0,126,0,3,76,0,8,111,112,
+ 101,110,84,121,112,101,116,0,37,76,
+ 106,97,118,97,120,47,109,97,110,97,
+ 103,101,109,101,110,116,47,111,112,101,
+ 110,109,98,101,97,110,47,79,112,101,
+ 110,84,121,112,101,59,120,114,0,35,
+ 106,97,118,97,120,46,109,97,110,97,
+ 103,101,109,101,110,116,46,77,66,101,
+ 97,110,65,116,116,114,105,98,117,116,
+ 101,73,110,102,111,119,-8,41,59,106,
+ 41,68,-40,2,0,4,90,0,2,105,
+ 115,90,0,6,105,115,82,101,97,100,
+ 90,0,7,105,115,87,114,105,116,101,
+ 76,0,13,97,116,116,114,105,98,117,
+ 116,101,84,121,112,101,116,0,18,76,
+ 106,97,118,97,47,108,97,110,103,47,
+ 83,116,114,105,110,103,59,120,114,0,
+ 33,106,97,118,97,120,46,109,97,110,
+ 97,103,101,109,101,110,116,46,77,66,
+ 101,97,110,70,101,97,116,117,114,101,
+ 73,110,102,111,54,-37,117,-36,-62,-63,
+ 85,33,2,0,2,76,0,11,100,101,
+ 115,99,114,105,112,116,105,111,110,113,
+ 0,126,0,6,76,0,4,110,97,109,
+ 101,113,0,126,0,6,120,112,116,0,
+ 5,100,101,115,99,114,116,0,9,102,
+ 108,111,97,116,65,116,116,114,0,1,
+ 1,116,0,15,106,97,118,97,46,108,
+ 97,110,103,46,70,108,111,97,116,115,
+ 114,0,15,106,97,118,97,46,108,97,
+ 110,103,46,70,108,111,97,116,-38,-19,
+ -55,-94,-37,60,-16,-20,2,0,1,70,
+ 0,5,118,97,108,117,101,120,114,0,
+ 16,106,97,118,97,46,108,97,110,103,
+ 46,78,117,109,98,101,114,-122,-84,-107,
+ 29,11,-108,-32,-117,2,0,0,120,112,
+ 63,-128,0,0,112,115,113,0,126,0,
+ 12,64,0,0,0,115,113,0,126,0,
+ 12,0,0,0,0,115,114,0,37,106,
+ 97,118,97,120,46,109,97,110,97,103,
+ 101,109,101,110,116,46,111,112,101,110,
+ 109,98,101,97,110,46,83,105,109,112,
+ 108,101,84,121,112,101,30,-65,79,-8,
+ -36,101,120,39,2,0,0,120,114,0,
+ 35,106,97,118,97,120,46,109,97,110,
+ 97,103,101,109,101,110,116,46,111,112,
+ 101,110,109,98,101,97,110,46,79,112,
+ 101,110,84,121,112,101,-128,100,26,-111,
+ -23,-22,-34,60,2,0,3,76,0,9,
+ 99,108,97,115,115,78,97,109,101,113,
+ 0,126,0,6,76,0,11,100,101,115,
+ 99,114,105,112,116,105,111,110,113,0,
+ 126,0,6,76,0,8,116,121,112,101,
+ 78,97,109,101,113,0,126,0,6,120,
+ 112,113,0,126,0,11,113,0,126,0,
+ 11,113,0,126,0,11
+ };
+ map.put("floatAttr",bytes);
+ }
+ // intAttr: javax.management.openmbean.OpenMBeanAttributeInfoSupport
+ //
+ {
+ final byte[] bytes = new byte[] {
+ -84,-19,0,5,115,114,0,56,106,97,
+ 118,97,120,46,109,97,110,97,103,101,
+ 109,101,110,116,46,111,112,101,110,109,
+ 98,101,97,110,46,79,112,101,110,77,
+ 66,101,97,110,65,116,116,114,105,98,
+ 117,116,101,73,110,102,111,83,117,112,
+ 112,111,114,116,-68,116,45,45,-28,-120,
+ -79,7,2,0,5,76,0,12,100,101,
+ 102,97,117,108,116,86,97,108,117,101,
+ 116,0,18,76,106,97,118,97,47,108,
+ 97,110,103,47,79,98,106,101,99,116,
+ 59,76,0,11,108,101,103,97,108,86,
+ 97,108,117,101,115,116,0,15,76,106,
+ 97,118,97,47,117,116,105,108,47,83,
+ 101,116,59,76,0,8,109,97,120,86,
+ 97,108,117,101,116,0,22,76,106,97,
+ 118,97,47,108,97,110,103,47,67,111,
+ 109,112,97,114,97,98,108,101,59,76,
+ 0,8,109,105,110,86,97,108,117,101,
+ 113,0,126,0,3,76,0,8,111,112,
+ 101,110,84,121,112,101,116,0,37,76,
+ 106,97,118,97,120,47,109,97,110,97,
+ 103,101,109,101,110,116,47,111,112,101,
+ 110,109,98,101,97,110,47,79,112,101,
+ 110,84,121,112,101,59,120,114,0,35,
+ 106,97,118,97,120,46,109,97,110,97,
+ 103,101,109,101,110,116,46,77,66,101,
+ 97,110,65,116,116,114,105,98,117,116,
+ 101,73,110,102,111,119,-8,41,59,106,
+ 41,68,-40,2,0,4,90,0,2,105,
+ 115,90,0,6,105,115,82,101,97,100,
+ 90,0,7,105,115,87,114,105,116,101,
+ 76,0,13,97,116,116,114,105,98,117,
+ 116,101,84,121,112,101,116,0,18,76,
+ 106,97,118,97,47,108,97,110,103,47,
+ 83,116,114,105,110,103,59,120,114,0,
+ 33,106,97,118,97,120,46,109,97,110,
+ 97,103,101,109,101,110,116,46,77,66,
+ 101,97,110,70,101,97,116,117,114,101,
+ 73,110,102,111,54,-37,117,-36,-62,-63,
+ 85,33,2,0,2,76,0,11,100,101,
+ 115,99,114,105,112,116,105,111,110,113,
+ 0,126,0,6,76,0,4,110,97,109,
+ 101,113,0,126,0,6,120,112,116,0,
+ 5,100,101,115,99,114,116,0,7,105,
+ 110,116,65,116,116,114,0,0,1,116,
+ 0,17,106,97,118,97,46,108,97,110,
+ 103,46,73,110,116,101,103,101,114,112,
+ 112,112,112,115,114,0,37,106,97,118,
+ 97,120,46,109,97,110,97,103,101,109,
+ 101,110,116,46,111,112,101,110,109,98,
+ 101,97,110,46,83,105,109,112,108,101,
+ 84,121,112,101,30,-65,79,-8,-36,101,
+ 120,39,2,0,0,120,114,0,35,106,
+ 97,118,97,120,46,109,97,110,97,103,
+ 101,109,101,110,116,46,111,112,101,110,
+ 109,98,101,97,110,46,79,112,101,110,
+ 84,121,112,101,-128,100,26,-111,-23,-22,
+ -34,60,2,0,3,76,0,9,99,108,
+ 97,115,115,78,97,109,101,113,0,126,
+ 0,6,76,0,11,100,101,115,99,114,
+ 105,112,116,105,111,110,113,0,126,0,
+ 6,76,0,8,116,121,112,101,78,97,
+ 109,101,113,0,126,0,6,120,112,113,
+ 0,126,0,11,113,0,126,0,11,113,
+ 0,126,0,11
+ };
+ map.put("intAttr",bytes);
+ }
+ // arrayOp: javax.management.openmbean.OpenMBeanOperationInfoSupport
+ //
+ {
+ final byte[] bytes = new byte[] {
+ -84,-19,0,5,115,114,0,56,106,97,
+ 118,97,120,46,109,97,110,97,103,101,
+ 109,101,110,116,46,111,112,101,110,109,
+ 98,101,97,110,46,79,112,101,110,77,
+ 66,101,97,110,79,112,101,114,97,116,
+ 105,111,110,73,110,102,111,83,117,112,
+ 112,111,114,116,69,88,105,115,-56,3,
+ 34,22,2,0,1,76,0,14,114,101,
+ 116,117,114,110,79,112,101,110,84,121,
+ 112,101,116,0,37,76,106,97,118,97,
+ 120,47,109,97,110,97,103,101,109,101,
+ 110,116,47,111,112,101,110,109,98,101,
+ 97,110,47,79,112,101,110,84,121,112,
+ 101,59,120,114,0,35,106,97,118,97,
+ 120,46,109,97,110,97,103,101,109,101,
+ 110,116,46,77,66,101,97,110,79,112,
+ 101,114,97,116,105,111,110,73,110,102,
+ 111,-86,64,71,34,-107,-2,-125,-98,2,
+ 0,3,73,0,6,105,109,112,97,99,
+ 116,91,0,9,115,105,103,110,97,116,
+ 117,114,101,116,0,38,91,76,106,97,
+ 118,97,120,47,109,97,110,97,103,101,
+ 109,101,110,116,47,77,66,101,97,110,
+ 80,97,114,97,109,101,116,101,114,73,
+ 110,102,111,59,76,0,4,116,121,112,
+ 101,116,0,18,76,106,97,118,97,47,
+ 108,97,110,103,47,83,116,114,105,110,
+ 103,59,120,114,0,33,106,97,118,97,
+ 120,46,109,97,110,97,103,101,109,101,
+ 110,116,46,77,66,101,97,110,70,101,
+ 97,116,117,114,101,73,110,102,111,54,
+ -37,117,-36,-62,-63,85,33,2,0,2,
+ 76,0,11,100,101,115,99,114,105,112,
+ 116,105,111,110,113,0,126,0,4,76,
+ 0,4,110,97,109,101,113,0,126,0,
+ 4,120,112,116,0,5,100,101,115,99,
+ 114,116,0,7,97,114,114,97,121,79,
+ 112,0,0,0,1,117,114,0,38,91,
+ 76,106,97,118,97,120,46,109,97,110,
+ 97,103,101,109,101,110,116,46,77,66,
+ 101,97,110,80,97,114,97,109,101,116,
+ 101,114,73,110,102,111,59,-51,104,101,
+ 54,3,-80,-18,54,2,0,0,120,112,
+ 0,0,0,0,116,0,20,91,76,106,
+ 97,118,97,46,108,97,110,103,46,73,
+ 110,116,101,103,101,114,59,115,114,0,
+ 36,106,97,118,97,120,46,109,97,110,
+ 97,103,101,109,101,110,116,46,111,112,
+ 101,110,109,98,101,97,110,46,65,114,
+ 114,97,121,84,121,112,101,9,-1,-66,
+ -10,39,33,-121,-118,2,0,2,73,0,
+ 9,100,105,109,101,110,115,105,111,110,
+ 76,0,11,101,108,101,109,101,110,116,
+ 84,121,112,101,113,0,126,0,1,120,
+ 114,0,35,106,97,118,97,120,46,109,
+ 97,110,97,103,101,109,101,110,116,46,
+ 111,112,101,110,109,98,101,97,110,46,
+ 79,112,101,110,84,121,112,101,-128,100,
+ 26,-111,-23,-22,-34,60,2,0,3,76,
+ 0,9,99,108,97,115,115,78,97,109,
+ 101,113,0,126,0,4,76,0,11,100,
+ 101,115,99,114,105,112,116,105,111,110,
+ 113,0,126,0,4,76,0,8,116,121,
+ 112,101,78,97,109,101,113,0,126,0,
+ 4,120,112,113,0,126,0,11,116,0,
+ 38,49,45,100,105,109,101,110,115,105,
+ 111,110,32,97,114,114,97,121,32,111,
+ 102,32,106,97,118,97,46,108,97,110,
+ 103,46,73,110,116,101,103,101,114,116,
+ 0,20,91,76,106,97,118,97,46,108,
+ 97,110,103,46,73,110,116,101,103,101,
+ 114,59,0,0,0,1,115,114,0,37,
+ 106,97,118,97,120,46,109,97,110,97,
+ 103,101,109,101,110,116,46,111,112,101,
+ 110,109,98,101,97,110,46,83,105,109,
+ 112,108,101,84,121,112,101,30,-65,79,
+ -8,-36,101,120,39,2,0,0,120,113,
+ 0,126,0,13,116,0,17,106,97,118,
+ 97,46,108,97,110,103,46,73,110,116,
+ 101,103,101,114,113,0,126,0,19,113,
+ 0,126,0,19
+ };
+ map.put("arrayOp",bytes);
+ }
+ // intPar: javax.management.openmbean.OpenMBeanParameterInfoSupport
+ //
+ {
+ final byte[] bytes = new byte[] {
+ -84,-19,0,5,115,114,0,56,106,97,
+ 118,97,120,46,109,97,110,97,103,101,
+ 109,101,110,116,46,111,112,101,110,109,
+ 98,101,97,110,46,79,112,101,110,77,
+ 66,101,97,110,80,97,114,97,109,101,
+ 116,101,114,73,110,102,111,83,117,112,
+ 112,111,114,116,-101,-104,14,124,111,-85,
+ -71,-114,2,0,5,76,0,12,100,101,
+ 102,97,117,108,116,86,97,108,117,101,
+ 116,0,18,76,106,97,118,97,47,108,
+ 97,110,103,47,79,98,106,101,99,116,
+ 59,76,0,11,108,101,103,97,108,86,
+ 97,108,117,101,115,116,0,15,76,106,
+ 97,118,97,47,117,116,105,108,47,83,
+ 101,116,59,76,0,8,109,97,120,86,
+ 97,108,117,101,116,0,22,76,106,97,
+ 118,97,47,108,97,110,103,47,67,111,
+ 109,112,97,114,97,98,108,101,59,76,
+ 0,8,109,105,110,86,97,108,117,101,
+ 113,0,126,0,3,76,0,8,111,112,
+ 101,110,84,121,112,101,116,0,37,76,
+ 106,97,118,97,120,47,109,97,110,97,
+ 103,101,109,101,110,116,47,111,112,101,
+ 110,109,98,101,97,110,47,79,112,101,
+ 110,84,121,112,101,59,120,114,0,35,
+ 106,97,118,97,120,46,109,97,110,97,
+ 103,101,109,101,110,116,46,77,66,101,
+ 97,110,80,97,114,97,109,101,116,101,
+ 114,73,110,102,111,103,37,-11,-84,-39,
+ 123,54,2,2,0,1,76,0,4,116,
+ 121,112,101,116,0,18,76,106,97,118,
+ 97,47,108,97,110,103,47,83,116,114,
+ 105,110,103,59,120,114,0,33,106,97,
+ 118,97,120,46,109,97,110,97,103,101,
+ 109,101,110,116,46,77,66,101,97,110,
+ 70,101,97,116,117,114,101,73,110,102,
+ 111,54,-37,117,-36,-62,-63,85,33,2,
+ 0,2,76,0,11,100,101,115,99,114,
+ 105,112,116,105,111,110,113,0,126,0,
+ 6,76,0,4,110,97,109,101,113,0,
+ 126,0,6,120,112,116,0,5,100,101,
+ 115,99,114,116,0,6,105,110,116,80,
+ 97,114,116,0,17,106,97,118,97,46,
+ 108,97,110,103,46,73,110,116,101,103,
+ 101,114,112,112,112,112,115,114,0,37,
+ 106,97,118,97,120,46,109,97,110,97,
+ 103,101,109,101,110,116,46,111,112,101,
+ 110,109,98,101,97,110,46,83,105,109,
+ 112,108,101,84,121,112,101,30,-65,79,
+ -8,-36,101,120,39,2,0,0,120,114,
+ 0,35,106,97,118,97,120,46,109,97,
+ 110,97,103,101,109,101,110,116,46,111,
+ 112,101,110,109,98,101,97,110,46,79,
+ 112,101,110,84,121,112,101,-128,100,26,
+ -111,-23,-22,-34,60,2,0,3,76,0,
+ 9,99,108,97,115,115,78,97,109,101,
+ 113,0,126,0,6,76,0,11,100,101,
+ 115,99,114,105,112,116,105,111,110,113,
+ 0,126,0,6,76,0,8,116,121,112,
+ 101,78,97,109,101,113,0,126,0,6,
+ 120,112,113,0,126,0,11,113,0,126,
+ 0,11,113,0,126,0,11
+ };
+ map.put("intPar",bytes);
+ }
+ // boolPar: javax.management.openmbean.OpenMBeanParameterInfoSupport
+ //
+ {
+ final byte[] bytes = new byte[] {
+ -84,-19,0,5,115,114,0,56,106,97,
+ 118,97,120,46,109,97,110,97,103,101,
+ 109,101,110,116,46,111,112,101,110,109,
+ 98,101,97,110,46,79,112,101,110,77,
+ 66,101,97,110,80,97,114,97,109,101,
+ 116,101,114,73,110,102,111,83,117,112,
+ 112,111,114,116,-101,-104,14,124,111,-85,
+ -71,-114,2,0,5,76,0,12,100,101,
+ 102,97,117,108,116,86,97,108,117,101,
+ 116,0,18,76,106,97,118,97,47,108,
+ 97,110,103,47,79,98,106,101,99,116,
+ 59,76,0,11,108,101,103,97,108,86,
+ 97,108,117,101,115,116,0,15,76,106,
+ 97,118,97,47,117,116,105,108,47,83,
+ 101,116,59,76,0,8,109,97,120,86,
+ 97,108,117,101,116,0,22,76,106,97,
+ 118,97,47,108,97,110,103,47,67,111,
+ 109,112,97,114,97,98,108,101,59,76,
+ 0,8,109,105,110,86,97,108,117,101,
+ 113,0,126,0,3,76,0,8,111,112,
+ 101,110,84,121,112,101,116,0,37,76,
+ 106,97,118,97,120,47,109,97,110,97,
+ 103,101,109,101,110,116,47,111,112,101,
+ 110,109,98,101,97,110,47,79,112,101,
+ 110,84,121,112,101,59,120,114,0,35,
+ 106,97,118,97,120,46,109,97,110,97,
+ 103,101,109,101,110,116,46,77,66,101,
+ 97,110,80,97,114,97,109,101,116,101,
+ 114,73,110,102,111,103,37,-11,-84,-39,
+ 123,54,2,2,0,1,76,0,4,116,
+ 121,112,101,116,0,18,76,106,97,118,
+ 97,47,108,97,110,103,47,83,116,114,
+ 105,110,103,59,120,114,0,33,106,97,
+ 118,97,120,46,109,97,110,97,103,101,
+ 109,101,110,116,46,77,66,101,97,110,
+ 70,101,97,116,117,114,101,73,110,102,
+ 111,54,-37,117,-36,-62,-63,85,33,2,
+ 0,2,76,0,11,100,101,115,99,114,
+ 105,112,116,105,111,110,113,0,126,0,
+ 6,76,0,4,110,97,109,101,113,0,
+ 126,0,6,120,112,116,0,5,100,101,
+ 115,99,114,116,0,7,98,111,111,108,
+ 80,97,114,116,0,17,106,97,118,97,
+ 46,108,97,110,103,46,66,111,111,108,
+ 101,97,110,115,114,0,17,106,97,118,
+ 97,46,108,97,110,103,46,66,111,111,
+ 108,101,97,110,-51,32,114,-128,-43,-100,
+ -6,-18,2,0,1,90,0,5,118,97,
+ 108,117,101,120,112,1,112,112,112,115,
+ 114,0,37,106,97,118,97,120,46,109,
+ 97,110,97,103,101,109,101,110,116,46,
+ 111,112,101,110,109,98,101,97,110,46,
+ 83,105,109,112,108,101,84,121,112,101,
+ 30,-65,79,-8,-36,101,120,39,2,0,
+ 0,120,114,0,35,106,97,118,97,120,
+ 46,109,97,110,97,103,101,109,101,110,
+ 116,46,111,112,101,110,109,98,101,97,
+ 110,46,79,112,101,110,84,121,112,101,
+ -128,100,26,-111,-23,-22,-34,60,2,0,
+ 3,76,0,9,99,108,97,115,115,78,
+ 97,109,101,113,0,126,0,6,76,0,
+ 11,100,101,115,99,114,105,112,116,105,
+ 111,110,113,0,126,0,6,76,0,8,
+ 116,121,112,101,78,97,109,101,113,0,
+ 126,0,6,120,112,113,0,126,0,11,
+ 113,0,126,0,11,113,0,126,0,11
+ };
+ map.put("boolPar",bytes);
+ }
+ // findWombat: javax.management.openmbean.OpenMBeanOperationInfoSupport
+ //
+ {
+ final byte[] bytes = new byte[] {
+ -84,-19,0,5,115,114,0,56,106,97,
+ 118,97,120,46,109,97,110,97,103,101,
+ 109,101,110,116,46,111,112,101,110,109,
+ 98,101,97,110,46,79,112,101,110,77,
+ 66,101,97,110,79,112,101,114,97,116,
+ 105,111,110,73,110,102,111,83,117,112,
+ 112,111,114,116,69,88,105,115,-56,3,
+ 34,22,2,0,1,76,0,14,114,101,
+ 116,117,114,110,79,112,101,110,84,121,
+ 112,101,116,0,37,76,106,97,118,97,
+ 120,47,109,97,110,97,103,101,109,101,
+ 110,116,47,111,112,101,110,109,98,101,
+ 97,110,47,79,112,101,110,84,121,112,
+ 101,59,120,114,0,35,106,97,118,97,
+ 120,46,109,97,110,97,103,101,109,101,
+ 110,116,46,77,66,101,97,110,79,112,
+ 101,114,97,116,105,111,110,73,110,102,
+ 111,-86,64,71,34,-107,-2,-125,-98,2,
+ 0,3,73,0,6,105,109,112,97,99,
+ 116,91,0,9,115,105,103,110,97,116,
+ 117,114,101,116,0,38,91,76,106,97,
+ 118,97,120,47,109,97,110,97,103,101,
+ 109,101,110,116,47,77,66,101,97,110,
+ 80,97,114,97,109,101,116,101,114,73,
+ 110,102,111,59,76,0,4,116,121,112,
+ 101,116,0,18,76,106,97,118,97,47,
+ 108,97,110,103,47,83,116,114,105,110,
+ 103,59,120,114,0,33,106,97,118,97,
+ 120,46,109,97,110,97,103,101,109,101,
+ 110,116,46,77,66,101,97,110,70,101,
+ 97,116,117,114,101,73,110,102,111,54,
+ -37,117,-36,-62,-63,85,33,2,0,2,
+ 76,0,11,100,101,115,99,114,105,112,
+ 116,105,111,110,113,0,126,0,4,76,
+ 0,4,110,97,109,101,113,0,126,0,
+ 4,120,112,116,0,36,84,104,105,115,
+ 32,109,101,116,104,111,100,32,108,111,
+ 111,107,115,32,102,111,114,32,87,111,
+ 109,98,97,116,32,105,110,32,106,97,
+ 114,115,116,0,10,102,105,110,100,87,
+ 111,109,98,97,116,0,0,0,2,117,
+ 114,0,38,91,76,106,97,118,97,120,
+ 46,109,97,110,97,103,101,109,101,110,
+ 116,46,77,66,101,97,110,80,97,114,
+ 97,109,101,116,101,114,73,110,102,111,
+ 59,-51,104,101,54,3,-80,-18,54,2,
+ 0,0,120,112,0,0,0,1,115,114,
+ 0,56,106,97,118,97,120,46,109,97,
+ 110,97,103,101,109,101,110,116,46,111,
+ 112,101,110,109,98,101,97,110,46,79,
+ 112,101,110,77,66,101,97,110,80,97,
+ 114,97,109,101,116,101,114,73,110,102,
+ 111,83,117,112,112,111,114,116,-101,-104,
+ 14,124,111,-85,-71,-114,2,0,5,76,
+ 0,12,100,101,102,97,117,108,116,86,
+ 97,108,117,101,116,0,18,76,106,97,
+ 118,97,47,108,97,110,103,47,79,98,
+ 106,101,99,116,59,76,0,11,108,101,
+ 103,97,108,86,97,108,117,101,115,116,
+ 0,15,76,106,97,118,97,47,117,116,
+ 105,108,47,83,101,116,59,76,0,8,
+ 109,97,120,86,97,108,117,101,116,0,
+ 22,76,106,97,118,97,47,108,97,110,
+ 103,47,67,111,109,112,97,114,97,98,
+ 108,101,59,76,0,8,109,105,110,86,
+ 97,108,117,101,113,0,126,0,14,76,
+ 0,8,111,112,101,110,84,121,112,101,
+ 113,0,126,0,1,120,114,0,35,106,
+ 97,118,97,120,46,109,97,110,97,103,
+ 101,109,101,110,116,46,77,66,101,97,
+ 110,80,97,114,97,109,101,116,101,114,
+ 73,110,102,111,103,37,-11,-84,-39,123,
+ 54,2,2,0,1,76,0,4,116,121,
+ 112,101,113,0,126,0,4,120,113,0,
+ 126,0,5,116,0,23,97,106,97,114,
+ 32,109,117,115,116,32,110,111,116,32,
+ 98,101,32,115,101,97,108,101,100,116,
+ 0,4,97,106,97,114,116,0,16,106,
+ 97,118,97,46,108,97,110,103,46,83,
+ 116,114,105,110,103,116,0,12,110,111,
+ 119,111,109,98,97,116,46,106,97,114,
+ 112,112,112,115,114,0,37,106,97,118,
+ 97,120,46,109,97,110,97,103,101,109,
+ 101,110,116,46,111,112,101,110,109,98,
+ 101,97,110,46,83,105,109,112,108,101,
+ 84,121,112,101,30,-65,79,-8,-36,101,
+ 120,39,2,0,0,120,114,0,35,106,
+ 97,118,97,120,46,109,97,110,97,103,
+ 101,109,101,110,116,46,111,112,101,110,
+ 109,98,101,97,110,46,79,112,101,110,
+ 84,121,112,101,-128,100,26,-111,-23,-22,
+ -34,60,2,0,3,76,0,9,99,108,
+ 97,115,115,78,97,109,101,113,0,126,
+ 0,4,76,0,11,100,101,115,99,114,
+ 105,112,116,105,111,110,113,0,126,0,
+ 4,76,0,8,116,121,112,101,78,97,
+ 109,101,113,0,126,0,4,120,112,113,
+ 0,126,0,19,113,0,126,0,19,113,
+ 0,126,0,19,116,0,17,106,97,118,
+ 97,46,108,97,110,103,46,66,111,111,
+ 108,101,97,110,115,113,0,126,0,21,
+ 113,0,126,0,24,113,0,126,0,24,
+ 113,0,126,0,24
+ };
+ map.put("findWombat",bytes);
+ }
+ // stringAttr: javax.management.openmbean.OpenMBeanAttributeInfoSupport
+ //
+ {
+ final byte[] bytes = new byte[] {
+ -84,-19,0,5,115,114,0,56,106,97,
+ 118,97,120,46,109,97,110,97,103,101,
+ 109,101,110,116,46,111,112,101,110,109,
+ 98,101,97,110,46,79,112,101,110,77,
+ 66,101,97,110,65,116,116,114,105,98,
+ 117,116,101,73,110,102,111,83,117,112,
+ 112,111,114,116,-68,116,45,45,-28,-120,
+ -79,7,2,0,5,76,0,12,100,101,
+ 102,97,117,108,116,86,97,108,117,101,
+ 116,0,18,76,106,97,118,97,47,108,
+ 97,110,103,47,79,98,106,101,99,116,
+ 59,76,0,11,108,101,103,97,108,86,
+ 97,108,117,101,115,116,0,15,76,106,
+ 97,118,97,47,117,116,105,108,47,83,
+ 101,116,59,76,0,8,109,97,120,86,
+ 97,108,117,101,116,0,22,76,106,97,
+ 118,97,47,108,97,110,103,47,67,111,
+ 109,112,97,114,97,98,108,101,59,76,
+ 0,8,109,105,110,86,97,108,117,101,
+ 113,0,126,0,3,76,0,8,111,112,
+ 101,110,84,121,112,101,116,0,37,76,
+ 106,97,118,97,120,47,109,97,110,97,
+ 103,101,109,101,110,116,47,111,112,101,
+ 110,109,98,101,97,110,47,79,112,101,
+ 110,84,121,112,101,59,120,114,0,35,
+ 106,97,118,97,120,46,109,97,110,97,
+ 103,101,109,101,110,116,46,77,66,101,
+ 97,110,65,116,116,114,105,98,117,116,
+ 101,73,110,102,111,119,-8,41,59,106,
+ 41,68,-40,2,0,4,90,0,2,105,
+ 115,90,0,6,105,115,82,101,97,100,
+ 90,0,7,105,115,87,114,105,116,101,
+ 76,0,13,97,116,116,114,105,98,117,
+ 116,101,84,121,112,101,116,0,18,76,
+ 106,97,118,97,47,108,97,110,103,47,
+ 83,116,114,105,110,103,59,120,114,0,
+ 33,106,97,118,97,120,46,109,97,110,
+ 97,103,101,109,101,110,116,46,77,66,
+ 101,97,110,70,101,97,116,117,114,101,
+ 73,110,102,111,54,-37,117,-36,-62,-63,
+ 85,33,2,0,2,76,0,11,100,101,
+ 115,99,114,105,112,116,105,111,110,113,
+ 0,126,0,6,76,0,4,110,97,109,
+ 101,113,0,126,0,6,120,112,116,0,
+ 5,100,101,115,99,114,116,0,10,115,
+ 116,114,105,110,103,65,116,116,114,0,
+ 1,0,116,0,16,106,97,118,97,46,
+ 108,97,110,103,46,83,116,114,105,110,
+ 103,112,112,112,112,115,114,0,37,106,
+ 97,118,97,120,46,109,97,110,97,103,
+ 101,109,101,110,116,46,111,112,101,110,
+ 109,98,101,97,110,46,83,105,109,112,
+ 108,101,84,121,112,101,30,-65,79,-8,
+ -36,101,120,39,2,0,0,120,114,0,
+ 35,106,97,118,97,120,46,109,97,110,
+ 97,103,101,109,101,110,116,46,111,112,
+ 101,110,109,98,101,97,110,46,79,112,
+ 101,110,84,121,112,101,-128,100,26,-111,
+ -23,-22,-34,60,2,0,3,76,0,9,
+ 99,108,97,115,115,78,97,109,101,113,
+ 0,126,0,6,76,0,11,100,101,115,
+ 99,114,105,112,116,105,111,110,113,0,
+ 126,0,6,76,0,8,116,121,112,101,
+ 78,97,109,101,113,0,126,0,6,120,
+ 112,113,0,126,0,11,113,0,126,0,
+ 11,113,0,126,0,11
+ };
+ map.put("stringAttr",bytes);
+ }
+ // datePar: javax.management.openmbean.OpenMBeanParameterInfoSupport
+ //
+ {
+ final byte[] bytes = new byte[] {
+ -84,-19,0,5,115,114,0,56,106,97,
+ 118,97,120,46,109,97,110,97,103,101,
+ 109,101,110,116,46,111,112,101,110,109,
+ 98,101,97,110,46,79,112,101,110,77,
+ 66,101,97,110,80,97,114,97,109,101,
+ 116,101,114,73,110,102,111,83,117,112,
+ 112,111,114,116,-101,-104,14,124,111,-85,
+ -71,-114,2,0,5,76,0,12,100,101,
+ 102,97,117,108,116,86,97,108,117,101,
+ 116,0,18,76,106,97,118,97,47,108,
+ 97,110,103,47,79,98,106,101,99,116,
+ 59,76,0,11,108,101,103,97,108,86,
+ 97,108,117,101,115,116,0,15,76,106,
+ 97,118,97,47,117,116,105,108,47,83,
+ 101,116,59,76,0,8,109,97,120,86,
+ 97,108,117,101,116,0,22,76,106,97,
+ 118,97,47,108,97,110,103,47,67,111,
+ 109,112,97,114,97,98,108,101,59,76,
+ 0,8,109,105,110,86,97,108,117,101,
+ 113,0,126,0,3,76,0,8,111,112,
+ 101,110,84,121,112,101,116,0,37,76,
+ 106,97,118,97,120,47,109,97,110,97,
+ 103,101,109,101,110,116,47,111,112,101,
+ 110,109,98,101,97,110,47,79,112,101,
+ 110,84,121,112,101,59,120,114,0,35,
+ 106,97,118,97,120,46,109,97,110,97,
+ 103,101,109,101,110,116,46,77,66,101,
+ 97,110,80,97,114,97,109,101,116,101,
+ 114,73,110,102,111,103,37,-11,-84,-39,
+ 123,54,2,2,0,1,76,0,4,116,
+ 121,112,101,116,0,18,76,106,97,118,
+ 97,47,108,97,110,103,47,83,116,114,
+ 105,110,103,59,120,114,0,33,106,97,
+ 118,97,120,46,109,97,110,97,103,101,
+ 109,101,110,116,46,77,66,101,97,110,
+ 70,101,97,116,117,114,101,73,110,102,
+ 111,54,-37,117,-36,-62,-63,85,33,2,
+ 0,2,76,0,11,100,101,115,99,114,
+ 105,112,116,105,111,110,113,0,126,0,
+ 6,76,0,4,110,97,109,101,113,0,
+ 126,0,6,120,112,116,0,5,100,101,
+ 115,99,114,116,0,7,100,97,116,101,
+ 80,97,114,116,0,14,106,97,118,97,
+ 46,117,116,105,108,46,68,97,116,101,
+ 115,114,0,14,106,97,118,97,46,117,
+ 116,105,108,46,68,97,116,101,104,106,
+ -127,1,75,89,116,25,3,0,0,120,
+ 112,119,8,0,0,1,8,16,-111,109,
+ 114,120,115,114,0,37,106,97,118,97,
+ 46,117,116,105,108,46,67,111,108,108,
+ 101,99,116,105,111,110,115,36,85,110,
+ 109,111,100,105,102,105,97,98,108,101,
+ 83,101,116,-128,29,-110,-47,-113,-101,-128,
+ 85,2,0,0,120,114,0,44,106,97,
+ 118,97,46,117,116,105,108,46,67,111,
+ 108,108,101,99,116,105,111,110,115,36,
+ 85,110,109,111,100,105,102,105,97,98,
+ 108,101,67,111,108,108,101,99,116,105,
+ 111,110,25,66,0,-128,-53,94,-9,30,
+ 2,0,1,76,0,1,99,116,0,22,
+ 76,106,97,118,97,47,117,116,105,108,
+ 47,67,111,108,108,101,99,116,105,111,
+ 110,59,120,112,115,114,0,17,106,97,
+ 118,97,46,117,116,105,108,46,72,97,
+ 115,104,83,101,116,-70,68,-123,-107,-106,
+ -72,-73,52,3,0,0,120,112,119,12,
+ 0,0,0,4,63,-128,0,0,0,0,
+ 0,2,115,113,0,126,0,12,119,8,
+ 0,0,1,8,11,107,17,114,120,113,
+ 0,126,0,13,120,112,112,115,114,0,
+ 37,106,97,118,97,120,46,109,97,110,
+ 97,103,101,109,101,110,116,46,111,112,
+ 101,110,109,98,101,97,110,46,83,105,
+ 109,112,108,101,84,121,112,101,30,-65,
+ 79,-8,-36,101,120,39,2,0,0,120,
+ 114,0,35,106,97,118,97,120,46,109,
+ 97,110,97,103,101,109,101,110,116,46,
+ 111,112,101,110,109,98,101,97,110,46,
+ 79,112,101,110,84,121,112,101,-128,100,
+ 26,-111,-23,-22,-34,60,2,0,3,76,
+ 0,9,99,108,97,115,115,78,97,109,
+ 101,113,0,126,0,6,76,0,11,100,
+ 101,115,99,114,105,112,116,105,111,110,
+ 113,0,126,0,6,76,0,8,116,121,
+ 112,101,78,97,109,101,113,0,126,0,
+ 6,120,112,113,0,126,0,11,113,0,
+ 126,0,11,113,0,126,0,11
+ };
+ map.put("datePar",bytes);
+ }
+ // dateAttr: javax.management.openmbean.OpenMBeanAttributeInfoSupport
+ //
+ {
+ final byte[] bytes = new byte[] {
+ -84,-19,0,5,115,114,0,56,106,97,
+ 118,97,120,46,109,97,110,97,103,101,
+ 109,101,110,116,46,111,112,101,110,109,
+ 98,101,97,110,46,79,112,101,110,77,
+ 66,101,97,110,65,116,116,114,105,98,
+ 117,116,101,73,110,102,111,83,117,112,
+ 112,111,114,116,-68,116,45,45,-28,-120,
+ -79,7,2,0,5,76,0,12,100,101,
+ 102,97,117,108,116,86,97,108,117,101,
+ 116,0,18,76,106,97,118,97,47,108,
+ 97,110,103,47,79,98,106,101,99,116,
+ 59,76,0,11,108,101,103,97,108,86,
+ 97,108,117,101,115,116,0,15,76,106,
+ 97,118,97,47,117,116,105,108,47,83,
+ 101,116,59,76,0,8,109,97,120,86,
+ 97,108,117,101,116,0,22,76,106,97,
+ 118,97,47,108,97,110,103,47,67,111,
+ 109,112,97,114,97,98,108,101,59,76,
+ 0,8,109,105,110,86,97,108,117,101,
+ 113,0,126,0,3,76,0,8,111,112,
+ 101,110,84,121,112,101,116,0,37,76,
+ 106,97,118,97,120,47,109,97,110,97,
+ 103,101,109,101,110,116,47,111,112,101,
+ 110,109,98,101,97,110,47,79,112,101,
+ 110,84,121,112,101,59,120,114,0,35,
+ 106,97,118,97,120,46,109,97,110,97,
+ 103,101,109,101,110,116,46,77,66,101,
+ 97,110,65,116,116,114,105,98,117,116,
+ 101,73,110,102,111,119,-8,41,59,106,
+ 41,68,-40,2,0,4,90,0,2,105,
+ 115,90,0,6,105,115,82,101,97,100,
+ 90,0,7,105,115,87,114,105,116,101,
+ 76,0,13,97,116,116,114,105,98,117,
+ 116,101,84,121,112,101,116,0,18,76,
+ 106,97,118,97,47,108,97,110,103,47,
+ 83,116,114,105,110,103,59,120,114,0,
+ 33,106,97,118,97,120,46,109,97,110,
+ 97,103,101,109,101,110,116,46,77,66,
+ 101,97,110,70,101,97,116,117,114,101,
+ 73,110,102,111,54,-37,117,-36,-62,-63,
+ 85,33,2,0,2,76,0,11,100,101,
+ 115,99,114,105,112,116,105,111,110,113,
+ 0,126,0,6,76,0,4,110,97,109,
+ 101,113,0,126,0,6,120,112,116,0,
+ 5,100,101,115,99,114,116,0,8,100,
+ 97,116,101,65,116,116,114,0,1,0,
+ 116,0,14,106,97,118,97,46,117,116,
+ 105,108,46,68,97,116,101,115,114,0,
+ 14,106,97,118,97,46,117,116,105,108,
+ 46,68,97,116,101,104,106,-127,1,75,
+ 89,116,25,3,0,0,120,112,119,8,
+ 0,0,1,8,16,-111,109,114,120,115,
+ 114,0,37,106,97,118,97,46,117,116,
+ 105,108,46,67,111,108,108,101,99,116,
+ 105,111,110,115,36,85,110,109,111,100,
+ 105,102,105,97,98,108,101,83,101,116,
+ -128,29,-110,-47,-113,-101,-128,85,2,0,
+ 0,120,114,0,44,106,97,118,97,46,
+ 117,116,105,108,46,67,111,108,108,101,
+ 99,116,105,111,110,115,36,85,110,109,
+ 111,100,105,102,105,97,98,108,101,67,
+ 111,108,108,101,99,116,105,111,110,25,
+ 66,0,-128,-53,94,-9,30,2,0,1,
+ 76,0,1,99,116,0,22,76,106,97,
+ 118,97,47,117,116,105,108,47,67,111,
+ 108,108,101,99,116,105,111,110,59,120,
+ 112,115,114,0,17,106,97,118,97,46,
+ 117,116,105,108,46,72,97,115,104,83,
+ 101,116,-70,68,-123,-107,-106,-72,-73,52,
+ 3,0,0,120,112,119,12,0,0,0,
+ 4,63,-128,0,0,0,0,0,2,115,
+ 113,0,126,0,12,119,8,0,0,1,
+ 8,11,107,17,114,120,113,0,126,0,
+ 13,120,112,112,115,114,0,37,106,97,
+ 118,97,120,46,109,97,110,97,103,101,
+ 109,101,110,116,46,111,112,101,110,109,
+ 98,101,97,110,46,83,105,109,112,108,
+ 101,84,121,112,101,30,-65,79,-8,-36,
+ 101,120,39,2,0,0,120,114,0,35,
+ 106,97,118,97,120,46,109,97,110,97,
+ 103,101,109,101,110,116,46,111,112,101,
+ 110,109,98,101,97,110,46,79,112,101,
+ 110,84,121,112,101,-128,100,26,-111,-23,
+ -22,-34,60,2,0,3,76,0,9,99,
+ 108,97,115,115,78,97,109,101,113,0,
+ 126,0,6,76,0,11,100,101,115,99,
+ 114,105,112,116,105,111,110,113,0,126,
+ 0,6,76,0,8,116,121,112,101,78,
+ 97,109,101,113,0,126,0,6,120,112,
+ 113,0,126,0,11,113,0,126,0,11,
+ 113,0,126,0,11
+ };
+ map.put("dateAttr",bytes);
+ }
+ // stringPar: javax.management.openmbean.OpenMBeanParameterInfoSupport
+ //
+ {
+ final byte[] bytes = new byte[] {
+ -84,-19,0,5,115,114,0,56,106,97,
+ 118,97,120,46,109,97,110,97,103,101,
+ 109,101,110,116,46,111,112,101,110,109,
+ 98,101,97,110,46,79,112,101,110,77,
+ 66,101,97,110,80,97,114,97,109,101,
+ 116,101,114,73,110,102,111,83,117,112,
+ 112,111,114,116,-101,-104,14,124,111,-85,
+ -71,-114,2,0,5,76,0,12,100,101,
+ 102,97,117,108,116,86,97,108,117,101,
+ 116,0,18,76,106,97,118,97,47,108,
+ 97,110,103,47,79,98,106,101,99,116,
+ 59,76,0,11,108,101,103,97,108,86,
+ 97,108,117,101,115,116,0,15,76,106,
+ 97,118,97,47,117,116,105,108,47,83,
+ 101,116,59,76,0,8,109,97,120,86,
+ 97,108,117,101,116,0,22,76,106,97,
+ 118,97,47,108,97,110,103,47,67,111,
+ 109,112,97,114,97,98,108,101,59,76,
+ 0,8,109,105,110,86,97,108,117,101,
+ 113,0,126,0,3,76,0,8,111,112,
+ 101,110,84,121,112,101,116,0,37,76,
+ 106,97,118,97,120,47,109,97,110,97,
+ 103,101,109,101,110,116,47,111,112,101,
+ 110,109,98,101,97,110,47,79,112,101,
+ 110,84,121,112,101,59,120,114,0,35,
+ 106,97,118,97,120,46,109,97,110,97,
+ 103,101,109,101,110,116,46,77,66,101,
+ 97,110,80,97,114,97,109,101,116,101,
+ 114,73,110,102,111,103,37,-11,-84,-39,
+ 123,54,2,2,0,1,76,0,4,116,
+ 121,112,101,116,0,18,76,106,97,118,
+ 97,47,108,97,110,103,47,83,116,114,
+ 105,110,103,59,120,114,0,33,106,97,
+ 118,97,120,46,109,97,110,97,103,101,
+ 109,101,110,116,46,77,66,101,97,110,
+ 70,101,97,116,117,114,101,73,110,102,
+ 111,54,-37,117,-36,-62,-63,85,33,2,
+ 0,2,76,0,11,100,101,115,99,114,
+ 105,112,116,105,111,110,113,0,126,0,
+ 6,76,0,4,110,97,109,101,113,0,
+ 126,0,6,120,112,116,0,5,100,101,
+ 115,99,114,116,0,9,115,116,114,105,
+ 110,103,80,97,114,116,0,16,106,97,
+ 118,97,46,108,97,110,103,46,83,116,
+ 114,105,110,103,112,112,112,112,115,114,
+ 0,37,106,97,118,97,120,46,109,97,
+ 110,97,103,101,109,101,110,116,46,111,
+ 112,101,110,109,98,101,97,110,46,83,
+ 105,109,112,108,101,84,121,112,101,30,
+ -65,79,-8,-36,101,120,39,2,0,0,
+ 120,114,0,35,106,97,118,97,120,46,
+ 109,97,110,97,103,101,109,101,110,116,
+ 46,111,112,101,110,109,98,101,97,110,
+ 46,79,112,101,110,84,121,112,101,-128,
+ 100,26,-111,-23,-22,-34,60,2,0,3,
+ 76,0,9,99,108,97,115,115,78,97,
+ 109,101,113,0,126,0,6,76,0,11,
+ 100,101,115,99,114,105,112,116,105,111,
+ 110,113,0,126,0,6,76,0,8,116,
+ 121,112,101,78,97,109,101,113,0,126,
+ 0,6,120,112,113,0,126,0,11,113,
+ 0,126,0,11,113,0,126,0,11
+ };
+ map.put("stringPar",bytes);
+ }
+ // boolAttr: javax.management.openmbean.OpenMBeanAttributeInfoSupport
+ //
+ {
+ final byte[] bytes = new byte[] {
+ -84,-19,0,5,115,114,0,56,106,97,
+ 118,97,120,46,109,97,110,97,103,101,
+ 109,101,110,116,46,111,112,101,110,109,
+ 98,101,97,110,46,79,112,101,110,77,
+ 66,101,97,110,65,116,116,114,105,98,
+ 117,116,101,73,110,102,111,83,117,112,
+ 112,111,114,116,-68,116,45,45,-28,-120,
+ -79,7,2,0,5,76,0,12,100,101,
+ 102,97,117,108,116,86,97,108,117,101,
+ 116,0,18,76,106,97,118,97,47,108,
+ 97,110,103,47,79,98,106,101,99,116,
+ 59,76,0,11,108,101,103,97,108,86,
+ 97,108,117,101,115,116,0,15,76,106,
+ 97,118,97,47,117,116,105,108,47,83,
+ 101,116,59,76,0,8,109,97,120,86,
+ 97,108,117,101,116,0,22,76,106,97,
+ 118,97,47,108,97,110,103,47,67,111,
+ 109,112,97,114,97,98,108,101,59,76,
+ 0,8,109,105,110,86,97,108,117,101,
+ 113,0,126,0,3,76,0,8,111,112,
+ 101,110,84,121,112,101,116,0,37,76,
+ 106,97,118,97,120,47,109,97,110,97,
+ 103,101,109,101,110,116,47,111,112,101,
+ 110,109,98,101,97,110,47,79,112,101,
+ 110,84,121,112,101,59,120,114,0,35,
+ 106,97,118,97,120,46,109,97,110,97,
+ 103,101,109,101,110,116,46,77,66,101,
+ 97,110,65,116,116,114,105,98,117,116,
+ 101,73,110,102,111,119,-8,41,59,106,
+ 41,68,-40,2,0,4,90,0,2,105,
+ 115,90,0,6,105,115,82,101,97,100,
+ 90,0,7,105,115,87,114,105,116,101,
+ 76,0,13,97,116,116,114,105,98,117,
+ 116,101,84,121,112,101,116,0,18,76,
+ 106,97,118,97,47,108,97,110,103,47,
+ 83,116,114,105,110,103,59,120,114,0,
+ 33,106,97,118,97,120,46,109,97,110,
+ 97,103,101,109,101,110,116,46,77,66,
+ 101,97,110,70,101,97,116,117,114,101,
+ 73,110,102,111,54,-37,117,-36,-62,-63,
+ 85,33,2,0,2,76,0,11,100,101,
+ 115,99,114,105,112,116,105,111,110,113,
+ 0,126,0,6,76,0,4,110,97,109,
+ 101,113,0,126,0,6,120,112,116,0,
+ 5,100,101,115,99,114,116,0,8,98,
+ 111,111,108,65,116,116,114,0,1,0,
+ 116,0,17,106,97,118,97,46,108,97,
+ 110,103,46,66,111,111,108,101,97,110,
+ 115,114,0,17,106,97,118,97,46,108,
+ 97,110,103,46,66,111,111,108,101,97,
+ 110,-51,32,114,-128,-43,-100,-6,-18,2,
+ 0,1,90,0,5,118,97,108,117,101,
+ 120,112,1,112,112,112,115,114,0,37,
+ 106,97,118,97,120,46,109,97,110,97,
+ 103,101,109,101,110,116,46,111,112,101,
+ 110,109,98,101,97,110,46,83,105,109,
+ 112,108,101,84,121,112,101,30,-65,79,
+ -8,-36,101,120,39,2,0,0,120,114,
+ 0,35,106,97,118,97,120,46,109,97,
+ 110,97,103,101,109,101,110,116,46,111,
+ 112,101,110,109,98,101,97,110,46,79,
+ 112,101,110,84,121,112,101,-128,100,26,
+ -111,-23,-22,-34,60,2,0,3,76,0,
+ 9,99,108,97,115,115,78,97,109,101,
+ 113,0,126,0,6,76,0,11,100,101,
+ 115,99,114,105,112,116,105,111,110,113,
+ 0,126,0,6,76,0,8,116,121,112,
+ 101,78,97,109,101,113,0,126,0,6,
+ 120,112,113,0,126,0,11,113,0,126,
+ 0,11,113,0,126,0,11
+ };
+ map.put("boolAttr",bytes);
+ }
+ // floatPar: javax.management.openmbean.OpenMBeanParameterInfoSupport
+ //
+ {
+ final byte[] bytes = new byte[] {
+ -84,-19,0,5,115,114,0,56,106,97,
+ 118,97,120,46,109,97,110,97,103,101,
+ 109,101,110,116,46,111,112,101,110,109,
+ 98,101,97,110,46,79,112,101,110,77,
+ 66,101,97,110,80,97,114,97,109,101,
+ 116,101,114,73,110,102,111,83,117,112,
+ 112,111,114,116,-101,-104,14,124,111,-85,
+ -71,-114,2,0,5,76,0,12,100,101,
+ 102,97,117,108,116,86,97,108,117,101,
+ 116,0,18,76,106,97,118,97,47,108,
+ 97,110,103,47,79,98,106,101,99,116,
+ 59,76,0,11,108,101,103,97,108,86,
+ 97,108,117,101,115,116,0,15,76,106,
+ 97,118,97,47,117,116,105,108,47,83,
+ 101,116,59,76,0,8,109,97,120,86,
+ 97,108,117,101,116,0,22,76,106,97,
+ 118,97,47,108,97,110,103,47,67,111,
+ 109,112,97,114,97,98,108,101,59,76,
+ 0,8,109,105,110,86,97,108,117,101,
+ 113,0,126,0,3,76,0,8,111,112,
+ 101,110,84,121,112,101,116,0,37,76,
+ 106,97,118,97,120,47,109,97,110,97,
+ 103,101,109,101,110,116,47,111,112,101,
+ 110,109,98,101,97,110,47,79,112,101,
+ 110,84,121,112,101,59,120,114,0,35,
+ 106,97,118,97,120,46,109,97,110,97,
+ 103,101,109,101,110,116,46,77,66,101,
+ 97,110,80,97,114,97,109,101,116,101,
+ 114,73,110,102,111,103,37,-11,-84,-39,
+ 123,54,2,2,0,1,76,0,4,116,
+ 121,112,101,116,0,18,76,106,97,118,
+ 97,47,108,97,110,103,47,83,116,114,
+ 105,110,103,59,120,114,0,33,106,97,
+ 118,97,120,46,109,97,110,97,103,101,
+ 109,101,110,116,46,77,66,101,97,110,
+ 70,101,97,116,117,114,101,73,110,102,
+ 111,54,-37,117,-36,-62,-63,85,33,2,
+ 0,2,76,0,11,100,101,115,99,114,
+ 105,112,116,105,111,110,113,0,126,0,
+ 6,76,0,4,110,97,109,101,113,0,
+ 126,0,6,120,112,116,0,5,100,101,
+ 115,99,114,116,0,8,102,108,111,97,
+ 116,80,97,114,116,0,15,106,97,118,
+ 97,46,108,97,110,103,46,70,108,111,
+ 97,116,115,114,0,15,106,97,118,97,
+ 46,108,97,110,103,46,70,108,111,97,
+ 116,-38,-19,-55,-94,-37,60,-16,-20,2,
+ 0,1,70,0,5,118,97,108,117,101,
+ 120,114,0,16,106,97,118,97,46,108,
+ 97,110,103,46,78,117,109,98,101,114,
+ -122,-84,-107,29,11,-108,-32,-117,2,0,
+ 0,120,112,63,-128,0,0,112,115,113,
+ 0,126,0,12,64,0,0,0,115,113,
+ 0,126,0,12,0,0,0,0,115,114,
+ 0,37,106,97,118,97,120,46,109,97,
+ 110,97,103,101,109,101,110,116,46,111,
+ 112,101,110,109,98,101,97,110,46,83,
+ 105,109,112,108,101,84,121,112,101,30,
+ -65,79,-8,-36,101,120,39,2,0,0,
+ 120,114,0,35,106,97,118,97,120,46,
+ 109,97,110,97,103,101,109,101,110,116,
+ 46,111,112,101,110,109,98,101,97,110,
+ 46,79,112,101,110,84,121,112,101,-128,
+ 100,26,-111,-23,-22,-34,60,2,0,3,
+ 76,0,9,99,108,97,115,115,78,97,
+ 109,101,113,0,126,0,6,76,0,11,
+ 100,101,115,99,114,105,112,116,105,111,
+ 110,113,0,126,0,6,76,0,8,116,
+ 121,112,101,78,97,109,101,113,0,126,
+ 0,6,120,112,113,0,126,0,11,113,
+ 0,126,0,11,113,0,126,0,11
+ };
+ map.put("floatPar",bytes);
+ }
+
+ }
+
+ /**
+ * Deserialize a byte array into an object.
+ * @param bytes The bytes to deserialize.
+ * @return The deserialized object.
+ * @throws IOException if the object cannot be deserialized.
+ * @throws ClassNotFoundException if the class of the serialized object
+ * cannot be loaded.
+ **/
+ public static Object deserialize(byte[] bytes) throws IOException,
+ ClassNotFoundException {
+ final ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
+ final ObjectInputStream istr = new ObjectInputStream(bin);
+ return istr.readObject();
+ }
+
+ /**
+ * The set of keys for objects registered in this serialized data store.
+ * For each of these keys we have a serialized object of type
+ * MBeanFeatureInfo.
+ * @return The set of keys corresponding to registered objects.
+ **/
+ public static Set<String> keySet() {
+ return map.keySet();
+ }
+
+ /**
+ * Retrieves and deserializes the object stored at the given key.
+ * @return The deserialized object.
+ * @throws IOException if the object cannot be deserialized.
+ * @throws ClassNotFoundException if the class of the serialized object
+ * cannot be loaded.
+ **/
+ public static MBeanFeatureInfo get(String name)
+ throws IOException, ClassNotFoundException {
+ final byte[] bytes = map.get(name);
+ final Object obj = deserialize(bytes);
+ return (MBeanFeatureInfo)obj;
+ }
+
+ /**
+ * Version of the JVM that was used to generate the serialized data.
+ **/
+ public static final String SERIALIZER_VM_VERSION =
+ "1.5.0_05";
+
+ /**
+ * Vendor of the JVM that was used to generate the serialized data.
+ **/
+ public static final String SERIALIZER_VM_VENDOR=
+ "Sun Microsystems Inc.";
+
+}
diff --git a/test/javax/management/openmbean/NullConstructorParamsTest.java b/test/javax/management/openmbean/NullConstructorParamsTest.java
new file mode 100644
index 0000000..527c50f
--- /dev/null
+++ b/test/javax/management/openmbean/NullConstructorParamsTest.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6434298
+ * @summary Test IAE is thrown when typeName or description parameter is null for TabularType and CompositeType constructors
+ * @author Joel FERAUD
+ */
+
+import javax.management.openmbean.*;
+
+public class NullConstructorParamsTest {
+
+ /**
+ * Print message
+ */
+ private static void echo(String message) {
+ System.out.println(message);
+ }
+
+ /**
+ * Main
+ */
+ public static void main(String[] args) throws Exception {
+
+ echo("SUMMARY: Test IAE is thrown when typeName or description parameter is null " +
+ "for TabularType and CompositeType constructors");
+
+ echo(">>> Create CompositeType with non null params: should be ok");
+ CompositeType ctok =
+ new CompositeType(
+ "typeNameOK",
+ "for test",
+ new String[] {"a", "b"},
+ new String[] {"a_desc", "b_desc"},
+ new OpenType[] {SimpleType.BOOLEAN,SimpleType.STRING});
+ echo("+++ CompositeType created ok");
+ echo("");
+
+ echo(">>> Create TabularType with non null params: should be ok");
+ TabularType tabok =
+ new TabularType(
+ "typeNameOK",
+ "for test",
+ ctok,
+ new String[] {"a"});
+ echo("+++ TabularType created ok");
+ echo("");
+
+
+ int IAENotThrown = 0;
+
+ try {
+ echo(">>> Create CompositeType with null typeName: expect IAE");
+ CompositeType ctnull1 =
+ new CompositeType(
+ null,
+ "for test",
+ new String[] {"a", "b"},
+ new String[] {"a_desc", "b_desc"},
+ new OpenType[] {SimpleType.BOOLEAN, SimpleType.STRING});
+ IAENotThrown++;
+ echo("*** IAE not thrown as expected ***");
+ echo("*** Test will FAIL ***");
+ echo("");
+ } catch (IllegalArgumentException iae) {
+ echo("+++ IAE thrown as expected");
+ echo("");
+ } catch (Exception e) {
+ IAENotThrown++;
+ echo("*** Did not get IAE as expected, but instead: ");
+ e.printStackTrace();
+ echo("*** Test will FAIL ***");
+ echo("");
+ }
+
+ try {
+ echo(">>> Create TabularType with null typeName: expect IAE");
+ TabularType tabnull1 =
+ new TabularType(
+ null,
+ "for test",
+ ctok,
+ new String[] {"a"});
+ IAENotThrown++;
+ echo("*** IAE not thrown as expected ***");
+ echo("*** Test will FAIL ***");
+ echo("");
+ } catch (IllegalArgumentException iae) {
+ echo("+++ IAE thrown as expected");
+ echo("");
+ } catch (Exception e) {
+ IAENotThrown++;
+ echo("*** Did not get IAE as expected, but instead: ");
+ e.printStackTrace();
+ echo("*** Test will FAIL ***");
+ echo("");
+ }
+
+ try {
+ echo(">>> Create CompositeType with null description: expect IAE");
+ CompositeType ctnull2 =
+ new CompositeType(
+ "test",
+ null,
+ new String[] {"a", "b"},
+ new String[] {"a_desc", "b_desc"},
+ new OpenType[] {SimpleType.BOOLEAN, SimpleType.STRING});
+ IAENotThrown++;
+ echo("*** IAE not thrown as expected ***");
+ echo("*** Test will FAIL ***");
+ echo("");
+ } catch (IllegalArgumentException iae) {
+ echo("+++ IAE thrown as expected");
+ echo("");
+ } catch (Exception e) {
+ IAENotThrown++;
+ echo("*** Did not get IAE as expected, but instead: ");
+ e.printStackTrace();
+ echo("*** Test will FAIL ***");
+ echo("");
+ }
+
+ try {
+ echo(">>> Create TabularType with null description: expect IAE");
+ TabularType tabnull2 =
+ new TabularType(
+ "test",
+ null,
+ ctok,
+ new String[] {"a"});
+ IAENotThrown++;
+ echo("*** IAE not thrown as expected ***");
+ echo("*** Test will FAIL ***");
+ echo("");
+ } catch (IllegalArgumentException iae) {
+ echo("+++ IAE thrown as expected");
+ echo("");
+ } catch (Exception e) {
+ IAENotThrown++;
+ echo("*** Did not get IAE as expected, but instead: ");
+ e.printStackTrace();
+ echo("*** Test will FAIL ***");
+ echo("");
+ }
+
+ if (IAENotThrown != 0 ) {
+ echo("*** Test FAILED: IAE not thrown as expected ***");
+ echo("");
+ throw new RuntimeException("IAE not thrown as expected");
+ }
+ echo("+++ Test PASSED");
+ echo("");
+
+ }
+}
diff --git a/test/javax/management/openmbean/OpenTypeDescriptorTest.java b/test/javax/management/openmbean/OpenTypeDescriptorTest.java
new file mode 100644
index 0000000..507ecff
--- /dev/null
+++ b/test/javax/management/openmbean/OpenTypeDescriptorTest.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6254721
+ * @bug 6360539
+ * @summary Test that Open*MBeanInfo classes include "openType" in descriptor
+ * and also test serial compatibility with Java 5.
+ * @author Eamonn McManus
+ * @run clean OpenTypeDescriptorTest
+ * @run build OpenTypeDescriptorTest
+ * @run main OpenTypeDescriptorTest
+ */
+
+import java.util.Date;
+import javax.management.*;
+import javax.management.openmbean.*;
+import static javax.management.MBeanOperationInfo.ACTION;
+
+public class OpenTypeDescriptorTest {
+ public static void main(String[] args) throws Exception {
+ Descriptor constraints =
+ new ImmutableDescriptor("defaultValue=25",
+ "minValue=3");
+ Date now = new Date();
+ Date then = new Date(System.currentTimeMillis() - 86400000);
+ final DescriptorRead[] testObjects = {
+ new OpenMBeanAttributeInfoSupport("name", "descr",
+ SimpleType.STRING,
+ true, false, false),
+ new OpenMBeanAttributeInfoSupport("name", "descr",
+ SimpleType.INTEGER,
+ false, true, false, constraints),
+ new OpenMBeanAttributeInfoSupport("name", "descr",
+ SimpleType.BOOLEAN,
+ true, false, false, true),
+ new OpenMBeanAttributeInfoSupport("name", "descr",
+ SimpleType.FLOAT,
+ true, true, false,
+ 1.0f, 0.0f, 2.0f),
+ new OpenMBeanAttributeInfoSupport("name", "descr",
+ SimpleType.DATE,
+ true, false, false,
+ now, new Date[] {now, then}),
+ new OpenMBeanParameterInfoSupport("name", "descr",
+ SimpleType.STRING),
+ new OpenMBeanParameterInfoSupport("name", "descr",
+ SimpleType.INTEGER, constraints),
+ new OpenMBeanParameterInfoSupport("name", "descr",
+ SimpleType.BOOLEAN, true),
+ new OpenMBeanParameterInfoSupport("name", "descr",
+ SimpleType.FLOAT,
+ 1.0f, 0.0f, 2.0f),
+ new OpenMBeanParameterInfoSupport("name", "descr",
+ SimpleType.DATE,
+ now, new Date[] {now, then}),
+ new OpenMBeanOperationInfoSupport("name", "descr", null,
+ ArrayType.getPrimitiveArrayType(
+ int[][].class),
+ ACTION),
+ new OpenMBeanOperationInfoSupport("name", "descr", null,
+ ArrayType.getArrayType(
+ SimpleType.INTEGER),
+ ACTION, constraints),
+ };
+
+ for (DescriptorRead x : testObjects) {
+ OpenType descriptorType = (OpenType)
+ x.getDescriptor().getFieldValue("openType");
+ OpenType openType;
+ if (x instanceof OpenMBeanParameterInfo)
+ openType = ((OpenMBeanParameterInfo) x).getOpenType();
+ else if (x instanceof OpenMBeanOperationInfo)
+ openType = ((OpenMBeanOperationInfo) x).getReturnOpenType();
+ else
+ throw new Exception("Can't get OpenType for " + x.getClass());
+ if (openType.equals(descriptorType))
+ System.out.println("OK: " + x);
+ else {
+ failure("OpenType is " + openType + ", descriptor says " +
+ descriptorType + " for " + x);
+ }
+ }
+
+ // Serial compatibility test:
+ //
+ System.out.println("Testing serial compatibility with Java "+
+ MBeanFeatureInfoSerialStore.SERIALIZER_VM_VERSION+
+ " "+
+ MBeanFeatureInfoSerialStore.SERIALIZER_VM_VENDOR);
+
+ for (String key : MBeanFeatureInfoSerialStore.keySet() ) {
+ MBeanFeatureInfo f = MBeanFeatureInfoSerialStore.get(key);
+ DescriptorRead x = (DescriptorRead)f;
+ OpenType descriptorType = (OpenType)
+ x.getDescriptor().getFieldValue("openType");
+ OpenType openType;
+ if (x instanceof OpenMBeanParameterInfo)
+ openType = ((OpenMBeanParameterInfo) x).getOpenType();
+ else if (x instanceof OpenMBeanOperationInfo)
+ openType = ((OpenMBeanOperationInfo) x).getReturnOpenType();
+ else
+ throw new Exception("Can't get OpenType for " + key +": "+
+ x.getClass());
+ if (openType.equals(descriptorType))
+ System.out.println("OK "+key+": " + x);
+ else {
+ failure("OpenType for "+key+" is " + openType +
+ ", descriptor says " +
+ descriptorType + " for " + x);
+ }
+
+ }
+
+ // Test that we get an exception if "openType" in Descriptor
+ // doesn't agree with OpenType parameter
+ Descriptor d =
+ new ImmutableDescriptor(new String[] {"openType"},
+ new Object[] {SimpleType.STRING});
+ for (Type t : Type.values()) {
+ try {
+ switch (t) {
+ case ATTR:
+ new OpenMBeanAttributeInfoSupport("name", "descr",
+ SimpleType.INTEGER,
+ true, true, false, d);
+ break;
+ case PARAM:
+ new OpenMBeanParameterInfoSupport("name", "descr",
+ SimpleType.INTEGER, d);
+ break;
+ case OPER:
+ new OpenMBeanOperationInfoSupport("name", "descr", null,
+ SimpleType.INTEGER,
+ ACTION, d);
+ break;
+ }
+ failure("did not get expected exception for " + t);
+ } catch (IllegalArgumentException e) {
+ System.out.println("OK: got expected exception for " + t);
+ } catch (Exception e) {
+ failure("wrong exception for " + t + ": " + e);
+ }
+ }
+
+ if (failed != null)
+ throw new Exception(failed);
+ System.out.println("Test passed");
+ }
+
+ private static enum Type {ATTR, PARAM, OPER}
+
+ private static void failure(String what) {
+ System.out.println("FAILED: what");
+ failed = what;
+ }
+
+ private static String failed;
+}
diff --git a/test/javax/management/proxy/NotificationEmitterProxy.java b/test/javax/management/proxy/NotificationEmitterProxy.java
new file mode 100644
index 0000000..75f7944
--- /dev/null
+++ b/test/javax/management/proxy/NotificationEmitterProxy.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @summary Test that we can create proxies which are NotificationEmitters.
+ * @bug 6411747
+ * @author Daniel Fuchs
+ * @run clean NotificationEmitterProxy
+ * @run build NotificationEmitterProxy
+ * @run main NotificationEmitterProxy
+ */
+
+import java.lang.management.ManagementFactory;
+
+import javax.management.*;
+import javax.management.remote.*;
+import javax.naming.NoPermissionException;
+
+public class NotificationEmitterProxy {
+
+ public static class Counter {
+ int count;
+ public synchronized int count() {
+ count++;
+ notifyAll();
+ return count;
+ }
+ public synchronized int peek() {
+ return count;
+ }
+ public synchronized int waitfor(int max, long timeout)
+ throws InterruptedException {
+ final long start = System.currentTimeMillis();
+ while (count < max && timeout > 0) {
+ final long rest = timeout -
+ (System.currentTimeMillis() - start);
+ if (rest <= 0) break;
+ wait(rest);
+ }
+ return count;
+ }
+ }
+
+ public static class CounterListener
+ implements NotificationListener {
+ final private Counter counter;
+ public CounterListener(Counter counter) {
+ this.counter = counter;
+ }
+ public void handleNotification(Notification notification,
+ Object handback) {
+ System.out.println("Received notif from " + handback +
+ ":\n\t" + notification);
+ counter.count();
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("<<< Register for notification from a proxy");
+
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ final ObjectName name = new ObjectName(":class=Simple");
+
+ JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
+ final JMXConnectorServer server =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
+ server.start();
+ url = server.getAddress();
+
+ final JMXConnector client = JMXConnectorFactory.connect(url);
+
+ final Counter counter = new Counter();
+ final CounterListener listener = new CounterListener(counter);
+ final Counter mxcounter = new Counter();
+ final CounterListener mxlistener = new CounterListener(mxcounter);
+ final NotificationFilterSupport filter =
+ new NotificationFilterSupport();
+ filter.enableType(MBeanServerNotification.REGISTRATION_NOTIFICATION);
+ filter.enableType(MBeanServerNotification.UNREGISTRATION_NOTIFICATION);
+ int registered = 0;
+ try {
+ final MBeanServerDelegateMBean delegate =
+ JMX.newMBeanProxy(client.getMBeanServerConnection(),
+ MBeanServerDelegate.DELEGATE_NAME,
+ MBeanServerDelegateMBean.class,
+ true);
+
+ NotificationEmitter emitter = (NotificationEmitter)delegate;
+ emitter.addNotificationListener(listener,filter,"JMX.newMBeanProxy");
+ } catch (Exception x) {
+ throw new RuntimeException("Failed to register listener with "+
+ " JMX.newMBeanProxy: " + x, x);
+ }
+
+ try {
+ final MBeanServerDelegateMBean delegate =
+ MBeanServerInvocationHandler.newProxyInstance(mbs,
+ MBeanServerDelegate.DELEGATE_NAME,
+ MBeanServerDelegateMBean.class,
+ true);
+
+ NotificationEmitter emitter = (NotificationEmitter)delegate;
+ emitter.addNotificationListener(listener,filter,
+ "MBeanServerInvocationHandler.newProxyInstance");
+ } catch (Exception x) {
+ throw new RuntimeException("Failed to register listener with "+
+ " MBeanServerInvocationHandler.newProxyInstance: " + x, x);
+ }
+
+ System.out.println("<<< Register an MBean.");
+
+ final Simple simple = new Simple();
+ mbs.registerMBean(simple, name);
+ registered++;
+
+ SimpleMXBean simple0 =
+ JMX.newMXBeanProxy(client.getMBeanServerConnection(),
+ name,
+ SimpleMXBean.class,
+ true);
+
+ SimpleMXBean simple1 =
+ JMX.newMXBeanProxy(mbs,
+ name,
+ SimpleMXBean.class,
+ false);
+
+ final int expected = 2*registered;
+ final int reg = counter.waitfor(expected,3000);
+ if (reg != expected)
+ throw new RuntimeException("Bad notification count: " + reg +
+ ", expected " +expected);
+ System.out.println("Received expected "+reg+
+ " notifs after registerMBean");
+
+ ((NotificationEmitter)simple0)
+ .addNotificationListener(mxlistener,null,name);
+ simple1.equals("Are you a Wombat?");
+ final int mxnotifs = mxcounter.waitfor(1,3000);
+ if (mxnotifs != 1)
+ throw new RuntimeException("Bad MXBean notification count: " +
+ mxnotifs);
+ System.out.println("Received expected "+mxnotifs+
+ " notifs from MXBean");
+
+ mbs.unregisterMBean(name);
+ final int unreg = counter.waitfor(expected+reg,3000);
+ if (unreg != (expected+reg))
+ throw new RuntimeException("Bad notification count: " + unreg +
+ ", expected " +expected+reg);
+ System.out.println("Received expected "+(unreg-reg)+
+ " notifs after unregisterMBean");
+ System.out.println("Total notifs received: " + unreg);
+
+
+ }
+
+ public static interface Simplest {
+
+ }
+
+ public static interface SimpleMXBean extends Simplest {
+ public String equals(String x);
+ }
+
+ private static class Simple extends NotificationBroadcasterSupport
+ implements SimpleMXBean {
+ public static final String NOTIF_TYPE = "simple.equals";
+ private static long seq=0;
+ private static synchronized long seq() { return ++seq; };
+ public String equals(String x) {
+ sendNotification(new Notification(NOTIF_TYPE,this,seq(),x));
+ return x;
+ }
+
+ }
+
+
+
+ }
diff --git a/test/javax/management/proxy/ProxyObjectMethodsTest.java b/test/javax/management/proxy/ProxyObjectMethodsTest.java
new file mode 100644
index 0000000..0b8a87d
--- /dev/null
+++ b/test/javax/management/proxy/ProxyObjectMethodsTest.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2004-2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6177524
+ * @summary Test how to execute the 3 Object methods by a Proxy.
+ * @author Shanliang JIANG
+ * @run clean ProxyObjectMethodsTest
+ * @run build ProxyObjectMethodsTest
+ * @run main ProxyObjectMethodsTest
+ */
+
+import java.lang.management.ManagementFactory;
+import java.lang.reflect.*;
+import java.util.*;
+
+import javax.management.*;
+import javax.management.remote.*;
+
+public class ProxyObjectMethodsTest {
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("<<< Test how to execute the 3 Object methods by a Proxy.");
+
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ final ObjectName name = new ObjectName(":class=Simple");
+
+ JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
+ final JMXConnectorServer server =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
+ server.start();
+ url = server.getAddress();
+
+ final JMXConnector client = JMXConnectorFactory.connect(url);
+
+ System.out.println("<<< Test the methods at local side.");
+
+ final Simple simple = new Simple();
+ mbs.registerMBean(simple, name);
+
+ SimpleMBean simple0 =
+ MBeanServerInvocationHandler.newProxyInstance(client.getMBeanServerConnection(),
+ name,
+ SimpleMBean.class,
+ false);
+
+ SimpleMBean simple1 =
+ MBeanServerInvocationHandler.newProxyInstance(client.getMBeanServerConnection(),
+ name,
+ SimpleMBean.class,
+ false);
+
+ Simplest simple3 =
+ MBeanServerInvocationHandler.newProxyInstance(client.getMBeanServerConnection(),
+ name,
+ Simplest.class,
+ false);
+
+ if (!simple0.equals(simple1) ||
+ simple0.equals(simple) ||
+ simple0.equals(simple3)) {
+ throw new RuntimeException("The method equals does not work correctly.");
+ }
+
+ if (simple0.hashCode() != simple1.hashCode() ||
+ simple.hashCode() == simple0.hashCode()) {
+ throw new RuntimeException("The method hashCode does not work correctly.");
+ }
+
+ if (!simple0.toString().equals(simple1.toString()) ||
+ simple.toString().equals(simple0.toString())) {
+ throw new RuntimeException("The method toString does not work correctly.");
+ }
+
+ /* Sorry about this. This is the equals(String) method,
+ which returns String, not boolean. */
+ if (!simple0.equals("foo").equals("foo"))
+ throw new RuntimeException("The method equals(String) was not forwarded.");
+
+ ArrayList al = new ArrayList();
+ al.add(simple0);
+
+ if (!al.contains(simple0) || !al.contains(simple1)) {
+ throw new RuntimeException("Cannot find correctly a proxy in an ArrayList.");
+ }
+
+ System.out.println("<<< Test whether the methods are done at server side.");
+
+ final ObjectName name1 = new ObjectName(":class=Test");
+ mbs.registerMBean(new Test(), name1);
+
+ TestMBean test0 = MBeanServerInvocationHandler.newProxyInstance(mbs,
+ name1,
+ TestMBean.class,
+ false);
+
+ if(test0.equals(test0)) {
+ throw new RuntimeException("The method equals is not done remotely as expected.");
+ }
+
+ if (!test0.toString().equals("Test-toString")) {
+ throw new RuntimeException("The method toString is not done remotely as expected.");
+ }
+
+ if (test0.hashCode() != 123) {
+ throw new RuntimeException("The method hashCode is not done remotely as expected.");
+ }
+
+ System.out.println("<<< Test on using a null connection or a null name.");
+ SimpleMBean simple2;
+ try {
+ simple2 = MBeanServerInvocationHandler.newProxyInstance(null,
+ name,
+ SimpleMBean.class,
+ false);
+ throw new RuntimeException(
+ "Null connection does not cause an IllegalArgumentException.");
+ } catch (IllegalArgumentException ie) {
+ // as expected
+ }
+
+ try {
+ simple2 = MBeanServerInvocationHandler.newProxyInstance(mbs,
+ null,
+ SimpleMBean.class,
+ false);
+ throw new RuntimeException(
+ "Null object name does not cause an IllegalArgumentException.");
+ } catch (IllegalArgumentException ie) {
+ // as expected
+ }
+ }
+
+ public static interface Simplest {
+
+ }
+
+ public static interface SimpleMBean extends Simplest {
+ public String equals(String x);
+ }
+
+ private static class Simple implements SimpleMBean {
+ public String equals(String x) {
+ return x;
+ }
+ }
+
+ public static interface TestMBean {
+ public boolean equals(Object o);
+
+ public String toString();
+
+ public int hashCode();
+ }
+
+ private static class Test implements TestMBean {
+ public boolean equals(Object o) {
+ // what can do here?
+
+ return false;
+ }
+
+ public String toString() {
+ return "Test-toString";
+ }
+
+ public int hashCode() {
+ return 123;
+ }
+ }
+}
diff --git a/test/javax/management/query/InstanceOfExpTest.java b/test/javax/management/query/InstanceOfExpTest.java
new file mode 100644
index 0000000..e1b2e1f
--- /dev/null
+++ b/test/javax/management/query/InstanceOfExpTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5072174 6335848
+ * @summary test the new method javax.management.Query.isInstanceOf("className")
+ * @author Shanliang JIANG
+ * @run clean InstanceOfExpTest
+ * @run build InstanceOfExpTest
+ * @run main InstanceOfExpTest
+ */
+
+import java.util.*;
+import java.lang.management.ManagementFactory;
+
+import javax.management.*;
+
+public class InstanceOfExpTest {
+
+ public static class Simple implements SimpleMBean {}
+ public static interface SimpleMBean {}
+
+ public static void main(String[] args) throws Exception {
+ System.out.println(">>> Test the method javax.management.Query.isInstanceOf");
+
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ final String className = "javax.management.NotificationBroadcaster";
+
+ final ObjectName name1 = new ObjectName("test:simple=1");
+ mbs.createMBean(Simple.class.getName(), name1);
+
+ final ObjectName name2 = new ObjectName("test:timer=1");
+ mbs.createMBean("javax.management.timer.Timer", name2);
+
+ QueryExp exp = Query.isInstanceOf(Query.value(className));
+ Set<ObjectName> list = mbs.queryNames(new ObjectName("*:*"), exp);
+
+ if (list.contains(name1) || !list.contains(name2)) {
+ throw new RuntimeException("InstanceOfExp does not work.");
+ }
+
+ for (ObjectName on : list) {
+ if (!mbs.isInstanceOf(on, className)) {
+ throw new RuntimeException("InstanceOfQueryExp does not work.");
+ }
+ }
+
+ Set<ObjectName> all = mbs.queryNames(null, null);
+ for (ObjectName n : all) {
+ if (mbs.isInstanceOf(n, className) != list.contains(n))
+ throw new RuntimeException("InstanceOfExp does not work.");
+ }
+
+ try {
+ QueryExp exp1 = Query.isInstanceOf(null);
+ throw new RuntimeException("Not got an exception with a null class name.");
+ } catch (IllegalArgumentException iae) {
+ // OK. Good
+ }
+ }
+}
diff --git a/test/javax/management/query/QueryExpStringTest.java b/test/javax/management/query/QueryExpStringTest.java
new file mode 100644
index 0000000..729a8e7
--- /dev/null
+++ b/test/javax/management/query/QueryExpStringTest.java
@@ -0,0 +1,404 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4886011
+ * @summary Test that QueryExp.toString() is reversible
+ * @author Eamonn McManus
+ * @run clean QueryExpStringTest
+ * @run build QueryExpStringTest
+ * @run main QueryExpStringTest
+ */
+
+import java.util.*;
+import javax.management.*;
+
+public class QueryExpStringTest {
+
+ private static final ValueExp
+ attr = Query.attr("attr"),
+ qattr = Query.attr("className", "attr"),
+ classattr = Query.classattr(),
+ simpleString = Query.value("simpleString"),
+ complexString = Query.value("a'b\\'\""),
+ intValue = Query.value(12345678),
+ integerValue = Query.value(new Integer(12345678)),
+ longValue = Query.value(12345678L),
+ floatValue = Query.value(2.5f),
+ doubleValue = Query.value(2.5d),
+ booleanValue = Query.value(true),
+ plusValue = Query.plus(intValue, integerValue),
+ timesValue = Query.times(doubleValue, floatValue),
+ minusValue = Query.minus(floatValue, doubleValue),
+ divValue = Query.div(doubleValue, floatValue);
+
+ private static final QueryExp
+ gt = Query.gt(intValue, floatValue),
+ geq = Query.geq(intValue, floatValue),
+ leq = Query.leq(intValue, floatValue),
+ lt = Query.lt(intValue, floatValue),
+ eq = Query.eq(intValue, floatValue),
+ between = Query.between(intValue, floatValue, doubleValue),
+ match = Query.match((AttributeValueExp) attr,
+ (StringValueExp) simpleString),
+ initial = Query.initialSubString((AttributeValueExp) attr,
+ (StringValueExp) simpleString),
+ initialStar = Query.initialSubString((AttributeValueExp) attr,
+ Query.value("*")),
+ any = Query.anySubString((AttributeValueExp) attr,
+ (StringValueExp) simpleString),
+ anyStar = Query.anySubString((AttributeValueExp) attr,
+ Query.value("*")),
+ ffinal = Query.finalSubString((AttributeValueExp) attr,
+ (StringValueExp) simpleString),
+ finalMagic = Query.finalSubString((AttributeValueExp) attr,
+ Query.value("?*[\\")),
+ in = Query.in(intValue, new ValueExp[] {intValue, floatValue}),
+ and = Query.and(gt, lt),
+ or = Query.or(gt, lt),
+ not = Query.not(gt);
+
+ // Commented-out tests below require change to implementation
+
+ private static final Object tests[] = {
+ attr, "attr",
+ qattr, "className.attr",
+ classattr, "Class",
+ simpleString, "'simpleString'",
+// complexString, "'a\\'b\\\\\\'\"'",
+ intValue, "12345678",
+ integerValue, "12345678",
+ longValue, "12345678",
+ floatValue, "2.5",
+ doubleValue, "2.5",
+ booleanValue, "true",
+ plusValue, "12345678 + 12345678",
+ timesValue, "2.5 * 2.5",
+ minusValue, "2.5 - 2.5",
+ divValue, "2.5 / 2.5",
+ gt, "(12345678) > (2.5)",
+ geq, "(12345678) >= (2.5)",
+ leq, "(12345678) <= (2.5)",
+ lt, "(12345678) < (2.5)",
+ eq, "(12345678) = (2.5)",
+ between, "(12345678) between (2.5) and (2.5)",
+ match, "attr like 'simpleString'",
+// initial, "attr like 'simpleString*'",
+// initialStar, "attr like '\\\\**'",
+// any, "attr like '*simpleString*'",
+// anyStar, "attr like '*\\\\**'",
+// ffinal, "attr like '*simpleString'",
+// finalMagic, "attr like '*\\\\?\\\\*\\\\[\\\\\\\\'",
+ in, "12345678 in (12345678, 2.5)",
+ and, "((12345678) > (2.5)) and ((12345678) < (2.5))",
+ or, "((12345678) > (2.5)) or ((12345678) < (2.5))",
+ not, "not ((12345678) > (2.5))",
+ };
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("Testing QueryExp.toString()");
+
+ boolean ok = true;
+
+ for (int i = 0; i < tests.length; i += 2) {
+ String testString = tests[i].toString();
+ String expected = (String) tests[i + 1];
+ if (expected.equals(testString))
+ System.out.println("OK: " + expected);
+ else {
+ System.err.println("Expected: {" + expected + "}; got: {" +
+ testString + "}");
+ ok = false;
+ }
+
+ try {
+ Object parsed;
+ String[] expectedref = new String[] {expected};
+ if (tests[i] instanceof ValueExp)
+ parsed = parseExp(expectedref);
+ else
+ parsed = parseQuery(expectedref);
+ if (expectedref[0].length() > 0)
+ throw new Exception("Junk after parse: " + expectedref[0]);
+ String parsedString = parsed.toString();
+ if (parsedString.equals(expected))
+ System.out.println("OK: parsed " + parsedString);
+ else {
+ System.err.println("Parse differs: expected: {" +
+ expected + "}; got: {" +
+ parsedString + "}");
+ ok = false;
+ }
+ } catch (Exception e) {
+ System.err.println("Parse got exception: {" + expected +
+ "}: " + e);
+ ok = false;
+ }
+ }
+
+ if (ok)
+ System.out.println("Test passed");
+ else {
+ System.out.println("TEST FAILED");
+ System.exit(1);
+ }
+ }
+
+ private static QueryExp parseQuery(String[] ss) throws Exception {
+ if (skip(ss, "("))
+ return parseQueryAfterParen(ss);
+
+ if (skip(ss, "not (")) {
+ QueryExp not = parseQuery(ss);
+ if (!skip(ss, ")"))
+ throw new Exception("Expected ) after not (...");
+ return Query.not(not);
+ }
+
+ ValueExp exp = parseExp(ss);
+
+ if (skip(ss, " like ")) {
+ ValueExp pat = parseExp(ss);
+ if (!(exp instanceof AttributeValueExp &&
+ pat instanceof StringValueExp)) {
+ throw new Exception("Expected types `attr like string': " +
+ exp + " like " + pat);
+ }
+ return Query.match((AttributeValueExp) exp, (StringValueExp) pat);
+ }
+
+ if (skip(ss, " in (")) {
+ List values = new ArrayList();
+ if (!skip(ss, ")")) {
+ do {
+ values.add(parseExp(ss));
+ } while (skip(ss, ", "));
+ if (!skip(ss, ")"))
+ throw new Exception("Expected ) after in (...");
+ }
+ return Query.in(exp, (ValueExp[]) values.toArray(new ValueExp[0]));
+ }
+
+ throw new Exception("Expected in or like after expression");
+ }
+
+ private static QueryExp parseQueryAfterParen(String[] ss)
+ throws Exception {
+ /* This is very ugly. We might have "(q1) and (q2)" here, or
+ we might have "(e1) < (e2)". Since the syntax for a query
+ (q1) is not the same as for an expression (e1), but can
+ begin with one, we try to parse the query, and if we get an
+ exception we then try to parse an expression. It's a hacky
+ kind of look-ahead. */
+ String start = ss[0];
+ try {
+ QueryExp lhs = parseQuery(ss);
+ QueryExp result;
+
+ if (skip(ss, ") and ("))
+ result = Query.and(lhs, parseQuery(ss));
+ else if (skip(ss, ") or ("))
+ result = Query.or(lhs, parseQuery(ss));
+ else
+ throw new Exception("Expected `) and/or ('");
+ if (!skip(ss, ")"))
+ throw new Exception("Expected `)' after subquery");
+ return result;
+ } catch (Exception e) {
+ ss[0] = start;
+ ValueExp lhs = parseExp(ss);
+ if (!skip(ss, ") "))
+ throw new Exception("Expected `) ' after subexpression");
+ String op = scanWord(ss);
+ if (!skip(ss, " ("))
+ throw new Exception("Expected ` (' after `" + op + "'");
+ ValueExp rhs = parseExp(ss);
+ if (!skip(ss, ")"))
+ throw new Exception("Expected `)' after subexpression");
+ if (op.equals("="))
+ return Query.eq(lhs, rhs);
+ if (op.equals("<"))
+ return Query.lt(lhs, rhs);
+ if (op.equals(">"))
+ return Query.gt(lhs, rhs);
+ if (op.equals("<="))
+ return Query.leq(lhs, rhs);
+ if (op.equals(">="))
+ return Query.geq(lhs, rhs);
+ if (!op.equals("between"))
+ throw new Exception("Unknown operator `" + op + "'");
+ if (!skip(ss, " and ("))
+ throw new Exception("Expected ` and (' after between");
+ ValueExp high = parseExp(ss);
+ if (!skip(ss, ")"))
+ throw new Exception("Expected `)' after subexpression");
+ return Query.between(lhs, rhs, high);
+ }
+ }
+
+ private static ValueExp parseExp(String[] ss) throws Exception {
+ final ValueExp prim = parsePrimary(ss);
+
+ /* Look ahead to see if we have an arithmetic operator. */
+ String back = ss[0];
+ if (!skip(ss, " "))
+ return prim;
+ if (ss[0].equals("") || "+-*/".indexOf(ss[0].charAt(0)) < 0) {
+ ss[0] = back;
+ return prim;
+ }
+
+ final String op = scanWord(ss);
+ if (op.length() != 1)
+ throw new Exception("Expected arithmetic operator after space");
+ if ("+-*/".indexOf(op) < 0)
+ throw new Exception("Unknown arithmetic operator: " + op);
+ if (!skip(ss, " "))
+ throw new Exception("Expected space after arithmetic operator");
+ ValueExp rhs = parseExp(ss);
+ switch (op.charAt(0)) {
+ case '+': return Query.plus(prim, rhs);
+ case '-': return Query.minus(prim, rhs);
+ case '*': return Query.times(prim, rhs);
+ case '/': return Query.div(prim, rhs);
+ default: throw new Exception("Can't happen: " + op.charAt(0));
+ }
+ }
+
+ private static ValueExp parsePrimary(String[] ss) throws Exception {
+ String s = ss[0];
+
+ if (s.length() == 0)
+ throw new Exception("Empty string found, expression expected");
+
+ char first = s.charAt(0);
+
+ if (first == ' ')
+ throw new Exception("Space found, expression expected");
+
+ if (first == '-' || Character.isDigit(first))
+ return parseNumberExp(ss);
+
+ if (first == '\'')
+ return parseString(ss);
+
+ if (matchWord(ss, "true"))
+ return Query.value(true);
+
+ if (matchWord(ss, "false"))
+ return Query.value(false);
+
+ if (matchWord(ss, "Class"))
+ return Query.classattr();
+
+ String word = scanWord(ss);
+ int lastDot = word.lastIndexOf('.');
+ if (lastDot < 0)
+ return Query.attr(word);
+ else
+ return Query.attr(word.substring(0, lastDot),
+ word.substring(lastDot + 1));
+ }
+
+ private static String scanWord(String[] ss) throws Exception {
+ String s = ss[0];
+ int space = s.indexOf(' ');
+ if (space < 0) {
+ ss[0] = "";
+ return s;
+ } else {
+ String word = s.substring(0, space);
+ ss[0] = s.substring(space);
+ return word;
+ }
+ }
+
+ private static boolean matchWord(String[] ss, String word)
+ throws Exception {
+ String s = ss[0];
+ if (s.startsWith(word)) {
+ int len = word.length();
+ if (s.length() == len || s.charAt(len) == ' '
+ || s.charAt(len) == ')') {
+ ss[0] = s.substring(len);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static ValueExp parseNumberExp(String[] ss) throws Exception {
+ String s = ss[0];
+ int len = s.length();
+ boolean isFloat = false;
+ int i;
+ for (i = 0; i < len; i++) {
+ char c = s.charAt(i);
+ if (Character.isDigit(c) || c == '-' || c == '+')
+ continue;
+ if (c == '.' || c == 'e' || c == 'E') {
+ isFloat = true;
+ continue;
+ }
+ break;
+ }
+ ss[0] = s.substring(i);
+ s = s.substring(0, i);
+ if (isFloat)
+ return Query.value(Double.parseDouble(s));
+ else
+ return Query.value(Long.parseLong(s));
+ }
+
+ private static ValueExp parseString(String[] ss) throws Exception {
+ if (!skip(ss, "'"))
+ throw new Exception("Expected ' at start of string");
+ String s = ss[0];
+ int len = s.length();
+ StringBuffer buf = new StringBuffer();
+ int i;
+ for (i = 0; i < len; i++) {
+ char c = s.charAt(i);
+ if (c == '\'') {
+ ss[0] = s.substring(i + 1);
+ return Query.value(buf.toString());
+ }
+ if (c == '\\') {
+ if (++i == len)
+ throw new Exception("\\ at end of string");
+ c = s.charAt(i);
+ }
+ buf.append(c);
+ }
+ throw new Exception("No closing ' at end of string");
+ }
+
+ private static boolean skip(String[] ss, String skip) {
+ if (ss[0].startsWith(skip)) {
+ ss[0] = ss[0].substring(skip.length());
+ return true;
+ } else
+ return false;
+ }
+}
diff --git a/test/javax/management/query/QueryMatchTest.java b/test/javax/management/query/QueryMatchTest.java
new file mode 100644
index 0000000..67a5500
--- /dev/null
+++ b/test/javax/management/query/QueryMatchTest.java
@@ -0,0 +1,516 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6266438
+ * @summary Query.match code for character sequences like [a-z] is wrong.
+ * @author Luis-Miguel Alventosa
+ * @run clean QueryMatchTest
+ * @run build QueryMatchTest
+ * @run main QueryMatchTest
+ */
+
+import java.lang.management.ManagementFactory;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.Query;
+import javax.management.QueryExp;
+
+public class QueryMatchTest {
+
+ public static interface SimpleMBean {
+ public String getStringNumber();
+ }
+
+ public static class Simple implements SimpleMBean {
+ public Simple(String number) {
+ this.number = number;
+ }
+ public String getStringNumber() {
+ return number;
+ }
+ private String number;
+ }
+
+ // Pattern = 2[7-9]
+ private static String[][] data11 = {
+ { "20", "KO" },
+ { "21", "KO" },
+ { "22", "KO" },
+ { "23", "KO" },
+ { "24", "KO" },
+ { "25", "KO" },
+ { "26", "KO" },
+ { "27", "OK" },
+ { "28", "OK" },
+ { "29", "OK" },
+ { "2-", "KO" },
+ };
+
+ // Pattern = 2[7-9]5
+ private static String[][] data12 = {
+ { "205", "KO" },
+ { "215", "KO" },
+ { "225", "KO" },
+ { "235", "KO" },
+ { "245", "KO" },
+ { "255", "KO" },
+ { "265", "KO" },
+ { "275", "OK" },
+ { "285", "OK" },
+ { "295", "OK" },
+ { "2-5", "KO" },
+ };
+
+ // Pattern = 2[-9]
+ private static String[][] data13 = {
+ { "20", "KO" },
+ { "21", "KO" },
+ { "22", "KO" },
+ { "23", "KO" },
+ { "24", "KO" },
+ { "25", "KO" },
+ { "26", "KO" },
+ { "27", "KO" },
+ { "28", "KO" },
+ { "29", "OK" },
+ { "2-", "OK" },
+ };
+
+ // Pattern = 2[-9]5
+ private static String[][] data14 = {
+ { "205", "KO" },
+ { "215", "KO" },
+ { "225", "KO" },
+ { "235", "KO" },
+ { "245", "KO" },
+ { "255", "KO" },
+ { "265", "KO" },
+ { "275", "KO" },
+ { "285", "KO" },
+ { "295", "OK" },
+ { "2-5", "OK" },
+ };
+
+ // Pattern = 2[9-]
+ private static String[][] data15 = {
+ { "20", "KO" },
+ { "21", "KO" },
+ { "22", "KO" },
+ { "23", "KO" },
+ { "24", "KO" },
+ { "25", "KO" },
+ { "26", "KO" },
+ { "27", "KO" },
+ { "28", "KO" },
+ { "29", "OK" },
+ { "2-", "OK" },
+ };
+
+ // Pattern = 2[9-]5
+ private static String[][] data16 = {
+ { "205", "KO" },
+ { "215", "KO" },
+ { "225", "KO" },
+ { "235", "KO" },
+ { "245", "KO" },
+ { "255", "KO" },
+ { "265", "KO" },
+ { "275", "KO" },
+ { "285", "KO" },
+ { "295", "OK" },
+ { "2-5", "OK" },
+ };
+
+ // Pattern = 2[-]
+ private static String[][] data17 = {
+ { "20", "KO" },
+ { "21", "KO" },
+ { "22", "KO" },
+ { "23", "KO" },
+ { "24", "KO" },
+ { "25", "KO" },
+ { "26", "KO" },
+ { "27", "KO" },
+ { "28", "KO" },
+ { "29", "KO" },
+ { "2-", "OK" },
+ };
+
+ // Pattern = 2[-]5
+ private static String[][] data18 = {
+ { "205", "KO" },
+ { "215", "KO" },
+ { "225", "KO" },
+ { "235", "KO" },
+ { "245", "KO" },
+ { "255", "KO" },
+ { "265", "KO" },
+ { "275", "KO" },
+ { "285", "KO" },
+ { "295", "KO" },
+ { "2-5", "OK" },
+ };
+
+ // Pattern = 2[1-36-8]
+ private static String[][] data19 = {
+ { "20", "KO" },
+ { "21", "OK" },
+ { "22", "OK" },
+ { "23", "OK" },
+ { "24", "KO" },
+ { "25", "KO" },
+ { "26", "OK" },
+ { "27", "OK" },
+ { "28", "OK" },
+ { "29", "KO" },
+ { "2-", "KO" },
+ };
+
+ // Pattern = 2[1-36-8]5
+ private static String[][] data20 = {
+ { "205", "KO" },
+ { "215", "OK" },
+ { "225", "OK" },
+ { "235", "OK" },
+ { "245", "KO" },
+ { "255", "KO" },
+ { "265", "OK" },
+ { "275", "OK" },
+ { "285", "OK" },
+ { "295", "KO" },
+ { "2-5", "KO" },
+ };
+
+ // Pattern = 2[!7-9]
+ private static String[][] data21 = {
+ { "20", "OK" },
+ { "21", "OK" },
+ { "22", "OK" },
+ { "23", "OK" },
+ { "24", "OK" },
+ { "25", "OK" },
+ { "26", "OK" },
+ { "27", "KO" },
+ { "28", "KO" },
+ { "29", "KO" },
+ { "2-", "OK" },
+ };
+
+ // Pattern = 2[!7-9]5
+ private static String[][] data22 = {
+ { "205", "OK" },
+ { "215", "OK" },
+ { "225", "OK" },
+ { "235", "OK" },
+ { "245", "OK" },
+ { "255", "OK" },
+ { "265", "OK" },
+ { "275", "KO" },
+ { "285", "KO" },
+ { "295", "KO" },
+ { "2-5", "OK" },
+ };
+
+ // Pattern = 2[!-9]
+ private static String[][] data23 = {
+ { "20", "OK" },
+ { "21", "OK" },
+ { "22", "OK" },
+ { "23", "OK" },
+ { "24", "OK" },
+ { "25", "OK" },
+ { "26", "OK" },
+ { "27", "OK" },
+ { "28", "OK" },
+ { "29", "KO" },
+ { "2-", "KO" },
+ };
+
+ // Pattern = 2[!-9]5
+ private static String[][] data24 = {
+ { "205", "OK" },
+ { "215", "OK" },
+ { "225", "OK" },
+ { "235", "OK" },
+ { "245", "OK" },
+ { "255", "OK" },
+ { "265", "OK" },
+ { "275", "OK" },
+ { "285", "OK" },
+ { "295", "KO" },
+ { "2-5", "KO" },
+ };
+
+ // Pattern = 2[!9-]
+ private static String[][] data25 = {
+ { "20", "OK" },
+ { "21", "OK" },
+ { "22", "OK" },
+ { "23", "OK" },
+ { "24", "OK" },
+ { "25", "OK" },
+ { "26", "OK" },
+ { "27", "OK" },
+ { "28", "OK" },
+ { "29", "KO" },
+ { "2-", "KO" },
+ };
+
+ // Pattern = 2[!9-]5
+ private static String[][] data26 = {
+ { "205", "OK" },
+ { "215", "OK" },
+ { "225", "OK" },
+ { "235", "OK" },
+ { "245", "OK" },
+ { "255", "OK" },
+ { "265", "OK" },
+ { "275", "OK" },
+ { "285", "OK" },
+ { "295", "KO" },
+ { "2-5", "KO" },
+ };
+
+ // Pattern = 2[!-]
+ private static String[][] data27 = {
+ { "20", "OK" },
+ { "21", "OK" },
+ { "22", "OK" },
+ { "23", "OK" },
+ { "24", "OK" },
+ { "25", "OK" },
+ { "26", "OK" },
+ { "27", "OK" },
+ { "28", "OK" },
+ { "29", "OK" },
+ { "2-", "KO" },
+ };
+
+ // Pattern = 2[!-]5
+ private static String[][] data28 = {
+ { "205", "OK" },
+ { "215", "OK" },
+ { "225", "OK" },
+ { "235", "OK" },
+ { "245", "OK" },
+ { "255", "OK" },
+ { "265", "OK" },
+ { "275", "OK" },
+ { "285", "OK" },
+ { "295", "OK" },
+ { "2-5", "KO" },
+ };
+
+ // Pattern = 2[!1-36-8]
+ private static String[][] data29 = {
+ { "20", "OK" },
+ { "21", "KO" },
+ { "22", "KO" },
+ { "23", "KO" },
+ { "24", "OK" },
+ { "25", "OK" },
+ { "26", "KO" },
+ { "27", "KO" },
+ { "28", "KO" },
+ { "29", "OK" },
+ { "2-", "OK" },
+ };
+
+ // Pattern = 2[!1-36-8]5
+ private static String[][] data30 = {
+ { "205", "OK" },
+ { "215", "KO" },
+ { "225", "KO" },
+ { "235", "KO" },
+ { "245", "OK" },
+ { "255", "OK" },
+ { "265", "KO" },
+ { "275", "KO" },
+ { "285", "KO" },
+ { "295", "OK" },
+ { "2-5", "OK" },
+ };
+
+ // Pattern = a*b?c[d-e]
+ private static String[][] data31 = {
+ { "a*b?cd", "OK" },
+ { "a*b?ce", "OK" },
+ { "a*b?cde", "KO" },
+ { "[a]*b?[c]", "KO" },
+ { "abc", "KO" },
+ { "ab?c", "KO" },
+ { "a*bc", "KO" },
+ { "axxbxc", "KO" },
+ { "axxbxcd", "OK" },
+ };
+
+ // Pattern = a\*b\?c\[d-e]
+ private static String[][] data32 = {
+ { "a*b?cd", "KO" },
+ { "a*b?ce", "KO" },
+ { "a*b?cde", "KO" },
+ { "[a]*b?[c]", "KO" },
+ { "abc", "KO" },
+ { "ab?c", "KO" },
+ { "a*bc", "KO" },
+ { "axxbxc", "KO" },
+ { "axxbxcd", "KO" },
+ { "a*b?c[d]", "KO" },
+ { "a*b?c[e]", "KO" },
+ { "a*b?c[d-e]", "OK" },
+ };
+
+ // Pattern = a\*b\?c\[de]
+ private static String[][] data33 = {
+ { "a*b?cd", "KO" },
+ { "a*b?ce", "KO" },
+ { "a*b?cde", "KO" },
+ { "[a]*b?[c]", "KO" },
+ { "abc", "KO" },
+ { "ab?c", "KO" },
+ { "a*bc", "KO" },
+ { "axxbxc", "KO" },
+ { "axxbxcd", "KO" },
+ { "a*b?c[d]", "KO" },
+ { "a*b?c[e]", "KO" },
+ { "a*b?c[d-e]", "KO" },
+ { "a*b?c[de]", "OK" },
+ };
+
+ // Pattern = abc[de]f
+ private static String[][] data34 = {
+ { "abcdf", "OK" },
+ { "abcef", "OK" },
+ { "abcdef", "KO" },
+ { "abcedf", "KO" },
+ { "abcd", "KO" },
+ { "abce", "KO" },
+ { "abcf", "KO" },
+ };
+
+ // Pattern = abc[d]e
+ private static String[][] data35 = {
+ { "abcde", "OK" },
+ { "abcd", "KO" },
+ { "abcdf", "KO" },
+ { "abcdef", "KO" },
+ };
+
+ // Pattern = a[b]
+ private static String[][] data36 = {
+ { "a", "KO" },
+ { "ab", "OK" },
+ { "a[b]", "KO" },
+ };
+
+ // Pattern = a\b
+ private static String[][] data37 = {
+ { "a", "KO" },
+ { "ab", "KO" },
+ { "a\\b", "OK" },
+ };
+
+ private static Object[][] tests = {
+ { "2[7-9]", data11 },
+ { "2[7-9]5", data12 },
+ { "2[-9]", data13 },
+ { "2[-9]5", data14 },
+ { "2[9-]", data15 },
+ { "2[9-]5", data16 },
+ { "2[-]", data17 },
+ { "2[-]5", data18 },
+ { "2[1-36-8]", data19 },
+ { "2[1-36-8]5", data20 },
+ { "2[!7-9]", data21 },
+ { "2[!7-9]5", data22 },
+ { "2[!-9]", data23 },
+ { "2[!-9]5", data24 },
+ { "2[!9-]", data25 },
+ { "2[!9-]5", data26 },
+ { "2[!-]", data27 },
+ { "2[!-]5", data28 },
+ { "2[!1-36-8]", data29 },
+ { "2[!1-36-8]5", data30 },
+ { "a*b?c[d-e]", data31 },
+ { "a\\*b\\?c\\[d-e]", data32 },
+ { "a\\*b\\?c\\[de]", data33 },
+ { "abc[de]f", data34 },
+ { "abc[d]e", data35 },
+ { "a[b]", data36 },
+ { "a\\\\b", data37 },
+ };
+
+ private static int query(MBeanServer mbs,
+ String pattern,
+ String[][] data) throws Exception {
+
+ int error = 0;
+
+ System.out.println("\nAttribute Value Pattern = " + pattern + "\n");
+ for (int i = 0; i < data.length; i++) {
+ ObjectName on = new ObjectName("domain:type=Simple,pattern=" +
+ ObjectName.quote(pattern) +
+ ",name=" + i);
+ Simple s = new Simple(data[i][0]);
+ mbs.registerMBean(s, on);
+ QueryExp q =
+ Query.match(Query.attr("StringNumber"), Query.value(pattern));
+ q.setMBeanServer(mbs);
+ boolean r = q.apply(on);
+ System.out.print("Attribute Value = " +
+ mbs.getAttribute(on, "StringNumber"));
+ if (r && "OK".equals(data[i][1])) {
+ System.out.println(" OK");
+ } else if (!r && "KO".equals(data[i][1])) {
+ System.out.println(" KO");
+ } else {
+ System.out.println(" Error");
+ error++;
+ }
+ }
+
+ return error;
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ int error = 0;
+
+ System.out.println("\n--- Test javax.management.Query.match ---");
+
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+
+ for (int i = 0; i < tests.length; i++) {
+ error += query(mbs, (String) tests[i][0], (String[][]) tests[i][1]);
+ }
+
+ if (error > 0) {
+ System.out.println("\nTest failed! " + error + " errors.\n");
+ throw new IllegalArgumentException("Test failed");
+ } else {
+ System.out.println("\nTest passed!\n");
+ }
+ }
+}
diff --git a/test/javax/management/query/QuerySubstringTest.java b/test/javax/management/query/QuerySubstringTest.java
new file mode 100644
index 0000000..394a41f
--- /dev/null
+++ b/test/javax/management/query/QuerySubstringTest.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4886033
+ * @summary Query.{initial,any,final}SubString fail if the
+ * matching constraint string contains wildcards.
+ * @author Luis-Miguel Alventosa
+ * @run clean QuerySubstringTest
+ * @run build QuerySubstringTest
+ * @run main QuerySubstringTest
+ */
+
+import java.lang.management.ManagementFactory;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.Query;
+import javax.management.QueryExp;
+
+public class QuerySubstringTest {
+
+ public static interface SimpleMBean {
+ public String getString();
+ }
+
+ public static class Simple implements SimpleMBean {
+ public Simple(String value) {
+ this.value = value;
+ }
+ public String getString() {
+ return value;
+ }
+ private String value;
+ }
+
+ private static String[][] data = {
+ { "a*b?c\\d[e-f]", "OK", "OK", "OK" },
+ { "a*b?c\\d[e-f]g", "OK", "OK", "KO" },
+ { "za*b?c\\d[e-f]", "KO", "OK", "OK" },
+ { "za*b?c\\d[e-f]g", "KO", "OK", "KO" },
+ { "a*b?c\\de", "KO", "KO", "KO" },
+ { "a*b?c\\deg", "KO", "KO", "KO" },
+ { "za*b?c\\de", "KO", "KO", "KO" },
+ { "za*b?c\\deg", "KO", "KO", "KO" },
+ { "a*b?c\\df", "KO", "KO", "KO" },
+ { "a*b?c\\dfg", "KO", "KO", "KO" },
+ { "za*b?c\\df", "KO", "KO", "KO" },
+ { "za*b?c\\dfg", "KO", "KO", "KO" },
+ { "axxbxc\\de", "KO", "KO", "KO" },
+ { "axxbxc\\deg", "KO", "KO", "KO" },
+ { "zaxxbxc\\de", "KO", "KO", "KO" },
+ { "zaxxbxc\\deg", "KO", "KO", "KO" },
+ { "axxbxc\\df", "KO", "KO", "KO" },
+ { "axxbxc\\dfg", "KO", "KO", "KO" },
+ { "zaxxbxc\\df", "KO", "KO", "KO" },
+ { "zaxxbxc\\dfg", "KO", "KO", "KO" },
+ };
+
+ private static int query(MBeanServer mbs,
+ int type,
+ String substring,
+ String[][] data) throws Exception {
+
+ int error = 0;
+
+ String querySubString = null;
+ switch (type) {
+ case 1:
+ querySubString = "InitialSubString";
+ break;
+ case 2:
+ querySubString = "AnySubString";
+ break;
+ case 3:
+ querySubString = "FinalSubString";
+ break;
+ }
+
+ System.out.println("\n" + querySubString + " = " + substring + "\n");
+
+ for (int i = 0; i < data.length; i++) {
+ ObjectName on = new ObjectName("test:type=Simple,query=" +
+ querySubString + ",name=" + i);
+ Simple s = new Simple(data[i][0]);
+ mbs.registerMBean(s, on);
+ QueryExp q = null;
+ switch (type) {
+ case 1:
+ q = Query.initialSubString(Query.attr("String"),
+ Query.value(substring));
+ break;
+ case 2:
+ q = Query.anySubString(Query.attr("String"),
+ Query.value(substring));
+ break;
+ case 3:
+ q = Query.finalSubString(Query.attr("String"),
+ Query.value(substring));
+ break;
+ }
+ q.setMBeanServer(mbs);
+ boolean r = q.apply(on);
+ System.out.print("Attribute Value = " +
+ mbs.getAttribute(on, "String"));
+ if (r && "OK".equals(data[i][type])) {
+ System.out.println(" OK");
+ } else if (!r && "KO".equals(data[i][type])) {
+ System.out.println(" KO");
+ } else {
+ System.out.println(" Error");
+ error++;
+ }
+ }
+
+ return error;
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ int error = 0;
+
+ String pattern = "a*b?c\\d[e-f]";
+
+ System.out.println(
+ "\n--- Test javax.management.Query.{initial|any|final}SubString ---");
+
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+
+ error += query(mbs, 1, pattern, data);
+
+ error += query(mbs, 2, pattern, data);
+
+ error += query(mbs, 3, pattern, data);
+
+ if (error > 0) {
+ System.out.println("\nTest failed! " + error + " errors.\n");
+ throw new IllegalArgumentException("Test failed");
+ } else {
+ System.out.println("\nTest passed!\n");
+ }
+ }
+}
diff --git a/test/javax/management/relation/NonArrayListTest.java b/test/javax/management/relation/NonArrayListTest.java
new file mode 100644
index 0000000..21155e2
--- /dev/null
+++ b/test/javax/management/relation/NonArrayListTest.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4848474
+ * @summary Test that relation service doesn't require List params to be ArrayList
+ * @author Eamonn McManus
+ * @run clean NonArrayListTest
+ * @run build NonArrayListTest
+ * @run main NonArrayListTest
+ */
+
+import java.util.*;
+import javax.management.*;
+import javax.management.relation.*;
+import javax.management.loading.MLet;
+
+public class NonArrayListTest {
+ public static void main(String[] args) throws Exception {
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ RelationService rs = new RelationService(true);
+ ObjectName rsName = new ObjectName("r:type=RelationService");
+ mbs.registerMBean(rs, rsName);
+ RelationServiceMBean rsProxy = (RelationServiceMBean)
+ MBeanServerInvocationHandler.newProxyInstance(mbs,
+ rsName,
+ RelationServiceMBean.class,
+ false);
+
+ ObjectName mlet1Name = new ObjectName("r:type=MLet,instance=1");
+ ObjectName mlet2Name = new ObjectName("r:type=MLet,instance=2");
+ mbs.createMBean(MLet.class.getName(), mlet1Name);
+ mbs.createMBean(MLet.class.getName(), mlet2Name);
+
+ RoleInfo leftRoleInfo = new RoleInfo("left", MLet.class.getName());
+ RoleInfo rightRoleInfo = new RoleInfo("right", MLet.class.getName());
+
+ ArrayList leftRoleValues =
+ new ArrayList(Arrays.asList(new ObjectName[] {mlet1Name}));
+ ArrayList rightRoleValues =
+ new ArrayList(Arrays.asList(new ObjectName[] {mlet2Name}));
+ Role leftRole = new Role("left", leftRoleValues);
+ Role rightRole = new Role("right", rightRoleValues);
+
+ RelationType leftRightType =
+ new RelationTypeSupport("leftRight",
+ new RoleInfo[] {leftRoleInfo,
+ rightRoleInfo});
+ RoleList roleList =
+ new RoleList(new ArrayList(Arrays.asList(new Role[] {
+ leftRole, rightRole,
+ })));
+ rsProxy.addRelationType(leftRightType);
+ rsProxy.createRelation("relId", "leftRight", roleList);
+
+ boolean ok = true;
+ ObjectName oname = new ObjectName("a:b=c");
+ List onameList =
+ new Vector(Arrays.asList(new ObjectName[] {oname}));
+
+ String testName;
+
+ testName = "RelationNotification constructor with only 9 arguments";
+ try {
+ RelationNotification notif =
+ new RelationNotification(RelationNotification.RELATION_BASIC_CREATION,
+ rs, // theSrcObj
+ 0L, // TheSeqNbr
+ 0L, // theTimeStamp
+ "theMsg",
+ "theRelId",
+ "theRelTypeName",
+ oname,
+ onameList);
+ System.out.println("OK: " + testName);
+ } catch (Exception e) {
+ System.err.println("Exception for " + testName);
+ e.printStackTrace();
+ ok = false;
+ }
+
+ testName = "RelationNotification constructor with 11 arguments";
+ try {
+ RelationNotification notif =
+ new RelationNotification(RelationNotification.RELATION_BASIC_UPDATE,
+ rs, // theSrcObj
+ 0L, // TheSeqNbr
+ 0L, // theTimeStamp
+ "theMsg",
+ "theRelId",
+ "theRelTypeName",
+ oname,
+ "theRoleName",
+ onameList,
+ onameList);
+ System.out.println("OK: " + testName);
+ } catch (Exception e) {
+ System.err.println("Exception for " + testName);
+ e.printStackTrace();
+ ok = false;
+ }
+
+ testName = "RelationService.sendNotification";
+ try {
+ rsProxy.sendRoleUpdateNotification("relId", leftRole, onameList);
+ System.out.println("OK: " + testName);
+ } catch (Exception e) {
+ System.err.println("Exception for " + testName);
+ e.printStackTrace();
+ ok = false;
+ }
+
+ testName = "RelationService.updateRoleMap";
+ try {
+ rsProxy.updateRoleMap("relId", leftRole, onameList);
+ System.out.println("OK: " + testName);
+ } catch (Exception e) {
+ System.err.println("Exception for " + testName);
+ e.printStackTrace();
+ ok = false;
+ }
+
+ if (ok)
+ System.out.println("Tests passed");
+ else
+ System.err.println("SOME TESTS FAILED");
+ }
+}
diff --git a/test/javax/management/relation/RelationNotificationSourceTest.java b/test/javax/management/relation/RelationNotificationSourceTest.java
new file mode 100644
index 0000000..1d4c50c
--- /dev/null
+++ b/test/javax/management/relation/RelationNotificationSourceTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4892674
+ * @summary Test that RelationNotification can be constructed with ObjectName.
+ * @author Eamonn McManus
+ * @run clean RelationNotificationSourceTest
+ * @run build RelationNotificationSourceTest
+ * @run main RelationNotificationSourceTest
+ */
+
+import java.util.Collections;
+import javax.management.*;
+import javax.management.relation.*;
+import static javax.management.relation.RelationNotification.*;
+
+public class RelationNotificationSourceTest {
+ public static void main(String[] args) throws Exception {
+ ObjectName name1 = new ObjectName("a:n=1");
+ ObjectName name2 = new ObjectName("a:n=2");
+ ObjectName name = new ObjectName("a:b=c");
+ Notification n1 =
+ new RelationNotification(RELATION_BASIC_REMOVAL,
+ name,
+ 1234L,
+ System.currentTimeMillis(),
+ "message",
+ "id",
+ "typeName",
+ name1,
+ Collections.singletonList(name2));
+ if (!name.equals(n1.getSource()))
+ throw new Exception("FAILED: source is " + n1.getSource());
+ Notification n2 =
+ new RelationNotification(RELATION_BASIC_UPDATE,
+ name,
+ 1234L,
+ System.currentTimeMillis(),
+ "message",
+ "id",
+ "typeName",
+ name1,
+ "role",
+ Collections.singletonList(name2),
+ Collections.singletonList(name2));
+ if (!name.equals(n2.getSource()))
+ throw new Exception("FAILED: source is " + n2.getSource());
+ System.out.println("TEST PASSED");
+ }
+}
diff --git a/test/javax/management/relation/RelationTypeTest.java b/test/javax/management/relation/RelationTypeTest.java
new file mode 100644
index 0000000..41cfa7a
--- /dev/null
+++ b/test/javax/management/relation/RelationTypeTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4716675
+ * @summary Test that relation type checking uses isInstanceOf
+ * @author Eamonn McManus
+ * @run clean RelationTypeTest
+ * @run build RelationTypeTest
+ * @run main RelationTypeTest
+ */
+
+import java.util.*;
+import javax.management.*;
+import javax.management.relation.*;
+
+public class RelationTypeTest {
+ public static void main(String[] args) throws Exception {
+ System.out.println("Test that relation type checking uses " +
+ "isInstanceOf");
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ ObjectName relSvc = new ObjectName("a:type=relationService");
+ mbs.createMBean("javax.management.relation.RelationService",
+ relSvc,
+ new Object[] {Boolean.TRUE},
+ new String[] {"boolean"});
+ RoleInfo leftInfo =
+ new RoleInfo("left", "javax.management.timer.TimerMBean");
+ RoleInfo rightInfo =
+ new RoleInfo("right", "javax.management.timer.Timer");
+ mbs.invoke(relSvc, "createRelationType",
+ new Object[] {
+ "typeName",
+ new RoleInfo[] {leftInfo, rightInfo},
+ },
+ new String[] {
+ "java.lang.String",
+ "[Ljavax.management.relation.RoleInfo;",
+ });
+ ObjectName timer1 = new ObjectName("a:type=timer,number=1");
+ ObjectName timer2 = new ObjectName("a:type=timer,number=2");
+ mbs.createMBean("javax.management.timer.Timer", timer1);
+ mbs.createMBean("javax.management.timer.Timer", timer2);
+ Role leftRole =
+ new Role("left", Arrays.asList(new ObjectName[] {timer1}));
+ Role rightRole =
+ new Role("right", Arrays.asList(new ObjectName[] {timer2}));
+ RoleList roles =
+ new RoleList(Arrays.asList(new Role[] {leftRole, rightRole}));
+ mbs.invoke(relSvc, "createRelation",
+ new Object[] {
+ "relationName",
+ "typeName",
+ roles,
+ },
+ new String[] {
+ "java.lang.String",
+ "java.lang.String",
+ "javax.management.relation.RoleList",
+ });
+ Map assoc =
+ (Map) mbs.invoke(relSvc, "findAssociatedMBeans",
+ new Object[] {
+ timer1,
+ "typeName",
+ "left",
+ },
+ new String[] {
+ "javax.management.ObjectName",
+ "java.lang.String",
+ "java.lang.String",
+ });
+
+ if (assoc.size() != 1) {
+ System.out.println("TEST FAILS: findAssociatedMBeans should " +
+ "return one association: " + assoc);
+ System.exit(1);
+ }
+
+ ArrayList list = (ArrayList) assoc.get(timer2);
+ if (list.size() != 1 || !list.get(0).equals("relationName")) {
+ System.out.println("TEST FAILS: MBean not associated as " +
+ "expected: " + list);
+ System.exit(1);
+ }
+ System.out.println("Test passes");
+ }
+}
diff --git a/test/javax/management/remote/mandatory/URLTest.java b/test/javax/management/remote/mandatory/URLTest.java
new file mode 100644
index 0000000..10c6c3f
--- /dev/null
+++ b/test/javax/management/remote/mandatory/URLTest.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2004-2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5057532
+ * @ignore Test will fail until 6338951 is resolved (java.net.URI now
+ * accepts "http://-a").
+ * @summary Tests that host names are parsed correctly in URLs
+ * @author Eamonn McManus
+ * @run clean URLTest
+ * @run build URLTest
+ * @run main URLTest
+ */
+
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URI;
+import javax.management.remote.JMXServiceURL;
+
+public class URLTest {
+ private static final String[] good = {
+ "",
+ "a",
+ "a.b",
+ "a.b.c.d.e.f.g",
+ "aaa.bbb",
+ "a-a.b-b",
+ "a-a",
+ "a--b",
+ "1.2.3.4",
+ "1.2.3.x",
+ "111.222.222.111",
+ "1",
+ "23skiddoo",
+ "23skiddoo.sfbay",
+ "a1.b2",
+ "1234.sfbay",
+ "[::]",
+ "[ffff::ffff]",
+ };
+ private static final String[] bad = {
+ "-a",
+ "a-",
+ "-",
+ "_",
+ "a_b",
+ "a_b.sfbay",
+ ".",
+ "..",
+ ".a",
+ "a.",
+ "a..",
+ "a..b",
+ ".a.b",
+ "a.b.",
+ "a.b..",
+ "1.2",
+ "111.222.333.444",
+ "a.23skiddoo",
+ "[:::]",
+ "[:]",
+ };
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("Testing that JMXServiceURL accepts the same " +
+ "hosts as java.net.URI");
+ System.out.println("(Except that it allows empty host names and " +
+ "forbids a trailing \".\")");
+ System.out.println();
+
+ int failures = 0;
+
+ for (int pass = 1; pass <= 2; pass++) {
+ final boolean accept = (pass == 1);
+ System.out.println(" Hosts that should " +
+ (accept ? "" : "not ") + "work");
+ String[] hosts = accept ? good : bad;
+
+ for (int i = 0; i < hosts.length; i++) {
+ final String host = hosts[i];
+ System.out.print(" " + host + ": ");
+
+ boolean jmxAccept = true;
+ try {
+ new JMXServiceURL("rmi", hosts[i], 0);
+ } catch (MalformedURLException e) {
+ jmxAccept = false;
+ }
+
+ boolean uriAccept;
+ try {
+ final URI uri = new URI("http://" + host + "/");
+ uriAccept = (uri.getHost() != null);
+ } catch (URISyntaxException e) {
+ uriAccept = false;
+ }
+
+ final int len = host.length();
+ if (accept != uriAccept && len != 0 &&
+ !(len > 1 && host.charAt(len - 1) == '.'
+ && host.charAt(len - 2) != '.')) {
+ // JMXServiceURL allows empty host name; also
+ // java.net.URI allows trailing dot in hostname,
+ // following RFC 2396, but JMXServiceURL doesn't,
+ // following RFC 2609
+ System.out.println("TEST BUG: URI accept=" + uriAccept);
+ failures++;
+ } else {
+ if (jmxAccept == accept)
+ System.out.println("OK");
+ else {
+ System.out.println("FAILED");
+ failures++;
+ }
+ }
+ }
+
+ System.out.println();
+ }
+
+ if (failures == 0)
+ System.out.println("Test passed");
+ else {
+ System.out.println("TEST FAILURES: " + failures);
+ System.exit(1);
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/connection/AddressableTest.java b/test/javax/management/remote/mandatory/connection/AddressableTest.java
new file mode 100644
index 0000000..ad21e8b
--- /dev/null
+++ b/test/javax/management/remote/mandatory/connection/AddressableTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6238815
+ * @summary test the new interface Addressable
+ * @author Shanliang JIANG
+ * @run clean AddressableTest
+ * @run build AddressableTest
+ * @run main AddressableTest
+ */
+
+import java.util.*;
+import java.net.MalformedURLException;
+import java.io.IOException;
+
+import javax.management.*;
+import javax.management.remote.*;
+import javax.management.remote.rmi.*;
+
+public class AddressableTest {
+ private static final String[] protocols = {"rmi", "iiop"};
+ private static final String[] prefixes = {"stub", "ior"};
+
+ private static final MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ public static void main(String[] args) throws Exception {
+ System.out.println(">>> test the new interface Addressable.");
+ boolean ok = true;
+
+ for (int i = 0; i < protocols.length; i++) {
+ try {
+ test(protocols[i], prefixes[i]);
+
+ System.out.println(">>> Test successed for "+protocols[i]);
+ } catch (Exception e) {
+ System.out.println(">>> Test failed for "+protocols[i]);
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+ }
+
+ if (ok) {
+ System.out.println(">>> All Test passed.");
+ } else {
+ System.out.println(">>> Some TESTs FAILED");
+ System.exit(1);
+ }
+ }
+
+ public static void test(String proto, String prefix) throws Exception {
+ JMXServiceURL url = new JMXServiceURL("service:jmx:" + proto + "://");
+ JMXConnectorServer server =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
+
+ server.start();
+
+ JMXServiceURL serverAddr1 = server.getAddress();
+ System.out.println(">>> Created a server with address "+serverAddr1);
+
+ JMXConnector client1 = JMXConnectorFactory.connect(serverAddr1);
+ JMXServiceURL clientAddr1 = ((JMXAddressable)client1).getAddress();
+
+ System.out.println(">>> Created a client with address "+clientAddr1);
+
+ if (!serverAddr1.equals(clientAddr1)) {
+ throw new RuntimeException("The "+proto+" client does not return correct address.");
+ }
+
+ int i = clientAddr1.toString().indexOf(prefix);
+
+ JMXServiceURL clientAddr2 =
+ new JMXServiceURL("service:jmx:"+proto+":///"+clientAddr1.toString().substring(i));
+
+ JMXConnector client2 = JMXConnectorFactory.connect(clientAddr2);
+
+ System.out.println(">>> Created a client with address "+clientAddr2);
+
+ if (!clientAddr2.equals(((JMXAddressable)client2).getAddress())) {
+ throw new RuntimeException("The "+proto+" client does not return correct address.");
+ }
+
+ System.out.println(">>> The new client's host is "+clientAddr2.getHost()
+ +", port is "+clientAddr2.getPort());
+
+ client1.close();
+ client2.close();
+ server.stop();
+ }
+}
diff --git a/test/javax/management/remote/mandatory/connection/BrokenConnectionTest.java b/test/javax/management/remote/mandatory/connection/BrokenConnectionTest.java
new file mode 100644
index 0000000..e3f7ba7
--- /dev/null
+++ b/test/javax/management/remote/mandatory/connection/BrokenConnectionTest.java
@@ -0,0 +1,807 @@
+/*
+ * Copyright 2003-2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4940957
+ * @summary Tests behaviour when connections break
+ * @author Eamonn McManus
+ * @run clean BrokenConnectionTest
+ * @run build BrokenConnectionTest
+ * @run main BrokenConnectionTest
+ */
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.nio.channels.ServerSocketChannel;
+import java.net.*;
+import java.rmi.server.*;
+import java.util.*;
+
+import java.rmi.UnmarshalException;
+
+import javax.management.*;
+import javax.management.remote.*;
+import javax.management.remote.rmi.*;
+
+// resolve ambiguity
+import java.lang.reflect.Proxy;
+
+public class BrokenConnectionTest {
+ private static ObjectName DELEGATE_NAME;
+ private static ObjectName BREAK_NAME;
+ private static ObjectName LISTENER_NAME;
+ public static void main(String[] args) throws Exception {
+ DELEGATE_NAME =
+ new ObjectName("JMImplementation:type=MBeanServerDelegate");
+ BREAK_NAME = new ObjectName("test:type=Break");
+ LISTENER_NAME = new ObjectName("test:type=Listener");
+
+ String failed = "";
+
+ final String[] protos = {"rmi", "jmxmp"};
+
+ for (int i = 0; i < protos.length; i++) {
+ final String proto = protos[i];
+ System.out.println();
+ System.out.println("------- Testing for " + proto + " -------");
+ try {
+ if (!test(proto))
+ failed += " " + proto;
+ } catch (Exception e) {
+ System.out.println("FAILED WITH EXCEPTION:");
+ e.printStackTrace(System.out);
+ failed += " " + proto;
+ }
+ }
+
+ System.out.println();
+
+ if (failed.length() > 0) {
+ System.out.println("TEST FAILED FOR:" + failed);
+ System.exit(1);
+ }
+
+ System.out.println("Test passed");
+ }
+
+ private static boolean test(String proto) throws Exception {
+ if (proto.equals("rmi"))
+ return rmiTest();
+ else if (proto.equals("jmxmp"))
+ return jmxmpTest();
+ else
+ throw new AssertionError(proto);
+ }
+
+ private static interface Breakable {
+ public JMXConnectorServer createConnectorServer(MBeanServer mbs)
+ throws IOException;
+ public void setBroken(boolean broken);
+ }
+
+ private static interface TestAction {
+ public String toString();
+ public boolean test(MBeanServerConnection mbsc, Breakable breakable)
+ throws Exception;
+ }
+
+ private static abstract class Operation implements TestAction {
+ public String toString() {
+ return opName() + ", break, " + opName();
+ }
+ void init(MBeanServerConnection mbsc) throws Exception {}
+ abstract String opName();
+ public boolean test(MBeanServerConnection mbsc, Breakable breakable)
+ throws Exception {
+ init(mbsc);
+ operation(mbsc);
+ System.out.println("Client ran " + opName() + " OK");
+ breakable.setBroken(true);
+ System.out.println("Broke connection, run " + opName() + " again");
+ try {
+ operation(mbsc);
+ System.out.println("TEST FAILED: " + opName() +
+ " should fail!");
+ return false;
+ } catch (IOException e) {
+ System.out.println("Got IOException as expected (" + e + ")");
+ }
+ return true;
+ }
+ abstract void operation(MBeanServerConnection mbsc) throws Exception;
+ }
+
+ private static TestAction[] tests = {
+ new Operation() {
+ String opName() {
+ return "getDefaultDomain";
+ }
+ void operation(MBeanServerConnection mbsc) throws Exception {
+ mbsc.getDefaultDomain();
+ }
+ },
+ new Operation() {
+ String opName() {
+ return "addNotificationListener(NL)";
+ }
+ void operation(MBeanServerConnection mbsc) throws Exception {
+ mbsc.addNotificationListener(DELEGATE_NAME,
+ new CountListener(), null, null);
+ }
+ },
+ new Operation() {
+ String opName() {
+ return "addNotificationListener(MB)";
+ }
+ void init(MBeanServerConnection mbsc) throws Exception {
+ mbsc.createMBean(CountListener.class.getName(),
+ LISTENER_NAME);
+ }
+ void operation(MBeanServerConnection mbsc) throws Exception {
+ mbsc.addNotificationListener(DELEGATE_NAME, LISTENER_NAME,
+ null, null);
+ }
+ },
+ new Operation() {
+ String opName() {
+ return "removeNotificationListener(NL)";
+ }
+ void init(MBeanServerConnection mbsc) throws Exception {
+ for (int i = 0; i < NLISTENERS; i++) {
+ NotificationListener l = new CountListener();
+ mbsc.addNotificationListener(DELEGATE_NAME, l, null, null);
+ listeners.add(l);
+ }
+ }
+ void operation(MBeanServerConnection mbsc) throws Exception {
+ NotificationListener l = (NotificationListener)
+ listeners.remove(0);
+ mbsc.removeNotificationListener(DELEGATE_NAME, l, null, null);
+ }
+ static final int NLISTENERS = 2;
+ List/*<NotificationListener>*/ listeners = new ArrayList();
+ },
+ new Operation() {
+ String opName() {
+ return "removeNotificationListener(MB)";
+ }
+ void init(MBeanServerConnection mbsc) throws Exception {
+ mbsc.createMBean(CountListener.class.getName(),
+ LISTENER_NAME);
+ }
+ void operation(MBeanServerConnection mbsc) throws Exception {
+ try {
+ mbsc.removeNotificationListener(DELEGATE_NAME,
+ LISTENER_NAME,
+ null, null);
+ throw new IllegalArgumentException("removeNL should not " +
+ "have worked!");
+ } catch (ListenerNotFoundException e) {
+ // normal - there isn't one!
+ }
+ }
+ },
+ new Operation() {
+ String opName() {
+ return "createMBean(className, objectName)";
+ }
+ void operation(MBeanServerConnection mbsc) throws Exception {
+ ObjectName name =
+ new ObjectName("test:instance=" + nextInstance());
+ mbsc.createMBean(CountListener.class.getName(), name);
+ }
+ private synchronized int nextInstance() {
+ return ++instance;
+ }
+ private int instance;
+ },
+ new Operation() {
+ String opName() {
+ return "getAttribute";
+ }
+ void operation(MBeanServerConnection mbsc) throws Exception {
+ mbsc.getAttribute(DELEGATE_NAME, "ImplementationName");
+ }
+ },
+ new Operation() {
+ String opName() {
+ return "getAttributes";
+ }
+ void operation(MBeanServerConnection mbsc) throws Exception {
+ mbsc.getAttribute(DELEGATE_NAME, "ImplementationName");
+ }
+ },
+ new Operation() {
+ String opName() {
+ return "getDomains";
+ }
+ void operation(MBeanServerConnection mbsc) throws Exception {
+ mbsc.getDomains();
+ }
+ },
+ new Operation() {
+ String opName() {
+ return "getMBeanCount";
+ }
+ void operation(MBeanServerConnection mbsc) throws Exception {
+ mbsc.getMBeanCount();
+ }
+ },
+ new Operation() {
+ String opName() {
+ return "getMBeanInfo";
+ }
+ void operation(MBeanServerConnection mbsc) throws Exception {
+ mbsc.getMBeanInfo(DELEGATE_NAME);
+ }
+ },
+ new Operation() {
+ String opName() {
+ return "getObjectInstance";
+ }
+ void operation(MBeanServerConnection mbsc) throws Exception {
+ mbsc.getObjectInstance(DELEGATE_NAME);
+ }
+ },
+ new Operation() {
+ String opName() {
+ return "invoke";
+ }
+ void operation(MBeanServerConnection mbsc) throws Exception {
+ mbsc.invoke(BREAK_NAME, "doNothing", new Object[0],
+ new String[0]);
+ }
+ },
+ new Operation() {
+ String opName() {
+ return "isInstanceOf";
+ }
+ void operation(MBeanServerConnection mbsc) throws Exception {
+ mbsc.isInstanceOf(DELEGATE_NAME, "whatsit");
+ }
+ },
+ new Operation() {
+ String opName() {
+ return "isRegistered";
+ }
+ void operation(MBeanServerConnection mbsc) throws Exception {
+ mbsc.isRegistered(DELEGATE_NAME);
+ }
+ },
+ new Operation() {
+ String opName() {
+ return "queryMBeans";
+ }
+ void operation(MBeanServerConnection mbsc) throws Exception {
+ mbsc.queryMBeans(new ObjectName("*:*"), null);
+ }
+ },
+ new Operation() {
+ String opName() {
+ return "queryNames";
+ }
+ void operation(MBeanServerConnection mbsc) throws Exception {
+ mbsc.queryNames(new ObjectName("*:*"), null);
+ }
+ },
+ new Operation() {
+ String opName() {
+ return "setAttribute";
+ }
+ void operation(MBeanServerConnection mbsc) throws Exception {
+ mbsc.setAttribute(BREAK_NAME,
+ new Attribute("Nothing", null));
+ }
+ },
+ new Operation() {
+ String opName() {
+ return "setAttributes";
+ }
+ void operation(MBeanServerConnection mbsc) throws Exception {
+ AttributeList attrs = new AttributeList();
+ attrs.add(new Attribute("Nothing", null));
+ mbsc.setAttributes(BREAK_NAME, attrs);
+ }
+ },
+ new Operation() {
+ String opName() {
+ return "unregisterMBean";
+ }
+ void init(MBeanServerConnection mbsc) throws Exception {
+ for (int i = 0; i < NBEANS; i++) {
+ ObjectName name = new ObjectName("test:instance=" + i);
+ mbsc.createMBean(CountListener.class.getName(), name);
+ names.add(name);
+ }
+ }
+ void operation(MBeanServerConnection mbsc) throws Exception {
+ ObjectName name = (ObjectName) names.remove(0);
+ mbsc.unregisterMBean(name);
+ }
+ private static final int NBEANS = 2;
+ private List/*<ObjectName>*/ names = new ArrayList();
+ },
+ new TestAction() {
+ public String toString() {
+ return "break during send for setAttribute";
+ }
+ public boolean test(MBeanServerConnection mbsc,
+ Breakable breakable) throws Exception {
+ Attribute attr =
+ new Attribute("Break", new BreakWhenSerialized(breakable));
+ try {
+ mbsc.setAttribute(BREAK_NAME, attr);
+ System.out.println("TEST FAILED: setAttribute with " +
+ "BreakWhenSerializable did not fail!");
+ return false;
+ } catch (IOException e) {
+ System.out.println("Got IOException as expected: " + e);
+
+ return true;
+ }
+ }
+ },
+ new TestAction() {
+ public String toString() {
+ return "break during receive for getAttribute";
+ }
+ public boolean test(MBeanServerConnection mbsc,
+ Breakable breakable) throws Exception {
+ try {
+ mbsc.getAttribute(BREAK_NAME, "Break");
+ System.out.println("TEST FAILED: getAttribute of " +
+ "BreakWhenSerializable did not fail!");
+ return false;
+ } catch (IOException e) {
+ System.out.println("Got IOException as expected: " + e);
+
+ return true;
+ }
+ }
+ },
+ };
+
+ public static interface BreakMBean {
+ public BreakWhenSerialized getBreak();
+ public void setBreak(BreakWhenSerialized x);
+// public void breakOnNotify();
+ public void doNothing();
+ public void setNothing(Object x);
+ }
+
+ public static class Break
+ extends NotificationBroadcasterSupport implements BreakMBean {
+ public Break(Breakable breakable) {
+ this.breakable = breakable;
+ }
+
+ public BreakWhenSerialized getBreak() {
+ return new BreakWhenSerialized(breakable);
+ }
+
+ public void setBreak(BreakWhenSerialized x) {
+ throw new IllegalArgumentException("setBreak worked but " +
+ "should not!");
+ }
+
+// public void breakOnNotify() {
+// Notification broken = new Notification("type", "source", 0L);
+// broken.setUserData(new BreakWhenSerialized(breakable));
+// sendNotification(broken);
+// }
+
+ public void doNothing() {}
+
+ public void setNothing(Object x) {}
+
+ private final Breakable breakable;
+ }
+
+ private static class BreakWhenSerialized implements Serializable {
+ BreakWhenSerialized(Breakable breakable) {
+ this.breakable = breakable;
+ }
+
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ breakable.setBroken(true);
+ }
+
+ private final transient Breakable breakable;
+ }
+
+ private static class FailureNotificationFilter
+ implements NotificationFilter {
+ public boolean isNotificationEnabled(Notification n) {
+ System.out.println("Filter: " + n + " (" + n.getType() + ")");
+
+ final String failed =
+ JMXConnectionNotification.FAILED;
+ return (n instanceof JMXConnectionNotification
+ && n.getType().equals(JMXConnectionNotification.FAILED));
+ }
+ }
+
+ public static interface CountListenerMBean {}
+
+ public static class CountListener
+ implements CountListenerMBean, NotificationListener {
+ public synchronized void handleNotification(Notification n, Object h) {
+ count++;
+ }
+
+ int count;
+ }
+
+ private static boolean test(Breakable breakable)
+ throws Exception {
+ boolean alreadyMissedFailureNotif = false;
+ String failed = "";
+ for (int i = 1; i <= tests.length; i++) {
+ TestAction ta = tests[i - 1];
+ System.out.println();
+ System.out.println("Test " + i + ": " + ta);
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ Break breakMBean = new Break(breakable);
+ mbs.registerMBean(breakMBean, BREAK_NAME);
+ JMXConnectorServer cs = breakable.createConnectorServer(mbs);
+ System.out.println("Created and started connector server");
+ JMXServiceURL addr = cs.getAddress();
+ JMXConnector cc = JMXConnectorFactory.connect(addr);
+ CountListener failureListener = new CountListener();
+ NotificationFilter failureFilter = new FailureNotificationFilter();
+ cc.addConnectionNotificationListener(failureListener,
+ failureFilter,
+ null);
+ MBeanServerConnection mbsc = cc.getMBeanServerConnection();
+ System.out.println("Client connected OK");
+ boolean thisok = ta.test(mbsc, breakable);
+
+ try {
+ System.out.println("Stopping server");
+ cs.stop();
+ } catch (IOException e) {
+ System.out.println("Ignoring exception on stop: " + e);
+ }
+ if (thisok) {
+ System.out.println("Waiting for failure notif");
+ long deadline = System.currentTimeMillis() + 5000;
+ while (failureListener.count < 1
+ && System.currentTimeMillis() < deadline)
+ Thread.sleep(500);
+ if (failureListener.count < 1) {
+ System.out.println("Did not get failure notif!");
+ thisok = false;
+ } else if (failureListener.count > 1) {
+ System.out.println("Got too many failure notifs: " +
+ failureListener.count);
+ thisok = false;
+ }
+ }
+ if (!thisok)
+ failed = failed + " " + i;
+ System.out.println("Test " + i + (thisok ? " passed" : " FAILED"));
+ breakable.setBroken(false);
+ }
+ if (failed.equals(""))
+ return true;
+ else {
+ System.out.println("FAILING CASES:" + failed);
+ return false;
+ }
+ }
+
+ private static class BreakableRMI implements Breakable {
+ public JMXConnectorServer createConnectorServer(MBeanServer mbs)
+ throws IOException {
+ JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
+ Map env = new HashMap();
+ env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE,
+ brssf);
+ JMXConnectorServer cs =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
+ cs.start();
+ return cs;
+ }
+
+ public void setBroken(boolean broken) {
+ brssf.setBroken(broken);
+ }
+
+ private final BreakableRMIServerSocketFactory brssf =
+ new BreakableRMIServerSocketFactory();
+ }
+
+ private static boolean rmiTest() throws Exception {
+ System.out.println("RMI broken connection test");
+ Breakable breakable = new BreakableRMI();
+ return test(breakable);
+ }
+
+ private static class BreakableRMIServerSocketFactory
+ implements RMIServerSocketFactory {
+
+ public synchronized ServerSocket createServerSocket(int port)
+ throws IOException {
+ if (broken)
+ throw new IOException("ServerSocket has been broken");
+ BreakableServerSocket bss = new BreakableServerSocket(port);
+ bssList.add(bss);
+ return bss;
+ }
+
+ synchronized void setBroken(boolean broken) {
+ this.broken = broken;
+// System.out.println("BRSSF.setBroken(" + broken + ")");
+ for (Iterator it = bssList.iterator(); it.hasNext(); ) {
+ BreakableServerSocket bss = (BreakableServerSocket) it.next();
+// System.out.println((broken ? "" : "un") + "break " + bss);
+ bss.setBroken(broken);
+ }
+ }
+
+ private final List/*<BreakableServerSocket>*/ bssList =
+ new ArrayList();
+ private boolean broken = false;
+ }
+
+ private static class BreakableJMXMP implements Breakable {
+ BreakableJMXMP() throws IOException {
+ bss = new BreakableServerSocket(0);
+ }
+
+ public JMXConnectorServer createConnectorServer(MBeanServer mbs)
+ throws IOException {
+ try {
+ InvocationHandler scsih =
+ new SocketConnectionServerInvocationHandler(bss);
+ final String mcs =
+ "javax.management.remote.generic.MessageConnectionServer";
+ final Class messageConnectionServerClass = Class.forName(mcs);
+ final Class[] proxyInterfaces = {messageConnectionServerClass};
+ Object socketConnectionServer =
+ Proxy.newProxyInstance(this.getClass().getClassLoader(),
+ proxyInterfaces,
+ scsih);
+ Map env = new HashMap();
+ env.put("jmx.remote.message.connection.server",
+ socketConnectionServer);
+ final String gcs =
+ "javax.management.remote.generic.GenericConnectorServer";
+ final Class genericConnectorServerClass = Class.forName(gcs);
+ final Class[] constrTypes = {Map.class, MBeanServer.class};
+ final Constructor constr =
+ genericConnectorServerClass.getConstructor(constrTypes);
+ JMXConnectorServer cs = (JMXConnectorServer)
+ constr.newInstance(new Object[] {env, mbs});
+ cs.start();
+ return cs;
+ } catch (Exception e) {
+ e.printStackTrace(System.out);
+ throw new AssertionError(e);
+ }
+ }
+
+ public void setBroken(boolean broken) {
+ bss.setBroken(broken);
+ }
+
+ private final BreakableServerSocket bss;
+ }
+
+ private static boolean jmxmpTest() throws Exception {
+ System.out.println("JMXMP broken connection test");
+ try {
+ Class.forName("javax.management.remote.generic.GenericConnector");
+ } catch (ClassNotFoundException e) {
+ System.out.println("Optional classes not present, skipping test");
+ return true;
+ }
+ Breakable breakable = new BreakableJMXMP();
+ return test(breakable);
+ }
+
+ private static class BreakableServerSocket extends ServerSocket {
+ BreakableServerSocket(int port) throws IOException {
+ super();
+ ss = new ServerSocket(port);
+ }
+
+ synchronized void setBroken(boolean broken) {
+ this.broken = broken;
+// System.out.println("BSS.setBroken(" + broken + ")");
+ if (!broken)
+ return;
+ for (Iterator it = sList.iterator(); it.hasNext(); ) {
+ Socket s = (Socket) it.next();
+ try {
+// System.out.println("Break: " + s);
+ s.close();
+ } catch (IOException e) {
+ System.out.println("Unable to close socket: " + s +
+ ", ignoring (" + e + ")");
+ }
+ it.remove();
+ }
+ }
+
+ public void bind(SocketAddress endpoint) throws IOException {
+ ss.bind(endpoint);
+ }
+
+ public void bind(SocketAddress endpoint, int backlog)
+ throws IOException {
+ ss.bind(endpoint, backlog);
+ }
+
+ public InetAddress getInetAddress() {
+ return ss.getInetAddress();
+ }
+
+ public int getLocalPort() {
+ return ss.getLocalPort();
+ }
+
+ public SocketAddress getLocalSocketAddress() {
+ return ss.getLocalSocketAddress();
+ }
+
+ public Socket accept() throws IOException {
+// System.out.println("BSS.accept");
+ Socket s = ss.accept();
+// System.out.println("BSS.accept returned: " + s);
+ if (broken)
+ s.close();
+ else
+ sList.add(s);
+ return s;
+ }
+
+ public void close() throws IOException {
+ ss.close();
+ }
+
+ public ServerSocketChannel getChannel() {
+ return ss.getChannel();
+ }
+
+ public boolean isBound() {
+ return ss.isBound();
+ }
+
+ public boolean isClosed() {
+ return ss.isClosed();
+ }
+
+ public void setSoTimeout(int timeout) throws SocketException {
+ ss.setSoTimeout(timeout);
+ }
+
+ public int getSoTimeout() throws IOException {
+ return ss.getSoTimeout();
+ }
+
+ public void setReuseAddress(boolean on) throws SocketException {
+ ss.setReuseAddress(on);
+ }
+
+ public boolean getReuseAddress() throws SocketException {
+ return ss.getReuseAddress();
+ }
+
+ public String toString() {
+ return "BreakableServerSocket wrapping " + ss.toString();
+ }
+
+ public void setReceiveBufferSize (int size) throws SocketException {
+ ss.setReceiveBufferSize(size);
+ }
+
+ public int getReceiveBufferSize() throws SocketException {
+ return ss.getReceiveBufferSize();
+ }
+
+ private final ServerSocket ss;
+ private final List/*<Socket>*/ sList = new ArrayList();
+ private boolean broken = false;
+ }
+
+ /* We do a lot of messy reflection stuff here because we don't
+ want to reference the optional parts of the JMX Remote API in
+ an environment (J2SE) where they won't be present. */
+
+ /* This class implements the logic that allows us to pretend that
+ we have a class that looks like this:
+ class SocketConnectionServer implements MessageConnectionServer {
+ public MessageConnection accept() throws IOException {...}
+ public JMXServiceURL getAddress() {...}
+ public void start(Map env) throws IOException {...}
+ public void stop() throws IOException {...}
+ }
+ */
+ private static class SocketConnectionServerInvocationHandler
+ implements InvocationHandler {
+ SocketConnectionServerInvocationHandler(ServerSocket ss) {
+ this.ss = ss;
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args)
+ throws Exception {
+ final String mname = method.getName();
+ try {
+ if (mname.equals("accept"))
+ return accept();
+ else if (mname.equals("getAddress"))
+ return getAddress();
+ else if (mname.equals("start"))
+ start((Map) args[0]);
+ else if (mname.equals("stop"))
+ stop();
+ else // probably a method inherited from Object
+ return method.invoke(this, args);
+ } catch (InvocationTargetException ite) {
+ Throwable t = ite.getCause();
+ if (t instanceof IOException) {
+ throw (IOException)t;
+ } else if (t instanceof RuntimeException) {
+ throw (RuntimeException)t;
+ } else {
+ throw ite;
+ }
+ }
+
+ return null;
+ }
+
+ private Object/*MessageConnection*/ accept() throws Exception {
+ System.out.println("SCSIH.accept()");
+ Socket s = ss.accept();
+ Class socketConnectionClass =
+ Class.forName("com.sun.jmx.remote.socket.SocketConnection");
+ Constructor constr =
+ socketConnectionClass.getConstructor(new Class[] {Socket.class});
+ return constr.newInstance(new Object[] {s});
+// InvocationHandler scih = new SocketConnectionInvocationHandler(s);
+// Class messageConnectionClass =
+// Class.forName("javax.management.generic.MessageConnection");
+// return Proxy.newProxyInstance(this.getClass().getClassLoader(),
+// new Class[] {messageConnectionClass},
+// scih);
+ }
+
+ private JMXServiceURL getAddress() throws Exception {
+ System.out.println("SCSIH.getAddress()");
+ return new JMXServiceURL("jmxmp", null, ss.getLocalPort());
+ }
+
+ private void start(Map env) throws IOException {
+ System.out.println("SCSIH.start(" + env + ")");
+ }
+
+ private void stop() throws IOException {
+ System.out.println("SCSIH.stop()");
+ }
+
+ private final ServerSocket ss;
+ }
+}
diff --git a/test/javax/management/remote/mandatory/connection/CloseFailedClientTest.java b/test/javax/management/remote/mandatory/connection/CloseFailedClientTest.java
new file mode 100644
index 0000000..addd2a8
--- /dev/null
+++ b/test/javax/management/remote/mandatory/connection/CloseFailedClientTest.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4921888
+ * @summary Tests that we do not get a NullPointException.
+ * @author Shanliang JIANG
+ * @run clean CloseFailedClientTest
+ * @run build CloseFailedClientTest
+ * @run main CloseFailedClientTest
+ */
+
+import java.net.MalformedURLException;
+import java.io.IOException;
+
+import javax.management.*;
+import javax.management.remote.*;
+
+/**
+ * Try to connect a client to a no-existing or not started server,
+ * expected to receive an IOException.
+ *
+ */
+public class CloseFailedClientTest {
+ /**
+ * we use a fix port on which we hope no server is running,
+ * or a server running on it will give an IOException when our
+ * clients try to connect to it.
+ * The port 999 is specified in
+ * http://www.iana.org/assignments/port-numbers
+ * as:
+ * garcon 999/tcp
+ * applix 999/udp Applix ac
+ * puprouter 999/tcp
+ * puprouter 999/udp
+ *
+ * If the test fails because a server runs on this port and does
+ * not give back an IOException, we can change to another one like
+ * 9999
+ */
+ private static final int port = 999;
+
+ private static final String[] protocols = {"rmi", "iiop", "jmxmp"};
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("Test to close a failed client.");
+
+ boolean ok = true;
+ for (int i = 0; i < protocols.length; i++) {
+ try {
+ if (!test(protocols[i])) {
+ System.out.println("Test failed for " + protocols[i]);
+ ok = false;
+ } else {
+ System.out.println("Test successed for " + protocols[i]);
+ }
+ } catch (Exception e) {
+ System.out.println("Test failed for " + protocols[i]);
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+ }
+
+ if (ok) {
+ System.out.println("Test passed");
+ return;
+ } else {
+ System.out.println("TEST FAILED");
+ System.exit(1);
+ }
+ }
+
+
+ private static boolean test(String proto)
+ throws Exception {
+ System.out.println("Test for protocol " + proto);
+ JMXServiceURL url = new JMXServiceURL(proto, null, port);
+
+ JMXConnector connector;
+ JMXConnectorServer server;
+
+ for (int i=0; i<20; i++) {
+ // no server
+ try {
+ connector = JMXConnectorFactory.newJMXConnector(url, null);
+ } catch (MalformedURLException e) {
+ System.out.println("Skipping unsupported URL " + url);
+ return true;
+ }
+
+ try {
+ connector.connect();
+
+ throw new RuntimeException("Do not get expected IOEeption.");
+ } catch (IOException e) {
+ // OK, the expected IOException is thrown.");
+ }
+
+ // close the connector client
+ connector.close();
+
+ // with server but not started
+ try {
+ server = JMXConnectorServerFactory.newJMXConnectorServer(url, null, null);
+ } catch (MalformedURLException e) {
+ System.out.println("Skipping unsupported URL " + url);
+ return true;
+ }
+
+ connector = JMXConnectorFactory.newJMXConnector(url, null);
+
+ try {
+ connector.connect();
+
+ throw new RuntimeException("Do not get expected IOEeption.");
+ } catch (IOException e) {
+ // OK, the expected IOException is thrown.");
+ }
+
+ // close the connector client
+ connector.close();
+ }
+
+ return true;
+ }
+}
diff --git a/test/javax/management/remote/mandatory/connection/CloseServerTest.java b/test/javax/management/remote/mandatory/connection/CloseServerTest.java
new file mode 100644
index 0000000..ca92bc7
--- /dev/null
+++ b/test/javax/management/remote/mandatory/connection/CloseServerTest.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4838640
+ * @summary test server close in different conditions.
+ * @author Shanliang JIANG
+ * @run clean CloseServerTest
+ * @run build CloseServerTest
+ * @run main CloseServerTest
+ */
+
+import java.net.MalformedURLException;
+import java.io.IOException;
+
+import javax.management.*;
+import javax.management.remote.*;
+
+public class CloseServerTest {
+ private static final String[] protocols = {"rmi", "iiop", "jmxmp"};
+ private static final MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ public static void main(String[] args) {
+ System.out.println(">>> Tests for closing a server.");
+
+ boolean ok = true;
+ for (int i = 0; i < protocols.length; i++) {
+ try {
+ if (!test(protocols[i])) {
+ System.out.println(">>> Test failed for " + protocols[i]);
+ ok = false;
+ } else {
+ System.out.println(">>> Test successed for " + protocols[i]);
+ }
+ } catch (Exception e) {
+ System.out.println(">>> Test failed for " + protocols[i]);
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+ }
+
+ if (ok) {
+ System.out.println(">>> Test passed");
+ } else {
+ System.out.println(">>> TEST FAILED");
+ System.exit(1);
+ }
+ }
+
+ private static boolean test(String proto)
+ throws Exception {
+ System.out.println(">>> Test for protocol " + proto);
+ JMXServiceURL u = new JMXServiceURL(proto, null, 0);
+ JMXConnectorServer server;
+ JMXServiceURL addr;
+ JMXConnector client;
+ MBeanServerConnection mserver;
+
+ final ObjectName delegateName =
+ new ObjectName("JMImplementation:type=MBeanServerDelegate");
+ final NotificationListener dummyListener = new NotificationListener() {
+ public void handleNotification(Notification n, Object o) {
+ // do nothing
+ return;
+ }
+ };
+
+ try {
+ // open and close
+ System.out.println(">>> Open and close a server.");
+
+ server = JMXConnectorServerFactory.newJMXConnectorServer(u, null, mbs);
+ server.stop();
+
+ // open, start then close
+ System.out.println(">>> Open, start and close a server.");
+
+ server = JMXConnectorServerFactory.newJMXConnectorServer(u, null, mbs);
+ server.start();
+ server.stop();
+
+ // with a client, but close the server first
+ System.out.println(">>> Open, start a server, create a client, close the server then the client.");
+
+ server = JMXConnectorServerFactory.newJMXConnectorServer(u, null, mbs);
+ server.start();
+
+ addr = server.getAddress();
+ client = JMXConnectorFactory.newJMXConnector(addr, null);
+ client.connect(null);
+
+ server.stop();
+
+ try {
+ client.close();
+ } catch (Exception ee) {
+ // OK, the server has been closed
+ }
+
+ // with a client, but close the client first
+ System.out.println(">>> Open, start a server, create a client, close the client then server.");
+ server = JMXConnectorServerFactory.newJMXConnectorServer(u, null, mbs);
+ server.start();
+
+ addr = server.getAddress();
+ client = JMXConnectorFactory.newJMXConnector(addr, null);
+ client.connect(null);
+
+ client.close();
+
+ server.stop();
+
+ // with a client listener, but close the server first
+ System.out.println(">>> Open, start a server, create a client, add a listener, close the server then the client.");
+ server = JMXConnectorServerFactory.newJMXConnectorServer(u, null, mbs);
+ server.start();
+
+ addr = server.getAddress();
+ client = JMXConnectorFactory.newJMXConnector(addr, null);
+ client.connect(null);
+
+ mserver = client.getMBeanServerConnection();
+ mserver.addNotificationListener(delegateName, dummyListener, null, null);
+
+ server.stop();
+
+ try {
+ client.close();
+ } catch (Exception e) {
+ // ok, it is because the server has been closed.
+ }
+
+ // with a client listener, but close the client first
+ System.out.println(">>> Open, start a server, create a client, add a listener, close the client then the server.");
+ server = JMXConnectorServerFactory.newJMXConnectorServer(u, null, mbs);
+ server.start();
+
+ addr = server.getAddress();
+ client = JMXConnectorFactory.newJMXConnector(addr, null);
+ client.connect(null);
+
+ mserver = client.getMBeanServerConnection();
+ mserver.addNotificationListener(delegateName, dummyListener, null, null);
+
+ client.close();
+ server.stop();
+ } catch (MalformedURLException e) {
+ System.out.println(">>> Skipping unsupported URL " + u);
+ return true;
+ }
+
+ return true;
+ }
+}
diff --git a/test/javax/management/remote/mandatory/connection/CloseUnconnectedTest.java b/test/javax/management/remote/mandatory/connection/CloseUnconnectedTest.java
new file mode 100644
index 0000000..52729ce
--- /dev/null
+++ b/test/javax/management/remote/mandatory/connection/CloseUnconnectedTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test CloseUnconnectedTest.java 1.1 03/07/28
+ * @bug 4897052
+ * @summary Tests that opening and immediately closing a connector works
+ * @author Eamonn McManus
+ * @run clean CloseUnconnectedTest
+ * @run build CloseUnconnectedTest
+ * @run main CloseUnconnectedTest
+ */
+
+/*
+ * Test that we can create a connection, but never call connect() on it,
+ * then close it again without anything surprising happening.
+ */
+
+import java.net.MalformedURLException;
+
+import javax.management.*;
+import javax.management.remote.*;
+
+public class CloseUnconnectedTest {
+ private static final String[] protocols = {"rmi", "iiop", "jmxmp"};
+
+ public static void main(String[] args) {
+ System.out.println("Test that a connection can be opened and " +
+ "immediately closed without any operations");
+
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ boolean ok = true;
+ for (int i = 0; i < protocols.length; i++) {
+ try {
+ if (!test(protocols[i], mbs)) {
+ System.out.println("Test failed for " + protocols[i]);
+ ok = false;
+ } else {
+ System.out.println("Test successed for " + protocols[i]);
+ }
+ } catch (Exception e) {
+ System.out.println("Test failed for " + protocols[i]);
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+ }
+
+ if (ok) {
+ System.out.println("Test passed");
+ return;
+ } else {
+ System.out.println("TEST FAILED");
+ System.exit(1);
+ }
+ }
+
+ private static boolean test(String proto, MBeanServer mbs)
+ throws Exception {
+ System.out.println("Test immediate client close for protocol " +
+ proto);
+ JMXServiceURL u = new JMXServiceURL(proto, null, 0);
+ JMXConnectorServer s;
+ try {
+ s = JMXConnectorServerFactory.newJMXConnectorServer(u, null, mbs);
+ } catch (MalformedURLException e) {
+ System.out.println("Skipping unsupported URL " + u);
+ return true;
+ }
+ s.start();
+ JMXServiceURL a = s.getAddress();
+ JMXConnector c = JMXConnectorFactory.newJMXConnector(a, null);
+ c.close();
+ s.stop();
+ return true;
+ }
+}
diff --git a/test/javax/management/remote/mandatory/connection/CloseableTest.java b/test/javax/management/remote/mandatory/connection/CloseableTest.java
new file mode 100644
index 0000000..f9d0127
--- /dev/null
+++ b/test/javax/management/remote/mandatory/connection/CloseableTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6231888
+ * @summary Test that all the JMX Remote API classes that define
+ * the method "void close() throws IOException;" extend
+ * or implement the java.io.Closeable interface.
+ * @author Luis-Miguel Alventosa
+ * @run clean CloseableTest
+ * @run build CloseableTest
+ * @run main CloseableTest
+ */
+
+import java.io.Closeable;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.rmi.RMIConnection;
+import javax.management.remote.rmi.RMIConnectionImpl;
+import javax.management.remote.rmi.RMIConnectionImpl_Stub;
+import javax.management.remote.rmi.RMIConnector;
+import javax.management.remote.rmi.RMIIIOPServerImpl;
+import javax.management.remote.rmi.RMIJRMPServerImpl;
+import javax.management.remote.rmi.RMIServerImpl;
+import org.omg.stub.javax.management.remote.rmi._RMIConnection_Stub;
+
+public class CloseableTest {
+ private static final Class closeArray[] = {
+ JMXConnector.class,
+ RMIConnector.class,
+ RMIConnection.class,
+ RMIConnectionImpl.class,
+ RMIConnectionImpl_Stub.class,
+ _RMIConnection_Stub.class,
+ RMIServerImpl.class,
+ RMIIIOPServerImpl.class,
+ RMIJRMPServerImpl.class
+ };
+ public static void main(String[] args) throws Exception {
+ System.out.println("Test that all the JMX Remote API classes that " +
+ "define\nthe method \"void close() throws " +
+ "IOException;\" extend\nor implement the " +
+ "java.io.Closeable interface.");
+ int error = 0;
+ for (Class c : closeArray) {
+ System.out.println("\nTest " + c);
+ if (Closeable.class.isAssignableFrom(c)) {
+ System.out.println("Test passed!");
+ } else {
+ error++;
+ System.out.println("Test failed!");
+ }
+ }
+ if (error > 0) {
+ final String msg = "\nTest FAILED! Got " + error + " error(s)";
+ System.out.println(msg);
+ throw new IllegalArgumentException(msg);
+ } else {
+ System.out.println("\nTest PASSED!");
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/connection/ConnectionListenerNullTest.java b/test/javax/management/remote/mandatory/connection/ConnectionListenerNullTest.java
new file mode 100644
index 0000000..677b664
--- /dev/null
+++ b/test/javax/management/remote/mandatory/connection/ConnectionListenerNullTest.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4943248
+ * @summary Tests that NullPointerException is thrown when listener is null.
+ * @author Daniel Fuchs
+ * @run clean ConnectionListenerNullTest
+ * @run build ConnectionListenerNullTest
+ * @run main ConnectionListenerNullTest
+ */
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.Notification;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import java.util.Map;
+public class ConnectionListenerNullTest {
+
+ static final boolean optionalFlag;
+ static {
+ Class genericClass = null;
+ try {
+ genericClass =
+ Class.forName("javax.management.remote.generic.GenericConnector");
+ } catch (ClassNotFoundException x) {
+ // NO optional package
+ }
+ optionalFlag = (genericClass != null);
+ }
+
+ final static String[] mandatoryList = {
+ "service:jmx:rmi://", "service:jmx:iiop://"
+ };
+
+ final static String[] optionalList = {
+ "service:jmx:jmxmp://"
+ };
+
+ public static int test(String[] urls) {
+ int errCount = 0;
+ for (int i=0;i<urls.length;i++) {
+ try {
+ final JMXServiceURL url = new JMXServiceURL(urls[i]);
+ final JMXConnector c =
+ JMXConnectorFactory.newJMXConnector(url,(Map)null);
+ final NotificationListener nl = null;
+ final NotificationFilter nf = null;
+ final Object h = null;
+ System.out.println("Testing " + c.getClass().getName());
+ try {
+ System.out.println(
+ "addConnectionNotificationListener(null,null,null)");
+ c.addConnectionNotificationListener(nl,nf,h);
+ throw new AssertionError("No exception raised");
+ } catch (NullPointerException npe) {
+ // OK.
+ }
+ final NotificationListener listener = new
+ NotificationListener() {
+ public void handleNotification(Notification notification,
+ Object handback) {
+ }
+ };
+ c.addConnectionNotificationListener(listener,nf,h);
+ try {
+ System.out.println(
+ "removeConnectionNotificationListener(null)");
+ c.removeConnectionNotificationListener(nl);
+ throw new AssertionError("No exception raised");
+ } catch (NullPointerException npe) {
+ // OK.
+ }
+ try {
+ System.out.println(
+ "removeConnectionNotificationListener(null,null,null)");
+ c.removeConnectionNotificationListener(nl,nf,h);
+ throw new AssertionError("No exception raised");
+ } catch (NullPointerException npe) {
+ // OK.
+ }
+ c.removeConnectionNotificationListener(listener);
+ System.out.println(c.getClass().getName() +
+ " successfully tested.");
+ } catch (Exception x) {
+ System.err.println("Unexpected exception for " +
+ urls[i] + ": " + x);
+ x.printStackTrace();
+ errCount++;
+ } catch (AssertionError e) {
+ System.err.println("Unexpected assertion error for " +
+ urls[i] + ": " + e);
+ e.printStackTrace();
+ errCount++;
+ }
+ }
+ return errCount;
+ }
+
+ public static void main(String args[]) {
+ int errCount = 0;
+ errCount += test(mandatoryList);
+ if (optionalFlag) errCount += test(optionalList);
+ if (errCount > 0) {
+ System.err.println("ConnectionListenerNullTest failed: " +
+ errCount + " error(s) reported.");
+ System.exit(1);
+ }
+ System.out.println("ConnectionListenerNullTest passed.");
+ }
+}
diff --git a/test/javax/management/remote/mandatory/connection/ConnectionTest.java b/test/javax/management/remote/mandatory/connection/ConnectionTest.java
new file mode 100644
index 0000000..67b3b59
--- /dev/null
+++ b/test/javax/management/remote/mandatory/connection/ConnectionTest.java
@@ -0,0 +1,358 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4865397
+ * @summary Tests remote JMX connections
+ * @author Eamonn McManus
+ * @run clean ConnectionTest
+ * @run build ConnectionTest
+ * @run main ConnectionTest
+ */
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import java.security.Principal;
+import javax.security.auth.Subject;
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerFactory;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+
+import javax.management.remote.JMXAuthenticator;
+import javax.management.remote.JMXConnectionNotification;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXPrincipal;
+import javax.management.remote.JMXServiceURL;
+
+public class ConnectionTest {
+
+ public static void main(String[] args) {
+// System.setProperty("java.util.logging.config.file",
+// "../../../../logging.properties");
+// // we are in <workspace>/build/test/JTwork/scratch
+// java.util.logging.LogManager.getLogManager().readConfiguration();
+ boolean ok = true;
+ String[] protocols = {"rmi", "iiop", "jmxmp"};
+ if (args.length > 0)
+ protocols = args;
+ for (int i = 0; i < protocols.length; i++) {
+ final String proto = protocols[i];
+ System.out.println("Testing for protocol " + proto);
+ try {
+ ok &= test(proto);
+ } catch (Exception e) {
+ System.err.println("Unexpected exception: " + e);
+ e.printStackTrace();
+ ok = false;
+ }
+ }
+
+ if (ok)
+ System.out.println("Test passed");
+ else {
+ System.out.println("TEST FAILED");
+ System.exit(1);
+ }
+ }
+
+ private static boolean test(String proto) throws Exception {
+ ObjectName serverName = ObjectName.getInstance("d:type=server");
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ JMXAuthenticator authenticator = new BogusAuthenticator();
+ Map env = Collections.singletonMap("jmx.remote.authenticator",
+ authenticator);
+ JMXServiceURL url = new JMXServiceURL("service:jmx:" + proto + "://");
+ JMXConnectorServer server;
+ try {
+ server =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, env,
+ null);
+ } catch (MalformedURLException e) {
+ System.out.println("Protocol " + proto +
+ " not supported, ignoring");
+ return true;
+ }
+ System.out.println("Created connector server");
+ mbs.registerMBean(server, serverName);
+ System.out.println("Registered connector server in MBean server");
+ mbs.addNotificationListener(serverName, logListener, null, null);
+ mbs.invoke(serverName, "start", null, null);
+ System.out.println("Started connector server");
+ JMXServiceURL address =
+ (JMXServiceURL) mbs.getAttribute(serverName, "Address");
+ System.out.println("Retrieved address: " + address);
+
+ if (address.getHost().length() == 0) {
+ System.out.println("Generated address has empty hostname");
+ return false;
+ }
+
+ JMXConnector client = JMXConnectorFactory.connect(address);
+ System.out.println("Client connected");
+
+ String clientConnId = client.getConnectionId();
+ System.out.println("Got connection ID on client: " + clientConnId);
+ boolean ok = checkConnectionId(proto, clientConnId);
+ if (!ok)
+ return false;
+ System.out.println("Connection ID is OK");
+
+ // 4901826: connection ids need some time to be updated using jmxmp
+ // we don't get the notif immediately either
+ // this was originally timeout 1ms, which was not enough
+ Notification notif = waitForNotification(1000);
+ System.out.println("Server got notification: " + notif);
+
+ ok = mustBeConnectionNotification(notif, clientConnId,
+ JMXConnectionNotification.OPENED);
+ if (!ok)
+ return false;
+
+ client.close();
+ System.out.println("Closed client");
+
+ notif = waitForNotification(1000);
+ System.out.println("Got notification: " + notif);
+
+ ok = mustBeConnectionNotification(notif, clientConnId,
+ JMXConnectionNotification.CLOSED);
+ if (!ok)
+ return false;
+
+ client = JMXConnectorFactory.connect(address);
+ System.out.println("Second client connected");
+
+ String clientConnId2 = client.getConnectionId();
+ if (clientConnId.equals(clientConnId2)) {
+ System.out.println("Same connection ID for two connections: " +
+ clientConnId2);
+ return false;
+ }
+ System.out.println("Second client connection ID is different");
+
+ notif = waitForNotification(1);
+ ok = mustBeConnectionNotification(notif, clientConnId2,
+ JMXConnectionNotification.OPENED);
+ if (!ok)
+ return false;
+
+ MBeanServerConnection mbsc = client.getMBeanServerConnection();
+ Map attrs = (Map) mbsc.getAttribute(serverName, "Attributes");
+ System.out.println("Server attributes received by client: " + attrs);
+
+ server.stop();
+ System.out.println("Server stopped");
+
+ notif = waitForNotification(1000);
+ System.out.println("Server got connection-closed notification: " +
+ notif);
+
+ ok = mustBeConnectionNotification(notif, clientConnId2,
+ JMXConnectionNotification.CLOSED);
+ if (!ok)
+ return false;
+
+ try {
+ mbsc.getDefaultDomain();
+ System.out.println("Connection still working but should not be");
+ return false;
+ } catch (IOException e) {
+ System.out.println("Connection correctly got exception: " + e);
+ }
+
+ try {
+ client = JMXConnectorFactory.connect(address);
+ System.out.println("Connector server still working but should " +
+ "not be");
+ return false;
+ } catch (IOException e) {
+ System.out.println("New connection correctly got exception: " + e);
+ }
+
+ return true;
+ }
+
+ private static boolean
+ mustBeConnectionNotification(Notification notif,
+ String requiredConnId,
+ String requiredType) {
+
+ if (!(notif instanceof JMXConnectionNotification)) {
+ System.out.println("Should have been a " +
+ "JMXConnectionNotification: " +
+ notif.getClass());
+ return false;
+ }
+
+ JMXConnectionNotification cnotif = (JMXConnectionNotification) notif;
+ if (!cnotif.getType().equals(requiredType)) {
+ System.out.println("Wrong type notif: is \"" + cnotif.getType() +
+ "\", should be \"" + requiredType + "\"");
+ return false;
+ }
+
+ if (!cnotif.getConnectionId().equals(requiredConnId)) {
+ System.out.println("Wrong connection id: is \"" +
+ cnotif.getConnectionId() + "\", should be \"" +
+ requiredConnId);
+ return false;
+ }
+
+ return true;
+ }
+
+ private static boolean checkConnectionId(String proto, String clientConnId)
+ throws Exception {
+ StringTokenizer tok = new StringTokenizer(clientConnId, " ", true);
+ String s;
+ s = tok.nextToken();
+ if (!s.startsWith(proto + ":")) {
+ System.out.println("Expected \"" + proto + ":\", found \"" + s +
+ "\"");
+ return false;
+ }
+ s = tok.nextToken();
+ if (!s.equals(" ")) {
+ System.out.println("Expected \" \", found \"" + s + "\"");
+ return false;
+ }
+ s = tok.nextToken();
+ StringTokenizer tok2 = new StringTokenizer(s, ";", true);
+ Set principalNames = new HashSet();
+ String s2;
+ s2 = tok2.nextToken();
+ if (s2.equals(";")) {
+ System.out.println("In identity \"" + s +
+ "\", expected name, found \";\"");
+ return false;
+ }
+ principalNames.add(s2);
+ s2 = tok2.nextToken();
+ if (!s2.equals(";"))
+ throw new Exception("Can't happen");
+ s2 = tok2.nextToken();
+ if (s2.equals(";")) {
+ System.out.println("In identity \"" + s +
+ "\", expected name, found \";\"");
+ return false;
+ }
+ principalNames.add(s2);
+ if (tok2.hasMoreTokens()) {
+ System.out.println("In identity \"" + s + "\", too many tokens");
+ return false;
+ }
+ if (principalNames.size() != bogusPrincipals.size()) {
+ System.out.println("Wrong number of principal names: " +
+ principalNames.size() + " != " +
+ bogusPrincipals.size());
+ return false;
+ }
+ for (Iterator it = bogusPrincipals.iterator(); it.hasNext(); ) {
+ Principal p = (Principal) it.next();
+ if (!principalNames.contains(p.getName())) {
+ System.out.println("Principal names don't contain \"" +
+ p.getName() + "\"");
+ return false;
+ }
+ }
+ s = tok.nextToken();
+ if (!s.equals(" ")) {
+ System.out.println("Expected \" \", found \"" + s + "\"");
+ return false;
+ }
+ return true;
+ }
+
+ private static Notification waitForNotification(long timeout)
+ throws InterruptedException {
+ synchronized (log) {
+ if (log.isEmpty()) {
+ long remainingTime = timeout;
+ final long startTime = System.currentTimeMillis();
+
+ while (log.isEmpty() && remainingTime >0) {
+ log.wait(remainingTime);
+ remainingTime = timeout - (System.currentTimeMillis() - startTime);
+ }
+
+ if (log.isEmpty()) {
+ throw new InterruptedException("Timed out waiting for " +
+ "notification!");
+ }
+ }
+ return (Notification) log.remove(0);
+ }
+ }
+
+ private static class LogListener implements NotificationListener {
+ LogListener(List log) {
+ this.log = log;
+ }
+
+ public void handleNotification(Notification n, Object h) {
+ synchronized (log) {
+ log.add(n);
+ log.notifyAll();
+ }
+ }
+
+ private final List log;
+ }
+
+ private static List log = new LinkedList();
+ private static NotificationListener logListener = new LogListener(log);
+
+ private static class BogusAuthenticator implements JMXAuthenticator {
+ public Subject authenticate(Object credentials) {
+ Subject subject =
+ new Subject(true, bogusPrincipals,
+ Collections.EMPTY_SET, Collections.EMPTY_SET);
+ System.out.println("Authenticator returns: " + subject);
+ return subject;
+ }
+ }
+
+ private static final Set bogusPrincipals = new HashSet();
+ static {
+ bogusPrincipals.add(new JMXPrincipal("foo"));
+ bogusPrincipals.add(new JMXPrincipal("bar"));
+ }
+}
diff --git a/test/javax/management/remote/mandatory/connection/DeadLockTest.java b/test/javax/management/remote/mandatory/connection/DeadLockTest.java
new file mode 100644
index 0000000..52f2b3c
--- /dev/null
+++ b/test/javax/management/remote/mandatory/connection/DeadLockTest.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5039210
+ * @summary test on a client notification deadlock.
+ * @author Shanliang JIANG
+ * @run clean DeadLockTest
+ * @run build DeadLockTest
+ * @run main DeadLockTest
+ */
+
+import java.net.MalformedURLException;
+import java.io.IOException;
+import java.util.HashMap;
+
+import javax.management.*;
+import javax.management.remote.*;
+
+public class DeadLockTest {
+ private static final String[] protocols = {"rmi", "iiop", "jmxmp"};
+ private static final MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ public static void main(String[] args) {
+ System.out.println(">>> test on a client notification deadlock.");
+
+ boolean ok = true;
+ for (int i = 0; i < protocols.length; i++) {
+ try {
+ test(protocols[i]);
+ } catch (Exception e) {
+ System.out.println(">>> Test failed for " + protocols[i]);
+ e.printStackTrace(System.out);
+ }
+ }
+
+ System.out.println(">>> Test passed");
+ }
+
+ private static void test(String proto)
+ throws Exception {
+ System.out.println(">>> Test for protocol " + proto);
+
+ JMXServiceURL u = null;
+ JMXConnectorServer server = null;
+
+ HashMap env = new HashMap(2);
+ // server will close a client connection after 1 second
+ env.put("jmx.remote.x.server.connection.timeout", "1000");
+
+ // disable the client ping
+ env.put("jmx.remote.x.client.connection.check.period", "0");
+
+ try {
+ u = new JMXServiceURL(proto, null, 0);
+ server = JMXConnectorServerFactory.newJMXConnectorServer(u, env, mbs);
+ } catch (MalformedURLException e) {
+ System.out.println(">>> Skipping unsupported URL " + proto);
+ }
+
+ server.start();
+
+ JMXServiceURL addr = server.getAddress();
+
+ long st = 2000;
+ MyListener myListener;
+
+ // a cycle to make sure that we test the blocking problem.
+ do {
+ JMXConnector client = JMXConnectorFactory.connect(addr, env);
+ MBeanServerConnection conn = client.getMBeanServerConnection();
+ myListener = new MyListener(conn);
+ client.addConnectionNotificationListener(myListener, null, null);
+
+ // wait the server to close the client connection
+ Thread.sleep(st);
+
+ // makes the listener to do a remote request via the connection
+ // which should be closed by the server.
+ conn.getDefaultDomain();
+
+ // allow the listner to have time to work
+ Thread.sleep(100);
+
+ // get a closed notif, should no block.
+ client.close();
+ Thread.sleep(100);
+
+ st += 2000;
+
+ } while(!myListener.isDone());
+
+ server.stop();
+ }
+
+ private static class MyListener implements NotificationListener {
+ public MyListener(MBeanServerConnection conn) {
+ this.conn = conn;
+ }
+
+ public void handleNotification(Notification n, Object h) {
+ if (n instanceof JMXConnectionNotification) {
+ JMXConnectionNotification jcn = (JMXConnectionNotification)n;
+ final String type = jcn.getType();
+ System.out.println(">>> The listener receives notif with the type:"+type);
+
+ if (JMXConnectionNotification.CLOSED.equals(type) ||
+ JMXConnectionNotification.FAILED.equals(type)) {
+
+ synchronized(this) {
+ done = false;
+ }
+
+ try {
+ conn.getDefaultDomain();
+ } catch (IOException ioe) {
+ // Greate !
+ }
+
+ synchronized(this) {
+ done = true;
+ }
+
+ System.out.println(">>> The listener is not blocked!");
+ }
+ }
+ }
+
+ public boolean isDone() {
+ synchronized(this) {
+ return done;
+ }
+ }
+
+ private boolean done = false;
+ private MBeanServerConnection conn;
+ }
+}
diff --git a/test/javax/management/remote/mandatory/connection/FailedConnectionTest.java b/test/javax/management/remote/mandatory/connection/FailedConnectionTest.java
new file mode 100644
index 0000000..a237c77
--- /dev/null
+++ b/test/javax/management/remote/mandatory/connection/FailedConnectionTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+
+/*
+ * @test FailedConnectionTest 1.1 03/11/26
+ * @bug 4939578
+ * @summary test to get an IOException.
+ * @author Shanliang JIANG
+ * @run clean FailedConnectionTest
+ * @run build FailedConnectionTest
+ * @run main FailedConnectionTest
+ */
+
+import java.net.MalformedURLException;
+import java.io.IOException;
+import java.util.HashMap;
+
+import javax.management.*;
+import javax.management.remote.*;
+
+public class FailedConnectionTest {
+ private static final String[] protocols = {"rmi", "iiop", "jmxmp"};
+ private static final MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ public static void main(String[] args) {
+ System.out.println(">>> test to get an IOException when calling"+
+ " getConnectionID on a closed connection.");
+
+ boolean ok = true;
+ for (int i = 0; i < protocols.length; i++) {
+ try {
+ if (!test(protocols[i])) {
+ System.out.println(">>> Test failed for " + protocols[i]);
+ ok = false;
+ } else {
+ System.out.println(">>> Test successed for " + protocols[i]);
+ }
+ } catch (Exception e) {
+ System.out.println(">>> Test failed for " + protocols[i]);
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+ }
+
+ if (ok) {
+ System.out.println(">>> Test passed");
+ } else {
+ System.out.println(">>> TEST FAILED");
+ System.exit(1);
+ }
+ }
+
+ private static boolean test(String proto)
+ throws Exception {
+ System.out.println(">>> Test for protocol " + proto);
+
+ JMXServiceURL u = null;
+ JMXConnectorServer server = null;
+
+ try {
+ u = new JMXServiceURL(proto, null, 0);
+ server = JMXConnectorServerFactory.newJMXConnectorServer(u, null, mbs);
+ } catch (MalformedURLException e) {
+ System.out.println("Skipping unsupported URL " + proto);
+ return true;
+ }
+
+ server.start();
+
+ JMXServiceURL addr = server.getAddress();
+
+ HashMap env = new HashMap(1);
+ env.put("jmx.remote.x.client.connection.check.period", "0");
+
+ JMXConnector client = JMXConnectorFactory.connect(addr, env);
+ server.stop();
+ Thread.sleep(1000);
+ try {
+ client.getConnectionId();
+
+ System.out.println("Do not get expected IOException, failed.");
+ return false;
+ } catch (IOException ioe) {
+ // Good
+ return true;
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/connection/GetConnectionTest.java b/test/javax/management/remote/mandatory/connection/GetConnectionTest.java
new file mode 100644
index 0000000..1342bdb
--- /dev/null
+++ b/test/javax/management/remote/mandatory/connection/GetConnectionTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4951414
+ * @summary Try to get an IOException.
+ * @author Shanliang JIANG
+ * @run clean GetConnectionTest
+ * @run build GetConnectionTest
+ * @run main GetConnectionTest
+ */
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerFactory;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+
+import javax.management.remote.JMXServiceURL;
+
+
+public class GetConnectionTest {
+ public static void main(String[] args) {
+ System.out.println("Verify whether getting an IOException when "+
+ "calling getMBeanServerConnection to a unconnected connector.");
+
+ boolean ok = true;
+ String[] protocols = {"rmi", "iiop", "jmxmp"};
+
+ for (int i = 0; i < protocols.length; i++) {
+ final String proto = protocols[i];
+ System.out.println("Testing for protocol " + proto);
+ try {
+ ok &= test(proto);
+ } catch (Exception e) {
+ System.err.println("Unexpected exception: " + e);
+ e.printStackTrace();
+ ok = false;
+ }
+ }
+
+ if (ok)
+ System.out.println("All Tests passed");
+ else {
+ System.out.println("TEST FAILED");
+ System.exit(1);
+ }
+ }
+
+ private static boolean test(String proto) throws Exception {
+ JMXConnector client;
+ try {
+ JMXServiceURL url = new JMXServiceURL(proto, null, 0);
+ client = JMXConnectorFactory.newJMXConnector(url, null);
+ } catch (MalformedURLException e) {
+ System.out.println("Protocol " + proto +
+ " not supported, ignoring");
+ return true;
+ }
+
+ // IOException is expected
+ try {
+ MBeanServerConnection connection =
+ client.getMBeanServerConnection();
+
+ System.out.println("FAILED: Expected IOException is not thrown.");
+ return false;
+ } catch (IOException e) {
+ System.out.println("PASSED");
+ return true;
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/connection/IIOPURLTest.java b/test/javax/management/remote/mandatory/connection/IIOPURLTest.java
new file mode 100644
index 0000000..0bc04a7
--- /dev/null
+++ b/test/javax/management/remote/mandatory/connection/IIOPURLTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4886799
+ * @summary Check that IIOP URLs have /ior/ in the path
+ * @author Eamonn McManus
+ * @run clean IIOPURLTest
+ * @run build IIOPURLTest
+ * @run main IIOPURLTest
+ */
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerFactory;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+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 IIOPURLTest {
+
+ public static void main(String[] args) throws Exception {
+ JMXServiceURL inputAddr =
+ new JMXServiceURL("service:jmx:iiop://");
+ JMXConnectorServer s =
+ JMXConnectorServerFactory.newJMXConnectorServer(inputAddr, null,
+ null);
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ mbs.registerMBean(s, new ObjectName("a:b=c"));
+ s.start();
+ JMXServiceURL outputAddr = s.getAddress();
+ if (!outputAddr.getURLPath().startsWith("/ior/IOR:")) {
+ System.out.println("URL path should start with \"/ior/IOR:\": " +
+ outputAddr);
+ System.exit(1);
+ }
+ System.out.println("IIOP URL path looks OK: " + outputAddr);
+ JMXConnector c = JMXConnectorFactory.connect(outputAddr);
+ System.out.println("Successfully got default domain: " +
+ c.getMBeanServerConnection().getDefaultDomain());
+ c.close();
+ s.stop();
+ }
+}
diff --git a/test/javax/management/remote/mandatory/connection/IdleTimeoutTest.java b/test/javax/management/remote/mandatory/connection/IdleTimeoutTest.java
new file mode 100644
index 0000000..caf0bc7
--- /dev/null
+++ b/test/javax/management/remote/mandatory/connection/IdleTimeoutTest.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright 2003-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4886838 4886830
+ * @summary Tests that idle timeouts happen at appropriate times
+ * @author Eamonn McManus
+ * @run clean IdleTimeoutTest
+ * @run build IdleTimeoutTest
+ * @run main IdleTimeoutTest
+ */
+
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.HashMap;
+import java.util.Map;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerFactory;
+import javax.management.MBeanServerNotification;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+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 com.sun.jmx.remote.util.EnvHelp;
+
+public class IdleTimeoutTest {
+ public static void main(String[] args) throws Exception {
+ boolean ok = true;
+ List protos;
+ if (args.length > 0)
+ protos = Arrays.asList(args);
+ else {
+ protos =
+ new ArrayList(Arrays.asList(new String[] {"rmi", "iiop"}));
+ try {
+ Class.forName("javax.management.remote.jmxmp." +
+ "JMXMPConnectorServer");
+ protos.add("jmxmp");
+ } catch (ClassNotFoundException e) {
+ // OK: Optional JMXMP support is not present
+ }
+ }
+ for (Iterator it = protos.iterator(); it.hasNext(); ) {
+ String proto = (String) it.next();
+ int liCount;
+ if (proto.equals("jmxmp")) liCount=1;
+ else liCount=2;
+ if (test(proto,4,liCount))
+ System.out.println("Test for protocol " + proto + " passed");
+ else {
+ System.out.println("Test for protocol " + proto + " FAILED");
+ ok = false;
+ }
+ }
+ if (!ok) {
+ System.out.println("SOME TESTS FAILED");
+ System.exit(1);
+ }
+ }
+
+ private static long getIdleTimeout(MBeanServer mbs, JMXServiceURL url)
+ throws Exception {
+ JMXConnectorServer server =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
+ server.start();
+ try {
+ url = server.getAddress();
+
+ // Force initialization (class loading, JIT, etc...)
+ //
+ JMXConnector client = JMXConnectorFactory.connect(url);
+ try {
+ String connId = client.getConnectionId();
+ MBeanServerConnection conn = client.getMBeanServerConnection();
+ } finally {
+ client.close();
+ }
+
+ // Do the time measurement
+ //
+ final long firstTime = System.currentTimeMillis();
+ final long endtime;
+ client = JMXConnectorFactory.connect(url);
+ try {
+ String connId = client.getConnectionId();
+ MBeanServerConnection conn = client.getMBeanServerConnection();
+ endtime = System.currentTimeMillis();
+ } finally {
+ client.close();
+ }
+
+ // multipled by 10 for a slow machine, plus 1500 for a fast one.
+ return 10*(endtime - firstTime) + 1500;
+ } finally {
+ server.stop();
+ }
+ }
+
+ private static class NotificationCounter
+ implements NotificationListener {
+ private final int[] listenerCount;
+ private final String listenerName;
+ NotificationCounter(int[] counter, String name) {
+ listenerCount=counter;
+ listenerName=name;
+ }
+
+ public void handleNotification(Notification n,
+ Object h) {
+ MBeanServerNotification mbsn =
+ (MBeanServerNotification) n;
+ System.out.println(listenerName + " got notification: "
+ + mbsn.getMBeanName());
+ synchronized (listenerCount) {
+ listenerCount[0]++;
+ listenerCount.notify();
+ }
+ }
+ public String toString() {
+ return listenerName;
+ }
+ }
+
+ private static boolean test(String proto,int opCount,int liCount)
+ throws Exception {
+ System.out.println("Idle timeout test for protocol " + proto);
+ ObjectName delegateName =
+ ObjectName.getInstance("JMImplementation:" +
+ "type=MBeanServerDelegate");
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ JMXServiceURL url = new JMXServiceURL("service:jmx:" + proto + "://");
+
+ final long timeout = getIdleTimeout(mbs,url);
+ System.out.println("Timeout for " + proto + " is: " +
+ timeout + " ms");
+
+ Map idleMap = new HashMap();
+ idleMap.put(EnvHelp.SERVER_CONNECTION_TIMEOUT, new Long(timeout));
+ JMXConnectorServer server =
+ JMXConnectorServerFactory.newJMXConnectorServer(url,idleMap,mbs);
+
+ final int[] listenerCount = new int[1];
+ final NotificationListener countListeners[] =
+ new NotificationListener[liCount];
+ int i;
+ for (i=0; i<countListeners.length; i++) {
+ countListeners[i] =
+ new NotificationCounter(listenerCount,"Listener"+i);
+ }
+
+ server.start();
+ try {
+ url = server.getAddress();
+ final long firstTime = System.currentTimeMillis();
+ JMXConnector client = JMXConnectorFactory.connect(url);
+ long elapsed, startIdle=0;
+ try {
+ String connId = client.getConnectionId();
+ MBeanServerConnection conn =
+ client.getMBeanServerConnection();
+ elapsed = System.currentTimeMillis() - firstTime;
+ System.out.println("Idle Time: " + elapsed + "ms");
+
+ for (i=0; i<countListeners.length; i++) {
+ System.out.println("add " + countListeners[i] +
+ ": starting at " + elapsed + "ms");
+ conn.addNotificationListener(delegateName,
+ countListeners[i],
+ null,null);
+ }
+
+ System.out.println("connId=" + connId);
+ for (i = 0; i < opCount; i++) {
+ elapsed = System.currentTimeMillis() - firstTime;
+ System.out.println("Operation[" + (i+1)
+ +"]: starting at " +
+ elapsed + "ms");
+ final String name = "d:type=mlet,instance=" + i;
+ mbs.createMBean("javax.management.loading.MLet",
+ new ObjectName(name));
+ if (i == (opCount-1))
+ startIdle = System.currentTimeMillis();
+ Thread.sleep(2);
+ }
+
+ // Wait for notifs to arrive before doing removeNListener
+ long startTime = System.currentTimeMillis();
+ long deadline = startTime + 10000;
+
+ System.out.println("Waiting for notifs: starting at " +
+ (startTime - firstTime) + "ms");
+
+ final int expectedCount = opCount*countListeners.length;
+ while (System.currentTimeMillis() < deadline) {
+ synchronized (listenerCount) {
+ if (listenerCount[0] >= expectedCount)
+ break;
+ listenerCount.wait();
+ }
+ }
+
+ long elapsedWait = System.currentTimeMillis() - startTime;
+ System.out.println("Waited " + elapsedWait +
+ "ms for notifs to arrive");
+
+ if (listenerCount[0] != expectedCount) {
+ System.out.println("Did not get expected " +
+ expectedCount + " notifications: "
+ + listenerCount[0]);
+ return false;
+ }
+
+ elapsed = System.currentTimeMillis() - firstTime;
+
+ System.out.println("idle time since last operation: " +
+ (elapsed + firstTime - startIdle) + "ms");
+ System.out.println("Requesting conn id at: " +
+ elapsed + "ms");
+ final String cid = client.getConnectionId();
+
+ elapsed = System.currentTimeMillis() - firstTime;
+ System.out.println("Got conn id <" + cid + "> at: " +
+ elapsed + "ms");
+
+ if (!connId.equals(cid)) {
+ System.out.println("Client id changed: <" + connId +
+ "> -> <" + cid +
+ ">");
+ return false;
+ }
+
+ List ids = Arrays.asList(server.getConnectionIds());
+ if (!ids.contains(connId)) {
+ System.out.println("Server ids don't contain our id: " +
+ ids + " - " + connId);
+ return false;
+ }
+
+ for (i=0;i<countListeners.length;i++) {
+ System.out.println("Removing notification listener: " +
+ countListeners[i]);
+ conn.removeNotificationListener(delegateName,
+ countListeners[i]);
+ }
+
+ System.out.println("Waiting for id list to drop ours");
+ deadline = System.currentTimeMillis() + timeout*2 + 10000;
+ while (true) {
+ ids = Arrays.asList(server.getConnectionIds());
+ if (!ids.contains(connId)
+ || System.currentTimeMillis() >= deadline)
+ break;
+ Thread.sleep(500);
+ }
+ if (ids.contains(connId)) {
+ System.out.println("Client id still in list after " +
+ "deadline: " + ids);
+ return false;
+ }
+
+ conn.getDefaultDomain();
+ if (connId.equals(client.getConnectionId())) {
+ System.out.println("Client id did not change: <" + connId +
+ ">: idle timeout did not happen?");
+ return false;
+ } else {
+ System.out.println("Client id changed as expected: <" +
+ connId + "> -> <" +
+ client.getConnectionId() + ">");
+ }
+ } finally {
+ client.close();
+ System.out.println("Connection id list on server after " +
+ "client close: " +
+ Arrays.asList(server.getConnectionIds()));
+ }
+ } finally {
+ server.stop();
+ }
+ System.out.println("*** ------------------------------------------");
+ System.out.println("*** Test passed for " + proto);
+ System.out.println("*** ------------------------------------------");
+ return true;
+ }
+}
diff --git a/test/javax/management/remote/mandatory/connection/MultiOpenCloseTest.java b/test/javax/management/remote/mandatory/connection/MultiOpenCloseTest.java
new file mode 100644
index 0000000..0d386db
--- /dev/null
+++ b/test/javax/management/remote/mandatory/connection/MultiOpenCloseTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test CloseUnconnectedTest.java 1.1 03/08/28
+ * @bug 1234567
+ * @summary Open, connect then close multi-connectors.
+ * @author Shanliang JIANG
+ * @run clean MultiOpenCloseTest
+ * @run build MultiOpenCloseTest
+ * @run main MultiOpenCloseTest
+ */
+
+/*
+ * Test that we can create a connection, call connect() on it,
+ * then close it without anything surprising happening.
+ */
+
+import java.net.MalformedURLException;
+import java.io.IOException;
+
+import javax.management.*;
+import javax.management.remote.*;
+
+public class MultiOpenCloseTest {
+ private static final String[] protocols = {"rmi", "iiop", "jmxmp"};
+ private static final MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ public static void main(String[] args) {
+ System.out.println("Open, connect then close multi-connectors.");
+
+ boolean ok = true;
+ for (int i = 0; i < protocols.length; i++) {
+ try {
+ if (!test(protocols[i])) {
+ System.out.println("Test failed for " + protocols[i]);
+ ok = false;
+ } else {
+ System.out.println("Test successed for " + protocols[i]);
+ }
+ } catch (Exception e) {
+ System.out.println("Test failed for " + protocols[i]);
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+ }
+
+ if (ok) {
+ System.out.println("Test passed");
+ return;
+ } else {
+ System.out.println("TEST FAILED");
+ System.exit(1);
+ }
+ }
+
+ private static boolean test(String proto)
+ throws Exception {
+ System.out.println("Test for protocol " + proto);
+ JMXServiceURL u = new JMXServiceURL(proto, null, 0);
+ JMXConnectorServer s;
+ try {
+ s = JMXConnectorServerFactory.newJMXConnectorServer(u, null, mbs);
+ } catch (MalformedURLException e) {
+ System.out.println("Skipping unsupported URL " + u);
+ return true;
+ }
+ s.start();
+ JMXServiceURL a = s.getAddress();
+
+ final int MAX_ITERS = 10;
+ System.out.println("Looping for " + MAX_ITERS + "iterations...");
+
+ for (int i=0; i<MAX_ITERS; i++) {
+ JMXConnector c = JMXConnectorFactory.newJMXConnector(a, null);
+ c.connect(null);
+ c.close();
+ }
+
+ JMXConnector[] cs = new JMXConnector[MAX_ITERS];
+ for (int i=0; i<MAX_ITERS; i++) {
+ cs[i] = JMXConnectorFactory.newJMXConnector(a, null);
+ cs[i].connect(null);
+ }
+
+ for (int i=0; i<MAX_ITERS; i++) {
+ cs[i].close();
+ }
+
+ try {
+ Thread.sleep(100);
+ } catch (Exception ee) {
+ // should not
+ }
+
+ // check state
+ for (int i=0; i<MAX_ITERS; i++) {
+ try {
+ cs[i].getMBeanServerConnection(null);
+ // no exception
+ System.out.println("Did not get an IOException as expected, failed to close a client.");
+ return false;
+ } catch (IOException ioe) {
+ // as expected
+ }
+ }
+
+ s.stop();
+ return true;
+ }
+}
diff --git a/test/javax/management/remote/mandatory/connection/RMIConnectionIdTest.java b/test/javax/management/remote/mandatory/connection/RMIConnectionIdTest.java
new file mode 100644
index 0000000..76c4305
--- /dev/null
+++ b/test/javax/management/remote/mandatory/connection/RMIConnectionIdTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4901808
+ * @summary Check that RMI connection ids include client host name
+ * @author Eamonn McManus
+ * @run clean RMIConnectionIdTest
+ * @run build RMIConnectionIdTest
+ * @run main RMIConnectionIdTest
+ */
+
+import java.net.*;
+import javax.management.*;
+import javax.management.remote.*;
+
+public class RMIConnectionIdTest {
+ public static void main(String[] args) throws Exception {
+ System.out.println("Testing that RMI connection id includes " +
+ "client host name");
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ 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);
+ String connectionId = cc.getConnectionId();
+ System.out.println("Got connection id: " + connectionId);
+ if (!connectionId.startsWith("rmi://")) {
+ System.out.println("TEST FAILED: does not begin with \"rmi://\"");
+ System.exit(1);
+ }
+ String rest = connectionId.substring("rmi://".length());
+ int spaceIndex = rest.indexOf(' ');
+ if (spaceIndex < 0) {
+ System.out.println("TEST FAILED: no space");
+ System.exit(1);
+ }
+ String clientAddr = rest.substring(0, spaceIndex);
+ InetAddress clientInetAddr = InetAddress.getByName(clientAddr);
+ InetAddress localAddr = InetAddress.getLocalHost();
+ System.out.println("InetAddresses: local=" + localAddr + "; " +
+ "connectionId=" + clientInetAddr);
+ if (!localAddr.equals(clientInetAddr)) {
+ System.out.println("TEST FAILS: addresses differ");
+ System.exit(1);
+ }
+ cc.close();
+ cs.stop();
+ System.out.println("Test passed");
+ }
+}
diff --git a/test/javax/management/remote/mandatory/connection/RMIExitTest.java b/test/javax/management/remote/mandatory/connection/RMIExitTest.java
new file mode 100644
index 0000000..08f687f
--- /dev/null
+++ b/test/javax/management/remote/mandatory/connection/RMIExitTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+
+/*
+ * @test
+ * @bug 4917237
+ * @summary test that process exit immediately after stop() / close() called
+ * @author Jean Francois Denise
+ * @run clean RMIExitTest
+ * @run build RMIExitTest
+ * @run main RMIExitTest
+ */
+
+import java.net.MalformedURLException;
+import java.io.IOException;
+
+import javax.management.MBeanServerFactory;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.MBeanServerConnection;
+import javax.management.NotificationListener;
+import javax.management.Notification;
+
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXConnectorFactory;
+
+/**
+ * VM shutdown hook. Test that the hook is called less than 5 secs
+ * after expected exit.
+ */
+class TimeChecker extends Thread {
+ public void run() {
+ System.out.println("shutdown hook called");
+ long elapsedTime =
+ System.currentTimeMillis() - RMIExitTest.exitStartTime;
+ if(elapsedTime >= 5000) {
+ System.out.println("BUG 4917237 not Fixed.");
+ // Once in hook, to provide an exit status != 0, halt must
+ // be called. Hooks are not called when halt is called.
+ Runtime.getRuntime().halt(1);
+ } else {
+ System.out.println("BUG 4917237 Fixed");
+ }
+ }
+}
+
+/**
+ * Start a server, connect a client, add/remove listeners, close client,
+ * stop server. Check that VM exits in less than 5 secs.
+ *
+ */
+public class RMIExitTest {
+ private static final MBeanServer mbs =
+ MBeanServerFactory.createMBeanServer();
+ public static long exitStartTime = 0;
+
+ public static void main(String[] args) {
+ System.out.println("Start test");
+ Runtime.getRuntime().addShutdownHook(new TimeChecker());
+ test();
+ exitStartTime = System.currentTimeMillis();
+ System.out.println("End test");
+ }
+
+ private static void test() {
+ try {
+ JMXServiceURL u = new JMXServiceURL("rmi", null, 0);
+ JMXConnectorServer server;
+ JMXServiceURL addr;
+ JMXConnector client;
+ MBeanServerConnection mserver;
+
+ final ObjectName delegateName =
+ new ObjectName("JMImplementation:type=MBeanServerDelegate");
+ final NotificationListener dummyListener =
+ new NotificationListener() {
+ public void handleNotification(Notification n,
+ Object o) {
+ // do nothing
+ return;
+ }
+ };
+
+ server = JMXConnectorServerFactory.newJMXConnectorServer(u,
+ null,
+ mbs);
+ server.start();
+
+ addr = server.getAddress();
+ client = JMXConnectorFactory.newJMXConnector(addr, null);
+ client.connect(null);
+
+ mserver = client.getMBeanServerConnection();
+ String s1 = "1";
+ String s2 = "2";
+ String s3 = "3";
+
+ mserver.addNotificationListener(delegateName,
+ dummyListener, null, s1);
+ mserver.addNotificationListener(delegateName,
+ dummyListener, null, s2);
+ mserver.addNotificationListener(delegateName,
+ dummyListener, null, s3);
+
+ mserver.removeNotificationListener(delegateName,
+ dummyListener, null, s3);
+ mserver.removeNotificationListener(delegateName,
+ dummyListener, null, s2);
+ mserver.removeNotificationListener(delegateName,
+ dummyListener, null, s1);
+ client.close();
+
+ server.stop();
+ } catch (Exception e) {
+ System.out.println(e);
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/connection/RMISerializeTest.java b/test/javax/management/remote/mandatory/connection/RMISerializeTest.java
new file mode 100644
index 0000000..f9c4f27
--- /dev/null
+++ b/test/javax/management/remote/mandatory/connection/RMISerializeTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @summary Tests to serialize RMIConnector
+ * @bug 5032052
+ * @author Shanliang JIANG
+ * @run clean RMISerializeTest
+ * @run build RMISerializeTest
+ * @run main RMISerializeTest
+ */
+
+// java imports
+//
+import java.io.*;
+
+// JMX imports
+//
+import javax.management.remote.*;
+import javax.management.remote.rmi.*;
+
+public class RMISerializeTest {
+ public static void main(String[] args) throws Exception {
+ System.out.println(">>> Tests to serialize RMIConnector.");
+
+ JMXServiceURL url = new JMXServiceURL("rmi", null, 1111);
+ RMIConnector rc1 = new RMIConnector(url, null);
+
+ // serialize
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(rc1);
+
+ byte[] bs = baos.toByteArray();
+
+ // deserialize
+ ByteArrayInputStream bais = new ByteArrayInputStream(bs);
+ ObjectInputStream ois = new ObjectInputStream(bais);
+ RMIConnector rc2 = (RMIConnector)ois.readObject();
+
+ try {
+ rc2.close();
+ } catch (NullPointerException npe) {
+ System.out.println(">>> Test failed.");
+ npe.printStackTrace(System.out);
+ System.exit(1);
+ } catch (Exception e) {
+ // OK.
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/connection/ReconnectTest.java b/test/javax/management/remote/mandatory/connection/ReconnectTest.java
new file mode 100644
index 0000000..674b830
--- /dev/null
+++ b/test/javax/management/remote/mandatory/connection/ReconnectTest.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2003-2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4927217
+ * @summary test to reconnect
+ * @author Shanliang JIANG
+ * @run clean ReconnectTest
+ * @run build ReconnectTest
+ * @run main ReconnectTest
+ */
+
+import java.util.*;
+import java.net.MalformedURLException;
+import java.io.IOException;
+
+import javax.management.*;
+import javax.management.remote.*;
+
+public class ReconnectTest {
+ private static final String[] protocols = {"rmi", "iiop", "jmxmp"};
+ private static final MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ private static HashMap env = new HashMap(2);
+
+ static {
+ String timeout = "1000";
+ env.put("jmx.remote.x.server.connection.timeout", timeout);
+ env.put("jmx.remote.x.client.connection.check.period", timeout);
+ }
+
+ public static void main(String[] args) throws Exception {
+ System.out.println(">>> test to reconnect.");
+
+
+ boolean ok = true;
+ for (int i = 0; i < protocols.length; i++) {
+ try {
+ if (!test(protocols[i])) {
+ System.out.println(">>> Test failed for " + protocols[i]);
+ ok = false;
+ } else {
+ System.out.println(">>> Test successed for " + protocols[i]);
+ }
+ } catch (Exception e) {
+ System.out.println(">>> Test failed for " + protocols[i]);
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+ }
+
+ if (ok) {
+ System.out.println(">>> Test passed");
+ } else {
+ System.out.println(">>> TEST FAILED");
+ System.exit(1);
+ }
+ }
+
+ private static boolean test(String proto)
+ throws Exception {
+ System.out.println("\n\n>>> Test for protocol " + proto);
+
+ JMXServiceURL u = null;
+ JMXConnectorServer server = null;
+
+ try {
+ u = new JMXServiceURL(proto, null, 0);
+ server = JMXConnectorServerFactory.newJMXConnectorServer(u, env, mbs);
+ } catch (MalformedURLException e) {
+ System.out.println("Skipping unsupported URL " + proto);
+ return true;
+ }
+
+ server.start();
+ u = server.getAddress();
+
+ JMXConnector conn = JMXConnectorFactory.newJMXConnector(u, env);
+ conn.connect();
+ System.out.print("The default domain is ");
+ System.out.println(conn.getMBeanServerConnection().getDefaultDomain());
+
+ for (int i=0; i<3; i++) {
+ System.out.println("************** Sleeping ...... "+i);
+ Thread.sleep(2000);
+ System.out.println("Sleep done.");
+
+ System.out.println("The default domain is "
+ +conn.getMBeanServerConnection().getDefaultDomain());
+ }
+
+ System.out.println("Close the client ...");
+
+ conn.close();
+
+ System.out.println("Close the server ...");
+
+ server.stop();
+
+ System.out.println("Bye bye.");
+
+ return true;
+ }
+}
diff --git a/test/javax/management/remote/mandatory/connectorServer/ConnectorStopDeadlockTest.java b/test/javax/management/remote/mandatory/connectorServer/ConnectorStopDeadlockTest.java
new file mode 100644
index 0000000..7ec47f6
--- /dev/null
+++ b/test/javax/management/remote/mandatory/connectorServer/ConnectorStopDeadlockTest.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6475157
+ * @summary Tests deadlock in simultaneous connection and connector-server close
+ * @author Eamonn McManus
+ */
+
+/* This test is somewhat dependent on implementation details. If it suddenly
+ * starts failing after a rewrite of the RMIConnectorServer code, you should
+ * consider whether it is still relevant.
+ */
+
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+import java.util.concurrent.Exchanger;
+import javax.management.MBeanServer;
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.rmi.RMIConnection;
+import javax.management.remote.rmi.RMIConnectorServer;
+import javax.management.remote.rmi.RMIJRMPServerImpl;
+
+public class ConnectorStopDeadlockTest {
+ private static String failure;
+ private static RMIConnectorServer connectorServer;
+
+ public static void main(String[] args) throws Exception {
+ JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://");
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ RMIJRMPServerImplSub impl = new RMIJRMPServerImplSub();
+
+ System.out.println("Creating connectorServer");
+ connectorServer = new RMIConnectorServer(url, null, impl, mbs);
+ System.out.println("Starting connectorServer");
+ connectorServer.start();
+ System.out.println("Making client");
+ RMIConnection cc = impl.newClient(null);
+ System.out.println("Closing client");
+ cc.close();
+ if (connectorServer.isActive()) {
+ System.out.println("Stopping connectorServer");
+ connectorServer.stop();
+ }
+ if (failure == null)
+ System.out.println("TEST PASSED, no deadlock");
+ else
+ System.out.println("TEST FAILED");
+ }
+
+ static void fail(Throwable e) {
+ System.out.println("FAILED WITH EXCEPTION: " + e);
+ e.printStackTrace(System.out);
+ failure = e.toString();
+ }
+
+ static void fail(String s) {
+ System.out.println("FAILED: " + s);
+ failure = s;
+ }
+
+// static MonitorInfo[] threadLocks(Thread t) {
+// ThreadMXBean tm = ManagementFactory.getThreadMXBean();
+// ThreadInfo[] tis = tm.getThreadInfo(new long[] {t.getId()}, true, true);
+// if (tis[0] == null)
+// return null;
+// else
+// return tis[0].getLockedMonitors();
+// }
+//
+// static void showLocks(Thread t) {
+// System.out.println("Locks for " + t.getName() + ":");
+// MonitorInfo[] mis = threadLocks(t);
+// if (mis == null)
+// System.out.println(" (no longer exists)");
+// else if (mis.length == 0)
+// System.out.println(" (none)");
+// else {
+// for (MonitorInfo mi : mis)
+// System.out.println(" " + mi);
+// }
+// }
+
+ // Wait until thread t blocks waiting for a lock held by the calling thread,
+ // or until it exits.
+ static void waitForBlock(Thread t) {
+ Thread currentThread = Thread.currentThread();
+ System.out.println("waiting for thread " + t.getName() + " to block " +
+ "on a lock held by thread " + currentThread.getName());
+ ThreadMXBean tm = ManagementFactory.getThreadMXBean();
+ while (true) {
+ ThreadInfo ti = tm.getThreadInfo(t.getId());
+ if (ti == null) {
+ System.out.println(" thread has exited");
+ return;
+ }
+ if (ti.getLockOwnerId() == currentThread.getId()) {
+ System.out.println(" thread now blocked");
+ return;
+ }
+ Thread.yield();
+ }
+ }
+
+ public static class RMIJRMPServerImplSub extends RMIJRMPServerImpl {
+ RMIJRMPServerImplSub() throws IOException {
+ super(0, null, null, null);
+ }
+
+ public RMIConnection makeClient() throws IOException {
+ return super.makeClient("connection id", null);
+ }
+
+ @Override
+ protected void clientClosed(RMIConnection conn) throws IOException {
+ System.out.println("clientClosed, will call connectorServer.stop");
+ final Exchanger<Void> x = new Exchanger<Void>();
+ Thread t = new Thread() {
+ public void run() {
+ try {
+ connectorServer.stop();
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+ };
+ t.setName("connectorServer.stop");
+ t.start();
+ waitForBlock(t);
+ /* If this thread is synchronized on RMIServerImpl, then
+ * the thread that does connectorServer.stop will acquire
+ * the clientList lock and then block waiting for the RMIServerImpl
+ * lock. Our call to super.clientClosed will then deadlock because
+ * it needs to acquire the clientList lock.
+ */
+ System.out.println("calling super.clientClosed");
+ System.out.flush();
+ super.clientClosed(conn);
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/connectorServer/JNDIFailureTest.java b/test/javax/management/remote/mandatory/connectorServer/JNDIFailureTest.java
new file mode 100644
index 0000000..36f37ed
--- /dev/null
+++ b/test/javax/management/remote/mandatory/connectorServer/JNDIFailureTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5065264
+ * @summary Tests that JNDI bind failure doesn't leave an orphan RMI
+ * Connector Server object
+ * @author Eamonn McManus
+ * @run clean JNDIFailureTest
+ * @run build JNDIFailureTest
+ * @run main JNDIFailureTest
+ */
+
+import java.io.IOException;
+import javax.management.*;
+import javax.management.remote.*;
+import javax.management.remote.rmi.*;
+
+public class JNDIFailureTest {
+ public static void main(String[] args) throws Exception {
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ JMXServiceURL jndiUrl =
+ new JMXServiceURL("service:jmx:rmi:///jndi/nonexistenthost/x");
+ SpyServerImpl impl = new SpyServerImpl();
+ JMXConnectorServer cs =
+ new RMIConnectorServer(jndiUrl, null, impl, mbs);
+ try {
+ cs.start();
+ } catch (IOException e) {
+ e.printStackTrace();
+ if (impl.exported) {
+ System.out.println("TEST FAILS: server not unexported");
+ System.exit(1);
+ } else {
+ if (cs.isActive()) {
+ System.out.println("TEST FAILS: server still active");
+ System.exit(1);
+ }
+ System.out.println("Test passed");
+ return;
+ }
+ }
+ System.out.println("TEST FAILS: start did not throw exception");
+ System.exit(1);
+ }
+
+ private static class SpyServerImpl extends RMIJRMPServerImpl {
+ SpyServerImpl() throws IOException {
+ super(0, null, null, null);
+ }
+
+ protected void export() throws IOException {
+ super.export();
+ exported = true;
+ }
+
+ protected void closeServer() throws IOException {
+ super.closeServer();
+ exported = false;
+ }
+
+ boolean exported;
+ }
+}
diff --git a/test/javax/management/remote/mandatory/connectorServer/MBSFPreStartPostStartTest.java b/test/javax/management/remote/mandatory/connectorServer/MBSFPreStartPostStartTest.java
new file mode 100644
index 0000000..f0059fd
--- /dev/null
+++ b/test/javax/management/remote/mandatory/connectorServer/MBSFPreStartPostStartTest.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6227124
+ * @summary Test that setting an MBeanServerForwarder on an already
+ * started RMI connector server has the expected behavior.
+ * @author Luis-Miguel Alventosa
+ * @run clean MBSFPreStartPostStartTest
+ * @run build MBSFPreStartPostStartTest
+ * @run main MBSFPreStartPostStartTest
+ */
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerFactory;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.MBeanServerForwarder;
+
+public class MBSFPreStartPostStartTest {
+
+ public static class MBSFInvocationHandler implements InvocationHandler {
+
+ public static MBeanServerForwarder newProxyInstance() {
+
+ final InvocationHandler handler = new MBSFInvocationHandler();
+
+ final Class[] interfaces =
+ new Class[] {MBeanServerForwarder.class};
+
+ Object proxy = Proxy.newProxyInstance(
+ MBeanServerForwarder.class.getClassLoader(),
+ interfaces,
+ handler);
+
+ return MBeanServerForwarder.class.cast(proxy);
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args)
+ throws Throwable {
+
+ final String methodName = method.getName();
+
+ if (methodName.equals("getMBeanServer")) {
+ return mbs;
+ }
+
+ if (methodName.equals("setMBeanServer")) {
+ if (args[0] == null)
+ throw new IllegalArgumentException("Null MBeanServer");
+ if (mbs != null)
+ throw new IllegalArgumentException("MBeanServer object " +
+ "already initialized");
+ mbs = (MBeanServer) args[0];
+ return null;
+ }
+
+ flag = true;
+
+ return method.invoke(mbs, args);
+ }
+
+ public boolean getFlag() {
+ return flag;
+ }
+
+ public void setFlag(boolean flag) {
+ this.flag = flag;
+ }
+
+ private boolean flag;
+ private MBeanServer mbs;
+ }
+
+ /**
+ * Run test
+ */
+ public int runTest(boolean setBeforeStart) throws Exception {
+
+ echo("=-=-= MBSFPreStartPostStartTest: Set MBSF " +
+ (setBeforeStart ? "before" : "after") +
+ " starting the connector server =-=-=");
+
+ JMXConnectorServer server = null;
+ JMXConnector client = null;
+
+ // Create a new MBeanServer
+ //
+ final MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ try {
+ // Create the JMXServiceURL
+ //
+ final JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://");
+
+ // Create a JMXConnectorServer
+ //
+ server = JMXConnectorServerFactory.newJMXConnectorServer(url,
+ null,
+ mbs);
+
+ // Create MBeanServerForwarder
+ //
+ MBeanServerForwarder mbsf =
+ MBSFInvocationHandler.newProxyInstance();
+
+ // Set MBeanServerForwarder before start()
+ //
+ if (setBeforeStart)
+ server.setMBeanServerForwarder(mbsf);
+
+ // Start the JMXConnectorServer
+ //
+ server.start();
+
+ // Set MBeanServerForwarder after start()
+ //
+ if (!setBeforeStart)
+ server.setMBeanServerForwarder(mbsf);
+
+ // Create a JMXConnector
+ //
+ client = server.toJMXConnector(null);
+
+ // Connect to the connector server
+ //
+ client.connect(null);
+
+ // Get non-secure MBeanServerConnection
+ //
+ final MBeanServerConnection mbsc =
+ client.getMBeanServerConnection();
+
+ // Run method
+ //
+ mbsc.getDefaultDomain();
+
+ // Check flag in MBeanServerForwarder
+ //
+ MBSFInvocationHandler mbsfih =
+ (MBSFInvocationHandler) Proxy.getInvocationHandler(mbsf);
+ if (mbsfih.getFlag() == true) {
+ echo("OK: Did go into MBeanServerForwarder!");
+ } else {
+ echo("KO: Didn't go into MBeanServerForwarder!");
+ return 1;
+ }
+ } catch (Exception e) {
+ echo("Failed to perform operation: " + e);
+ return 1;
+ } finally {
+ // Close the connection
+ //
+ if (client != null)
+ client.close();
+
+ // Stop the connector server
+ //
+ if (server != null)
+ server.stop();
+
+ // Release the MBeanServer
+ //
+ if (mbs != null)
+ MBeanServerFactory.releaseMBeanServer(mbs);
+ }
+
+ return 0;
+ }
+
+ /*
+ * Print message
+ */
+ private static void echo(String message) {
+ System.out.println(message);
+ }
+
+ /*
+ * Standalone entry point.
+ *
+ * Run the test and report to stdout.
+ */
+ public static void main (String args[]) throws Exception {
+
+ int error = 0;
+
+ MBSFPreStartPostStartTest test = new MBSFPreStartPostStartTest();
+
+ // Set MBSF before start()
+ //
+ error += test.runTest(true);
+ // Set MBSF after start()
+ //
+ error += test.runTest(false);
+
+ // Check test results
+ //
+ if (error > 0) {
+ echo(">>> Unhappy Bye, Bye!");
+ throw new IllegalStateException(
+ "Test FAILED: Unexpected error!");
+ } else {
+ echo(">>> Happy Bye, Bye!");
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/connectorServer/RMIExporterTest.java b/test/javax/management/remote/mandatory/connectorServer/RMIExporterTest.java
new file mode 100644
index 0000000..b50e95d
--- /dev/null
+++ b/test/javax/management/remote/mandatory/connectorServer/RMIExporterTest.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5016705
+ * @summary Tests the use of the RMIExporter class.
+ * @author Luis-Miguel Alventosa
+ * @run clean RMIExporterTest
+ * @run build RMIExporterTest
+ * @run main RMIExporterTest
+ */
+
+import java.rmi.NoSuchObjectException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.HashMap;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+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 com.sun.jmx.remote.internal.RMIExporter;
+
+public class RMIExporterTest {
+
+ public static class CustomRMIExporter implements RMIExporter {
+
+ public boolean rmiServerExported = false;
+ public boolean rmiServerUnexported = false;
+ public boolean rmiConnectionExported = false;
+ public boolean rmiConnectionUnexported = false;
+
+ public Remote exportObject(Remote obj,
+ int port,
+ RMIClientSocketFactory csf,
+ RMIServerSocketFactory ssf)
+ throws RemoteException {
+ System.out.println("CustomRMIExporter::exportObject():: " +
+ "Remote = " + obj);
+ if (obj.toString().startsWith(
+ "javax.management.remote.rmi.RMIJRMPServerImpl"))
+ rmiServerExported = true;
+ if (obj.toString().startsWith(
+ "javax.management.remote.rmi.RMIConnectionImpl"))
+ rmiConnectionExported = true;
+ return UnicastRemoteObject.exportObject(obj, port, csf, ssf);
+ }
+
+ public boolean unexportObject(Remote obj, boolean force)
+ throws NoSuchObjectException {
+ System.out.println("CustomRMIExporter::unexportObject():: " +
+ "Remote = " + obj);
+ if (obj.toString().startsWith(
+ "javax.management.remote.rmi.RMIJRMPServerImpl"))
+ rmiServerUnexported = true;
+ if (obj.toString().startsWith(
+ "javax.management.remote.rmi.RMIConnectionImpl"))
+ rmiConnectionUnexported = true;
+ return UnicastRemoteObject.unexportObject(obj, force);
+ }
+ }
+
+ public static void main(String[] args) {
+
+ try {
+ // Instantiate the MBean server
+ //
+ System.out.println("Create the MBean server");
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ // Initialize environment map to be passed to the connector server
+ //
+ System.out.println("Initialize environment map");
+ HashMap env = new HashMap();
+ CustomRMIExporter exporter = new CustomRMIExporter();
+ env.put(RMIExporter.EXPORTER_ATTRIBUTE, exporter);
+
+ // Create an RMI connector server
+ //
+ System.out.println("Create an RMI connector server");
+ JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://");
+ JMXConnectorServer cs =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
+ cs.start();
+
+ // Create an RMI connector client
+ //
+ System.out.println("Create an RMI connector client");
+ JMXConnector cc =
+ JMXConnectorFactory.connect(cs.getAddress(), null);
+
+ // Close RMI connector client
+ //
+ System.out.println("Close the RMI connector client");
+ cc.close();
+
+ // Stop RMI connector server
+ //
+ System.out.println("Stop the RMI connector server");
+ cs.stop();
+
+ // Check if remote objects were exported/unexported successfully
+ //
+ int errorCount = 0;
+
+ if (exporter.rmiServerExported) {
+ System.out.println("RMIServer exported OK!");
+ } else {
+ System.out.println("RMIServer exported KO!");
+ errorCount++;
+ }
+
+ if (exporter.rmiServerUnexported) {
+ System.out.println("RMIServer unexported OK!");
+ } else {
+ System.out.println("RMIServer unexported KO!");
+ errorCount++;
+ }
+
+ if (exporter.rmiConnectionExported) {
+ System.out.println("RMIConnection exported OK!");
+ } else {
+ System.out.println("RMIConnection exported KO!");
+ errorCount++;
+ }
+
+ if (exporter.rmiConnectionUnexported) {
+ System.out.println("RMIConnection unexported OK!");
+ } else {
+ System.out.println("RMIConnection unexported KO!");
+ errorCount++;
+ }
+
+ System.out.println("Bye! Bye!");
+
+ if (errorCount > 0) {
+ System.out.println("RMIExporterTest FAILED!");
+ System.exit(1);
+ } else {
+ System.out.println("RMIExporterTest PASSED!");
+ }
+ } catch (Exception e) {
+ System.out.println("Unexpected exception caught = " + e);
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/connectorServer/SetMBeanServerForwarder.java b/test/javax/management/remote/mandatory/connectorServer/SetMBeanServerForwarder.java
new file mode 100644
index 0000000..c16d25f
--- /dev/null
+++ b/test/javax/management/remote/mandatory/connectorServer/SetMBeanServerForwarder.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4944680
+ * @summary Tests that IllegalArgumentException is thrown when
+ * MBeanServerForwrder is null.
+ * @author Daniel Fuchs
+ * @run clean SetMBeanServerForwarder
+ * @run build SetMBeanServerForwarder
+ * @run main SetMBeanServerForwarder
+ */
+import javax.management.*;
+import javax.management.remote.*;
+import javax.management.remote.rmi.*;
+import java.util.Map;
+
+import com.sun.jmx.remote.security.MBeanServerAccessController;
+
+public class SetMBeanServerForwarder {
+
+ static final boolean optionalFlag;
+ static {
+ Class genericClass = null;
+ try {
+ genericClass =
+ Class.forName("javax.management.remote.generic.GenericConnector");
+ } catch (ClassNotFoundException x) {
+ // NO optional package
+ }
+ optionalFlag = (genericClass != null);
+ }
+
+ final static String[] mandatoryList = {
+ "service:jmx:rmi://", "service:jmx:iiop://"
+ };
+
+ final static String[] optionalList = {
+ "service:jmx:jmxmp://"
+ };
+
+ public static int test(String[] urls) {
+ int errorCount = 0;
+ for (int i=0;i<urls.length;i++) {
+ try {
+ final MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ final JMXConnectorServer cs1,cs2;
+ final JMXServiceURL url;
+
+ System.out.println("*** -----------------------------------");
+ System.out.println("*** JMXConnectorServer("+urls[i]+")");
+ System.out.println("*** -----------------------------------");
+
+ try {
+ url = new JMXServiceURL(urls[i]);
+ cs1 = JMXConnectorServerFactory
+ .newJMXConnectorServer(url,(Map)null,mbs);
+ cs2 = JMXConnectorServerFactory
+ .newJMXConnectorServer(url,(Map)null,null);
+ } catch (Throwable thr) {
+ System.out.println("Failed to create ConnectorServer "+
+ "from [" + urls[i] +"]: " + thr);
+ thr.printStackTrace();
+ errorCount++;
+ continue;
+ }
+
+ // Test using a JMXConnectorServer already connected to an
+ // MBeanServer
+ //
+
+ // Set null MBeanServerForwarder - expect exception
+ //
+ try {
+ cs1.setMBeanServerForwarder(null);
+ errorCount++;
+ System.out.println("Expected IllegalArgumentException "+
+ " not thrown (null forwarder) for " +
+ url);
+ System.out.println("\t\t[connected to MBeanServer]");
+ } catch (IllegalArgumentException iae) {
+ System.out.println("Received expected exception: " +
+ iae);
+ }
+
+ // Now try with a real MBSF - should not throw exception
+ //
+ try {
+ final MBeanServerForwarder fwd = new
+ MBeanServerAccessController() {
+ protected void checkRead() {}
+ protected void checkWrite() {}
+ };
+ cs1.setMBeanServerForwarder(fwd);
+
+ // Verify that the MBSF was correctly set.
+ //
+ if (cs1.getMBeanServer() != fwd) {
+ System.out.println("MBeanServerForwarder not set "+
+ "for " + url);
+ System.out.println("\t\t[connected to MBeanServer]");
+ throw new AssertionError("cs1.getMBeanServer()!=fwd");
+ }
+
+ // Verify that the MBS was correctly forwarded to the MBSF
+ //
+ if (fwd.getMBeanServer() != mbs) {
+ System.out.println("MBeanServer not set in Forwarder"+
+ " for " + url);
+ System.out.println("\t\t[connected to MBeanServer]");
+ throw new AssertionError("fwd.getMBeanServer()!=mbs");
+ }
+ System.out.println("MBeanServerForwarder successfully "+
+ "set for " + url);
+ System.out.println("\t\t[connected to MBeanServer]");
+ } catch (Throwable x) {
+ errorCount++;
+ System.out.println("Failed to set forwarder for " +
+ url);
+ System.out.println("\t\t[connected to MBeanServer]");
+ System.out.println("Unexpected exception: " +
+ x);
+ x.printStackTrace();
+ }
+
+ // Test using a JMXConnectorServer not connected to any
+ // MBeanServer
+ //
+
+ // Set null MBeanServerForwarder - expect exception
+ //
+ try {
+ cs2.setMBeanServerForwarder(null);
+ errorCount++;
+ System.out.println("Expected IllegalArgumentException "+
+ " not thrown (null forwarder) for " +
+ url);
+ System.out.println("\t\t[not connected to MBeanServer]");
+ } catch (IllegalArgumentException iae) {
+ System.out.println("Received expected exception: " +
+ iae);
+ }
+
+ // Now try with a real MBSF - should not throw exception
+ //
+ try {
+ final MBeanServerForwarder fwd = new
+ MBeanServerAccessController() {
+ protected void checkRead() {}
+ protected void checkWrite() {}
+ };
+ cs2.setMBeanServerForwarder(fwd);
+
+ // Verify that the MBSF was correctly set.
+ //
+ if (cs2.getMBeanServer() != fwd) {
+ System.out.println("MBeanServerForwarder not set "+
+ "for " + url);
+ System.out.println("\t\t[not connected to MBeanServer]");
+ throw new AssertionError("cs2.getMBeanServer()!=fwd");
+ }
+
+ // Now register the connector
+ //
+ final ObjectName name =
+ new ObjectName(":type="+cs2.getClass().getName()+
+ ",url="+ObjectName.quote(urls[i]));
+ mbs.registerMBean(cs2,name);
+ try {
+
+ // Verify that the MBSF was not disconnected.
+ //
+ if (cs2.getMBeanServer() != fwd) {
+ System.out.
+ println("MBeanServerForwarder changed "+
+ "for " + url);
+ System.out.
+ println("\t\t[registerMBean]");
+ throw new
+ AssertionError("cs2.getMBeanServer()!=fwd");
+ }
+
+ // Verify that the MBS was not forwarded to the MBSF
+ //
+ if (fwd.getMBeanServer() != null) {
+ System.out.
+ println("MBeanServer changed in Forwarder"+
+ " for " + url);
+ System.out.println("\t\t[registerMBean]");
+ throw new
+ AssertionError("fwd.getMBeanServer()!=null");
+ }
+
+ } finally {
+ mbs.unregisterMBean(name);
+ }
+
+ System.out.println("MBeanServerForwarder successfully "+
+ "set for " + url);
+ System.out.println("\t\t[not connected to MBeanServer]");
+ } catch (Throwable x) {
+ errorCount++;
+ System.out.println("Failed to set forwarder for " +
+ url);
+ System.out.println("\t\t[not connected to MBeanServer]");
+ System.out.println("Unexpected exception: " +
+ x);
+ x.printStackTrace();
+ }
+
+ } catch (Exception x) {
+ System.err.println("Unexpected exception for " +
+ urls[i] + ": " + x);
+ x.printStackTrace();
+ errorCount++;
+ }
+ }
+ return errorCount;
+ }
+
+ public static void main(String args[]) {
+ int errCount = 0;
+ errCount += test(mandatoryList);
+ if (optionalFlag) errCount += test(optionalList);
+ if (errCount > 0) {
+ System.err.println("SetMBeanServerForwarder failed: " +
+ errCount + " error(s) reported.");
+ System.exit(1);
+ }
+ System.out.println("SetMBeanServerForwarder passed.");
+ }
+}
diff --git a/test/javax/management/remote/mandatory/loading/DefaultProviderTest.java b/test/javax/management/remote/mandatory/loading/DefaultProviderTest.java
new file mode 100644
index 0000000..fb2722c
--- /dev/null
+++ b/test/javax/management/remote/mandatory/loading/DefaultProviderTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4884913
+ * @summary Tests that default protocols are loaded correctly
+ * @author Eamonn McManus
+ * @run clean DefaultProviderTest
+ * @run build DefaultProviderTest
+ * @run main DefaultProviderTest
+ */
+
+import java.net.*;
+import java.util.*;
+import javax.management.remote.*;
+
+/**
+ * Create an environment where the providers for the default protocols
+ * (e.g. rmi) are not visible to the loader that is used to load
+ * non-default providers. Check that we can load the default
+ * protocols nevertheless.
+ *
+ * If JMX Remote is part of J2SE, this test becomes meaningless,
+ * because the default protocol providers are visible to the bootstrap
+ * class loader.
+ */
+public class DefaultProviderTest {
+ public static void main(String[] args) throws Exception {
+ URLClassLoader emptyLoader = new URLClassLoader(new URL[0], null);
+ Thread.currentThread().setContextClassLoader(emptyLoader);
+ Map env = new HashMap();
+ env.put(JMXConnectorFactory.PROTOCOL_PROVIDER_CLASS_LOADER,
+ emptyLoader);
+ JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///bogus");
+ JMXConnector conn = JMXConnectorFactory.newJMXConnector(url, env);
+ System.out.println("Successfully created RMI connector in hostile " +
+ "class-loading environment");
+ }
+}
diff --git a/test/javax/management/remote/mandatory/loading/DeserializeEncodedURLTest.java b/test/javax/management/remote/mandatory/loading/DeserializeEncodedURLTest.java
new file mode 100644
index 0000000..5d9c2ed
--- /dev/null
+++ b/test/javax/management/remote/mandatory/loading/DeserializeEncodedURLTest.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4924683
+ * @summary Check RMI/JRMP stubs can be deserialized using user's loader
+ * @author Eamonn McManus
+ * @run clean DeserializeEncodedURLTest SingleClassLoader
+ * @run build DeserializeEncodedURLTest SingleClassLoader
+ * @run main DeserializeEncodedURLTest
+ */
+
+import java.io.*;
+import java.rmi.*;
+import java.util.*;
+import javax.management.*;
+import javax.management.remote.*;
+import javax.management.remote.rmi.*;
+
+/*
+ Test that the RMI connector client can handle a URL of the form
+ where the serialized RMIServer stub is encoded directly in the URL,
+ when the class of that stub is known to the supplied
+ DEFAULT_CLASS_LOADER but not to the calling code's class loader.
+ This is an unusual usage, and is not explicitly specified in the JMX
+ Remote API, but it is potentially useful where client and server
+ agree to a code base for mutant stubs (that e.g. use a different
+ protocol or include debugging or optimization).
+
+ We make an RMI connector server by giving it an instance of an
+ RMIJRMPServerImpl subclass that manufactures mutant stubs. These
+ stubs are known to a special loader (mutantLoader) but not to this
+ test's loader. We set up the client's default loader to
+ mutantLoader, and check that it can deserialize the stub containing
+ the mutant stub.
+
+ This test incidentally creates the connector server as an MBean
+ rather than using the JMXConnectorServerFactory, just because I'm
+ not sure we have coverage of that elsewhere.
+*/
+public class DeserializeEncodedURLTest {
+ private static final ClassLoader mutantLoader =
+ new SingleClassLoader("SubMutantRMIServerStub",
+ MutantRMIServerStub.class,
+ MutantRMIServerStub.class.getClassLoader());
+ private static final Class subMutantRMIServerStubClass;
+ static {
+ try {
+ subMutantRMIServerStubClass =
+ mutantLoader.loadClass("SubMutantRMIServerStub");
+ } catch (ClassNotFoundException e) {
+ throw new Error(e);
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("Check that we can deserialize a mutant stub " +
+ "from an RMI connector URL even when the stub's " +
+ "class is known to the user's default loader " +
+ "but not the caller's loader");
+
+ System.out.println("Create RMI connector server as an MBean");
+
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ ObjectName csName = new ObjectName("test:type=RMIConnectorServer");
+ JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
+ RMIServerImpl impl = new MutantRMIServerImpl();
+ mbs.createMBean("javax.management.remote.rmi.RMIConnectorServer",
+ csName,
+ new Object[] {url, null, impl, null},
+ new String[] {JMXServiceURL.class.getName(),
+ Map.class.getName(),
+ RMIServerImpl.class.getName(),
+ MBeanServer.class.getName()});
+ mbs.invoke(csName, "start", new Object[0], new String[0]);
+
+ JMXServiceURL address =
+ (JMXServiceURL) mbs.getAttribute(csName, "Address");
+
+ System.out.println("Address with mutant stub: " + address);
+
+ Map env = new HashMap();
+ env.put(JMXConnectorFactory.DEFAULT_CLASS_LOADER, mutantLoader);
+ JMXConnector conn = JMXConnectorFactory.newJMXConnector(address, env);
+
+ System.out.println("Client successfully created with this address");
+ System.out.println("Try to connect newly-created client");
+
+ try {
+ conn.connect();
+ System.out.println("TEST FAILS: Connect worked but should not " +
+ "have");
+ System.exit(1);
+ } catch (MutantException e) {
+ System.out.println("Caught MutantException as expected");
+ } catch (Exception e) {
+ System.out.println("TEST FAILS: Caught unexpected exception:");
+ e.printStackTrace(System.out);
+ System.exit(1);
+ }
+
+ mbs.invoke(csName, "stop", new Object[0], new String[0]);
+ System.out.println("Test passed");
+ }
+
+ private static class MutantException extends IOException {}
+
+ public static class MutantRMIServerStub
+ implements RMIServer, Serializable {
+ public MutantRMIServerStub() {}
+
+ public String getVersion() {
+ return "1.0 BOGUS";
+ }
+
+ public RMIConnection newClient(Object credentials) throws IOException {
+ throw new MutantException();
+ }
+ }
+
+ private static class MutantRMIServerImpl extends RMIJRMPServerImpl {
+ public MutantRMIServerImpl() throws IOException {
+ super(0, null, null, null);
+ }
+
+ public Remote toStub() throws IOException {
+ try {
+ return (Remote) subMutantRMIServerStubClass.newInstance();
+ } catch (Exception e) {
+ IOException ioe =
+ new IOException("Couldn't make submutant stub");
+ ioe.initCause(e);
+ throw ioe;
+ }
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/loading/MethodResultTest.java b/test/javax/management/remote/mandatory/loading/MethodResultTest.java
new file mode 100644
index 0000000..c4b9a57
--- /dev/null
+++ b/test/javax/management/remote/mandatory/loading/MethodResultTest.java
@@ -0,0 +1,333 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4898478
+ * @summary Tests client default class loader used before JSR 160 loader
+ * @author Eamonn McManus
+ * @run clean MethodResultTest
+ * @run build MethodResultTest
+ * @run main MethodResultTest
+ */
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import javax.management.*;
+import javax.management.remote.*;
+
+/*
+ This test checks that the class loader that is used to deserialize
+ the return values from remote MBean server operations is indeed the
+ one specified by the user. The only MBean server operations that
+ matter are those than can return an arbitrary Object. We don't
+ care about getMBeanCount or queryNames or whatever because their
+ return values are always of classes loaded by the bootstrap loader.
+ But for the operations getAttribute, getAttributes, setAttributes,
+ and invoke, the return value can include any Java class. This is
+ also true of getMBeanInfo, since the return value can be an exotic
+ subclass of MBeanInfo, or a ModelMBeanInfo that refers to an
+ arbitrary Object. The JMX Remote API spec requires that these
+ return values be deserialized using the class loader supplied by
+ the user (default is context class loader). In particular it must
+ not be deserialized using the system class loader, which it will be
+ with RMI unless special precautions are taken.
+ */
+public class MethodResultTest {
+ public static void main(String[] args) throws Exception {
+ Class thisClass = MethodResultTest.class;
+ Class exoticClass = Exotic.class;
+ String exoticClassName = Exotic.class.getName();
+ ClassLoader testClassLoader = thisClass.getClassLoader();
+ if (!(testClassLoader instanceof URLClassLoader)) {
+ System.out.println("TEST INVALID: Not loaded by a " +
+ "URLClassLoader: " + testClassLoader);
+ System.exit(1);
+ }
+
+ URLClassLoader tcl = (URLClassLoader) testClassLoader;
+ URL[] urls = tcl.getURLs();
+ ClassLoader shadowLoader =
+ new ShadowLoader(urls, testClassLoader,
+ new String[] {exoticClassName,
+ ExoticMBeanInfo.class.getName(),
+ ExoticException.class.getName()});
+ Class cl = shadowLoader.loadClass(exoticClassName);
+ if (cl == exoticClass) {
+ System.out.println("TEST INVALID: Shadow class loader loaded " +
+ "same class as test class loader");
+ System.exit(1);
+ }
+ Thread.currentThread().setContextClassLoader(shadowLoader);
+
+ ObjectName on = new ObjectName("a:b=c");
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ mbs.createMBean(Thing.class.getName(), on);
+
+ final String[] protos = {"rmi", "iiop", "jmxmp"};
+
+ boolean ok = true;
+ for (int i = 0; i < protos.length; i++) {
+ try {
+ ok &= test(protos[i], mbs, on);
+ System.out.println();
+ } catch (Exception e) {
+ System.out.println("TEST FAILED WITH EXCEPTION:");
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+ }
+
+ if (ok)
+ System.out.println("Test passed");
+ else {
+ System.out.println("TEST FAILED");
+ System.exit(1);
+ }
+ }
+
+ private static boolean test(String proto, MBeanServer mbs, ObjectName on)
+ throws Exception {
+ System.out.println("Testing for protocol " + proto);
+
+ JMXConnectorServer cs;
+ JMXServiceURL url = new JMXServiceURL(proto, null, 0);
+ try {
+ cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null,
+ mbs);
+ } catch (MalformedURLException e) {
+ System.out.println("System does not recognize URL: " + url +
+ "; ignoring");
+ return true;
+ }
+ cs.start();
+ JMXServiceURL addr = cs.getAddress();
+ JMXConnector client = JMXConnectorFactory.connect(addr);
+ MBeanServerConnection mbsc = client.getMBeanServerConnection();
+ Object getAttributeExotic = mbsc.getAttribute(on, "Exotic");
+ AttributeList getAttrs =
+ mbsc.getAttributes(on, new String[] {"Exotic"});
+ AttributeList setAttrs = new AttributeList();
+ setAttrs.add(new Attribute("Exotic", new Exotic()));
+ setAttrs = mbsc.setAttributes(on, setAttrs);
+ Object invokeExotic =
+ mbsc.invoke(on, "anExotic", new Object[] {}, new String[] {});
+ MBeanInfo exoticMBI = mbsc.getMBeanInfo(on);
+
+ mbsc.setAttribute(on, new Attribute("Exception", Boolean.TRUE));
+ Exception
+ getAttributeException, setAttributeException, invokeException;
+ try {
+ try {
+ mbsc.getAttribute(on, "Exotic");
+ throw noException("getAttribute");
+ } catch (Exception e) {
+ getAttributeException = e;
+ }
+ try {
+ mbsc.setAttribute(on, new Attribute("Exotic", new Exotic()));
+ throw noException("setAttribute");
+ } catch (Exception e) {
+ setAttributeException = e;
+ }
+ try {
+ mbsc.invoke(on, "anExotic", new Object[] {}, new String[] {});
+ throw noException("invoke");
+ } catch (Exception e) {
+ invokeException = e;
+ }
+ } finally {
+ mbsc.setAttribute(on, new Attribute("Exception", Boolean.FALSE));
+ }
+ client.close();
+ cs.stop();
+
+ boolean ok = true;
+
+ ok &= checkAttrs("getAttributes", getAttrs);
+ ok &= checkAttrs("setAttributes", setAttrs);
+
+ ok &= checkType("getAttribute", getAttributeExotic, Exotic.class);
+ ok &= checkType("getAttributes", attrValue(getAttrs), Exotic.class);
+ ok &= checkType("setAttributes", attrValue(setAttrs), Exotic.class);
+ ok &= checkType("invoke", invokeExotic, Exotic.class);
+ ok &= checkType("getMBeanInfo", exoticMBI, ExoticMBeanInfo.class);
+
+ ok &= checkExceptionType("getAttribute", getAttributeException,
+ ExoticException.class);
+ ok &= checkExceptionType("setAttribute", setAttributeException,
+ ExoticException.class);
+ ok &= checkExceptionType("invoke", invokeException,
+ ExoticException.class);
+
+ if (ok)
+ System.out.println("Test passes for protocol " + proto);
+ return ok;
+ }
+
+ private static Exception noException(String what) {
+ final String msg =
+ "Operation " + what + " returned when exception expected";
+ return new IllegalStateException(msg);
+ }
+
+ private static Object attrValue(AttributeList attrs) {
+ return ((Attribute) attrs.get(0)).getValue();
+ }
+
+ private static boolean checkType(String what, Object object,
+ Class wrongClass) {
+ return checkType(what, object, wrongClass, false);
+ }
+
+ private static boolean checkType(String what, Object object,
+ Class wrongClass, boolean isException) {
+ final String type = isException ? "exception" : "object";
+ final String rendered = isException ? "thrown" : "returned";
+ System.out.println("For " + type + " " + rendered + " by " + what +
+ ":");
+ if (wrongClass.isInstance(object)) {
+ System.out.println("TEST FAILS: " + type + " loaded by test " +
+ "classloader");
+ return false;
+ }
+ String className = object.getClass().getName();
+ if (!className.equals(wrongClass.getName())) {
+ System.out.println("TEST FAILS: " + rendered + " " + type +
+ " has wrong class name: " + className);
+ return false;
+ }
+ System.out.println("Test passes: " + rendered + " " + type +
+ " has same class name but is not same class");
+ return true;
+ }
+
+ private static boolean checkExceptionType(String what, Exception exception,
+ Class wrongClass) {
+ if (!(exception instanceof MBeanException)) {
+ System.out.println("Exception thrown by " + what + " is not an " +
+ MBeanException.class.getName() +
+ ":");
+ exception.printStackTrace(System.out);
+ return false;
+ }
+
+ exception = ((MBeanException) exception).getTargetException();
+
+ return checkType(what, exception, wrongClass, true);
+ }
+
+ private static boolean checkAttrs(String what, AttributeList attrs) {
+ if (attrs.size() != 1) {
+ System.out.println("TEST FAILS: list returned by " + what +
+ " does not have size 1: " + attrs);
+ return false;
+ }
+ Attribute attr = (Attribute) attrs.get(0);
+ if (!"Exotic".equals(attr.getName())) {
+ System.out.println("TEST FAILS: " + what + " returned wrong " +
+ "attribute: " + attr);
+ return false;
+ }
+
+ return true;
+ }
+
+ public static class Thing
+ extends StandardMBean implements ThingMBean {
+ public Thing() throws NotCompliantMBeanException {
+ super(ThingMBean.class);
+ }
+
+ public Exotic getExotic() throws ExoticException {
+ if (exception)
+ throw new ExoticException();
+ return new Exotic();
+ }
+
+ public void setExotic(Exotic x) throws ExoticException {
+ if (exception)
+ throw new ExoticException();
+ }
+
+ public Exotic anExotic() throws ExoticException {
+ if (exception)
+ throw new ExoticException();
+ return new Exotic();
+ }
+
+ public void cacheMBeanInfo(MBeanInfo mbi) {
+ if (mbi != null)
+ mbi = new ExoticMBeanInfo(mbi);
+ super.cacheMBeanInfo(mbi);
+ }
+
+ public void setException(boolean x) {
+ this.exception = x;
+ }
+
+ private boolean exception;
+ }
+
+ public static interface ThingMBean {
+ public Exotic getExotic() throws ExoticException;
+ public void setExotic(Exotic x) throws ExoticException;
+ public Exotic anExotic() throws ExoticException;
+ public void setException(boolean x);
+ }
+
+ public static class Exotic implements Serializable {}
+
+ public static class ExoticException extends Exception {}
+
+ public static class ExoticMBeanInfo extends MBeanInfo {
+ public ExoticMBeanInfo(MBeanInfo mbi) {
+ super(mbi.getClassName(),
+ mbi.getDescription(),
+ mbi.getAttributes(),
+ mbi.getConstructors(),
+ mbi.getOperations(),
+ mbi.getNotifications());
+ }
+ }
+
+ private static class ShadowLoader extends URLClassLoader {
+ ShadowLoader(URL[] urls, ClassLoader realLoader,
+ String[] shadowClassNames) {
+ super(urls, null);
+ this.realLoader = realLoader;
+ this.shadowClassNames = Arrays.asList(shadowClassNames);
+ }
+
+ protected Class findClass(String name) throws ClassNotFoundException {
+ if (shadowClassNames.contains(name))
+ return super.findClass(name);
+ else
+ return realLoader.loadClass(name);
+ }
+
+ private final ClassLoader realLoader;
+ private final List shadowClassNames;
+ }
+}
diff --git a/test/javax/management/remote/mandatory/loading/MissingClassTest.java b/test/javax/management/remote/mandatory/loading/MissingClassTest.java
new file mode 100644
index 0000000..7aab830
--- /dev/null
+++ b/test/javax/management/remote/mandatory/loading/MissingClassTest.java
@@ -0,0 +1,646 @@
+/*
+ * Copyright 2003-2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4915825 4921009 4934965 4977469
+ * @summary Tests behavior when client or server gets object of unknown class
+ * @author Eamonn McManus
+ * @run clean MissingClassTest SingleClassLoader
+ * @run build MissingClassTest SingleClassLoader
+ * @run main MissingClassTest
+ */
+
+/*
+ Tests that clients and servers react correctly when they receive
+ objects of unknown classes. This can happen easily due to version
+ skew or missing jar files on one end or the other. The default
+ behaviour of causing a connection to die because of the resultant
+ IOException is not acceptable! We try sending attributes and invoke
+ parameters to the server of classes it doesn't know, and we try
+ sending attributes, exceptions and notifications to the client of
+ classes it doesn't know.
+
+ We also test objects that are of known class but not serializable.
+ The test cases are similar.
+ */
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import javax.management.*;
+import javax.management.loading.*;
+import javax.management.remote.*;
+import javax.management.remote.rmi.RMIConnectorServer;
+
+public class MissingClassTest {
+ private static final int NNOTIFS = 50;
+
+ private static ClassLoader clientLoader, serverLoader;
+ private static Object serverUnknown;
+ private static Exception clientUnknown;
+ private static ObjectName on;
+ private static final Object[] NO_OBJECTS = new Object[0];
+ private static final String[] NO_STRINGS = new String[0];
+
+ private static final Object unserializableObject = Thread.currentThread();
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("Test that the client or server end of a " +
+ "connection does not fail if sent an object " +
+ "it cannot deserialize");
+
+ on = new ObjectName("test:type=Test");
+
+ ClassLoader testLoader = MissingClassTest.class.getClassLoader();
+ clientLoader =
+ new SingleClassLoader("$ServerUnknown$", HashMap.class,
+ testLoader);
+ serverLoader =
+ new SingleClassLoader("$ClientUnknown$", Exception.class,
+ testLoader);
+ serverUnknown =
+ clientLoader.loadClass("$ServerUnknown$").newInstance();
+ clientUnknown = (Exception)
+ serverLoader.loadClass("$ClientUnknown$").newInstance();
+
+ final String[] protos = {"rmi", /*"iiop",*/ "jmxmp"};
+ // iiop commented out until bug 4935098 is fixed
+ boolean ok = true;
+ for (int i = 0; i < protos.length; i++) {
+ try {
+ ok &= test(protos[i]);
+ } catch (Exception e) {
+ System.out.println("TEST FAILED WITH EXCEPTION:");
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+ }
+
+ if (ok)
+ System.out.println("Test passed");
+ else {
+ System.out.println("TEST FAILED");
+ System.exit(1);
+ }
+ }
+
+ private static boolean test(String proto) throws Exception {
+ System.out.println("Testing for proto " + proto);
+
+ boolean ok = true;
+
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ mbs.createMBean(Test.class.getName(), on);
+
+ JMXConnectorServer cs;
+ JMXServiceURL url = new JMXServiceURL(proto, null, 0);
+ Map serverMap = new HashMap();
+ serverMap.put(JMXConnectorServerFactory.DEFAULT_CLASS_LOADER,
+ serverLoader);
+
+ // make sure no auto-close at server side
+ serverMap.put("jmx.remote.x.server.connection.timeout", "888888888");
+
+ try {
+ cs = JMXConnectorServerFactory.newJMXConnectorServer(url,
+ serverMap,
+ mbs);
+ } catch (MalformedURLException e) {
+ System.out.println("System does not recognize URL: " + url +
+ "; ignoring");
+ return true;
+ }
+ cs.start();
+ JMXServiceURL addr = cs.getAddress();
+ Map clientMap = new HashMap();
+ clientMap.put(JMXConnectorFactory.DEFAULT_CLASS_LOADER,
+ clientLoader);
+
+ System.out.println("Connecting for client-unknown test");
+
+ JMXConnector client = JMXConnectorFactory.connect(addr, clientMap);
+
+ // add a listener to verify no failed notif
+ CNListener cnListener = new CNListener();
+ client.addConnectionNotificationListener(cnListener, null, null);
+
+ MBeanServerConnection mbsc = client.getMBeanServerConnection();
+
+ System.out.println("Getting attribute with class unknown to client");
+ try {
+ Object result = mbsc.getAttribute(on, "ClientUnknown");
+ System.out.println("TEST FAILS: getAttribute for class " +
+ "unknown to client should fail, returned: " +
+ result);
+ ok = false;
+ } catch (IOException e) {
+ Throwable cause = e.getCause();
+ if (cause instanceof ClassNotFoundException) {
+ System.out.println("Success: got an IOException wrapping " +
+ "a ClassNotFoundException");
+ } else {
+ System.out.println("TEST FAILS: Caught IOException (" + e +
+ ") but cause should be " +
+ "ClassNotFoundException: " + cause);
+ ok = false;
+ }
+ }
+
+ System.out.println("Doing queryNames to ensure connection alive");
+ Set names = mbsc.queryNames(null, null);
+ System.out.println("queryNames returned " + names);
+
+ System.out.println("Provoke exception of unknown class");
+ try {
+ mbsc.invoke(on, "throwClientUnknown", NO_OBJECTS, NO_STRINGS);
+ System.out.println("TEST FAILS: did not get exception");
+ ok = false;
+ } catch (IOException e) {
+ Throwable wrapped = e.getCause();
+ if (wrapped instanceof ClassNotFoundException) {
+ System.out.println("Success: got an IOException wrapping " +
+ "a ClassNotFoundException: " +
+ wrapped);
+ } else {
+ System.out.println("TEST FAILS: Got IOException but cause " +
+ "should be ClassNotFoundException: ");
+ if (wrapped == null)
+ System.out.println("(null)");
+ else
+ wrapped.printStackTrace(System.out);
+ ok = false;
+ }
+ } catch (Exception e) {
+ System.out.println("TEST FAILS: Got wrong exception: " +
+ "should be IOException with cause " +
+ "ClassNotFoundException:");
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+
+ System.out.println("Doing queryNames to ensure connection alive");
+ names = mbsc.queryNames(null, null);
+ System.out.println("queryNames returned " + names);
+
+ ok &= notifyTest(client, mbsc);
+
+ System.out.println("Doing queryNames to ensure connection alive");
+ names = mbsc.queryNames(null, null);
+ System.out.println("queryNames returned " + names);
+
+ for (int i = 0; i < 2; i++) {
+ boolean setAttribute = (i == 0); // else invoke
+ String what = setAttribute ? "setAttribute" : "invoke";
+ System.out.println("Trying " + what +
+ " with class unknown to server");
+ try {
+ if (setAttribute) {
+ mbsc.setAttribute(on, new Attribute("ServerUnknown",
+ serverUnknown));
+ } else {
+ mbsc.invoke(on, "useServerUnknown",
+ new Object[] {serverUnknown},
+ new String[] {"java.lang.Object"});
+ }
+ System.out.println("TEST FAILS: " + what + " with " +
+ "class unknown to server should fail " +
+ "but did not");
+ ok = false;
+ } catch (IOException e) {
+ Throwable cause = e.getCause();
+ if (cause instanceof ClassNotFoundException) {
+ System.out.println("Success: got an IOException " +
+ "wrapping a ClassNotFoundException");
+ } else {
+ System.out.println("TEST FAILS: Caught IOException (" + e +
+ ") but cause should be " +
+ "ClassNotFoundException: " + cause);
+ e.printStackTrace(System.out); // XXX
+ ok = false;
+ }
+ }
+ }
+
+ System.out.println("Doing queryNames to ensure connection alive");
+ names = mbsc.queryNames(null, null);
+ System.out.println("queryNames returned " + names);
+
+ System.out.println("Trying to get unserializable attribute");
+ try {
+ mbsc.getAttribute(on, "Unserializable");
+ System.out.println("TEST FAILS: get unserializable worked " +
+ "but should not");
+ ok = false;
+ } catch (IOException e) {
+ System.out.println("Success: got an IOException: " + e +
+ " (cause: " + e.getCause() + ")");
+ }
+
+ System.out.println("Doing queryNames to ensure connection alive");
+ names = mbsc.queryNames(null, null);
+ System.out.println("queryNames returned " + names);
+
+ System.out.println("Trying to set unserializable attribute");
+ try {
+ Attribute attr =
+ new Attribute("Unserializable", unserializableObject);
+ mbsc.setAttribute(on, attr);
+ System.out.println("TEST FAILS: set unserializable worked " +
+ "but should not");
+ ok = false;
+ } catch (IOException e) {
+ System.out.println("Success: got an IOException: " + e +
+ " (cause: " + e.getCause() + ")");
+ }
+
+ System.out.println("Doing queryNames to ensure connection alive");
+ names = mbsc.queryNames(null, null);
+ System.out.println("queryNames returned " + names);
+
+ System.out.println("Trying to throw unserializable exception");
+ try {
+ mbsc.invoke(on, "throwUnserializable", NO_OBJECTS, NO_STRINGS);
+ System.out.println("TEST FAILS: throw unserializable worked " +
+ "but should not");
+ ok = false;
+ } catch (IOException e) {
+ System.out.println("Success: got an IOException: " + e +
+ " (cause: " + e.getCause() + ")");
+ }
+
+ client.removeConnectionNotificationListener(cnListener);
+ ok = ok && !cnListener.failed;
+
+ client.close();
+ cs.stop();
+
+ if (ok)
+ System.out.println("Test passed for protocol " + proto);
+
+ System.out.println();
+ return ok;
+ }
+
+ private static class TestListener implements NotificationListener {
+ TestListener(LostListener ll) {
+ this.lostListener = ll;
+ }
+
+ public void handleNotification(Notification n, Object h) {
+ /* Connectors can handle unserializable notifications in
+ one of two ways. Either they can arrange for the
+ client to get a NotSerializableException from its
+ fetchNotifications call (RMI connector), or they can
+ replace the unserializable notification by a
+ JMXConnectionNotification.NOTIFS_LOST (JMXMP
+ connector). The former case is handled by code within
+ the connector client which will end up sending a
+ NOTIFS_LOST to our LostListener. The logic here
+ handles the latter case by converting it into the
+ former.
+ */
+ if (n instanceof JMXConnectionNotification
+ && n.getType().equals(JMXConnectionNotification.NOTIFS_LOST)) {
+ lostListener.handleNotification(n, h);
+ return;
+ }
+
+ synchronized (result) {
+ if (!n.getType().equals("interesting")
+ || !n.getUserData().equals("known")) {
+ System.out.println("TestListener received strange notif: "
+ + notificationString(n));
+ result.failed = true;
+ result.notifyAll();
+ } else {
+ result.knownCount++;
+ if (result.knownCount == NNOTIFS)
+ result.notifyAll();
+ }
+ }
+ }
+
+ private LostListener lostListener;
+ }
+
+ private static class LostListener implements NotificationListener {
+ public void handleNotification(Notification n, Object h) {
+ synchronized (result) {
+ handle(n, h);
+ }
+ }
+
+ private void handle(Notification n, Object h) {
+ if (!(n instanceof JMXConnectionNotification)) {
+ System.out.println("LostListener received strange notif: " +
+ notificationString(n));
+ result.failed = true;
+ result.notifyAll();
+ return;
+ }
+
+ JMXConnectionNotification jn = (JMXConnectionNotification) n;
+ if (!jn.getType().equals(jn.NOTIFS_LOST)) {
+ System.out.println("Ignoring JMXConnectionNotification: " +
+ notificationString(jn));
+ return;
+ }
+ final String msg = jn.getMessage();
+ if ((!msg.startsWith("Dropped ")
+ || !msg.endsWith("classes were missing locally"))
+ && (!msg.startsWith("Not serializable: "))) {
+ System.out.println("Surprising NOTIFS_LOST getMessage: " +
+ msg);
+ }
+ if (!(jn.getUserData() instanceof Long)) {
+ System.out.println("JMXConnectionNotification userData " +
+ "not a Long: " + jn.getUserData());
+ result.failed = true;
+ } else {
+ int lost = ((Long) jn.getUserData()).intValue();
+ result.lostCount += lost;
+ if (result.lostCount == NNOTIFS*2)
+ result.notifyAll();
+ }
+ }
+ }
+
+ private static class TestFilter implements NotificationFilter {
+ public boolean isNotificationEnabled(Notification n) {
+ return (n.getType().equals("interesting"));
+ }
+ }
+
+ private static class Result {
+ int knownCount, lostCount;
+ boolean failed;
+ }
+ private static Result result;
+
+ /* Send a bunch of notifications to exercise the logic to recover
+ from unknown notification classes. We have four kinds of
+ notifications: "known" ones are of a class known to the client
+ and which match its filters; "unknown" ones are of a class that
+ match the client's filters but that the client can't load;
+ "tricky" ones are unserializable; and "boring" notifications
+ are of a class that the client knows but that doesn't match its
+ filters. We emit NNOTIFS notifications of each kind. We do a
+ random shuffle on these 4*NNOTIFS notifications so it is likely
+ that we will cover the various different cases in the logic.
+
+ Specifically, what we are testing here is the logic that
+ recovers from a fetchNotifications request that gets a
+ ClassNotFoundException. Because the request can contain
+ several notifications, the client doesn't know which of them
+ generated the exception. So it redoes a request that asks for
+ just one notification. We need to be sure that this works when
+ that one notification is of an unknown class and when it is of
+ a known class, and in both cases when there are filtered
+ notifications that are skipped.
+
+ We are also testing the behaviour in the server when it tries
+ to include an unserializable notification in the response to a
+ fetchNotifications, and in the client when that happens.
+
+ If the test succeeds, the listener should receive the NNOTIFS
+ "known" notifications, and the connection listener should
+ receive an indication of NNOTIFS lost notifications
+ representing the "unknown" notifications.
+
+ We depend on some implementation-specific features here:
+
+ 1. The buffer size is sufficient to contain the 4*NNOTIFS
+ notifications which are all sent at once, before the client
+ gets a chance to start receiving them.
+
+ 2. When one or more notifications are dropped because they are
+ of unknown classes, the NOTIFS_LOST notification contains a
+ userData that is a Long with a count of the number dropped.
+
+ 3. If a notification is not serializable on the server, the
+ client gets told about it somehow, rather than having it just
+ dropped on the floor. The somehow might be through an RMI
+ exception, or it might be by the server replacing the
+ unserializable notif by a JMXConnectionNotification.NOTIFS_LOST.
+ */
+ private static boolean notifyTest(JMXConnector client,
+ MBeanServerConnection mbsc)
+ throws Exception {
+ System.out.println("Send notifications including unknown ones");
+ result = new Result();
+ LostListener ll = new LostListener();
+ client.addConnectionNotificationListener(ll, null, null);
+ TestListener nl = new TestListener(ll);
+ mbsc.addNotificationListener(on, nl, new TestFilter(), null);
+ mbsc.invoke(on, "sendNotifs", NO_OBJECTS, NO_STRINGS);
+
+ // wait for the listeners to receive all their notifs
+ // or to fail
+ long deadline = System.currentTimeMillis() + 60000;
+ long remain;
+ while ((remain = deadline - System.currentTimeMillis()) >= 0) {
+ synchronized (result) {
+ if (result.failed
+ || (result.knownCount == NNOTIFS
+ && result.lostCount == NNOTIFS*2))
+ break;
+ result.wait(remain);
+ }
+ }
+ if (result.failed) {
+ System.out.println("TEST FAILS: Notification strangeness");
+ return false;
+ } else if (result.knownCount == NNOTIFS
+ && result.lostCount == NNOTIFS*2) {
+ System.out.println("Success: received known notifications and " +
+ "got NOTIFS_LOST for unknown and " +
+ "unserializable ones");
+ return true;
+ } else {
+ System.out.println("TEST FAILS: Timed out without receiving " +
+ "all notifs: known=" + result.knownCount +
+ "; lost=" + result.lostCount);
+ return false;
+ }
+ }
+
+ public static interface TestMBean {
+ public Object getClientUnknown() throws Exception;
+ public void throwClientUnknown() throws Exception;
+ public void setServerUnknown(Object o) throws Exception;
+ public void useServerUnknown(Object o) throws Exception;
+ public Object getUnserializable() throws Exception;
+ public void setUnserializable(Object un) throws Exception;
+ public void throwUnserializable() throws Exception;
+ public void sendNotifs() throws Exception;
+ }
+
+ public static class Test extends NotificationBroadcasterSupport
+ implements TestMBean {
+
+ public Object getClientUnknown() {
+ return clientUnknown;
+ }
+
+ public void throwClientUnknown() throws Exception {
+ throw clientUnknown;
+ }
+
+ public void setServerUnknown(Object o) {
+ throw new IllegalArgumentException("setServerUnknown succeeded "+
+ "but should not have");
+ }
+
+ public void useServerUnknown(Object o) {
+ throw new IllegalArgumentException("useServerUnknown succeeded "+
+ "but should not have");
+ }
+
+ public Object getUnserializable() {
+ return unserializableObject;
+ }
+
+ public void setUnserializable(Object un) {
+ throw new IllegalArgumentException("setUnserializable succeeded " +
+ "but should not have");
+ }
+
+ public void throwUnserializable() throws Exception {
+ throw new Exception() {
+ private Object unserializable = unserializableObject;
+ };
+ }
+
+ public void sendNotifs() {
+ /* We actually send the same four notification objects
+ NNOTIFS times each. This doesn't particularly matter,
+ but note that the MBeanServer will replace "this" by
+ the sender's ObjectName the first time. Since that's
+ always the same, no problem. */
+ Notification known =
+ new Notification("interesting", this, 1L, 1L, "known");
+ known.setUserData("known");
+ Notification unknown =
+ new Notification("interesting", this, 1L, 1L, "unknown");
+ unknown.setUserData(clientUnknown);
+ Notification boring =
+ new Notification("boring", this, 1L, 1L, "boring");
+ Notification tricky =
+ new Notification("interesting", this, 1L, 1L, "tricky");
+ tricky.setUserData(unserializableObject);
+
+ // check that the tricky notif is indeed unserializable
+ try {
+ new ObjectOutputStream(new ByteArrayOutputStream())
+ .writeObject(tricky);
+ System.out.println("TEST INCORRECT: tricky notif is " +
+ "serializable");
+ System.exit(1);
+ } catch (NotSerializableException e) {
+ // OK: tricky notif is not serializable
+ } catch (IOException e) {
+ System.out.println("TEST INCORRECT: tricky notif " +
+ "serialization check failed");
+ System.exit(1);
+ }
+
+ /* Now shuffle an imaginary deck of cards where K, U, T, and
+ B (known, unknown, tricky, boring) each appear NNOTIFS times.
+ We explicitly seed the random number generator so we
+ can reproduce rare test failures if necessary. We only
+ use a StringBuffer so we can print the shuffled deck --
+ otherwise we could just emit the notifications as the
+ cards are placed. */
+ long seed = System.currentTimeMillis();
+ System.out.println("Random number seed is " + seed);
+ Random r = new Random(seed);
+ int knownCount = NNOTIFS; // remaining K cards
+ int unknownCount = NNOTIFS; // remaining U cards
+ int trickyCount = NNOTIFS; // remaining T cards
+ int boringCount = NNOTIFS; // remaining B cards
+ StringBuffer notifList = new StringBuffer();
+ for (int i = NNOTIFS * 4; i > 0; i--) {
+ int rand = r.nextInt(i);
+ // use rand to pick a card from the remaining ones
+ if ((rand -= knownCount) < 0) {
+ notifList.append('k');
+ knownCount--;
+ } else if ((rand -= unknownCount) < 0) {
+ notifList.append('u');
+ unknownCount--;
+ } else if ((rand -= trickyCount) < 0) {
+ notifList.append('t');
+ trickyCount--;
+ } else {
+ notifList.append('b');
+ boringCount--;
+ }
+ }
+ if (knownCount != 0 || unknownCount != 0
+ || trickyCount != 0 || boringCount != 0) {
+ System.out.println("TEST INCORRECT: Shuffle failed: " +
+ "known=" + knownCount +" unknown=" +
+ unknownCount + " tricky=" + trickyCount +
+ " boring=" + boringCount +
+ " deal=" + notifList);
+ System.exit(1);
+ }
+ String notifs = notifList.toString();
+ System.out.println("Shuffle: " + notifs);
+ for (int i = 0; i < NNOTIFS * 4; i++) {
+ Notification n;
+ switch (notifs.charAt(i)) {
+ case 'k': n = known; break;
+ case 'u': n = unknown; break;
+ case 't': n = tricky; break;
+ case 'b': n = boring; break;
+ default:
+ System.out.println("TEST INCORRECT: Bad shuffle char: " +
+ notifs.charAt(i));
+ System.exit(1);
+ throw new Error();
+ }
+ sendNotification(n);
+ }
+ }
+ }
+
+ private static String notificationString(Notification n) {
+ return n.getClass().getName() + "/" + n.getType() + " \"" +
+ n.getMessage() + "\" <" + n.getUserData() + ">";
+ }
+
+ //
+ private static class CNListener implements NotificationListener {
+ public void handleNotification(Notification n, Object o) {
+ if (n instanceof JMXConnectionNotification) {
+ JMXConnectionNotification jn = (JMXConnectionNotification)n;
+ if (JMXConnectionNotification.FAILED.equals(jn.getType())) {
+ failed = true;
+ }
+ }
+ }
+
+ public boolean failed = false;
+ }
+}
diff --git a/test/javax/management/remote/mandatory/loading/RMIDownloadTest.java b/test/javax/management/remote/mandatory/loading/RMIDownloadTest.java
new file mode 100644
index 0000000..1c36f18
--- /dev/null
+++ b/test/javax/management/remote/mandatory/loading/RMIDownloadTest.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5021246
+ * @summary Check that class downloading is supported by RMI connector
+ * @author Eamonn McManus
+ * @run main RMIDownloadTest receive without
+ * @run main RMIDownloadTest send without
+ * @run main RMIDownloadTest receive with
+ * @run main RMIDownloadTest send with
+ */
+
+/*
+ * This test checks that class downloading is supported by the RMI connector.
+ * We copy a precompiled class file into the temporary directory (which we
+ * assume is not in the classpath). We also create an instance of that
+ * class using a hardcoded ClassLoader. Then we try to get a remote attribute
+ * that returns that instance, and we try to set the remote attribute to the
+ * instance. In both cases, this will only work if the class can be downloaded
+ * based on the codebase that we have set to the temporary directory. We also
+ * test that it does *not* work when the codebase is not set, in case the test
+ * is succeeding for some other reason.
+ *
+ * We run the test four times, for each combination of (send, receive) x
+ * (with-codebase, without-codebase). Doing all four tests within the same
+ * run doesn't work, probably because RMI remembers the codebase property
+ * setting at some point.
+ */
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.lang.management.ManagementFactory;
+import java.net.URL;
+import java.security.Permission;
+import java.util.Arrays;
+import javax.management.Attribute;
+import javax.management.MBeanServer;
+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 RMIDownloadTest {
+ /* Following byte array was produced from this class:
+ *
+ * public class Zooby implements java.io.Serializable {}
+ *
+ * by this program:
+ *
+ * public class MakeZooby {
+ * public static void main(String[] args) throws Exception {
+ * int b;
+ * for (int offset = 0; (b = System.in.read()) >= 0; offset++) {
+ * System.out.print((byte) b + "," +
+ * ((offset % 16) == 15 ? '\n' : ' '));
+ * }
+ * System.out.println();
+ * }
+ * }
+ */
+ private static final byte[] zoobyClassBytes = {
+ -54, -2, -70, -66, 0, 0, 0, 49, 0, 12, 10, 0, 3, 0, 8, 7,
+ 0, 9, 7, 0, 10, 7, 0, 11, 1, 0, 6, 60, 105, 110, 105, 116,
+ 62, 1, 0, 3, 40, 41, 86, 1, 0, 4, 67, 111, 100, 101, 12, 0,
+ 5, 0, 6, 1, 0, 5, 90, 111, 111, 98, 121, 1, 0, 16, 106, 97,
+ 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 1, 0,
+ 20, 106, 97, 118, 97, 47, 105, 111, 47, 83, 101, 114, 105, 97, 108, 105,
+ 122, 97, 98, 108, 101, 0, 33, 0, 2, 0, 3, 0, 1, 0, 4, 0,
+ 0, 0, 1, 0, 1, 0, 5, 0, 6, 0, 1, 0, 7, 0, 0, 0,
+ 17, 0, 1, 0, 1, 0, 0, 0, 5, 42, -73, 0, 1, -79, 0, 0,
+ 0, 0, 0, 0,
+ };
+
+ private static class ZoobyClassLoader extends ClassLoader {
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ if (name.equals("Zooby")) {
+ return super.defineClass(name, zoobyClassBytes,
+ 0, zoobyClassBytes.length);
+ } else
+ throw new ClassNotFoundException(name);
+ }
+ }
+
+
+ private static MBeanServer pmbs;
+ private static ObjectName getSetName;
+ private static GetSet getSetInstance;
+
+ public static void main(String[] args) throws Exception {
+ int sendIndex = -1;
+ int withIndex = -1;
+ if (args.length == 2) {
+ sendIndex =
+ Arrays.asList("send", "receive").indexOf(args[0]);
+ withIndex =
+ Arrays.asList("with", "without").indexOf(args[1]);
+ }
+ if (sendIndex < 0 || withIndex < 0)
+ throw new Exception("Usage: RMIDownloadTest (send|receive) (with|without)");
+ final boolean send = (sendIndex == 0);
+ final boolean with = (withIndex == 0);
+
+ pmbs = ManagementFactory.getPlatformMBeanServer();
+ getSetName = new ObjectName(":type=GetSet");
+ getSetInstance = new GetSet();
+ pmbs.registerMBean(getSetInstance, getSetName);
+
+ System.setSecurityManager(new LaidBackSecurityManager());
+
+// System.setProperty("sun.rmi.loader.logLevel", "VERBOSE");
+
+ String tmpdir = System.getProperty("java.io.tmpdir");
+ String classfile = tmpdir + File.separator + "Zooby.class";
+ File zoobyFile = new File(classfile);
+ zoobyFile.deleteOnExit();
+ OutputStream os = new FileOutputStream(zoobyFile);
+ for (byte b : zoobyClassBytes)
+ os.write(b);
+ os.close();
+
+ // Check that we can't load the Zooby class from the classpath
+ try {
+ Class.forName("Zooby");
+ throw new Exception("Class \"Zooby\" is in the classpath!");
+ } catch (ClassNotFoundException e) {
+ // OK: expected
+ }
+
+ if (send)
+ System.out.println("Testing we can send an object from client to server");
+ else
+ System.out.println("Testing we can receive an object from server to client");
+
+ if (with) {
+ // Test with the codebase property. Downloading should work.
+ URL zoobyURL = zoobyFile.getParentFile().toURI().toURL();
+ System.setProperty("java.rmi.server.codebase", zoobyURL.toString());
+ System.out.println("Testing with codebase, should work");
+ System.out.println("Codebase is " +
+ System.getProperty("java.rmi.server.codebase"));
+ test(send, true);
+ } else {
+ // Test without setting the codebase property.
+ // This should not work; if it does it probably means java.io.tmpdir
+ // is in the classpath.
+ System.out.println("Testing without codebase, should fail");
+ test(send, false);
+ }
+
+ }
+
+ private static void test(boolean send, boolean shouldWork) throws Exception {
+ try {
+ testWithException(send);
+ } catch (Exception e) {
+ if (shouldWork)
+ throw e;
+ System.out.println("Got exception as expected: " + e);
+ return;
+ }
+ if (!shouldWork)
+ throw new Exception("Test passed without codebase but should not");
+ }
+
+ private static void testWithException(boolean send)
+ throws Exception {
+ ClassLoader zoobyCL = new ZoobyClassLoader();
+ Class<?> zoobyClass = Class.forName("Zooby", false, zoobyCL);
+ Object zooby = zoobyClass.newInstance();
+
+ JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///");
+ JMXConnectorServer cs =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, null, pmbs);
+ cs.start();
+ JMXServiceURL addr = cs.getAddress();
+ JMXConnector cc = JMXConnectorFactory.connect(addr);
+ MBeanServerConnection mbsc = cc.getMBeanServerConnection();
+
+ Object rzooby;
+ if (send) {
+ System.out.println("Sending object...");
+ mbsc.setAttribute(getSetName, new Attribute("It", zooby));
+ rzooby = getSetInstance.getIt();
+ } else {
+ System.out.println("Receiving object...");
+ getSetInstance.setIt(zooby);
+ rzooby = mbsc.getAttribute(getSetName, "It");
+ }
+
+ if (!rzooby.getClass().getName().equals("Zooby")) {
+ throw new Exception("FAILED: remote object is not a Zooby");
+ }
+ if (rzooby.getClass().getClassLoader() ==
+ zooby.getClass().getClassLoader()) {
+ throw new Exception("FAILED: same class loader: " +
+ zooby.getClass().getClassLoader());
+ }
+
+ cc.close();
+ cs.stop();
+ }
+
+ public static interface GetSetMBean {
+ public Object getIt();
+ public void setIt(Object x);
+ }
+
+ public static class GetSet implements GetSetMBean {
+ public GetSet() {
+ }
+
+ public Object getIt() {
+ return what;
+ }
+
+ public void setIt(Object x) {
+ this.what = x;
+ }
+
+ private Object what;
+ }
+
+ public static class LaidBackSecurityManager extends SecurityManager {
+ public void checkPermission(Permission perm) {
+ // OK, dude
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/loading/SingleClassLoader.java b/test/javax/management/remote/mandatory/loading/SingleClassLoader.java
new file mode 100644
index 0000000..37cae97
--- /dev/null
+++ b/test/javax/management/remote/mandatory/loading/SingleClassLoader.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * build @BUILD_TAG_PLACEHOLDER@
+ *
+ * @COPYRIGHT_MINI_LEGAL_NOTICE_PLACEHOLDER@
+ */
+
+import java.io.*;
+import java.lang.reflect.*;
+
+/*
+ ClassLoader that knows how to fabricate exactly one class. The name
+ of the class is defined by the parameter singleClassName. When
+ asked to load a class, this loader first delegates to its parent as
+ usual, then, if that doesn't find the class and if the name is the
+ same as singleClassName, the class is fabricated. It is a public
+ class with no fields or methods and a single public no-arg
+ constructor that simply calls its parent's no-arg constructor. This
+ means that the parent must have a public or protected no-arg
+ constructor.
+ */
+public class SingleClassLoader extends ClassLoader {
+ SingleClassLoader(String singleClassName, Class superclass,
+ ClassLoader parent) {
+ super(parent);
+
+ Constructor superConstr;
+ try {
+ superConstr = superclass.getDeclaredConstructor(new Class[0]);
+ } catch (NoSuchMethodException e) {
+ throw new IllegalArgumentException("Superclass must have no-arg " +
+ "constructor");
+ }
+ int superConstrMods = superConstr.getModifiers();
+ if ((superConstrMods & (Modifier.PUBLIC|Modifier.PROTECTED)) == 0) {
+ final String msg =
+ "Superclass no-arg constructor must be public or protected";
+ throw new IllegalArgumentException(msg);
+ }
+
+ this.singleClassName = singleClassName;
+ final Class c;
+ try {
+ c = makeClass(superclass);
+ } catch (IOException e) {
+ throw new RuntimeException(e.toString());
+ }
+ this.singleClass = c;
+ }
+
+ private Class makeClass(Class superclass) throws IOException {
+ final String superName = superclass.getName();
+
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ dout = new DataOutputStream(bout);
+
+ String thisNameInternal = singleClassName.replace('.', '/');
+ String superNameInternal = superName.replace('.', '/');
+
+ dout.writeInt(0xcafebabe); // magic
+ dout.writeInt(0x0003002d); // major 45 minor 3
+ dout.writeShort(10); // cpool count (incl virtual 0 element)
+
+ cpoolIndex = 1;
+
+ int thisNameConst = writeUTFConst(thisNameInternal);
+ int thisClassConst = writeClassConst(thisNameConst);
+ int superNameConst = writeUTFConst(superNameInternal);
+ int superClassConst = writeClassConst(superNameConst);
+ int initNameConst = writeUTFConst("<init>");
+ int voidNoArgSigConst = writeUTFConst("()V");
+ int codeNameConst = writeUTFConst("Code");
+ int superConstructorNameAndTypeConst =
+ writeNameAndTypeConst(initNameConst, voidNoArgSigConst);
+ int superConstructorMethodRefConst =
+ writeMethodRefConst(superClassConst,
+ superConstructorNameAndTypeConst);
+
+ dout.writeShort(Modifier.PUBLIC | 0x20 /*SUPER*/);
+ dout.writeShort(thisClassConst);
+ dout.writeShort(superClassConst);
+ dout.writeInt(0); // n interfaces, n fields
+ dout.writeShort(1); // n methods
+
+ // <init> method
+ dout.writeShort(Modifier.PUBLIC);
+ dout.writeShort(initNameConst);
+ dout.writeShort(voidNoArgSigConst);
+ dout.writeShort(1); // attr count
+
+ // Code attribute
+ dout.writeShort(codeNameConst);
+ dout.writeInt(17); // len
+ dout.writeShort(1); // max stack
+ dout.writeShort(1); // max locals
+ dout.writeInt(5); // code len
+ dout.writeByte(42); // aload_0
+ dout.writeByte(183); // invokespecial
+ dout.writeShort(superConstructorMethodRefConst);
+ dout.writeByte(177); // return
+
+ dout.writeShort(0); // 0 catches
+
+ dout.writeShort(0); // 0 method attrs
+
+ dout.writeShort(0); // 0 class attrs
+
+ dout.close();
+ byte[] classBytes = bout.toByteArray();
+
+ dout = null;
+
+ return
+ defineClass(singleClassName, classBytes, 0, classBytes.length);
+ }
+
+ protected Class findClass(String name) throws ClassNotFoundException {
+ if (name.equals(singleClassName))
+ return singleClass;
+ else
+ throw new ClassNotFoundException(name);
+ }
+
+ private int writeUTFConst(String s) throws IOException {
+ dout.writeByte(1);
+ dout.writeUTF(s);
+ return cpoolIndex++;
+ }
+
+ private int writeClassConst(int nameIndex) throws IOException {
+ dout.writeByte(7);
+ dout.writeShort((short) nameIndex);
+ return cpoolIndex++;
+ }
+
+ private int writeNameAndTypeConst(int nameIndex, int typeIndex)
+ throws IOException {
+ dout.writeByte(12);
+ dout.writeShort((short) nameIndex);
+ dout.writeShort((short) typeIndex);
+ return cpoolIndex++;
+ }
+
+ private int writeMethodRefConst(int classIndex, int nameAndTypeIndex)
+ throws IOException {
+ dout.writeByte(10);
+ dout.writeShort((short) classIndex);
+ dout.writeShort((short) nameAndTypeIndex);
+ return cpoolIndex++;
+ }
+
+ private final String singleClassName;
+ private final Class singleClass;
+
+ private DataOutputStream dout;
+ private int cpoolIndex;
+}
diff --git a/test/javax/management/remote/mandatory/loading/TargetMBeanTest.java b/test/javax/management/remote/mandatory/loading/TargetMBeanTest.java
new file mode 100644
index 0000000..acb70f8
--- /dev/null
+++ b/test/javax/management/remote/mandatory/loading/TargetMBeanTest.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4910428
+ * @summary Tests target MBean class loader used before JSR 160 loader
+ * @author Eamonn McManus
+ * @run clean TargetMBeanTest
+ * @run build TargetMBeanTest
+ * @run main TargetMBeanTest
+ */
+
+/*
+ The JSR 160 spec says that, when invoking a method (or setting an
+ attribute or creating) on a target MBean, that MBean's class loader
+ is used to deserialize parameters. The problem is that the RMI
+ connector protocol wraps these parameters as MarshalledObjects.
+ When you call get() on a MarshalledObject, the context class loader
+ is used to deserialize, so if we set this to the target MBean's
+ class loader everything should work. EXCEPT that MarshalledObject
+ first tries to load classes using the first class loader it finds in
+ the caller's stack. If our JSR 160 implementation is part of J2SE,
+ it will not find any such class loader (only the system class
+ loader). But if it's standalone, then it will find the class loader
+ of the JSR 160 implementation. If the class name of a parameter is
+ known to both the 160 loader and the target MBean loader, then we
+ will use the wrong loader for deserialization and the attempt to
+ invoke the target MBean with the deserialized object will fail.
+
+ We test this as follows. We fabricate an MLet that has the same set
+ of URLs as the 160 class loader, which we assume is the system class
+ loader (or at least, it is a URLClassLoader). This MLet is
+ therefore a "shadow class loader" -- for every class name known to
+ the 160 class loader, it can load the same name, but the result is
+ not the same class, since it has not been loaded by the same loader.
+ Then, we use the MLet to create an RMIConnectorServer MBean. This
+ MBean is an instance of "shadow RMIConnectorServer", and its
+ constructor has a parameter of type "shadow JMXServiceURL". If the
+ constructor is invoked with "real JMXServiceURL" it will fail.
+
+ While we are at it, we also test that the behaviour is correct for
+ the JMXMP protocol, if that optional protocol is present.
+ */
+import java.lang.reflect.*;
+import java.net.*;
+import java.util.*;
+import javax.management.*;
+import javax.management.loading.*;
+import javax.management.remote.*;
+import javax.management.remote.rmi.RMIConnectorServer;
+
+public class TargetMBeanTest {
+ private static final ObjectName mletName;
+ static {
+ try {
+ mletName = new ObjectName("x:type=mlet");
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new Error();
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("Test that target MBean class loader is used " +
+ "before JMX Remote API class loader");
+
+ ClassLoader jmxRemoteClassLoader =
+ JMXServiceURL.class.getClassLoader();
+ if (jmxRemoteClassLoader == null) {
+ System.out.println("JMX Remote API loaded by bootstrap " +
+ "class loader, this test is irrelevant");
+ return;
+ }
+ if (!(jmxRemoteClassLoader instanceof URLClassLoader)) {
+ System.out.println("TEST INVALID: JMX Remote API not loaded by " +
+ "URLClassLoader");
+ System.exit(1);
+ }
+
+ URLClassLoader jrcl = (URLClassLoader) jmxRemoteClassLoader;
+ URL[] urls = jrcl.getURLs();
+ PrivateMLet mlet = new PrivateMLet(urls, null, false);
+ Class shadowClass = mlet.loadClass(JMXServiceURL.class.getName());
+ if (shadowClass == JMXServiceURL.class) {
+ System.out.println("TEST INVALID: MLet got original " +
+ "JMXServiceURL not shadow");
+ System.exit(1);
+ }
+
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ mbs.registerMBean(mlet, mletName);
+
+ final String[] protos = {"rmi", "iiop", "jmxmp"};
+ boolean ok = true;
+ for (int i = 0; i < protos.length; i++) {
+ try {
+ ok &= test(protos[i], mbs);
+ } catch (Exception e) {
+ System.out.println("TEST FAILED WITH EXCEPTION:");
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+ }
+
+ if (ok)
+ System.out.println("Test passed");
+ else {
+ System.out.println("TEST FAILED");
+ System.exit(1);
+ }
+ }
+
+ private static boolean test(String proto, MBeanServer mbs)
+ throws Exception {
+ System.out.println("Testing for proto " + proto);
+
+ JMXConnectorServer cs;
+ JMXServiceURL url = new JMXServiceURL(proto, null, 0);
+ try {
+ cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null,
+ mbs);
+ } catch (MalformedURLException e) {
+ System.out.println("System does not recognize URL: " + url +
+ "; ignoring");
+ return true;
+ }
+ cs.start();
+ JMXServiceURL addr = cs.getAddress();
+ JMXServiceURL rmiurl = new JMXServiceURL("rmi", null, 0);
+ JMXConnector client = JMXConnectorFactory.connect(addr);
+ MBeanServerConnection mbsc = client.getMBeanServerConnection();
+ ObjectName on = new ObjectName("x:proto=" + proto + ",ok=yes");
+ mbsc.createMBean(RMIConnectorServer.class.getName(),
+ on,
+ mletName,
+ new Object[] {rmiurl, null},
+ new String[] {JMXServiceURL.class.getName(),
+ Map.class.getName()});
+ System.out.println("Successfully deserialized with " + proto);
+ mbsc.unregisterMBean(on);
+
+ client.close();
+ cs.stop();
+ return true;
+ }
+}
diff --git a/test/javax/management/remote/mandatory/loading/UserClassLoaderTest.java b/test/javax/management/remote/mandatory/loading/UserClassLoaderTest.java
new file mode 100644
index 0000000..a768174
--- /dev/null
+++ b/test/javax/management/remote/mandatory/loading/UserClassLoaderTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6356458
+ * @summary test to not lose a user classloader
+ * @author Shanliang JIANG
+ * @run clean UserClassLoaderTest
+ * @run build UserClassLoaderTest
+ * @run main UserClassLoaderTest
+ */
+
+import java.util.*;
+import java.net.*;
+import java.io.IOException;
+
+import javax.management.*;
+import javax.management.remote.*;
+
+public class UserClassLoaderTest {
+ private static final String[] protocols = {"rmi", "iiop", "jmxmp"};
+ private static final MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ private static ObjectName timer;
+ private final static NotificationListener listener = new NotificationListener() {
+ public void handleNotification(Notification notification, Object handback) {
+ }
+ };
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("main: we should not lose client classloader.");
+
+ timer = new ObjectName("test:name=timer");
+ mbs.createMBean("javax.management.timer.Timer", timer);
+
+ boolean ok = true;
+ for (int i = 0; i < protocols.length; i++) {
+ try {
+ if (!test(protocols[i])) {
+ System.out.println("main: Test failed for " + protocols[i]);
+ ok = false;
+ } else {
+ System.out.println("main: Test successed for " + protocols[i]);
+ }
+ } catch (Exception e) {
+ System.out.println("main: Test failed for " + protocols[i]);
+ e.printStackTrace(System.out);
+ ok = false;
+ } }
+
+ if (ok) {
+ System.out.println("main: Tests passed");
+ } else {
+ System.out.println("main: Tests FAILED");
+ System.exit(1);
+ }
+ }
+
+ private static boolean test(String proto) throws Exception {
+ System.out.println("\ntest: Test for protocol " + proto);
+
+ JMXServiceURL u = null;
+ JMXConnectorServer server = null;
+
+ try {
+ u = new JMXServiceURL(proto, null, 0);
+ server = JMXConnectorServerFactory.newJMXConnectorServer(u, null, mbs);
+ } catch (MalformedURLException e) {
+ System.out.println("Skipping unsupported URL " + proto);
+ return true;
+ }
+
+ server.start();
+ u = server.getAddress();
+
+ System.out.println("test: create a server on: "+u);
+
+ JMXConnector client = JMXConnectorFactory.connect(u, null);
+ MBeanServerConnection conn = client.getMBeanServerConnection();
+
+ final ClassLoader orgCL = Thread.currentThread().getContextClassLoader();
+ System.out.println("test: the orginal classloader is "+orgCL);
+
+ final URL url = new URL("file:/xxx");
+ final ClassLoader newCL = new URLClassLoader(new URL[]{url}, orgCL);
+
+ try {
+ System.out.println("test: set classloader to "+newCL);
+ Thread.currentThread().setContextClassLoader(newCL);
+
+ // reproduce the bug
+ conn.addNotificationListener(timer, listener, null, null);
+
+ client.close();
+ server.stop();
+
+ if (Thread.currentThread().getContextClassLoader() != newCL) {
+ System.out.println("ERROR: The client class loader is lost.");
+
+ return false;
+ } else {
+ System.out.println("test: Bye bye.");
+
+ return true;
+ }
+ } finally {
+ Thread.currentThread().setContextClassLoader(orgCL);
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/notif/AddRemoveTest.java b/test/javax/management/remote/mandatory/notif/AddRemoveTest.java
new file mode 100644
index 0000000..126a761
--- /dev/null
+++ b/test/javax/management/remote/mandatory/notif/AddRemoveTest.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+
+/*
+ * @test
+ * @bug 4838640 4917194
+ * @summary test on add/remove NotificationListener
+ * @author Shanliang JIANG
+ * @run clean AddRemoveTest
+ * @run build AddRemoveTest
+ * @run main AddRemoveTest
+ */
+
+import java.net.MalformedURLException;
+import java.io.IOException;
+
+import javax.management.*;
+import javax.management.remote.*;
+
+public class AddRemoveTest {
+ private static final String[] protocols = {"rmi", "iiop", "jmxmp"};
+ private static final MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ public static void main(String[] args) {
+ System.out.println(">>> test on add/remove NotificationListener.");
+
+ boolean ok = true;
+ for (int i = 0; i < protocols.length; i++) {
+ try {
+ if (!test(protocols[i])) {
+ System.out.println(">>> Test failed for " + protocols[i]);
+ ok = false;
+ } else {
+ System.out.println(">>> Test successed for " + protocols[i]);
+ }
+ } catch (Exception e) {
+ System.out.println(">>> Test failed for " + protocols[i]);
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+ }
+
+ if (ok) {
+ System.out.println(">>> Test passed");
+ } else {
+ System.out.println(">>> TEST FAILED");
+ System.exit(1);
+ }
+ }
+
+ private static boolean test(String proto)
+ throws Exception {
+ System.out.println(">>> Test for protocol " + proto);
+ JMXServiceURL u = new JMXServiceURL(proto, null, 0);
+ JMXConnectorServer server;
+ JMXServiceURL addr;
+ JMXConnector client;
+ MBeanServerConnection mserver;
+
+ final ObjectName delegateName =
+ new ObjectName("JMImplementation:type=MBeanServerDelegate");
+ final NotificationListener dummyListener = new NotificationListener() {
+ public void handleNotification(Notification n, Object o) {
+ // do nothing
+ return;
+ }
+ };
+
+ try {
+ // with a client listener, but close the server first
+ server = JMXConnectorServerFactory.newJMXConnectorServer(u, null, mbs);
+ server.start();
+
+ addr = server.getAddress();
+ client = JMXConnectorFactory.newJMXConnector(addr, null);
+ client.connect(null);
+
+ mserver = client.getMBeanServerConnection();
+ String s1 = "1";
+ String s2 = "2";
+ String s3 = "3";
+
+ for (int i=0; i<3; i++) {
+ mserver.addNotificationListener(delegateName, dummyListener, null, s1);
+ mserver.addNotificationListener(delegateName, dummyListener, null, s2);
+ mserver.addNotificationListener(delegateName, dummyListener, null, s3);
+
+ mserver.removeNotificationListener(delegateName, dummyListener, null, s3);
+ mserver.removeNotificationListener(delegateName, dummyListener, null, s2);
+ mserver.removeNotificationListener(delegateName, dummyListener, null, s1);
+ }
+
+ for (int i=0; i<3; i++) {
+ mserver.addNotificationListener(delegateName, dummyListener, null, s1);
+ mserver.addNotificationListener(delegateName, dummyListener, null, s2);
+ mserver.addNotificationListener(delegateName, dummyListener, null, s3);
+
+ mserver.removeNotificationListener(delegateName, dummyListener);
+
+ try {
+ mserver.removeNotificationListener(delegateName, dummyListener, null, s1);
+ System.out.println("Failed to remove a listener.");
+
+ // no expected exception
+ return false;
+ } catch (ListenerNotFoundException lne) {
+ // As expected.
+ }
+ }
+ client.close();
+
+ server.stop();
+
+ } catch (MalformedURLException e) {
+ System.out.println(">>> Skipping unsupported URL " + u);
+ return true;
+ }
+
+ return true;
+ }
+}
diff --git a/test/javax/management/remote/mandatory/notif/DiffHBTest.java b/test/javax/management/remote/mandatory/notif/DiffHBTest.java
new file mode 100644
index 0000000..8903d88
--- /dev/null
+++ b/test/javax/management/remote/mandatory/notif/DiffHBTest.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4911721
+ * @summary test on add/remove NotificationListener
+ * @author Shanliang JIANG
+ * @run clean DiffHBTest
+ * @run build DiffHBTest
+ * @run main DiffHBTest
+ */
+
+import java.net.MalformedURLException;
+import java.io.IOException;
+
+import javax.management.*;
+import javax.management.remote.*;
+
+/**
+ * This test registeres an unique listener with two different handbacks,
+ * it expects to receive a same notification two times.
+ */
+public class DiffHBTest {
+ private static final String[] protocols = {"rmi", "iiop", "jmxmp"};
+
+ private static final MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ private static ObjectName delegateName;
+ private static ObjectName timerName;
+
+ public static int received = 0;
+ public static final int[] receivedLock = new int[0];
+ public static Notification receivedNotif = null;
+
+ public static Object receivedHB = null;
+ public static final String[] hbs = new String[] {"0", "1"};
+
+ public static void main(String[] args) throws Exception {
+ System.out.println(">>> test on one listener with two different handbacks.");
+
+ delegateName = new ObjectName("JMImplementation:type=MBeanServerDelegate");
+ timerName = new ObjectName("MBean:name=Timer");
+
+ boolean ok = true;
+ for (int i = 0; i < protocols.length; i++) {
+ try {
+ if (!test(protocols[i])) {
+ System.out.println(">>> Test failed for " + protocols[i]);
+ ok = false;
+ } else {
+ System.out.println(">>> Test successed for " + protocols[i]);
+ }
+ } catch (Exception e) {
+ System.out.println(">>> Test failed for " + protocols[i]);
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+ }
+
+ if (ok) {
+ System.out.println(">>> Test passed");
+ } else {
+ System.out.println(">>> TEST FAILED");
+ System.exit(1);
+ }
+ }
+
+ private static boolean test(String proto) throws Exception {
+ System.out.println(">>> Test for protocol " + proto);
+ JMXServiceURL u = new JMXServiceURL(proto, null, 0);
+ JMXConnectorServer server;
+ JMXServiceURL addr;
+ JMXConnector client;
+ MBeanServerConnection mserver;
+
+ final NotificationListener dummyListener = new NotificationListener() {
+ public void handleNotification(Notification n, Object o) {
+ synchronized(receivedLock) {
+ if (n == null) {
+ System.out.println(">>> Got a null notification.");
+ System.exit(1);
+ }
+
+ // check number
+ if (received > 2) {
+ System.out.println(">>> Expect to receive 2 notifs, but get "+received);
+ System.exit(1);
+ }
+
+ if (received == 0) { // first time
+ receivedNotif = n;
+ receivedHB = o;
+
+ if (!hbs[0].equals(o) && !hbs[1].equals(o)) {
+ System.out.println(">>> Unkown handback: "+o);
+ System.exit(1);
+ }
+ } else { // second time
+ if (!receivedNotif.equals(n)) {
+ System.out.println(">>> Not get same notif twice.");
+ System.exit(1);
+ } else if (!hbs[0].equals(o) && !hbs[1].equals(o)) { // validate handback
+ System.out.println(">>> Unkown handback: "+o);
+ System.exit(1);
+ } else if (receivedHB.equals(o)) {
+ System.out.println(">>> Got same handback twice: "+o);
+ System.exit(1);
+ }
+ }
+
+ ++received;
+
+ if (received == 2) {
+ receivedLock.notify();
+ }
+ }
+ }
+ };
+
+ try {
+ server = JMXConnectorServerFactory.newJMXConnectorServer(u, null, mbs);
+ server.start();
+
+ addr = server.getAddress();
+ client = JMXConnectorFactory.newJMXConnector(addr, null);
+ client.connect(null);
+
+ mserver = client.getMBeanServerConnection();
+
+ mserver.addNotificationListener(delegateName, dummyListener, null, hbs[0]);
+ mserver.addNotificationListener(delegateName, dummyListener, null, hbs[1]);
+
+ for (int i=0; i<20; i++) {
+ synchronized(receivedLock) {
+ received = 0;
+ }
+
+ mserver.createMBean("javax.management.timer.Timer", timerName);
+
+ synchronized(receivedLock) {
+ if (received != 2) {
+ long remainingTime = waitingTime;
+ final long startTime = System.currentTimeMillis();
+
+ while (received != 2 && remainingTime > 0) {
+ receivedLock.wait(remainingTime);
+ remainingTime = waitingTime -
+ (System.currentTimeMillis() - startTime);
+ }
+ }
+
+ if (received != 2) {
+ System.out.println(">>> Expected 2 notifis, but received "+received);
+
+ return false;
+ }
+ }
+
+
+ synchronized(receivedLock) {
+ received = 0;
+ }
+
+ mserver.unregisterMBean(timerName);
+
+ synchronized(receivedLock) {
+ if (received != 2) {
+
+ long remainingTime = waitingTime;
+ final long startTime = System.currentTimeMillis();
+
+ while (received != 2 && remainingTime >0) {
+ receivedLock.wait(remainingTime);
+ remainingTime = waitingTime -
+ (System.currentTimeMillis() - startTime);
+ }
+ }
+
+ if (received != 2) {
+ System.out.println(">>> Expected 2 notifis, but received "+received);
+
+ return false;
+ }
+ }
+ }
+
+ mserver.removeNotificationListener(delegateName, dummyListener);
+
+ client.close();
+
+ server.stop();
+
+ } catch (MalformedURLException e) {
+ System.out.println(">>> Skipping unsupported URL " + u);
+ return true;
+ }
+
+ return true;
+ }
+
+ private final static long waitingTime = 10000;
+}
diff --git a/test/javax/management/remote/mandatory/notif/EmptyDomainNotificationTest.java b/test/javax/management/remote/mandatory/notif/EmptyDomainNotificationTest.java
new file mode 100644
index 0000000..0e7a69d
--- /dev/null
+++ b/test/javax/management/remote/mandatory/notif/EmptyDomainNotificationTest.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6238731
+ * @summary Check that the expected notification is received by the JMX
+ * client even when the domain in the ObjectName is not specified
+ * @author Shanliang JIANG
+ * @run clean EmptyDomainNotificationTest
+ * @run build EmptyDomainNotificationTest
+ * @run main EmptyDomainNotificationTest
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerFactory;
+import javax.management.Notification;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.NotificationListener;
+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 EmptyDomainNotificationTest {
+
+ public static interface SimpleMBean {
+ public void emitNotification();
+ }
+
+ public static class Simple
+ extends NotificationBroadcasterSupport
+ implements SimpleMBean {
+ public void emitNotification() {
+ sendNotification(new Notification("simple", this, 0));
+ }
+ }
+
+ public static class Listener implements NotificationListener {
+ public void handleNotification(Notification n, Object h) {
+ System.out.println(
+ "EmptyDomainNotificationTest-Listener-handleNotification: receives:" + n);
+
+ if (n.getType().equals("simple")) {
+ synchronized(this) {
+ received++;
+
+ this.notifyAll();
+ }
+ }
+ }
+
+ public int received;
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ final MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ final JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://");
+
+ JMXConnectorServer server = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
+ server.start();
+
+ JMXConnector client = JMXConnectorFactory.connect(server.getAddress(), null);
+
+ final MBeanServerConnection mbsc = client.getMBeanServerConnection();
+
+ final ObjectName mbean = ObjectName.getInstance(":type=Simple");
+ mbsc.createMBean(Simple.class.getName(), mbean);
+
+ System.out.println("EmptyDomainNotificationTest-main: add a listener ...");
+ final Listener li = new Listener();
+ mbsc.addNotificationListener(mbean, li, null, null);
+
+ System.out.println("EmptyDomainNotificationTest-main: ask to send a notif ...");
+ mbsc.invoke(mbean, "emitNotification", null, null);
+
+ System.out.println("EmptyDomainNotificationTest-main: waiting notif...");
+ final long stopTime = System.currentTimeMillis() + 2000;
+ synchronized(li) {
+ long toWait = stopTime - System.currentTimeMillis();
+
+ while (li.received < 1 && toWait > 0) {
+ li.wait(toWait);
+
+ toWait = stopTime - System.currentTimeMillis();
+ }
+ }
+
+ if (li.received < 1) {
+ throw new RuntimeException("No notif received!");
+ } else if (li.received > 1) {
+ throw new RuntimeException("Wait one notif but got: "+li.received);
+ }
+
+ System.out.println("EmptyDomainNotificationTest-main: Got the expected notif!");
+
+ System.out.println("EmptyDomainNotificationTest-main: remove the listener.");
+ mbsc.removeNotificationListener(mbean, li);
+
+ // clean
+ client.close();
+ server.stop();
+
+ System.out.println("EmptyDomainNotificationTest-main: Bye.");
+ }
+}
diff --git a/test/javax/management/remote/mandatory/notif/ListenerScaleTest.java b/test/javax/management/remote/mandatory/notif/ListenerScaleTest.java
new file mode 100644
index 0000000..d0c519e
--- /dev/null
+++ b/test/javax/management/remote/mandatory/notif/ListenerScaleTest.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6338874
+ * @summary Check that notification dispatch is not linear in number of MBeans.
+ * @author Eamonn McManus
+ */
+
+/*
+ * The notification dispatch logic in the connector server used to be
+ * linear in the number of listeners there were on any MBean. For
+ * example, if there were 1000 MBeans, each with one listener, then
+ * every time a notification was sent it would be compared against
+ * every one of the 1000 MBeans, even though its source ObjectName was
+ * known and could not possibly match the name of 999 of the MBeans.
+ * This test checks that we no longer have linear behaviour. We do
+ * this by registering just one MBean and measuring the time it takes
+ * to send and receive a certain number of notifications from that
+ * MBean. Then we register many other MBeans, each with a listener,
+ * and we make the same measurement as before. The presence of the
+ * extra MBeans with their listeners should not impact the dispatch
+ * time significantly. If it does, the test fails.
+ *
+ * As usual with timing-sensitive tests, we could potentially get
+ * sporadic failures. We fail if the ratio of the time with many
+ * MBeans to the time with just one MBean is more than 100. With the
+ * fix in place, it is usually less than 1, presumably because some
+ * code was being interpreted during the first measurement but had
+ * been compiled by the second.
+ */
+
+import java.lang.management.ManagementFactory;
+import javax.management.*;
+import javax.management.remote.*;
+import java.util.concurrent.*;
+
+public class ListenerScaleTest {
+ private static final int WARMUP_WITH_ONE_MBEAN = 1000;
+ private static final int NOTIFS_TO_TIME = 100;
+ private static final int EXTRA_MBEANS = 20000;
+
+ private static final MBeanServer mbs =
+ ManagementFactory.getPlatformMBeanServer();
+ private static final ObjectName testObjectName;
+ static {
+ try {
+ testObjectName = new ObjectName("test:type=Sender,number=-1");
+ } catch (MalformedObjectNameException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static volatile int nnotifs;
+ private static volatile long startTime;
+ private static volatile long elapsed;
+ private static final Semaphore sema = new Semaphore(0);
+
+ private static final NotificationListener timingListener =
+ new NotificationListener() {
+ public void handleNotification(Notification n, Object h) {
+ if (++nnotifs == NOTIFS_TO_TIME) {
+ elapsed = System.nanoTime() - startTime;
+ sema.release();
+ }
+ }
+ };
+
+ private static final long timeNotif() {
+ try {
+ startTime = System.nanoTime();
+ nnotifs = 0;
+ mbs.invoke(testObjectName, "send", null, null);
+ sema.acquire();
+ return elapsed;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static interface SenderMBean {
+ public void send();
+ }
+
+ public static class Sender extends NotificationBroadcasterSupport
+ implements SenderMBean {
+ public void send() {
+ for (int i = 0; i < NOTIFS_TO_TIME; i++)
+ sendNotification(new Notification("type", this, 1L));
+ }
+ }
+
+ private static final NotificationListener nullListener =
+ new NotificationListener() {
+ public void handleNotification(Notification n, Object h) {}
+ };
+
+ public static void main(String[] args) throws Exception {
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ Sender sender = new Sender();
+ mbs.registerMBean(sender, testObjectName);
+ JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://");
+ JMXConnectorServer cs =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
+ cs.start();
+ JMXServiceURL addr = cs.getAddress();
+ JMXConnector cc = JMXConnectorFactory.connect(addr);
+ try {
+ test(mbs, cs, cc);
+ } finally {
+ cc.close();
+ cs.stop();
+ }
+ }
+
+ private static void test(MBeanServer mbs, JMXConnectorServer cs,
+ JMXConnector cc) throws Exception {
+ MBeanServerConnection mbsc = cc.getMBeanServerConnection();
+ mbsc.addNotificationListener(testObjectName, timingListener, null, null);
+ long singleMBeanTime = 0;
+ for (int i = 0; i < WARMUP_WITH_ONE_MBEAN; i++)
+ singleMBeanTime = timeNotif();
+ if (singleMBeanTime == 0)
+ singleMBeanTime = 1;
+ System.out.println("Time with a single MBean: " + singleMBeanTime + "ns");
+ System.out.println("Now registering " + EXTRA_MBEANS + " MBeans");
+ for (int i = 0; i < EXTRA_MBEANS; i++) {
+ ObjectName on = new ObjectName("test:type=Sender,number=" + i);
+ mbs.registerMBean(new Sender(), on);
+ if (i % 1000 == 999) {
+ System.out.print("..." + (i+1));
+ System.out.flush();
+ }
+ }
+ System.out.println();
+ System.out.println("Now registering " + EXTRA_MBEANS + " listeners");
+ for (int i = 0; i < EXTRA_MBEANS; i++) {
+ ObjectName on = new ObjectName("test:type=Sender,number=" + i);
+ mbsc.addNotificationListener(on, nullListener, null, null);
+ if (i % 1000 == 999) {
+ System.out.print("..." + (i+1));
+ System.out.flush();
+ }
+ }
+ System.out.println();
+ System.out.println("Timing a notification send now");
+ long manyMBeansTime = timeNotif();
+ System.out.println("Time with many MBeans: " + manyMBeansTime + "ns");
+ double ratio = (double) manyMBeansTime / singleMBeanTime;
+ if (ratio > 100.0)
+ throw new Exception("Failed: ratio=" + ratio);
+ System.out.println("Test passed: ratio=" + ratio);
+ }
+}
diff --git a/test/javax/management/remote/mandatory/notif/NotSerializableNotifTest.java b/test/javax/management/remote/mandatory/notif/NotSerializableNotifTest.java
new file mode 100644
index 0000000..2b82bb7
--- /dev/null
+++ b/test/javax/management/remote/mandatory/notif/NotSerializableNotifTest.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @summary Tests to send a not serializable notification.
+ * @bug 5022196
+ * @author Shanliang JIANG
+ * @run clean NotSerializableNotifTest
+ * @run build NotSerializableNotifTest
+ * @run main NotSerializableNotifTest
+ */
+
+// java imports
+//
+import java.io.IOException;
+import java.net.MalformedURLException;
+
+// JMX imports
+//
+import javax.management.* ;
+
+import javax.management.remote.*;
+import javax.management.remote.JMXServiceURL;
+
+public class NotSerializableNotifTest {
+ private static MBeanServer mbeanServer = MBeanServerFactory.createMBeanServer();
+ private static ObjectName emitter;
+ private static int port = 2468;
+
+ private static String[] protocols;
+
+ private static final int sentNotifs = 10;
+
+ public static void main(String[] args) throws Exception {
+ System.out.println(">>> Test to send a not serializable notification");
+
+ // IIOP fails on JDK1.4, see 5034318
+ final String v = System.getProperty("java.version");
+ float f = Float.parseFloat(v.substring(0, 3));
+ if (f<1.5) {
+ protocols = new String[] {"rmi", "jmxmp"};
+ } else {
+ protocols = new String[] {"rmi", "iiop", "jmxmp"};
+ }
+
+ emitter = new ObjectName("Default:name=NotificationEmitter");
+ mbeanServer.registerMBean(new NotificationEmitter(), emitter);
+
+ boolean ok = true;
+ for (int i = 0; i < protocols.length; i++) {
+ try {
+ if (!test(protocols[i])) {
+ System.out.println(">>> Test failed for " + protocols[i]);
+ ok = false;
+ } else {
+ System.out.println(">>> Test successed for " + protocols[i]);
+ }
+ } catch (Exception e) {
+ System.out.println(">>> Test failed for " + protocols[i]);
+ e.printStackTrace(System.out);
+ ok = false;
+ }
+ }
+
+ if (ok) {
+ System.out.println(">>> Test passed");
+ } else {
+ System.out.println(">>> TEST FAILED");
+ System.exit(1);
+ }
+ }
+
+
+ private static boolean test(String proto) throws Exception {
+ System.out.println("\n>>> Test for protocol " + proto);
+
+ JMXServiceURL url = new JMXServiceURL(proto, null, port++);
+
+ System.out.println(">>> Create a server: "+url);
+
+ JMXConnectorServer server = null;
+ try {
+ server = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbeanServer);
+ } catch (MalformedURLException e) {
+ System.out.println("System does not recognize URL: " + url +
+ "; ignoring");
+ return true;
+ }
+
+ server.start();
+
+ url = server.getAddress();
+
+ System.out.println(">>> Creating a client connectint to: "+url);
+ JMXConnector conn = JMXConnectorFactory.connect(url, null);
+ MBeanServerConnection client = conn.getMBeanServerConnection();
+
+ // add listener from the client side
+ Listener listener = new Listener();
+ client.addNotificationListener(emitter, listener, null, null);
+
+ // ask to send one not serializable notif
+ Object[] params = new Object[] {new Integer(1)};
+ String[] signatures = new String[] {"java.lang.Integer"};
+ client.invoke(emitter, "sendNotserializableNotifs", params, signatures);
+
+ // listener clean
+ client.removeNotificationListener(emitter, listener);
+ listener = new Listener();
+ client.addNotificationListener(emitter, listener, null, null);
+
+ //ask to send serializable notifs
+ params = new Object[] {new Integer(sentNotifs)};
+ client.invoke(emitter, "sendNotifications", params, signatures);
+
+ // waiting ...
+ synchronized (listener) {
+ for (int i=0; i<10; i++) {
+ if (listener.received() < sentNotifs) {
+ listener.wait(1000);
+ } else {
+ break;
+ }
+ }
+ }
+
+ // check
+ boolean ok = true;
+
+ if (listener.received() != sentNotifs) {
+ System.out.println("Failed: received "+listener.received()+
+ " but should be "+sentNotifs);
+ ok = false;
+ } else {
+ System.out.println("The client received all notifications.");
+ }
+
+ // clean
+ client.removeNotificationListener(emitter, listener);
+
+ conn.close();
+ server.stop();
+
+ return ok;
+ }
+
+//--------------------------
+// private classes
+//--------------------------
+
+ private static class Listener implements NotificationListener {
+ public void handleNotification(Notification notif, Object handback) {
+ synchronized (this) {
+ if(++receivedNotifs == sentNotifs) {
+ this.notifyAll();
+ }
+ }
+ }
+
+ public int received() {
+ return receivedNotifs;
+ }
+
+ private int receivedNotifs = 0;
+ }
+
+ public static class NotificationEmitter extends NotificationBroadcasterSupport
+ implements NotificationEmitterMBean {
+
+ public MBeanNotificationInfo[] getNotificationInfo() {
+ final String[] ntfTypes = {myType};
+
+ final MBeanNotificationInfo[] ntfInfoArray = {
+ new MBeanNotificationInfo(ntfTypes,
+ "javax.management.Notification",
+ "Notifications sent by the NotificationEmitter")};
+
+ return ntfInfoArray;
+ }
+
+ /**
+ * Send not serializable Notifications.
+ *
+ * @param nb The number of notifications to send
+ */
+ public void sendNotserializableNotifs(Integer nb) {
+
+ Notification notif;
+ for (int i=1; i<=nb.intValue(); i++) {
+ notif = new Notification(myType, this, i);
+
+ notif.setUserData(new Object());
+ sendNotification(notif);
+ }
+ }
+
+ /**
+ * Send Notification objects.
+ *
+ * @param nb The number of notifications to send
+ */
+ public void sendNotifications(Integer nb) {
+ Notification notif;
+ for (int i=1; i<=nb.intValue(); i++) {
+ notif = new Notification(myType, this, i);
+
+ sendNotification(notif);
+ }
+ }
+
+ private final String myType = "notification.my_notification";
+ }
+
+ public interface NotificationEmitterMBean {
+ public void sendNotifications(Integer nb);
+
+ public void sendNotserializableNotifs(Integer nb);
+ }
+}
diff --git a/test/javax/management/remote/mandatory/notif/NotifBufferSizePropertyNameTest.java b/test/javax/management/remote/mandatory/notif/NotifBufferSizePropertyNameTest.java
new file mode 100644
index 0000000..254e871
--- /dev/null
+++ b/test/javax/management/remote/mandatory/notif/NotifBufferSizePropertyNameTest.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2004-2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test NotifBufferSizePropertyNameTest
+ * @bug 6174229
+ * @summary Verify the property name specifying server notification buffer size.
+ * @author Shanliang JIANG
+ * @run clean NotifBufferSizePropertyNameTest
+ * @run build NotifBufferSizePropertyNameTest
+ * @run main NotifBufferSizePropertyNameTest
+ */
+
+import java.io.IOException;
+import java.util.*;
+
+import javax.management.*;
+import javax.management.remote.*;
+
+/**
+ * This class tests also the size of a server notification buffer.
+ */
+public class NotifBufferSizePropertyNameTest {
+
+ private static ObjectName oname;
+ private static JMXServiceURL url;
+ private final static NotificationListener listener = new NotificationListener() {
+ public void handleNotification(Notification n, Object hb) {
+ // nothing
+ }
+ };
+
+ public static void main(String[] args) throws Exception {
+ System.out.println(
+ "Verify the property name specifying the server notification buffer size.");
+
+ oname = new ObjectName ("Default:name=NotificationEmitter");
+ url = new JMXServiceURL("rmi", null, 0);
+ Map env = new HashMap(2);
+
+ System.out.println("Test the new property name.");
+ env.put("jmx.remote.x.notification.buffer.size", String.valueOf(bufferSize));
+ test(env);
+
+ System.out.println("Test the old property name.");
+ env.remove("jmx.remote.x.notification.buffer.size");
+ env.put("jmx.remote.x.buffer.size", String.valueOf(bufferSize));
+ test(env);
+
+ System.out.println("Test that the new property name overwrite the old one.");
+ env.put("jmx.remote.x.notification.buffer.size", String.valueOf(bufferSize));
+ env.put("jmx.remote.x.buffer.size", String.valueOf(bufferSize*6));
+ test(env);
+
+ System.out.println("Test the old property name on system.");
+ System.setProperty("jmx.remote.x.buffer.size", String.valueOf(bufferSize));
+ test(null);
+
+ System.out.println(
+ "Test that the new property name overwrite the old one on system.");
+ System.setProperty("jmx.remote.x.notification.buffer.size",
+ String.valueOf(bufferSize));
+ System.setProperty("jmx.remote.x.buffer.size", String.valueOf(bufferSize*6));
+ test(null);
+ }
+
+
+ private static void test(Map env) throws Exception {
+ final MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+
+ mbs.registerMBean(new NotificationEmitter(), oname);
+ JMXConnectorServer server = JMXConnectorServerFactory.newJMXConnectorServer(
+ url,
+ env,
+ mbs);
+ server.start();
+
+ JMXServiceURL addr = server.getAddress();
+ JMXConnector client = JMXConnectorFactory.connect(addr);
+ client.getMBeanServerConnection().addNotificationListener(oname,
+ listener,
+ null,
+ null);
+
+ Thread.sleep(10); // give time to other notifs
+ weakNotifs.clear();
+
+ // send notifd
+ mbs.invoke(oname, "sendNotifications",
+ new Object[] {new Integer(toSend)},
+ new String[] {"java.lang.Integer"});
+
+ client.close();
+ client = null;
+
+ // give time to GC
+ for(int i=0; i<200; i++) {
+ if (weakNotifs.keySet().size() > bufferSize) {
+ Thread.sleep(10);
+ System.gc();
+ } else {
+ break;
+ }
+ }
+
+ // check
+ if (weakNotifs.keySet().size() != bufferSize) {
+ throw new RuntimeException("The buffer size is not correctly specified."+
+ "\nExpected to be <= "+bufferSize+", but got "+weakNotifs.keySet().size());
+ }
+
+ server.stop();
+ server = null;
+ }
+
+//--------------------------
+// private classes
+//--------------------------
+ public static class NotificationEmitter extends NotificationBroadcasterSupport
+ implements NotificationEmitterMBean {
+
+ public void sendNotifications(Integer nb) {
+ Notification notif;
+ for (int i=1; i<=nb.intValue(); i++) {
+ notif = new Notification("MyType", this, i);
+ weakNotifs.put(notif, null);
+ sendNotification(notif);
+ }
+ }
+ }
+
+ public interface NotificationEmitterMBean {
+ public void sendNotifications(Integer nb);
+ }
+
+ private static final int toSend = 20;
+ private static final int bufferSize = 10;
+ private static WeakHashMap weakNotifs = new WeakHashMap(toSend);
+
+}
diff --git a/test/javax/management/remote/mandatory/notif/NotifReconnectDeadlockTest.java b/test/javax/management/remote/mandatory/notif/NotifReconnectDeadlockTest.java
new file mode 100644
index 0000000..bb05399
--- /dev/null
+++ b/test/javax/management/remote/mandatory/notif/NotifReconnectDeadlockTest.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test NotifReconnectDeadlockTest
+ * @bug 6199899
+ * @summary Tests reconnection done by a fetching notif thread.
+ * @author Shanliang JIANG
+ * @run clean NotifReconnectDeadlockTest
+ * @run build NotifReconnectDeadlockTest
+ * @run main NotifReconnectDeadlockTest
+ */
+
+import java.io.IOException;
+import java.util.*;
+
+import javax.management.*;
+import javax.management.remote.*;
+
+/**
+ * "This test checks for a bug whereby reconnection did not work if (a) it was
+ * initiated by the fetchNotifications thread and (b) it succeeded. These conditions
+ * are not usual, since connection failure is usually caused by either idle timeout
+ * (which doesn't usually happen if fetchNotifications is running) or communication
+ * problems (which are usually permanent so reconnection fails). But they can happen,
+ * so we test for them here.
+ * The test sets a very short idle timeout, and effectively suspends the
+ * fetchNotifications thread by having it invoke a listener with a delay in it.
+ * This means that the idle timeout happens. When the delayed listener returns,
+ * the fetchNotifications thread will attempt to reconnect, and this attempt should
+ * succeed, so we meet the two conditions above.
+ * The test succeeds if there is indeed a reconnection, detected by the connection
+ * listener seeing an OPENED notification. The connection listener should not see
+ * a CLOSED or FAILED notification."
+ */
+public class NotifReconnectDeadlockTest {
+
+ public static void main(String[] args) throws Exception {
+ System.out.println(
+ ">>> Tests reconnection done by a fetching notif thread.");
+
+ ObjectName oname = new ObjectName ("Default:name=NotificationEmitter");
+ JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
+ Map env = new HashMap(2);
+ env.put("jmx.remote.x.server.connection.timeout", new Long(serverTimeout));
+ env.put("jmx.remote.x.client.connection.check.period", new Long(Long.MAX_VALUE));
+
+ final MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+
+ mbs.registerMBean(new NotificationEmitter(), oname);
+ JMXConnectorServer server = JMXConnectorServerFactory.newJMXConnectorServer(
+ url,
+ env,
+ mbs);
+ server.start();
+
+ JMXServiceURL addr = server.getAddress();
+ JMXConnector client = JMXConnectorFactory.connect(addr, env);
+
+ Thread.sleep(100); // let pass the first client open notif if there is
+ client.getMBeanServerConnection().addNotificationListener(oname,
+ listener,
+ null,
+ null);
+
+ client.addConnectionNotificationListener(listener, null, null);
+
+ // max test time: 2 minutes
+ final long end = System.currentTimeMillis()+120000;
+
+ synchronized(lock) {
+ while(clientState == null && System.currentTimeMillis() < end) {
+ mbs.invoke(oname, "sendNotifications",
+ new Object[] {new Notification("MyType", "", 0)},
+ new String[] {"javax.management.Notification"});
+
+ try {
+ lock.wait(10);
+ } catch (Exception e) {}
+ }
+ }
+
+ if (clientState == null) {
+ throw new RuntimeException(
+ "No reconnection happened, need to reconfigure the test.");
+ } else if (JMXConnectionNotification.FAILED.equals(clientState) ||
+ JMXConnectionNotification.CLOSED.equals(clientState)) {
+ throw new RuntimeException("Failed to reconnect.");
+ }
+
+ System.out.println(">>> Passed!");
+
+ client.removeConnectionNotificationListener(listener);
+ client.close();
+ server.stop();
+ }
+
+//--------------------------
+// private classes
+//--------------------------
+ public static class NotificationEmitter extends NotificationBroadcasterSupport
+ implements NotificationEmitterMBean {
+
+ public void sendNotifications(Notification n) {
+ sendNotification(n);
+ }
+ }
+
+ public interface NotificationEmitterMBean {
+ public void sendNotifications(Notification n);
+ }
+
+ private final static NotificationListener listener = new NotificationListener() {
+ public void handleNotification(Notification n, Object hb) {
+
+ // treat the client notif to know the end
+ if (n instanceof JMXConnectionNotification) {
+ if (!JMXConnectionNotification.NOTIFS_LOST.equals(n.getType())) {
+
+ clientState = n.getType();
+ System.out.println(
+ ">>> The client state has been changed to: "+clientState);
+
+ synchronized(lock) {
+ lock.notifyAll();
+ }
+ }
+
+ return;
+ }
+
+ System.out.println(">>> Do sleep to make reconnection.");
+ synchronized(lock) {
+ try {
+ lock.wait(listenerSleep);
+ } catch (Exception e) {
+ // OK
+ }
+ }
+ }
+ };
+
+ private static final long serverTimeout = 1000;
+ private static final long listenerSleep = serverTimeout*6;
+
+ private static String clientState = null;
+ private static final int[] lock = new int[0];
+}
diff --git a/test/javax/management/remote/mandatory/notif/NotificationAccessControllerTest.java b/test/javax/management/remote/mandatory/notif/NotificationAccessControllerTest.java
new file mode 100644
index 0000000..42a4eb7
--- /dev/null
+++ b/test/javax/management/remote/mandatory/notif/NotificationAccessControllerTest.java
@@ -0,0 +1,377 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5106721
+ * @summary Check the NotificationAccessController methods are properly called.
+ * @author Luis-Miguel Alventosa
+ * @run clean NotificationAccessControllerTest
+ * @run build NotificationAccessControllerTest
+ * @run main NotificationAccessControllerTest
+ */
+
+import com.sun.jmx.remote.security.NotificationAccessController;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerFactory;
+import javax.management.Notification;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.remote.JMXAuthenticator;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXPrincipal;
+import javax.management.remote.JMXServiceURL;
+import javax.security.auth.Subject;
+
+public class NotificationAccessControllerTest {
+
+ public class NAC implements NotificationAccessController {
+ private boolean throwException;
+ public NAC(boolean throwException) {
+ this.throwException = throwException;
+ }
+ public void addNotificationListener(
+ String connectionId,
+ ObjectName name,
+ Subject subject)
+ throws SecurityException {
+ echo("addNotificationListener:");
+ echo("\tconnectionId: " + connectionId);
+ echo("\tname: " + name);
+ echo("\tsubject: " +
+ (subject == null ? null : subject.getPrincipals()));
+ if (throwException)
+ if (name.getCanonicalName().equals("domain:name=1,type=NB")
+ &&
+ subject.getPrincipals().contains(new JMXPrincipal("role")))
+ throw new SecurityException();
+ }
+ public void removeNotificationListener(
+ String connectionId,
+ ObjectName name,
+ Subject subject)
+ throws SecurityException {
+ echo("removeNotificationListener:");
+ echo("\tconnectionId: " + connectionId);
+ echo("\tname: " + name);
+ echo("\tsubject: " +
+ (subject == null ? null : subject.getPrincipals()));
+ if (throwException)
+ if (name.getCanonicalName().equals("domain:name=2,type=NB")
+ &&
+ subject.getPrincipals().contains(new JMXPrincipal("role")))
+ throw new SecurityException();
+ }
+ public void fetchNotification(
+ String connectionId,
+ ObjectName name,
+ Notification notification,
+ Subject subject)
+ throws SecurityException {
+ echo("fetchNotification:");
+ echo("\tconnectionId: " + connectionId);
+ echo("\tname: " + name);
+ echo("\tnotification: " + notification);
+ echo("\tsubject: " +
+ (subject == null ? null : subject.getPrincipals()));
+ if (!throwException)
+ if (name.getCanonicalName().equals("domain:name=2,type=NB") &&
+ subject.getPrincipals().contains(new JMXPrincipal("role")))
+ throw new SecurityException();
+ }
+ }
+
+ public class CustomJMXAuthenticator implements JMXAuthenticator {
+ public Subject authenticate(Object credentials) {
+ String role = ((String[]) credentials)[0];
+ echo("\nCreate principal with name = " + role);
+ return new Subject(true,
+ Collections.singleton(new JMXPrincipal(role)),
+ Collections.EMPTY_SET,
+ Collections.EMPTY_SET);
+ }
+ }
+
+ public interface NBMBean {
+ public void emitNotification(int seqnum, ObjectName name);
+ }
+
+ public static class NB
+ extends NotificationBroadcasterSupport
+ implements NBMBean {
+ public void emitNotification(int seqnum, ObjectName name) {
+ if (name == null) {
+ sendNotification(new Notification("nb", this, seqnum));
+ } else {
+ sendNotification(new Notification("nb", name, seqnum));
+ }
+ }
+ }
+
+ public class Listener implements NotificationListener {
+ public List<Notification> notifs = new ArrayList<Notification>();
+ public void handleNotification(Notification n, Object h) {
+ echo("handleNotification:");
+ echo("\tNotification = " + n);
+ echo("\tNotification.SeqNum = " + n.getSequenceNumber());
+ echo("\tHandback = " + h);
+ notifs.add(n);
+ }
+ }
+
+ /**
+ * Check received notifications
+ */
+ public int checkNotifs(int size,
+ List<Notification> received,
+ List<ObjectName> expected) {
+ if (received.size() != size) {
+ echo("Error: expecting " + size + " notifications");
+ return 1;
+ } else {
+ for (Notification n : received) {
+ echo("Received notification: " + n);
+ if (!n.getType().equals("nb")) {
+ echo("Notification type must be \"nb\"");
+ return 1;
+ }
+ ObjectName o = (ObjectName) n.getSource();
+ int index = (int) n.getSequenceNumber();
+ ObjectName nb = expected.get(index);
+ if (!o.equals(nb)) {
+ echo("Notification source must be " + nb);
+ return 1;
+ }
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Run test
+ */
+ public int runTest(boolean enableChecks, boolean throwException)
+ throws Exception {
+
+ echo("\n=-=-= " + (enableChecks ? "Enable" : "Disable") +
+ " notification access control checks " +
+ (!enableChecks ? "" : (throwException ? ": add/remove " :
+ ": fetch ")) + "=-=-=");
+
+ JMXConnectorServer server = null;
+ JMXConnector client = null;
+
+ // Create a new MBeanServer
+ //
+ final MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ try {
+ // Create server environment map
+ //
+ final Map<String,Object> env = new HashMap<String,Object>();
+ env.put("jmx.remote.authenticator", new CustomJMXAuthenticator());
+ if (enableChecks) {
+ env.put("com.sun.jmx.remote.notification.access.controller",
+ new NAC(throwException));
+ }
+
+ // Create the JMXServiceURL
+ //
+ final JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://");
+
+ // Create a JMXConnectorServer
+ //
+ server = JMXConnectorServerFactory.newJMXConnectorServer(url,
+ env,
+ mbs);
+
+ // Start the JMXConnectorServer
+ //
+ server.start();
+
+ // Create server environment map
+ //
+ final Map<String,Object> cenv = new HashMap<String,Object>();
+ String[] credentials = new String[] { "role" , "password" };
+ cenv.put("jmx.remote.credentials", credentials);
+
+ // Create JMXConnector and connect to JMXConnectorServer
+ //
+ client = JMXConnectorFactory.connect(server.getAddress(), cenv);
+
+ // Get non-secure MBeanServerConnection
+ //
+ final MBeanServerConnection mbsc =
+ client.getMBeanServerConnection();
+
+ // Create NB MBean
+ //
+ ObjectName nb1 = ObjectName.getInstance("domain:type=NB,name=1");
+ ObjectName nb2 = ObjectName.getInstance("domain:type=NB,name=2");
+ ObjectName nb3 = ObjectName.getInstance("domain:type=NB,name=3");
+ mbsc.createMBean(NB.class.getName(), nb1);
+ mbsc.createMBean(NB.class.getName(), nb2);
+ mbsc.createMBean(NB.class.getName(), nb3);
+
+ // Add notification listener
+ //
+ Listener li = new Listener();
+ try {
+ mbsc.addNotificationListener(nb1, li, null, null);
+ if (enableChecks && throwException) {
+ echo("Didn't get expected exception");
+ return 1;
+ }
+ } catch (SecurityException e) {
+ if (enableChecks && throwException) {
+ echo("Got expected exception: " + e);
+ } else {
+ echo("Got unexpected exception: " + e);
+ return 1;
+ }
+ }
+ mbsc.addNotificationListener(nb2, li, null, null);
+
+ // Invoke the "sendNotification" method
+ //
+ mbsc.invoke(nb1, "emitNotification",
+ new Object[] {0, null},
+ new String[] {"int", "javax.management.ObjectName"});
+ mbsc.invoke(nb2, "emitNotification",
+ new Object[] {1, null},
+ new String[] {"int", "javax.management.ObjectName"});
+ mbsc.invoke(nb2, "emitNotification",
+ new Object[] {2, nb3},
+ new String[] {"int", "javax.management.ObjectName"});
+
+ // Wait for notifications to be emitted
+ //
+ Thread.sleep(2000);
+
+ // Remove notification listener
+ //
+ if (!throwException)
+ mbsc.removeNotificationListener(nb1, li);
+ try {
+ mbsc.removeNotificationListener(nb2, li);
+ if (enableChecks && throwException) {
+ echo("Didn't get expected exception");
+ return 1;
+ }
+ } catch (SecurityException e) {
+ if (enableChecks && throwException) {
+ echo("Got expected exception: " + e);
+ } else {
+ echo("Got unexpected exception: " + e);
+ return 1;
+ }
+ }
+
+ int result = 0;
+ List<ObjectName> sources = new ArrayList();
+ sources.add(nb1);
+ sources.add(nb2);
+ sources.add(nb3);
+ if (!enableChecks) {
+ // List must contain three notifs from sources nb1, nb2 and nb3
+ //
+ result = checkNotifs(3, li.notifs, sources);
+ }
+ if (enableChecks && !throwException) {
+ // List must contain one notif from source nb1
+ //
+ result = checkNotifs(1, li.notifs, sources);
+ }
+ if (enableChecks && throwException) {
+ // List must contain two notifs from sources nb2 and nb3
+ //
+ result = checkNotifs(2, li.notifs, sources);
+ }
+ if (result > 0) {
+ return result;
+ }
+ } catch (Exception e) {
+ echo("Failed to perform operation: " + e);
+ e.printStackTrace();
+ return 1;
+ } finally {
+ // Close the connection
+ //
+ if (client != null)
+ client.close();
+
+ // Stop the connector server
+ //
+ if (server != null)
+ server.stop();
+
+ // Release the MBeanServer
+ //
+ if (mbs != null)
+ MBeanServerFactory.releaseMBeanServer(mbs);
+ }
+
+ return 0;
+ }
+
+ /*
+ * Print message
+ */
+ private static void echo(String message) {
+ System.out.println(message);
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ System.out.println("\nTest notification access control.");
+
+ NotificationAccessControllerTest nact =
+ new NotificationAccessControllerTest();
+
+ int error = 0;
+
+ error += nact.runTest(false, false);
+
+ error += nact.runTest(true, false);
+
+ error += nact.runTest(true, true);
+
+ if (error > 0) {
+ final String msg = "\nTest FAILED! Got " + error + " error(s)";
+ System.out.println(msg);
+ throw new IllegalArgumentException(msg);
+ } else {
+ System.out.println("\nTest PASSED!");
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/notif/NotificationBufferCreationTest.java b/test/javax/management/remote/mandatory/notif/NotificationBufferCreationTest.java
new file mode 100644
index 0000000..1721647
--- /dev/null
+++ b/test/javax/management/remote/mandatory/notif/NotificationBufferCreationTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2003-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4934236
+ * @summary Tests that NotificationBuffer is created when used.
+ * @author jfd@...
+ * @run clean NotificationBufferCreationTest NotificationSender
+ * @run build NotificationBufferCreationTest
+ * @run main NotificationBufferCreationTest
+ */
+import java.net.MalformedURLException;
+
+import javax.management.MBeanServerFactory;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.Notification;
+
+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 NotificationBufferCreationTest {
+ private static final MBeanServer mbs =
+ MBeanServerFactory.createMBeanServer();
+ private static final String[] protocols = {"rmi", "iiop", "jmxmp"};
+ public static void main(String[] args) {
+ try {
+ boolean error = false;
+ ObjectName notifierName =
+ new ObjectName("TestDomain:type=NotificationSender");
+
+ NotificationSender s = new NotificationSender();
+ mbs.registerMBean(s, notifierName);
+
+ for(int i = 0; i < protocols.length; i++) {
+ try {
+ System.out.println("dotest for " + protocols[i]);
+ dotest(protocols[i], s, notifierName);
+ }catch(Exception e) {
+ e.printStackTrace();
+ error = true;
+ }
+ }
+
+ if(error)
+ System.exit(1);
+
+ System.out.println("Test OK");
+
+ }catch(Exception e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+ private static void dotest(String protocol,
+ NotificationSender s,
+ ObjectName notifierName) throws Exception {
+ JMXConnector client = null;
+ JMXConnectorServer server = null;
+ JMXServiceURL u = null;
+ try {
+ u = new JMXServiceURL(protocol, null, 0);
+ server =
+ JMXConnectorServerFactory.newJMXConnectorServer(u,
+ null,
+ mbs);
+ checkNotifier(s, 0, "new ConnectorServer");
+
+ server.start();
+
+ checkNotifier(s, 0, "ConnectorServer start");
+
+ JMXServiceURL addr = server.getAddress();
+ client = JMXConnectorFactory.newJMXConnector(addr, null);
+
+ checkNotifier(s, 0, "new Connector");
+
+ client.connect(null);
+
+ checkNotifier(s, 0, "Connector connect");
+
+ MBeanServerConnection mbsc = client.getMBeanServerConnection();
+
+ final NotificationListener dummyListener =
+ new NotificationListener() {
+ public void handleNotification(Notification n,
+ Object o) {
+ // do nothing
+ return;
+ }
+ };
+
+ mbsc.addNotificationListener(notifierName,
+ dummyListener,
+ null,
+ null);
+
+ // 1 Listener is expected to be added by the ServerNotifForwader
+ checkNotifier(s, 1, "addNotificationListener");
+
+ mbsc.removeNotificationListener(notifierName,
+ dummyListener);
+ System.out.println("Test OK for " + protocol);
+ }catch(MalformedURLException e) {
+ System.out.println("Skipping URL " + u);
+ }
+ finally {
+ if(client != null)
+ client.close();
+ if(server != null)
+ server.stop();
+ }
+ }
+
+ private static void checkNotifier(NotificationSender s,
+ int expectedListenerCount,
+ String msg) throws Exception {
+ int count = s.getListenerCount();
+ if(count != expectedListenerCount) {
+ String errorMsg = "Invalid expected listener count [" +
+ expectedListenerCount + "], real [" + count +"] for " + msg;
+ System.out.println(errorMsg);
+ throw new Exception(errorMsg);
+ }
+
+ }
+}
diff --git a/test/javax/management/remote/mandatory/notif/NotificationBufferDeadlockTest.java b/test/javax/management/remote/mandatory/notif/NotificationBufferDeadlockTest.java
new file mode 100644
index 0000000..3698da4
--- /dev/null
+++ b/test/javax/management/remote/mandatory/notif/NotificationBufferDeadlockTest.java
@@ -0,0 +1,316 @@
+/*
+ * Copyright 2005-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6239400
+ * @summary Tests NotificationBuffer doesn't hold locks when adding listeners.
+ * @author Eamonn McManus
+ * @run clean NotificationBufferDeadlockTest
+ * @run build NotificationBufferDeadlockTest
+ * @run main NotificationBufferDeadlockTest
+ */
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.net.MalformedURLException;
+import java.util.List;
+import java.util.Set;
+import java.util.Vector;
+import javax.management.*;
+import javax.management.remote.*;
+
+/*
+ * Regression test for a rare but not unheard-of deadlock condition in
+ * the notification buffer support for connector servers.
+ * See bug 6239400 for the description of the bug and the example that
+ * showed it up.
+ *
+ * Here we test that, when the connector server adds its listener to an
+ * MBean, it is not holding a lock that would prevent another thread from
+ * emitting a notification (from that MBean or another one). This is
+ * important, because we don't know how user MBeans might implement
+ * NotificationBroadcaster.addNotificationListener, and in particular we
+ * can't be sure that the method is well-behaved and can never do a
+ * blocking operation, such as attempting to acquire a lock that is also
+ * acquired when notifications are emitted.
+ *
+ * The test creates a special MBean whose addNotificationListener method
+ * does the standard addNotificationListener logic inherited
+ * from NotificationBroadcasterSupport, then
+ * creates another thread that emits a notification from the same MBean.
+ * The addNotificationListener method waits for this thread to complete.
+ * If the notification buffer logic is incorrect, then emitting the
+ * notification will attempt to acquire the lock on the buffer, but that
+ * lock is being held by the thread that called addNotificationListener,
+ * so there will be deadlock.
+ *
+ * We use this DeadlockMBean several times. First, we create one and then
+ * add a remote listener to it. The first time you add a remote listener
+ * through a connector server, the connector server adds its own listener
+ * to all NotificationBroadcaster MBeans. If it holds a lock while doing
+ * this, we will see deadlock.
+ *
+ * Then we create a second DeadlockMBean. When a new MBean is created that
+ * is a NotificationBroadcaster, the connector server adds its listener to
+ * that MBean too. Again if it holds a lock while doing this, we will see
+ * deadlock.
+ *
+ * Finally, we do some magic with MBeanServerForwarders so that while
+ * queryNames is running (to find MBeans to which listeners must be added)
+ * we will create new MBeans. This tests that this tricky situation is
+ * handled correctly. It also tests the queryNames that is run when the
+ * notification buffer is being destroyed (to remove the listeners).
+ *
+ * We cause all of our test MBeans to emit exactly one notification and
+ * check that we have received exactly one notification from each MBean.
+ * If the logic for adding the notification buffer's listener is incorrect
+ * we could remove zero or two notifications from an MBean.
+ */
+public class NotificationBufferDeadlockTest {
+ public static void main(String[] args) throws Exception {
+ System.out.println("Check no deadlock if notif sent while initial " +
+ "remote listeners being added");
+ final String[] protos = {"rmi", "iiop", "jmxmp"};
+ for (String p : protos) {
+ try {
+ test(p);
+ } catch (Exception e) {
+ System.out.println("TEST FAILED: GOT EXCEPTION:");
+ e.printStackTrace(System.out);
+ failure = e.toString();
+ }
+ }
+ if (failure == null)
+ return;
+ else
+ throw new Exception("TEST FAILED: " + failure);
+ }
+
+ private static void test(String proto) throws Exception {
+ System.out.println("Testing protocol " + proto);
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ ObjectName testName = newName();
+ DeadlockTest test = new DeadlockTest();
+ mbs.registerMBean(test, testName);
+ JMXServiceURL url = new JMXServiceURL("service:jmx:" + proto + ":///");
+ JMXConnectorServer cs;
+ try {
+ cs =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
+ } catch (MalformedURLException e) {
+ System.out.println("...protocol not supported, ignoring");
+ return;
+ }
+
+ MBeanServerForwarder createDuringQueryForwarder = (MBeanServerForwarder)
+ Proxy.newProxyInstance(new Object() {}.getClass().getClassLoader(),
+ new Class[] {MBeanServerForwarder.class},
+ new CreateDuringQueryInvocationHandler());
+ cs.setMBeanServerForwarder(createDuringQueryForwarder);
+ cs.start();
+ JMXServiceURL addr = cs.getAddress();
+ JMXConnector cc = JMXConnectorFactory.connect(addr);
+ MBeanServerConnection mbsc = cc.getMBeanServerConnection();
+ try {
+ String fail = test(mbsc, testName);
+ if (fail != null)
+ System.out.println("FAILED: " + fail);
+ failure = fail;
+ } finally {
+ cc.close();
+ cs.stop();
+ }
+ }
+
+ private static String test(MBeanServerConnection mbsc,
+ ObjectName testName) throws Exception {
+
+ NotificationListener dummyListener = new NotificationListener() {
+ public void handleNotification(Notification n, Object h) {
+ }
+ };
+ thisFailure = null;
+ mbsc.addNotificationListener(testName, dummyListener, null, null);
+ if (thisFailure != null)
+ return thisFailure;
+ ObjectName newName = newName();
+ mbsc.createMBean(DeadlockTest.class.getName(), newName);
+ if (thisFailure != null)
+ return thisFailure;
+ Set<ObjectName> names =
+ mbsc.queryNames(new ObjectName("d:type=DeadlockTest,*"), null);
+ System.out.printf("...found %d test MBeans\n", names.size());
+
+ sources.clear();
+ countListener = new MyListener(names.size());
+
+ for (ObjectName name : names)
+ mbsc.addNotificationListener(name, countListener, null, null);
+ if (thisFailure != null)
+ return thisFailure;
+ for (ObjectName name : names)
+ mbsc.invoke(name, "send", null, null);
+
+ if (!countListener.waiting(MAX_WAITING_TIME)) {
+ return "did not get " + names.size() + " notifs as expected\n";
+ }
+
+ if (!sources.containsAll(names))
+ return "missing names: " + sources;
+ return thisFailure;
+ }
+
+ public static interface DeadlockTestMBean {
+ public void send();
+ }
+
+ public static class DeadlockTest extends NotificationBroadcasterSupport
+ implements DeadlockTestMBean {
+ @Override
+ public void addNotificationListener(NotificationListener listener,
+ NotificationFilter filter,
+ Object handback) {
+ super.addNotificationListener(listener, filter, handback);
+ Thread t = new Thread() {
+ @Override
+ public void run() {
+ Notification n =
+ new Notification("type", DeadlockTest.this, 0L);
+ DeadlockTest.this.sendNotification(n);
+ }
+ };
+ t.start();
+ try {
+ t.join(5000L);
+ } catch (Exception e) {
+ thisFailure = "Join exception: " + e;
+ }
+ if (t.isAlive())
+ thisFailure = "Deadlock detected";
+ }
+
+ public void send() {
+ sendNotification(new Notification(TESTING_TYPE, DeadlockTest.this, 1L));
+ }
+ }
+
+ private static class CreateDuringQueryInvocationHandler
+ implements InvocationHandler {
+ public Object invoke(Object proxy, Method m, Object[] args)
+ throws Throwable {
+ if (m.getName().equals("setMBeanServer")) {
+ mbs = (MBeanServer) args[0];
+ return null;
+ }
+ createMBeanIfQuery(m);
+ Object ret = m.invoke(mbs, args);
+ createMBeanIfQuery(m);
+ return ret;
+ }
+
+ private void createMBeanIfQuery(Method m) throws InterruptedException {
+ if (m.getName().equals("queryNames")) {
+ Thread t = new Thread() {
+ public void run() {
+ try {
+ mbs.createMBean(DeadlockTest.class.getName(),
+ newName());
+ } catch (Exception e) {
+ e.printStackTrace();
+ thisFailure = e.toString();
+ }
+ }
+ };
+ t.start();
+ t.join(5000);
+ if (t.isAlive())
+ failure = "Query deadlock detected";
+ }
+ }
+
+ private MBeanServer mbs;
+ }
+
+ private static synchronized ObjectName newName() {
+ try {
+ return new ObjectName("d:type=DeadlockTest,instance=" +
+ ++nextNameIndex);
+ } catch (MalformedObjectNameException e) {
+ throw new IllegalArgumentException("bad ObjectName", e);
+ }
+ }
+
+ private static class MyListener implements NotificationListener {
+ public MyListener(int waitNB) {
+ this.waitNB= waitNB;
+ }
+
+ public void handleNotification(Notification n, Object h) {
+ System.out.println("MyListener got: "+n.getSource()+" "+n.getType());
+
+ synchronized(this) {
+ if (TESTING_TYPE.equals(n.getType())) {
+ sources.add((ObjectName) n.getSource());
+
+ if (sources.size() == waitNB) {
+ this.notifyAll();
+ }
+ }
+ }
+ }
+
+ public boolean waiting(long timeout) {
+ final long startTime = System.currentTimeMillis();
+ long toWait = timeout;
+
+ synchronized(this) {
+ while(sources.size() < waitNB && toWait > 0) {
+ try {
+ this.wait(toWait);
+ } catch (InterruptedException ire) {
+ break;
+ }
+
+ toWait = timeout -
+ (System.currentTimeMillis() - startTime);
+ }
+ }
+
+ return sources.size() == waitNB;
+ }
+
+ private final int waitNB;
+ }
+
+ static String thisFailure;
+ static String failure;
+ static int nextNameIndex;
+ static final long MAX_WAITING_TIME = 10000;
+
+ private static MyListener countListener;
+ private static final List<ObjectName> sources = new Vector();
+
+ private static final String TESTING_TYPE = "testing_type";
+}
diff --git a/test/javax/management/remote/mandatory/notif/NotificationBufferTest.java b/test/javax/management/remote/mandatory/notif/NotificationBufferTest.java
new file mode 100644
index 0000000..0fa2121
--- /dev/null
+++ b/test/javax/management/remote/mandatory/notif/NotificationBufferTest.java
@@ -0,0 +1,451 @@
+/*
+ * Copyright 2003-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 7654321
+ * @summary Tests the NotificationBuffer class.
+ * @author Eamonn McManus
+ * @run clean NotificationBufferTest
+ * @run build NotificationBufferTest NotificationSender NotificationSenderMBean
+ * @run main NotificationBufferTest
+ */
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.HashMap;
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.MBeanServerNotification;
+import javax.management.Notification;
+import javax.management.NotificationFilter;
+import javax.management.NotificationFilterSupport;
+import javax.management.ObjectName;
+import javax.management.loading.MLet;
+
+import javax.management.remote.NotificationResult;
+import javax.management.remote.TargetedNotification;
+
+import com.sun.jmx.remote.internal.ArrayNotificationBuffer;
+import com.sun.jmx.remote.internal.NotificationBufferFilter;
+import com.sun.jmx.remote.internal.NotificationBuffer;
+
+public class NotificationBufferTest {
+
+ public static void main(String[] args) {
+// System.setProperty("java.util.logging.config.file",
+// "../../../../logging.properties");
+// // we are in <workspace>/build/test/JTwork/scratch
+ try {
+// java.util.logging.LogManager.getLogManager().readConfiguration();
+ boolean ok = test();
+ if (ok) {
+ System.out.println("Test completed");
+ return;
+ } else {
+ System.out.println("Test failed!");
+ System.exit(1);
+ }
+ } catch (Exception e) {
+ System.err.println("Unexpected exception: " + e);
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static boolean test() throws Exception {
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ Integer queuesize = new Integer(10);
+ HashMap env = new HashMap();
+ env.put(com.sun.jmx.remote.util.EnvHelp.BUFFER_SIZE_PROPERTY, queuesize);
+ final NotificationBuffer nb =
+ ArrayNotificationBuffer.getNotificationBuffer(mbs, env);
+
+ final ObjectName senderName = new ObjectName("dom:type=sender");
+ final ObjectName wildcardName = new ObjectName("*:*");
+ final String notifType =
+ MBeanServerNotification.REGISTRATION_NOTIFICATION;
+
+ Integer allListenerId = new Integer(99);
+ NotificationBufferFilter allListenerFilter =
+ makeFilter(allListenerId, wildcardName, null);
+ NotificationFilterSupport regFilter = new NotificationFilterSupport();
+ regFilter.enableType(notifType);
+
+ // Get initial sequence number
+ NotificationResult nr =
+ nb.fetchNotifications(allListenerFilter, 0, 0L, 0);
+ int nnotifs = nr.getTargetedNotifications().length;
+ if (nnotifs > 0) {
+ System.out.println("Expected 0 notifs for initial fetch, " +
+ "got " + nnotifs);
+ return false;
+ }
+ System.out.println("Got 0 notifs for initial fetch, OK");
+
+ long earliest = nr.getEarliestSequenceNumber();
+ long next = nr.getNextSequenceNumber();
+ if (earliest != next) {
+ System.out.println("Expected earliest==next in initial fetch, " +
+ "earliest=" + earliest + "; next=" + next);
+ return false;
+ }
+ System.out.println("Got earliest==next in initial fetch, OK");
+
+ mbs.createMBean(MLet.class.getName(), null);
+ mbs.createMBean(NotificationSender.class.getName(), senderName);
+
+ NotificationSenderMBean sender = (NotificationSenderMBean)
+ MBeanServerInvocationHandler.newProxyInstance(mbs,
+ senderName,
+ NotificationSenderMBean.class,
+ false);
+
+ /* We test here that MBeans already present when the
+ NotificationBuffer was created get a listener for the
+ buffer, as do MBeans created later. The
+ MBeanServerDelegate was already present, while the
+ NotificationSender was created later. */
+
+ // Check that the NotificationSender does indeed have a listener
+ /* Note we are dependent on the specifics of our JMX
+ implementation here. There is no guarantee that the MBean
+ creation listeners will have run to completion when
+ creation of the MBean returns. */
+ int nlisteners = sender.getListenerCount();
+ if (nlisteners != 1) {
+ System.out.println("Notification sender should have 1 listener, " +
+ "has " + nlisteners);
+ return false;
+ }
+ System.out.println("Notification sender has 1 listener, OK");
+
+ // Now we should see two creation notifications
+ nr = nb.fetchNotifications(allListenerFilter, next, 0L,
+ Integer.MAX_VALUE);
+ TargetedNotification[] tns = nr.getTargetedNotifications();
+ if (tns.length != 2) {
+ System.out.println("Expected 2 notifs, got: " +
+ Arrays.asList(tns));
+ return false;
+ }
+ if (!(tns[0].getNotification() instanceof MBeanServerNotification)
+ || !(tns[1].getNotification() instanceof MBeanServerNotification))
+ {
+ System.out.println("Expected 2 MBeanServerNotifications, got: " +
+ Arrays.asList(tns));
+ return false;
+ }
+ if (!tns[0].getListenerID().equals(tns[1].getListenerID())
+ || !tns[0].getListenerID().equals(allListenerId)) {
+ System.out.println("Bad listener IDs: " + Arrays.asList(tns));
+ return false;
+ }
+ System.out.println("Got 2 different MBeanServerNotifications, OK");
+
+ // If we ask for max 1 notifs, we should only get one
+ nr = nb.fetchNotifications(allListenerFilter, next, 0L, 1);
+ tns = nr.getTargetedNotifications();
+ if (tns.length != 1) {
+ System.out.println("Expected 1 notif, got: " + Arrays.asList(tns));
+ return false;
+ }
+ TargetedNotification tn1 = tns[0];
+ System.out.println("Got 1 notif when asked for 1, OK");
+
+ // Now we should get the other one
+ nr = nb.fetchNotifications(allListenerFilter, nr.getNextSequenceNumber(),
+ 0L, 1);
+ tns = nr.getTargetedNotifications();
+ if (tns.length != 1) {
+ System.out.println("Expected 1 notif, got: " + Arrays.asList(tns));
+ return false;
+ }
+ TargetedNotification tn2 = tns[0];
+ System.out.println("Got 1 notif when asked for 1 again, OK");
+
+ if (tn1.getNotification() == tn2.getNotification()) {
+ System.out.println("Returned same notif twice: " + tn1);
+ return false;
+ }
+ System.out.println("2 creation notifs are different, OK");
+
+ // Now we should get none (timeout is 0)
+ long oldNext = nr.getNextSequenceNumber();
+ nr = nb.fetchNotifications(allListenerFilter, oldNext, 0L,
+ Integer.MAX_VALUE);
+ tns = nr.getTargetedNotifications();
+ if (tns.length != 0) {
+ System.out.println("Expected 0 notifs, got: " +
+ Arrays.asList(tns));
+ return false;
+ }
+ System.out.println("Got 0 notifs with 0 timeout, OK");
+ if (nr.getNextSequenceNumber() != oldNext) {
+ System.out.println("Sequence number changed: " + oldNext + " -> " +
+ nr.getNextSequenceNumber());
+ return false;
+ }
+ System.out.println("Next seqno unchanged with 0 timeout, OK");
+
+ // Check that timeouts work
+ long startTime = System.currentTimeMillis();
+ nr = nb.fetchNotifications(allListenerFilter, oldNext, 250L,
+ Integer.MAX_VALUE);
+ tns = nr.getTargetedNotifications();
+ if (tns.length != 0) {
+ System.out.println("Expected 0 notifs, got: " +
+ Arrays.asList(tns));
+ return false;
+ }
+ long endTime = System.currentTimeMillis();
+ long elapsed = endTime - startTime;
+ if (elapsed < 250L) {
+ System.out.println("Elapsed time shorter than timeout: " +
+ elapsed);
+ return false;
+ }
+ System.out.println("Timeout worked, OK");
+
+ // Check that notification filtering works
+ NotificationFilter senderFilter = new NotificationFilter() {
+ public boolean isNotificationEnabled(Notification n) {
+ if (!(n instanceof MBeanServerNotification))
+ return false;
+ MBeanServerNotification mbsn = (MBeanServerNotification) n;
+ return (mbsn.getMBeanName().equals(senderName));
+ }
+ };
+ Integer senderListenerId = new Integer(88);
+ NotificationBufferFilter senderListenerFilter =
+ makeFilter(senderListenerId, wildcardName, senderFilter);
+ nr = nb.fetchNotifications(senderListenerFilter, 0, 1000L,
+ Integer.MAX_VALUE);
+ tns = nr.getTargetedNotifications();
+ if (tns.length != 1) {
+ System.out.println("Expected 1 notif, got: " + Arrays.asList(tns));
+ return false;
+ }
+ MBeanServerNotification mbsn =
+ (MBeanServerNotification) tns[0].getNotification();
+ if (!mbsn.getMBeanName().equals(senderName)) {
+ System.out.println("Expected notif with senderName, got: " +
+ mbsn + " (" + mbsn.getMBeanName() + ")");
+ return false;
+ }
+ System.out.println("Successfully applied NotificationFilter, OK");
+
+ // Now send 8 notifs to fill up our 10-element buffer
+ sender.sendNotifs("tiddly.pom", 8);
+ nr = nb.fetchNotifications(allListenerFilter, 0, 1000L,
+ Integer.MAX_VALUE);
+ tns = nr.getTargetedNotifications();
+ if (tns.length != 10) {
+ System.out.println("Expected 10 notifs, got: " +
+ Arrays.asList(tns));
+ return false;
+ }
+ System.out.println("Got full buffer of 10 notifications, OK");
+
+ // Check that the 10 notifs are the ones we expected
+ for (int i = 0; i < 10; i++) {
+ String expected =
+ (i < 2) ? notifType : "tiddly.pom";
+ String found = tns[i].getNotification().getType();
+ if (!found.equals(expected)) {
+ System.out.println("Notif " + i + " bad type: expected <" +
+ expected + ">, found <" + found + ">");
+ return false;
+ }
+ }
+ System.out.println("Notifs have right types, OK");
+
+ // Check that ObjectName filtering works
+ NotificationBufferFilter senderNameFilter =
+ makeFilter(new Integer(66), senderName, null);
+ nr = nb.fetchNotifications(senderNameFilter, 0, 0L,
+ Integer.MAX_VALUE);
+ tns = nr.getTargetedNotifications();
+ if (tns.length != 8) {
+ System.out.println("Bad result from ObjectName filtering: " +
+ Arrays.asList(tns));
+ return false;
+ }
+ System.out.println("ObjectName filtering works, OK");
+
+ // Send one more notif, which should cause the oldest one to drop
+ sender.sendNotifs("foo.bar", 1);
+ nr = nb.fetchNotifications(allListenerFilter, 0, 1000L,
+ Integer.MAX_VALUE);
+ if (nr.getEarliestSequenceNumber() <= earliest) {
+ System.out.println("Expected earliest to increase: " +
+ nr.getEarliestSequenceNumber() + " should be > "
+ + earliest);
+ return false;
+ }
+ System.out.println("Earliest notif dropped, OK");
+
+ // Check that the 10 notifs are the ones we expected
+ tns = nr.getTargetedNotifications();
+ for (int i = 0; i < 10; i++) {
+ String expected =
+ (i < 1) ? notifType
+ : (i < 9) ? "tiddly.pom" : "foo.bar";
+ String found = tns[i].getNotification().getType();
+ if (!found.equals(expected)) {
+ System.out.println("Notif " + i + " bad type: expected <" +
+ expected + ">, found <" + found + ">");
+ return false;
+ }
+ }
+ System.out.println("Notifs have right types, OK");
+
+ // Apply a filter that only selects the first notif, with max notifs 1,
+ // then check that it skipped past the others even though it already
+ // had its 1 notif
+ NotificationBufferFilter firstFilter =
+ makeFilter(new Integer(55), wildcardName, regFilter);
+ nr = nb.fetchNotifications(firstFilter, 0, 1000L, 1);
+ tns = nr.getTargetedNotifications();
+ if (tns.length != 1
+ || !tns[0].getNotification().getType().equals(notifType)) {
+ System.out.println("Unexpected return from filtered call: " +
+ Arrays.asList(tns));
+ return false;
+ }
+ nr = nb.fetchNotifications(allListenerFilter, nr.getNextSequenceNumber(),
+ 0L, 1000);
+ tns = nr.getTargetedNotifications();
+ if (tns.length != 0) {
+ System.out.println("Expected 0 notifs, got: " +
+ Arrays.asList(tns));
+ return false;
+ }
+
+ // Create a second, larger buffer, which should share the same notifs
+ nr = nb.fetchNotifications(allListenerFilter, 0,
+ 1000L, Integer.MAX_VALUE);
+ queuesize = new Integer(20);
+ env.put(com.sun.jmx.remote.util.EnvHelp.BUFFER_SIZE_PROPERTY, queuesize);
+ NotificationBuffer nb2 =
+ ArrayNotificationBuffer.getNotificationBuffer(mbs, env);
+ NotificationResult nr2 =
+ nb2.fetchNotifications(allListenerFilter, 0,
+ 1000L, Integer.MAX_VALUE);
+ if (nr.getEarliestSequenceNumber() != nr2.getEarliestSequenceNumber()
+ || nr.getNextSequenceNumber() != nr2.getNextSequenceNumber()
+ || !sameTargetedNotifs(nr.getTargetedNotifications(),
+ nr2.getTargetedNotifications()))
+ return false;
+ System.out.println("Adding second buffer preserved notif list, OK");
+
+ // Check that the capacity is now 20
+ sender.sendNotifs("propter.hoc", 10);
+ nr2 = nb2.fetchNotifications(allListenerFilter, 0,
+ 1000L, Integer.MAX_VALUE);
+ if (nr.getEarliestSequenceNumber() !=
+ nr2.getEarliestSequenceNumber()) {
+ System.out.println("Earliest seq number changed after notifs " +
+ "that should have fit");
+ return false;
+ }
+ TargetedNotification[] tns2 = new TargetedNotification[10];
+ Arrays.asList(nr2.getTargetedNotifications()).subList(0, 10).toArray(tns2);
+ if (!sameTargetedNotifs(nr.getTargetedNotifications(), tns2)) {
+ System.out.println("Early notifs changed after notifs " +
+ "that should have fit");
+ return false;
+ }
+ System.out.println("New notifications fit in now-larger buffer, OK");
+
+ // Drop the second buffer and check that the capacity shrinks
+ nb2.dispose();
+ NotificationResult nr3 =
+ nb.fetchNotifications(allListenerFilter, 0,
+ 1000L, Integer.MAX_VALUE);
+ if (nr3.getEarliestSequenceNumber() != nr.getNextSequenceNumber()) {
+ System.out.println("After shrink, notifs not dropped as expected");
+ return false;
+ }
+ if (nr3.getNextSequenceNumber() != nr2.getNextSequenceNumber()) {
+ System.out.println("After shrink, next seq no does not match");
+ return false;
+ }
+ tns2 = new TargetedNotification[10];
+ Arrays.asList(nr2.getTargetedNotifications()).subList(10, 20).toArray(tns2);
+ if (!sameTargetedNotifs(nr3.getTargetedNotifications(), tns2)) {
+ System.out.println("Later notifs not preserved after shrink");
+ return false;
+ }
+ System.out.println("Dropping second buffer shrank capacity, OK");
+
+ // Final test: check that destroying the final shared buffer
+ // removes its listeners
+ nb.dispose();
+ nlisteners = sender.getListenerCount();
+ if (nlisteners != 0) {
+ System.out.println("Disposing buffer should leave 0 listeners, " +
+ "but notification sender has " + nlisteners);
+ return false;
+ }
+ System.out.println("Dropping first buffer drops listeners, OK");
+
+ return true;
+ }
+
+ private static boolean sameTargetedNotifs(TargetedNotification[] tn1,
+ TargetedNotification[] tn2) {
+ if (tn1.length != tn2.length) {
+ System.out.println("Not same length");
+ return false;
+ }
+ for (int i = 0; i < tn1.length; i++) {
+ TargetedNotification n1 = tn1[i];
+ TargetedNotification n2 = tn2[i];
+ if (n1.getNotification() != n2.getNotification()
+ || !n1.getListenerID().equals(n2.getListenerID()))
+ return false;
+ }
+ return true;
+ }
+
+ private static NotificationBufferFilter makeFilter(final Integer id,
+ final ObjectName pattern,
+ final NotificationFilter filter) {
+ return new NotificationBufferFilter() {
+ public void apply(List<TargetedNotification> notifs,
+ ObjectName source, Notification notif) {
+ if (pattern.apply(source)) {
+ if (filter == null || filter.isNotificationEnabled(notif))
+ notifs.add(new TargetedNotification(notif, id));
+ }
+ }
+ };
+ };
+}
diff --git a/test/javax/management/remote/mandatory/notif/NotificationEmissionTest.java b/test/javax/management/remote/mandatory/notif/NotificationEmissionTest.java
new file mode 100644
index 0000000..1c42043
--- /dev/null
+++ b/test/javax/management/remote/mandatory/notif/NotificationEmissionTest.java
@@ -0,0 +1,355 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5106721
+ * @summary Check the emission of notifications when a Security Manager is
+ * installed. Test the property "jmx.remote.x.check.notification.emission".
+ * @author Luis-Miguel Alventosa
+ * @run clean NotificationEmissionTest
+ * @run build NotificationEmissionTest
+ * @run main NotificationEmissionTest 1
+ * @run main NotificationEmissionTest 2
+ * @run main NotificationEmissionTest 3
+ * @run main NotificationEmissionTest 4
+ * @run main NotificationEmissionTest 5
+ */
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerFactory;
+import javax.management.Notification;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.remote.JMXAuthenticator;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXPrincipal;
+import javax.management.remote.JMXServiceURL;
+import javax.security.auth.Subject;
+
+public class NotificationEmissionTest {
+
+ public class CustomJMXAuthenticator implements JMXAuthenticator {
+ public Subject authenticate(Object credentials) {
+ String role = ((String[]) credentials)[0];
+ echo("Create principal with name = " + role);
+ return new Subject(true,
+ Collections.singleton(new JMXPrincipal(role)),
+ Collections.EMPTY_SET,
+ Collections.EMPTY_SET);
+ }
+ }
+
+ public interface NBMBean {
+ public void emitNotification(int seqnum, ObjectName name);
+ }
+
+ public static class NB
+ extends NotificationBroadcasterSupport
+ implements NBMBean {
+ public void emitNotification(int seqnum, ObjectName name) {
+ if (name == null) {
+ sendNotification(new Notification("nb", this, seqnum));
+ } else {
+ sendNotification(new Notification("nb", name, seqnum));
+ }
+ }
+ }
+
+ public class Listener implements NotificationListener {
+ public List<Notification> notifs = new ArrayList<Notification>();
+ public void handleNotification(Notification n, Object h) {
+ echo("handleNotification:");
+ echo("\tNotification = " + n);
+ echo("\tNotification.SeqNum = " + n.getSequenceNumber());
+ echo("\tHandback = " + h);
+ notifs.add(n);
+ }
+ }
+
+ public int checkNotifs(int size,
+ List<Notification> received,
+ List<ObjectName> expected) {
+ if (received.size() != size) {
+ echo("Error: expecting " + size + " notifications");
+ return 1;
+ } else {
+ for (Notification n : received) {
+ echo("Received notification: " + n);
+ if (!n.getType().equals("nb")) {
+ echo("Notification type must be \"nb\"");
+ return 1;
+ }
+ ObjectName o = (ObjectName) n.getSource();
+ int index = (int) n.getSequenceNumber();
+ ObjectName nb = expected.get(index);
+ if (!o.equals(nb)) {
+ echo("Notification source must be " + nb);
+ return 1;
+ }
+ }
+ }
+ return 0;
+ }
+
+ public int runTest(int testcase) throws Exception {
+ echo("\n=-=-= Running testcase " + testcase + " =-=-=");
+ switch (testcase) {
+ case 1:
+ return testNotificationEmissionProperty();
+ case 2:
+ return testNotificationEmissionPositive(false);
+ case 3:
+ return testNotificationEmissionNegative(false);
+ case 4:
+ return testNotificationEmissionPositive(true);
+ case 5:
+ return testNotificationEmissionNegative(true);
+ default:
+ echo("Invalid testcase");
+ return 1;
+ }
+ }
+
+ public int testNotificationEmissionProperty(boolean exception,
+ Object propValue)
+ throws Exception {
+ try {
+ testNotificationEmission(propValue);
+ if (exception) {
+ echo("Did not get expected exception for value: " + propValue);
+ return 1;
+ } else {
+ echo("Property has been correctly set to value: " + propValue);
+ }
+ } catch (Exception e) {
+ if (exception) {
+ echo("Got expected exception for value: " + propValue);
+ echo("Exception: " + e);
+ } else {
+ echo("Got unexpected exception for value: " + propValue);
+ echo("Exception: " + e);
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ public int testNotificationEmissionProperty() throws Exception {
+ int error = 0;
+ error += testNotificationEmissionProperty(true, new Boolean(false));
+ error += testNotificationEmissionProperty(true, new Boolean(true));
+ error += testNotificationEmissionProperty(true, "dummy");
+ error += testNotificationEmissionProperty(false, "false");
+ error += testNotificationEmissionProperty(false, "true");
+ error += testNotificationEmissionProperty(false, "FALSE");
+ error += testNotificationEmissionProperty(false, "TRUE");
+ return error;
+ }
+
+ public int testNotificationEmissionPositive(boolean prop) throws Exception {
+ return testNotificationEmission(prop, "true", true, true);
+ }
+
+ public int testNotificationEmissionNegative(boolean prop) throws Exception {
+ return testNotificationEmission(prop, "true", true, false);
+ }
+
+ public int testNotificationEmission(Object propValue) throws Exception {
+ return testNotificationEmission(true, propValue, false, true);
+ }
+
+ public int testNotificationEmission(boolean prop,
+ Object propValue,
+ boolean sm,
+ boolean policyPositive)
+ throws Exception {
+
+ JMXConnectorServer server = null;
+ JMXConnector client = null;
+
+ // Set policy file
+ //
+ String policyFile =
+ System.getProperty("test.src") + File.separator +
+ (policyPositive ? "policy.positive" : "policy.negative");
+ echo("\nSetting policy file " + policyFile);
+ System.setProperty("java.security.policy", policyFile);
+
+ // Create a new MBeanServer
+ //
+ final MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ try {
+ // Create server environment map
+ //
+ final Map<String,Object> env = new HashMap<String,Object>();
+ env.put("jmx.remote.authenticator", new CustomJMXAuthenticator());
+ if (prop)
+ env.put("jmx.remote.x.check.notification.emission", propValue);
+
+ // Create the JMXServiceURL
+ //
+ final JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://");
+
+ // Create a JMXConnectorServer
+ //
+ server = JMXConnectorServerFactory.newJMXConnectorServer(url,
+ env,
+ mbs);
+
+ // Start the JMXConnectorServer
+ //
+ server.start();
+
+ // Create server environment map
+ //
+ final Map<String,Object> cenv = new HashMap<String,Object>();
+ String[] credentials = new String[] { "role" , "password" };
+ cenv.put("jmx.remote.credentials", credentials);
+
+ // Create JMXConnector and connect to JMXConnectorServer
+ //
+ client = JMXConnectorFactory.connect(server.getAddress(), cenv);
+
+ // Get non-secure MBeanServerConnection
+ //
+ final MBeanServerConnection mbsc =
+ client.getMBeanServerConnection();
+
+ // Create NB MBean
+ //
+ ObjectName nb1 = ObjectName.getInstance("domain:type=NB,name=1");
+ ObjectName nb2 = ObjectName.getInstance("domain:type=NB,name=2");
+ ObjectName nb3 = ObjectName.getInstance("domain:type=NB,name=3");
+ mbsc.createMBean(NB.class.getName(), nb1);
+ mbsc.createMBean(NB.class.getName(), nb2);
+ mbsc.createMBean(NB.class.getName(), nb3);
+
+ // Add notification listener
+ //
+ Listener li = new Listener();
+ mbsc.addNotificationListener(nb1, li, null, null);
+ mbsc.addNotificationListener(nb2, li, null, null);
+
+ // Set security manager
+ //
+ if (sm) {
+ echo("Setting SM");
+ System.setSecurityManager(new SecurityManager());
+ }
+
+ // Invoke the "sendNotification" method
+ //
+ mbsc.invoke(nb1, "emitNotification",
+ new Object[] {0, null},
+ new String[] {"int", "javax.management.ObjectName"});
+ mbsc.invoke(nb2, "emitNotification",
+ new Object[] {1, null},
+ new String[] {"int", "javax.management.ObjectName"});
+ mbsc.invoke(nb2, "emitNotification",
+ new Object[] {2, nb3},
+ new String[] {"int", "javax.management.ObjectName"});
+
+ // Wait for notifications to be emitted
+ //
+ Thread.sleep(2000);
+
+ // Remove notification listener
+ //
+ mbsc.removeNotificationListener(nb1, li);
+ mbsc.removeNotificationListener(nb2, li);
+
+ int result = 0;
+ List<ObjectName> sources = new ArrayList();
+ sources.add(nb1);
+ sources.add(nb2);
+ sources.add(nb3);
+
+ if (prop && sm && !policyPositive) {
+ // List must contain two notifs from sources nb2 and nb3
+ //
+ result = checkNotifs(2, li.notifs, sources);
+ } else {
+ // List must contain three notifs from sources nb1, nb2 and nb3
+ //
+ result = checkNotifs(3, li.notifs, sources);
+ }
+ if (result > 0) {
+ return result;
+ }
+ } finally {
+ // Close the connection
+ //
+ if (client != null)
+ client.close();
+
+ // Stop the connector server
+ //
+ if (server != null)
+ server.stop();
+
+ // Release the MBeanServer
+ //
+ if (mbs != null)
+ MBeanServerFactory.releaseMBeanServer(mbs);
+ }
+
+ return 0;
+ }
+
+ private static void echo(String message) {
+ System.out.println(message);
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ echo("\n--- Check the emission of notifications " +
+ "when a Security Manager is installed ---");
+
+ NotificationEmissionTest net = new NotificationEmissionTest();
+
+ int error = 0;
+
+ error += net.runTest(Integer.parseInt(args[0]));
+
+ if (error > 0) {
+ final String msg = "\nTest FAILED! Got " + error + " error(s)";
+ echo(msg);
+ throw new IllegalArgumentException(msg);
+ } else {
+ echo("\nTest PASSED!");
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/notif/NotificationSender.java b/test/javax/management/remote/mandatory/notif/NotificationSender.java
new file mode 100644
index 0000000..5351458
--- /dev/null
+++ b/test/javax/management/remote/mandatory/notif/NotificationSender.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * build @BUILD_TAG_PLACEHOLDER@
+ *
+ * @COPYRIGHT_MINI_LEGAL_NOTICE_PLACEHOLDER@
+ */
+
+import javax.management.ListenerNotFoundException;
+import javax.management.Notification;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+
+public class NotificationSender
+ extends NotificationBroadcasterSupport
+ implements NotificationSenderMBean {
+
+ public void sendNotifs(String type, int count) {
+ for (int i = 0; i < count; i++) {
+ Notification n = new Notification(type, this, newSeqNo());
+ sendNotification(n);
+ }
+ }
+
+ public int getListenerCount() {
+ return listenerCount;
+ }
+
+ public void addNotificationListener(NotificationListener l,
+ NotificationFilter f,
+ Object h) {
+ super.addNotificationListener(l, f, h);
+ listenerCount++;
+ }
+
+ public void removeNotificationListener(NotificationListener l)
+ throws ListenerNotFoundException {
+ super.removeNotificationListener(l);
+ listenerCount--;
+ }
+
+ public void removeNotificationListener(NotificationListener l,
+ NotificationFilter f,
+ Object h)
+ throws ListenerNotFoundException {
+ super.removeNotificationListener(l, f, h);
+ listenerCount--;
+ }
+
+ private static long newSeqNo() {
+ return ++seqNo;
+ }
+
+ private static long seqNo = 0;
+ private int listenerCount = 0;
+}
diff --git a/test/javax/management/remote/mandatory/notif/NotificationSenderMBean.java b/test/javax/management/remote/mandatory/notif/NotificationSenderMBean.java
new file mode 100644
index 0000000..cc8b311
--- /dev/null
+++ b/test/javax/management/remote/mandatory/notif/NotificationSenderMBean.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * build @BUILD_TAG_PLACEHOLDER@
+ *
+ * @COPYRIGHT_MINI_LEGAL_NOTICE_PLACEHOLDER@
+ */
+
+public interface NotificationSenderMBean {
+ public void sendNotifs(String type, int count);
+
+ public int getListenerCount();
+}
diff --git a/test/javax/management/remote/mandatory/notif/RMINotifTest.java b/test/javax/management/remote/mandatory/notif/RMINotifTest.java
new file mode 100644
index 0000000..327274c
--- /dev/null
+++ b/test/javax/management/remote/mandatory/notif/RMINotifTest.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2003-2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test RMINotifTest.java
+ * @bug 7654321
+ * @summary Tests to receive notifications for opened and closed connect
+ions
+ * @author sjiang
+ * @run clean RMINotifTest
+ * @run build RMINotifTest
+ * @run main RMINotifTest
+ */
+
+// java imports
+//
+import java.io.IOException;
+import java.net.UnknownHostException;
+
+import java.rmi.*;
+import java.rmi.registry.*;
+import java.util.Random;
+
+// JMX imports
+//
+import javax.management.* ;
+
+import javax.management.remote.*;
+import javax.management.remote.rmi.*;
+import javax.management.remote.JMXServiceURL;
+
+public class RMINotifTest {
+
+ public static void main(String[] args) {
+ try {
+ // create a rmi registry
+ Registry reg = null;
+ int port = 6666;
+ final Random r = new Random();
+
+ while(port++<7000) {
+ try {
+ reg = LocateRegistry.createRegistry(++port);
+ System.out.println("Creation of rmi registry succeeded. Running on port " + port);
+ break;
+ } catch (RemoteException re) {
+ // no problem
+ }
+ }
+
+ if (reg == null) {
+ System.out.println("Failed to create a RMI registry, "+
+ "the ports from 6666 to 6999 are all occupied.");
+ System.exit(1);
+ }
+
+ // create a MBeanServer
+ MBeanServer server = MBeanServerFactory.createMBeanServer();
+
+ // create a notif emitter mbean
+ ObjectName mbean = new ObjectName ("Default:name=NotificationEmitter");
+
+ server.registerMBean(new NotificationEmitter(), mbean);
+
+ // create a rmi server
+ JMXServiceURL url =
+ new JMXServiceURL("rmi", null, port,
+ "/jndi/rmi://:" + port + "/server" + port);
+ System.out.println("RMIConnectorServer address " + url);
+
+ JMXConnectorServer sServer =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, null,
+ null);
+
+ ObjectInstance ss = server.registerMBean(sServer, new ObjectName("Default:name=RmiConnectorServer"));
+
+ sServer.start();
+
+ // create a rmi client
+ JMXConnector rmiConnection =
+ JMXConnectorFactory.newJMXConnector(url, null);
+ rmiConnection.connect(null);
+ MBeanServerConnection client = rmiConnection.getMBeanServerConnection();
+
+ // add listener at the client side
+ client.addNotificationListener(mbean, listener, null, null);
+
+ //ask to send notifs
+ Object[] params = new Object[1];
+ String[] signatures = new String[1];
+
+ params[0] = new Integer(nb);
+ signatures[0] = "java.lang.Integer";
+
+ client.invoke(mbean, "sendNotifications", params, signatures);
+
+ // waiting ...
+ synchronized (lock) {
+ if (receivedNotifs != nb) {
+ lock.wait(10000);
+ System.out.println(">>> Received notifications..."+receivedNotifs);
+
+ }
+ }
+
+ // check
+ if (receivedNotifs != nb) {
+ System.exit(1);
+ } else {
+ System.out.println("The client received all notifications.");
+ }
+
+ // remove listener
+ client.removeNotificationListener(mbean, listener);
+
+ // more test
+ NotificationFilterSupport filter = new NotificationFilterSupport();
+ Object o = new Object();
+ client.addNotificationListener(mbean, listener, filter, o);
+ client.removeNotificationListener(mbean, listener, filter, o);
+
+ sServer.stop();
+
+// // clean
+// client.unregisterMBean(mbean);
+// rmiConnection.close();
+
+// Thread.sleep(2000);
+
+
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+//--------------------------
+// private classes
+//--------------------------
+
+ private static class Listener implements NotificationListener {
+ public void handleNotification(Notification notif, Object handback) {
+ if(++receivedNotifs == nb) {
+ synchronized(lock) {
+ lock.notifyAll();
+ }
+ }
+ }
+ }
+
+ public static class NotificationEmitter extends NotificationBroadcasterSupport implements NotificationEmitterMBean {
+// public NotificationEmitter() {
+// super();
+// System.out.println("===NotificationEmitter: new instance.");
+// }
+
+ /**
+ * Returns a NotificationInfo object containing the name of the Java class of the notification
+ * and the notification types sent by this notification broadcaster.
+ */
+ public MBeanNotificationInfo[] getNotificationInfo() {
+
+ MBeanNotificationInfo[] ntfInfoArray = new MBeanNotificationInfo[1];
+
+ String[] ntfTypes = new String[1];
+ ntfTypes[0] = myType;
+
+ ntfInfoArray[0] = new MBeanNotificationInfo(ntfTypes,
+ "javax.management.Notification",
+ "Notifications sent by the NotificationEmitter");
+ return ntfInfoArray;
+ }
+
+// public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) {
+// super.addNotificationListener(listener, filter, handback);
+
+// System.out.println("============NotificationEmitter: add new listener");
+// }
+
+ /**
+ * Send a Notification object with the specified times.
+ * The sequence number will be from zero to times-1.
+ *
+ * @param nb The number of notifications to send
+ */
+ public void sendNotifications(Integer nb) {
+ System.out.println("===NotificationEmitter: be asked to send notifications: "+nb);
+
+ Notification notif;
+ for (int i=1; i<=nb.intValue(); i++) {
+ notif = new Notification(myType, this, i);
+ sendNotification(notif);
+ }
+ }
+
+ private String myType = "notification.my_notification";
+ }
+
+ public interface NotificationEmitterMBean {
+ public void sendNotifications(Integer nb);
+ }
+
+ private static NotificationListener listener = new Listener();
+
+ private static int nb = 10;
+ private static int receivedNotifs = 0;
+ private static int[] lock = new int[0];
+}
diff --git a/test/javax/management/remote/mandatory/notif/ServerNotifs.java b/test/javax/management/remote/mandatory/notif/ServerNotifs.java
new file mode 100644
index 0000000..fa8d5a2
--- /dev/null
+++ b/test/javax/management/remote/mandatory/notif/ServerNotifs.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test ServerNotifs.java
+ * @bug 7654321
+ * @summary Tests the reception of the notifications for opened and closed
+ * connections
+ * @author sjiang
+ * @run clean ServerNotifs
+ * @run build ServerNotifs
+ * @run main ServerNotifs
+ */
+
+// JAVA
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+// JMX
+import javax.management.*;
+
+// RJMX
+import javax.management.remote.*;
+
+public class ServerNotifs {
+
+ private static void echo(String msg) {
+ System.out.println(msg);
+ }
+
+ public static void main(String[] args) {
+
+ try {
+ // Create MBeanServer
+ //
+ echo("---Create the MBeanServer...");
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ // Create RMIConnectorServer
+ //
+ echo("---Instantiate the RMIConnectorServer...");
+ JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://");
+ JMXConnectorServer cs =
+ JMXConnectorServerFactory.newJMXConnectorServer(url,
+ null,
+ mbs);
+
+ echo("---Register the RMIConnectorServer in the MBeanServer...");
+ ObjectName on =
+ new ObjectName("JMXConnectors:name=RMIConnectorServer");
+ mbs.registerMBean(cs, on);
+
+ echo("---Start the RMIConnectorServer...");
+ cs.start();
+ url = cs.getAddress();
+ echo("---RMIConnectorServer address: " + url);
+
+ echo("---Add a local listener to the RMIConnectorServer...");
+ mbs.addNotificationListener(on, new MyListener(), null, null);
+
+ // Create RMI connector
+ //
+ echo("---Instantiate the RMIConnector...");
+ JMXConnector c = JMXConnectorFactory.newJMXConnector(url, null);
+
+ // Expect to get a "jmx.remote.connection.opened" notification
+ //
+ echo("---Open connection...");
+ c.connect(null);
+ Thread.sleep(100);
+
+ // Expect to get a "jmx.remote.connection.closed" notification
+ //
+ echo("---Close connection...");
+ c.close();
+ Thread.sleep(100);
+
+ // Waiting for all notifications
+ //
+ synchronized(waiting) {
+ if (!succeeded) {
+ final long waitingTime = 10000;
+ long remainingTime = waitingTime;
+ final long startTime = System.currentTimeMillis();
+ while (!succeeded && remainingTime > 0) {
+ waiting.wait(remainingTime);
+ remainingTime = waitingTime -
+ (System.currentTimeMillis() - startTime);
+ }
+ }
+ }
+
+ // Stop the RMIConnectorServer
+ //
+ echo("---Stop the RMIConnectorServer...");
+ cs.stop();
+
+ if (!succeeded) {
+ System.out.println("Timeout, did not get all notifications!");
+ System.exit(1);
+ }
+ } catch (MBeanException mbe) {
+ echo("---Test failed.");
+ echo("---Got exception: " + mbe);
+ mbe.getTargetException().printStackTrace();
+ System.exit(1);
+ } catch (RuntimeOperationsException roe) {
+ echo("---Test failed.");
+ echo("---Got exception: " + roe);
+ roe.getTargetException().printStackTrace();
+ System.exit(1);
+ } catch (Throwable t) {
+ echo("---Test failed.");
+ echo("---Got throwable: " + t);
+ t.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static class MyListener implements NotificationListener {
+ public void handleNotification(Notification n, Object o) {
+ if (index == types.length) {
+ return;
+ }
+ echo("---Got a notification: " + n.getType());
+ echo(n.getMessage());
+ if (n instanceof JMXConnectionNotification) {
+ if (!n.getType().equals(types[index++])) {
+ System.out.println("Waiting to get a notification with " +
+ "type: " + types[index-1] + ", but " +
+ "got one with type: " + n.getType());
+ System.exit(1);
+ }
+ if (index == types.length) {
+ synchronized(waiting) {
+ succeeded = true;
+ waiting.notify();
+ }
+ }
+ }
+ }
+ }
+
+ private static final String[] types =
+ new String[] {JMXConnectionNotification.OPENED,
+ JMXConnectionNotification.CLOSED};
+ private static int index = 0;
+ private static int[] waiting = new int[0];
+ private static boolean succeeded = false;
+}
diff --git a/test/javax/management/remote/mandatory/notif/UnexpectedNotifTest.java b/test/javax/management/remote/mandatory/notif/UnexpectedNotifTest.java
new file mode 100644
index 0000000..0b3aa2b
--- /dev/null
+++ b/test/javax/management/remote/mandatory/notif/UnexpectedNotifTest.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 7654321
+ * @summary Tests whether a listener receives notifs emitted before the
+ * listener is registered.
+ * @author Shanliang JIANG
+ * @run clean UnexpectedNotifTest
+ * @run build UnexpectedNotifTest
+ * @run main UnexpectedNotifTest
+ */
+
+// java imports
+//
+import java.io.IOException;
+
+// JMX imports
+//
+import javax.management.*;
+import javax.management.remote.*;
+
+public class UnexpectedNotifTest {
+
+ public static void main(String[] args) throws Exception {
+ String[] protos = null;
+ try {
+ Class.forName("javax.management.remote.jmxmp.JMXMPConnectorServer");
+ protos = new String[2];
+ protos[0] = "rmi";
+ protos[1] = "jmxmp";
+ } catch (ClassNotFoundException e) {
+ protos = new String[1];
+ protos[0] = "rmi";
+ }
+ for (int i = 0; i < protos.length; i++) {
+ System.out.println("Unexpected notifications test for protocol " +
+ protos[i]);
+ MBeanServer mbs = null;
+ try {
+ // Create a MBeanServer
+ //
+ mbs = MBeanServerFactory.createMBeanServer();
+
+ // Create a NotificationEmitter MBean
+ //
+ mbean = new ObjectName ("Default:name=NotificationEmitter");
+ mbs.registerMBean(new NotificationEmitter(), mbean);
+
+ // Create a connector server
+ //
+ url = new JMXServiceURL("service:jmx:" + protos[i] + "://");
+ server = JMXConnectorServerFactory.newJMXConnectorServer(url,
+ null,
+ mbs);
+
+ mbs.registerMBean(
+ server,
+ new ObjectName("Default:name=ConnectorServer"));
+
+ server.start();
+
+ url = server.getAddress();
+
+ for (int j = 0; j < 2; j++) {
+ test();
+ }
+ } finally {
+ // Stop server
+ //
+ server.stop();
+ // Release the MBeanServer
+ //
+ MBeanServerFactory.releaseMBeanServer(mbs);
+ }
+ }
+ }
+
+ private static void test() throws Exception {
+ // Create client
+ //
+ JMXConnector connector = JMXConnectorFactory.connect(url);
+ MBeanServerConnection client = connector.getMBeanServerConnection();
+
+ // Add listener at the client side
+ //
+ client.addNotificationListener(mbean, listener, null, null);
+
+ // Cleanup
+ //
+ receivedNotifs = 0;
+
+ // Ask to send notifs
+ //
+ Object[] params = new Object[] {new Integer(nb)};
+ String[] signatures = new String[] {"java.lang.Integer"};
+
+ client.invoke(mbean, "sendNotifications", params, signatures);
+
+ // Waiting...
+ //
+ synchronized (lock) {
+ for (int i = 0; i < 10; i++) {
+ if (receivedNotifs < nb) {
+ lock.wait(1000);
+ }
+ }
+ }
+
+ // Waiting again to ensure no more notifs
+ //
+ Thread.sleep(3000);
+
+ synchronized (lock) {
+ if (receivedNotifs != nb) {
+ throw new Exception("The client expected to receive " +
+ nb + " notifs, but got " + receivedNotifs);
+ }
+ }
+
+ // Remove listener
+ //
+ client.removeNotificationListener(mbean, listener);
+
+ connector.close();
+ }
+
+ //--------------------------
+ // private classes
+ //--------------------------
+
+ private static class Listener implements NotificationListener {
+ public void handleNotification(Notification notif, Object handback) {
+ System.out.println("Received: " + notif + " (" +
+ notif.getSequenceNumber() + ")");
+ synchronized(lock) {
+ if(++receivedNotifs == nb) {
+ lock.notifyAll();
+ } else if (receivedNotifs > nb) {
+ System.out.println("The client expected to receive " +
+ nb + " notifs, but got at least " +
+ receivedNotifs);
+ System.exit(1);
+ }
+ }
+ }
+ }
+
+ public static class NotificationEmitter
+ extends NotificationBroadcasterSupport
+ implements NotificationEmitterMBean {
+
+ /**
+ * Returns a NotificationInfo object containing the name of the Java
+ * class of the notification and the notification types sent by this
+ * notification broadcaster.
+ */
+ public MBeanNotificationInfo[] getNotificationInfo() {
+
+ MBeanNotificationInfo[] ntfInfoArray = new MBeanNotificationInfo[1];
+
+ String[] ntfTypes = new String[1];
+ ntfTypes[0] = myType;
+
+ ntfInfoArray[0] = new MBeanNotificationInfo(
+ ntfTypes,
+ "javax.management.Notification",
+ "Notifications sent by the NotificationEmitter");
+ return ntfInfoArray;
+ }
+
+ /**
+ * Send a Notification object with the specified times.
+ * The sequence number will be from zero to times-1.
+ *
+ * @param nb The number of notifications to send
+ */
+ public void sendNotifications(Integer nb) {
+ System.out.println("NotificationEmitter: asked to send " +
+ "notifications: " + nb);
+
+ Notification notif;
+ for (int i = 1; i <= nb.intValue(); i++) {
+ notif = new Notification(myType, this, ++seqno);
+ sendNotification(notif);
+ }
+ }
+
+ private String myType = "notification.my_notification";
+ }
+
+ public interface NotificationEmitterMBean {
+ public void sendNotifications(Integer nb);
+ }
+
+ private static JMXConnectorServer server;
+ private static JMXServiceURL url;
+ private static ObjectName mbean;
+ private static NotificationListener listener = new Listener();
+
+ private static int nb = 10;
+ private static int receivedNotifs = 0;
+ private static int[] lock = new int[0];
+ private static volatile long seqno;
+}
diff --git a/test/javax/management/remote/mandatory/notif/policy.negative b/test/javax/management/remote/mandatory/notif/policy.negative
new file mode 100644
index 0000000..c6ca50a
--- /dev/null
+++ b/test/javax/management/remote/mandatory/notif/policy.negative
@@ -0,0 +1,7 @@
+grant {
+ permission java.net.SocketPermission "*:*", "accept,connect,listen,resolve";
+ permission javax.management.MBeanServerPermission "*";
+ permission javax.management.MBeanPermission "*", "invoke";
+ permission javax.management.MBeanPermission "[domain:type=NB,name=2]", "addNotificationListener";
+ permission javax.management.MBeanPermission "*", "removeNotificationListener";
+};
diff --git a/test/javax/management/remote/mandatory/notif/policy.positive b/test/javax/management/remote/mandatory/notif/policy.positive
new file mode 100644
index 0000000..ddd142d
--- /dev/null
+++ b/test/javax/management/remote/mandatory/notif/policy.positive
@@ -0,0 +1,7 @@
+grant {
+ permission java.net.SocketPermission "*:*", "accept,connect,listen,resolve";
+ permission javax.management.MBeanServerPermission "*";
+ permission javax.management.MBeanPermission "*", "invoke";
+ permission javax.management.MBeanPermission "*", "addNotificationListener";
+ permission javax.management.MBeanPermission "*", "removeNotificationListener";
+};
diff --git a/test/javax/management/remote/mandatory/passwordAccessFile/NonJMXPrincipalsTest.java b/test/javax/management/remote/mandatory/passwordAccessFile/NonJMXPrincipalsTest.java
new file mode 100644
index 0000000..bb47a1b
--- /dev/null
+++ b/test/javax/management/remote/mandatory/passwordAccessFile/NonJMXPrincipalsTest.java
@@ -0,0 +1,344 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5025141
+ * @summary Tests that MBeanServerFileAccessController supports
+ * principals other than JMXPrincipal.
+ * @author Luis-Miguel Alventosa
+ * @run clean NonJMXPrincipalsTest SimpleStandard SimpleStandardMBean
+ * @run build NonJMXPrincipalsTest SimpleStandard SimpleStandardMBean
+ * @run main NonJMXPrincipalsTest
+ */
+
+import java.io.File;
+import java.io.Serializable;
+import java.security.Principal;
+import java.util.HashMap;
+import javax.management.Attribute;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerFactory;
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.remote.JMXAuthenticator;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXPrincipal;
+import javax.management.remote.JMXServiceURL;
+import javax.security.auth.Subject;
+
+public class NonJMXPrincipalsTest {
+
+ private static class OtherPrincipal implements Principal, Serializable {
+
+ private String name;
+
+ public OtherPrincipal(String name) {
+ if (name == null)
+ throw new NullPointerException("illegal null input");
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String toString() {
+ return("OtherPrincipal: " + name);
+ }
+
+ public boolean equals(Object o) {
+ if (o == null)
+ return false;
+ if (this == o)
+ return true;
+ if (!(o instanceof OtherPrincipal))
+ return false;
+ OtherPrincipal that = (OtherPrincipal)o;
+ return (this.getName().equals(that.getName()));
+ }
+
+ public int hashCode() {
+ return name.hashCode();
+ }
+ }
+
+ private static class OtherPrincipalAuthenticator
+ implements JMXAuthenticator {
+ public Subject authenticate(Object credentials) {
+ final String[] aCredentials = (String[]) credentials;
+ final String username = (String) aCredentials[0];
+ final Subject subject = new Subject();
+ subject.getPrincipals().add(new JMXPrincipal("dummy"));
+ subject.getPrincipals().add(new OtherPrincipal(username));
+ return subject;
+ }
+ }
+
+ private static class NoPrincipalAuthenticator
+ implements JMXAuthenticator {
+ public Subject authenticate(Object credentials) {
+ return new Subject();
+ }
+ }
+
+ public static void runTest(JMXAuthenticator authenticator)
+ throws Exception {
+ //------------------------------------------------------------------
+ // SERVER
+ //------------------------------------------------------------------
+
+ // Instantiate the MBean server
+ //
+ System.out.println("Create the MBean server");
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ // Create SimpleStandard MBean
+ //
+ ObjectName mbeanName = new ObjectName("MBeans:type=SimpleStandard");
+ System.out.println("Create SimpleStandard MBean...");
+ mbs.createMBean("SimpleStandard", mbeanName, null, null);
+
+ // Server's environment map
+ //
+ System.out.println(">>> Initialize the server's environment map");
+ HashMap sEnv = new HashMap();
+
+ // Provide a JMX Authenticator
+ //
+ sEnv.put("jmx.remote.authenticator", authenticator);
+
+ // Provide the access level file used by the connector server to
+ // perform user authorization. The access level file is a properties
+ // based text file specifying username/access level pairs where
+ // access level is either "readonly" or "readwrite" access to the
+ // MBeanServer operations. This properties based access control
+ // checker has been implemented using the MBeanServerForwarder
+ // interface which wraps the real MBean server inside an access
+ // controller MBean server which performs the access control checks
+ // before forwarding the requests to the real MBean server.
+ //
+ // This property is implementation-dependent and might not be
+ // supported by all implementations of the JMX Remote API.
+ //
+ sEnv.put("jmx.remote.x.access.file",
+ System.getProperty("test.src") +
+ File.separator +
+ "access.properties");
+
+ // Create an RMI connector server
+ //
+ System.out.println("Create an RMI connector server");
+ JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://");
+ JMXConnectorServer cs =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, sEnv, mbs);
+
+ // Start the RMI connector server
+ //
+ System.out.println("Start the RMI connector server");
+ cs.start();
+ System.out.println("RMI connector server successfully started");
+ System.out.println("Waiting for incoming connections...");
+
+ //------------------------------------------------------------------
+ // CLIENT (admin)
+ //------------------------------------------------------------------
+
+ // Admin client environment map
+ //
+ String[] adminCreds = new String[] { "admin" , "adminPassword" };
+ System.out.println(">>> Initialize the client environment map for" +
+ " user [" + adminCreds[0] + "] with " +
+ "password [" + adminCreds[1] + "]");
+ HashMap adminEnv = new HashMap();
+ adminEnv.put("jmx.remote.credentials", adminCreds);
+
+ // Create an RMI connector client and
+ // connect it to the RMI connector server
+ //
+ System.out.println("Create an RMI connector client and " +
+ "connect it to the RMI connector server");
+ JMXConnector adminConnector =
+ JMXConnectorFactory.connect(cs.getAddress(), adminEnv);
+
+ // Get an MBeanServerConnection
+ //
+ System.out.println("Get an MBeanServerConnection");
+ MBeanServerConnection adminConnection =
+ adminConnector.getMBeanServerConnection();
+
+ // Get the proxy for the Simple MBean
+ //
+ SimpleStandardMBean adminProxy = (SimpleStandardMBean)
+ MBeanServerInvocationHandler.newProxyInstance(
+ adminConnection,
+ mbeanName,
+ SimpleStandardMBean.class,
+ false);
+
+ // Get State attribute
+ //
+ System.out.println("State = " + adminProxy.getState());
+
+ // Set State attribute
+ //
+ adminProxy.setState("changed state");
+
+ // Get State attribute
+ //
+ System.out.println("State = " + adminProxy.getState());
+
+ // Invoke "reset" in SimpleStandard MBean
+ //
+ System.out.println("Invoke reset() in SimpleStandard MBean...");
+ adminProxy.reset();
+
+ // Close MBeanServer connection
+ //
+ System.out.println("Close the admin connection to the server");
+ adminConnector.close();
+
+ //------------------------------------------------------------------
+ // CLIENT (user)
+ //------------------------------------------------------------------
+
+ // User client environment map
+ //
+ String[] userCreds = new String[] { "user" , "userPassword" };
+ System.out.println(">>> Initialize the client environment map for" +
+ " user [" + userCreds[0] + "] with " +
+ "password [" + userCreds[1] + "]");
+ HashMap userEnv = new HashMap();
+ userEnv.put("jmx.remote.credentials", userCreds);
+
+ // Create an RMI connector client and
+ // connect it to the RMI connector server
+ //
+ System.out.println("Create an RMI connector client and " +
+ "connect it to the RMI connector server");
+ JMXConnector userConnector =
+ JMXConnectorFactory.connect(cs.getAddress(), userEnv);
+
+ // Get an MBeanServerConnection
+ //
+ System.out.println("Get an MBeanServerConnection");
+ MBeanServerConnection userConnection =
+ userConnector.getMBeanServerConnection();
+
+ // Get the proxy for the Simple MBean
+ //
+ SimpleStandardMBean userProxy = (SimpleStandardMBean)
+ MBeanServerInvocationHandler.newProxyInstance(
+ userConnection,
+ mbeanName,
+ SimpleStandardMBean.class,
+ false);
+
+ // Get State attribute
+ //
+ System.out.println("State = " + userProxy.getState());
+
+ // Set State attribute
+ //
+ try {
+ userProxy.setState("changed state");
+ } catch (SecurityException e) {
+ System.out.println("Got expected security exception: " + e);
+ } catch (Exception e) {
+ System.out.println("Got unexpected exception: " + e);
+ e.printStackTrace(System.out);
+ }
+
+ // Get State attribute
+ //
+ System.out.println("State = " + userProxy.getState());
+
+ // Invoke "reset" in SimpleStandard MBean
+ //
+ try {
+ System.out.println("Invoke reset() in SimpleStandard MBean...");
+ userProxy.reset();
+ } catch (SecurityException e) {
+ System.out.println("Got expected security exception: " + e);
+ } catch (Exception e) {
+ System.out.println("Got unexpected exception: " + e);
+ e.printStackTrace(System.out);
+ }
+
+ // Close MBeanServer connection
+ //
+ System.out.println("Close the user connection to the server");
+ userConnector.close();
+
+ //------------------------------------------------------------------
+ // SERVER
+ //------------------------------------------------------------------
+
+ // Stop the connector server
+ //
+ System.out.println(">>> Stop the connector server");
+ cs.stop();
+ }
+
+ public static void main(String[] args) {
+ int errorCount = 0;
+ // Runt tests
+ //
+ System.out.println("\n>>> Run NoPrincipalAuthenticator test...");
+ try {
+ NonJMXPrincipalsTest.runTest(new NoPrincipalAuthenticator());
+ System.out.println("Did not get expected SecurityException");
+ errorCount++;
+ } catch (Exception e) {
+ if (e instanceof SecurityException) {
+ System.out.println("Got expected exception: " + e);
+ } else {
+ System.out.println("Got unexpected exception: " + e);
+ errorCount++;
+ }
+ e.printStackTrace(System.out);
+ }
+ System.out.println("\n>>> Run OtherPrincipalAuthenticator test...");
+ try {
+ NonJMXPrincipalsTest.runTest(new OtherPrincipalAuthenticator());
+ } catch (Exception e) {
+ errorCount++;
+ System.out.println("Got unexpected exception: " + e);
+ e.printStackTrace(System.out);
+ }
+
+ if (errorCount > 0) {
+ System.out.println("\nTEST FAILED! Error count = " + errorCount);
+ System.exit(1);
+ }
+
+ System.out.println("\nTEST PASSED!");
+ System.out.println("\nBye! Bye!");
+ }
+}
diff --git a/test/javax/management/remote/mandatory/passwordAccessFile/PasswordAccessFileTest.java b/test/javax/management/remote/mandatory/passwordAccessFile/PasswordAccessFileTest.java
new file mode 100644
index 0000000..fb3c780
--- /dev/null
+++ b/test/javax/management/remote/mandatory/passwordAccessFile/PasswordAccessFileTest.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4924664
+ * @summary Tests the use of the "jmx.remote.x.password.file" and
+ * "jmx.remote.x.access.file" environment map properties.
+ * @author Luis-Miguel Alventosa
+ * @run clean PasswordAccessFileTest SimpleStandard SimpleStandardMBean
+ * @run build PasswordAccessFileTest SimpleStandard SimpleStandardMBean
+ * @run main PasswordAccessFileTest
+ */
+
+import java.io.File;
+import java.util.HashMap;
+import javax.management.Attribute;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerFactory;
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+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 PasswordAccessFileTest {
+
+ public static void main(String[] args) {
+ try {
+ //------------------------------------------------------------------
+ // SERVER
+ //------------------------------------------------------------------
+
+ // Instantiate the MBean server
+ //
+ System.out.println("Create the MBean server");
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ // Create SimpleStandard MBean
+ //
+ ObjectName mbeanName = new ObjectName("MBeans:type=SimpleStandard");
+ System.out.println("Create SimpleStandard MBean...");
+ mbs.createMBean("SimpleStandard", mbeanName, null, null);
+
+ // Server's environment map
+ //
+ System.out.println(">>> Initialize the server's environment map");
+ HashMap sEnv = new HashMap();
+
+ // Provide the password file used by the connector server to
+ // perform user authentication. The password file is a properties
+ // based text file specifying username/password pairs. This
+ // properties based password authenticator has been implemented
+ // using the JMXAuthenticator interface and is passed to the
+ // connector through the "jmx.remote.authenticator" property
+ // in the map.
+ //
+ // This property is implementation-dependent and might not be
+ // supported by all implementations of the JMX Remote API.
+ //
+ sEnv.put("jmx.remote.x.password.file",
+ System.getProperty("test.src") +
+ File.separator +
+ "password.properties");
+
+ // Provide the access level file used by the connector server to
+ // perform user authorization. The access level file is a properties
+ // based text file specifying username/access level pairs where
+ // access level is either "readonly" or "readwrite" access to the
+ // MBeanServer operations. This properties based access control
+ // checker has been implemented using the MBeanServerForwarder
+ // interface which wraps the real MBean server inside an access
+ // controller MBean server which performs the access control checks
+ // before forwarding the requests to the real MBean server.
+ //
+ // This property is implementation-dependent and might not be
+ // supported by all implementations of the JMX Remote API.
+ //
+ sEnv.put("jmx.remote.x.access.file",
+ System.getProperty("test.src") +
+ File.separator +
+ "access.properties");
+
+ // Create an RMI connector server
+ //
+ System.out.println("Create an RMI connector server");
+ JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://");
+ JMXConnectorServer cs =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, sEnv, mbs);
+
+ // Start the RMI connector server
+ //
+ System.out.println("Start the RMI connector server");
+ cs.start();
+ System.out.println("RMI connector server successfully started");
+ System.out.println("Waiting for incoming connections...");
+
+ //------------------------------------------------------------------
+ // CLIENT : Invalid authentication credentials
+ //------------------------------------------------------------------
+
+ final String invalidCreds[][] = {
+ {"admin1", "adminPassword"},
+ {"admin", "adminPassword1"},
+ {"user1", "userPassword"},
+ {"user", "userPassword1"}
+ };
+
+ // Try to connect to the server using the invalid credentials.
+ // All the connect calls should get SecurityException.
+ //
+ for (int i = 0 ; i < invalidCreds.length ; i++) {
+ // Client environment map
+ //
+ System.out.println(">>> Initialize the client environment map" +
+ " for user [" +
+ invalidCreds[i][0] +
+ "] with password [" +
+ invalidCreds[i][1] + "]");
+ HashMap cEnv = new HashMap();
+ cEnv.put("jmx.remote.credentials", invalidCreds[i]);
+
+ // Create an RMI connector client and
+ // connect it to the RMI connector server
+ //
+ System.out.println("Create an RMI connector client and " +
+ "connect it to the RMI connector server");
+ try {
+ JMXConnector jmxc =
+ JMXConnectorFactory.connect(cs.getAddress(), cEnv);
+ } catch (SecurityException e) {
+ System.out.println("Got expected security exception: " + e);
+ } catch (Exception e) {
+ System.out.println("Got unexpected exception: " + e);
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ //------------------------------------------------------------------
+ // CLIENT (admin)
+ //------------------------------------------------------------------
+
+ // Admin client environment map
+ //
+ String[] adminCreds = new String[] { "admin" , "adminPassword" };
+ System.out.println(">>> Initialize the client environment map for" +
+ " user [" + adminCreds[0] + "] with " +
+ "password [" + adminCreds[1] + "]");
+ HashMap adminEnv = new HashMap();
+ adminEnv.put("jmx.remote.credentials", adminCreds);
+
+ // Create an RMI connector client and
+ // connect it to the RMI connector server
+ //
+ System.out.println("Create an RMI connector client and " +
+ "connect it to the RMI connector server");
+ JMXConnector adminConnector =
+ JMXConnectorFactory.connect(cs.getAddress(), adminEnv);
+
+ // Get an MBeanServerConnection
+ //
+ System.out.println("Get an MBeanServerConnection");
+ MBeanServerConnection adminConnection =
+ adminConnector.getMBeanServerConnection();
+
+ // Get the proxy for the Simple MBean
+ //
+ SimpleStandardMBean adminProxy = (SimpleStandardMBean)
+ MBeanServerInvocationHandler.newProxyInstance(
+ adminConnection,
+ mbeanName,
+ SimpleStandardMBean.class,
+ false);
+
+ // Get State attribute
+ //
+ System.out.println("State = " + adminProxy.getState());
+
+ // Set State attribute
+ //
+ adminProxy.setState("changed state");
+
+ // Get State attribute
+ //
+ System.out.println("State = " + adminProxy.getState());
+
+ // Invoke "reset" in SimpleStandard MBean
+ //
+ System.out.println("Invoke reset() in SimpleStandard MBean...");
+ adminProxy.reset();
+
+ // Close MBeanServer connection
+ //
+ System.out.println("Close the admin connection to the server");
+ adminConnector.close();
+
+ //------------------------------------------------------------------
+ // CLIENT (user)
+ //------------------------------------------------------------------
+
+ // User client environment map
+ //
+ String[] userCreds = new String[] { "user" , "userPassword" };
+ System.out.println(">>> Initialize the client environment map for" +
+ " user [" + userCreds[0] + "] with " +
+ "password [" + userCreds[1] + "]");
+ HashMap userEnv = new HashMap();
+ userEnv.put("jmx.remote.credentials", userCreds);
+
+ // Create an RMI connector client and
+ // connect it to the RMI connector server
+ //
+ System.out.println("Create an RMI connector client and " +
+ "connect it to the RMI connector server");
+ JMXConnector userConnector =
+ JMXConnectorFactory.connect(cs.getAddress(), userEnv);
+
+ // Get an MBeanServerConnection
+ //
+ System.out.println("Get an MBeanServerConnection");
+ MBeanServerConnection userConnection =
+ userConnector.getMBeanServerConnection();
+
+ // Get the proxy for the Simple MBean
+ //
+ SimpleStandardMBean userProxy = (SimpleStandardMBean)
+ MBeanServerInvocationHandler.newProxyInstance(
+ userConnection,
+ mbeanName,
+ SimpleStandardMBean.class,
+ false);
+
+ // Get State attribute
+ //
+ System.out.println("State = " + userProxy.getState());
+
+ // Set State attribute
+ //
+ try {
+ userProxy.setState("changed state");
+ } catch (SecurityException e) {
+ System.out.println("Got expected security exception: " + e);
+ } catch (Exception e) {
+ System.out.println("Got unexpected exception: " + e);
+ e.printStackTrace();
+ System.exit(1);
+ }
+
+ // Get State attribute
+ //
+ System.out.println("State = " + userProxy.getState());
+
+ // Invoke "reset" in SimpleStandard MBean
+ //
+ try {
+ System.out.println("Invoke reset() in SimpleStandard MBean...");
+ userProxy.reset();
+ } catch (SecurityException e) {
+ System.out.println("Got expected security exception: " + e);
+ } catch (Exception e) {
+ System.out.println("Got unexpected exception: " + e);
+ e.printStackTrace();
+ System.exit(1);
+ }
+
+ // Close MBeanServer connection
+ //
+ System.out.println("Close the user connection to the server");
+ userConnector.close();
+
+ //------------------------------------------------------------------
+ // SERVER
+ //------------------------------------------------------------------
+
+ // Stop the connector server
+ //
+ System.out.println(">>> Stop the connector server");
+ cs.stop();
+
+ System.out.println("Bye! Bye!");
+ } catch (Exception e) {
+ System.out.println("Got unexpected exception: " + e);
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/passwordAccessFile/SimpleStandard.java b/test/javax/management/remote/mandatory/passwordAccessFile/SimpleStandard.java
new file mode 100644
index 0000000..ef4bfe5
--- /dev/null
+++ b/test/javax/management/remote/mandatory/passwordAccessFile/SimpleStandard.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * build @BUILD_TAG_PLACEHOLDER@
+ *
+ * @COPYRIGHT_MINI_LEGAL_NOTICE_PLACEHOLDER@
+ */
+
+/**
+ * Simple definition of a standard MBean, named "SimpleStandard".
+ *
+ * The "SimpleStandard" standard MBean shows how to expose attributes
+ * and operations for management by implementing its corresponding
+ * "SimpleStandardMBean" management interface.
+ *
+ * This MBean has two attributes and one operation exposed
+ * for management by a JMX agent:
+ * - the read/write "State" attribute,
+ * - the read only "NbChanges" attribute,
+ * - the "reset()" operation.
+ *
+ * This object also has one property and one method not exposed
+ * for management by a JMX agent:
+ * - the "NbResets" property,
+ * - the "getNbResets()" method.
+ */
+
+import javax.management.AttributeChangeNotification;
+import javax.management.NotificationBroadcasterSupport;
+
+public class SimpleStandard
+ extends NotificationBroadcasterSupport
+ implements SimpleStandardMBean {
+
+ /*
+ * -----------------------------------------------------
+ * CONSTRUCTORS
+ * -----------------------------------------------------
+ */
+
+ /* "SimpleStandard" does not provide any specific constructors.
+ * However, "SimpleStandard" is JMX compliant with regards to
+ * contructors because the default contructor SimpleStandard()
+ * provided by the Java compiler is public.
+ */
+
+ /*
+ * -----------------------------------------------------
+ * IMPLEMENTATION OF THE SimpleStandardMBean INTERFACE
+ * -----------------------------------------------------
+ */
+
+ /**
+ * Getter: get the "State" attribute of the "SimpleStandard" standard MBean.
+ *
+ * @return the current value of the "State" attribute.
+ */
+ public String getState() {
+ return state;
+ }
+
+ /**
+ * Setter: set the "State" attribute of the "SimpleStandard" standard MBean.
+ *
+ * @param <VAR>s</VAR> the new value of the "State" attribute.
+ */
+ public void setState(String s) {
+ state = s;
+ nbChanges++;
+ }
+
+ /**
+ * Getter: get the "NbChanges" attribute of the "SimpleStandard" standard
+ * MBean.
+ *
+ * @return the current value of the "NbChanges" attribute.
+ */
+ public int getNbChanges() {
+ return nbChanges;
+ }
+
+ /**
+ * Operation: reset to their initial values the "State" and "NbChanges"
+ * attributes of the "SimpleStandard" standard MBean.
+ */
+ public void reset() {
+ AttributeChangeNotification acn =
+ new AttributeChangeNotification(this,
+ 0,
+ 0,
+ "NbChanges reset",
+ "NbChanges",
+ "Integer",
+ new Integer(nbChanges),
+ new Integer(0));
+ state = "initial state";
+ nbChanges = 0;
+ nbResets++;
+ sendNotification(acn);
+ }
+
+ /*
+ * -----------------------------------------------------
+ * METHOD NOT EXPOSED FOR MANAGEMENT BY A JMX AGENT
+ * -----------------------------------------------------
+ */
+
+ /**
+ * Return the "NbResets" property.
+ * This method is not a Getter in the JMX sense because it
+ * is not exposed in the "SimpleStandardMBean" interface.
+ *
+ * @return the current value of the "NbResets" property.
+ */
+ public int getNbResets() {
+ return nbResets;
+ }
+
+ /*
+ * -----------------------------------------------------
+ * ATTRIBUTES ACCESSIBLE FOR MANAGEMENT BY A JMX AGENT
+ * -----------------------------------------------------
+ */
+
+ private String state = "initial state";
+ private int nbChanges = 0;
+
+ /*
+ * -----------------------------------------------------
+ * PROPERTY NOT ACCESSIBLE FOR MANAGEMENT BY A JMX AGENT
+ * -----------------------------------------------------
+ */
+
+ private int nbResets = 0;
+}
diff --git a/test/javax/management/remote/mandatory/passwordAccessFile/SimpleStandardMBean.java b/test/javax/management/remote/mandatory/passwordAccessFile/SimpleStandardMBean.java
new file mode 100644
index 0000000..b2fd634
--- /dev/null
+++ b/test/javax/management/remote/mandatory/passwordAccessFile/SimpleStandardMBean.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * build @BUILD_TAG_PLACEHOLDER@
+ *
+ * @COPYRIGHT_MINI_LEGAL_NOTICE_PLACEHOLDER@
+ */
+
+/**
+ * This is the management interface explicitly defined for the
+ * "SimpleStandard" standard MBean.
+ *
+ * The "SimpleStandard" standard MBean implements this interface
+ * in order to be manageable through a JMX agent.
+ *
+ * The "SimpleStandardMBean" interface shows how to expose for management:
+ * - a read/write attribute (named "State") through its getter and setter
+ * methods,
+ * - a read-only attribute (named "NbChanges") through its getter method,
+ * - an operation (named "reset").
+ */
+public interface SimpleStandardMBean {
+
+ /**
+ * Getter: set the "State" attribute of the "SimpleStandard" standard
+ * MBean.
+ *
+ * @return the current value of the "State" attribute.
+ */
+ public String getState();
+
+ /**
+ * Setter: set the "State" attribute of the "SimpleStandard" standard
+ * MBean.
+ *
+ * @param <VAR>s</VAR> the new value of the "State" attribute.
+ */
+ public void setState(String s);
+
+ /**
+ * Getter: get the "NbChanges" attribute of the "SimpleStandard" standard
+ * MBean.
+ *
+ * @return the current value of the "NbChanges" attribute.
+ */
+ public int getNbChanges();
+
+ /**
+ * Operation: reset to their initial values the "State" and "NbChanges"
+ * attributes of the "SimpleStandard" standard MBean.
+ */
+ public void reset();
+}
diff --git a/test/javax/management/remote/mandatory/passwordAccessFile/access.properties b/test/javax/management/remote/mandatory/passwordAccessFile/access.properties
new file mode 100644
index 0000000..7ab29b1
--- /dev/null
+++ b/test/javax/management/remote/mandatory/passwordAccessFile/access.properties
@@ -0,0 +1,38 @@
+#
+
+# Access control file for Remote JMX API access to MBeanServer resources.
+# This file defines the allowed access for different roles.
+
+# The file format for the access file is syntactically the same as the
+# Properties file format. The syntax is described in the Javadoc for
+# java.util.Properties.load.
+
+# A typical access file has multiple lines, where each line is blank,
+# a comment (like this one), or an access control entry.
+
+# An access control entry consists of a role name, and an associated access
+# level. The role name is any string that does not itself contain spaces or
+# tabs. It corresponds to an entry in the password file. The access level
+# is one of the following:
+#
+# "readonly" grants access to read attributes of MBeans.
+# For monitoring, this means that a remote client in this
+# role can read measurements but cannot perform any action
+# that changes the environment of the running program.
+#
+# "readwrite" grants access to read and write attributes of MBeans, to
+# invoke operations on them, and to create or remove them.
+# This access should be only granted to trusted clients,
+# since they can potentially interfere with the smooth
+# operation of a running program.
+
+# A given role should have at most one entry in this file. If a role has no
+# entry, it has no access.
+# If multiple entries are found for the same role name, then the last access
+# entry is used.
+
+# Access rights granted to the authenticated identity by the RMI connector
+# in this example.
+#
+admin readwrite
+user readonly
diff --git a/test/javax/management/remote/mandatory/passwordAccessFile/password.properties b/test/javax/management/remote/mandatory/passwordAccessFile/password.properties
new file mode 100644
index 0000000..ebbea24
--- /dev/null
+++ b/test/javax/management/remote/mandatory/passwordAccessFile/password.properties
@@ -0,0 +1,34 @@
+#
+
+# Password file for Remote JMX API authentication. This file defines
+# the different roles and their passwords.
+
+# The file format for the password file is syntactically the same as
+# the Properties file format. The syntax is described in the Javadoc
+# for java.util.Properties.load.
+
+# A typical password file has multiple lines, where each line is blank,
+# a comment (like this one), or a password entry.
+
+# A password entry consists of a role name and an associated password.
+# The role name is any string that does not itself contain spaces or
+# tabs. The password is again any string that does not contain spaces
+# or tabs. Note that passwords appear in the clear in this file, so it
+# is a good idea not to use valuable passwords.
+
+# A given role should have at most one entry in this file. If a role
+# has no entry, it has no access.
+# If multiple entries are found for the same role name, then the last
+# one is used.
+
+# In a typical installation, this file can be read by anybody on the
+# local machine, and possibly by people on other machines.
+# For security, you should either restrict the access to this file,
+# or specify another, less accessible file in the management config
+# file as described above.
+
+# Role and password used for authentication by the RMI connector in
+# this example.
+#
+admin adminPassword
+user userPassword
diff --git a/test/javax/management/remote/mandatory/passwordAuthenticator/RMIAltAuthTest.java b/test/javax/management/remote/mandatory/passwordAuthenticator/RMIAltAuthTest.java
new file mode 100644
index 0000000..ebea4fc
--- /dev/null
+++ b/test/javax/management/remote/mandatory/passwordAuthenticator/RMIAltAuthTest.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5016508
+ * @summary Supplies an alternative JAAS configuration for authenticating RMI clients
+ * @author Luis-Miguel Alventosa
+ * @run clean RMIAltAuthTest
+ * @run build RMIAltAuthTest SimpleStandard SimpleStandardMBean
+ * @run main RMIAltAuthTest
+ */
+
+import java.io.File;
+import java.rmi.RemoteException;
+import java.rmi.registry.Registry;
+import java.rmi.registry.LocateRegistry;
+import java.util.HashMap;
+import java.util.Properties;
+
+import javax.management.Attribute;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerFactory;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+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 com.sun.jmx.remote.security.JMXPluggableAuthenticator;
+
+public class RMIAltAuthTest {
+
+ public static void main(String[] args) {
+ try {
+
+ // Override the default JAAS configuration
+ //
+ final String loginConfig = System.getProperty("test.src") +
+ File.separator + "jmxremote.login";
+ System.out.println("JAAS configuration file = " + loginConfig);
+ System.setProperty("java.security.auth.login.config",
+ "file:" + loginConfig);
+
+ // Create an RMI registry
+ //
+ System.out.println("Start RMI registry...");
+ Registry reg = null;
+ int port = 5800;
+ while (port++ < 6000) {
+ try {
+ reg = LocateRegistry.createRegistry(port);
+ System.out.println("RMI registry running on port " + port);
+ break;
+ } catch (RemoteException e) {
+ // Failed to create RMI registry...
+ System.out.println("Failed to create RMI registry " +
+ "on port " + port);
+ }
+ }
+ if (reg == null) {
+ System.exit(1);
+ }
+
+ // Instantiate the MBean server
+ //
+ System.out.println("Create the MBean server");
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ // Register the ClassPathClassLoaderMBean
+ //
+ System.out.println("Create ClassPathClassLoader MBean");
+ ObjectName cpcl =
+ new ObjectName("ClassLoader:name=ClassPathClassLoader");
+ mbs.createMBean("javax.management.loading.MLet", cpcl);
+ // Register the SimpleStandardMBean
+ //
+ System.out.println("Create SimpleStandard MBean");
+ mbs.createMBean("SimpleStandard",
+ new ObjectName("MBeans:name=SimpleStandard"));
+ // Create Properties containing the username/password entries
+ //
+ Properties props = new Properties();
+ props.setProperty("jmx.remote.x.login.config",
+ "PasswordFileAuthentication");
+ // Initialize environment map to be passed to the connector server
+ //
+ System.out.println("Initialize environment map");
+ HashMap env = new HashMap();
+ env.put("jmx.remote.authenticator",
+ new JMXPluggableAuthenticator(props));
+ // Create an RMI connector server
+ //
+ System.out.println("Create an RMI connector server");
+ JMXServiceURL url =
+ new JMXServiceURL("rmi", null, 0,
+ "/jndi/rmi://:" + port + "/server" + port);
+ JMXConnectorServer rcs =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
+ rcs.start();
+
+ // Create an RMI connector client
+ //
+ System.out.println("Create an RMI connector client");
+ HashMap cli_env = new HashMap();
+ // These credentials must match those in the supplied password file
+ //
+ String[] credentials = new String[] { "monitorRole" , "pwd1" };
+ cli_env.put("jmx.remote.credentials", credentials);
+ JMXConnector jmxc = JMXConnectorFactory.connect(url, cli_env);
+ MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
+ // Get domains from MBeanServer
+ //
+ System.out.println("Domains:");
+ String domains[] = mbsc.getDomains();
+ for (int i = 0; i < domains.length; i++) {
+ System.out.println("\tDomain[" + i + "] = " + domains[i]);
+ }
+ // Get MBean count
+ //
+ System.out.println("MBean count = " + mbsc.getMBeanCount());
+ // Get State attribute
+ //
+ String oldState =
+ (String) mbsc.getAttribute(
+ new ObjectName("MBeans:name=SimpleStandard"),
+ "State");
+ System.out.println("Old State = \"" + oldState + "\"");
+ // Set State attribute
+ //
+ System.out.println("Set State to \"changed state\"");
+ mbsc.setAttribute(new ObjectName("MBeans:name=SimpleStandard"),
+ new Attribute("State", "changed state"));
+ // Get State attribute
+ //
+ String newState =
+ (String) mbsc.getAttribute(
+ new ObjectName("MBeans:name=SimpleStandard"),
+ "State");
+ System.out.println("New State = \"" + newState + "\"");
+ if (!newState.equals("changed state")) {
+ System.out.println("Invalid State = \"" + newState + "\"");
+ System.exit(1);
+ }
+ // Add notification listener on SimpleStandard MBean
+ //
+ System.out.println("Add notification listener...");
+ mbsc.addNotificationListener(
+ new ObjectName("MBeans:name=SimpleStandard"),
+ new NotificationListener() {
+ public void handleNotification(Notification notification,
+ Object handback) {
+ System.out.println("Received notification: " +
+ notification);
+ }
+ },
+ null,
+ null);
+ // Unregister SimpleStandard MBean
+ //
+ System.out.println("Unregister SimpleStandard MBean...");
+ mbsc.unregisterMBean(new ObjectName("MBeans:name=SimpleStandard"));
+ // Close MBeanServer connection
+ //
+ jmxc.close();
+ System.out.println("Bye! Bye!");
+ } catch (Exception e) {
+ System.out.println("Unexpected exception caught = " + e);
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/passwordAuthenticator/RMIPasswdAuthTest.java b/test/javax/management/remote/mandatory/passwordAuthenticator/RMIPasswdAuthTest.java
new file mode 100644
index 0000000..924a5a3
--- /dev/null
+++ b/test/javax/management/remote/mandatory/passwordAuthenticator/RMIPasswdAuthTest.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2003-2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5016508
+ * @summary Tests the default JAAS configuration for authenticating RMI clients
+ * @author Luis-Miguel Alventosa
+ * @run clean RMIPasswdAuthTest
+ * @run build RMIPasswdAuthTest SimpleStandard SimpleStandardMBean
+ * @run main RMIPasswdAuthTest
+ */
+
+import java.io.File;
+import java.rmi.RemoteException;
+import java.rmi.registry.Registry;
+import java.rmi.registry.LocateRegistry;
+import java.util.HashMap;
+import java.util.Properties;
+
+import javax.management.Attribute;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerFactory;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+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 com.sun.jmx.remote.security.JMXPluggableAuthenticator;
+
+public class RMIPasswdAuthTest {
+
+ public static void main(String[] args) {
+ try {
+
+ // Set the default password file
+ //
+ final String passwordFile = System.getProperty("test.src") +
+ File.separator + "jmxremote.password";
+ System.out.println("Password file = " + passwordFile);
+
+ // Create an RMI registry
+ //
+ System.out.println("Start RMI registry...");
+ Registry reg = null;
+ int port = 5800;
+ while (port++ < 6000) {
+ try {
+ reg = LocateRegistry.createRegistry(port);
+ System.out.println("RMI registry running on port " + port);
+ break;
+ } catch (RemoteException e) {
+ // Failed to create RMI registry...
+ System.out.println("Failed to create RMI registry " +
+ "on port " + port);
+ }
+ }
+ if (reg == null) {
+ System.exit(1);
+ }
+
+ // Instantiate the MBean server
+ //
+ System.out.println("Create the MBean server");
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ // Register the ClassPathClassLoaderMBean
+ //
+ System.out.println("Create ClassPathClassLoader MBean");
+ ObjectName cpcl =
+ new ObjectName("ClassLoader:name=ClassPathClassLoader");
+ mbs.createMBean("javax.management.loading.MLet", cpcl);
+ // Register the SimpleStandardMBean
+ //
+ System.out.println("Create SimpleStandard MBean");
+ mbs.createMBean("SimpleStandard",
+ new ObjectName("MBeans:name=SimpleStandard"));
+ // Create Properties containing the location of the password file
+ //
+ Properties props = new Properties();
+ props.setProperty("jmx.remote.x.password.file", passwordFile);
+ // Initialize environment map to be passed to the connector server
+ //
+ System.out.println("Initialize environment map");
+ HashMap env = new HashMap();
+ env.put("jmx.remote.authenticator",
+ new JMXPluggableAuthenticator(props));
+ // Create an RMI connector server
+ //
+ System.out.println("Create an RMI connector server");
+ JMXServiceURL url =
+ new JMXServiceURL("rmi", null, 0,
+ "/jndi/rmi://:" + port + "/server" + port);
+ JMXConnectorServer rcs =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
+ rcs.start();
+
+ // Create an RMI connector client
+ //
+ System.out.println("Create an RMI connector client");
+ HashMap cli_env = new HashMap();
+ // These credentials must match those in the supplied password file
+ //
+ String[] credentials = new String[] { "monitorRole" , "QED" };
+ cli_env.put("jmx.remote.credentials", credentials);
+ JMXConnector jmxc = JMXConnectorFactory.connect(url, cli_env);
+ MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
+ // Get domains from MBeanServer
+ //
+ System.out.println("Domains:");
+ String domains[] = mbsc.getDomains();
+ for (int i = 0; i < domains.length; i++) {
+ System.out.println("\tDomain[" + i + "] = " + domains[i]);
+ }
+ // Get MBean count
+ //
+ System.out.println("MBean count = " + mbsc.getMBeanCount());
+ // Get State attribute
+ //
+ String oldState =
+ (String) mbsc.getAttribute(
+ new ObjectName("MBeans:name=SimpleStandard"),
+ "State");
+ System.out.println("Old State = \"" + oldState + "\"");
+ // Set State attribute
+ //
+ System.out.println("Set State to \"changed state\"");
+ mbsc.setAttribute(new ObjectName("MBeans:name=SimpleStandard"),
+ new Attribute("State", "changed state"));
+ // Get State attribute
+ //
+ String newState =
+ (String) mbsc.getAttribute(
+ new ObjectName("MBeans:name=SimpleStandard"),
+ "State");
+ System.out.println("New State = \"" + newState + "\"");
+ if (!newState.equals("changed state")) {
+ System.out.println("Invalid State = \"" + newState + "\"");
+ System.exit(1);
+ }
+ // Add notification listener on SimpleStandard MBean
+ //
+ System.out.println("Add notification listener...");
+ mbsc.addNotificationListener(
+ new ObjectName("MBeans:name=SimpleStandard"),
+ new NotificationListener() {
+ public void handleNotification(Notification notification,
+ Object handback) {
+ System.out.println("Received notification: " +
+ notification);
+ }
+ },
+ null,
+ null);
+ // Unregister SimpleStandard MBean
+ //
+ System.out.println("Unregister SimpleStandard MBean...");
+ mbsc.unregisterMBean(new ObjectName("MBeans:name=SimpleStandard"));
+ // Close MBeanServer connection
+ //
+ jmxc.close();
+ System.out.println("Bye! Bye!");
+ } catch (Exception e) {
+ System.out.println("Unexpected exception caught = " + e);
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/passwordAuthenticator/SimpleStandard.java b/test/javax/management/remote/mandatory/passwordAuthenticator/SimpleStandard.java
new file mode 100644
index 0000000..3294539
--- /dev/null
+++ b/test/javax/management/remote/mandatory/passwordAuthenticator/SimpleStandard.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2003-2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * Simple definition of a standard MBean, named "SimpleStandard".
+ *
+ * The "SimpleStandard" standard MBean shows how to expose attributes and
+ * operations for management by implementing its corresponding
+ * "SimpleStandardMBean" management interface.
+ *
+ * This MBean has two attributes and one operation exposed
+ * for management by a JMX agent:
+ * - the read/write "State" attribute,
+ * - the read only "NbChanges" attribute,
+ * - the "reset()" operation.
+ *
+ * This object also has one property and one method not exposed
+ * for management by a JMX agent:
+ * - the "NbResets" property,
+ * - the "getNbResets()" method.
+ */
+
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.Principal;
+import java.util.Set;
+import javax.management.AttributeChangeNotification;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.remote.JMXPrincipal;
+import javax.security.auth.Subject;
+
+public class SimpleStandard
+ extends NotificationBroadcasterSupport
+ implements SimpleStandardMBean {
+
+ /*
+ * -----------------------------------------------------
+ * CONSTRUCTORS
+ * -----------------------------------------------------
+ */
+
+ /* "SimpleStandard" does not provide any specific constructors.
+ * However, "SimpleStandard" is JMX compliant with regards to
+ * contructors because the default contructor SimpleStandard()
+ * provided by the Java compiler is public.
+ */
+
+ /*
+ * -----------------------------------------------------
+ * IMPLEMENTATION OF THE SimpleStandardMBean INTERFACE
+ * -----------------------------------------------------
+ */
+
+ /**
+ * Getter: get the "State" attribute of the "SimpleStandard" standard MBean.
+ *
+ * @return the current value of the "State" attribute.
+ */
+ public String getState() {
+ checkSubject();
+ return state;
+ }
+
+ /**
+ * Setter: set the "State" attribute of the "SimpleStandard" standard MBean.
+ *
+ * @param <VAR>s</VAR> the new value of the "State" attribute.
+ */
+ public void setState(String s) {
+ checkSubject();
+ state = s;
+ nbChanges++;
+ }
+
+ /**
+ * Getter: get the "NbChanges" attribute of the "SimpleStandard" standard
+ * MBean.
+ *
+ * @return the current value of the "NbChanges" attribute.
+ */
+ public int getNbChanges() {
+ checkSubject();
+ return nbChanges;
+ }
+
+ /**
+ * Operation: reset to their initial values the "State" and "NbChanges"
+ * attributes of the "SimpleStandard" standard MBean.
+ */
+ public void reset() {
+ checkSubject();
+ AttributeChangeNotification acn =
+ new AttributeChangeNotification(this,
+ 0,
+ 0,
+ "NbChanges reset",
+ "NbChanges",
+ "Integer",
+ new Integer(nbChanges),
+ new Integer(0));
+ state = "initial state";
+ nbChanges = 0;
+ nbResets++;
+ sendNotification(acn);
+ }
+
+ /*
+ * -----------------------------------------------------
+ * METHOD NOT EXPOSED FOR MANAGEMENT BY A JMX AGENT
+ * -----------------------------------------------------
+ */
+
+ /**
+ * Return the "NbResets" property.
+ * This method is not a Getter in the JMX sense because
+ * it is not exposed in the "SimpleStandardMBean" interface.
+ *
+ * @return the current value of the "NbResets" property.
+ */
+ public int getNbResets() {
+ return nbResets;
+ }
+
+ /*
+ * ---------------
+ * PRIVATE METHODS
+ * ---------------
+ */
+
+ /**
+ * Check that the principal contained in the Subject is of
+ * type JMXPrincipal and refers to the "monitorRole" identity.
+ */
+ private void checkSubject() {
+ AccessControlContext acc = AccessController.getContext();
+ Subject subject = Subject.getSubject(acc);
+ Set principals = subject.getPrincipals();
+ Principal principal = (Principal) principals.iterator().next();
+ if (!(principal instanceof JMXPrincipal))
+ throw new SecurityException("Authenticated subject contains " +
+ "invalid principal type = " +
+ principal.getClass().getName());
+ String identity = principal.getName();
+ if (!identity.equals("monitorRole"))
+ throw new SecurityException("Authenticated subject contains " +
+ "invalid principal name = " + identity);
+ }
+
+ /*
+ * -----------------------------------------------------
+ * ATTRIBUTES ACCESSIBLE FOR MANAGEMENT BY A JMX AGENT
+ * -----------------------------------------------------
+ */
+
+ private String state = "initial state";
+ private int nbChanges = 0;
+
+ /*
+ * -----------------------------------------------------
+ * PROPERTY NOT ACCESSIBLE FOR MANAGEMENT BY A JMX AGENT
+ * -----------------------------------------------------
+ */
+
+ private int nbResets = 0;
+}
diff --git a/test/javax/management/remote/mandatory/passwordAuthenticator/SimpleStandardMBean.java b/test/javax/management/remote/mandatory/passwordAuthenticator/SimpleStandardMBean.java
new file mode 100644
index 0000000..e214087
--- /dev/null
+++ b/test/javax/management/remote/mandatory/passwordAuthenticator/SimpleStandardMBean.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * This is the management interface explicitly defined for the
+ * "SimpleStandard" standard MBean.
+ * The "SimpleStandard" standard MBean implements this interface
+ * in order to be manageable through a JMX agent.
+ *
+ * The "SimpleStandardMBean" interface shows how to expose for management:
+ * - a read/write attribute (named "State") through its getter and setter
+ * methods,
+ * - a read-only attribute (named "NbChanges") through its getter method,
+ * - an operation (named "reset").
+ */
+public interface SimpleStandardMBean {
+
+ /**
+ * Getter: set the "State" attribute of the "SimpleStandard" standard
+ * MBean.
+ *
+ * @return the current value of the "State" attribute.
+ */
+ public String getState();
+
+ /**
+ * Setter: set the "State" attribute of the "SimpleStandard" standard
+ * MBean.
+ *
+ * @param <VAR>s</VAR> the new value of the "State" attribute.
+ */
+ public void setState(String s);
+
+ /**
+ * Getter: get the "NbChanges" attribute of the "SimpleStandard" standard
+ * MBean.
+ *
+ * @return the current value of the "NbChanges" attribute.
+ */
+ public int getNbChanges();
+
+ /**
+ * Operation: reset to their initial values the "State" and "NbChanges"
+ * attributes of the "SimpleStandard" standard MBean.
+ */
+ public void reset();
+}
diff --git a/test/javax/management/remote/mandatory/passwordAuthenticator/jmxremote.login b/test/javax/management/remote/mandatory/passwordAuthenticator/jmxremote.login
new file mode 100644
index 0000000..9483c3a
--- /dev/null
+++ b/test/javax/management/remote/mandatory/passwordAuthenticator/jmxremote.login
@@ -0,0 +1,5 @@
+PasswordFileAuthentication {
+ com.sun.jmx.remote.security.FileLoginModule required
+ passwordFile="${test.src}${/}jmxremote.password-alt";
+};
+
diff --git a/test/javax/management/remote/mandatory/passwordAuthenticator/jmxremote.password b/test/javax/management/remote/mandatory/passwordAuthenticator/jmxremote.password
new file mode 100644
index 0000000..b29b668
--- /dev/null
+++ b/test/javax/management/remote/mandatory/passwordAuthenticator/jmxremote.password
@@ -0,0 +1 @@
+monitorRole QED
diff --git a/test/javax/management/remote/mandatory/passwordAuthenticator/jmxremote.password-alt b/test/javax/management/remote/mandatory/passwordAuthenticator/jmxremote.password-alt
new file mode 100644
index 0000000..7a4abe7
--- /dev/null
+++ b/test/javax/management/remote/mandatory/passwordAuthenticator/jmxremote.password-alt
@@ -0,0 +1 @@
+monitorRole pwd1
diff --git a/test/javax/management/remote/mandatory/provider/META-INF/services/javax.management.remote.JMXConnectorProvider b/test/javax/management/remote/mandatory/provider/META-INF/services/javax.management.remote.JMXConnectorProvider
new file mode 100644
index 0000000..0456199
--- /dev/null
+++ b/test/javax/management/remote/mandatory/provider/META-INF/services/javax.management.remote.JMXConnectorProvider
@@ -0,0 +1 @@
+provider.JMXConnectorProviderImpl
diff --git a/test/javax/management/remote/mandatory/provider/META-INF/services/javax.management.remote.JMXConnectorServerProvider b/test/javax/management/remote/mandatory/provider/META-INF/services/javax.management.remote.JMXConnectorServerProvider
new file mode 100644
index 0000000..e5c9612
--- /dev/null
+++ b/test/javax/management/remote/mandatory/provider/META-INF/services/javax.management.remote.JMXConnectorServerProvider
@@ -0,0 +1 @@
+provider.JMXConnectorServerProviderImpl
diff --git a/test/javax/management/remote/mandatory/provider/ProviderTest.java b/test/javax/management/remote/mandatory/provider/ProviderTest.java
new file mode 100644
index 0000000..0c7e906
--- /dev/null
+++ b/test/javax/management/remote/mandatory/provider/ProviderTest.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test ProviderTest.java
+ * @summary Tests jar services provider are called
+ * @run clean ProviderTest provider.JMXConnectorProviderImpl provider.JMXConnectorServerProviderImpl
+ * @run build ProviderTest provider.JMXConnectorProviderImpl provider.JMXConnectorServerProviderImpl
+ * @run main ProviderTest
+ */
+
+import java.net.MalformedURLException;
+
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.JMXProviderException;
+
+
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerFactory;
+import javax.management.MBeanServer;
+
+/*
+ * Tests jar services provider are called
+ */
+public class ProviderTest {
+ public static void main(String[] args) throws Exception {
+ System.out.println("Starting ProviderTest");
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ //First do the test with a protocol handled by Service providers
+ JMXServiceURL url =
+ new JMXServiceURL("service:jmx:rmi://");
+
+ dotest(url, mbs);
+
+ if(!provider.JMXConnectorProviderImpl.called() ||
+ !provider.JMXConnectorServerProviderImpl.called()) {
+ System.out.println("Test Failed");
+ System.exit(1);
+ }
+
+ //The Service Provider doesn't handle IIOP. Default providers MUST
+ //be called.
+ url =
+ new JMXServiceURL("service:jmx:iiop://");
+
+ dotest(url, mbs);
+
+ // Unsupported protocol.
+ JMXConnectorServer server = null;
+ JMXConnector client = null;
+ url =
+ new JMXServiceURL("service:jmx:unknown-protocol://");
+ try {
+ server =
+ JMXConnectorServerFactory.newJMXConnectorServer(url,
+ null,
+ mbs);
+ System.out.println("Exception not thrown.");
+ System.exit(1);
+ }catch(MalformedURLException e) {
+ System.out.println("Expected MalformedURLException thrown.");
+ }
+ catch(Exception e) {
+ e.printStackTrace();
+ System.out.println("Exception thrown : " + e);
+ System.exit(1);
+ }
+
+ try {
+ client =
+ JMXConnectorFactory.newJMXConnector(url,
+ null);
+ System.out.println("Exception not thrown.");
+ System.exit(1);
+ }catch(MalformedURLException e) {
+ System.out.println("Expected MalformedURLException thrown.");
+ }
+ catch(Exception e) {
+ e.printStackTrace();
+ System.out.println("Exception thrown : " + e);
+ System.exit(1);
+ }
+
+ //JMXConnectorProviderException
+ url =
+ new JMXServiceURL("service:jmx:throw-provider-exception://");
+ try {
+ server =
+ JMXConnectorServerFactory.newJMXConnectorServer(url,
+ null,
+ mbs);
+ System.out.println("Exception not thrown.");
+ System.exit(1);
+ }catch(JMXProviderException e) {
+ System.out.println("Expected JMXProviderException thrown.");
+ }
+ catch(Exception e) {
+ e.printStackTrace();
+ System.out.println("Exception thrown : " + e);
+ System.exit(1);
+ }
+
+ try {
+ client =
+ JMXConnectorFactory.newJMXConnector(url,
+ null);
+ System.out.println("Exception not thrown.");
+ System.exit(1);
+ }catch(JMXProviderException e) {
+ System.out.println("Expected JMXProviderException thrown.");
+ }
+ catch(Exception e) {
+ e.printStackTrace();
+ System.out.println("Exception thrown : " + e);
+ System.exit(1);
+ }
+
+ System.out.println("Test OK");
+ return;
+ }
+
+ private static void dotest(JMXServiceURL url, MBeanServer mbs)
+ throws Exception {
+ JMXConnectorServer server = null;
+ JMXConnector client = null;
+ try {
+ server =
+ JMXConnectorServerFactory.newJMXConnectorServer(url,
+ null,
+ mbs);
+ }catch(IllegalArgumentException e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ server.start();
+ JMXServiceURL outputAddr = server.getAddress();
+ System.out.println("Server started ["+ outputAddr+ "]");
+
+ try {
+ client =
+ JMXConnectorFactory.newJMXConnector(outputAddr, null);
+ }catch(IllegalArgumentException e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+
+ client.connect();
+ System.out.println("Client connected");
+
+ MBeanServerConnection connection
+ = client.getMBeanServerConnection();
+
+ System.out.println(connection.getDefaultDomain());
+ }
+}
diff --git a/test/javax/management/remote/mandatory/provider/provider/JMXConnectorProviderImpl.java b/test/javax/management/remote/mandatory/provider/provider/JMXConnectorProviderImpl.java
new file mode 100644
index 0000000..38f9ee5
--- /dev/null
+++ b/test/javax/management/remote/mandatory/provider/provider/JMXConnectorProviderImpl.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2003-2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package provider;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.management.remote.JMXConnectorProvider;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXServiceURL;
+
+import javax.management.remote.rmi.RMIConnector;
+import javax.management.remote.JMXProviderException;
+
+public class JMXConnectorProviderImpl implements JMXConnectorProvider {
+ private static boolean called = false;
+ public static boolean called() {
+ return called;
+ }
+
+ public JMXConnector newJMXConnector(JMXServiceURL url,
+ Map<String,?> map)
+ throws IOException {
+ final String protocol = url.getProtocol();
+ called = true;
+ System.out.println("JMXConnectorProviderImpl called");
+
+ if(protocol.equals("rmi"))
+ return new RMIConnector(url, map);
+ if(protocol.equals("throw-provider-exception"))
+ throw new JMXProviderException("I have been asked to throw");
+
+ throw new IllegalArgumentException("UNKNOWN PROTOCOL");
+ }
+}
diff --git a/test/javax/management/remote/mandatory/provider/provider/JMXConnectorServerProviderImpl.java b/test/javax/management/remote/mandatory/provider/provider/JMXConnectorServerProviderImpl.java
new file mode 100644
index 0000000..e230d2e
--- /dev/null
+++ b/test/javax/management/remote/mandatory/provider/provider/JMXConnectorServerProviderImpl.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2003-2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package provider;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.management.MBeanServer;
+
+import javax.management.remote.JMXConnectorServerProvider;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXServiceURL;
+
+import javax.management.remote.rmi.RMIConnectorServer;
+import javax.management.remote.JMXProviderException;
+
+public class JMXConnectorServerProviderImpl
+ implements JMXConnectorServerProvider {
+ private static boolean called = false;
+
+ public static boolean called() {
+ return called;
+ }
+
+ public JMXConnectorServer newJMXConnectorServer(JMXServiceURL url,
+ Map<String,?> map,
+ MBeanServer mbeanServer)
+ throws IOException {
+ final String protocol = url.getProtocol();
+ called = true;
+ System.out.println("JMXConnectorServerProviderImpl called");
+ if(protocol.equals("rmi"))
+ return new RMIConnectorServer(url, map, mbeanServer);
+ if(protocol.equals("throw-provider-exception"))
+ throw new JMXProviderException("I have been asked to throw");
+
+ throw new IllegalArgumentException("UNKNOWN PROTOCOL");
+ }
+}
diff --git a/test/javax/management/remote/mandatory/serverError/JMXServerErrorTest.java b/test/javax/management/remote/mandatory/serverError/JMXServerErrorTest.java
new file mode 100644
index 0000000..a43fab7
--- /dev/null
+++ b/test/javax/management/remote/mandatory/serverError/JMXServerErrorTest.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4871761
+ * @summary Tests that JMXServiceErrorException is correctly emitted.
+ * @author Daniel Fuchs
+ * @run clean JMXServerErrorTest
+ * @run build JMXServerErrorTest
+ * @run main JMXServerErrorTest
+ */
+
+import java.util.HashMap ;
+import java.util.Map ;
+import java.net.MalformedURLException;
+import java.io.IOException ;
+
+import javax.management.MBeanServerFactory;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXServerErrorException;
+
+import com.sun.jmx.remote.security.MBeanServerAccessController;
+
+public class JMXServerErrorTest {
+
+ public static String urls[] = {
+ "service:jmx:rmi://", "service:jmx:iiop://","service:jmx:jmxmp://"
+ };
+
+ public static class KaefferError extends Error {
+ public KaefferError(String message, Throwable cause) {
+ super(message,cause);
+ }
+ }
+
+ /**
+ * generates an error...
+ **/
+ public static class MBeanServerKaeffer
+ extends MBeanServerAccessController {
+
+ MBeanServerKaeffer(MBeanServer srv) {
+ super();
+ setMBeanServer(srv);
+ }
+
+
+ /**
+ * Check if the caller can do read operations. This method does
+ * nothing if so, otherwise throws SecurityException.
+ */
+ protected void checkRead() {
+ // do nothing
+ }
+
+ /**
+ * Check if the caller can do write operations. This method does
+ * nothing if so, otherwise throws SecurityException.
+ */
+ protected void checkWrite() {
+ // generate error
+ throw new KaefferError("Try to catch this!",null);
+ }
+ }
+
+ public interface KaefferMBean {
+ public String getThis() throws IOException;
+ public void setThis(String that) throws IOException;
+ public String doThis(String that) throws IOException;
+ }
+
+ public static class Kaeffer implements KaefferMBean {
+ String that = "";
+ public Kaeffer(String that) {
+ setThis(that);
+ }
+ public String getThis() {return that;}
+ public void setThis(String that) { this.that=(that==null)?"":that; }
+ public String doThis(String that) { return this.that += " " + that;}
+ }
+
+ public void test(String url) throws Exception {
+ final JMXServiceURL jurl = new JMXServiceURL(url);
+ final ObjectName kname = new ObjectName(":type=Kaeffer");
+ final MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ final String that = "that";
+ mbs.registerMBean(new Kaeffer(that),kname);
+ final MBeanServer kbs = new MBeanServerKaeffer(mbs);
+
+ final JMXConnectorServer cs;
+ try {
+ cs=JMXConnectorServerFactory.newJMXConnectorServer(jurl,null,kbs);
+ } catch (MalformedURLException m) {
+ if ("jmxmp".equals(jurl.getProtocol())) {
+ // OK, we may not have this in the classpath...
+ System.out.println("WARNING: Skipping protocol: " + jurl);
+ return;
+ }
+ throw m;
+ }
+
+ final ObjectName cname =
+ new ObjectName(":type=JMXConnectorServer");
+ mbs.registerMBean(cs,cname);
+ cs.start();
+ JMXConnector c = null;
+ try {
+ c = JMXConnectorFactory.connect(cs.getAddress(),null);
+
+ final MBeanServerConnection mbsc = c.getMBeanServerConnection();
+ final KaefferMBean kaeffer = (KaefferMBean)
+ MBeanServerInvocationHandler.
+ newProxyInstance(mbsc, kname, KaefferMBean.class, false);
+ final String that1 = kaeffer.getThis();
+ if (!that.equals(that1))
+ throw new Exception("Unexpected string returned by " +
+ kname + ": " + that1);
+ try {
+ kaeffer.setThis("but not that");
+ throw new Exception("Expected JMXServerErrorException"+
+ " not thrown"+
+ " for setAttribute \"This\" ");
+ } catch (JMXServerErrorException jsee) {
+ if (!(jsee.getCause() instanceof KaefferError)) {
+ final Exception e =
+ new Exception("Expected JMXServerErrorException"+
+ " is not an instance of " +
+ KaefferError.class.getName()+
+ ": " + jsee.getCause());
+ e.initCause(jsee);
+ throw e;
+ }
+ System.out.println("Got expected error: " + jsee);
+ }
+
+ try {
+ kaeffer.doThis("but not that");
+ throw new Exception("Expected JMXServerErrorException" +
+ " not thrown"+
+ " for invoke \"doThis\" ");
+ } catch (JMXServerErrorException jsee) {
+ if (!(jsee.getCause() instanceof KaefferError)) {
+ final Exception e =
+ new Exception("Expected JMXServerErrorException"+
+ " is not an instance of " +
+ KaefferError.class.getName()+
+ ": " + jsee.getCause());
+ e.initCause(jsee);
+ throw e;
+ }
+ System.out.println("Got expected error: " + jsee);
+ }
+ } finally {
+ if (c != null) try { c.close(); }
+ catch (Exception x) {
+ System.err.println("Failed to close client: " + x);
+ throw x;
+ }
+ try { cs.stop(); }
+ catch (Exception x) {
+ System.err.println("Failed to stop server: " + x);
+ throw x;
+ }
+ }
+ }
+
+ public static void main(String args[]) {
+ final JMXServerErrorTest test = new JMXServerErrorTest();
+ int errCount=0;
+ for (int i=0; i<urls.length; i++) {
+ try {
+ System.out.println("Trying with url: " + urls[i]);
+ test.test(urls[i]);
+ System.out.println("PASSED: test passed for: " + urls[i]);
+ } catch (Exception x) {
+ errCount++;
+ System.err.println("FAILED: test failed for " + urls[i] +
+ ": " + x);
+ x.printStackTrace();
+ }
+ }
+ if (errCount != 0) System.exit(errCount);
+ }
+}
diff --git a/test/javax/management/remote/mandatory/socketFactories/RMIClientFactory.java b/test/javax/management/remote/mandatory/socketFactories/RMIClientFactory.java
new file mode 100644
index 0000000..17b92fd
--- /dev/null
+++ b/test/javax/management/remote/mandatory/socketFactories/RMIClientFactory.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import java.io.*;
+import java.net.*;
+import java.rmi.server.*;
+
+public class RMIClientFactory
+ implements RMIClientSocketFactory, Serializable {
+
+ private String test;
+ private boolean throwException;
+
+ public RMIClientFactory(String test) {
+ this.test = test;
+ throwException = test.equals("test_client_factory") ? true : false;
+ }
+
+ public Socket createSocket(String host, int port) throws IOException {
+ if (throwException) {
+ throw new RuntimeException(test);
+ } else {
+ System.out.println("Calling createSocket("+host+","+port+")");
+ Socket s = new Socket(host, port);
+ System.out.println("Socket = " + s);
+ return s;
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/socketFactories/RMIServerFactory.java b/test/javax/management/remote/mandatory/socketFactories/RMIServerFactory.java
new file mode 100644
index 0000000..e34f690
--- /dev/null
+++ b/test/javax/management/remote/mandatory/socketFactories/RMIServerFactory.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import java.io.*;
+import java.net.*;
+import java.rmi.server.*;
+
+public class RMIServerFactory
+ implements RMIServerSocketFactory, Serializable {
+
+ private String test;
+ private boolean throwException;
+
+ public RMIServerFactory(String test) {
+ this.test = test;
+ throwException = test.equals("test_server_factory") ? true : false;
+ }
+
+ public ServerSocket createServerSocket(int port) throws IOException {
+ if (throwException) {
+ throw new RuntimeException(test);
+ } else {
+ System.out.println("Calling createServerSocket(" + port + ")");
+ ServerSocket ss = new ServerSocket(port);
+ System.out.println("ServerSocket = " + ss);
+ return ss;
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/socketFactories/RMISocketFactoriesTest.java b/test/javax/management/remote/mandatory/socketFactories/RMISocketFactoriesTest.java
new file mode 100644
index 0000000..1098049
--- /dev/null
+++ b/test/javax/management/remote/mandatory/socketFactories/RMISocketFactoriesTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 7654321
+ * @summary Tests the use of the custom RMI socket factories.
+ * @author Luis-Miguel Alventosa
+ * @run clean RMISocketFactoriesTest
+ * @run build RMISocketFactoriesTest RMIClientFactory RMIServerFactory
+ * @run main RMISocketFactoriesTest test_server_factory
+ * @run main RMISocketFactoriesTest test_client_factory
+ */
+
+import java.io.IOException;
+import java.rmi.RemoteException;
+import java.rmi.registry.Registry;
+import java.rmi.registry.LocateRegistry;
+import java.util.HashMap;
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerFactory;
+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.remote.rmi.RMIConnectorServer; // for constants
+
+public class RMISocketFactoriesTest {
+
+ public static void main(String[] args) {
+ System.out.println("Test RMI factories : " + args[0]);
+ try {
+ // Create an RMI registry
+ //
+ System.out.println("Start RMI registry...");
+ Registry reg = null;
+ int port = 5800;
+ while (port++ < 6000) {
+ try {
+ reg = LocateRegistry.createRegistry(port);
+ System.out.println("RMI registry running on port " + port);
+ break;
+ } catch (RemoteException e) {
+ // Failed to create RMI registry...
+ System.out.println("Failed to create RMI registry " +
+ "on port " + port);
+ }
+ }
+ if (reg == null) {
+ System.exit(1);
+ }
+
+ // Instantiate the MBean server
+ //
+ System.out.println("Create the MBean server");
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ // Initialize environment map to be passed to the connector server
+ //
+ System.out.println("Initialize environment map");
+ HashMap env = new HashMap();
+ env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE,
+ new RMIServerFactory(args[0]));
+ env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE,
+ new RMIClientFactory(args[0]));
+ // Create an RMI connector server
+ //
+ System.out.println("Create an RMI connector server");
+ JMXServiceURL url =
+ new JMXServiceURL("rmi", null, 0,
+ "/jndi/rmi://:" + port + "/server" + port);
+ JMXConnectorServer rcs =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
+ rcs.start();
+
+ // Create an RMI connector client
+ //
+ System.out.println("Create an RMI connector client");
+ JMXConnector jmxc = JMXConnectorFactory.connect(url, new HashMap());
+
+ // If this line is executed then the test failed
+ //
+ System.exit(1);
+ } catch (Exception e) {
+ if (e.getMessage().equals(args[0])) {
+ System.out.println("Expected exception caught = " + e);
+ System.out.println("Bye! Bye!");
+ } else {
+ System.out.println("Unexpected exception caught = " + e);
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/subjectDelegation/SimpleStandard.java b/test/javax/management/remote/mandatory/subjectDelegation/SimpleStandard.java
new file mode 100644
index 0000000..1a0e1df
--- /dev/null
+++ b/test/javax/management/remote/mandatory/subjectDelegation/SimpleStandard.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2003-2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * Simple definition of a standard MBean, named "SimpleStandard".
+ *
+ * The "SimpleStandard" standard MBean shows how to expose attributes and
+ * operations for management by implementing its corresponding
+ * "SimpleStandardMBean" management interface.
+ *
+ * This MBean has two attributes and one operation exposed
+ * for management by a JMX agent:
+ * - the read/write "State" attribute,
+ * - the read only "NbChanges" attribute,
+ * - the "reset()" operation.
+ *
+ * This object also has one property and one method not exposed
+ * for management by a JMX agent:
+ * - the "NbResets" property,
+ * - the "getNbResets()" method.
+ */
+
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.Principal;
+import java.util.Set;
+import javax.management.AttributeChangeNotification;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.remote.JMXPrincipal;
+import javax.security.auth.Subject;
+
+public class SimpleStandard
+ extends NotificationBroadcasterSupport
+ implements SimpleStandardMBean {
+
+ /*
+ * -----------------------------------------------------
+ * CONSTRUCTORS
+ * -----------------------------------------------------
+ */
+
+ public SimpleStandard(String principalName) {
+ this.principalName = principalName;
+ }
+
+ /*
+ * -----------------------------------------------------
+ * IMPLEMENTATION OF THE SimpleStandardMBean INTERFACE
+ * -----------------------------------------------------
+ */
+
+ /**
+ * Getter: get the "State" attribute of the "SimpleStandard" standard MBean.
+ *
+ * @return the current value of the "State" attribute.
+ */
+ public String getState() {
+ checkSubject();
+ return state;
+ }
+
+ /**
+ * Setter: set the "State" attribute of the "SimpleStandard" standard MBean.
+ *
+ * @param <VAR>s</VAR> the new value of the "State" attribute.
+ */
+ public void setState(String s) {
+ checkSubject();
+ state = s;
+ nbChanges++;
+ }
+
+ /**
+ * Getter: get the "NbChanges" attribute of the "SimpleStandard" standard
+ * MBean.
+ *
+ * @return the current value of the "NbChanges" attribute.
+ */
+ public int getNbChanges() {
+ checkSubject();
+ return nbChanges;
+ }
+
+ /**
+ * Operation: reset to their initial values the "State" and "NbChanges"
+ * attributes of the "SimpleStandard" standard MBean.
+ */
+ public void reset() {
+ checkSubject();
+ AttributeChangeNotification acn =
+ new AttributeChangeNotification(this,
+ 0,
+ 0,
+ "NbChanges reset",
+ "NbChanges",
+ "Integer",
+ new Integer(nbChanges),
+ new Integer(0));
+ state = "initial state";
+ nbChanges = 0;
+ nbResets++;
+ sendNotification(acn);
+ }
+
+ /*
+ * -----------------------------------------------------
+ * METHOD NOT EXPOSED FOR MANAGEMENT BY A JMX AGENT
+ * -----------------------------------------------------
+ */
+
+ /**
+ * Return the "NbResets" property.
+ * This method is not a Getter in the JMX sense because
+ * it is not exposed in the "SimpleStandardMBean" interface.
+ *
+ * @return the current value of the "NbResets" property.
+ */
+ public int getNbResets() {
+ return nbResets;
+ }
+
+ /*
+ * ---------------
+ * PRIVATE METHODS
+ * ---------------
+ */
+
+ /**
+ * Check that the principal contained in the Subject is of
+ * type JMXPrincipal and refers to the principalName identity.
+ */
+ private void checkSubject() {
+ AccessControlContext acc = AccessController.getContext();
+ Subject subject = Subject.getSubject(acc);
+ Set principals = subject.getPrincipals();
+ Principal principal = (Principal) principals.iterator().next();
+ if (!(principal instanceof JMXPrincipal))
+ throw new SecurityException("Authenticated subject contains " +
+ "invalid principal type = " +
+ principal.getClass().getName());
+ String identity = principal.getName();
+ if (!identity.equals(principalName))
+ throw new SecurityException("Authenticated subject contains " +
+ "invalid principal name = " + identity);
+ }
+
+ /*
+ * -----------------------------------------------------
+ * ATTRIBUTES ACCESSIBLE FOR MANAGEMENT BY A JMX AGENT
+ * -----------------------------------------------------
+ */
+
+ private String state = "initial state";
+ private int nbChanges = 0;
+
+ /*
+ * -----------------------------------------------------
+ * PROPERTY NOT ACCESSIBLE FOR MANAGEMENT BY A JMX AGENT
+ * -----------------------------------------------------
+ */
+
+ private int nbResets = 0;
+ private String principalName;
+}
diff --git a/test/javax/management/remote/mandatory/subjectDelegation/SimpleStandardMBean.java b/test/javax/management/remote/mandatory/subjectDelegation/SimpleStandardMBean.java
new file mode 100644
index 0000000..e214087
--- /dev/null
+++ b/test/javax/management/remote/mandatory/subjectDelegation/SimpleStandardMBean.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * This is the management interface explicitly defined for the
+ * "SimpleStandard" standard MBean.
+ * The "SimpleStandard" standard MBean implements this interface
+ * in order to be manageable through a JMX agent.
+ *
+ * The "SimpleStandardMBean" interface shows how to expose for management:
+ * - a read/write attribute (named "State") through its getter and setter
+ * methods,
+ * - a read-only attribute (named "NbChanges") through its getter method,
+ * - an operation (named "reset").
+ */
+public interface SimpleStandardMBean {
+
+ /**
+ * Getter: set the "State" attribute of the "SimpleStandard" standard
+ * MBean.
+ *
+ * @return the current value of the "State" attribute.
+ */
+ public String getState();
+
+ /**
+ * Setter: set the "State" attribute of the "SimpleStandard" standard
+ * MBean.
+ *
+ * @param <VAR>s</VAR> the new value of the "State" attribute.
+ */
+ public void setState(String s);
+
+ /**
+ * Getter: get the "NbChanges" attribute of the "SimpleStandard" standard
+ * MBean.
+ *
+ * @return the current value of the "NbChanges" attribute.
+ */
+ public int getNbChanges();
+
+ /**
+ * Operation: reset to their initial values the "State" and "NbChanges"
+ * attributes of the "SimpleStandard" standard MBean.
+ */
+ public void reset();
+}
diff --git a/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation1Test.java b/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation1Test.java
new file mode 100644
index 0000000..07680db
--- /dev/null
+++ b/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation1Test.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright 2003-2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6261831
+ * @summary Tests the use of the subject delegation feature in the
+ * RMI connector
+ * @author Luis-Miguel Alventosa
+ * @run clean SubjectDelegation1Test SimpleStandard SimpleStandardMBean
+ * @run build SubjectDelegation1Test SimpleStandard SimpleStandardMBean
+ * @run main SubjectDelegation1Test policy11 ok
+ * @run main SubjectDelegation1Test policy12 ko
+ * @run main SubjectDelegation1Test policy13 ko
+ * @run main SubjectDelegation1Test policy14 ko
+ * @run main SubjectDelegation1Test policy15 ok
+ * @run main SubjectDelegation1Test policy16 ko
+ */
+
+import com.sun.jmx.remote.security.JMXPluggableAuthenticator;
+import java.io.File;
+import java.lang.management.ManagementFactory;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Properties;
+import javax.management.Attribute;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+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.JMXPrincipal;
+import javax.management.remote.JMXServiceURL;
+import javax.security.auth.Subject;
+
+public class SubjectDelegation1Test {
+
+ public static void main(String[] args) throws Exception {
+ // Check for supported operating systems: Solaris
+ //
+ // This test runs only on Solaris due to CR 6285916
+ //
+ String osName = System.getProperty("os.name");
+ System.out.println("os.name = " + osName);
+ if (!osName.equals("SunOS")) {
+ System.out.println("This test runs on Solaris only.");
+ System.out.println("Bye! Bye!");
+ return;
+ }
+ String policyFile = args[0];
+ String testResult = args[1];
+ System.out.println("Policy file = " + policyFile);
+ System.out.println("Expected test result = " + testResult);
+ JMXConnectorServer jmxcs = null;
+ JMXConnector jmxc = null;
+ try {
+ // Create an RMI registry
+ //
+ System.out.println("Start RMI registry...");
+ Registry reg = null;
+ int port = 5800;
+ while (port++ < 6000) {
+ try {
+ reg = LocateRegistry.createRegistry(port);
+ System.out.println("RMI registry running on port " + port);
+ break;
+ } catch (RemoteException e) {
+ // Failed to create RMI registry...
+ System.out.println("Failed to create RMI registry " +
+ "on port " + port);
+ }
+ }
+ if (reg == null) {
+ System.exit(1);
+ }
+ // Set the default password file
+ //
+ final String passwordFile = System.getProperty("test.src") +
+ File.separator + "jmxremote.password";
+ System.out.println("Password file = " + passwordFile);
+ // Set policy file
+ //
+ final String policy = System.getProperty("test.src") +
+ File.separator + policyFile;
+ System.out.println("PolicyFile = " + policy);
+ System.setProperty("java.security.policy", policy);
+ // Instantiate the MBean server
+ //
+ System.out.println("Create the MBean server");
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ // Register the SimpleStandardMBean
+ //
+ System.out.println("Create SimpleStandard MBean");
+ SimpleStandard s = new SimpleStandard("delegate");
+ mbs.registerMBean(s, new ObjectName("MBeans:type=SimpleStandard"));
+ // Create Properties containing the username/password entries
+ //
+ Properties props = new Properties();
+ props.setProperty("jmx.remote.x.password.file", passwordFile);
+ // Initialize environment map to be passed to the connector server
+ //
+ System.out.println("Initialize environment map");
+ HashMap env = new HashMap();
+ env.put("jmx.remote.authenticator",
+ new JMXPluggableAuthenticator(props));
+ // Create an RMI connector server
+ //
+ System.out.println("Create an RMI connector server");
+ JMXServiceURL url =
+ new JMXServiceURL("rmi", null, 0,
+ "/jndi/rmi://:" + port + "/server" + port);
+ jmxcs =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
+ jmxcs.start();
+ // Create an RMI connector client
+ //
+ System.out.println("Create an RMI connector client");
+ HashMap cli_env = new HashMap();
+ // These credentials must match those in the default password file
+ //
+ String[] credentials = new String[] { "monitorRole" , "QED" };
+ cli_env.put("jmx.remote.credentials", credentials);
+ jmxc = JMXConnectorFactory.connect(url, cli_env);
+ Subject delegationSubject =
+ new Subject(true,
+ Collections.singleton(new JMXPrincipal("delegate")),
+ Collections.EMPTY_SET,
+ Collections.EMPTY_SET);
+ MBeanServerConnection mbsc =
+ jmxc.getMBeanServerConnection(delegationSubject);
+ // Get domains from MBeanServer
+ //
+ System.out.println("Domains:");
+ String domains[] = mbsc.getDomains();
+ for (int i = 0; i < domains.length; i++) {
+ System.out.println("\tDomain[" + i + "] = " + domains[i]);
+ }
+ // Get MBean count
+ //
+ System.out.println("MBean count = " + mbsc.getMBeanCount());
+ // Get State attribute
+ //
+ String oldState =
+ (String) mbsc.getAttribute(
+ new ObjectName("MBeans:type=SimpleStandard"),
+ "State");
+ System.out.println("Old State = \"" + oldState + "\"");
+ // Set State attribute
+ //
+ System.out.println("Set State to \"changed state\"");
+ mbsc.setAttribute(new ObjectName("MBeans:type=SimpleStandard"),
+ new Attribute("State", "changed state"));
+ // Get State attribute
+ //
+ String newState =
+ (String) mbsc.getAttribute(
+ new ObjectName("MBeans:type=SimpleStandard"),
+ "State");
+ System.out.println("New State = \"" + newState + "\"");
+ if (!newState.equals("changed state")) {
+ System.out.println("Invalid State = \"" + newState + "\"");
+ System.exit(1);
+ }
+ // Add notification listener on SimpleStandard MBean
+ //
+ System.out.println("Add notification listener...");
+ mbsc.addNotificationListener(
+ new ObjectName("MBeans:type=SimpleStandard"),
+ new NotificationListener() {
+ public void handleNotification(Notification notification,
+ Object handback) {
+ System.out.println("Received notification: " +
+ notification);
+ }
+ },
+ null,
+ null);
+ // Unregister SimpleStandard MBean
+ //
+ System.out.println("Unregister SimpleStandard MBean...");
+ mbsc.unregisterMBean(new ObjectName("MBeans:type=SimpleStandard"));
+ } catch (SecurityException e) {
+ if (testResult.equals("ko")) {
+ System.out.println("Got expected security exception = " + e);
+ } else {
+ System.out.println("Got unexpected security exception = " + e);
+ e.printStackTrace();
+ throw e;
+ }
+ } catch (Exception e) {
+ System.out.println("Unexpected exception caught = " + e);
+ e.printStackTrace();
+ throw e;
+ } finally {
+ // Close connector client
+ //
+ if (jmxc != null)
+ jmxc.close();
+ // Stop connector server
+ //
+ if (jmxcs != null)
+ jmxcs.stop();
+ // Say goodbye
+ //
+ System.out.println("Bye! Bye!");
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java b/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java
new file mode 100644
index 0000000..48eca94
--- /dev/null
+++ b/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6261831
+ * @summary Tests the use of the subject delegation feature on the authenticated
+ * principals within the RMI connector server's creator codebase.
+ * @author Luis-Miguel Alventosa
+ * @run clean SubjectDelegation2Test SimpleStandard SimpleStandardMBean
+ * @run build SubjectDelegation2Test SimpleStandard SimpleStandardMBean
+ * @run main SubjectDelegation2Test policy21 ok
+ * @run main SubjectDelegation2Test policy22 ko
+ * @run main SubjectDelegation2Test policy23 ko
+ * @run main SubjectDelegation2Test policy24 ok
+ * @run main SubjectDelegation2Test policy25 ko
+ */
+
+import com.sun.jmx.remote.security.JMXPluggableAuthenticator;
+import java.io.File;
+import java.lang.management.ManagementFactory;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Properties;
+import javax.management.Attribute;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+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.JMXPrincipal;
+import javax.management.remote.JMXServiceURL;
+import javax.security.auth.Subject;
+
+public class SubjectDelegation2Test {
+
+ public static void main(String[] args) throws Exception {
+ // Check for supported operating systems: Solaris
+ //
+ // This test runs only on Solaris due to CR 6285916
+ //
+ String osName = System.getProperty("os.name");
+ System.out.println("os.name = " + osName);
+ if (!osName.equals("SunOS")) {
+ System.out.println("This test runs on Solaris only.");
+ System.out.println("Bye! Bye!");
+ return;
+ }
+ String policyFile = args[0];
+ String testResult = args[1];
+ System.out.println("Policy file = " + policyFile);
+ System.out.println("Expected test result = " + testResult);
+ JMXConnectorServer jmxcs = null;
+ JMXConnector jmxc = null;
+ try {
+ // Create an RMI registry
+ //
+ System.out.println("Start RMI registry...");
+ Registry reg = null;
+ int port = 5800;
+ while (port++ < 6000) {
+ try {
+ reg = LocateRegistry.createRegistry(port);
+ System.out.println("RMI registry running on port " + port);
+ break;
+ } catch (RemoteException e) {
+ // Failed to create RMI registry...
+ System.out.println("Failed to create RMI registry " +
+ "on port " + port);
+ }
+ }
+ if (reg == null) {
+ System.exit(1);
+ }
+ // Set the default password file
+ //
+ final String passwordFile = System.getProperty("test.src") +
+ File.separator + "jmxremote.password";
+ System.out.println("Password file = " + passwordFile);
+ // Set policy file
+ //
+ final String policy = System.getProperty("test.src") +
+ File.separator + policyFile;
+ System.out.println("PolicyFile = " + policy);
+ System.setProperty("java.security.policy", policy);
+ // Instantiate the MBean server
+ //
+ System.out.println("Create the MBean server");
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ // Register the SimpleStandardMBean
+ //
+ System.out.println("Create SimpleStandard MBean");
+ SimpleStandard s = new SimpleStandard("monitorRole");
+ mbs.registerMBean(s, new ObjectName("MBeans:type=SimpleStandard"));
+ // Set Security Manager
+ //
+ System.setSecurityManager(new SecurityManager());
+ // Create Properties containing the username/password entries
+ //
+ Properties props = new Properties();
+ props.setProperty("jmx.remote.x.password.file", passwordFile);
+ // Initialize environment map to be passed to the connector server
+ //
+ System.out.println("Initialize environment map");
+ HashMap env = new HashMap();
+ env.put("jmx.remote.authenticator",
+ new JMXPluggableAuthenticator(props));
+ // Create an RMI connector server
+ //
+ System.out.println("Create an RMI connector server");
+ JMXServiceURL url =
+ new JMXServiceURL("rmi", null, 0,
+ "/jndi/rmi://:" + port + "/server" + port);
+ jmxcs =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
+ jmxcs.start();
+ // Create an RMI connector client
+ //
+ System.out.println("Create an RMI connector client");
+ HashMap cli_env = new HashMap();
+ // These credentials must match those in the default password file
+ //
+ String[] credentials = new String[] { "monitorRole" , "QED" };
+ cli_env.put("jmx.remote.credentials", credentials);
+ jmxc = JMXConnectorFactory.connect(url, cli_env);
+ MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
+ // Get domains from MBeanServer
+ //
+ System.out.println("Domains:");
+ String domains[] = mbsc.getDomains();
+ for (int i = 0; i < domains.length; i++) {
+ System.out.println("\tDomain[" + i + "] = " + domains[i]);
+ }
+ // Get MBean count
+ //
+ System.out.println("MBean count = " + mbsc.getMBeanCount());
+ // Get State attribute
+ //
+ String oldState =
+ (String) mbsc.getAttribute(
+ new ObjectName("MBeans:type=SimpleStandard"),
+ "State");
+ System.out.println("Old State = \"" + oldState + "\"");
+ // Set State attribute
+ //
+ System.out.println("Set State to \"changed state\"");
+ mbsc.setAttribute(new ObjectName("MBeans:type=SimpleStandard"),
+ new Attribute("State", "changed state"));
+ // Get State attribute
+ //
+ String newState =
+ (String) mbsc.getAttribute(
+ new ObjectName("MBeans:type=SimpleStandard"),
+ "State");
+ System.out.println("New State = \"" + newState + "\"");
+ if (!newState.equals("changed state")) {
+ System.out.println("Invalid State = \"" + newState + "\"");
+ System.exit(1);
+ }
+ // Add notification listener on SimpleStandard MBean
+ //
+ System.out.println("Add notification listener...");
+ mbsc.addNotificationListener(
+ new ObjectName("MBeans:type=SimpleStandard"),
+ new NotificationListener() {
+ public void handleNotification(Notification notification,
+ Object handback) {
+ System.out.println("Received notification: " +
+ notification);
+ }
+ },
+ null,
+ null);
+ // Unregister SimpleStandard MBean
+ //
+ System.out.println("Unregister SimpleStandard MBean...");
+ mbsc.unregisterMBean(new ObjectName("MBeans:type=SimpleStandard"));
+ } catch (SecurityException e) {
+ if (testResult.equals("ko")) {
+ System.out.println("Got expected security exception = " + e);
+ } else {
+ System.out.println("Got unexpected security exception = " + e);
+ e.printStackTrace();
+ throw e;
+ }
+ } catch (Exception e) {
+ System.out.println("Unexpected exception caught = " + e);
+ e.printStackTrace();
+ throw e;
+ } finally {
+ // Close connector client
+ //
+ if (jmxc != null)
+ jmxc.close();
+ // Stop connector server
+ //
+ if (jmxcs != null)
+ jmxcs.stop();
+ // Say goodbye
+ //
+ System.out.println("Bye! Bye!");
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java b/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java
new file mode 100644
index 0000000..a9f706b
--- /dev/null
+++ b/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6261831
+ * @summary Tests the use of the subject delegation feature on the authenticated
+ * principals within the RMI connector server's creator codebase with
+ * subject delegation.
+ * @author Luis-Miguel Alventosa
+ * @run clean SubjectDelegation3Test SimpleStandard SimpleStandardMBean
+ * @run build SubjectDelegation3Test SimpleStandard SimpleStandardMBean
+ * @run main SubjectDelegation3Test policy31 ok
+ * @run main SubjectDelegation3Test policy32 ko
+ * @run main SubjectDelegation3Test policy33 ko
+ * @run main SubjectDelegation3Test policy34 ok
+ * @run main SubjectDelegation3Test policy35 ko
+ */
+
+import com.sun.jmx.remote.security.JMXPluggableAuthenticator;
+import java.io.File;
+import java.lang.management.ManagementFactory;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Properties;
+import javax.management.Attribute;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+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.JMXPrincipal;
+import javax.management.remote.JMXServiceURL;
+import javax.security.auth.Subject;
+
+public class SubjectDelegation3Test {
+
+ public static void main(String[] args) throws Exception {
+ // Check for supported operating systems: Solaris
+ //
+ // This test runs only on Solaris due to CR 6285916
+ //
+ String osName = System.getProperty("os.name");
+ System.out.println("os.name = " + osName);
+ if (!osName.equals("SunOS")) {
+ System.out.println("This test runs on Solaris only.");
+ System.out.println("Bye! Bye!");
+ return;
+ }
+ String policyFile = args[0];
+ String testResult = args[1];
+ System.out.println("Policy file = " + policyFile);
+ System.out.println("Expected test result = " + testResult);
+ JMXConnectorServer jmxcs = null;
+ JMXConnector jmxc = null;
+ try {
+ // Create an RMI registry
+ //
+ System.out.println("Start RMI registry...");
+ Registry reg = null;
+ int port = 5800;
+ while (port++ < 6000) {
+ try {
+ reg = LocateRegistry.createRegistry(port);
+ System.out.println("RMI registry running on port " + port);
+ break;
+ } catch (RemoteException e) {
+ // Failed to create RMI registry...
+ System.out.println("Failed to create RMI registry " +
+ "on port " + port);
+ }
+ }
+ if (reg == null) {
+ System.exit(1);
+ }
+ // Set the default password file
+ //
+ final String passwordFile = System.getProperty("test.src") +
+ File.separator + "jmxremote.password";
+ System.out.println("Password file = " + passwordFile);
+ // Set policy file
+ //
+ final String policy = System.getProperty("test.src") +
+ File.separator + policyFile;
+ System.out.println("PolicyFile = " + policy);
+ System.setProperty("java.security.policy", policy);
+ // Instantiate the MBean server
+ //
+ System.out.println("Create the MBean server");
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ // Register the SimpleStandardMBean
+ //
+ System.out.println("Create SimpleStandard MBean");
+ SimpleStandard s = new SimpleStandard("delegate");
+ mbs.registerMBean(s, new ObjectName("MBeans:type=SimpleStandard"));
+ // Set Security Manager
+ //
+ System.setSecurityManager(new SecurityManager());
+ // Create Properties containing the username/password entries
+ //
+ Properties props = new Properties();
+ props.setProperty("jmx.remote.x.password.file", passwordFile);
+ // Initialize environment map to be passed to the connector server
+ //
+ System.out.println("Initialize environment map");
+ HashMap env = new HashMap();
+ env.put("jmx.remote.authenticator",
+ new JMXPluggableAuthenticator(props));
+ // Create an RMI connector server
+ //
+ System.out.println("Create an RMI connector server");
+ JMXServiceURL url =
+ new JMXServiceURL("rmi", null, 0,
+ "/jndi/rmi://:" + port + "/server" + port);
+ jmxcs =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
+ jmxcs.start();
+ // Create an RMI connector client
+ //
+ System.out.println("Create an RMI connector client");
+ HashMap cli_env = new HashMap();
+ // These credentials must match those in the default password file
+ //
+ String[] credentials = new String[] { "monitorRole" , "QED" };
+ cli_env.put("jmx.remote.credentials", credentials);
+ jmxc = JMXConnectorFactory.connect(url, cli_env);
+ Subject delegationSubject =
+ new Subject(true,
+ Collections.singleton(new JMXPrincipal("delegate")),
+ Collections.EMPTY_SET,
+ Collections.EMPTY_SET);
+ MBeanServerConnection mbsc =
+ jmxc.getMBeanServerConnection(delegationSubject);
+ // Get domains from MBeanServer
+ //
+ System.out.println("Domains:");
+ String domains[] = mbsc.getDomains();
+ for (int i = 0; i < domains.length; i++) {
+ System.out.println("\tDomain[" + i + "] = " + domains[i]);
+ }
+ // Get MBean count
+ //
+ System.out.println("MBean count = " + mbsc.getMBeanCount());
+ // Get State attribute
+ //
+ String oldState =
+ (String) mbsc.getAttribute(
+ new ObjectName("MBeans:type=SimpleStandard"),
+ "State");
+ System.out.println("Old State = \"" + oldState + "\"");
+ // Set State attribute
+ //
+ System.out.println("Set State to \"changed state\"");
+ mbsc.setAttribute(new ObjectName("MBeans:type=SimpleStandard"),
+ new Attribute("State", "changed state"));
+ // Get State attribute
+ //
+ String newState =
+ (String) mbsc.getAttribute(
+ new ObjectName("MBeans:type=SimpleStandard"),
+ "State");
+ System.out.println("New State = \"" + newState + "\"");
+ if (!newState.equals("changed state")) {
+ System.out.println("Invalid State = \"" + newState + "\"");
+ System.exit(1);
+ }
+ // Add notification listener on SimpleStandard MBean
+ //
+ System.out.println("Add notification listener...");
+ mbsc.addNotificationListener(
+ new ObjectName("MBeans:type=SimpleStandard"),
+ new NotificationListener() {
+ public void handleNotification(Notification notification,
+ Object handback) {
+ System.out.println("Received notification: " +
+ notification);
+ }
+ },
+ null,
+ null);
+ // Unregister SimpleStandard MBean
+ //
+ System.out.println("Unregister SimpleStandard MBean...");
+ mbsc.unregisterMBean(new ObjectName("MBeans:type=SimpleStandard"));
+ } catch (SecurityException e) {
+ if (testResult.equals("ko")) {
+ System.out.println("Got expected security exception = " + e);
+ } else {
+ System.out.println("Got unexpected security exception = " + e);
+ e.printStackTrace();
+ throw e;
+ }
+ } catch (Exception e) {
+ System.out.println("Unexpected exception caught = " + e);
+ e.printStackTrace();
+ throw e;
+ } finally {
+ // Close connector client
+ //
+ if (jmxc != null)
+ jmxc.close();
+ // Stop connector server
+ //
+ if (jmxcs != null)
+ jmxcs.stop();
+ // Say goodbye
+ //
+ System.out.println("Bye! Bye!");
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/subjectDelegation/jmxremote.password b/test/javax/management/remote/mandatory/subjectDelegation/jmxremote.password
new file mode 100644
index 0000000..b29b668
--- /dev/null
+++ b/test/javax/management/remote/mandatory/subjectDelegation/jmxremote.password
@@ -0,0 +1 @@
+monitorRole QED
diff --git a/test/javax/management/remote/mandatory/subjectDelegation/policy11 b/test/javax/management/remote/mandatory/subjectDelegation/policy11
new file mode 100644
index 0000000..bd5582b
--- /dev/null
+++ b/test/javax/management/remote/mandatory/subjectDelegation/policy11
@@ -0,0 +1,7 @@
+grant codebase "file:/-" {
+ permission javax.management.remote.SubjectDelegationPermission "javax.management.remote.JMXPrincipal.delegate";
+};
+
+grant principal javax.management.remote.JMXPrincipal "monitorRole" {
+ permission javax.management.remote.SubjectDelegationPermission "javax.management.remote.JMXPrincipal.delegate";
+};
diff --git a/test/javax/management/remote/mandatory/subjectDelegation/policy12 b/test/javax/management/remote/mandatory/subjectDelegation/policy12
new file mode 100644
index 0000000..b02f98c
--- /dev/null
+++ b/test/javax/management/remote/mandatory/subjectDelegation/policy12
@@ -0,0 +1,6 @@
+grant codebase "file:/-" {
+ permission javax.management.remote.SubjectDelegationPermission "javax.management.remote.JMXPrincipal.delegate";
+};
+
+grant principal javax.management.remote.JMXPrincipal "monitorRole" {
+};
diff --git a/test/javax/management/remote/mandatory/subjectDelegation/policy13 b/test/javax/management/remote/mandatory/subjectDelegation/policy13
new file mode 100644
index 0000000..3f80b31
--- /dev/null
+++ b/test/javax/management/remote/mandatory/subjectDelegation/policy13
@@ -0,0 +1,6 @@
+grant codebase "file:/-" {
+};
+
+grant principal javax.management.remote.JMXPrincipal "monitorRole" {
+ permission javax.management.remote.SubjectDelegationPermission "javax.management.remote.JMXPrincipal.delegate";
+};
diff --git a/test/javax/management/remote/mandatory/subjectDelegation/policy14 b/test/javax/management/remote/mandatory/subjectDelegation/policy14
new file mode 100644
index 0000000..0d5bd88
--- /dev/null
+++ b/test/javax/management/remote/mandatory/subjectDelegation/policy14
@@ -0,0 +1,5 @@
+grant codebase "file:/-" {
+};
+
+grant principal javax.management.remote.JMXPrincipal "monitorRole" {
+};
diff --git a/test/javax/management/remote/mandatory/subjectDelegation/policy15 b/test/javax/management/remote/mandatory/subjectDelegation/policy15
new file mode 100644
index 0000000..e38b09f
--- /dev/null
+++ b/test/javax/management/remote/mandatory/subjectDelegation/policy15
@@ -0,0 +1,7 @@
+grant codebase "file:/-" {
+ permission javax.management.remote.SubjectDelegationPermission "javax.management.remote.JMXPrincipal.monitorRole";
+};
+
+grant principal javax.management.remote.JMXPrincipal "monitorRole" {
+ permission javax.management.remote.SubjectDelegationPermission "javax.management.remote.JMXPrincipal.delegate";
+};
diff --git a/test/javax/management/remote/mandatory/subjectDelegation/policy16 b/test/javax/management/remote/mandatory/subjectDelegation/policy16
new file mode 100644
index 0000000..51a65ad
--- /dev/null
+++ b/test/javax/management/remote/mandatory/subjectDelegation/policy16
@@ -0,0 +1,6 @@
+grant codebase "file:/-" {
+ permission javax.management.remote.SubjectDelegationPermission "javax.management.remote.JMXPrincipal.monitorRole";
+};
+
+grant principal javax.management.remote.JMXPrincipal "monitorRole" {
+};
diff --git a/test/javax/management/remote/mandatory/subjectDelegation/policy21 b/test/javax/management/remote/mandatory/subjectDelegation/policy21
new file mode 100644
index 0000000..4b83e5f
--- /dev/null
+++ b/test/javax/management/remote/mandatory/subjectDelegation/policy21
@@ -0,0 +1,24 @@
+grant codebase "file:/-" {
+ permission javax.security.auth.AuthPermission "createLoginContext.JMXPluggableAuthenticator";
+ permission java.net.SocketPermission "*:*", "accept,connect,listen,resolve";
+ permission java.security.SecurityPermission "createAccessControlContext";
+ permission javax.management.MBeanPermission "*", "getDomains";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "getAttribute";
+ permission javax.security.auth.AuthPermission "getSubject";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "setAttribute";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "removeNotificationListener";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "unregisterMBean";
+};
+
+grant principal javax.management.remote.JMXPrincipal "monitorRole" {
+ permission javax.management.MBeanPermission "*", "getDomains";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "getAttribute";
+ permission javax.security.auth.AuthPermission "getSubject";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "setAttribute";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "removeNotificationListener";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "unregisterMBean";
+};
diff --git a/test/javax/management/remote/mandatory/subjectDelegation/policy22 b/test/javax/management/remote/mandatory/subjectDelegation/policy22
new file mode 100644
index 0000000..7db4277
--- /dev/null
+++ b/test/javax/management/remote/mandatory/subjectDelegation/policy22
@@ -0,0 +1,24 @@
+grant codebase "file:/-" {
+ permission javax.security.auth.AuthPermission "createLoginContext.JMXPluggableAuthenticator";
+ permission java.net.SocketPermission "*:*", "accept,connect,listen,resolve";
+ permission java.security.SecurityPermission "createAccessControlContext";
+// permission javax.management.MBeanPermission "*", "getDomains";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "getAttribute";
+ permission javax.security.auth.AuthPermission "getSubject";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "setAttribute";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "removeNotificationListener";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "unregisterMBean";
+};
+
+grant principal javax.management.remote.JMXPrincipal "monitorRole" {
+ permission javax.management.MBeanPermission "*", "getDomains";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "getAttribute";
+ permission javax.security.auth.AuthPermission "getSubject";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "setAttribute";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "removeNotificationListener";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "unregisterMBean";
+};
diff --git a/test/javax/management/remote/mandatory/subjectDelegation/policy23 b/test/javax/management/remote/mandatory/subjectDelegation/policy23
new file mode 100644
index 0000000..4a92cb5
--- /dev/null
+++ b/test/javax/management/remote/mandatory/subjectDelegation/policy23
@@ -0,0 +1,24 @@
+grant codebase "file:/-" {
+ permission javax.security.auth.AuthPermission "createLoginContext.JMXPluggableAuthenticator";
+ permission java.net.SocketPermission "*:*", "accept,connect,listen,resolve";
+ permission java.security.SecurityPermission "createAccessControlContext";
+ permission javax.management.MBeanPermission "*", "getDomains";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "getAttribute";
+ permission javax.security.auth.AuthPermission "getSubject";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "setAttribute";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "removeNotificationListener";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "unregisterMBean";
+};
+
+grant principal javax.management.remote.JMXPrincipal "monitorRole" {
+// permission javax.management.MBeanPermission "*", "getDomains";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "getAttribute";
+ permission javax.security.auth.AuthPermission "getSubject";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "setAttribute";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "removeNotificationListener";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "unregisterMBean";
+};
diff --git a/test/javax/management/remote/mandatory/subjectDelegation/policy24 b/test/javax/management/remote/mandatory/subjectDelegation/policy24
new file mode 100644
index 0000000..cbb92df
--- /dev/null
+++ b/test/javax/management/remote/mandatory/subjectDelegation/policy24
@@ -0,0 +1,17 @@
+grant codebase "file:/-" {
+ permission javax.security.auth.AuthPermission "createLoginContext.JMXPluggableAuthenticator";
+ permission java.net.SocketPermission "*:*", "accept,connect,listen,resolve";
+ permission java.security.SecurityPermission "createAccessControlContext";
+ permission javax.management.remote.SubjectDelegationPermission "javax.management.remote.JMXPrincipal.monitorRole";
+};
+
+grant principal javax.management.remote.JMXPrincipal "monitorRole" {
+ permission javax.management.MBeanPermission "*", "getDomains";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "getAttribute";
+ permission javax.security.auth.AuthPermission "getSubject";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "setAttribute";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "removeNotificationListener";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "unregisterMBean";
+};
diff --git a/test/javax/management/remote/mandatory/subjectDelegation/policy25 b/test/javax/management/remote/mandatory/subjectDelegation/policy25
new file mode 100644
index 0000000..98b83de
--- /dev/null
+++ b/test/javax/management/remote/mandatory/subjectDelegation/policy25
@@ -0,0 +1,17 @@
+grant codebase "file:/-" {
+ permission javax.security.auth.AuthPermission "createLoginContext.JMXPluggableAuthenticator";
+ permission java.net.SocketPermission "*:*", "accept,connect,listen,resolve";
+ permission java.security.SecurityPermission "createAccessControlContext";
+ permission javax.management.remote.SubjectDelegationPermission "javax.management.remote.JMXPrincipal.monitorRole";
+};
+
+grant principal javax.management.remote.JMXPrincipal "monitorRole" {
+// permission javax.management.MBeanPermission "*", "getDomains";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "getAttribute";
+ permission javax.security.auth.AuthPermission "getSubject";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "setAttribute";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "removeNotificationListener";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "unregisterMBean";
+};
diff --git a/test/javax/management/remote/mandatory/subjectDelegation/policy31 b/test/javax/management/remote/mandatory/subjectDelegation/policy31
new file mode 100644
index 0000000..70939f5
--- /dev/null
+++ b/test/javax/management/remote/mandatory/subjectDelegation/policy31
@@ -0,0 +1,29 @@
+grant codebase "file:/-" {
+ permission javax.security.auth.AuthPermission "createLoginContext.JMXPluggableAuthenticator";
+ permission java.net.SocketPermission "*:*", "accept,connect,listen,resolve";
+ permission java.security.SecurityPermission "createAccessControlContext";
+ permission javax.management.MBeanPermission "*", "getDomains";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "getAttribute";
+ permission javax.security.auth.AuthPermission "getSubject";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "setAttribute";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "removeNotificationListener";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "unregisterMBean";
+ permission javax.management.remote.SubjectDelegationPermission "javax.management.remote.JMXPrincipal.delegate";
+};
+
+grant principal javax.management.remote.JMXPrincipal "monitorRole" {
+ permission javax.management.remote.SubjectDelegationPermission "javax.management.remote.JMXPrincipal.delegate";
+};
+
+grant principal javax.management.remote.JMXPrincipal "delegate" {
+ permission javax.management.MBeanPermission "*", "getDomains";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "getAttribute";
+ permission javax.security.auth.AuthPermission "getSubject";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "setAttribute";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "removeNotificationListener";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "unregisterMBean";
+};
diff --git a/test/javax/management/remote/mandatory/subjectDelegation/policy32 b/test/javax/management/remote/mandatory/subjectDelegation/policy32
new file mode 100644
index 0000000..3f5354e
--- /dev/null
+++ b/test/javax/management/remote/mandatory/subjectDelegation/policy32
@@ -0,0 +1,29 @@
+grant codebase "file:/-" {
+ permission javax.security.auth.AuthPermission "createLoginContext.JMXPluggableAuthenticator";
+ permission java.net.SocketPermission "*:*", "accept,connect,listen,resolve";
+ permission java.security.SecurityPermission "createAccessControlContext";
+// permission javax.management.MBeanPermission "*", "getDomains";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "getAttribute";
+ permission javax.security.auth.AuthPermission "getSubject";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "setAttribute";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "removeNotificationListener";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "unregisterMBean";
+ permission javax.management.remote.SubjectDelegationPermission "javax.management.remote.JMXPrincipal.delegate";
+};
+
+grant principal javax.management.remote.JMXPrincipal "monitorRole" {
+ permission javax.management.remote.SubjectDelegationPermission "javax.management.remote.JMXPrincipal.delegate";
+};
+
+grant principal javax.management.remote.JMXPrincipal "delegate" {
+ permission javax.management.MBeanPermission "*", "getDomains";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "getAttribute";
+ permission javax.security.auth.AuthPermission "getSubject";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "setAttribute";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "removeNotificationListener";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "unregisterMBean";
+};
diff --git a/test/javax/management/remote/mandatory/subjectDelegation/policy33 b/test/javax/management/remote/mandatory/subjectDelegation/policy33
new file mode 100644
index 0000000..b11df45
--- /dev/null
+++ b/test/javax/management/remote/mandatory/subjectDelegation/policy33
@@ -0,0 +1,29 @@
+grant codebase "file:/-" {
+ permission javax.security.auth.AuthPermission "createLoginContext.JMXPluggableAuthenticator";
+ permission java.net.SocketPermission "*:*", "accept,connect,listen,resolve";
+ permission java.security.SecurityPermission "createAccessControlContext";
+ permission javax.management.MBeanPermission "*", "getDomains";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "getAttribute";
+ permission javax.security.auth.AuthPermission "getSubject";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "setAttribute";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "removeNotificationListener";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "unregisterMBean";
+ permission javax.management.remote.SubjectDelegationPermission "javax.management.remote.JMXPrincipal.delegate";
+};
+
+grant principal javax.management.remote.JMXPrincipal "monitorRole" {
+ permission javax.management.remote.SubjectDelegationPermission "javax.management.remote.JMXPrincipal.delegate";
+};
+
+grant principal javax.management.remote.JMXPrincipal "delegate" {
+// permission javax.management.MBeanPermission "*", "getDomains";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "getAttribute";
+ permission javax.security.auth.AuthPermission "getSubject";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "setAttribute";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "removeNotificationListener";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "unregisterMBean";
+};
diff --git a/test/javax/management/remote/mandatory/subjectDelegation/policy34 b/test/javax/management/remote/mandatory/subjectDelegation/policy34
new file mode 100644
index 0000000..761444e
--- /dev/null
+++ b/test/javax/management/remote/mandatory/subjectDelegation/policy34
@@ -0,0 +1,21 @@
+grant codebase "file:/-" {
+ permission javax.security.auth.AuthPermission "createLoginContext.JMXPluggableAuthenticator";
+ permission java.net.SocketPermission "*:*", "accept,connect,listen,resolve";
+ permission java.security.SecurityPermission "createAccessControlContext";
+ permission javax.management.remote.SubjectDelegationPermission "javax.management.remote.JMXPrincipal.monitorRole";
+};
+
+grant principal javax.management.remote.JMXPrincipal "monitorRole" {
+ permission javax.management.remote.SubjectDelegationPermission "javax.management.remote.JMXPrincipal.delegate";
+};
+
+grant principal javax.management.remote.JMXPrincipal "delegate" {
+ permission javax.management.MBeanPermission "*", "getDomains";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "getAttribute";
+ permission javax.security.auth.AuthPermission "getSubject";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "setAttribute";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "removeNotificationListener";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "unregisterMBean";
+};
diff --git a/test/javax/management/remote/mandatory/subjectDelegation/policy35 b/test/javax/management/remote/mandatory/subjectDelegation/policy35
new file mode 100644
index 0000000..5aebb6b
--- /dev/null
+++ b/test/javax/management/remote/mandatory/subjectDelegation/policy35
@@ -0,0 +1,21 @@
+grant codebase "file:/-" {
+ permission javax.security.auth.AuthPermission "createLoginContext.JMXPluggableAuthenticator";
+ permission java.net.SocketPermission "*:*", "accept,connect,listen,resolve";
+ permission java.security.SecurityPermission "createAccessControlContext";
+ permission javax.management.remote.SubjectDelegationPermission "javax.management.remote.JMXPrincipal.monitorRole";
+};
+
+grant principal javax.management.remote.JMXPrincipal "monitorRole" {
+ permission javax.management.remote.SubjectDelegationPermission "javax.management.remote.JMXPrincipal.delegate";
+};
+
+grant principal javax.management.remote.JMXPrincipal "delegate" {
+// permission javax.management.MBeanPermission "*", "getDomains";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "getAttribute";
+ permission javax.security.auth.AuthPermission "getSubject";
+ permission javax.management.MBeanPermission "SimpleStandard#State[MBeans:type=SimpleStandard]", "setAttribute";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "addNotificationListener";
+ permission javax.management.MBeanPermission "javax.management.MBeanServerDelegate#-[JMImplementation:type=MBeanServerDelegate]", "removeNotificationListener";
+ permission javax.management.MBeanPermission "SimpleStandard#-[MBeans:type=SimpleStandard]", "unregisterMBean";
+};
diff --git a/test/javax/management/remote/mandatory/threads/ExecutorTest.java b/test/javax/management/remote/mandatory/threads/ExecutorTest.java
new file mode 100644
index 0000000..00dcc3a
--- /dev/null
+++ b/test/javax/management/remote/mandatory/threads/ExecutorTest.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright 2004-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6190873
+ * @summary Tests that thread creation can use a user-supplied Executor
+ * @author Eamonn McManus
+ * @run clean ExecutorTest
+ * @run build ExecutorTest
+ * @run main ExecutorTest
+ */
+
+import java.lang.reflect.*;
+import java.net.MalformedURLException;
+
+import java.util.*;
+import java.util.concurrent.*;
+
+import javax.management.*;
+import javax.management.remote.*;
+
+/*
+ When you create a JMXConnector client, you can supply a
+ "fetch-notifications Executor", which is a
+ java.util.concurrent.Executor that will be used each time the
+ connector client wants to call RMIConnection.fetchNotifications.
+ This is a hook that allows users to make that potentially-blocking
+ call from within a thread pool or the like. If you have very many
+ connections, you can potentially share the work of
+ fetchNotifications calls among a number of threads that is less than
+ the number of connections, decreasing thread usage at the expense of
+ increased latency.
+
+ This test checks that the environment property does in fact work.
+ It creates a connection without that property and ensures that
+ notification sending does in fact work (with the default Executor).
+ Then it creates a connection with the property set to an Executor
+ that records how many times its execute method is invoked.
+ Notifications are sent one by one and each time the test waits for
+ the notification to be received. This implies that
+ fetchNotifications will be executed at least as many times as there
+ are notifications. Since each fetchNotifications call is supposed
+ to happen as an Executor.execute call, if Executor.execute has been
+ called fewer times then there were notifications, we know that the
+ Executor is not being used correctly.
+ */
+public class ExecutorTest {
+ private static final String EXECUTOR_PROPERTY =
+ "jmx.remote.x.fetch.notifications.executor";
+ private static final String NOTIF_TYPE = "test.type";
+
+ public static void main(String[] args) throws Exception {
+ String lastfail = null;
+ for (String proto : new String[] {"rmi", "iiop", "jmxmp"}) {
+ JMXServiceURL url = new JMXServiceURL(proto, null, 0);
+ JMXConnectorServer cs;
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ try {
+ // Create server just to see if the protocol is supported
+ cs = JMXConnectorServerFactory.newJMXConnectorServer(url,
+ null,
+ mbs);
+ } catch (MalformedURLException e) {
+ System.out.println();
+ System.out.println("Ignoring protocol: " + proto);
+ continue;
+ }
+ String fail;
+ try {
+ fail = test(proto);
+ if (fail != null)
+ System.out.println("TEST FAILED: " + fail);
+ } catch (Exception e) {
+ e.printStackTrace(System.out);
+ fail = e.toString();
+ }
+ if (lastfail == null)
+ lastfail = fail;
+ }
+ if (lastfail == null)
+ return;
+ System.out.println();
+ System.out.println("TEST FAILED");
+ throw new Exception("Test failed: " + lastfail);
+ }
+
+ private static enum TestType {NO_EXECUTOR, NULL_EXECUTOR, COUNT_EXECUTOR};
+
+ private static String test(String proto) throws Exception {
+ System.out.println();
+ System.out.println("TEST: " + proto);
+ ClassLoader myClassLoader =
+ CountInvocationHandler.class.getClassLoader();
+ ExecutorService wrappedExecutor = Executors.newCachedThreadPool();
+ CountInvocationHandler executorHandler =
+ new CountInvocationHandler(wrappedExecutor);
+ Executor countExecutor = (Executor)
+ Proxy.newProxyInstance(myClassLoader,
+ new Class<?>[] {Executor.class},
+ executorHandler);
+
+ JMXServiceURL url = new JMXServiceURL(proto, null, 0);
+
+ for (TestType test : TestType.values()) {
+ Map<String, Executor> env = new HashMap<String, Executor>();
+ switch (test) {
+ case NO_EXECUTOR:
+ System.out.println("Test with no executor in env");
+ break;
+ case NULL_EXECUTOR:
+ System.out.println("Test with null executor in env");
+ env.put(EXECUTOR_PROPERTY, null);
+ break;
+ case COUNT_EXECUTOR:
+ System.out.println("Test with non-null executor in env");
+ env.put(EXECUTOR_PROPERTY, countExecutor);
+ break;
+ }
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ ObjectName emitName = new ObjectName("blah:type=Emitter");
+ mbs.registerMBean(new Emitter(), emitName);
+ JMXConnectorServer cs =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
+ cs.start();
+ JMXServiceURL addr = cs.getAddress();
+ JMXConnector cc = JMXConnectorFactory.connect(addr, env);
+ MBeanServerConnection mbsc = cc.getMBeanServerConnection();
+ EmitterMBean emitter = (EmitterMBean)
+ MBeanServerInvocationHandler.newProxyInstance(mbsc,
+ emitName,
+ EmitterMBean.class,
+ false);
+ SemaphoreListener listener = new SemaphoreListener();
+ NotificationFilterSupport filter = new NotificationFilterSupport();
+ filter.enableType(NOTIF_TYPE);
+ mbsc.addNotificationListener(emitName, listener, filter, null);
+ final int NOTIF_COUNT = 10;
+ for (int i = 0; i < NOTIF_COUNT; i++) {
+ emitter.emit();
+ listener.await();
+ }
+ Thread.sleep(1);
+ listener.checkUnavailable();
+ System.out.println("Got notifications");
+ cc.close();
+ cs.stop();
+ if (test == TestType.COUNT_EXECUTOR) {
+ Method m = Executor.class.getMethod("execute", Runnable.class);
+ Integer count = executorHandler.methodCount.get(m);
+ if (count == null || count < NOTIF_COUNT)
+ return "Incorrect method count for execute: " + count;
+ System.out.println("Executor was called enough times");
+ }
+ }
+
+ wrappedExecutor.shutdown();
+ return null;
+ }
+
+ /* Simple MBean that sends a notification every time we ask it to. */
+ public static interface EmitterMBean {
+ public void emit();
+ }
+
+ public static class Emitter
+ extends NotificationBroadcasterSupport implements EmitterMBean {
+ public void emit() {
+ sendNotification(new Notification(NOTIF_TYPE, this, seq++));
+ }
+
+ private long seq = 1;
+ }
+
+ /* Simple NotificationListener that allows you to wait until a
+ notification has been received. Since it uses a semaphore, you
+ can wait either before or after the notification has in fact
+ been received and it will work in either case. */
+ private static class SemaphoreListener implements NotificationListener {
+ void await() throws InterruptedException {
+ semaphore.acquire();
+ }
+
+ /* Ensure no extra notifications were received. If we can acquire
+ the semaphore, that means its release() method was called more
+ times than its acquire() method, which means there were too
+ many notifications. */
+ void checkUnavailable() throws Exception {
+ if (semaphore.tryAcquire())
+ throw new Exception("Got extra notifications!");
+ }
+
+ public void handleNotification(Notification n, Object h) {
+ semaphore.release();
+ }
+
+ private final Semaphore semaphore = new Semaphore(0);
+ }
+
+ /* Generic InvocationHandler that forwards all methods to a wrapped
+ object, but counts for each method how many times it was invoked. */
+ private static class CountInvocationHandler implements InvocationHandler {
+ final Map<Method, Integer> methodCount =
+ new HashMap<Method, Integer>();
+ private final Object wrapped;
+
+ public CountInvocationHandler(Object wrapped) {
+ this.wrapped = wrapped;
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args)
+ throws Throwable {
+ synchronized (methodCount) {
+ Integer count = methodCount.get(method);
+ if (count == null)
+ count = 0;
+ methodCount.put(method, count + 1);
+ }
+ return method.invoke(wrapped, (Object[]) args);
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/threads/NoServerTimeoutTest.java b/test/javax/management/remote/mandatory/threads/NoServerTimeoutTest.java
new file mode 100644
index 0000000..6f617bb
--- /dev/null
+++ b/test/javax/management/remote/mandatory/threads/NoServerTimeoutTest.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6192124
+ * @summary Tests that you can turn off the server connection timeout thread
+ * @author Eamonn McManus
+ * @run clean NoServerTimeoutTest
+ * @run build NoServerTimeoutTest
+ * @run main NoServerTimeoutTest
+ */
+
+import java.lang.management.*;
+import java.net.MalformedURLException;
+import java.util.*;
+import javax.management.*;
+import javax.management.remote.*;
+
+public class NoServerTimeoutTest {
+ public static void main(String[] args) throws Exception {
+ boolean ok = true;
+
+ for (String proto : new String[] {"rmi", "iiop", "jmxmp"}) {
+ JMXServiceURL url = new JMXServiceURL(proto, null, 0);
+ try {
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ // Create server just to see if the protocol is supported
+ JMXConnectorServerFactory.newJMXConnectorServer(url,
+ null,
+ mbs);
+ } catch (MalformedURLException e) {
+ System.out.println();
+ System.out.println("Ignoring protocol: " + proto);
+ continue;
+ }
+ try {
+ ok &= test(url);
+ } catch (Exception e) {
+ System.out.println("TEST FAILED WITH EXCEPTION:");
+ e.printStackTrace();
+ ok = false;
+ }
+ }
+
+ System.out.println();
+ if (ok)
+ System.out.println("Test passed");
+ else
+ throw new Exception("Test failed");
+ }
+
+ private static enum Test {
+ NO_ENV("No Map for connector server"),
+ EMPTY_ENV("Empty Map for connector server"),
+ PLAIN_TIMEOUT("Map with two-minute timeout as int"),
+ PLAIN_STRING_TIMEOUT("Map with two-minute timeout as string"),
+ INFINITE_TIMEOUT("Map with Long.MAX_VALUE timeout as long"),
+ INFINITE_STRING_TIMEOUT("Map with Long.MAX_VALUE timeout as string");
+
+ Test(String description) {
+ this.description = description;
+ }
+
+ public String toString() {
+ return description;
+ }
+
+ private final String description;
+ }
+ // define which tests should see a timeout thread
+ private static final Set<Test> expectThread =
+ EnumSet.copyOf(Arrays.asList(Test.NO_ENV,
+ Test.EMPTY_ENV,
+ Test.PLAIN_TIMEOUT,
+ Test.PLAIN_STRING_TIMEOUT));
+
+ private static boolean test(JMXServiceURL url) throws Exception {
+ System.out.println();
+ System.out.println("Test: " + url);
+
+ boolean ok = true;
+
+ for (Test test : Test.values())
+ ok &= test(url, test);
+
+ return ok;
+ }
+
+ private static final String TIMEOUT =
+ "jmx.remote.x.server.connection.timeout";
+
+ private static boolean test(JMXServiceURL url, Test test)
+ throws Exception {
+
+ System.out.println("* " + test);
+
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ Map<String, Object> env = new HashMap<String, Object>();
+ switch (test) {
+ case NO_ENV: env = null; break;
+ case EMPTY_ENV: break;
+ case PLAIN_TIMEOUT: env.put(TIMEOUT, 120 * 1000L); break;
+ case PLAIN_STRING_TIMEOUT: env.put(TIMEOUT, (120 * 1000L) + ""); break;
+ case INFINITE_TIMEOUT: env.put(TIMEOUT, Long.MAX_VALUE); break;
+ case INFINITE_STRING_TIMEOUT: env.put(TIMEOUT, "" + Long.MAX_VALUE);
+ break;
+ default: throw new AssertionError();
+ }
+
+ // In case there's a timeout thread left over from a previous run
+ for (int i = 0; i < 10 && countTimeoutThreads() > 0; i++)
+ Thread.sleep(500);
+ if (countTimeoutThreads() > 0) {
+ System.out.println("TIMEOUT THREAD(S) WOULD NOT GO AWAY");
+ return false;
+ }
+
+ JMXConnectorServer cs =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
+ cs.start();
+ JMXServiceURL addr = cs.getAddress();
+ JMXConnector cc = JMXConnectorFactory.connect(addr);
+ MBeanServerConnection mbsc = cc.getMBeanServerConnection();
+ mbsc.getDefaultDomain();
+ int expectTimeoutThreads = expectThread.contains(test) ? 1 : 0;
+ int timeoutThreads = countTimeoutThreads();
+ boolean ok = (expectTimeoutThreads == timeoutThreads);
+ if (!ok) {
+ System.out.println("TEST FAILS: Expected timeout threads: " +
+ expectTimeoutThreads +
+ "; actual timeout threads: " + timeoutThreads);
+ ok = false;
+ }
+ cc.close();
+ cs.stop();
+ return ok;
+ }
+
+ private static int countTimeoutThreads() {
+ ThreadMXBean mb = ManagementFactory.getThreadMXBean();
+ int count = 0;
+ long[] ids = mb.getAllThreadIds();
+ for (ThreadInfo ti : mb.getThreadInfo(ids)) {
+ if (ti != null &&
+ ti.getThreadName().startsWith("JMX server connection timeout"))
+ count++;
+ }
+ return count;
+ }
+}
diff --git a/test/javax/management/remote/mandatory/util/CacheMapTest.java b/test/javax/management/remote/mandatory/util/CacheMapTest.java
new file mode 100644
index 0000000..a1369af
--- /dev/null
+++ b/test/javax/management/remote/mandatory/util/CacheMapTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 7654321
+ * @summary Tests the CacheMap class.
+ * @author Eamonn McManus
+ * @run clean CacheMapTest
+ * @run build CacheMapTest
+ * @run main CacheMapTest
+ */
+
+import java.util.Iterator;
+import java.util.Map;
+
+import com.sun.jmx.remote.util.CacheMap;
+
+public class CacheMapTest {
+ public static void main(String[] args) {
+ try {
+ boolean ok = test(5) && test(100);
+ if (ok) {
+ System.out.println("Test completed");
+ return;
+ } else {
+ System.out.println("Test failed!");
+ System.exit(1);
+ }
+ } catch (Exception e) {
+ System.err.println("Unexpected exception: " + e);
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static boolean test(int cacheSize) throws Exception {
+ System.out.println("CacheMap test with cache size " + cacheSize);
+ CacheMap map = new CacheMap(cacheSize);
+ int size = 0;
+ int maxIterations = cacheSize * 10;
+ while (map.size() == size && size < maxIterations) {
+ Integer key = new Integer(size);
+ Object x = map.put(key, "x");
+ if (x != null) {
+ System.out.println("Map already had entry " + key + "!");
+ return false;
+ }
+ x = map.get(key);
+ if (!"x".equals(x)) {
+ System.out.println("Got back surprising value: " + x);
+ return false;
+ }
+ size++;
+ }
+ System.out.println("Map size is " + map.size() + " after inserting " +
+ size + " elements");
+ do {
+ System.gc();
+ Thread.sleep(1);
+ System.out.println("Map size is " + map.size() + " after GC");
+ } while (map.size() > cacheSize);
+ if (map.size() < cacheSize) {
+ System.out.println("Map shrank to less than cache size: " +
+ map.size() + " (surprising but not wrong)");
+ } else
+ System.out.println("Map shrank to cache size as expected");
+ int lowest = size - cacheSize;
+ // lowest value that can still be in cache if LRU is respected
+ for (Iterator it = map.entrySet().iterator(); it.hasNext(); ) {
+ Map.Entry entry = (Map.Entry) it.next();
+ Integer x = (Integer) entry.getKey();
+ int xx = x.intValue();
+ if (xx < lowest || xx >= size) {
+ System.out.println("Old value remained (" + x + "), " +
+ "expected none earlier than " + lowest);
+ return false;
+ }
+ Object xxx = entry.getValue();
+ if (!"x".equals(xxx)) {
+ System.out.println("Got back surprising value: " + xxx);
+ return false;
+ }
+ }
+ if (map.size() > 0)
+ System.out.println("Remaining elements are the most recent ones");
+ System.out.println("Test passed");
+ return true;
+ }
+}
diff --git a/test/javax/management/remote/mandatory/util/MapNullValuesTest.java b/test/javax/management/remote/mandatory/util/MapNullValuesTest.java
new file mode 100644
index 0000000..8dc7eb7
--- /dev/null
+++ b/test/javax/management/remote/mandatory/util/MapNullValuesTest.java
@@ -0,0 +1,398 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4982668
+ * @summary Test that a map containing 'null' values is handled
+ * properly when converting the map into a hashtable,
+ * i.e. all 'null' values should be removed before creating
+ * the hashtable in order to avoid a NullPointerException.
+ * Check also that null values for keys are not allowed in
+ * the maps passed to the JMXConnector[Server] factories.
+ * @author Luis-Miguel Alventosa
+ * @run clean MapNullValuesTest
+ * @run build MapNullValuesTest
+ * @run main MapNullValuesTest
+ */
+
+import java.rmi.RemoteException;
+import java.rmi.registry.Registry;
+import java.rmi.registry.LocateRegistry;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+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 com.sun.jmx.remote.util.EnvHelp;
+
+public class MapNullValuesTest {
+
+ private static int port;
+ private Map map0;
+ private Map map1;
+ private Map map2;
+ private Map map3;
+ private Map maps[];
+
+ public MapNullValuesTest() {
+ // Map 0
+ //
+ map0 = new HashMap();
+
+ // Map 1
+ //
+ map1 = new HashMap();
+ map1.put("key1", "value1");
+ map1.put("key2", "value2");
+ map1.put("key3", "value3");
+
+ // Map 2
+ //
+ map2 = new HashMap();
+ map2.put("key1", "value1");
+ map2.put("key2", null);
+ map2.put("key3", "value3");
+ map2.put("key4", null);
+ map2.put("key5", "value5");
+
+ // Map 3
+ //
+ map3 = new HashMap();
+ map3.put("key1", "value1");
+ map3.put(null, "value2");
+ map3.put("key3", "value3");
+
+ // Map Array
+ //
+ maps = new Map[] { map0, map1, map2, map3 };
+ }
+
+ private void checkContents(Map m, Hashtable t)
+ throws IllegalArgumentException {
+ int size = m.size();
+ Set s = m.entrySet();
+ for (Iterator i = s.iterator(); i.hasNext(); ) {
+ Map.Entry e = (Map.Entry) i.next();
+ Object key = e.getKey();
+ Object value = e.getValue();
+ if (key == null || value == null) { // Null value
+ size--;
+ } else { // Check for equality
+ if (t.get(key) == null)
+ throw new IllegalArgumentException("Unknown key!");
+ else if (!t.get(key).equals(value))
+ throw new IllegalArgumentException("Value mismatch!");
+ }
+ }
+ if (t.size() != size)
+ throw new IllegalArgumentException("Size mismatch!");
+ }
+
+ private int mapToHashtableTests() {
+ int errorCount = 0;
+ echo("");
+ echo(dashedMessage("Run MapToHashtable Tests"));
+ for (int i = 0; i < maps.length; i++) {
+ echo("\n>>> MapToHashtable Test [" + i + "]");
+ try {
+ echo("\tMap = " + maps[i]);
+ Hashtable t = EnvHelp.mapToHashtable(maps[i]);
+ echo("\tHashtable = " + t);
+ checkContents(maps[i], t);
+ echo("\tTest [" + i + "] PASSED!");
+ } catch (Exception e) {
+ errorCount++;
+ echo("\tTest [" + i + "] FAILED!");
+ e.printStackTrace(System.out);
+ }
+ }
+ if (errorCount == 0) {
+ echo("");
+ echo(dashedMessage("MapToHashtable Tests PASSED!"));
+ } else {
+ echo("");
+ echo(dashedMessage("MapToHashtable Tests FAILED!"));
+ }
+ return errorCount;
+ }
+
+ private int jmxConnectorServerFactoryTests() {
+ int errorCount = 0;
+ echo("");
+ echo(dashedMessage("Run JMXConnectorServerFactory Tests"));
+ for (int i = 0; i < maps.length - 1; i++) {
+ echo("\n>>> JMXConnectorServerFactory Test [" + i + "]");
+ try {
+ echo("\tMap = " + maps[i]);
+ echo("\tCreate the MBean server");
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ echo("\tCreate the RMI connector server");
+ JMXServiceURL url =
+ new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:" +
+ port + "/JMXConnectorServerFactory" + i);
+ JMXConnectorServer jmxcs =
+ JMXConnectorServerFactory.newJMXConnectorServer(url,
+ maps[i],
+ mbs);
+ echo("\tStart the RMI connector server");
+ jmxcs.start();
+ echo("\tCall RMIConnectorServer.toJMXConnector(Map)");
+ jmxcs.toJMXConnector(maps[i]);
+ echo("\tStop the RMI connector server");
+ jmxcs.stop();
+ echo("\tTest [" + i + "] PASSED!");
+ } catch (Exception e) {
+ errorCount++;
+ echo("\tTest [" + i + "] FAILED!");
+ e.printStackTrace(System.out);
+ }
+ }
+ if (errorCount == 0) {
+ echo("");
+ echo(dashedMessage("JMXConnectorServerFactory Tests PASSED!"));
+ } else {
+ echo("");
+ echo(dashedMessage("JMXConnectorServerFactory Tests FAILED!"));
+ }
+ return errorCount;
+ }
+
+ private int jmxConnectorFactoryTests() {
+ int errorCount = 0;
+ echo("");
+ echo(dashedMessage("Run JMXConnectorFactory Tests"));
+ for (int i = 0; i < maps.length - 1; i++) {
+ echo("\n>>> JMXConnectorFactory Test [" + i + "]");
+ try {
+ echo("\tMap = " + maps[i]);
+ echo("\tCreate the MBean server");
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ echo("\tCreate the RMI connector server");
+ JMXServiceURL url =
+ new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:" +
+ port + "/JMXConnectorFactory" + i);
+ JMXConnectorServer jmxcs =
+ JMXConnectorServerFactory.newJMXConnectorServer(url,
+ null,
+ mbs);
+ echo("\tStart the RMI connector server");
+ jmxcs.start();
+ echo("\tCreate and connect the RMI connector");
+ JMXConnector jmxc =
+ JMXConnectorFactory.connect(jmxcs.getAddress(), maps[i]);
+ echo("\tClose the RMI connector");
+ jmxc.close();
+ echo("\tTest [" + i + "] PASSED!");
+ } catch (Exception e) {
+ errorCount++;
+ echo("\tTest [" + i + "] FAILED!");
+ e.printStackTrace(System.out);
+ }
+ }
+ if (errorCount == 0) {
+ echo("");
+ echo(dashedMessage("JMXConnectorFactory Tests PASSED!"));
+ } else {
+ echo("");
+ echo(dashedMessage("JMXConnectorFactory Tests FAILED!"));
+ }
+ return errorCount;
+ }
+
+ private int nullKeyFactoryTests() {
+ int errorCount = 0;
+ echo("");
+ echo(dashedMessage("Run Null Key Factory Tests"));
+ echo("\tMap = " + map3);
+ try {
+ String urlStr =
+ "service:jmx:rmi:///jndi/rmi://:" + port + "/NullKeyFactory";
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ JMXServiceURL url = null;
+ JMXConnectorServer jmxcs = null;
+ JMXConnector jmxc = null;
+
+ echo("\tJMXConnectorServerFactory.newJMXConnectorServer()");
+ try {
+ url = new JMXServiceURL(urlStr + "1");
+ jmxcs = JMXConnectorServerFactory.newJMXConnectorServer(url,
+ map3,
+ mbs);
+ errorCount++;
+ echo("\tTest FAILED!");
+ } catch (Exception e) {
+ echo("\tException Message: " + e.getMessage());
+ echo("\tTest PASSED!");
+ }
+
+ echo("\tJMXConnectorServerFactory.toJMXConnector()");
+ try {
+ url = new JMXServiceURL(urlStr + "2");
+ jmxcs = JMXConnectorServerFactory.newJMXConnectorServer(url,
+ null,
+ mbs);
+ jmxcs.start();
+ jmxcs.toJMXConnector(map3);
+ errorCount++;
+ echo("\tTest FAILED!");
+ } catch (Exception e) {
+ echo("\tException Message: " + e.getMessage());
+ echo("\tTest PASSED!");
+ } finally {
+ jmxcs.stop();
+ }
+
+ echo("\tJMXConnectorFactory.newJMXConnector()");
+ try {
+ url = new JMXServiceURL(urlStr + "3");
+ jmxcs = JMXConnectorServerFactory.newJMXConnectorServer(url,
+ null,
+ mbs);
+ jmxcs.start();
+ jmxc = JMXConnectorFactory.newJMXConnector(jmxcs.getAddress(),
+ map3);
+ errorCount++;
+ echo("\tTest FAILED!");
+ } catch (Exception e) {
+ echo("\tException Message: " + e.getMessage());
+ echo("\tTest PASSED!");
+ } finally {
+ jmxcs.stop();
+ }
+
+ echo("\tJMXConnectorFactory.connect()");
+ try {
+ url = new JMXServiceURL(urlStr + "4");
+ jmxcs = JMXConnectorServerFactory.newJMXConnectorServer(url,
+ null,
+ mbs);
+ jmxcs.start();
+ jmxc = JMXConnectorFactory.connect(jmxcs.getAddress(), map3);
+ errorCount++;
+ echo("\tTest FAILED!");
+ } catch (Exception e) {
+ echo("\tException Message: " + e.getMessage());
+ echo("\tTest PASSED!");
+ } finally {
+ jmxcs.stop();
+ }
+
+ echo("\tJMXConnector.connect()");
+ try {
+ url = new JMXServiceURL(urlStr + "5");
+ jmxcs = JMXConnectorServerFactory.newJMXConnectorServer(url,
+ null,
+ mbs);
+ jmxcs.start();
+ jmxc = JMXConnectorFactory.newJMXConnector(jmxcs.getAddress(),
+ null);
+ jmxc.connect(map3);
+ errorCount++;
+ echo("\tTest FAILED!");
+ } catch (Exception e) {
+ echo("\tException Message: " + e.getMessage());
+ echo("\tTest PASSED!");
+ } finally {
+ jmxcs.stop();
+ }
+
+ } catch (Exception e) {
+ echo("\tGot unexpected exception!");
+ e.printStackTrace(System.out);
+ errorCount = 1;
+ }
+
+ if (errorCount == 0) {
+ echo("");
+ echo(dashedMessage("Null Key Factory Tests PASSED!"));
+ } else {
+ echo("");
+ echo(dashedMessage("Null Key Factory Tests FAILED!"));
+ }
+ return errorCount;
+ }
+
+ private static String dashedMessage(String message) {
+ final int MAX_LINE = 80;
+ StringBuffer sb = new StringBuffer(message);
+ sb.append(" ");
+ for (int i = MAX_LINE; i > message.length() + 1; i--)
+ sb.append("-");
+ return sb.toString();
+ }
+
+ private static void echo(String message) {
+ System.out.println(message);
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ int errorCount = 0;
+
+ MapNullValuesTest test = new MapNullValuesTest();
+
+ // Create an RMI registry
+ //
+ echo("");
+ echo(dashedMessage("Start RMI registry"));
+ Registry reg = null;
+ port = 7500;
+ while (port++ < 7550) {
+ try {
+ reg = LocateRegistry.createRegistry(port);
+ echo("\nRMI registry running on port " + port);
+ break;
+ } catch (RemoteException e) {
+ // Failed to create RMI registry...
+ //
+ echo("\nFailed to create RMI registry on port " + port);
+ e.printStackTrace(System.out);
+ }
+ }
+ if (reg == null) {
+ System.exit(1);
+ }
+
+ // Run tests
+ //
+ errorCount += test.mapToHashtableTests();
+ errorCount += test.jmxConnectorServerFactoryTests();
+ errorCount += test.jmxConnectorFactoryTests();
+ errorCount += test.nullKeyFactoryTests();
+
+ if (errorCount == 0) {
+ echo("\nNull values for key/value pairs in Map Tests PASSED!");
+ } else {
+ echo("\nNull values for key/value pairs in Map Tests FAILED!");
+ System.exit(1);
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/version/ImplVersionCommand.java b/test/javax/management/remote/mandatory/version/ImplVersionCommand.java
new file mode 100644
index 0000000..b74dcf0
--- /dev/null
+++ b/test/javax/management/remote/mandatory/version/ImplVersionCommand.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ */
+
+import javax.management.remote.rmi.RMIJRMPServerImpl;
+import javax.management.remote.rmi.RMIServer;
+
+public class ImplVersionCommand {
+
+ public static void main(String[] args) throws Exception {
+
+ // Create RMIJRMPServerImpl
+ //
+ System.out.println("Create RMIJRMPServerImpl");
+ RMIServer server = new RMIJRMPServerImpl(0, null, null, null);
+
+ // Get the JMX Remote impl version from RMIServer
+ //
+ System.out.println("Get JMX Remote implementation version from RMIServer");
+ String full_version = server.getVersion();
+ System.out.println("RMIServer.getVersion() = "+ full_version);
+ String impl_version = full_version.substring(
+ full_version.indexOf("java_runtime_")+"java_runtime_".length());
+
+ // Display JMX Remote impl version and Java Runtime version
+ //
+ System.out.println("JMX Remote implementation version = " +
+ impl_version);
+ System.out.println("Java Runtime implementation version = " +
+ args[0]);
+
+ // Check JMX Remote impl version vs. Java Runtime version
+ //
+ if (!impl_version.equals(args[0])) {
+ // Test FAILED
+ throw new IllegalArgumentException(
+ "***FAILED: JMX Remote and Java Runtime versions do NOT match***");
+ }
+ // Test OK!
+ System.out.println("JMX Remote and Java Runtime versions match.");
+ System.out.println("Bye! Bye!");
+ }
+}
diff --git a/test/javax/management/remote/mandatory/version/ImplVersionReader.java b/test/javax/management/remote/mandatory/version/ImplVersionReader.java
new file mode 100644
index 0000000..8a70670
--- /dev/null
+++ b/test/javax/management/remote/mandatory/version/ImplVersionReader.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ */
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+
+public class ImplVersionReader extends Thread {
+
+ private BufferedReader in;
+ private Process proc;
+
+ public ImplVersionReader(Process p, InputStream is) {
+ proc = p;
+ in = new BufferedReader(new InputStreamReader(is));
+ }
+
+ public void run() {
+ boolean terminate = false;
+ while (!terminate) {
+ try {
+ String trace = in.readLine();
+ if (trace != null) {
+ System.out.println("ImplVersionCommand: " + trace);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ try {
+ proc.exitValue();
+ terminate = true;
+ } catch (IllegalThreadStateException e) {
+ terminate = false;
+ }
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/version/ImplVersionTest.java b/test/javax/management/remote/mandatory/version/ImplVersionTest.java
new file mode 100644
index 0000000..770c4ce
--- /dev/null
+++ b/test/javax/management/remote/mandatory/version/ImplVersionTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2004-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5046815
+ * @summary Test that RMIServer.getVersion() reflects the JDK version when
+ * JMX is bundled into the Java platform and the application is run with a
+ * security manager and the test codebase has the java permission to read
+ * the "java.runtime.version" system property.
+ * @author Luis-Miguel Alventosa, Joel Feraud
+ * @run clean ImplVersionTest ImplVersionCommand
+ * @run build ImplVersionTest ImplVersionCommand ImplVersionReader
+ * @run main ImplVersionTest
+ */
+
+import java.io.File;
+import java.security.CodeSource;
+import javax.management.MBeanServer;
+
+public class ImplVersionTest {
+
+ public static void main(String[] args) {
+ try {
+ // Get OS name
+ //
+ String osName = System.getProperty("os.name");
+ System.out.println("osName = " + osName);
+ if ("Windows 98".equals(osName)) {
+ // Disable this test on Win98 due to parsing
+ // errors (bad handling of white spaces) when
+ // J2SE is installed under "Program Files".
+ //
+ System.out.println("This test is disabled on Windows 98.");
+ System.out.println("Bye! Bye!");
+ return;
+ }
+
+ // Get Java Home
+ String javaHome = System.getProperty("java.home");
+
+ // Get test src
+ //
+ String testSrc = System.getProperty("test.src");
+
+ // Get test classes
+ String testClasses = System.getProperty("test.classes");
+
+ // Get boot class path
+ String bootClassPath = System.getProperty("sun.boot.class.path");
+
+ // Build command string
+ String command =
+ javaHome + File.separator + "bin" + File.separator + "java " +
+ " -Xbootclasspath/p:" + bootClassPath +
+ " -classpath " + testClasses +
+ " -Djava.security.manager -Djava.security.policy==" + testSrc +
+ File.separator + "policy -Dtest.classes=" + testClasses +
+ " ImplVersionCommand " + System.getProperty("java.runtime.version");
+ System.out.println("ImplVersionCommand Exec Command = " + command);
+
+ // Exec command
+ Process proc = Runtime.getRuntime().exec(command);
+ new ImplVersionReader(proc, proc.getInputStream()).start();
+ new ImplVersionReader(proc, proc.getErrorStream()).start();
+ int exitValue = proc.waitFor();
+
+ System.out.println("ImplVersionCommand Exit Value = " +
+ exitValue);
+ if (exitValue != 0) {
+ System.out.println("TEST FAILED: Incorrect exit value " +
+ "from ImplVersionCommand");
+ System.exit(exitValue);
+ }
+ // Test OK!
+ System.out.println("Bye! Bye!");
+ } catch (Exception e) {
+ System.out.println("Unexpected exception caught = " + e);
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+}
diff --git a/test/javax/management/remote/mandatory/version/policy b/test/javax/management/remote/mandatory/version/policy
new file mode 100644
index 0000000..8b99224
--- /dev/null
+++ b/test/javax/management/remote/mandatory/version/policy
@@ -0,0 +1,3 @@
+grant codebase "file:${test.classes}" {
+ permission java.util.PropertyPermission "java.runtime.version", "read";
+};
diff --git a/test/javax/management/security/AvoidGetMBeanInfoCallsTest.java b/test/javax/management/security/AvoidGetMBeanInfoCallsTest.java
new file mode 100644
index 0000000..237a636
--- /dev/null
+++ b/test/javax/management/security/AvoidGetMBeanInfoCallsTest.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6331783
+ * @summary Test that MBeanServer.queryNames doesn't call getMBeanInfo on every
+ * resultant MBean when there is no security manager installed.
+ * @author Luis-Miguel Alventosa
+ * @run clean AvoidGetMBeanInfoCallsTest
+ * @run build AvoidGetMBeanInfoCallsTest
+ * @run main AvoidGetMBeanInfoCallsTest
+ */
+
+import java.util.Set;
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.DynamicMBean;
+import javax.management.InvalidAttributeValueException;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+
+public class AvoidGetMBeanInfoCallsTest {
+
+ /**
+ * Test DynamicMBean class
+ */
+ public static class Test implements DynamicMBean {
+
+ public Object getAttribute(String attribute)
+ throws AttributeNotFoundException,
+ MBeanException,
+ ReflectionException {
+ return null;
+ }
+
+ public void setAttribute(Attribute attribute)
+ throws AttributeNotFoundException,
+ InvalidAttributeValueException,
+ MBeanException,
+ ReflectionException {
+ }
+
+ public AttributeList getAttributes(String[] attributes) {
+ return null;
+ }
+
+ public AttributeList setAttributes(AttributeList attributes) {
+ return null;
+ }
+
+ public Object invoke(String actionName,
+ Object params[],
+ String signature[])
+ throws MBeanException,
+ ReflectionException {
+ return null;
+ }
+
+ public MBeanInfo getMBeanInfo() {
+ entered = true;
+ return new MBeanInfo(Test.class.getName(),
+ "Test description",
+ null, null, null, null);
+ }
+
+ public boolean entered;
+ }
+
+ /*
+ * Print message
+ */
+ private static void echo(String message) {
+ System.out.println(message);
+ }
+
+ /**
+ * Standalone entry point.
+ *
+ * Run the test and report to stdout.
+ */
+ public static void main(String args[]) throws Exception {
+
+ echo(">>> Create MBeanServer");
+ MBeanServer server = MBeanServerFactory.newMBeanServer();
+
+ echo(">>> Default Domain: " + server.getDefaultDomain());
+
+ echo(">>> Create and register Test MBean");
+ Test mbean = new Test();
+ ObjectName name = ObjectName.getInstance(":type=Test");
+ server.registerMBean(mbean, name);
+
+ echo(">>> Set entered flag to false in Test MBean");
+ mbean.entered = false;
+
+ echo(">>> Query Names:");
+ Set<ObjectName> names = server.queryNames(null, null);
+ for (ObjectName on : names) {
+ echo("\t" + on.toString());
+ }
+
+ echo(">>> Entered flag = " + mbean.entered);
+
+ if (mbean.entered) {
+ echo(">>> Test FAILED!");
+ throw new IllegalArgumentException("getMBeanInfo got called");
+ } else {
+ echo(">>> Test PASSED!");
+ }
+ }
+}
diff --git a/test/javax/management/security/MBeanPermissionTest.java b/test/javax/management/security/MBeanPermissionTest.java
new file mode 100644
index 0000000..fe6a7d5
--- /dev/null
+++ b/test/javax/management/security/MBeanPermissionTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6228749
+ * @summary MBeanPermission(null,"") should throw IllegalArgumentException.
+ * @author Luis-Miguel Alventosa
+ * @run clean MBeanPermissionTest
+ * @run build MBeanPermissionTest
+ * @run main MBeanPermissionTest
+ */
+
+import javax.management.MBeanPermission;
+
+public class MBeanPermissionTest {
+ public static void main(String[] args) {
+ int error = 0;
+ System.out.println(">>> MBeanPermissionTest");
+ try {
+ System.out.println("Create MBeanPermission(null,\"\")");
+ MBeanPermission mbp = new MBeanPermission(null, "");
+ System.out.println("Didn't get expected IllegalArgumentException");
+ error++;
+ } catch (IllegalArgumentException e) {
+ System.out.println("Got expected exception = " + e);
+ } catch (Exception e) {
+ System.out.println("Got unexpected exception = " + e);
+ error++;
+ }
+ try {
+ System.out.println("Create MBeanPermission(\"\", null)");
+ MBeanPermission mbp = new MBeanPermission("", null);
+ System.out.println("Didn't get expected IllegalArgumentException");
+ error++;
+ } catch (IllegalArgumentException e) {
+ System.out.println("Got expected exception = " + e);
+ } catch (Exception e) {
+ System.out.println("Got unexpected exception = " + e);
+ error++;
+ }
+ if (error > 0) {
+ final String msg = "Test FAILED! Got " + error + " error(s)";
+ System.out.println(msg);
+ throw new IllegalArgumentException(msg);
+ } else {
+ System.out.println("Test PASSED!");
+ }
+ }
+}
diff --git a/test/javax/management/standardmbean/DeadlockTest.java b/test/javax/management/standardmbean/DeadlockTest.java
new file mode 100644
index 0000000..0cf2526
--- /dev/null
+++ b/test/javax/management/standardmbean/DeadlockTest.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6331746
+ * @summary Deadlock on synchronization problem
+ * @author Shanliang JIANG
+ * @run main DeadlockTest
+ */
+
+import javax.management.*;
+import javax.management.timer.*;
+
+public class DeadlockTest extends StandardMBean {
+ public <T> DeadlockTest(T implementation, Class<T> mbeanInterface)
+ throws NotCompliantMBeanException {
+ super(implementation, mbeanInterface);
+ }
+
+ public MBeanInfo getCachedMBeanInfo() {
+ return super.getCachedMBeanInfo();
+ }
+
+ public void cacheMBeanInfo(MBeanInfo mi) {
+ super.cacheMBeanInfo(mi);
+ }
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("main: No deadlock please.");
+
+ System.out.println("main: Create a BadBay to hold the lock forever.");
+ DeadlockTest dt = new DeadlockTest(new Timer(), TimerMBean.class);
+
+ BadBoy bb = new BadBoy(dt);
+ bb.start();
+
+ final long timeout = 2000;
+ long stopTime = System.currentTimeMillis() + timeout;
+ long timeToWait = timeout;
+ synchronized(bb) {
+ while(!bb.gotLock || timeToWait > 0) {
+ bb.wait(timeToWait);
+
+ timeToWait = stopTime - System.currentTimeMillis();
+ }
+ }
+
+ if (!bb.gotLock) {
+ throw new RuntimeException("Failed to get lock, impossible!");
+ }
+
+ System.out.println("main: The BadBay is holding the lock forever.");
+
+ System.out.println("main: Create a WorkingBoy to see blocking ...");
+ WorkingBoy wb = new WorkingBoy(dt);
+
+ stopTime = System.currentTimeMillis() + timeout;
+ timeToWait = timeout;
+
+ synchronized(wb) {
+ wb.start();
+
+ while(!wb.done || timeToWait > 0) {
+ wb.wait(timeToWait);
+
+ timeToWait = stopTime - System.currentTimeMillis();
+ }
+ }
+
+ if (!wb.done) {
+ throw new RuntimeException("It is blocked!");
+ }
+
+ System.out.println("main: OK, bye bye.");
+ }
+
+ private static class BadBoy extends Thread {
+ public BadBoy(Object o) {
+ setDaemon(true);
+
+ this.o = o;
+ }
+
+ public void run() {
+ System.out.println("BadBoy-run: keep synchronization lock forever!");
+
+ synchronized(o) {
+ synchronized(this) {
+ gotLock = true;
+
+ this.notify();
+ }
+
+ try {
+ Thread.sleep(10000000);
+ } catch (Exception e) {
+ // OK
+ }
+ }
+ }
+
+ final Object o;
+ public boolean gotLock;
+ }
+
+ private static class WorkingBoy extends Thread {
+ public WorkingBoy(DeadlockTest sm) {
+ setDaemon(true);
+
+ this.sm = sm;
+ }
+
+ public void run() {
+ try {
+ System.out.println("WorkingBoy-run: calling StandardMBean methods ...");
+
+ System.out.println("WorkingBoy-run: calling setImplementation ...");
+ sm.setImplementation(new Timer());
+
+ System.out.println("WorkingBoy-run: calling getImplementation ...");
+ sm.getImplementation();
+
+ System.out.println("WorkingBoy-run: calling getMBeanInterface ...");
+ sm.getMBeanInterface();
+
+ System.out.println("WorkingBoy-run: calling getImplementationClass ...");
+ sm.getImplementationClass();
+
+ System.out.println("WorkingBoy-run: calling cacheMBeanInfo ...");
+ sm.cacheMBeanInfo(null);
+
+ System.out.println("WorkingBoy-run: calling getCachedMBeanInfo ...");
+ sm.getCachedMBeanInfo();
+
+ System.out.println("WorkingBoy-run: All done!");
+
+ synchronized(this) {
+ done = true;
+
+ this.notifyAll();
+ }
+ } catch (NotCompliantMBeanException ne) {
+ // Impossible?
+ throw new RuntimeException(ne);
+ }
+ }
+
+ final DeadlockTest sm;
+ public boolean done;
+ }
+}
diff --git a/test/javax/naming/InitialContext/EnvClone.java b/test/javax/naming/InitialContext/EnvClone.java
new file mode 100644
index 0000000..f7d95a8
--- /dev/null
+++ b/test/javax/naming/InitialContext/EnvClone.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 1999 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4241351
+ * @summary Ensure that initial context constructor clones its environment
+ * parameter before calling init(), and that it doesn't clone it
+ * within init().
+ */
+
+import java.util.Hashtable;
+import javax.naming.*;
+
+public class EnvClone extends InitialContext {
+
+ EnvClone(Hashtable env) throws NamingException{
+ super(env);
+ }
+
+ EnvClone(boolean lazy) throws NamingException{
+ super(lazy);
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ Hashtable env = new Hashtable(5);
+ EnvClone ctx = new EnvClone(env);
+
+ if (env == ctx.myProps) {
+ throw new Exception(
+ "Test failed: constructor didn't clone environment");
+ }
+
+ ctx = new EnvClone(true);
+ ctx.init(env);
+
+ if (env != ctx.myProps) {
+ throw new Exception("Test failed: init() cloned environment");
+ }
+ }
+}
diff --git a/test/javax/naming/Name/Serialized13Name.java b/test/javax/naming/Name/Serialized13Name.java
new file mode 100644
index 0000000..58d4ec9
--- /dev/null
+++ b/test/javax/naming/Name/Serialized13Name.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4941591
+ * @summary REGRESSION: 4 JCK1.5-runtime api/javax_naming/... tests fail
+ */
+
+import java.io.*;
+import javax.naming.*;
+
+/**
+ * Ensure that a Name class object serialized with J2SE1.3 is
+ * deserialized with J2SE1.5
+ */
+public class Serialized13Name {
+
+ public static void main(String args[]) throws Exception {
+ Name name;
+ String serialFilename = System.getProperty("test.src", ".") +
+ "/" + "j2se13-name.ser";
+
+ ObjectInputStream in = new ObjectInputStream(
+ new FileInputStream(serialFilename));
+ System.out.println();
+ System.out.println("Deserialized Name class object:" + in.readObject());
+ in.close();
+ }
+}
diff --git a/test/javax/naming/Name/j2se13-name.ser b/test/javax/naming/Name/j2se13-name.ser
new file mode 100644
index 0000000..65bed33
--- /dev/null
+++ b/test/javax/naming/Name/j2se13-name.ser
Binary files differ
diff --git a/test/javax/naming/RefAddr/NullContent.java b/test/javax/naming/RefAddr/NullContent.java
new file mode 100644
index 0000000..71bfc57
--- /dev/null
+++ b/test/javax/naming/RefAddr/NullContent.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2000 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4347817
+ * @summary RefAddr.toString() throws NullPointerException when content is null
+ */
+
+import javax.naming.*;
+
+public class NullContent {
+
+ public static void main(String[] args) throws Exception {
+ RefAddr addr1 = new StringRefAddr("Type1", null);
+ RefAddr addr2 = new StringRefAddr("Type2", "type2");
+ Reference ref = new Reference("com.sun.test.Class", addr1);
+ ref.add(addr2);
+
+ try {
+ addr1.toString();
+ addr2.toString();
+ addr1.hashCode();
+ addr2.hashCode();
+ ref.toString();
+ } catch (Exception e) {
+ throw new Exception(
+ "Test failed: does not accept null content: " + e);
+ }
+ }
+}
diff --git a/test/javax/naming/ldap/LdapName/CompareToEqualsTests.java b/test/javax/naming/ldap/LdapName/CompareToEqualsTests.java
new file mode 100644
index 0000000..2dbe9c7
--- /dev/null
+++ b/test/javax/naming/ldap/LdapName/CompareToEqualsTests.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4635618
+ * @summary Support for manipulating LDAP Names
+ */
+
+import javax.naming.ldap.*;
+import java.util.ArrayList;
+import java.util.List;
+import javax.naming.InvalidNameException;
+
+/**
+ * Tests for LdapName/Rdn compareTo, equals and hashCode methods.
+ */
+public class CompareToEqualsTests {
+
+ public static void main(String args[])
+ throws Exception {
+
+ /**
+ * Test cases:
+ * 1) Same RDNs.
+ * 2) same RDN sequence with an AVA ordered differently.
+ * 3) RDN sequences of a differing AVA.
+ * 4) RDN sequence of different length.
+ * 5) RDN sequence of different Case.
+ * 6) Matching binary return values.
+ * 7) Binary values that don't match.
+ */
+ String names1[] = new String [] {
+ "ou=Sales+cn=Bob", "ou=Sales+cn=Bob", "ou=Sales+cn=Bob",
+ "ou=Sales+cn=Scott+c=US", "cn=config"};
+
+ String names2[] = new String [] {
+ "ou=Sales+cn=Bob", "cn=Bob+ou=Sales", "ou=Sales+cn=Scott",
+ "ou=Sales+cn=Scott", "Cn=COnFIG"};
+
+ int expectedResults[] = {0, 0, -1, -1, 0};
+
+
+ for (int i = 0; i < names1.length; i++) {
+ checkResults(new LdapName(names1[i]),
+ new LdapName(names2[i]), expectedResults[i]);
+ }
+
+ byte[] value = "abcxyz".getBytes();
+ Rdn rdn1 = new Rdn("binary", value);
+ ArrayList rdns1 = new ArrayList();
+ rdns1.add(rdn1);
+ LdapName l1 = new LdapName(rdns1);
+
+ Rdn rdn2 = new Rdn("binary", value);
+ ArrayList rdns2 = new ArrayList();
+ rdns2.add(rdn2);
+ LdapName l2 = new LdapName(rdns2);
+ checkResults(l1, l2, 0);
+
+ l2 = new LdapName("binary=#61626378797A");
+ checkResults(l1, l2, 0);
+
+ l2 = new LdapName("binary=#61626378797B");
+ checkResults(l1, l2, -1);
+
+ System.out.println("Tests passed");
+ }
+
+
+ static void checkResults(LdapName name1, LdapName name2, int expectedResult)
+ throws Exception {
+
+ System.out.println("Checking name1: " + name1 +
+ " and name2: " + name2);
+
+ boolean isEquals = (expectedResult == 0) ? true : false;
+
+ int result = name1.compareTo(name2);
+ if ((isEquals && (result != expectedResult)) ||
+ isPositive(result) != isPositive(expectedResult)) {
+ throw new Exception(
+ "Comparison test failed for name1:" +
+ name1 + " name2:" + name2 +
+ ", expected (1 => positive, -1 => negetive): " +
+ expectedResult + " but got: " + result);
+ }
+
+ if (name1.equals(name2) != isEquals) {
+ throw new Exception("Equality test failed for name1: " +
+ name1 + " name2:" + name2 + ", expected: " +
+ isEquals);
+ }
+
+ if (isEquals && (name1.hashCode() != name2.hashCode())) {
+ System.out.println("name1.hashCode(): " + name1.hashCode() +
+ " name2.hashCode(): " + name2.hashCode());
+ throw new Exception("hashCode test failed for name1:" +
+ name1 + " name2:" + name2);
+ }
+ }
+
+ static boolean isPositive(int n) {
+ return (n >= 0) ? true : false;
+ }
+}
diff --git a/test/javax/naming/ldap/LdapName/EscapeUnescapeTests.java b/test/javax/naming/ldap/LdapName/EscapeUnescapeTests.java
new file mode 100644
index 0000000..47ed358
--- /dev/null
+++ b/test/javax/naming/ldap/LdapName/EscapeUnescapeTests.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4635618
+ * @summary Support for manipulating LDAP Names
+ */
+
+import javax.naming.ldap.Rdn;
+
+/**
+ * Tests for Rdn escapeValue and unescapeValue methods
+ */
+public class EscapeUnescapeTests {
+
+ public static void main(String args[]) throws Exception {
+
+ /**
+ * Unescape tests
+ */
+ String[] invalids = new String[] {"\\", "\\\\\\" };
+
+ String[] valids = new String[] {"\\\\", "\\\\\\\\"};
+
+ String val;
+ Object unescVal = null;
+ System.out.println("##### Unescape value tests #####");
+
+ for (int i = 0; i < valids.length; i++) {
+ unescVal = Rdn.unescapeValue(valids[i]);
+ System.out.println("Orig val: " + valids[i] +
+ " Unescaped val: " + unescVal);
+ }
+
+ boolean isExcepThrown = false;
+ for (int i = 0; i < invalids.length; i++) {
+ val = "Juicy" + invalids[i] + "Fruit";
+ try {
+ unescVal = Rdn.unescapeValue(val);
+ } catch (IllegalArgumentException e) {
+ System.out.println("Caught the right exception: " + e);
+ isExcepThrown = true;
+ }
+ if (!isExcepThrown) {
+ throw new Exception(
+ "Unescaped successfully an invalid string "
+ + val + " as Rdn: " + unescVal);
+ }
+ isExcepThrown = false;
+ }
+
+ /**
+ * Escape tests
+ */
+ String[] values = new String[] {";", "<<<", "###", "=="};
+ System.out.println("##### Escape value tests #####");
+ printEscapedVal(values);
+
+ // leading space, trailing space
+ values = new String[] {" leading space", "trailing space "};
+ printEscapedVal(values);
+
+ // binary values
+ byte[] bytes = new byte[] {1, 2, 3, 4};
+ String escVal = Rdn.escapeValue(bytes);
+ System.out.println("Orig val: " + bytes +
+ " Escaped val: " + escVal);
+ }
+
+ static void printEscapedVal(Object[] values) {
+ String escVal;
+ for (int i = 0; i < values.length; i++) {
+ escVal = Rdn.escapeValue(values[i]);
+ System.out.println("Orig val: " + values[i] +
+ " Escaped val: " + escVal);
+ }
+ }
+}
diff --git a/test/javax/naming/ldap/LdapName/LdapNameConstruction.java b/test/javax/naming/ldap/LdapName/LdapNameConstruction.java
new file mode 100644
index 0000000..8a1d9f5
--- /dev/null
+++ b/test/javax/naming/ldap/LdapName/LdapNameConstruction.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4635618
+ * @summary Support for manipulating LDAP Names
+ */
+
+import javax.naming.ldap.*;
+import java.util.ArrayList;
+import java.util.List;
+import javax.naming.InvalidNameException;
+import javax.naming.directory.*;
+
+/**
+ * These tests are for checking the LdapName and Rdn
+ * constructors.
+ */
+public class LdapNameConstruction {
+
+ public static void main(String args[])
+ throws Exception {
+ /**
+ * Four ways of constructing the same Rdn
+ */
+ Rdn rdn1 = new Rdn("ou= Juicy\\, Fruit");
+ System.out.println("rdn1:" + rdn1.toString());
+
+ Rdn rdn2 = new Rdn(rdn1);
+ System.out.println("rdn2:" + rdn2.toString());
+
+ Attributes attrs = new BasicAttributes();
+ attrs.put("ou", "Juicy, Fruit");
+ attrs.put("cn", "Mango");
+ Rdn rdn3 = new Rdn(attrs);
+ System.out.println("rdn3:" + rdn3.toString());
+
+ Rdn rdn4 = new Rdn("ou", "Juicy, Fruit");
+ System.out.println("rdn4:" + rdn4.toString());
+
+ // Rdn with unicode value
+ Rdn rdn5 = new Rdn("SN=Lu\\C4\\8Di\\C4\\87");
+ System.out.println("rdn5:" + rdn5.toString());
+
+ /**
+ * LdapName creation tests
+ */
+ List rdns = new ArrayList();
+ rdns.add(new Rdn("o=Food"));
+ rdns.add(new Rdn("ou=Fruits"));
+ rdns.add(rdn3);
+ LdapName name1 = new LdapName(rdns);
+ System.out.println("ldapname1:" + name1.toString());
+
+ LdapName name2 = new LdapName(
+ "ou=Juicy\\, Fruit + cn = Mango, ou=Fruits, o=Food");
+ System.out.println("ldapName2:" + name2.toString());
+
+ if (!name2.equals(name1)) {
+ throw new Exception("ldapname1 does not equals ldapname2");
+ }
+ System.out.println("ldapname1 and ldapname2 are equal");
+
+ LdapName name = new LdapName(new ArrayList());
+ System.out.println("Empty ldapname:" + name);
+ }
+}
diff --git a/test/javax/naming/ldap/LdapName/LdapParserTests.java b/test/javax/naming/ldap/LdapName/LdapParserTests.java
new file mode 100644
index 0000000..b389e39
--- /dev/null
+++ b/test/javax/naming/ldap/LdapName/LdapParserTests.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4635618
+ * @summary Support for manipulating LDAP Names
+ */
+
+import javax.naming.ldap.*;
+import java.util.ArrayList;
+import java.util.List;
+import javax.naming.InvalidNameException;
+
+/**
+ * Tests for LDAP name parsing
+ */
+
+public class LdapParserTests {
+ public static void main(String args[])
+ throws Exception {
+ Rdn rdn = null;
+
+ /**
+ * Presence of any of these characters in an attribute value
+ * without a preceeding escape is considered Illegal by
+ * the LDAP parser.
+ */
+ String[] mustEscSpecials = new String[]
+ {";", ",", "\\", "+"};
+
+ /**
+ * The special characters that should be preceeded by an escape
+ */
+ String[] specials = new String[]
+ {";", ",", "\\", "<", ">", "#", "\"", "+"};
+
+ /**
+ * Test with unescaped speicial characters in the Rdn
+ */
+ System.out.println();
+ System.out.print("*****Tests with unescaped special ");
+ System.out.println("characters in the Rdn*****");
+
+ for (int i = 0; i < mustEscSpecials.length; i++) {
+ String rdnStr = "cn=Juicy" + mustEscSpecials[i] + "Fruit";
+ testInvalids(rdnStr);
+ }
+
+ /*
+ * special characters with a preceeding backslash must be accepted.
+ */
+ System.out.println();
+ System.out.println("******Special character escaping tests ******");
+ for (int i = 0; i < specials.length; i++) {
+ rdn = new Rdn("cn=Juicy\\" + specials[i] + "Fruit");
+ }
+ System.out.println("Escape leading space:" +
+ new Rdn("cn=\\ Juicy Fruit")); // escaped leading space
+ System.out.println("Escaped leading #:" +
+ new Rdn("cn=\\#Juicy Fruit")); // escaped leading # in string
+ System.out.println("Escaped trailing space:" +
+ new Rdn("cn=Juicy Fruit\\ ")); // escaped trailing space
+
+ // Unescaped special characters at the beginning of a value
+ System.out.println();
+ System.out.println(
+ "******Other unescaped special character tests ******");
+ rdn = new Rdn("cn= Juicy Fruit");
+ System.out.println(
+ "Accepted Rdn with value containing leading spaces:" +
+ rdn.toString());
+ rdn = new Rdn("cn=Juicy Fruit ");
+ System.out.println(
+ "Accepted Rdn with value containing trailing spaces:" +
+ rdn.toString());
+
+ String[] invalids = new String[]
+ {"cn=#xabc", "cn=#axcd", "cn=#abcx", "cn=#abcdex"};
+
+ for (int i = 0; i < invalids.length; i++) {
+ testInvalids(invalids[i]);
+ }
+
+ /**
+ * Other special cases
+ */
+ System.out.println();
+ System.out.println(
+ "***************Other special cases****************");
+
+ LdapName name = new LdapName("");
+ System.out.println("Empty LDAP name:" + name.toString());
+
+ // Rdn with quoted value
+ rdn = new Rdn("cn=\"Juicy ,=+<>#; Fruit\"");
+ System.out.println("Quoted Rdn string:" + rdn.toString());
+
+ // Rdn with unicode value
+ rdn = new Rdn("SN=Lu\\C4\\8Di\\C4\\87");
+ System.out.println("Unicode Rdn string:" + rdn.toString());
+
+ /*
+ * oid type and binary value
+ */
+ name = new LdapName(
+ "1.3.6.1.4.1.466.0=#04024869,O=Test,C=GB");
+ System.out.println("binary valued LDAP name:" + name.toString());
+
+ // ';' seperated name- RFC 1779 style
+ name = new LdapName("CN=Steve Kille;O=Isode;C=GB");
+ System.out.println("';' seperated LDAP name:" + name.toString());
+ }
+
+ static void testInvalids(String rdnStr) throws Exception {
+ boolean isExcepThrown = false;
+ Rdn rdn = null;
+ try {
+ rdn = new Rdn(rdnStr);
+ } catch (InvalidNameException e) {
+ System.out.println("Caught the right exception: " + e);
+ isExcepThrown = true;
+ } catch (IllegalArgumentException e) {
+ System.out.println("Caught the right exception: " + e);
+ isExcepThrown = true;
+ }
+ if (!isExcepThrown) {
+ throw new Exception(
+ "Accepted an invalid Rdn string:" +
+ rdnStr + " as Rdn: " + rdn);
+ }
+ }
+}
diff --git a/test/javax/naming/ldap/LdapName/NameTests.java b/test/javax/naming/ldap/LdapName/NameTests.java
new file mode 100644
index 0000000..d003631
--- /dev/null
+++ b/test/javax/naming/ldap/LdapName/NameTests.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4635618
+ * @summary Support for manipulating LDAP Names
+ */
+
+import javax.naming.ldap.*;
+import java.util.*;
+import javax.naming.*;
+import java.io.*;
+
+/**
+ * LdapName tests- These tests are for testing the methods of
+ * javax.naming.Name interface as it applied to LdapName.
+ */
+public class NameTests {
+
+ public static void main(String args[]) throws Exception {
+
+ String[] rdnStr = new String[] {"one=voilet"};
+
+ ArrayList rdnList = new ArrayList();
+
+ for (int i = 0; i < rdnStr.length; i++) {
+ rdnList.add(i, new Rdn(rdnStr[i]));
+ }
+ LdapName dn = new LdapName(rdnList);
+
+ Collection rdns = dn.getRdns();
+ System.out.println("size is :" + dn.size());
+ System.out.println("isEmpty :" + dn.isEmpty());
+ System.out.println("************Printing as Rdns*********");
+ Iterator iter = rdns.iterator();
+ while (iter.hasNext()) {
+ System.out.println(iter.next());
+ }
+
+ System.out.println();
+ System.out.println("************Printing the Enumeration*********");
+ Enumeration dnEnum = dn.getAll();
+ while (dnEnum.hasMoreElements()) {
+ System.out.println(dnEnum.nextElement());
+ }
+
+ // addAll tests
+ System.out.println();
+ LdapName nameSuffix = new LdapName("two=Indigo");
+ System.out.println("addAll():" + dn.addAll(nameSuffix));
+
+ ArrayList list = new ArrayList();
+ list.add(new Rdn("five=Yellow"));
+ System.out.println("Rdn- addAll():" + dn.addAll(list));
+
+ nameSuffix = new LdapName("three=Blue");
+ System.out.println();
+ System.out.println("addAll at pos = 2");
+ System.out.println("addAll():" + dn.addAll(2, nameSuffix));
+
+ list = new ArrayList();
+ list.add(new Rdn("four=Green"));
+ System.out.println();
+ System.out.println("addAll at pos = 3");
+ System.out.println("Rdn- addAll():" + dn.addAll(3, list));
+
+ // add() tests
+ Rdn rdn;
+ System.out.println();
+ System.out.println("add():" + dn.add("eight=white"));
+ rdn = new Rdn("nine=Black");
+ System.out.println();
+ System.out.println("Rdn- add():" + dn.add(rdn));
+
+ /*
+ Rdn nullRdn = null;
+ System.out.println("Rdn- add() with null RDN:" +
+ dn.add(nullRdn));
+ */
+
+ System.out.println();
+ System.out.println("add() at pos 5");
+ System.out.println("add():" + dn.add(5, "six=Orange"));
+ rdn = new Rdn("six=Orange");
+ System.out.println();
+ System.out.println("add() at pos 6");
+ System.out.println("Rdn- add():" + dn.add(6, "seven=Red"));
+
+ // remove tests
+ System.out.println();
+ System.out.println("Removing entries at positions: 7, 8");
+ System.out.println("Removed:" + dn.remove(8));
+ System.out.println("Removed:" + dn.remove(7));
+
+ // get tests
+ System.out.println();
+ System.out.println("toString():" + dn);
+ int size = dn.size();
+ System.out.println("get(0):" + dn.get(0));
+ System.out.println("get(size() - 1):" + dn.get(size - 1));
+ System.out.println("getRdn(0):" + dn.getRdn(0));
+ System.out.println("getRdn(size() - 1):" + dn.getRdn(size - 1));
+
+ System.out.println();
+ System.out.println("********Prefixes**********");
+ System.out.println("getPrefix(0):" + dn.getPrefix(0));
+ System.out.println("getPrefix(size / 2):" + dn.getPrefix(size / 2));
+ System.out.println("getPrefix(size):" + dn.getPrefix(size));
+
+ System.out.println();
+ System.out.println("********Suffixes**********");
+ System.out.println("getSuffix(0):" + dn.getSuffix(0));
+ System.out.println("getSuffix(size/2):" + dn.getSuffix(size / 2));
+ System.out.println("getSuffix(size):" + dn.getSuffix(size));
+
+ System.out.println();
+ System.out.println("startsWith(" + rdnStr[0] + "):" +
+ dn.startsWith(new LdapName(rdnStr[0])));
+
+ String lastEntry = "seven=red";
+ System.out.println("startsWith(" + lastEntry + "):" +
+ dn.startsWith(new LdapName(lastEntry)));
+
+ System.out.println("compositeName- startsWith(" +
+ rdnStr[0] + "): " + dn.startsWith(
+ new CompositeName(rdnStr[0])));
+
+ java.util.List prefixList = (dn.getRdns()).subList(0, size /2);
+ System.out.println("Rdn - startsWith(" + prefixList + "):" +
+ dn.startsWith(prefixList));
+
+ System.out.println("Rdn - startsWith() - empty RDN list:" +
+ dn.startsWith(new ArrayList()));
+
+ System.out.println();
+ System.out.println("endsWith(" + rdnStr[0] + "):" +
+ dn.endsWith(new LdapName(rdnStr[0])));
+
+ System.out.println("endsWith(" + lastEntry + "):" +
+ dn.endsWith(new LdapName(lastEntry)));
+
+ System.out.println("compositeName- endsWith(" + rdnStr[0] + "): " +
+ dn.endsWith(new CompositeName(rdnStr[0])));
+
+ System.out.println("Rdn - endsWith(" + prefixList + "):" +
+ dn.endsWith(prefixList));
+
+ System.out.println("Rdn - endsWith() empty RDN list:" +
+ dn.endsWith(new ArrayList()));
+
+ // test clone
+ System.out.println();
+ System.out.println("cloned name:" + dn.clone());
+
+ // test serialization
+ ObjectOutputStream out = new ObjectOutputStream(
+ new FileOutputStream("dn.ser"));
+ out.writeObject(dn);
+ out.close();
+
+ ObjectInputStream in = new ObjectInputStream(
+ new FileInputStream("dn.ser"));
+
+ System.out.println();
+ System.out.println("Deserialized name:" + in.readObject());
+ in.close();
+ }
+}
diff --git a/test/javax/naming/ldap/LdapName/RdnMisc.java b/test/javax/naming/ldap/LdapName/RdnMisc.java
new file mode 100644
index 0000000..69406a7
--- /dev/null
+++ b/test/javax/naming/ldap/LdapName/RdnMisc.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4635618
+ * @summary Support for manipulating LDAP Names
+ */
+
+import javax.naming.ldap.*;
+import javax.naming.InvalidNameException;
+import java.util.*;
+import javax.naming.directory.*;
+import java.io.*;
+
+/**
+ * Miscelleneous tests of Rdn methods and serialization test
+ */
+public class RdnMisc {
+
+ public static void main(String args[])
+ throws Exception {
+ Attributes attrs = new BasicAttributes();
+ attrs.put("a", "Mango");
+ attrs.put("l", "Yellow<right");
+ attrs.put("b", "Juicy, Fruit");
+ attrs.put("k", "Orange>ripe");
+ attrs.put("c", "Favourite+Fruit");
+ attrs.put("j", "Green#raw");
+ attrs.put("d", "Tropical\\Fruit");
+ attrs.put("i", "Alfanso;expensive");
+ attrs.put("e", "Seasonal\"Fruit");
+ attrs.put("h", "Summer");
+ attrs.put("f", "Smell=Great");
+ attrs.put("g", "Taste==Yummy");
+
+ byte[] mangoJuice = new byte[6];
+ for (int i = 0; i < mangoJuice.length; i++) {
+ mangoJuice[i] = (byte) i;
+ }
+ attrs.put("m", mangoJuice);
+ Rdn rdn = new Rdn(attrs);
+
+ System.out.println();
+ System.out.println("size:" + rdn.size());
+ System.out.println("toString():" + rdn.toString());
+ System.out.println("getType(): " + rdn.getType());
+ System.out.println("getValue(): " + rdn.getValue());
+
+ // test toAttributes
+ System.out.println();
+ System.out.println("toAttributes(): " + rdn.toAttributes());
+
+ // serialization test
+ Rdn rdn2 = new Rdn("cn=Juicy\\, Fruit");
+ System.out.println("Serializing rdn:" + rdn2);
+ ObjectOutputStream out = new ObjectOutputStream(
+ new FileOutputStream("rdn.ser"));
+ out.writeObject(rdn2);
+ out.close();
+
+ ObjectInputStream in = new ObjectInputStream(
+ new FileInputStream("rdn.ser"));
+
+ System.out.println();
+ System.out.println("Deserialized RDN:" + in.readObject());
+ in.close();
+ }
+}
diff --git a/test/javax/naming/ldap/LdapName/RdnToAttrsTest.java b/test/javax/naming/ldap/LdapName/RdnToAttrsTest.java
new file mode 100644
index 0000000..3bf6f71
--- /dev/null
+++ b/test/javax/naming/ldap/LdapName/RdnToAttrsTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6245035
+ * @summary [J2SE 1.5] Rdn generates incorrect attributes sometimes
+ */
+
+import javax.naming.ldap.*;
+import javax.naming.*;
+import java.util.*;
+import javax.naming.directory.*;
+import java.io.*;
+
+public class RdnToAttrsTest {
+
+ public static void main(String args[])
+ throws Exception {
+
+ Rdn rdn = new Rdn("cn = commonName1 + cn = commonName2");
+ String attrStr = rdn.toAttributes().toString();
+ System.out.println("attributes=" + attrStr);
+ if ("{cn=cn: commonName1, commonName2}".equals(attrStr)) {
+ System.out.println("The test PASSED");
+ } else {
+ throw new Exception("The test failed");
+ }
+}
+}
diff --git a/test/javax/naming/ldap/LdapName/TrailingSpaceTest.java b/test/javax/naming/ldap/LdapName/TrailingSpaceTest.java
new file mode 100644
index 0000000..c032686
--- /dev/null
+++ b/test/javax/naming/ldap/LdapName/TrailingSpaceTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4985339
+ * @summary javax.naming.ldap.LdapName(String) doesn't parse
+ * some strings well
+ */
+
+import javax.naming.ldap.*;
+import javax.naming.*;
+
+public class TrailingSpaceTest {
+
+ public static void main(String[] args) throws Exception {
+ String[] input = {"cn=Tyler\\ ",
+ "cn=Ty ler",
+ "cn=Tyler\\\\ ",
+ "cn=Tyler\\\\\\ ",
+ "cn= Tyler ",
+ "cn=Tyler\\\\ \\ ",
+ "cn= ",
+ "cn= \\ "
+ };
+
+ String[] expected = { "Tyler ",
+ "Ty ler",
+ "Tyler\\",
+ "Tyler\\ ",
+ "Tyler",
+ "Tyler\\ ",
+ "",
+ " "
+ };
+
+ try {
+ System.out.println("*************************");
+ System.out.println();
+
+ for (int i = 0; i < input.length; i++) {
+
+ Rdn rdn = new Rdn(input[i]);
+
+ System.out.println((i + 1) + ") RDN string: [" +
+ input[i] + "]");
+ Object value = rdn.getValue();
+
+ // escape the value
+ String escaped = Rdn.escapeValue(value);
+ System.out.println("escaped: [" + escaped + "]");
+
+ // unescape the value
+ String unescaped = (String) Rdn.unescapeValue(escaped);
+ System.out.println("unescaped: [" + unescaped + "]");
+
+ System.out.println();
+ System.out.println("*************************");
+ System.out.println();
+
+ if (!unescaped.equals(expected[i])) {
+ throw new Exception("Invalid unescaping for: " +
+ " input #" + (i + 1));
+ }
+ }
+ } catch (InvalidNameException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/test/javax/naming/spi/DirectoryManager/DummyContext.java b/test/javax/naming/spi/DirectoryManager/DummyContext.java
new file mode 100644
index 0000000..5a31e7a
--- /dev/null
+++ b/test/javax/naming/spi/DirectoryManager/DummyContext.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ *
+ * Used by GetContDirCtx.java
+ */
+
+import javax.naming.*;
+import java.util.Hashtable;
+
+public class DummyContext extends InitialContext {
+
+ private Hashtable env;
+
+ DummyContext(Hashtable env) throws NamingException {
+ this.env = env;
+ }
+
+ public Hashtable getEnvironment() throws NamingException {
+ return env;
+ }
+}
diff --git a/test/javax/naming/spi/DirectoryManager/DummyObjectFactory.java b/test/javax/naming/spi/DirectoryManager/DummyObjectFactory.java
new file mode 100644
index 0000000..ba416dd
--- /dev/null
+++ b/test/javax/naming/spi/DirectoryManager/DummyObjectFactory.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2003-2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ *
+ * Used by GetContDirCtx.java
+ */
+
+import javax.naming.*;
+import javax.naming.spi.*;
+import javax.naming.directory.*;
+import java.util.Hashtable;
+
+public class DummyObjectFactory implements ObjectFactory {
+
+ public DummyObjectFactory() {
+
+ }
+
+ public Object getObjectInstance(Object obj, Name name, Context nameCtx,
+ Hashtable<?,?> environment) throws Exception {
+ return new DummyContext(environment);
+ }
+}
diff --git a/test/javax/naming/spi/DirectoryManager/GetContDirCtx.java b/test/javax/naming/spi/DirectoryManager/GetContDirCtx.java
new file mode 100644
index 0000000..8df10f1
--- /dev/null
+++ b/test/javax/naming/spi/DirectoryManager/GetContDirCtx.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 1999-2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4241676
+ * @summary getContinuationDirContext() should set CPE environment property.
+ * @build DummyObjectFactory DummyContext
+ */
+
+import java.util.Hashtable;
+import javax.naming.*;
+import javax.naming.directory.*;
+import javax.naming.spi.*;
+
+public class GetContDirCtx {
+
+ public static void main(String[] args) throws Exception {
+
+ CannotProceedException cpe = new CannotProceedException();
+ Hashtable env = new Hashtable(1);
+ cpe.setEnvironment(env);
+
+ Reference ref = new Reference("java.lang.Object",
+ "DummyObjectFactory",
+ null);
+ cpe.setResolvedObj(ref);
+ Context contCtx = null;
+ try {
+ contCtx = DirectoryManager.getContinuationDirContext(cpe);
+ } catch (CannotProceedException e) {
+ }
+
+ Hashtable contEnv = contCtx.getEnvironment();
+ if (contEnv.get(NamingManager.CPE) != cpe) {
+ throw new Exception("Test failed: CPE property not set" +
+ " in the continuation context");
+ }
+ }
+}
diff --git a/test/javax/print/PrintSubInputStream/Example.java b/test/javax/print/PrintSubInputStream/Example.java
new file mode 100644
index 0000000..6195c2c
--- /dev/null
+++ b/test/javax/print/PrintSubInputStream/Example.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 4700712 4707777
+ * @summary Should submit only 1 job in Windows and print only 1 page.
+ * @author jgodinez
+ * @run main/manual Example
+ */
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.io.*;
+import javax.print.*;
+import javax.print.attribute.*;
+import javax.print.event.*;
+
+public class Example
+{
+ public static void main(String [] args)
+ {
+ if(args.length != 1)
+ {
+ System.err.println("Usage: Example num_sections");
+ return;
+ }
+
+ try{
+ int stream_sections = Integer.parseInt(args[0]);
+ DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE;
+ PrintService [] services = PrintServiceLookup.lookupPrintServices
+(flavor, null);
+
+ if(services.length > 0)
+ {
+ PrintRequestAttributeSet attbs = new
+HashPrintRequestAttributeSet();
+ PrintService service = ServiceUI.printDialog(null, 100, 100,
+services, null, flavor, attbs);
+
+ if(service != null)
+ {
+ InputStream stream = createInputStream(stream_sections);
+ Doc doc = new SimpleDoc(stream, flavor, null);
+ DocPrintJob job = service.createPrintJob();
+ job.addPrintJobListener(new PrintJobListener(){
+ public void printJobCanceled(PrintJobEvent e)
+ {
+ finish("Canceled");
+ }
+
+ public void printJobCompleted(PrintJobEvent e)
+ {
+ finish("Complete");
+ }
+
+ public void printJobFailed(PrintJobEvent e)
+ {
+ finish("Failed");
+ }
+
+ public void printDataTransferCompleted(PrintJobEvent
+pje)
+ {
+ System.out.println("data transfered");
+ }
+
+ public void printJobNoMoreEvents(PrintJobEvent pje)
+ {
+ finish("Complete");
+ }
+ public void printJobRequiresAttention(PrintJobEvent pje)
+{}
+
+ });
+ System.out.println("Printing...");
+ job.print(doc, attbs);
+ }
+
+ }else
+ {
+ System.out.println("no printers found");
+ }
+
+ }catch(Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ private static void finish(String message)
+ {
+ System.out.println("Printing " + message);
+ System.out.flush();
+ }
+
+ private static InputStream createInputStream(int num_sections)
+ {
+ byte [] bytes = "Returns the number of bytes that can be read (or skipped over)\nfrom this input stream without blocking by the next caller of\na method for this input stream. The next caller might be the same thread or\nanother thread. ".getBytes();
+
+ return new TestInputStream(bytes, num_sections);
+ }
+
+ private static class TestInputStream extends ByteArrayInputStream
+ {
+ public TestInputStream(byte [] bytes, int sections)
+ {
+ super(bytes);
+ int avail = super.available();
+ block_size = avail / sections;
+ }
+
+ public int available()
+ {
+ int true_avail = super.available();
+ return true_avail == 0 ? 0 : block_size;
+ }
+
+ private int block_size;
+ }
+}
diff --git a/test/javax/print/applet/AppletPrintLookup.html b/test/javax/print/applet/AppletPrintLookup.html
new file mode 100644
index 0000000..1a0801b
--- /dev/null
+++ b/test/javax/print/applet/AppletPrintLookup.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+<title> APL </title>
+</head>
+<body>
+ Wait until 5 applets have initialised and started and display string
+ messages. Applet 0 and Applet 2 should find one less print service
+ than the rest.
+ Specifically all except Applets 0 and 2 should find a service called
+ Applet N printer where N is the number of the applet. They should *NOT*
+ find Applet M printer (where M != N).
+
+
+<h1>Applet Print Service Lookup</h1>
+
+<APPLET CODE="Applet0.class" CODEBASE=applet0 WIDTH=300 HEIGHT=200></APPLET>
+<APPLET CODE="Applet1.class" ARCHIVE="applet1.jar" CODEBASE=applet1 WIDTH=300 HEIGHT=200></APPLET>
+<APPLET CODE="Applet2.class" CODEBASE=applet2 WIDTH=300 HEIGHT=200></APPLET>
+<APPLET CODE="Applet3.class" CODEBASE=applet3 WIDTH=300 HEIGHT=200></APPLET>
+<APPLET CODE="Applet4.class" CODEBASE=applet4 WIDTH=300 HEIGHT=200></APPLET>
+</body>
+</html>
diff --git a/test/javax/print/applet/AppletPrintLookup.sh b/test/javax/print/applet/AppletPrintLookup.sh
new file mode 100644
index 0000000..1f73166
--- /dev/null
+++ b/test/javax/print/applet/AppletPrintLookup.sh
@@ -0,0 +1,93 @@
+#!/bin/sh
+
+#
+# Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+#
+# @test
+# @bug 4457046 6592906
+# @summary checks that applets can lookup print services and will not
+# see services registered by other applets from difference code bases.
+# @run shell/manual AppletPrintLookup.sh
+
+echo "TESTJAVA=${TESTJAVA}"
+echo "TESTSRC=${TESTSRC}"
+echo "TESTCLASSES=${TESTCLASSES}"
+
+echo "Wait until 5 applets have initialised and started and display string"
+echo "messages. Applet 0 and Applet 2 should find one less print service"
+echo "than the rest."
+echo "Specifically all except Applets 0 and 2 should find a service called"
+echo "Applet N printer where N is the number of the applet. They should NOT"
+echo "find Applet M printer (where M != N)."
+
+OS=`uname -s`
+
+SEP="/"
+OS=`uname -s`
+case "$OS" in
+ Win* )
+ echo "WINDOWS"
+ SEP="\\"
+ ;;
+ * )
+ ;;
+esac
+
+JAVAC_CMD=${TESTJAVA}${SEP}bin${SEP}javac
+
+(cd ${TESTSRC} ; ${JAVAC_CMD} -d ${TESTCLASSES} YesNo.java)
+
+mkdir -p ${TESTCLASSES}${SEP}applet0
+(cd ${TESTSRC}${SEP}applet0 ; ${JAVAC_CMD} -d ${TESTCLASSES}${SEP}applet0 Applet0.java)
+
+mkdir -p ${TESTCLASSES}${SEP}applet1
+(cd ${TESTSRC}${SEP}applet1 ; ${JAVAC_CMD} -d ${TESTCLASSES}${SEP}applet1 Applet1.java Applet1PrintService.java Applet1PrintServiceLookup.java)
+rm -rf ${TESTCLASSES}${SEP}applet1/META-INF/services
+mkdir -p ${TESTCLASSES}${SEP}applet1/META-INF/services
+cp -p ${TESTSRC}${SEP}applet1/META-INF/services/javax.print.PrintServiceLookup ${TESTCLASSES}${SEP}applet1/META-INF/services
+(cd ${TESTCLASSES}${SEP}applet1 ; ${TESTJAVA}${SEP}bin${SEP}jar -cf applet1.jar *.class META-INF)
+
+mkdir -p ${TESTCLASSES}${SEP}applet2
+(cd ${TESTSRC}${SEP}applet2 ; ${JAVAC_CMD} -d ${TESTCLASSES}${SEP}applet2 Applet2.java Applet2PrintService.java Applet2PrintServiceLookup.java)
+
+mkdir -p ${TESTCLASSES}${SEP}applet3
+(cd ${TESTSRC}${SEP}applet3 ; ${JAVAC_CMD} -d ${TESTCLASSES}${SEP}applet3 Applet3.java Applet3PrintService.java)
+
+mkdir -p ${TESTCLASSES}${SEP}applet4
+(cd ${TESTSRC}${SEP}applet4 ; ${JAVAC_CMD} -d ${TESTCLASSES}${SEP}applet4 Applet4.java Applet4PrintService.java Applet4PrintServiceLookup.java)
+
+cp ${TESTSRC}${SEP}AppletPrintLookup.html ${TESTCLASSES}
+
+${TESTJAVA}${SEP}bin${SEP}appletviewer ${TESTCLASSES}${SEP}AppletPrintLookup.html &
+
+cd ${TESTCLASSES}
+${TESTJAVA}${SEP}bin${SEP}java YesNo
+ if [ $? -ne 0 ]
+ then
+ echo "Test fails!"
+ exit 1
+ fi
+
+echo "Test passes."
+exit 0
diff --git a/test/javax/print/applet/YesNo.java b/test/javax/print/applet/YesNo.java
new file mode 100644
index 0000000..cdcb4ec
--- /dev/null
+++ b/test/javax/print/applet/YesNo.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2001 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import java.awt.*;
+import java.awt.event.*;
+
+public class YesNo extends Panel implements ActionListener {
+
+ static String nl = System.getProperty("line.Separator", "\n");
+ static String instructions =
+ "Wait until 5 applets have initialised and started and display string"
+ +nl+
+ "messages. Applet 0 and Applet 2 should find one less print service"
+ +nl+
+ "than the rest."
+ +nl+
+ "Specifically all except Applets 0 and 2 should find a service called"
+ +nl+
+ "Applet N printer where N is the number of the applet."
+ +nl+
+ "They should *NOT* find Applet M printer (where M != N)."
+ +nl+
+ "After deciding if the test passes, Quit appletviewer, and next"
+ +nl+
+ "Select either the Pass or Fail button below";
+
+
+ public static void main(String args[]) {
+ Frame f = new Frame("Test Execution Instructions");
+ f.setLayout(new BorderLayout());
+ TextArea ta = new TextArea(instructions, 12,80);
+ ta.setEditable(false);
+ f.add(BorderLayout.CENTER, ta);
+ f.add(BorderLayout.SOUTH, new YesNo());
+ f.pack();
+ f.setVisible(true);
+ }
+
+ public YesNo() {
+ Button pass = new Button("Pass");
+ Button fail = new Button("Fail");
+ pass.addActionListener(this);
+ fail.addActionListener(this);
+ add(pass);
+ add(fail);
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ if (e.getActionCommand().equals("Pass")) {
+ System.exit(0);
+ } else {
+ System.exit(-1);
+ }
+ }
+
+}
diff --git a/test/javax/print/applet/applet0/Applet0.java b/test/javax/print/applet/applet0/Applet0.java
new file mode 100644
index 0000000..c0ddc0e
--- /dev/null
+++ b/test/javax/print/applet/applet0/Applet0.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2001 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import javax.print.*;
+import java.applet.*;
+import java.awt.*;
+
+public class Applet0 extends Applet {
+
+ String name = "Applet 0 ";
+ PrintService defServ = null;
+ PrintService[] allServices = null;
+ StreamPrintServiceFactory []fact = null;
+
+ public void init() {
+ defServ = PrintServiceLookup.lookupDefaultPrintService();
+
+ allServices = PrintServiceLookup.lookupPrintServices(null,null);
+
+ fact = StreamPrintServiceFactory.lookupStreamPrintServiceFactories(
+ DocFlavor.SERVICE_FORMATTED.PRINTABLE,
+ DocFlavor.BYTE_ARRAY.POSTSCRIPT.getMimeType());
+
+ }
+
+ public void paint(Graphics g) {
+ g.drawString("This is " + name, 10, 20);
+ g.drawString("Default print service="+defServ,10,40);
+ g.drawString("Number of print services="+allServices.length,10,60);
+ g.drawString("Number of PS stream services="+fact.length,10,80);
+ int y=100;
+ for (int i=0;i<allServices.length;i++) {
+ if (allServices[i].getName().startsWith("Applet ")) {
+ g.drawString("Found service : "+allServices[i].getName(),10,y);
+ y+=20;
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ Applet0 applet = new Applet0();
+ applet.init();
+ Frame f = new Frame("Print Lookup Test");
+ f.add(applet);
+ f.setSize(300,200);
+ f.show();
+ }
+
+}
diff --git a/test/javax/print/applet/applet1/Applet1.java b/test/javax/print/applet/applet1/Applet1.java
new file mode 100644
index 0000000..84828e8
--- /dev/null
+++ b/test/javax/print/applet/applet1/Applet1.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2001 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import javax.print.*;
+import java.applet.*;
+import java.awt.*;
+
+public class Applet1 extends Applet {
+
+ String name = "Applet 1 ";
+ PrintService defServ = null;
+ PrintService[] allServices = null;
+ StreamPrintServiceFactory []fact = null;
+
+ public void init() {
+ defServ = PrintServiceLookup.lookupDefaultPrintService();
+
+ allServices = PrintServiceLookup.lookupPrintServices(null,null);
+
+ fact = StreamPrintServiceFactory.lookupStreamPrintServiceFactories(
+ DocFlavor.SERVICE_FORMATTED.PRINTABLE,
+ DocFlavor.BYTE_ARRAY.POSTSCRIPT.getMimeType());
+ }
+
+ public void paint(Graphics g) {
+ g.drawString("This is " + name, 10, 20);
+ g.drawString("Default print service="+defServ,10,40);
+ g.drawString("Number of print services="+allServices.length,10,60);
+ g.drawString("Number of PS stream services="+fact.length,10,80);
+ int y=100;
+ for (int i=0;i<allServices.length;i++) {
+ if (allServices[i] instanceof Applet1PrintService ||
+ allServices[i].getName().startsWith("Applet ")) {
+ g.drawString("Found service : "+allServices[i].getName(),10,y);
+ y+=20;
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ Applet1 applet = new Applet1();
+ applet.init();
+ Frame f = new Frame("Print Lookup Test");
+ f.add(applet);
+ f.setSize(300,200);
+ f.show();
+ }
+
+
+}
diff --git a/test/javax/print/applet/applet1/Applet1PrintService.java b/test/javax/print/applet/applet1/Applet1PrintService.java
new file mode 100644
index 0000000..682d7db
--- /dev/null
+++ b/test/javax/print/applet/applet1/Applet1PrintService.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2001 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import javax.print.*;
+import javax.print.attribute.*;
+import javax.print.event.*;
+
+public class Applet1PrintService implements PrintService {
+
+
+ public Applet1PrintService() {
+ }
+
+ public String getName() {
+ return "Applet 1 Printer";
+ }
+
+ public DocPrintJob createPrintJob() {
+ return null;
+ }
+
+ public PrintServiceAttributeSet getUpdatedAttributes() {
+ return null;
+ }
+
+ public void addPrintServiceAttributeListener(
+ PrintServiceAttributeListener listener) {
+ return;
+ }
+
+ public void removePrintServiceAttributeListener(
+ PrintServiceAttributeListener listener) {
+ return;
+ }
+
+ public PrintServiceAttribute getAttribute(Class category) {
+ return null;
+ }
+
+ public PrintServiceAttributeSet getAttributes() {
+ return null;
+ }
+
+ public DocFlavor[] getSupportedDocFlavors() {
+ return null;
+ }
+
+ public boolean isDocFlavorSupported(DocFlavor flavor) {
+ return false;
+ }
+
+ public Class[] getSupportedAttributeCategories() {
+ return null;
+ }
+
+ public boolean isAttributeCategorySupported(Class category) {
+ return false;
+ }
+
+ public Object getDefaultAttributeValue(Class category) {
+ return null;
+ }
+
+ public Object getSupportedAttributeValues(Class category,
+ DocFlavor flavor,
+ AttributeSet attributes) {
+ return null;
+ }
+
+ public boolean isAttributeValueSupported(Attribute attr,
+ DocFlavor flavor,
+ AttributeSet attributes) {
+ return false;
+ }
+
+ public AttributeSet getUnsupportedAttributes(DocFlavor flavor,
+ AttributeSet attributes) {
+
+ return null;
+ }
+ public ServiceUIFactory getServiceUIFactory() {
+ return null;
+ }
+
+ public String toString() {
+ return "Printer : " + getName();
+ }
+
+ public boolean equals(Object obj) {
+ return (obj == this ||
+ (obj instanceof Applet1PrintService &&
+ ((Applet1PrintService)obj).getName().equals(getName())));
+ }
+
+ public int hashCode() {
+ return this.getClass().hashCode()+getName().hashCode();
+ }
+
+}
diff --git a/test/javax/print/applet/applet1/Applet1PrintServiceLookup.java b/test/javax/print/applet/applet1/Applet1PrintServiceLookup.java
new file mode 100644
index 0000000..79379ca
--- /dev/null
+++ b/test/javax/print/applet/applet1/Applet1PrintServiceLookup.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2001 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import javax.print.*;
+import javax.print.attribute.*;
+
+public class Applet1PrintServiceLookup extends PrintServiceLookup {
+ PrintService defaultPrintService = null;
+
+ public synchronized PrintService[] getPrintServices() {
+ PrintService []printServices = new PrintService[1];
+ printServices[0] = getDefaultPrintService();
+ return printServices;
+ }
+
+ public PrintService[] getPrintServices(DocFlavor flavor,
+ AttributeSet attributes) {
+
+ return getPrintServices();
+ }
+
+ public MultiDocPrintService[]
+ getMultiDocPrintServices(DocFlavor[] flavors,
+ AttributeSet attributes) {
+
+ return new MultiDocPrintService[0];
+ }
+
+
+ public synchronized PrintService getDefaultPrintService() {
+ if (defaultPrintService == null) {
+ defaultPrintService = new Applet1PrintService();
+ }
+ return defaultPrintService;
+ }
+}
diff --git a/test/javax/print/applet/applet1/META-INF/services/javax.print.PrintServiceLookup b/test/javax/print/applet/applet1/META-INF/services/javax.print.PrintServiceLookup
new file mode 100644
index 0000000..6c328d1
--- /dev/null
+++ b/test/javax/print/applet/applet1/META-INF/services/javax.print.PrintServiceLookup
@@ -0,0 +1 @@
+Applet1PrintServiceLookup
diff --git a/test/javax/print/applet/applet2/Applet2.java b/test/javax/print/applet/applet2/Applet2.java
new file mode 100644
index 0000000..fbcd8c7
--- /dev/null
+++ b/test/javax/print/applet/applet2/Applet2.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2001 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import javax.print.*;
+import java.applet.*;
+import java.awt.*;
+
+public class Applet2 extends Applet {
+
+ String name = "Applet 2 ";
+ PrintService defServ = null;
+ PrintService[] allServices = null;
+ StreamPrintServiceFactory []fact = null;
+
+ public void init() {
+ defServ = PrintServiceLookup.lookupDefaultPrintService();
+
+ allServices = PrintServiceLookup.lookupPrintServices(null,null);
+
+ fact = StreamPrintServiceFactory.lookupStreamPrintServiceFactories(
+ DocFlavor.SERVICE_FORMATTED.PRINTABLE,
+ DocFlavor.BYTE_ARRAY.POSTSCRIPT.getMimeType());
+
+ }
+
+ public void paint(Graphics g) {
+ g.drawString("This is " + name, 10, 20);
+ g.drawString("Default print service="+defServ,10,40);
+ g.drawString("Number of print services="+allServices.length,10,60);
+ g.drawString("Number of PS stream services="+fact.length,10,80);
+ int y=100;
+ for (int i=0;i<allServices.length;i++) {
+ if (allServices[i] instanceof Applet2PrintService ||
+ allServices[i].getName().startsWith("Applet ")) {
+ g.drawString("Found service : "+allServices[i].getName(),10,y);
+ y+=20;
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ Applet2 applet = new Applet2();
+ applet.init();
+ Frame f = new Frame("Print Lookup Test");
+ f.add(applet);
+ f.setSize(300,200);
+ f.show();
+ }
+
+
+}
diff --git a/test/javax/print/applet/applet2/Applet2PrintService.java b/test/javax/print/applet/applet2/Applet2PrintService.java
new file mode 100644
index 0000000..84296d1
--- /dev/null
+++ b/test/javax/print/applet/applet2/Applet2PrintService.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2001 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import javax.print.*;
+import javax.print.attribute.*;
+import javax.print.event.*;
+
+public class Applet2PrintService implements PrintService {
+
+
+ public Applet2PrintService() {
+ }
+
+ public String getName() {
+ return "Applet 2 Printer";
+ }
+
+ public DocPrintJob createPrintJob() {
+ return null;
+ }
+
+ public PrintServiceAttributeSet getUpdatedAttributes() {
+ return null;
+ }
+
+ public void addPrintServiceAttributeListener(
+ PrintServiceAttributeListener listener) {
+ return;
+ }
+
+ public void removePrintServiceAttributeListener(
+ PrintServiceAttributeListener listener) {
+ return;
+ }
+
+ public PrintServiceAttribute getAttribute(Class category) {
+ return null;
+ }
+
+ public PrintServiceAttributeSet getAttributes() {
+ return null;
+ }
+
+ public DocFlavor[] getSupportedDocFlavors() {
+ return null;
+ }
+
+ public boolean isDocFlavorSupported(DocFlavor flavor) {
+ return false;
+ }
+
+ public Class[] getSupportedAttributeCategories() {
+ return null;
+ }
+
+ public boolean isAttributeCategorySupported(Class category) {
+ return false;
+ }
+
+ public Object getDefaultAttributeValue(Class category) {
+ return null;
+ }
+
+ public Object getSupportedAttributeValues(Class category,
+ DocFlavor flavor,
+ AttributeSet attributes) {
+ return null;
+ }
+
+ public boolean isAttributeValueSupported(Attribute attr,
+ DocFlavor flavor,
+ AttributeSet attributes) {
+ return false;
+ }
+
+ public AttributeSet getUnsupportedAttributes(DocFlavor flavor,
+ AttributeSet attributes) {
+
+ return null;
+ }
+ public ServiceUIFactory getServiceUIFactory() {
+ return null;
+ }
+
+ public String toString() {
+ return "Printer : " + getName();
+ }
+
+ public boolean equals(Object obj) {
+ return (obj == this ||
+ (obj instanceof Applet2PrintService &&
+ ((Applet2PrintService)obj).getName().equals(getName())));
+ }
+
+ public int hashCode() {
+ return this.getClass().hashCode()+getName().hashCode();
+ }
+
+}
diff --git a/test/javax/print/applet/applet2/Applet2PrintServiceLookup.java b/test/javax/print/applet/applet2/Applet2PrintServiceLookup.java
new file mode 100644
index 0000000..dc940ed
--- /dev/null
+++ b/test/javax/print/applet/applet2/Applet2PrintServiceLookup.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2001 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import javax.print.*;
+import javax.print.attribute.*;
+
+public class Applet2PrintServiceLookup extends PrintServiceLookup {
+ PrintService defaultPrintService = null;
+
+ public synchronized PrintService[] getPrintServices() {
+ PrintService []printServices = new PrintService[1];
+ printServices[0] = getDefaultPrintService();
+ return printServices;
+ }
+
+ public PrintService[] getPrintServices(DocFlavor flavor,
+ AttributeSet attributes) {
+
+ return getPrintServices();
+ }
+
+ public MultiDocPrintService[]
+ getMultiDocPrintServices(DocFlavor[] flavors,
+ AttributeSet attributes) {
+
+ return new MultiDocPrintService[0];
+ }
+
+
+ public synchronized PrintService getDefaultPrintService() {
+ if (defaultPrintService == null) {
+ defaultPrintService = new Applet2PrintService();
+ }
+ return defaultPrintService;
+ }
+}
diff --git a/test/javax/print/applet/applet2/META-INF/services/javax.print.PrintServiceLookup b/test/javax/print/applet/applet2/META-INF/services/javax.print.PrintServiceLookup
new file mode 100644
index 0000000..9110e6a
--- /dev/null
+++ b/test/javax/print/applet/applet2/META-INF/services/javax.print.PrintServiceLookup
@@ -0,0 +1 @@
+Applet2PrintServiceLookup
diff --git a/test/javax/print/applet/applet3/Applet3.java b/test/javax/print/applet/applet3/Applet3.java
new file mode 100644
index 0000000..ab8b19f
--- /dev/null
+++ b/test/javax/print/applet/applet3/Applet3.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2001 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import javax.print.*;
+import java.applet.*;
+import java.awt.*;
+
+public class Applet3 extends Applet {
+
+ String name = "Applet 3 ";
+ PrintService defServ = null;
+ PrintService[] allServices = null;
+ StreamPrintServiceFactory []fact = null;
+
+ public void init() {
+ PrintServiceLookup.registerService(new Applet3PrintService());
+ defServ = PrintServiceLookup.lookupDefaultPrintService();
+
+ allServices = PrintServiceLookup.lookupPrintServices(null,null);
+
+ fact = StreamPrintServiceFactory.lookupStreamPrintServiceFactories(
+ DocFlavor.SERVICE_FORMATTED.PRINTABLE,
+ DocFlavor.BYTE_ARRAY.POSTSCRIPT.getMimeType());
+
+ }
+
+ public void paint(Graphics g) {
+ g.drawString("This is " + name, 10, 20);
+ g.drawString("Default print service="+defServ,10,40);
+ g.drawString("Number of print services="+allServices.length,10,60);
+ g.drawString("Number of PS stream services="+fact.length,10,80);
+ int y=100;
+ for (int i=0;i<allServices.length;i++) {
+ if (allServices[i].getName().startsWith("Applet ")) {
+ g.drawString("Found service : "+allServices[i].getName(),10,y);
+ y+=20;
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ Applet3 applet = new Applet3();
+ applet.init();
+ Frame f = new Frame("Print Lookup Test");
+ f.add(applet);
+ f.setSize(300,200);
+ f.show();
+ }
+
+
+}
diff --git a/test/javax/print/applet/applet3/Applet3PrintService.java b/test/javax/print/applet/applet3/Applet3PrintService.java
new file mode 100644
index 0000000..818ff0d
--- /dev/null
+++ b/test/javax/print/applet/applet3/Applet3PrintService.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2001 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import javax.print.*;
+import javax.print.attribute.*;
+import javax.print.event.*;
+
+public class Applet3PrintService implements PrintService {
+
+
+ public Applet3PrintService() {
+ }
+
+ public String getName() {
+ return "Applet 3 Printer";
+ }
+
+ public DocPrintJob createPrintJob() {
+ return null;
+ }
+
+ public PrintServiceAttributeSet getUpdatedAttributes() {
+ return null;
+ }
+
+ public void addPrintServiceAttributeListener(
+ PrintServiceAttributeListener listener) {
+ return;
+ }
+
+ public void removePrintServiceAttributeListener(
+ PrintServiceAttributeListener listener) {
+ return;
+ }
+
+ public PrintServiceAttribute getAttribute(Class category) {
+ return null;
+ }
+
+ public PrintServiceAttributeSet getAttributes() {
+ return null;
+ }
+
+ public DocFlavor[] getSupportedDocFlavors() {
+ return null;
+ }
+
+ public boolean isDocFlavorSupported(DocFlavor flavor) {
+ return false;
+ }
+
+ public Class[] getSupportedAttributeCategories() {
+ return null;
+ }
+
+ public boolean isAttributeCategorySupported(Class category) {
+ return false;
+ }
+
+ public Object getDefaultAttributeValue(Class category) {
+ return null;
+ }
+
+ public Object getSupportedAttributeValues(Class category,
+ DocFlavor flavor,
+ AttributeSet attributes) {
+ return null;
+ }
+
+ public boolean isAttributeValueSupported(Attribute attr,
+ DocFlavor flavor,
+ AttributeSet attributes) {
+ return false;
+ }
+
+ public AttributeSet getUnsupportedAttributes(DocFlavor flavor,
+ AttributeSet attributes) {
+
+ return null;
+ }
+ public ServiceUIFactory getServiceUIFactory() {
+ return null;
+ }
+
+ public String toString() {
+ return "Printer : " + getName();
+ }
+
+ public boolean equals(Object obj) {
+ return (obj == this ||
+ (obj instanceof Applet3PrintService &&
+ ((Applet3PrintService)obj).getName().equals(getName())));
+ }
+
+ public int hashCode() {
+ return this.getClass().hashCode()+getName().hashCode();
+ }
+
+}
diff --git a/test/javax/print/applet/applet4/Applet4.java b/test/javax/print/applet/applet4/Applet4.java
new file mode 100644
index 0000000..afa20f2
--- /dev/null
+++ b/test/javax/print/applet/applet4/Applet4.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2001 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import javax.print.*;
+import java.applet.*;
+import java.awt.*;
+
+public class Applet4 extends Applet {
+
+ String name = "Applet 4 ";
+ PrintService defServ = null;
+ PrintService[] allServices = null;
+ StreamPrintServiceFactory []fact = null;
+
+ public void init() {
+ PrintServiceLookup psl = new Applet4PrintServiceLookup();
+ PrintServiceLookup.registerServiceProvider(psl);
+ defServ = PrintServiceLookup.lookupDefaultPrintService();
+
+ allServices = PrintServiceLookup.lookupPrintServices(null,null);
+
+ fact = StreamPrintServiceFactory.lookupStreamPrintServiceFactories(
+ DocFlavor.SERVICE_FORMATTED.PRINTABLE,
+ DocFlavor.BYTE_ARRAY.POSTSCRIPT.getMimeType());
+ }
+
+ public void paint(Graphics g) {
+ g.drawString("This is " + name, 10, 20);
+ g.drawString("Default print service="+defServ,10,40);
+ g.drawString("Number of print services="+allServices.length,10,60);
+ g.drawString("Number of PS stream services="+fact.length,10,80);
+ int y=100;
+ for (int i=0;i<allServices.length;i++) {
+ if (allServices[i] instanceof Applet4PrintService ||
+ allServices[i].getName().startsWith("Applet ")) {
+ g.drawString("Found service : "+allServices[i].getName(),10,y);
+ y+=20;
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ Applet4 applet = new Applet4();
+ applet.init();
+ Frame f = new Frame("Print Lookup Test");
+ f.add(applet);
+ f.setSize(300,200);
+ f.show();
+ }
+
+
+}
diff --git a/test/javax/print/applet/applet4/Applet4PrintService.java b/test/javax/print/applet/applet4/Applet4PrintService.java
new file mode 100644
index 0000000..7453db6
--- /dev/null
+++ b/test/javax/print/applet/applet4/Applet4PrintService.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2001 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import javax.print.*;
+import javax.print.attribute.*;
+import javax.print.event.*;
+
+public class Applet4PrintService implements PrintService {
+
+
+ public Applet4PrintService() {
+ }
+
+ public String getName() {
+ return "Applet 4 Printer";
+ }
+
+ public DocPrintJob createPrintJob() {
+ return null;
+ }
+
+ public PrintServiceAttributeSet getUpdatedAttributes() {
+ return null;
+ }
+
+ public void addPrintServiceAttributeListener(
+ PrintServiceAttributeListener listener) {
+ return;
+ }
+
+ public void removePrintServiceAttributeListener(
+ PrintServiceAttributeListener listener) {
+ return;
+ }
+
+ public PrintServiceAttribute getAttribute(Class category) {
+ return null;
+ }
+
+ public PrintServiceAttributeSet getAttributes() {
+ return null;
+ }
+
+ public DocFlavor[] getSupportedDocFlavors() {
+ return null;
+ }
+
+ public boolean isDocFlavorSupported(DocFlavor flavor) {
+ return false;
+ }
+
+ public Class[] getSupportedAttributeCategories() {
+ return null;
+ }
+
+ public boolean isAttributeCategorySupported(Class category) {
+ return false;
+ }
+
+ public Object getDefaultAttributeValue(Class category) {
+ return null;
+ }
+
+ public Object getSupportedAttributeValues(Class category,
+ DocFlavor flavor,
+ AttributeSet attributes) {
+ return null;
+ }
+
+ public boolean isAttributeValueSupported(Attribute attr,
+ DocFlavor flavor,
+ AttributeSet attributes) {
+ return false;
+ }
+
+ public AttributeSet getUnsupportedAttributes(DocFlavor flavor,
+ AttributeSet attributes) {
+
+ return null;
+ }
+ public ServiceUIFactory getServiceUIFactory() {
+ return null;
+ }
+
+ public String toString() {
+ return "Printer : " + getName();
+ }
+
+ public boolean equals(Object obj) {
+ return (obj == this ||
+ (obj instanceof Applet4PrintService &&
+ ((Applet4PrintService)obj).getName().equals(getName())));
+ }
+
+ public int hashCode() {
+ return this.getClass().hashCode()+getName().hashCode();
+ }
+
+}
diff --git a/test/javax/print/applet/applet4/Applet4PrintServiceLookup.java b/test/javax/print/applet/applet4/Applet4PrintServiceLookup.java
new file mode 100644
index 0000000..cd64478
--- /dev/null
+++ b/test/javax/print/applet/applet4/Applet4PrintServiceLookup.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2001 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import javax.print.*;
+import javax.print.attribute.*;
+
+public class Applet4PrintServiceLookup extends PrintServiceLookup {
+ PrintService defaultPrintService = null;
+
+ public synchronized PrintService[] getPrintServices() {
+ PrintService []printServices = new PrintService[1];
+ printServices[0] = getDefaultPrintService();
+ return printServices;
+ }
+
+ public PrintService[] getPrintServices(DocFlavor flavor,
+ AttributeSet attributes) {
+
+ return getPrintServices();
+ }
+
+ public MultiDocPrintService[]
+ getMultiDocPrintServices(DocFlavor[] flavors,
+ AttributeSet attributes) {
+
+ return new MultiDocPrintService[0];
+ }
+
+
+ public synchronized PrintService getDefaultPrintService() {
+ if (defaultPrintService == null) {
+ defaultPrintService = new Applet4PrintService();
+ }
+ return defaultPrintService;
+ }
+}
diff --git a/test/javax/print/attribute/CollateAttr.java b/test/javax/print/attribute/CollateAttr.java
new file mode 100644
index 0000000..68e14a6
--- /dev/null
+++ b/test/javax/print/attribute/CollateAttr.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6574117
+ * @summary Verify no NPE testing service support of SheetCollate
+ * @run main CollateAttr
+ */
+
+import javax.print.*;
+import javax.print.attribute.*;
+import javax.print.attribute.standard.*;
+
+public class CollateAttr {
+
+ public static void main(String args[]) throws Exception {
+
+ PrintService[] services =
+ PrintServiceLookup.lookupPrintServices(null,null);
+ for (int i=0; i<services.length; i++) {
+ if (services[i].isAttributeCategorySupported(SheetCollate.class)) {
+ System.out.println("Testing " + services[i]);
+ services[i].isAttributeValueSupported(SheetCollate.COLLATED,
+ null, null);
+ services[i].getSupportedAttributeValues(SheetCollate.class,
+ null,null);
+ }
+ }
+ }
+}
diff --git a/test/javax/print/attribute/PSCopiesFlavorTest.java b/test/javax/print/attribute/PSCopiesFlavorTest.java
new file mode 100644
index 0000000..f4dc8ca
--- /dev/null
+++ b/test/javax/print/attribute/PSCopiesFlavorTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6527316
+ * @summary Copies isn't supported for PS flavors.
+ * @run main PSCopiesFlavorTest
+ */
+
+import javax.print.*;
+import javax.print.attribute.*;
+import javax.print.attribute.standard.*;
+
+public class PSCopiesFlavorTest {
+
+ public static void main(String args[]) {
+
+ DocFlavor flavor = DocFlavor.INPUT_STREAM.POSTSCRIPT;
+ PrintService ps = PrintServiceLookup.lookupDefaultPrintService();
+ if (!(ps.isDocFlavorSupported(flavor))) {
+ System.out.println("unsupported flavor :" + flavor);
+ return;
+ }
+ Copies c = new Copies(1);
+ PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
+ aset.add(c);
+ boolean suppVal = ps.isAttributeValueSupported(c, flavor, null);
+ AttributeSet us = ps.getUnsupportedAttributes(flavor, aset);
+ if (suppVal || us == null) {
+ throw new RuntimeException("Copies should be unsupported value");
+ }
+ }
+}
diff --git a/test/javax/rmi/ssl/SSLSocketParametersTest.java b/test/javax/rmi/ssl/SSLSocketParametersTest.java
new file mode 100644
index 0000000..fcc61de
--- /dev/null
+++ b/test/javax/rmi/ssl/SSLSocketParametersTest.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright 2004-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import java.io.IOException;
+import java.io.File;
+import java.io.Serializable;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+import java.rmi.server.UnicastRemoteObject;
+import javax.net.ssl.SSLContext;
+import javax.rmi.ssl.SslRMIClientSocketFactory;
+import javax.rmi.ssl.SslRMIServerSocketFactory;
+
+public class SSLSocketParametersTest implements Serializable {
+
+ public interface Hello extends Remote {
+ public String sayHello() throws RemoteException;
+ }
+
+ public class HelloImpl extends UnicastRemoteObject implements Hello {
+
+ public HelloImpl(int port,
+ RMIClientSocketFactory csf,
+ RMIServerSocketFactory ssf)
+ throws RemoteException {
+ super(port, csf, ssf);
+ }
+
+ public String sayHello() {
+ return "Hello World!";
+ }
+
+ public Remote runServer() throws IOException {
+ System.out.println("Inside HelloImpl::runServer");
+ // Get a remote stub for this RMI object
+ //
+ Remote stub = toStub(this);
+ System.out.println("Stub = " + stub);
+ return stub;
+ }
+ }
+
+ public class HelloClient {
+
+ public void runClient(Remote stub) throws IOException {
+ System.out.println("Inside HelloClient::runClient");
+ // "obj" is the identifier that we'll use to refer
+ // to the remote object that implements the "Hello"
+ // interface
+ Hello obj = (Hello) stub;
+ String message = obj.sayHello();
+ System.out.println(message);
+ }
+ }
+
+ public class ClientFactory extends SslRMIClientSocketFactory {
+
+ public ClientFactory() {
+ super();
+ }
+
+ public Socket createSocket(String host, int port) throws IOException {
+ System.out.println("ClientFactory::Calling createSocket(" +
+ host + "," + port + ")");
+ return super.createSocket(host, port);
+ }
+ }
+
+ public class ServerFactory extends SslRMIServerSocketFactory {
+
+ public ServerFactory() {
+ super();
+ }
+
+ public ServerFactory(String[] ciphers,
+ String[] protocols,
+ boolean need) {
+ super(ciphers, protocols, need);
+ }
+
+ public ServerFactory(SSLContext context,
+ String[] ciphers,
+ String[] protocols,
+ boolean need) {
+ super(context, ciphers, protocols, need);
+ }
+
+ public ServerSocket createServerSocket(int port) throws IOException {
+ System.out.println("ServerFactory::Calling createServerSocket(" +
+ port + ")");
+ return super.createServerSocket(port);
+ }
+ }
+
+ public void runTest(String[] args) {
+
+ int test = Integer.parseInt(args[0]);
+
+ String msg1 = "Running SSLSocketParametersTest [" + test + "]";
+ String msg2 = "SSLSocketParametersTest [" + test + "] PASSED!";
+ String msg3 = "SSLSocketParametersTest [" + test + "] FAILED!";
+
+ switch (test) {
+ case 1: /* default constructor - default config */
+ System.out.println(msg1);
+ try {
+ HelloImpl server = new HelloImpl(
+ 0,
+ new ClientFactory(),
+ new ServerFactory());
+ Remote stub = server.runServer();
+ HelloClient client = new HelloClient();
+ client.runClient(stub);
+ System.out.println(msg2);
+ } catch (Exception e) {
+ System.out.println(msg3 + " Exception: " + e.toString());
+ e.printStackTrace(System.out);
+ System.exit(1);
+ }
+ break;
+ case 2: /* non-default constructor - default config */
+ System.out.println(msg1);
+ try {
+ HelloImpl server = new HelloImpl(
+ 0,
+ new ClientFactory(),
+ new ServerFactory(null,
+ null,
+ false));
+ Remote stub = server.runServer();
+ HelloClient client = new HelloClient();
+ client.runClient(stub);
+ System.out.println(msg2);
+ } catch (Exception e) {
+ System.out.println(msg3 + " Exception: " + e.toString());
+ e.printStackTrace(System.out);
+ System.exit(1);
+ }
+ break;
+ case 3: /* needClientAuth=true */
+ System.out.println(msg1);
+ try {
+ HelloImpl server = new HelloImpl(
+ 0,
+ new ClientFactory(),
+ new ServerFactory(null,
+ null,
+ null,
+ true));
+ Remote stub = server.runServer();
+ HelloClient client = new HelloClient();
+ client.runClient(stub);
+ System.out.println(msg2);
+ } catch (Exception e) {
+ System.out.println(msg3 + " Exception: " + e.toString());
+ e.printStackTrace(System.out);
+ System.exit(1);
+ }
+ break;
+ case 4: /* server side dummy_ciphersuite */
+ System.out.println(msg1);
+ try {
+ HelloImpl server = new HelloImpl(
+ 0,
+ new ClientFactory(),
+ new ServerFactory(SSLContext.getDefault(),
+ new String[] {"dummy_ciphersuite"},
+ null,
+ false));
+ Remote stub = server.runServer();
+ HelloClient client = new HelloClient();
+ client.runClient(stub);
+ System.out.println(msg3);
+ System.exit(1);
+ } catch (Exception e) {
+ System.out.println(msg2 + " Exception: " + e.toString());
+ System.exit(0);
+ }
+ break;
+ case 5: /* server side dummy_protocol */
+ System.out.println(msg1);
+ try {
+ HelloImpl server = new HelloImpl(
+ 0,
+ new ClientFactory(),
+ new ServerFactory(null,
+ new String[] {"dummy_protocol"},
+ false));
+ Remote stub = server.runServer();
+ HelloClient client = new HelloClient();
+ client.runClient(stub);
+ System.out.println(msg3);
+ System.exit(1);
+ } catch (Exception e) {
+ System.out.println(msg2 + " Exception: " + e.toString());
+ System.exit(0);
+ }
+ break;
+ case 6: /* client side dummy_ciphersuite */
+ System.out.println(msg1);
+ try {
+ System.setProperty("javax.rmi.ssl.client.enabledCipherSuites",
+ "dummy_ciphersuite");
+ HelloImpl server = new HelloImpl(
+ 0,
+ new ClientFactory(),
+ new ServerFactory());
+ Remote stub = server.runServer();
+ HelloClient client = new HelloClient();
+ client.runClient(stub);
+ System.out.println(msg3);
+ System.exit(1);
+ } catch (Exception e) {
+ System.out.println(msg2 + " Exception: " + e.toString());
+ System.exit(0);
+ }
+ break;
+ case 7: /* client side dummy_protocol */
+ System.out.println(msg1);
+ try {
+ System.setProperty("javax.rmi.ssl.client.enabledProtocols",
+ "dummy_protocol");
+ HelloImpl server = new HelloImpl(
+ 0,
+ new ClientFactory(),
+ new ServerFactory());
+ Remote stub = server.runServer();
+ HelloClient client = new HelloClient();
+ client.runClient(stub);
+ System.out.println(msg3);
+ System.exit(1);
+ } catch (Exception e) {
+ System.out.println(msg2 + " Exception: " + e.toString());
+ System.exit(0);
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("invalid test number");
+ }
+ }
+
+ public static void main(String[] args) {
+ // Set keystore properties (server-side)
+ //
+ final String keystore = System.getProperty("test.src") +
+ File.separator + "keystore";
+ System.out.println("KeyStore = " + keystore);
+ System.setProperty("javax.net.ssl.keyStore", keystore);
+ System.setProperty("javax.net.ssl.keyStorePassword", "password");
+
+ // Set truststore properties (client-side)
+ //
+ final String truststore = System.getProperty("test.src") +
+ File.separator + "truststore";
+ System.out.println("TrustStore = " + truststore);
+ System.setProperty("javax.net.ssl.trustStore", truststore);
+ System.setProperty("javax.net.ssl.trustStorePassword", "trustword");
+
+ // Run test
+ //
+ SSLSocketParametersTest test = new SSLSocketParametersTest();
+ test.runTest(args);
+ System.exit(0);
+ }
+}
diff --git a/test/javax/rmi/ssl/SSLSocketParametersTest.sh b/test/javax/rmi/ssl/SSLSocketParametersTest.sh
new file mode 100644
index 0000000..7bb7f3b
--- /dev/null
+++ b/test/javax/rmi/ssl/SSLSocketParametersTest.sh
@@ -0,0 +1,56 @@
+#
+# Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+#
+# @test
+# @bug 5016500
+# @summary Test SslRmi[Client|Server]SocketFactory SSL socket parameters.
+# @author Luis-Miguel Alventosa
+# @run clean SSLSocketParametersTest
+# @run build SSLSocketParametersTest
+# @run shell/timeout=300 SSLSocketParametersTest.sh
+
+echo -------------------------------------------------------------
+echo Launching test for `basename $0 .sh`
+echo -------------------------------------------------------------
+
+# case 1: /* default constructor - default config */
+${TESTJAVA}/bin/java ${TESTVMOPTS} -classpath ${TESTCLASSES} -Dtest.src=${TESTSRC} SSLSocketParametersTest 1 || exit $?
+
+# case 2: /* non-default constructor - default config */
+${TESTJAVA}/bin/java ${TESTVMOPTS} -classpath ${TESTCLASSES} -Dtest.src=${TESTSRC} SSLSocketParametersTest 2 || exit $?
+
+# case 3: /* needClientAuth=true */
+${TESTJAVA}/bin/java ${TESTVMOPTS} -classpath ${TESTCLASSES} -Dtest.src=${TESTSRC} SSLSocketParametersTest 3 || exit $?
+
+# case 4: /* server side dummy_ciphersuite */
+${TESTJAVA}/bin/java ${TESTVMOPTS} -classpath ${TESTCLASSES} -Dtest.src=${TESTSRC} SSLSocketParametersTest 4 || exit $?
+
+# case 5: /* server side dummy_protocol */
+${TESTJAVA}/bin/java ${TESTVMOPTS} -classpath ${TESTCLASSES} -Dtest.src=${TESTSRC} SSLSocketParametersTest 5 || exit $?
+
+# case 6: /* client side dummy_ciphersuite */
+${TESTJAVA}/bin/java ${TESTVMOPTS} -classpath ${TESTCLASSES} -Dtest.src=${TESTSRC} SSLSocketParametersTest 6 || exit $?
+
+# case 7: /* client side dummy_protocol */
+${TESTJAVA}/bin/java ${TESTVMOPTS} -classpath ${TESTCLASSES} -Dtest.src=${TESTSRC} SSLSocketParametersTest 7 || exit $?
diff --git a/test/javax/rmi/ssl/SocketFactoryTest.java b/test/javax/rmi/ssl/SocketFactoryTest.java
new file mode 100644
index 0000000..7e39f29
--- /dev/null
+++ b/test/javax/rmi/ssl/SocketFactoryTest.java
@@ -0,0 +1,355 @@
+/*
+ * Copyright 2003-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4932837 6582235
+ * @summary Test SslRMI[Client|Server]SocketFactory equals() and hashCode().
+ * @author Daniel Fuchs
+ * @run clean SocketFactoryTest
+ * @run build SocketFactoryTest
+ * @run main SocketFactoryTest
+ */
+
+import java.io.PrintWriter;
+import java.io.IOException;
+import java.io.Serializable;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.Map;
+import java.util.HashMap;
+import javax.net.ssl.SSLContext;
+import javax.rmi.ssl.SslRMIClientSocketFactory;
+import javax.rmi.ssl.SslRMIServerSocketFactory;
+
+public class SocketFactoryTest {
+
+ public static final String[] ciphersuite =
+ new String[] { "SSL_RSA_WITH_NULL_MD5" };
+
+ public static final String[] protocol =
+ new String[] { "TLSv1" };
+
+ public static class MySslRMIClientSocketFactory
+ extends SslRMIClientSocketFactory {
+ }
+
+ public static class MySslRMIServerSocketFactory
+ extends SslRMIServerSocketFactory {
+ public MySslRMIServerSocketFactory() {
+ super();
+ }
+ public MySslRMIServerSocketFactory(String[] ciphers,
+ String[] protocols,
+ boolean need) {
+ super(ciphers, protocols, need);
+ }
+ public MySslRMIServerSocketFactory(SSLContext context,
+ String[] ciphers,
+ String[] protocols,
+ boolean need) {
+ super(context, ciphers, protocols, need);
+ }
+ }
+
+ public static Object serializeAndClone(Object o) throws Exception {
+ System.out.println("Serializing object: " + o);
+ final ByteArrayOutputStream obytes =
+ new ByteArrayOutputStream();
+ final ObjectOutputStream ostr =
+ new ObjectOutputStream(obytes);
+ ostr.writeObject(o);
+ ostr.flush();
+
+ System.out.println("Deserializing object");
+ final ByteArrayInputStream ibytes =
+ new ByteArrayInputStream(obytes.toByteArray());
+ final ObjectInputStream istr =
+ new ObjectInputStream(ibytes);
+ return istr.readObject();
+ }
+
+ public static void testEquals(Object a, Object b, boolean expected) {
+ final boolean found = a.equals(b);
+ if (found != expected)
+ throw new RuntimeException("testEquals failed: objects are " +
+ ((found)?"equals":"not equals"));
+ if (found && a.hashCode()!=b.hashCode())
+ throw new RuntimeException("testEquals failed: objects are " +
+ "equals but their hashcode differ");
+ }
+
+ public static void main(String[] args) {
+ try {
+ System.out.println("SocketFactoryTest START.");
+
+ final SSLContext context = SSLContext.getInstance("SSL");
+ context.init(null, null, null);
+
+ final SslRMIClientSocketFactory client1 =
+ new SslRMIClientSocketFactory();
+ final SslRMIClientSocketFactory client2 =
+ new SslRMIClientSocketFactory();
+ final SslRMIClientSocketFactory client11 =
+ (SslRMIClientSocketFactory) serializeAndClone(client1);
+ final SslRMIClientSocketFactory client21 =
+ (SslRMIClientSocketFactory) serializeAndClone(client2);
+ final SslRMIServerSocketFactory server1 =
+ new SslRMIServerSocketFactory();
+ final SslRMIServerSocketFactory server2 =
+ new SslRMIServerSocketFactory(null,
+ null,
+ false);
+ final SslRMIServerSocketFactory server3 =
+ new SslRMIServerSocketFactory(ciphersuite,
+ null,
+ false);
+ final SslRMIServerSocketFactory server4 =
+ new SslRMIServerSocketFactory(null,
+ protocol,
+ false);
+ final SslRMIServerSocketFactory server5 =
+ new SslRMIServerSocketFactory(null,
+ null,
+ true);
+ final SslRMIServerSocketFactory server6 =
+ new SslRMIServerSocketFactory(null,
+ null,
+ null,
+ false);
+ final SslRMIServerSocketFactory server7 =
+ new SslRMIServerSocketFactory(SSLContext.getDefault(),
+ null,
+ null,
+ false);
+ final SslRMIServerSocketFactory server8 =
+ new SslRMIServerSocketFactory(null,
+ null,
+ null,
+ true);
+ final SslRMIServerSocketFactory server9 =
+ new SslRMIServerSocketFactory(SSLContext.getDefault(),
+ null,
+ null,
+ true);
+ final SslRMIServerSocketFactory server10 =
+ new SslRMIServerSocketFactory(context,
+ null,
+ null,
+ true);
+ final MySslRMIClientSocketFactory subclient1 =
+ new MySslRMIClientSocketFactory();
+ final MySslRMIClientSocketFactory subclient2 =
+ new MySslRMIClientSocketFactory();
+ final MySslRMIServerSocketFactory subserver1 =
+ new MySslRMIServerSocketFactory();
+ final MySslRMIServerSocketFactory subserver2 =
+ new MySslRMIServerSocketFactory(null,
+ null,
+ false);
+ final MySslRMIServerSocketFactory subserver3 =
+ new MySslRMIServerSocketFactory(ciphersuite,
+ null,
+ false);
+ final MySslRMIServerSocketFactory subserver4 =
+ new MySslRMIServerSocketFactory(null,
+ protocol,
+ false);
+ final MySslRMIServerSocketFactory subserver5 =
+ new MySslRMIServerSocketFactory(null,
+ null,
+ true);
+ final MySslRMIServerSocketFactory subserver6 =
+ new MySslRMIServerSocketFactory(null,
+ ciphersuite,
+ null,
+ false);
+ final MySslRMIServerSocketFactory subserver7 =
+ new MySslRMIServerSocketFactory(SSLContext.getDefault(),
+ ciphersuite,
+ null,
+ false);
+ final MySslRMIServerSocketFactory subserver8 =
+ new MySslRMIServerSocketFactory(context,
+ null,
+ null,
+ true);
+
+ // clients
+ System.out.println("testEquals(client1,client1,true)");
+ testEquals(client1,client1,true);
+ System.out.println("testEquals(client1,client2,true)");
+ testEquals(client1,client2,true);
+ System.out.println("testEquals(client1,client11,true)");
+ testEquals(client1,client11,true);
+ System.out.println("testEquals(client1,client21,true)");
+ testEquals(client1,client21,true);
+ System.out.println("testEquals(client11,client21,true)");
+ testEquals(client11,client21,true);
+ System.out.println("testEquals(client1,null,false)");
+ testEquals(client1,null,false);
+ System.out.println("testEquals(client1,server1,false)");
+ testEquals(client1,server1,false);
+ System.out.println("testEquals(client21,server2,false)");
+ testEquals(client21,server2,false);
+ System.out.println("testEquals(client1,new Object(),false)");
+ testEquals(client1,new Object(),false);
+
+ // servers
+ System.out.println("testEquals(server1,server1,true)");
+ testEquals(server1,server1,true);
+ System.out.println("testEquals(server2,server2,true)");
+ testEquals(server2,server2,true);
+ System.out.println("testEquals(server3,server3,true)");
+ testEquals(server3,server3,true);
+ System.out.println("testEquals(server4,server4,true)");
+ testEquals(server4,server4,true);
+ System.out.println("testEquals(server5,server5,true)");
+ testEquals(server5,server5,true);
+ System.out.println("testEquals(server1,server2,true)");
+ testEquals(server1,server2,true);
+ System.out.println("testEquals(server1,server3,false)");
+ testEquals(server1,server3,false);
+ System.out.println("testEquals(server2,server3,false)");
+ testEquals(server2,server3,false);
+ System.out.println("testEquals(server3,server4,false)");
+ testEquals(server3,server4,false);
+ System.out.println("testEquals(server4,server5,false)");
+ testEquals(server4,server5,false);
+ System.out.println("testEquals(server6,server7,false)");
+ testEquals(server6,server7,false);
+ System.out.println("testEquals(server8,server9,false)");
+ testEquals(server8,server9,false);
+ System.out.println("testEquals(server9,server10,false)");
+ testEquals(server9,server10,false);
+ System.out.println("testEquals(server2,server6,true)");
+ testEquals(server2,server6,true);
+ System.out.println("testEquals(server2,server7,false)");
+ testEquals(server2,server7,false);
+ System.out.println("testEquals(server5,server8,true)");
+ testEquals(server5,server8,true);
+ System.out.println("testEquals(server5,server9,false)");
+ testEquals(server5,server9,false);
+ System.out.println("testEquals(server1,null,false)");
+ testEquals(server1,null,false);
+ System.out.println("testEquals(server2,null,false)");
+ testEquals(server2,null,false);
+ System.out.println("testEquals(server3,null,false)");
+ testEquals(server3,null,false);
+ System.out.println("testEquals(server1,client2,false)");
+ testEquals(server1,client2,false);
+ System.out.println("testEquals(server2,client11,false)");
+ testEquals(server2,client11,false);
+ System.out.println("testEquals(server1,new Object(),false)");
+ testEquals(server1,new Object(),false);
+
+ // client subclass
+ System.out.println("testEquals(subclient1,subclient1,true)");
+ testEquals(subclient1,subclient1,true);
+ System.out.println("testEquals(subclient1,subclient2,true)");
+ testEquals(subclient1,subclient2,true);
+ System.out.println("testEquals(subclient1,client1,false)");
+ testEquals(subclient1,client1,false);
+ System.out.println("testEquals(client1,subclient1,false)");
+ testEquals(client1,subclient1,false);
+ System.out.println("testEquals(subclient1,null,false)");
+ testEquals(subclient1,null,false);
+ System.out.println("testEquals(subclient1,server1,false)");
+ testEquals(subclient1,server1,false);
+ System.out.println("testEquals(server1,subclient1,false)");
+ testEquals(server1,subclient1,false);
+ System.out.println("testEquals(subclient2,subserver2,false)");
+ testEquals(subclient1,subserver2,false);
+ System.out.println("testEquals(subclient1,new Object(),false)");
+ testEquals(subclient1,new Object(),false);
+
+ // server subclass
+ System.out.println("testEquals(subserver1,subserver1,true)");
+ testEquals(subserver1,subserver1,true);
+ System.out.println("testEquals(subserver2,subserver2,true)");
+ testEquals(subserver2,subserver2,true);
+ System.out.println("testEquals(subserver3,subserver3,true)");
+ testEquals(subserver3,subserver3,true);
+ System.out.println("testEquals(subserver4,subserver4,true)");
+ testEquals(subserver4,subserver4,true);
+ System.out.println("testEquals(subserver5,subserver5,true)");
+ testEquals(subserver5,subserver5,true);
+ System.out.println("testEquals(subserver1,subserver2,true)");
+ testEquals(subserver1,subserver2,true);
+ System.out.println("testEquals(subserver1,subserver3,false)");
+ testEquals(subserver1,subserver3,false);
+ System.out.println("testEquals(subserver2,subserver3,false)");
+ testEquals(subserver2,subserver3,false);
+ System.out.println("testEquals(subserver3,subserver4,false)");
+ testEquals(subserver3,subserver4,false);
+ System.out.println("testEquals(subserver4,subserver5,false)");
+ testEquals(subserver4,subserver5,false);
+ System.out.println("testEquals(subserver3,subserver6,true)");
+ testEquals(subserver3,subserver6,true);
+ System.out.println("testEquals(subserver3,subserver7,false)");
+ testEquals(subserver3,subserver7,false);
+ System.out.println("testEquals(subserver1,server1,false)");
+ testEquals(subserver1,server1,false);
+ System.out.println("testEquals(server1,subserver1,false)");
+ testEquals(server1,subserver1,false);
+ System.out.println("testEquals(subserver2,server2,false)");
+ testEquals(subserver2,server2,false);
+ System.out.println("testEquals(server2,subserver2,false)");
+ testEquals(server2,subserver2,false);
+ System.out.println("testEquals(subserver3,server3,false)");
+ testEquals(subserver3,server3,false);
+ System.out.println("testEquals(server3,subserver3,false)");
+ testEquals(server3,subserver3,false);
+ System.out.println("testEquals(subserver4,server4,false)");
+ testEquals(subserver4,server4,false);
+ System.out.println("testEquals(server4,subserver4,false)");
+ testEquals(server4,subserver4,false);
+ System.out.println("testEquals(subserver5,server5,false)");
+ testEquals(subserver5,server5,false);
+ System.out.println("testEquals(server5,subserver5,false)");
+ testEquals(server5,subserver5,false);
+ System.out.println("testEquals(server10,subserver8,false)");
+ testEquals(server10,subserver8,false);
+ System.out.println("testEquals(subserver8,server10,false)");
+ testEquals(subserver8,server10,false);
+ System.out.println("testEquals(subserver1,null,false)");
+ testEquals(subserver1,null,false);
+ System.out.println("testEquals(subserver1,client2,false)");
+ testEquals(subserver1,client2,false);
+ System.out.println("testEquals(subserver1,subclient2,false)");
+ testEquals(subserver1,subclient2,false);
+ System.out.println("testEquals(client1,subserver2,false)");
+ testEquals(client1,subserver2,false);
+ System.out.println("testEquals(subserver1,new Object(),false)");
+ testEquals(subserver1,new Object(),false);
+
+ System.out.println("SocketFactoryTest PASSED.");
+ } catch (Exception x) {
+ System.out.println("SocketFactoryTest FAILED: " + x);
+ x.printStackTrace();
+ System.exit(1);
+ }
+ }
+}
diff --git a/test/javax/rmi/ssl/keystore b/test/javax/rmi/ssl/keystore
new file mode 100644
index 0000000..05f5356
--- /dev/null
+++ b/test/javax/rmi/ssl/keystore
Binary files differ
diff --git a/test/javax/rmi/ssl/truststore b/test/javax/rmi/ssl/truststore
new file mode 100644
index 0000000..2f5ba34
--- /dev/null
+++ b/test/javax/rmi/ssl/truststore
Binary files differ
diff --git a/test/javax/script/CommonSetup.sh b/test/javax/script/CommonSetup.sh
new file mode 100644
index 0000000..e76da82
--- /dev/null
+++ b/test/javax/script/CommonSetup.sh
@@ -0,0 +1,79 @@
+#!/bin/sh
+
+#
+# Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+
+#
+#
+# Common setup for the script API unit tests. Setups up the following variables:
+#
+# PS - path sep.
+# FS - file sep.
+# JAVA - java cmd.
+# JAVAC - javac cmd.
+# JAR - jar cmd.
+
+OS=`uname -s`
+case "$OS" in
+ SunOS )
+ PS=":"
+ FS="/"
+ ;;
+ Linux )
+ PS=":"
+ FS="/"
+ ;;
+ Windows* )
+ PS=";"
+ OS="Windows"
+ FS="\\"
+ ;;
+ * )
+ echo "Unrecognized system!"
+ exit 1;
+ ;;
+esac
+
+if [ "${TESTJAVA}" = "" ]
+then
+ echo "TESTJAVA not set. Test cannot execute. Failed."
+ exit 1
+fi
+
+if [ "${TESTSRC}" = "" ]
+then
+ echo "TESTSRC not set. Test cannot execute. Failed."
+ exit 1
+fi
+
+if [ "${TESTCLASSES}" = "" ]
+then
+ echo "TESTCLASSES not set. Test cannot execute. Failed."
+ exit 1
+fi
+
+JAVA="${TESTJAVA}/bin/java"
+JAVAC="${TESTJAVA}/bin/javac"
+JAR="${TESTJAVA}/bin/jar"
+
diff --git a/test/javax/script/DummyScriptEngine.java b/test/javax/script/DummyScriptEngine.java
new file mode 100644
index 0000000..a1d83dc
--- /dev/null
+++ b/test/javax/script/DummyScriptEngine.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ *
+ *
+ * This is a dummy script engine implementation
+ */
+import javax.script.*;
+import java.io.*;
+
+public class DummyScriptEngine extends AbstractScriptEngine {
+ public Object eval(String str, ScriptContext ctx) {
+ return eval(new StringReader(str), ctx);
+ }
+
+ public Object eval(Reader reader, ScriptContext ctx) {
+ System.out.println("eval done!");
+ return null;
+ }
+
+ public ScriptEngineFactory getFactory() {
+ return new DummyScriptEngineFactory();
+ }
+
+ public Bindings createBindings() {
+ return new SimpleBindings();
+ }
+}
diff --git a/test/javax/script/DummyScriptEngineFactory.java b/test/javax/script/DummyScriptEngineFactory.java
new file mode 100644
index 0000000..ae150e8
--- /dev/null
+++ b/test/javax/script/DummyScriptEngineFactory.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ *
+ *
+ * This is script engine factory for dummy engine.
+ */
+
+import javax.script.*;
+import java.util.*;
+
+public class DummyScriptEngineFactory implements ScriptEngineFactory {
+ public String getEngineName() {
+ return "dummy";
+ }
+
+ public String getEngineVersion() {
+ return "-1.0";
+ }
+
+ public List<String> getExtensions() {
+ return extensions;
+ }
+
+ public String getLanguageName() {
+ return "dummy";
+ }
+
+ public String getLanguageVersion() {
+ return "-1.0";
+ }
+
+ public String getMethodCallSyntax(String obj, String m, String... args) {
+ StringBuffer buf = new StringBuffer();
+ buf.append("call " + m + " ");
+ buf.append(" on " + obj + " with ");
+ for (int i = 0; i < args.length; i++) {
+ buf.append(args[i] + ", ");
+ }
+ buf.append(";");
+ return buf.toString();
+ }
+
+ public List<String> getMimeTypes() {
+ return mimeTypes;
+ }
+
+ public List<String> getNames() {
+ return names;
+ }
+
+ public String getOutputStatement(String str) {
+ return "output " + str;
+ }
+
+ public String getParameter(String key) {
+ if (key.equals(ScriptEngine.ENGINE)) {
+ return getEngineName();
+ } else if (key.equals(ScriptEngine.ENGINE_VERSION)) {
+ return getEngineVersion();
+ } else if (key.equals(ScriptEngine.NAME)) {
+ return getEngineName();
+ } else if (key.equals(ScriptEngine.LANGUAGE)) {
+ return getLanguageName();
+ } else if (key.equals(ScriptEngine.LANGUAGE_VERSION)) {
+ return getLanguageVersion();
+ } else {
+ return null;
+ }
+ }
+
+ public String getProgram(String... statements) {
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < statements.length; i++) {
+ buf.append(statements[i]);
+ }
+ return buf.toString();
+ }
+
+ public ScriptEngine getScriptEngine() {
+ return new DummyScriptEngine();
+ }
+
+ private static List<String> names;
+ private static List<String> extensions;
+ private static List<String> mimeTypes;
+ static {
+ names = new ArrayList<String>(1);
+ names.add("dummy");
+ names = Collections.unmodifiableList(names);
+ extensions = names;
+ mimeTypes = new ArrayList<String>(0);
+ mimeTypes = Collections.unmodifiableList(mimeTypes);
+ }
+}
diff --git a/test/javax/script/E4XErrorTest.java b/test/javax/script/E4XErrorTest.java
new file mode 100644
index 0000000..5936fd4
--- /dev/null
+++ b/test/javax/script/E4XErrorTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6346734
+ * @summary We do *not* support E4X (ECMAScript for XML) in our
+ * implementation. We want to throw error on XML literals
+ * as early as possible rather than at "runtime" - i.e., when
+ * engine looks for "XML" constructor.
+ */
+
+import javax.script.*;
+import java.util.Locale;
+
+public class E4XErrorTest {
+
+ public static void main(String[] args) throws Exception {
+ ScriptEngineManager manager = new ScriptEngineManager();
+ ScriptEngine jsengine = manager.getEngineByName("js");
+ if (jsengine == null) {
+ throw new RuntimeException("no js engine found");
+ }
+
+ // The test below depends on the error message content
+ // that is loaded from resource bundles. So, we force
+ // English Locale to compare correct value..
+ Locale.setDefault(Locale.US);
+
+ try {
+ jsengine.eval("var v = <html></html>;");
+ } catch (ScriptException se) {
+ String msg = se.getMessage();
+ if (msg.indexOf("syntax error") == -1) {
+ throw new RuntimeException("syntax error expected, got " +
+ msg);
+ }
+ return;
+ }
+ // should not reach here.. exception should have been thrown.
+ throw new RuntimeException("Huh! E4X is supported??");
+ }
+}
diff --git a/test/javax/script/JavaScriptScopeTest.java b/test/javax/script/JavaScriptScopeTest.java
new file mode 100644
index 0000000..1bce7b6
--- /dev/null
+++ b/test/javax/script/JavaScriptScopeTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6346733
+ * @summary Verify that independent Bindings instances don't
+ * get affected by default scope assignments. Also, verify
+ * that script globals can be created and accessed from Java
+ * as well as JavaScript.
+ */
+
+import javax.script.*;
+
+public class JavaScriptScopeTest {
+
+ public static void main(String[] args) throws Exception {
+ ScriptEngineManager manager = new ScriptEngineManager();
+ ScriptEngine jsengine = manager.getEngineByName("js");
+ if (jsengine == null) {
+ throw new RuntimeException("no js engine found");
+ }
+ jsengine.eval("var v = 'hello';");
+ // Create a new scope
+ Bindings b = jsengine.createBindings();
+ // b is newly created scope. We don't expect 'v' there.
+ // we expect b to be empty...
+ if (b.keySet().size() != 0) {
+ throw new RuntimeException("no variables expected in new scope");
+ }
+
+ // verify that we can create new variable from Java
+ jsengine.put("fromJava", "hello world");
+ // below should execute without problems..
+ jsengine.eval(" if (fromJava != 'hello world') throw 'unexpected'");
+
+ // verify that script globals are exposed to Java
+ // we have created 'v' and 'fromJava' already.
+ if (! jsengine.get("v").equals("hello")) {
+ throw new RuntimeException("unexpected value of 'v'");
+ }
+
+ if (! jsengine.get("fromJava").equals("hello world")) {
+ throw new RuntimeException("unexpected value of 'fromJava'");
+ }
+ }
+}
diff --git a/test/javax/script/META-INF/services/javax.script.ScriptEngineFactory b/test/javax/script/META-INF/services/javax.script.ScriptEngineFactory
new file mode 100644
index 0000000..bc6a5b8
--- /dev/null
+++ b/test/javax/script/META-INF/services/javax.script.ScriptEngineFactory
@@ -0,0 +1,5 @@
+#
+
+# dummy script engine
+
+DummyScriptEngineFactory
diff --git a/test/javax/script/MyContext.java b/test/javax/script/MyContext.java
new file mode 100644
index 0000000..642cf84
--- /dev/null
+++ b/test/javax/script/MyContext.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * This is pluggable context used by test for 6398614
+ */
+
+import javax.script.*;
+import java.util.*;
+import java.io.*;
+
+public class MyContext implements ScriptContext {
+
+ public static final int APP_SCOPE = 125;
+
+ protected Writer writer;
+
+ protected Writer errorWriter;
+
+ protected Reader reader;
+
+
+ protected Bindings appScope;
+ protected Bindings engineScope;
+ protected Bindings globalScope;
+
+
+ public MyContext() {
+ appScope = new SimpleBindings();
+ engineScope = new SimpleBindings();
+ globalScope = null;
+ reader = new InputStreamReader(System.in);
+ writer = new PrintWriter(System.out , true);
+ errorWriter = new PrintWriter(System.err, true);
+ }
+
+ public void setBindings(Bindings bindings, int scope) {
+
+ switch (scope) {
+ case APP_SCOPE:
+ if (bindings == null) {
+ throw new NullPointerException("App scope cannot be null.");
+ }
+ appScope = bindings;
+ break;
+
+ case ENGINE_SCOPE:
+ if (bindings == null) {
+ throw new NullPointerException("Engine scope cannot be null.");
+ }
+ engineScope = bindings;
+ break;
+ case GLOBAL_SCOPE:
+ globalScope = bindings;
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid scope value.");
+ }
+ }
+
+ public Object getAttribute(String name) {
+ if (engineScope.containsKey(name)) {
+ return getAttribute(name, ENGINE_SCOPE);
+ } else if (appScope.containsKey(name)) {
+ return getAttribute(name, APP_SCOPE);
+ } else if (globalScope != null && globalScope.containsKey(name)) {
+ return getAttribute(name, GLOBAL_SCOPE);
+ }
+
+ return null;
+ }
+
+ public Object getAttribute(String name, int scope) {
+
+ switch (scope) {
+ case APP_SCOPE:
+ return appScope.get(name);
+
+ case ENGINE_SCOPE:
+ return engineScope.get(name);
+
+ case GLOBAL_SCOPE:
+ if (globalScope != null) {
+ return globalScope.get(name);
+ }
+ return null;
+
+ default:
+ throw new IllegalArgumentException("Illegal scope value.");
+ }
+ }
+
+ public Object removeAttribute(String name, int scope) {
+
+ switch (scope) {
+ case APP_SCOPE:
+ if (getBindings(APP_SCOPE) != null) {
+ return getBindings(APP_SCOPE).remove(name);
+ }
+ return null;
+
+
+ case ENGINE_SCOPE:
+ if (getBindings(ENGINE_SCOPE) != null) {
+ return getBindings(ENGINE_SCOPE).remove(name);
+ }
+ return null;
+
+ case GLOBAL_SCOPE:
+ if (getBindings(GLOBAL_SCOPE) != null) {
+ return getBindings(GLOBAL_SCOPE).remove(name);
+ }
+ return null;
+
+ default:
+ throw new IllegalArgumentException("Illegal scope value.");
+ }
+ }
+
+ public void setAttribute(String name, Object value, int scope) {
+
+ switch (scope) {
+ case APP_SCOPE:
+ appScope.put(name, value);
+ return;
+
+ case ENGINE_SCOPE:
+ engineScope.put(name, value);
+ return;
+
+ case GLOBAL_SCOPE:
+ if (globalScope != null) {
+ globalScope.put(name, value);
+ }
+ return;
+
+ default:
+ throw new IllegalArgumentException("Illegal scope value.");
+ }
+ }
+
+ public Writer getWriter() {
+ return writer;
+ }
+
+ public Reader getReader() {
+ return reader;
+ }
+
+ public void setReader(Reader reader) {
+ this.reader = reader;
+ }
+
+ public void setWriter(Writer writer) {
+ this.writer = writer;
+ }
+
+ public Writer getErrorWriter() {
+ return errorWriter;
+ }
+
+ public void setErrorWriter(Writer writer) {
+ this.errorWriter = writer;
+ }
+
+ public int getAttributesScope(String name) {
+ if (engineScope.containsKey(name)) {
+ return ENGINE_SCOPE;
+ } else if (appScope.containsKey(name)) {
+ return APP_SCOPE;
+ } else if (globalScope != null && globalScope.containsKey(name)) {
+ return GLOBAL_SCOPE;
+ } else {
+ return -1;
+ }
+ }
+
+ public Bindings getBindings(int scope) {
+ if (scope == ENGINE_SCOPE) {
+ return engineScope;
+ } else if (scope == APP_SCOPE) {
+ return appScope;
+ } else if (scope == GLOBAL_SCOPE) {
+ return globalScope;
+ } else {
+ throw new IllegalArgumentException("Illegal scope value.");
+ }
+ }
+
+ public List<Integer> getScopes() {
+ return scopes;
+ }
+
+ private static List<Integer> scopes;
+ static {
+ scopes = new ArrayList<Integer>(3);
+ scopes.add(ENGINE_SCOPE);
+ scopes.add(APP_SCOPE);
+ scopes.add(GLOBAL_SCOPE);
+ scopes = Collections.unmodifiableList(scopes);
+ }
+}
diff --git a/test/javax/script/NullUndefinedVarTest.java b/test/javax/script/NullUndefinedVarTest.java
new file mode 100644
index 0000000..b07d5af
--- /dev/null
+++ b/test/javax/script/NullUndefinedVarTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6346732
+ * @summary should be able to assign null and undefined
+ * value to JavaScript global variables.
+ */
+
+import javax.script.*;
+
+public class NullUndefinedVarTest {
+
+ public static void main(String[] args) throws Exception {
+ ScriptEngineManager manager = new ScriptEngineManager();
+ ScriptEngine jsengine = manager.getEngineByName("js");
+ if (jsengine == null) {
+ throw new RuntimeException("no js engine found");
+ }
+ jsengine.eval("var n = null; " +
+ "if (n !== null) throw 'expecting null';" +
+ "var u = undefined; " +
+ "if (u !== undefined) throw 'undefined expected';");
+ }
+}
diff --git a/test/javax/script/PluggableContextTest.java b/test/javax/script/PluggableContextTest.java
new file mode 100644
index 0000000..1e6f4fa
--- /dev/null
+++ b/test/javax/script/PluggableContextTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6398614
+ * @summary Create a user defined ScriptContext and check
+ * that script can access variables from non-standard scopes
+ */
+
+import javax.script.*;
+
+public class PluggableContextTest {
+ public static void main(String[] args) throws Exception {
+ ScriptEngineManager m = new ScriptEngineManager();
+ ScriptContext ctx = new MyContext();
+ ctx.setAttribute("x", "hello", MyContext.APP_SCOPE);
+ ScriptEngine e = m.getEngineByName("js");
+ // the following reference to 'x' throws exception
+ // if APP_SCOPE is not searched.
+ e.eval("x", ctx);
+ }
+}
diff --git a/test/javax/script/ProviderTest.java b/test/javax/script/ProviderTest.java
new file mode 100644
index 0000000..79d6f16
--- /dev/null
+++ b/test/javax/script/ProviderTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ *
+ *
+ * Unit test for testing script engine discovery.
+ */
+import javax.script.*;
+
+public class ProviderTest {
+ public static void main(String args[]) throws Exception {
+ ScriptEngineManager manager = new ScriptEngineManager();
+ ScriptEngine se = manager.getEngineByName("dummy");
+ if (se == null) {
+ throw new RuntimeException("can't locate dummy engine");
+ }
+ se = manager.getEngineByName("js");
+ if (se == null) {
+ throw new RuntimeException("can't locate JavaScript engine");
+ }
+ }
+}
diff --git a/test/javax/script/ProviderTest.sh b/test/javax/script/ProviderTest.sh
new file mode 100644
index 0000000..211d9ed
--- /dev/null
+++ b/test/javax/script/ProviderTest.sh
@@ -0,0 +1,50 @@
+#
+# Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+# @test
+# @bug 6249843
+# @summary ScriptEngine provider unit test
+#
+# @build ProviderTest DummyScriptEngineFactory
+# @run shell ProviderTest.sh
+
+if [ "${TESTSRC}" = "" ]
+then
+ echo "TESTSRC not set. Test cannot execute. Failed."
+ exit 1
+fi
+
+. ${TESTSRC}/CommonSetup.sh
+
+echo "Creating JAR file ..."
+
+$JAR -cf ${TESTCLASSES}/dummy.jar \
+ -C ${TESTCLASSES} DummyScriptEngine.class \
+ -C ${TESTCLASSES} DummyScriptEngineFactory.class \
+ -C "${TESTSRC}" META-INF/services/javax.script.ScriptEngineFactory
+
+echo "Running test ..."
+
+$JAVA -classpath \
+ ${TESTCLASSES}${PS}${TESTCLASSES}/dummy.jar \
+ ProviderTest
diff --git a/test/javax/script/RhinoExceptionTest.java b/test/javax/script/RhinoExceptionTest.java
new file mode 100644
index 0000000..439b947
--- /dev/null
+++ b/test/javax/script/RhinoExceptionTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6474943
+ * @summary Test that Rhion exception messages are
+ * available from ScriptException.
+ */
+
+import java.io.*;
+import javax.script.*;
+
+public class RhinoExceptionTest {
+ private static final String ERROR_MSG = "error from JavaScript";
+
+ public static void main(String[] args) throws Exception {
+ ScriptEngineManager m = new ScriptEngineManager();
+ ScriptEngine engine = m.getEngineByName("js");
+ engine.put("msg", ERROR_MSG);
+ try {
+ engine.eval("throw new Error(msg);");
+ } catch (ScriptException exp) {
+ if (exp.getMessage().indexOf(ERROR_MSG) == -1) {
+ throw exp;
+ }
+ }
+ try {
+ engine.eval("throw (msg);");
+ } catch (ScriptException exp) {
+ if (exp.getMessage().indexOf(ERROR_MSG) == -1) {
+ throw exp;
+ }
+ }
+ try {
+ CompiledScript scr = ((Compilable)engine).compile("throw new Error(msg);");
+ scr.eval();
+ } catch (ScriptException exp) {
+ if (exp.getMessage().indexOf(ERROR_MSG) == -1) {
+ throw exp;
+ }
+ }
+ try {
+ CompiledScript scr = ((Compilable)engine).compile("throw msg;");
+ scr.eval();
+ } catch (ScriptException exp) {
+ if (exp.getMessage().indexOf(ERROR_MSG) == -1) {
+ throw exp;
+ }
+ }
+ }
+}
diff --git a/test/javax/script/Test1.java b/test/javax/script/Test1.java
new file mode 100644
index 0000000..fdfdef9
--- /dev/null
+++ b/test/javax/script/Test1.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6249843
+ * @summary Create JavaScript engine and execute a simple script.
+ * Tests script engine discovery mechanism.
+ */
+
+import javax.script.*;
+import java.io.*;
+
+public class Test1 {
+ public static void main(String[] args) throws Exception {
+ System.out.println("\nTest1\n");
+ ScriptEngineManager manager = new ScriptEngineManager();
+ ScriptEngine jsengine = manager.getEngineByName("js");
+ if (jsengine == null) {
+ throw new RuntimeException("no js engine found");
+ }
+ jsengine.eval(new FileReader(
+ new File(System.getProperty("test.src", "."), "Test1.js")));
+ }
+}
diff --git a/test/javax/script/Test1.js b/test/javax/script/Test1.js
new file mode 100644
index 0000000..4e46efb
--- /dev/null
+++ b/test/javax/script/Test1.js
@@ -0,0 +1 @@
+print("Test1 passes");
diff --git a/test/javax/script/Test2.java b/test/javax/script/Test2.java
new file mode 100644
index 0000000..0a70eb1
--- /dev/null
+++ b/test/javax/script/Test2.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2005-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6249843
+ * @summary Test exposing a Java object to script
+ */
+
+import javax.script.*;
+import java.io.*;
+
+public class Test2 {
+ public static class Testobj {
+ private String val;
+ public Testobj(String s) {
+ val = s;
+ }
+ public void setVal(String v) {
+ val = v;
+ }
+ public String getVal() {
+ return val;
+ }
+ public String toString() {
+ return "Testobj containing " + val;
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("\nTest2\n");
+ ScriptEngineManager m = new ScriptEngineManager();
+ ScriptEngine eng = m.getEngineByName("js");
+ eng.put("Testobj", new Testobj("Hello World"));
+ eng.eval(new FileReader(
+ new File(System.getProperty("test.src", "."), "Test2.js")));
+ }
+}
diff --git a/test/javax/script/Test2.js b/test/javax/script/Test2.js
new file mode 100644
index 0000000..673a4e6
--- /dev/null
+++ b/test/javax/script/Test2.js
@@ -0,0 +1,9 @@
+if (Testobj.getVal() != 'Hello World') {
+ throw "unexpected value";
+}
+
+Testobj = "a string";
+if (Testobj.getVal != undefined ||
+ Testobj != 'a string') {
+ throw "can' change Testobj?";
+}
diff --git a/test/javax/script/Test3.java b/test/javax/script/Test3.java
new file mode 100644
index 0000000..84b610a
--- /dev/null
+++ b/test/javax/script/Test3.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2005-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6249843
+ * @summary Test engine and global scopes
+ */
+
+import javax.script.*;
+import java.io.*;
+import java.util.*;
+
+public class Test3 {
+ public static void main(String[] args) throws Exception {
+ System.out.println("\nTest3\n");
+ final Reader reader = new FileReader(
+ new File(System.getProperty("test.src", "."), "Test3.js"));
+ ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine engine = m.getEngineByName("js");
+ Bindings en = new SimpleBindings();
+ engine.setBindings(en, ScriptContext.ENGINE_SCOPE);
+ en.put("key", "engine value");
+ Bindings gn = new SimpleBindings();
+ engine.setBindings(gn, ScriptContext.GLOBAL_SCOPE);
+ gn.put("key", "global value");
+ engine.eval(reader);
+ }
+}
diff --git a/test/javax/script/Test3.js b/test/javax/script/Test3.js
new file mode 100644
index 0000000..4cdb828
--- /dev/null
+++ b/test/javax/script/Test3.js
@@ -0,0 +1,22 @@
+if (key == undefined || key != 'engine value') {
+ throw "unexpected engine scope value";
+}
+
+// pre-defined context variable refers to current ScriptContext
+if (context.getAttribute('key', context.GLOBAL_SCOPE) != 'global value') {
+ throw "unexpected global scope value";
+}
+
+// change the engine scope value
+key = 'new engine value';
+
+if (context.getAttribute('key', context.GLOBAL_SCOPE) != 'global value') {
+ throw "global scope should not change here";
+}
+
+// delete engine scope value
+delete key;
+
+if (key == undefined && key != 'xglobal value') {
+ throw 'global scope should be visible after engine scope removal';
+}
diff --git a/test/javax/script/Test4.java b/test/javax/script/Test4.java
new file mode 100644
index 0000000..bae2550
--- /dev/null
+++ b/test/javax/script/Test4.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2005-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6249843
+ * @summary Test script functions implementing Java interface
+ */
+
+import javax.script.*;
+import java.io.*;
+
+public class Test4 {
+ public static void main(String[] args) throws Exception {
+ System.out.println("\nTest4\n");
+ ScriptEngineManager m = new ScriptEngineManager();
+ ScriptEngine e = m.getEngineByName("js");
+ e.eval(new FileReader(
+ new File(System.getProperty("test.src", "."), "Test4.js")));
+ Invocable inv = (Invocable)e;
+ Runnable run1 = (Runnable)inv.getInterface(Runnable.class);
+ run1.run();
+ // use methods of a specific script object
+ Object intfObj = e.get("intfObj");
+ Runnable run2 = (Runnable)inv.getInterface(intfObj, Runnable.class);
+ run2.run();
+ }
+}
diff --git a/test/javax/script/Test4.js b/test/javax/script/Test4.js
new file mode 100644
index 0000000..6c3c1f4
--- /dev/null
+++ b/test/javax/script/Test4.js
@@ -0,0 +1,7 @@
+function run() {
+ print("global run method");
+}
+
+var intfObj = {
+ run: function() { print("object run method"); }
+};
diff --git a/test/javax/script/Test5.java b/test/javax/script/Test5.java
new file mode 100644
index 0000000..cf32cff
--- /dev/null
+++ b/test/javax/script/Test5.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2005-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6249843
+ * @summary Tests engine, global scopes and scope hiding.
+ */
+
+import java.io.*;
+import javax.script.*;
+
+public class Test5 {
+ public static void main(String[] args) throws Exception {
+ System.out.println("\nTest5\n");
+ ScriptEngineManager m = new ScriptEngineManager();
+ ScriptEngine engine = m.getEngineByName("js");
+ Bindings g = new SimpleBindings();
+ Bindings e = new SimpleBindings();
+ g.put("key", "value in global");
+ e.put("key", "value in engine");
+ ScriptContext ctxt = new SimpleScriptContext();
+ ctxt.setBindings(e, ScriptContext.ENGINE_SCOPE);
+ System.out.println("engine scope only");
+ e.put("count", new Integer(1));
+
+ Reader reader = new FileReader(
+ new File(System.getProperty("test.src", "."), "Test5.js"));
+ engine.eval(reader,ctxt);
+ System.out.println("both scopes");
+ ctxt.setBindings(g, ScriptContext.GLOBAL_SCOPE);
+ e.put("count", new Integer(2));
+ engine.eval(reader,ctxt);
+ System.out.println("only global");
+ e.put("count", new Integer(3));
+ ctxt.setAttribute("key", null, ScriptContext.ENGINE_SCOPE);
+ engine.eval(reader,ctxt);
+ }
+}
diff --git a/test/javax/script/Test5.js b/test/javax/script/Test5.js
new file mode 100644
index 0000000..c607cbc
--- /dev/null
+++ b/test/javax/script/Test5.js
@@ -0,0 +1,42 @@
+var key;
+var count;
+
+print(count);
+
+switch (count) {
+ // engine only
+ case 1:
+ if (key != 'value in engine') {
+ throw "unexpected engine scope value";
+ }
+ if (context.getAttribute("key", context.GLOBAL_SCOPE ) != null) {
+ throw "unexpected global scope value";
+ }
+ break;
+
+ // both scopes
+ case 2:
+ if (key != 'value in engine') {
+ throw "unexpected engine scope value";
+ }
+ if (context.getAttribute("key", context.GLOBAL_SCOPE ) !=
+ "value in global") {
+ throw "unexpected global scope value";
+ }
+ break;
+
+ // global only
+ case 3:
+ if (key != 'value in global') {
+ throw "unexpected global scope value";
+ }
+ if (context.getAttribute("key", context.GLOBAL_SCOPE ) !=
+ "value in global") {
+ throw "unexpected global scope value";
+ }
+ break;
+
+ default:
+ throw "unexpected count";
+ break;
+}
diff --git a/test/javax/script/Test6.java b/test/javax/script/Test6.java
new file mode 100644
index 0000000..15bbda1
--- /dev/null
+++ b/test/javax/script/Test6.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2005-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6249843
+ * @summary Test basic script compilation. Value eval'ed from
+ * compiled and interpreted scripts should be same.
+ */
+
+import java.io.*;
+import javax.script.*;
+
+public class Test6 {
+ public static void main(String[] args) throws Exception {
+ System.out.println("\nTest6\n");
+ ScriptEngineManager m = new ScriptEngineManager();
+ ScriptEngine engine = m.getEngineByName("js");
+ Reader reader = new FileReader(
+ new File(System.getProperty("test.src", "."), "Test6.js"));
+ engine.eval(reader);
+ Object res = engine.get("res");
+ CompiledScript scr = ((Compilable)engine).compile(reader);
+ scr.eval();
+ Object res1 = engine.get("res");
+ if (! res.equals(res1)) {
+ throw new RuntimeException("values not equal");
+ }
+ }
+}
diff --git a/test/javax/script/Test6.js b/test/javax/script/Test6.js
new file mode 100644
index 0000000..2a4fd4a
--- /dev/null
+++ b/test/javax/script/Test6.js
@@ -0,0 +1 @@
+var res = 45 + 34;
diff --git a/test/javax/script/Test7.java b/test/javax/script/Test7.java
new file mode 100644
index 0000000..9cdd8ac
--- /dev/null
+++ b/test/javax/script/Test7.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2005-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6249843
+ * @summary Tests importPackage and java access in script
+ */
+
+import java.io.*;
+import javax.script.*;
+
+public class Test7 {
+ public static void main(String[] args) throws Exception {
+ System.out.println("\nTest7\n");
+ File file =
+ new File(System.getProperty("test.src", "."), "Test7.js");
+ Reader r = new FileReader(file);
+ ScriptEngineManager m = new ScriptEngineManager();
+ ScriptEngine eng = m.getEngineByName("js");
+ eng.put("filename", file.getAbsolutePath());
+ eng.eval(r);
+ String str = (String)eng.get("firstLine");
+ // do not change first line in Test7.js -- we check it here!
+ if (!str.equals("//this is the first line of Test7.js")) {
+ throw new RuntimeException("unexpected first line");
+ }
+ }
+}
diff --git a/test/javax/script/Test7.js b/test/javax/script/Test7.js
new file mode 100644
index 0000000..b1ec2a8
--- /dev/null
+++ b/test/javax/script/Test7.js
@@ -0,0 +1,9 @@
+//this is the first line of Test7.js
+var filename;
+importPackage(java.io);
+importPackage(java);
+var f = new File(filename);
+var r = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
+
+var firstLine = r.readLine() + '';
+print(firstLine);
diff --git a/test/javax/script/Test8.java b/test/javax/script/Test8.java
new file mode 100644
index 0000000..80f0a6a
--- /dev/null
+++ b/test/javax/script/Test8.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2005-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6249843
+ * @summary Test invoking script function or method from Java
+ */
+
+import javax.script.*;
+import java.io.*;
+
+public class Test8 {
+ public static void main(String[] args) throws Exception {
+ System.out.println("\nTest8\n");
+ ScriptEngineManager m = new ScriptEngineManager();
+ ScriptEngine e = m.getEngineByName("js");
+ e.eval(new FileReader(
+ new File(System.getProperty("test.src", "."), "Test8.js")));
+ Invocable inv = (Invocable)e;
+ inv.invokeFunction("main", "Mustang");
+ // use method of a specific script object
+ Object scriptObj = e.get("scriptObj");
+ inv.invokeMethod(scriptObj, "main", "Mustang");
+ }
+}
diff --git a/test/javax/script/Test8.js b/test/javax/script/Test8.js
new file mode 100644
index 0000000..70d4e77
--- /dev/null
+++ b/test/javax/script/Test8.js
@@ -0,0 +1,7 @@
+function main(name) {
+ print(name);
+}
+
+var scriptObj = {
+ main: function(name) { print(name); }
+};
diff --git a/test/javax/script/VersionTest.java b/test/javax/script/VersionTest.java
new file mode 100644
index 0000000..b4fc2fc
--- /dev/null
+++ b/test/javax/script/VersionTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6346729
+ * @summary Create JavaScript engine and check language and engine version
+ */
+
+import javax.script.*;
+import java.io.*;
+
+public class VersionTest {
+
+ private static final String JS_LANG_VERSION = "1.6";
+ private static final String JS_ENGINE_VERSION = "1.6 release 2";
+
+ public static void main(String[] args) throws Exception {
+ ScriptEngineManager manager = new ScriptEngineManager();
+ ScriptEngine jsengine = manager.getEngineByName("js");
+ if (jsengine == null) {
+ throw new RuntimeException("no js engine found");
+ }
+ String langVersion = jsengine.getFactory().getLanguageVersion();
+ if (! langVersion.equals(JS_LANG_VERSION)) {
+ throw new RuntimeException("Expected JavaScript version is " +
+ JS_LANG_VERSION);
+ }
+ String engineVersion = jsengine.getFactory().getEngineVersion();
+ if (! engineVersion.equals(JS_ENGINE_VERSION)) {
+ throw new RuntimeException("Expected Rhino version is " +
+ JS_ENGINE_VERSION);
+ }
+ }
+}
diff --git a/test/javax/security/auth/PrivateCredentialPermission/CanonError.java b/test/javax/security/auth/PrivateCredentialPermission/CanonError.java
new file mode 100644
index 0000000..7d42954
--- /dev/null
+++ b/test/javax/security/auth/PrivateCredentialPermission/CanonError.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2000 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4364833
+ * @summary PrivateCredentialPermission incorrectly canonicalizes
+ * spaces in names
+ */
+
+import javax.security.auth.*;
+
+public class CanonError {
+
+ public static void main(String[] args) {
+
+ // test regular equals and implies
+ PrivateCredentialPermission pcp1 = new PrivateCredentialPermission
+ ("a b \"pcp1\"", "read");
+ PrivateCredentialPermission pcp2 = new PrivateCredentialPermission
+ ("a b \"pcp1\"", "read");
+ if (!pcp1.equals(pcp2) || !pcp2.equals(pcp1))
+ throw new SecurityException("CanonError test failed: #1");
+ if (!pcp1.implies(pcp2) || !pcp2.implies(pcp1))
+ throw new SecurityException("CanonError test failed: #2");
+
+ // test equals/implies failure
+ PrivateCredentialPermission pcp3 = new PrivateCredentialPermission
+ ("a b \"pcp3\"", "read");
+ if (pcp1.equals(pcp3) || pcp3.equals(pcp1))
+ throw new SecurityException("CanonError test failed: #3");
+ if (pcp1.implies(pcp3) || pcp3.implies(pcp1))
+ throw new SecurityException("CanonError test failed: #4");
+
+ // test spaces in name
+ PrivateCredentialPermission pcp_4 = new PrivateCredentialPermission
+ ("a b \"pcp 4\"", "read");
+ PrivateCredentialPermission pcp__4 = new PrivateCredentialPermission
+ ("a b \"pcp 4\"", "read");
+ if (pcp_4.equals(pcp__4) || pcp__4.equals(pcp_4))
+ throw new SecurityException("CanonError test failed: #5");
+ if (pcp_4.implies(pcp__4) || pcp__4.implies(pcp_4))
+ throw new SecurityException("CanonError test failed: #6");
+
+ String credClass = pcp__4.getCredentialClass();
+ System.out.println("credentialClass = " + credClass);
+ String[][] principals = pcp__4.getPrincipals();
+ if (!principals[0][1].equals("pcp 4"))
+ throw new SecurityException("CanonError test failed: #7");
+ for (int i = 0; i < principals.length; i++) {
+ for (int j = 0; j < 2; j++) {
+ System.out.println("principals[" + i + "][" + j + "] = " +
+ principals[i][j]);
+ }
+ }
+
+ credClass = pcp_4.getCredentialClass();
+ System.out.println("credentialClass = " + credClass);
+ principals = pcp_4.getPrincipals();
+ if (!principals[0][1].equals("pcp 4"))
+ throw new SecurityException("CanonError test failed: #8");
+ for (int i = 0; i < principals.length; i++) {
+ for (int j = 0; j < 2; j++) {
+ System.out.println("principals[" + i + "][" + j + "] = " +
+ principals[i][j]);
+ }
+ }
+
+ System.out.println("CanonError test passed");
+ }
+}
diff --git a/test/javax/security/auth/PrivateCredentialPermission/EmptyName.java b/test/javax/security/auth/PrivateCredentialPermission/EmptyName.java
new file mode 100644
index 0000000..6affaf7
--- /dev/null
+++ b/test/javax/security/auth/PrivateCredentialPermission/EmptyName.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4893796
+ * @summary PrivateCredentialPermission constructor throws wrong exception
+ */
+
+import javax.security.auth.PrivateCredentialPermission;
+
+public class EmptyName {
+ public static void main(String[] args) throws Exception {
+ try {
+ PrivateCredentialPermission perm =
+ new PrivateCredentialPermission("", "read");
+ throw new SecurityException("test 1 failed");
+ } catch (IllegalArgumentException iae) {
+ // good
+ }
+ try {
+ PrivateCredentialPermission perm =
+ new PrivateCredentialPermission(null, "read");
+ throw new SecurityException("test 2 failed");
+ } catch (IllegalArgumentException iae) {
+ // good
+ }
+ System.out.println("test passed");
+ }
+}
diff --git a/test/javax/security/auth/PrivateCredentialPermission/Equals.java b/test/javax/security/auth/PrivateCredentialPermission/Equals.java
new file mode 100644
index 0000000..ae1d568
--- /dev/null
+++ b/test/javax/security/auth/PrivateCredentialPermission/Equals.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2000-2001 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4364848
+ * @bug 4364851
+ * @summary PrivateCredentialPermission doesn't ignore principal order
+ * PrivateCredentialPermission incorrectly ignores case
+ */
+
+import javax.security.auth.*;
+
+public class Equals {
+
+ public static void main(String[] args) {
+
+ // test regular equals and implies
+ PrivateCredentialPermission pcp1 = new PrivateCredentialPermission
+ ("a b \"pcp1\" c \"pcp2\"", "read");
+ PrivateCredentialPermission pcp2 = new PrivateCredentialPermission
+ ("a b \"pcp1\" c \"pcp2\"", "read");
+ if (!pcp1.equals(pcp2) || !pcp2.equals(pcp1))
+ throw new SecurityException("Equals test failed: #1");
+ if (!pcp1.implies(pcp2) || !pcp2.implies(pcp1))
+ throw new SecurityException("Equals test failed: #2");
+
+ // reverse principals
+ pcp1 = new PrivateCredentialPermission
+ ("a c \"pcp2\" b \"pcp1\"", "read");
+ pcp2 = new PrivateCredentialPermission
+ ("a b \"pcp1\" c \"pcp2\"", "read");
+ if (!pcp1.equals(pcp2) || !pcp2.equals(pcp1))
+ throw new SecurityException("Equals test failed: #3");
+ if (!pcp1.implies(pcp2) || !pcp2.implies(pcp1))
+ throw new SecurityException("Equals test failed: #4");
+
+ // test equals/implies failure
+ pcp1 = new PrivateCredentialPermission
+ ("a b \"pcp1\"", "read");
+ if (pcp1.equals(pcp2) || pcp2.equals(pcp1))
+ throw new SecurityException("Equals test failed: #5");
+ if (!pcp1.implies(pcp2) || pcp2.implies(pcp1))
+ throw new SecurityException("Equals test failed: #6");
+
+ // test wildcards
+ pcp1 = new PrivateCredentialPermission
+ ("* b \"pcp1\" c \"pcp2\"", "read");
+ if (pcp1.equals(pcp2) || pcp2.equals(pcp1))
+ throw new SecurityException("Equals test failed: #7");
+ if (!pcp1.implies(pcp2) || pcp2.implies(pcp1))
+ throw new SecurityException("Equals test failed: #8");
+
+ pcp1 = new PrivateCredentialPermission
+ ("a c \"pcp2\" b \"*\"", "read");
+ if (pcp1.equals(pcp2) || pcp2.equals(pcp1))
+ throw new SecurityException("Equals test failed: #9");
+ if (!pcp1.implies(pcp2) || pcp2.implies(pcp1))
+ throw new SecurityException("Equals test failed: #10");
+
+ pcp2 = new PrivateCredentialPermission
+ ("a b \"*\" c \"pcp2\"", "read");
+ if (!pcp1.equals(pcp2) || !pcp2.equals(pcp1))
+ throw new SecurityException("Equals test failed: #11");
+ if (!pcp1.implies(pcp2) || !pcp2.implies(pcp1))
+ throw new SecurityException("Equals test failed: #12");
+
+ System.out.println("Equals test passed");
+ }
+}
diff --git a/test/javax/security/auth/PrivateCredentialPermission/Serial.java b/test/javax/security/auth/PrivateCredentialPermission/Serial.java
new file mode 100644
index 0000000..230cde0
--- /dev/null
+++ b/test/javax/security/auth/PrivateCredentialPermission/Serial.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2000 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4364855
+ * @summary PrivateCredentialPermission serialized set has
+ * implementation-dependent class
+ * @run main/othervm/policy=Serial.policy Serial
+ */
+
+import javax.security.auth.*;
+import java.io.*;
+import java.util.*;
+
+public class Serial implements java.io.Serializable {
+
+ public static void main(String[] args) {
+
+ try {
+ FileOutputStream fos = new FileOutputStream("serial.tmp");
+ ObjectOutputStream oos = new ObjectOutputStream(fos);
+
+ PrivateCredentialPermission pcp = new PrivateCredentialPermission
+ ("cred1 pc1 \"pn1\" pc2 \"pn2\"", "read");
+ oos.writeObject(pcp);
+ oos.flush();
+ fos.close();
+
+ FileInputStream fis = new FileInputStream("serial.tmp");
+ ObjectInputStream ois = new ObjectInputStream(fis);
+
+ PrivateCredentialPermission pcp2 =
+ (PrivateCredentialPermission)ois.readObject();
+ fis.close();
+
+ System.out.println("pcp2 = " + pcp2.toString());
+ System.out.println("pcp2.getPrincipals().length = " +
+ pcp2.getPrincipals().length);
+ if (!pcp.equals(pcp2) || !pcp2.equals(pcp)) {
+ throw new SecurityException("Serial test failed: " +
+ "EQUALS TEST FAILED");
+ }
+
+ System.out.println("Serial test succeeded");
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new SecurityException("Serial test failed");
+ }
+ }
+}
diff --git a/test/javax/security/auth/PrivateCredentialPermission/Serial.policy b/test/javax/security/auth/PrivateCredentialPermission/Serial.policy
new file mode 100644
index 0000000..161d52a
--- /dev/null
+++ b/test/javax/security/auth/PrivateCredentialPermission/Serial.policy
@@ -0,0 +1,5 @@
+grant {
+ permission java.io.FilePermission "serial.tmp", "read,write";
+ permission java.io.FilePermission "serial2.tmp", "read,write";
+ permission javax.security.auth.AuthPermission "modifyPrivateCredentials";
+};
diff --git a/test/javax/security/auth/PrivateCredentialPermission/Subset.java b/test/javax/security/auth/PrivateCredentialPermission/Subset.java
new file mode 100644
index 0000000..c40e3c8
--- /dev/null
+++ b/test/javax/security/auth/PrivateCredentialPermission/Subset.java
@@ -0,0 +1,608 @@
+/*
+ * Copyright 2000-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @author Ram Marti
+ * @bug 4326852
+ * @summary Retrive a subset of private credentials can be accessed
+ * @run main/othervm/policy=Subset.policy Subset
+ */
+
+import java.util.*;
+import com.sun.security.auth.SolarisPrincipal;
+import javax.security.auth.Subject;
+
+/*
+ * Author : Ram Marti
+ * This is a test program to verify the fix for Bug 4326852
+ * (impossible to extract a subset of private credentials)
+ * The policy file used allows read access only to String classes.
+ * grant {
+ * permission javax.security.auth.AuthPermission \
+ * "modifyPrivateCredentials";
+ * permission javax.security.auth.PrivateCredentialPermission \
+ * "java.lang.String com.sun.security.auth.SolarisPrincipal \"user"", "read";
+ * };
+
+ * The test verifies the following:
+ * - String class creds can be retrieved by using
+ * getPrivateCredentials(String.class)
+ * - The above set is not backed internally
+ * - getPrivateCredentials(Boolean or Integer) returns an empty set
+ * - Set is returned by getPrivateCredentials() throws
+ * security exception when trying to access non-String
+ * class credentials
+ * - The above set is internally backed up and any changes in
+ * internal private creds are reflected in the set returned
+ * - When the above set throws security exception the iterator
+ * - is advanced to the next item in the list of creds.
+ * - equals,contains,containsAll,add,remove operations work correctly
+ */
+
+public class Subset {
+ public static void main(String[] args) throws Exception {
+ int exceptionCounter =0;
+ Iterator iter1;
+ HashSet creds = new HashSet();
+ Subject emptys =
+ new Subject(false, //readOnly
+ Collections.singleton(new SolarisPrincipal("user")),
+ Collections.EMPTY_SET,
+ creds);
+ /* Test principals */
+
+ Set princ= emptys.getPrincipals();
+ HashSet collp= new HashSet();
+ collp.add(new String("abc"));
+ collp.add(new String("def"));
+ collp.add(new String("Exists"));
+ collp.add(new String("Does not Exist"));
+ try {
+ if (princ.containsAll(collp)) {
+ throw new Exception ("Error: Contains the collection");
+ } else
+ System.out.println ("Does not Contain the collection");
+ } catch (SecurityException e) {
+ throw new Exception ("Error: Exception in containsAll (string coll)!!");
+ }
+
+
+ Set p1 = emptys.getPrivateCredentials();
+
+ if (p1.size() != 0) {
+ throw new Exception("Error:p1 size should have been 6 and was " +
+ p1.size());
+ }
+
+ creds.add("abc");
+ creds.add(new Integer(3));
+ creds.add(Boolean.TRUE);
+ Subject sremove =
+ new Subject(false, //readOnly
+ Collections.singleton(new SolarisPrincipal("user")),
+ Collections.EMPTY_SET,
+ creds);
+ Set p2 = sremove.getPrivateCredentials();
+
+ if (p2.size() !=3){
+ throw new Exception("Error: p2 size should have been 3 and was " +
+ p2.size());
+ }
+ iter1 = p2.iterator();
+ exceptionCounter=0;
+ while (iter1.hasNext()) {
+ try {
+ Object o = iter1.next();
+ System.out.println(" private creds of class " +
+ o.getClass() + "value is " + o.toString());
+ } catch (SecurityException e) {
+ System.out.println("Expected Exception occured");
+ exceptionCounter++;
+ }
+ }
+ if (exceptionCounter != 2) {
+ throw new Exception("Expected number of exceptions was 2 " +
+ "The actual number was " + exceptionCounter);
+ }
+
+ // Verify that remove op was successful
+
+ iter1.remove();
+ if (p2.size() !=2) {
+ throw new RuntimeException("Error: p2 size should have been 2 and was " +
+ p2.size());
+ }
+ System.out.println ("Checking the value after removal");
+ p2 = sremove.getPrivateCredentials();
+ try {
+ if (!p2.add(new String("XYZ"))) {
+
+ throw new RuntimeException("Error in adding string");
+ }
+ if (!p2.add(new Integer(99))) {
+
+ throw new RuntimeException("Error in adding Integer");
+ }
+ HashSet coll1 = new HashSet();
+ coll1.add(new String("RST"));
+ coll1.add(new Integer(1));
+ if (!p2.addAll(coll1)) {
+
+ throw new RuntimeException("Error in addAll");
+ }
+
+ } catch (Exception e){
+ e.printStackTrace();
+ throw new RuntimeException("Unexpected exception in add");
+
+ }
+ iter1 = p2.iterator();
+
+ while (iter1.hasNext()) {
+ try {
+ Object o = iter1.next();
+ System.out.println(" private creds of class " +
+ o.getClass() + "value is " + o.toString());
+ } catch (SecurityException e) {
+ // System.out.println("Exception!!");
+ }
+ }
+ iter1 = p2.iterator();
+
+ System.out.println ("Checked the value after removal");
+
+ HashSet creds1 = new HashSet();
+ creds1.add("abc");
+ creds1.add("def");
+ creds1.add(Boolean.TRUE);
+ creds1.add(new Integer(1));
+ creds1.add(new String("Exists"));
+ Subject scontain =
+ new Subject(false, //readOnly
+ Collections.singleton(new SolarisPrincipal("user")),
+ Collections.EMPTY_SET,
+ creds1);
+ p2 = scontain.getPrivateCredentials();
+ try {
+ Object ObjAr = p2.toArray();
+ } catch (SecurityException e) {
+ System.out.println("Should get an Exception in toArray()");
+ }
+
+ HashSet creds3 = new HashSet();
+ creds3.add (new String("abc"));
+ p2 = scontain.getPrivateCredentials();
+
+ try {
+ Object ObjCred = (Object)creds3.clone();
+ System.out.println ("Size of p2 is " + p2.size() +
+ "Size of ObjCred is " +
+ ((HashSet)ObjCred).size()
+ );
+ if (p2.equals(ObjCred))
+ throw new RuntimeException("Error:Equals ObjCred *** ");
+ else
+ System.out.println ("Does not Equal Objcred");
+ } catch (SecurityException e) {
+ throw new RuntimeException("Error:Should not get an Exception in equals of creds3");
+
+
+ }
+
+ try {
+ Object ObjCred = (Object)creds1.clone();
+ System.out.println ("Size of p2 is " + p2.size() +
+ "Size of ObjCred is " +
+ ((HashSet)ObjCred).size()
+ );
+ if (p2.equals(ObjCred))
+ throw new RuntimeException ("Error: Equals ObjCred");
+ else
+ throw new RuntimeException ("Error: Does not Equal Objcred");
+ } catch (SecurityException e) {
+ System.out.println("Should get an Exception in equals of creds1");
+ }
+ /* We can store only string types of creds
+ * Let us create a subject with only string type of creds
+ */
+
+ HashSet creds2 = new HashSet();
+ creds2.add("abc");
+ creds2.add("def");
+ creds2.add("ghi");
+ Subject sstring =
+ new Subject(false, //readOnly
+ Collections.singleton(new SolarisPrincipal("user")),
+ Collections.EMPTY_SET,
+ creds2);
+ p2 = sstring.getPrivateCredentials();
+ try {
+ String[] selectArray = { "exits", "Does not exist"};
+ Object ObjAr = p2.toArray(selectArray);
+ System.out.println(" No Exception in ObjAr- String");
+
+ } catch (SecurityException e) {
+ throw new RuntimeException(" Error: Exception in ObjAr- String!!");
+ }
+ /*
+ * New subject scontain1, set p3, creds4
+ */
+
+
+ HashSet creds4 = new HashSet();
+ creds4.add("abc");
+ creds4.add("def");
+ creds4.add("ghi");
+ creds4.add(new Integer(1));
+ creds4.add("Exists");
+ Subject scontain1 =
+ new Subject(false, //readOnly
+ Collections.singleton(new SolarisPrincipal("user")),
+ Collections.EMPTY_SET,
+ creds4);
+ Set p3 = scontain1.getPrivateCredentials();
+ try {
+ Object Obj = new String("Exists");
+ if (p3.contains(Obj))
+ System.out.println ("Contains String cred");
+ else
+ throw new RuntimeException ("Error Does not Contain the stringcred exists");
+ } catch (SecurityException e) {
+ throw new RuntimeException("Error:Exception!!");
+
+ }
+ try {
+ Object ObjCred = (Object)creds4.clone();
+ if (p3.equals(ObjCred))
+ throw new RuntimeException ("Error:Equals ObjCred");
+ else
+ throw new RuntimeException ("Error:Does not Equal Objcred");
+ } catch (SecurityException e) {
+ System.out.println("Should get an Exception in equals");
+ }
+
+ try {
+ Object Obj = new Integer(1);
+ if (p3.contains(Obj))
+ throw new RuntimeException ("Error:Contains integer cred");
+ else
+ throw new RuntimeException ("Error:Does not Contain integer cred");
+ } catch (SecurityException e) {
+ System.out.println("Should get an Exception in contains Integer cred");
+ }
+
+
+
+ HashSet coll = new HashSet();
+ coll.add(new String("abc"));
+ coll.add(new String("def"));
+ coll.add(new String("Exists"));
+ coll.add(new String("Does not Exist"));
+ try {
+ if (p3.containsAll(coll))
+ throw new RuntimeException ("Error: Contains the collection");
+ else
+ System.out.println ("Does not Contain the collection");
+ } catch (SecurityException e) {
+ throw new RuntimeException("Error: Exception in containsAll (string coll)!!");
+
+ }
+ coll.remove(new String("Exists"));
+ coll.remove(new String("Does not Exist"));
+ try {
+ if (p3.containsAll(coll))
+ System.out.println ("Contains the collection");
+ else
+ throw new RuntimeException ("Error:Does not Contain the collection");
+ } catch (SecurityException e) {
+ throw new RuntimeException("Error: Exception in containsAll (string coll)!!");
+ }
+
+ Object Obj = new String("Exists");
+ try {
+ if (p3.contains(Obj))
+ System.out.println ("Contains String cred exists");
+ else
+ System.out.println ("Does not Contain String cred exists");
+ } catch (SecurityException e) {
+ System.out.println("Exception in String cred!!");
+ }
+
+ Obj = new String("Does not exist");
+ try {
+ if (p3.contains(Obj))
+ throw new RuntimeException ("Error: Contains the String does not exist");
+ else
+ System.out.println ("Does not Contain the String cred Does not exist");
+ } catch (SecurityException e) {
+ throw new RuntimeException("Error: Exception in Contains!!");
+ }
+ p3.add(new Integer(2));
+ coll.add(new Integer(2));
+ p3.add("XYZ");
+
+ System.out.println ("Testing Retainall ");
+ exceptionCounter =0;
+ iter1 = p3.iterator();
+ while (iter1.hasNext())
+ {
+ try {
+ Object o = iter1.next();
+ System.out.println(" private creds of class " +
+ o.getClass() + "value is " + o.toString());
+ } catch (SecurityException e) {
+ System.out.println(" We should get exception");
+ System.out.println("Exception!!");
+ exceptionCounter++;
+ }
+ }
+ System.out.println(" After the retainall Operation");
+ try {
+ if (p3.retainAll(coll))
+ System.out.println ("Retained the collection");
+ else
+ throw new RuntimeException ("Error: RetainAll did not succeed");
+ } catch (SecurityException e) {
+ e.printStackTrace();
+ throw new RuntimeException("Error: Unexpected Exception in retainAll!");
+ }
+ iter1 = p3.iterator();
+ while (iter1.hasNext())
+ {
+ try {
+ Object o = iter1.next();
+ System.out.println(" private creds of class " +
+ o.getClass() + "value is " + o.toString());
+ } catch (SecurityException e) {
+ exceptionCounter++;
+ }
+ }
+ System.out.println ("Retainall collection");
+ p3.add(new Integer (3));
+ iter1 = p3.iterator();
+ while (iter1.hasNext()) {
+ try {
+ Object o = iter1.next();
+ System.out.println(" private creds of class " +
+ o.getClass() + "value is " + o.toString());
+ } catch (SecurityException e) {
+ System.out.println("Should get Exception ");
+ }
+ }
+ exceptionCounter=0;
+ HashSet coll2 = new HashSet();
+ coll2.add(new String("abc"));
+ coll2.add(new Integer (3));
+ System.out.println(" before removeall");
+ iter1 = p3.iterator();
+ exceptionCounter =0;
+ while (iter1.hasNext()) {
+ try {
+ Object o = iter1.next();
+ System.out.println(" private creds of class " +
+ o.getClass() + "value is " + o.toString());
+ } catch (SecurityException e) {
+ System.out.println("Expected Exception thrown ");
+ exceptionCounter++;
+ }
+ }
+ // We added two integer creds so there must be two exceptions only
+
+ if (exceptionCounter != 2) {
+ throw new RuntimeException("Expected 2 Exceptions; received " +
+ exceptionCounter + "exceptions ");
+ }
+
+ try {
+ p3.removeAll(coll2);
+ System.out.println(" removeall successful! ");
+ } catch (SecurityException e) {
+ throw new RuntimeException(" Error: removeAll Security Exception!!");
+ }
+
+ iter1 = p3.iterator();
+ System.out.println(" After removeall");
+ exceptionCounter = 0;
+ while (iter1.hasNext()) {
+ try {
+ Object o = iter1.next();
+ System.out.println (" private creds of class " +
+ o.getClass() + "value is " + o.toString());
+ } catch (SecurityException e) {
+ System.out.println("Expected Exception thrown ");
+ exceptionCounter++;
+ }
+ }
+ // We had two integer creds; removed one as a part of coll2; so
+ // only one exception must have been thrown
+ if (exceptionCounter != 1) {
+ throw new RuntimeException("Expected 1 Exceptions; received " +
+ exceptionCounter + "exceptions ");
+ }
+ try {
+ p3.clear();
+ System.out.println(" Clear() successful! ");
+ } catch (SecurityException e) {
+ throw new RuntimeException(" Error: Clear Security Exception!!");
+ }
+
+
+ /* New subject s with creds and privCredSet
+ *
+ */
+ creds.clear();
+ creds.add("abc");
+ creds.add("def");
+ creds.add("ghi");
+ creds.add(new Integer(1));
+ Subject s =
+ new Subject(false, //readOnly
+ Collections.singleton(new SolarisPrincipal("user")),
+ Collections.EMPTY_SET,
+ creds);
+ try {
+ Set privCredSet = s.getPrivateCredentials(char.class);
+ if (privCredSet.size() != 0) {
+ throw new RuntimeException("Error:String Privcred size should have been 0 and was " +
+ privCredSet.size());
+ }
+
+ } catch (Exception e) {
+ throw new RuntimeException ("Error " + e.toString());
+ }
+
+
+ try {
+ Set privCredSet = s.getPrivateCredentials(String.class);
+ if (privCredSet.size() != 3) {
+ throw new RuntimeException("Error:String Privcred size should have been 2 and was " +
+ privCredSet.size());
+ }
+ s.getPrivateCredentials().add("XYZ");
+ /*
+ * Since the privCredSet is not backed by internal private
+ * creds adding to it should not make any difference to
+ * privCredSet and theize should still be 3
+ */
+
+ if (privCredSet.size() != 3) {
+ throw new RuntimeException("Error:String Privcred size should have been 2 and was " +
+ privCredSet.size());
+ }
+ s.getPrivateCredentials().remove("XYZ");
+ /*
+ * Let us try to get the elements
+ * No exception should occur
+ */
+
+ Iterator iter = privCredSet.iterator();
+ while (iter.hasNext()) {
+ try {
+ Object o = iter.next();
+ System.out.println(" private creds of class " +
+ o.getClass() + "value is " + o.toString());
+ } catch (SecurityException e) {
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException("Unexcpected Exception");
+ }
+
+ /*
+ * Can we add and remove the creds
+ */
+ s.getPrivateCredentials().add("XYZ");
+ s.getPrivateCredentials().remove("XYZ");
+ s.getPrivateCredentials().add(new Integer(2));
+ s.getPrivateCredentials().remove(new Integer(2));
+
+
+ // We don't have permission to read Boolean creds
+ // SInce the creds have no boolean creds we should get an empty
+ // set
+ try {
+ Set privCredSet1 = s.getPrivateCredentials(Boolean.class);
+ if (privCredSet1.size() != 0){
+ throw new RuntimeException("Error:String PrivcredSet1 of Boolean size should have been 0 and was " +
+ privCredSet1.size());
+ }
+ } catch (SecurityException e) {
+ e.printStackTrace();
+ throw new RuntimeException("Unexcpected Exception");
+ }
+ System.out.println ("Checked Boolean Creds ");
+
+ /*
+ * We don't have permission to read Integer creds
+ * We should get an empty set even though the private creds
+ * has an integer cred. No security exception either !
+ */
+
+ try {
+ Set privCredSet1 = s.getPrivateCredentials(Integer.class);
+ if (privCredSet1.size() != 0){
+ throw new RuntimeException("Error:String PrivcredSet1 of Integer size should have been 0 and was " +
+ privCredSet1.size());
+ }
+ } catch (SecurityException e) {
+ System.out.println ("Expected exception");
+ }
+ System.out.println ("Checked Integer Creds ");
+
+ Set privCredSet2 = s.getPrivateCredentials();
+
+ if (privCredSet2.size() != 4){
+ throw new RuntimeException("Error:String PrivcredSet1 size should have been 4 and was " +
+ privCredSet2.size());
+ }
+
+ /*
+ * Since the returned privCredSet2 is internally backed by the
+ * private creds, any additions to it should be reflected in
+ * privcredSet2
+ */
+ s.getPrivateCredentials().add("XYZ");
+ if (privCredSet2.size() != 5) {
+ throw new RuntimeException("Error:String PrivcredSet1 size should have been 5 and was " +
+ privCredSet2.size());
+ }
+ s.getPrivateCredentials().remove("XYZ");
+ if (privCredSet2.size() != 4) {
+ throw new RuntimeException("String privCredSet2 size should have been 5 and was " +
+ privCredSet2.size());
+ }
+ System.out.println("Checked remove(String) operation");
+ /* Let us add a couple of Boolean creds */
+ s.getPrivateCredentials().add(Boolean.TRUE);
+ s.getPrivateCredentials().add(new Integer(2));
+
+ exceptionCounter =0;
+ iter1 = privCredSet2.iterator();
+ while (iter1.hasNext())
+ {
+ try {
+ Object o = iter1.next();
+ System.out.println(" private creds of class " +
+ o.getClass() + "value is " + o.toString());
+ } catch (SecurityException e) {
+ System.out.println(" We should get exception");
+ System.out.println("Exception!!");
+ exceptionCounter++;
+ }
+ }
+ if (exceptionCounter != 3) {
+ throw new RuntimeException("Expected number of exception was 3 " +
+ "The actual number was " + exceptionCounter);
+ }
+ privCredSet2.add (new Integer(3));
+ try {
+ int hashCode = privCredSet2.hashCode();
+ } catch (SecurityException e) {
+ System.out.println ("hashCode Expected exception");
+ }
+ System.out.println ("Tests completed");
+ }
+
+}
diff --git a/test/javax/security/auth/PrivateCredentialPermission/Subset.policy b/test/javax/security/auth/PrivateCredentialPermission/Subset.policy
new file mode 100644
index 0000000..efb3a0f
--- /dev/null
+++ b/test/javax/security/auth/PrivateCredentialPermission/Subset.policy
@@ -0,0 +1,10 @@
+grant {
+ permission java.security.SecurityPermission "getProperty.combiner.provider";
+ permission java.util.PropertyPermission "*", "read";
+ permission java.lang.RuntimePermission "*";
+};
+grant {
+ permission javax.security.auth.AuthPermission "modifyPrivateCredentials";
+ permission javax.security.auth.AuthPermission "modifyPublicCredentials";
+ permission javax.security.auth.PrivateCredentialPermission "java.lang.String com.sun.security.auth.SolarisPrincipal \"user\"", "read";
+};
diff --git a/test/javax/security/auth/Subject/Generic.java b/test/javax/security/auth/Subject/Generic.java
new file mode 100644
index 0000000..ff243a1
--- /dev/null
+++ b/test/javax/security/auth/Subject/Generic.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6219304
+ * @summary Subject.doAs* should be generified
+ */
+
+import java.security.*;
+import javax.security.auth.*;
+
+public class Generic {
+ public static void main(String[] args) throws Exception {
+ String foo = Subject.doAs(new Subject(),
+ new A1<String>("foo"));
+
+ Integer one = Subject.doAs(new Subject(),
+ new A2<Integer>(new Integer("1")));
+
+ Boolean troo = Subject.doAsPrivileged(new Subject(),
+ new A1<Boolean>(new Boolean("true")),
+ AccessController.getContext());
+
+ Generic gen = Subject.doAsPrivileged(new Subject(),
+ new A2<Generic>(new Generic()),
+ AccessController.getContext());
+ }
+
+ private static class A1<T> implements PrivilegedAction<T> {
+ T t;
+
+ public A1(T t) {
+ this.t = t;
+ }
+
+ public T run() {
+ return t;
+ }
+ }
+
+ private static class A2<T> implements PrivilegedExceptionAction<T> {
+ T t;
+
+ public A2(T t) {
+ this.t = t;
+ }
+
+ public T run() throws PrivilegedActionException {
+ return t;
+ }
+ }
+}
diff --git a/test/javax/security/auth/Subject/Serial.java b/test/javax/security/auth/Subject/Serial.java
new file mode 100644
index 0000000..753cb2b
--- /dev/null
+++ b/test/javax/security/auth/Subject/Serial.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2000-2002 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4364826
+ * @summary Subject serialized principal set is
+ * implementation-dependent class
+ * @run main/othervm/policy=Serial.policy Serial
+ */
+
+import javax.security.auth.*;
+import java.io.*;
+import java.util.*;
+
+public class Serial implements java.io.Serializable {
+
+ public static void main(String[] args) {
+
+ try {
+ FileOutputStream fos = new FileOutputStream("serial.tmp");
+ ObjectOutputStream oos = new ObjectOutputStream(fos);
+
+ HashSet principals = new HashSet();
+ principals.add
+ (new com.sun.security.auth.NTUserPrincipal("test"));
+ principals.add
+ (new com.sun.security.auth.NTDomainPrincipal("test2"));
+
+ Subject s = new Subject
+ (false,
+ principals,
+ new HashSet(),
+ new HashSet());
+ oos.writeObject(s);
+ oos.flush();
+ fos.close();
+
+ FileInputStream fis = new FileInputStream("serial.tmp");
+ ObjectInputStream ois = new ObjectInputStream(fis);
+
+ Subject s2 = (Subject)ois.readObject();
+ fis.close();
+
+ System.out.println("s2 = " + s2.toString());
+ System.out.println("s2.getPrincipals().size() = " +
+ s2.getPrincipals().size());
+ if (!s.equals(s2) || !s2.equals(s)) {
+ throw new SecurityException("Serial test failed: " +
+ "EQUALS TEST FAILED");
+ }
+
+ // make sure private credentials are not serializable
+ // without permissions
+
+ Set privateCredentials = s.getPrivateCredentials();
+ privateCredentials.add(new Serial());
+
+ fos = new FileOutputStream("serial2.tmp");
+ oos = new ObjectOutputStream(fos);
+ try {
+ oos.writeObject(privateCredentials);
+ oos.flush();
+ fos.close();
+ throw new RuntimeException("Serial test failed: " +
+ "allowed to serialize private credential set");
+ } catch (SecurityException se) {
+ // good
+ se.printStackTrace();
+ }
+
+ System.out.println("Serial test succeeded");
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new SecurityException("Serial test failed");
+ }
+ }
+}
diff --git a/test/javax/security/auth/Subject/Serial.policy b/test/javax/security/auth/Subject/Serial.policy
new file mode 100644
index 0000000..161d52a
--- /dev/null
+++ b/test/javax/security/auth/Subject/Serial.policy
@@ -0,0 +1,5 @@
+grant {
+ permission java.io.FilePermission "serial.tmp", "read,write";
+ permission java.io.FilePermission "serial2.tmp", "read,write";
+ permission javax.security.auth.AuthPermission "modifyPrivateCredentials";
+};
diff --git a/test/javax/security/auth/Subject/Synch.java b/test/javax/security/auth/Subject/Synch.java
new file mode 100644
index 0000000..d60759f
--- /dev/null
+++ b/test/javax/security/auth/Subject/Synch.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4893489
+ * @summary Subject.doAs not thread-safe against changes to principals
+ */
+
+import java.security.Principal;
+import java.security.PrivilegedAction;
+import java.util.Collections;
+import java.util.Set;
+import javax.security.auth.Subject;
+import javax.security.auth.x500.X500Principal;
+
+public class Synch {
+ public static void main(String[] args) {
+ Subject subject = new Subject();
+ final Set principals = subject.getPrincipals();
+ principals.add(new X500Principal("CN=Alice"));
+ new Thread() {
+ { setDaemon(true); }
+ public void run() {
+ Principal last = new X500Principal("CN=Bob");
+ for (int i = 0; true; i++) {
+ Principal next = new X500Principal("CN=Bob" + i);
+ principals.add(next);
+ principals.remove(last);
+ last = next;
+ }
+ }
+ }.start();
+ for (int i = 0; i < 1000; i++) {
+ Subject.doAs(
+ subject,
+ new PrivilegedAction() {
+ public Object run() {
+ return Subject.doAs(
+ new Subject(true,
+ Collections.singleton(
+ new X500Principal("CN=Claire")),
+ Collections.EMPTY_SET,
+ Collections.EMPTY_SET),
+ new PrivilegedAction() {
+ public Object run() {
+ return null;
+ }
+ });
+ }
+ });
+ }
+ }
+}
diff --git a/test/javax/security/auth/Subject/Synch2.java b/test/javax/security/auth/Subject/Synch2.java
new file mode 100644
index 0000000..1763e18
--- /dev/null
+++ b/test/javax/security/auth/Subject/Synch2.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4892913
+ * @summary Subject.getPrivateCredentials not thread-safe against changes to
+ * principals
+ * @run main/othervm/policy=Synch2.policy Synch2
+ */
+
+import java.util.Iterator;
+import java.util.Set;
+import javax.security.auth.Subject;
+import javax.security.auth.x500.X500Principal;
+
+public class Synch2 {
+ public static void main(String[] args) {
+ System.setSecurityManager(new SecurityManager());
+ Subject subject = new Subject();
+ final Set principals = subject.getPrincipals();
+ principals.add(new X500Principal("CN=Alice"));
+ final Set credentials = subject.getPrivateCredentials();
+ credentials.add("Dummy credential");
+ new Thread() {
+ {
+ setDaemon(true);
+ start();
+ }
+ public void run() {
+ X500Principal p = new X500Principal("CN=Bob");
+ while (true) {
+ principals.add(p);
+ principals.remove(p);
+ }
+ }
+ };
+ for (int i = 0; i < 1000; i++) {
+ synchronized (credentials) {
+ for (Iterator it = credentials.iterator(); it.hasNext(); ) {
+ it.next();
+ }
+ }
+ }
+ }
+}
diff --git a/test/javax/security/auth/Subject/Synch2.policy b/test/javax/security/auth/Subject/Synch2.policy
new file mode 100644
index 0000000..cb9dbed
--- /dev/null
+++ b/test/javax/security/auth/Subject/Synch2.policy
@@ -0,0 +1,3 @@
+grant {
+ permission java.security.AllPermission;
+};
diff --git a/test/javax/security/auth/Subject/Synch3.java b/test/javax/security/auth/Subject/Synch3.java
new file mode 100644
index 0000000..b90d798
--- /dev/null
+++ b/test/javax/security/auth/Subject/Synch3.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4892841
+ * @summary Subject.getPrincipals(Class) not thread-safe against changes to
+ * principals
+ */
+
+import java.util.Set;
+import javax.security.auth.Subject;
+import javax.security.auth.x500.X500Principal;
+
+public class Synch3 {
+ public static void main(String[] args) {
+ Subject subject = new Subject();
+ final Set principals = subject.getPrincipals();
+ principals.add(new X500Principal("CN=Alice"));
+ new Thread() {
+ {
+ setDaemon(true);
+ start();
+ }
+ public void run() {
+ X500Principal p = new X500Principal("CN=Bob");
+ while (true) {
+ principals.add(p);
+ principals.remove(p);
+ }
+ }
+ };
+ for (int i = 0; i < 1000; i++) {
+ subject.getPrincipals(X500Principal.class);
+ }
+ }
+}
diff --git a/test/javax/security/auth/Subject/doAs/Test.java b/test/javax/security/auth/Subject/doAs/Test.java
new file mode 100644
index 0000000..18589ef
--- /dev/null
+++ b/test/javax/security/auth/Subject/doAs/Test.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2001 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import javax.security.auth.Subject;
+import javax.security.auth.x500.X500Principal;
+import java.security.*;
+import java.util.*;
+
+public class Test {
+ public static Subject get(String name) {
+ return new Subject(true,
+ Collections.singleton(new X500Principal(name)),
+ new HashSet(),
+ Collections.singleton(Boolean.TRUE));
+ }
+
+ public static void main(String[] args) {
+ System.setSecurityManager(new SecurityManager());
+ try {
+ Subject.doAsPrivileged(get("CN=joe"), new PrivilegedAction() {
+ public Object run() {
+ return Subject.doAs(null, new PrivilegedAction() {
+ public Object run() {
+ return System.getProperty("foobar");
+ }
+ });
+ }
+ }, null);
+ throw new RuntimeException
+ ("Access control exception should have occcured");
+ } catch (java.security.AccessControlException e) {
+ // Expected exception occured
+ }
+ }
+}
diff --git a/test/javax/security/auth/Subject/doAs/Test.sh b/test/javax/security/auth/Subject/doAs/Test.sh
new file mode 100644
index 0000000..9844c99
--- /dev/null
+++ b/test/javax/security/auth/Subject/doAs/Test.sh
@@ -0,0 +1,69 @@
+#! /bin/sh
+
+#
+# Copyright 2001-2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+# @test 1.1, 02/14/01
+# @author Ram Marti
+# @bug 4399067
+# @summary Subject.doAs(null, action) does not clear the executing
+#
+# ${TESTJAVA} is pointing to the jre
+#
+# set platform-dependent variables
+OS=`uname -s`
+case "$OS" in
+ SunOS )
+ PS=":"
+ FS="/"
+ RM="/bin/rm -f"
+ ;;
+ Linux )
+ PS=":"
+ FS="/"
+ RM="/bin/rm -f"
+ ;;
+ Windows* )
+ PS=";"
+ FS="\\"
+ RM="rm"
+ ;;
+ * )
+ echo "Unrecognized system!"
+ exit 1;
+ ;;
+esac
+# remove any leftover built class
+cd ${TESTCLASSES}${FS}
+${RM} Test.class
+${TESTJAVA}${FS}bin${FS}javac -d ${TESTCLASSES}${FS} ${TESTSRC}${FS}Test.java
+WD=`pwd`
+cd ${TESTSRC}${FS}
+cd $WD
+echo $WD
+${TESTJAVA}${FS}bin${FS}java -classpath "${TESTCLASSES}${FS}" \
+-Djava.security.manager \
+-Djava.security.policy=${TESTSRC}${FS}policy \
+Test
+
+exit $?
diff --git a/test/javax/security/auth/Subject/doAs/policy b/test/javax/security/auth/Subject/doAs/policy
new file mode 100644
index 0000000..3a2eb62
--- /dev/null
+++ b/test/javax/security/auth/Subject/doAs/policy
@@ -0,0 +1,10 @@
+grant {
+ permission javax.security.auth.AuthPermission "doAs";
+ permission javax.security.auth.AuthPermission "doAsPrivileged";
+ permission java.lang.RuntimePermission "createSecurityManager";
+ permission java.lang.RuntimePermission "setSecurityManager";
+};
+
+grant principal javax.security.auth.x500.X500Principal "CN=joe" {
+ permission java.util.PropertyPermission "foobar", "read";
+};
diff --git a/test/javax/security/auth/SubjectDomainCombiner/Optimize.java b/test/javax/security/auth/SubjectDomainCombiner/Optimize.java
new file mode 100644
index 0000000..cf3a8aa
--- /dev/null
+++ b/test/javax/security/auth/SubjectDomainCombiner/Optimize.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2000-2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4887017
+ * @summary SubjectDomainCombiner optimization incorrect
+ */
+
+import javax.security.auth.Subject;
+import javax.security.auth.SubjectDomainCombiner;
+import java.security.*;
+
+public class Optimize {
+
+ public static void main(String[] args) {
+
+ ProtectionDomain pd1 = new ProtectionDomain(
+ new CodeSource(null, (java.security.cert.Certificate[]) null),
+ new Permissions());
+ ProtectionDomain pd2 = new ProtectionDomain(
+ new CodeSource(null, (java.security.cert.Certificate[]) null),
+ new Permissions());
+ ProtectionDomain pd3 = new ProtectionDomain(
+ new CodeSource(null, (java.security.cert.Certificate[]) null),
+ new Permissions());
+
+ ProtectionDomain[] current = new ProtectionDomain[] {pd1, pd2};
+ ProtectionDomain[] assigned = new ProtectionDomain[] {pd3, pd2};
+
+ SubjectDomainCombiner sdc = new SubjectDomainCombiner(new Subject());
+ ProtectionDomain[] combined = sdc.combine(current, assigned);
+
+ // this depends on current SubjectDomainCombiner implementation
+ // (ordering of returned domains)
+ if (combined.length == 4 &&
+ combined[0] != pd1 && combined[1] != pd2 &&
+ combined[2] == pd3 && combined[3] == pd2) {
+ System.out.println("test passed");
+ } else {
+ System.out.println("test failed");
+ throw new SecurityException("Test Failed");
+ }
+ }
+}
diff --git a/test/javax/security/auth/SubjectDomainCombiner/Regression.java b/test/javax/security/auth/SubjectDomainCombiner/Regression.java
new file mode 100644
index 0000000..ff1902e
--- /dev/null
+++ b/test/javax/security/auth/SubjectDomainCombiner/Regression.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2000-2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4390546
+ * @summary performance regression and other bugs in
+ * SubjectDomainCombiner.combine
+ *
+ * @run main/othervm/policy=Regression.policy -Djava.security.auth.debug=combiner Regression
+ */
+
+import javax.security.auth.*;
+import java.security.ProtectionDomain;
+import java.security.CodeSource;
+import java.net.URL;
+import java.util.Set;
+import java.util.HashSet;
+
+public class Regression {
+
+ public static void main(String[] args) {
+
+ Set principals = new HashSet();
+ principals.add(new com.sun.security.auth.NTUserPrincipal("test1"));
+ principals.add(new com.sun.security.auth.NTUserPrincipal("test2"));
+
+ Subject subject = new Subject
+ (false, principals, new HashSet(), new HashSet());
+
+ SubjectDomainCombiner sdc = new SubjectDomainCombiner(subject);
+
+ URL url1;
+ URL url2;
+ URL url3;
+ URL url4;
+ try {
+ url1 = new URL("http://one");
+ url2 = new URL("http://two");
+ url3 = new URL("http://three");
+ url4 = new URL("http://four");
+ } catch (java.net.MalformedURLException mue) {
+ mue.printStackTrace();
+ throw new SecurityException("Test failed: " + mue.toString());
+ }
+
+ ProtectionDomain d1 = new ProtectionDomain
+ (new CodeSource(url1,
+ (java.security.cert.Certificate[]) null),
+ null, // permissions
+ null, // class loader
+ null); // principals
+ ProtectionDomain d2 = new ProtectionDomain
+ (new CodeSource(url2,
+ (java.security.cert.Certificate[]) null),
+ null, // permissions
+ null, // class loader
+ null); // principals
+ ProtectionDomain d3 = new ProtectionDomain
+ (new CodeSource(url3,
+ (java.security.cert.Certificate[]) null),
+ null, // permissions
+ null, // class loader
+ null); // principals
+ ProtectionDomain d4 = new ProtectionDomain
+ (new CodeSource(url4,
+ (java.security.cert.Certificate[]) null),
+ null, // permissions
+ null, // class loader
+ null); // principals
+
+ // test 1
+ // -- regular combine, make sure we get a proper combination back
+
+ ProtectionDomain currentDomains[] = { d1, d2, d3 };
+ ProtectionDomain assignedDomains[] = { d4 };
+ ProtectionDomain domains1[] = sdc.combine
+ (currentDomains, assignedDomains);
+
+ if (domains1.length != 4 ||
+ domains1[0] == d1 || domains1[1] == d2 || domains1[2] == d3 ||
+ domains1[3] != d4 ||
+ !domains1[0].implies(new RuntimePermission("queuePrintJob"))) {
+ throw new SecurityException("Test failed: combine test 1 failed");
+ }
+
+ System.out.println("-------- TEST ONE PASSED --------");
+
+ // test 2
+ // -- repeat combine, make sure combiner cachine returned the
+ // same PD's back
+
+ ProtectionDomain domains2[] = sdc.combine
+ (currentDomains, assignedDomains);
+ if (domains2.length != 4 ||
+ domains2[0] != domains1[0] || domains2[1] != domains1[1] ||
+ domains2[2] != domains1[2] ||
+ domains2[3] != domains1[3] ||
+ !domains2[0].implies(new RuntimePermission("queuePrintJob"))) {
+ throw new SecurityException("Test failed: combine test 2 failed");
+ }
+
+ System.out.println("-------- TEST TWO PASSED --------");
+
+ // test 3
+ // -- mutate the Subject and make sure the combiner cache
+ // got cleared out
+
+ subject.getPrincipals().remove
+ (new com.sun.security.auth.NTUserPrincipal("test2"));
+ ProtectionDomain domains3[] = sdc.combine
+ (currentDomains, assignedDomains);
+ if (domains3.length != 4 ||
+ domains3[0] == domains1[0] || domains3[1] == domains1[1] ||
+ domains3[2] == domains1[2] ||
+ domains3[3] != domains1[3] ||
+ !domains3[0].implies(new RuntimePermission("createClassLoader")) ||
+ domains3[0].implies(new RuntimePermission("queuePrintJob"))) {
+ throw new SecurityException("Test failed: combine test 3 failed");
+ }
+
+ System.out.println("-------- TEST THREE PASSED --------");
+
+ System.out.println("Test Passed");
+ }
+}
diff --git a/test/javax/security/auth/SubjectDomainCombiner/Regression.policy b/test/javax/security/auth/SubjectDomainCombiner/Regression.policy
new file mode 100644
index 0000000..ae29a1d
--- /dev/null
+++ b/test/javax/security/auth/SubjectDomainCombiner/Regression.policy
@@ -0,0 +1,12 @@
+grant {
+ permission javax.security.auth.AuthPermission "modifyPrincipals";
+};
+
+grant principal com.sun.security.auth.NTUserPrincipal "test1" {
+ permission java.lang.RuntimePermission "createClassLoader";
+};
+
+grant principal com.sun.security.auth.NTUserPrincipal "test1",
+ principal com.sun.security.auth.NTUserPrincipal "test2" {
+ permission java.lang.RuntimePermission "queuePrintJob";
+};
diff --git a/test/javax/security/auth/kerberos/KerberosHashEqualsTest.java b/test/javax/security/auth/kerberos/KerberosHashEqualsTest.java
new file mode 100644
index 0000000..8b4b1b4
--- /dev/null
+++ b/test/javax/security/auth/kerberos/KerberosHashEqualsTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4641821
+ * @summary hashCode() and equals() for KerberosKey and KerberosTicket
+ * @ignore Must set up KDC and setup Kerberos configuration file
+ */
+
+import java.net.InetAddress;
+import java.util.Date;
+import javax.security.auth.kerberos.KerberosKey;
+import javax.security.auth.kerberos.KerberosPrincipal;
+import javax.security.auth.kerberos.KerberosTicket;
+
+public class KerberosHashEqualsTest {
+ public static void main(String[] args) throws Exception {
+ new KerberosHashEqualsTest().check();
+ }
+
+ void checkSame(Object o1, Object o2) {
+ if(!o1.equals(o2)) {
+ throw new RuntimeException("equals() fails");
+ }
+ if(o1.hashCode() != o2.hashCode()) {
+ throw new RuntimeException("hashCode() not same");
+ }
+ }
+
+ void checkNotSame(Object o1, Object o2) {
+ if(o1.equals(o2)) {
+ throw new RuntimeException("equals() succeeds");
+ }
+ }
+
+ void check() throws Exception {
+ KerberosKey k1, k2;
+ k1 = new KerberosKey(new KerberosPrincipal("A"), "pass".getBytes(), 1, 1);
+ k2 = new KerberosKey(new KerberosPrincipal("A"), "pass".getBytes(), 1, 1);
+ checkSame(k1, k1); // me to me
+ checkSame(k1, k2); // same
+
+ k2.destroy();
+ checkNotSame(k1, k2);
+
+ // destroyed keys doesn't equal to each other
+ checkNotSame(k2, k1);
+ checkSame(k2, k2);
+
+ // a little different
+ k2 = new KerberosKey(new KerberosPrincipal("B"), "pass".getBytes(), 1, 1);
+ checkNotSame(k1, k2);
+ k2 = new KerberosKey(new KerberosPrincipal("A"), "ssap".getBytes(), 1, 1);
+ checkNotSame(k1, k2);
+ k2 = new KerberosKey(new KerberosPrincipal("A"), "pass".getBytes(), 2, 1);
+ checkNotSame(k1, k2);
+ k2 = new KerberosKey(new KerberosPrincipal("A"), "pass".getBytes(), 1, 2);
+ checkNotSame(k1, k2);
+
+ k1 = new KerberosKey(null, "pass".getBytes(), 1, 2);
+ checkNotSame(k1, k2); // null to non-null
+ k2 = new KerberosKey(null, "pass".getBytes(), 1, 2);
+ checkSame(k1, k2); // null to null
+
+ checkNotSame(k1, "Another Object");
+
+ KerberosTicket t1, t2;
+ t1 = new KerberosTicket("asn1".getBytes(), new KerberosPrincipal("client"), new KerberosPrincipal("server"), "pass".getBytes(), 1, new boolean[] {true, true}, new Date(0), new Date(0), new Date(0), new Date(0), null);
+ t2 = new KerberosTicket("asn1".getBytes(), new KerberosPrincipal("client"), new KerberosPrincipal("server"), "pass".getBytes(), 1, new boolean[] {true, true}, new Date(0), new Date(0), new Date(0), new Date(0), null);
+ checkSame(t1, t1);
+ checkSame(t1, t2);
+ t2 = new KerberosTicket("asn11".getBytes(), new KerberosPrincipal("client"), new KerberosPrincipal("server"), "pass".getBytes(), 1, new boolean[] {true, true}, new Date(0), new Date(0), new Date(0), new Date(0), null);
+ checkNotSame(t1, t2);
+ t2 = new KerberosTicket("asn1".getBytes(), new KerberosPrincipal("client1"), new KerberosPrincipal("server"), "pass".getBytes(), 1, new boolean[] {true, true}, new Date(0), new Date(0), new Date(0), new Date(0), null);
+ checkNotSame(t1, t2);
+ t2 = new KerberosTicket("asn1".getBytes(), new KerberosPrincipal("client"), new KerberosPrincipal("server1"), "pass".getBytes(), 1, new boolean[] {true, true}, new Date(0), new Date(0), new Date(0), new Date(0), null);
+ checkNotSame(t1, t2);
+ t2 = new KerberosTicket("asn1".getBytes(), new KerberosPrincipal("client"), new KerberosPrincipal("server"), "pass1".getBytes(), 1, new boolean[] {true, true}, new Date(0), new Date(0), new Date(0), new Date(0), null);
+ checkNotSame(t1, t2);
+ t2 = new KerberosTicket("asn1".getBytes(), new KerberosPrincipal("client"), new KerberosPrincipal("server"), "pass".getBytes(), 2, new boolean[] {true, true}, new Date(0), new Date(0), new Date(0), new Date(0), null);
+ checkNotSame(t1, t2);
+ t2 = new KerberosTicket("asn1".getBytes(), new KerberosPrincipal("client"), new KerberosPrincipal("server"), "pass".getBytes(), 1, new boolean[] {false, true}, new Date(0), new Date(0), new Date(0), new Date(0), null);
+ checkNotSame(t1, t2);
+ t2 = new KerberosTicket("asn1".getBytes(), new KerberosPrincipal("client"), new KerberosPrincipal("server"), "pass".getBytes(), 1, new boolean[] {true, true}, new Date(1), new Date(0), new Date(0), new Date(0), null);
+ checkNotSame(t1, t2);
+ t2 = new KerberosTicket("asn1".getBytes(), new KerberosPrincipal("client"), new KerberosPrincipal("server"), "pass".getBytes(), 1, new boolean[] {true, true}, new Date(0), new Date(1), new Date(0), new Date(0), null);
+ checkNotSame(t1, t2);
+ t2 = new KerberosTicket("asn1".getBytes(), new KerberosPrincipal("client"), new KerberosPrincipal("server"), "pass".getBytes(), 1, new boolean[] {true, true}, new Date(0), new Date(0), new Date(1), new Date(0), null);
+ checkNotSame(t1, t2);
+ t2 = new KerberosTicket("asn1".getBytes(), new KerberosPrincipal("client"), new KerberosPrincipal("server"), "pass".getBytes(), 1, new boolean[] {true, true}, new Date(0), new Date(0), new Date(0), new Date(0), new InetAddress[2]);
+ checkNotSame(t1, t2);
+
+ t2 = new KerberosTicket("asn1".getBytes(), new KerberosPrincipal("client"), new KerberosPrincipal("server"), "pass".getBytes(), 1, new boolean[] {true, true}, new Date(0), new Date(0), new Date(0), new Date(1), null);
+ t1 = new KerberosTicket("asn1".getBytes(), new KerberosPrincipal("client"), new KerberosPrincipal("server"), "pass".getBytes(), 1, new boolean[] {true, true}, new Date(0), new Date(0), new Date(0), new Date(2), null);
+ checkSame(t1, t2); // renewtill is useless
+
+ t2.destroy();
+ checkNotSame(t1, t2);
+
+ // destroyed tickets doesn't equal to each other
+ checkNotSame(t2, t1);
+ checkSame(t2, t2);
+
+ t2 = new KerberosTicket("asn1".getBytes(), new KerberosPrincipal("client"), new KerberosPrincipal("server"), "pass".getBytes(), 1, new boolean[] {true, true, true, true, true, true, true, true, true, true}, new Date(0), new Date(0), new Date(0), new Date(1), null);
+ t1 = new KerberosTicket("asn1".getBytes(), new KerberosPrincipal("client"), new KerberosPrincipal("server"), "pass".getBytes(), 1, new boolean[] {true, true, true, true, true, true, true, true, true, true}, new Date(0), new Date(0), new Date(0), new Date(2), null);
+ checkNotSame(t1, t2); // renewtill is useful
+
+ checkNotSame(t1, "Another Object");
+ System.out.println("Good!");
+ }
+}
diff --git a/test/javax/security/auth/kerberos/ServicePermissionTest.java b/test/javax/security/auth/kerberos/ServicePermissionTest.java
new file mode 100644
index 0000000..4975803
--- /dev/null
+++ b/test/javax/security/auth/kerberos/ServicePermissionTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5032593
+ * @summary extraneous null check
+ */
+
+import javax.security.auth.kerberos.ServicePermission;
+
+public class ServicePermissionTest {
+ public static void main(String[] args) throws Exception {
+ try {
+ // the constructor will call getMask(String)
+ ServicePermission sp = new ServicePermission("you", null);
+ } catch(NullPointerException e) {
+ System.out.println("NullPointerException caught: OK");
+ e.printStackTrace(System.out);
+ return;
+ }
+ throw new Exception("Test Failed: Not behaved as descibed.");
+ }
+}
diff --git a/test/javax/security/auth/login/Configuration/GetInstance.bad.configURI b/test/javax/security/auth/login/Configuration/GetInstance.bad.configURI
new file mode 100644
index 0000000..751105b
--- /dev/null
+++ b/test/javax/security/auth/login/Configuration/GetInstance.bad.configURI
@@ -0,0 +1,3 @@
+{
+ Module required;
+};
diff --git a/test/javax/security/auth/login/Configuration/GetInstance.config b/test/javax/security/auth/login/Configuration/GetInstance.config
new file mode 100644
index 0000000..32c87c1
--- /dev/null
+++ b/test/javax/security/auth/login/Configuration/GetInstance.config
@@ -0,0 +1,14 @@
+one {
+ com.foo.Module required;
+};
+
+two {
+ com.foo.Module sufficient;
+ com.bar.Module required;
+};
+
+three {
+ com.foo.Module sufficient;
+ com.bar.Module required;
+ com.foobar.Module optional;
+};
diff --git a/test/javax/security/auth/login/Configuration/GetInstance.configURI b/test/javax/security/auth/login/Configuration/GetInstance.configURI
new file mode 100644
index 0000000..82a1c3f
--- /dev/null
+++ b/test/javax/security/auth/login/Configuration/GetInstance.configURI
@@ -0,0 +1,6 @@
+four {
+ com.foo.Module sufficient;
+ com.bar.Module required;
+ com.foobar.Module optional;
+ Module required;
+};
diff --git a/test/javax/security/auth/login/Configuration/GetInstance.java b/test/javax/security/auth/login/Configuration/GetInstance.java
new file mode 100644
index 0000000..815fdc6
--- /dev/null
+++ b/test/javax/security/auth/login/Configuration/GetInstance.java
@@ -0,0 +1,346 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6268315
+ * @bug 6273812
+ * @summary Configuration should be provider-based
+ * @build GetInstanceConfigSpi GetInstanceProvider
+ * @run main/othervm -Djava.security.auth.login.config==${test.src}${/}GetInstance.config GetInstance
+ */
+
+import javax.security.auth.login.*;
+
+import java.security.*;
+import java.io.File;
+import java.net.URI;
+
+public class GetInstance {
+
+ private static final String JAVA_CONFIG = "JavaLoginConfig";
+
+ private static final String MOD0 = "com.foo.Module";
+ private static final String MOD1 = "com.bar.Module";
+ private static final String MOD2 = "com.foobar.Module";
+ private static final String MOD3 = "Module";
+
+ private static class BadParam implements Configuration.Parameters { }
+
+ public static void main(String[] args) throws Exception {
+
+ int testnum = 1;
+ GetInstance gi = new GetInstance();
+
+ testnum = gi.testDefault(testnum);
+ testnum = gi.testStringProvider(testnum);
+ testnum = gi.testProvider(testnum);
+ testnum = gi.testCustomImpl(testnum);
+ testnum = gi.testURIParam(testnum);
+ testnum = gi.testException(testnum);
+ }
+
+ private int testDefault(int testnum) throws Exception {
+ // get an instance of the default ConfigSpiFile
+ Configuration c = Configuration.getInstance(JAVA_CONFIG, null);
+ doTest(c, testnum++);
+
+ // get an instance of FooConfig
+ try {
+ c = Configuration.getInstance("FooConfig", null);
+ throw new SecurityException("test " + testnum++ + " failed");
+ } catch (NoSuchAlgorithmException nsae) {
+ // good
+ System.out.println("test " + testnum++ + " passed");
+ }
+
+ return testnum;
+ }
+
+ private int testStringProvider(int testnum) throws Exception {
+ // get an instance of JavaLoginConfig from SUN
+ Configuration c = Configuration.getInstance(JAVA_CONFIG, null, "SUN");
+ doTest(c, testnum++);
+
+ // get an instance of JavaLoginConfig from SunRsaSign
+ try {
+ c = Configuration.getInstance(JAVA_CONFIG, null, "SunRsaSign");
+ throw new SecurityException("test " + testnum++ + " failed");
+ } catch (NoSuchAlgorithmException nsae) {
+ // good
+ System.out.println("test " + testnum++ + " passed");
+ }
+
+ // get an instance of JavaLoginConfig from FOO
+ try {
+ c = Configuration.getInstance(JAVA_CONFIG, null, "FOO");
+ throw new SecurityException("test " + testnum++ + " failed");
+ } catch (NoSuchProviderException nspe) {
+ // good
+ System.out.println("test " + testnum++ + " passed");
+ }
+
+ return testnum;
+ }
+
+ private int testProvider(int testnum) throws Exception {
+ // get an instance of JavaLoginConfig from SUN
+ Configuration c = Configuration.getInstance(JAVA_CONFIG,
+ null,
+ Security.getProvider("SUN"));
+ doTest(c, testnum++);
+
+ // get an instance of JavaLoginConfig from SunRsaSign
+ try {
+ c = Configuration.getInstance(JAVA_CONFIG,
+ null,
+ Security.getProvider("SunRsaSign"));
+ throw new SecurityException("test " + testnum++ + " failed");
+ } catch (NoSuchAlgorithmException nsae) {
+ // good
+ System.out.println("test " + testnum++ + " passed");
+ }
+
+ return testnum;
+ }
+
+ private int testCustomImpl(int testnum) throws Exception {
+ Provider customProvider = new GetInstanceProvider();
+ Configuration c = Configuration.getInstance("GetInstanceConfigSpi",
+ null,
+ customProvider);
+ doCustomTest(c, testnum++, customProvider);
+ return testnum;
+ }
+
+ private int testURIParam(int testnum) throws Exception {
+ // get an instance of JavaLoginConfig
+ // from SUN and have it read from the URI
+
+ File file = new File(System.getProperty("test.src", "."),
+ "GetInstance.configURI");
+ URI uri = file.toURI();
+ URIParameter uriParam = new URIParameter(uri);
+ Configuration c = Configuration.getInstance(JAVA_CONFIG, uriParam);
+ doTestURI(c, uriParam, testnum++);
+
+ return testnum;
+ }
+
+ private int testException(int testnum) throws Exception {
+ // get an instance of JavaLoginConfig
+ // from SUN and have it read from the bad URI
+
+ File file = new File(System.getProperty("test.src", "."),
+ "GetInstance.bad.configURI");
+ URI uri = file.toURI();
+ URIParameter uriParam = new URIParameter(uri);
+
+ try {
+ Configuration c = Configuration.getInstance(JAVA_CONFIG, uriParam);
+ throw new SecurityException("expected IOException");
+ } catch (NoSuchAlgorithmException nsae) {
+ if (nsae.getCause() instanceof java.io.IOException) {
+ System.out.println("exception test passed: " +
+ nsae.getCause().getMessage());
+ } else {
+ throw new SecurityException("expected IOException");
+ }
+ }
+
+ // pass bad param
+ try {
+ Configuration c = Configuration.getInstance(JAVA_CONFIG,
+ new BadParam());
+ throw new SecurityException("test " + testnum++ + " failed");
+ } catch (IllegalArgumentException iae) {
+ // good
+ System.out.println("test " + testnum++ + " passed");
+ }
+
+ try {
+ Configuration c = Configuration.getInstance(JAVA_CONFIG,
+ new BadParam(),
+ "SUN");
+ throw new SecurityException("test " + testnum++ + " failed");
+ } catch (IllegalArgumentException iae) {
+ // good
+ System.out.println("test " + testnum++ + " passed");
+ }
+
+ try {
+ Configuration c = Configuration.getInstance(JAVA_CONFIG,
+ new BadParam(),
+ Security.getProvider("SUN"));
+ throw new SecurityException("test " + testnum++ + " failed");
+ } catch (IllegalArgumentException iae) {
+ // good
+ System.out.println("test " + testnum++ + " passed");
+ }
+
+ return testnum;
+ }
+
+ private int doCommon(Configuration c, int testnum) throws Exception {
+
+ AppConfigurationEntry[] entries = c.getAppConfigurationEntry("EMPTY");
+ if (entries == null) {
+ System.out.println("test " + testnum + ".1 passed");
+ } else {
+ throw new SecurityException("test " + testnum + ".1 failed");
+ }
+
+ entries = c.getAppConfigurationEntry("one");
+ if (entries.length == 1 &&
+ MOD0.equals(entries[0].getLoginModuleName()) &&
+ AppConfigurationEntry.LoginModuleControlFlag.REQUIRED ==
+ entries[0].getControlFlag()) {
+ System.out.println("test " + testnum + ".2 passed");
+ } else {
+ throw new SecurityException("test " + testnum + ".2 failed");
+ }
+
+ entries = c.getAppConfigurationEntry("two");
+ if (entries.length == 2 &&
+ MOD0.equals(entries[0].getLoginModuleName()) &&
+ AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT ==
+ entries[0].getControlFlag() &&
+ MOD1.equals(entries[1].getLoginModuleName()) &&
+ AppConfigurationEntry.LoginModuleControlFlag.REQUIRED ==
+ entries[1].getControlFlag()) {
+ System.out.println("test " + testnum + ".3 passed");
+ } else {
+ throw new SecurityException("test " + testnum + ".3 failed");
+ }
+
+ entries = c.getAppConfigurationEntry("three");
+ if (entries.length == 3 &&
+ MOD0.equals(entries[0].getLoginModuleName()) &&
+ AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT ==
+ entries[0].getControlFlag() &&
+ MOD1.equals(entries[1].getLoginModuleName()) &&
+ AppConfigurationEntry.LoginModuleControlFlag.REQUIRED ==
+ entries[1].getControlFlag() &&
+ MOD2.equals(entries[2].getLoginModuleName()) &&
+ AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL ==
+ entries[2].getControlFlag()) {
+ System.out.println("test " + testnum + ".4 passed");
+ } else {
+ throw new SecurityException("test " + testnum + ".4 failed");
+ }
+
+ return testnum;
+ }
+
+ private void doCustomTest(Configuration c,
+ int testnum,
+ Provider custom) throws Exception {
+
+ testnum = doCommon(c, testnum);
+
+ // test getProvider
+ if (custom == c.getProvider() &&
+ "GetInstanceProvider".equals(c.getProvider().getName())) {
+ System.out.println("test " + testnum + " (getProvider) passed");
+ } else {
+ throw new SecurityException
+ ("test " + testnum + " (getProvider) failed");
+ }
+
+ // test getType
+ if ("GetInstanceConfigSpi".equals(c.getType())) {
+ System.out.println("test " + testnum + "(getType) passed");
+ } else {
+ throw new SecurityException("test " + testnum +
+ " (getType) failed");
+ }
+ }
+
+ private void doTest(Configuration c, int testnum) throws Exception {
+ testnum = doCommon(c, testnum);
+
+ // test getProvider
+ if ("SUN".equals(c.getProvider().getName())) {
+ System.out.println("test " + testnum + " (getProvider) passed");
+ } else {
+ throw new SecurityException("test " + testnum +
+ " (getProvider) failed");
+ }
+
+ // test getType
+ if (JAVA_CONFIG.equals(c.getType())) {
+ System.out.println("test " + testnum + " (getType) passed");
+ } else {
+ throw new SecurityException("test " + testnum +
+ " (getType) failed");
+ }
+ }
+
+ private void doTestURI(Configuration c,
+ Configuration.Parameters uriParam,
+ int testnum) throws Exception {
+
+ AppConfigurationEntry[] entries = c.getAppConfigurationEntry("four");
+ if (entries.length == 4 &&
+ MOD0.equals(entries[0].getLoginModuleName()) &&
+ AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT ==
+ entries[0].getControlFlag() &&
+ MOD1.equals(entries[1].getLoginModuleName()) &&
+ AppConfigurationEntry.LoginModuleControlFlag.REQUIRED ==
+ entries[1].getControlFlag() &&
+ MOD2.equals(entries[2].getLoginModuleName()) &&
+ AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL ==
+ entries[2].getControlFlag() &&
+ MOD3.equals(entries[3].getLoginModuleName()) &&
+ AppConfigurationEntry.LoginModuleControlFlag.REQUIRED ==
+ entries[3].getControlFlag()) {
+ System.out.println("test " + testnum + ".1 passed");
+ } else {
+ throw new SecurityException("test " + testnum + ".1 failed");
+ }
+
+ // test getProvider
+ if ("SUN".equals(c.getProvider().getName())) {
+ System.out.println("test " + testnum + " (getProvider) passed");
+ } else {
+ throw new SecurityException("test " + testnum +
+ " (getProvider) failed");
+ }
+
+ // test getType
+ if (JAVA_CONFIG.equals(c.getType())) {
+ System.out.println("test " + testnum + " (getType) passed");
+ } else {
+ throw new SecurityException("test " + testnum +
+ " (getType) failed");
+ }
+
+ // test getParameters
+ if (uriParam.equals(c.getParameters())) {
+ System.out.println("test " + testnum + " (getParameters) passed");
+ } else {
+ throw new SecurityException("test " + testnum +
+ " (getParameters) failed");
+ }
+ }
+}
diff --git a/test/javax/security/auth/login/Configuration/GetInstanceConfigSpi.java b/test/javax/security/auth/login/Configuration/GetInstanceConfigSpi.java
new file mode 100644
index 0000000..68300f0
--- /dev/null
+++ b/test/javax/security/auth/login/Configuration/GetInstanceConfigSpi.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import java.security.*;
+import javax.security.auth.login.*;
+import com.sun.security.auth.login.*;
+
+public class GetInstanceConfigSpi extends ConfigurationSpi {
+
+ private Configuration c;
+
+ public GetInstanceConfigSpi(final Configuration.Parameters params) {
+
+ c = AccessController.doPrivileged
+ (new PrivilegedAction<Configuration>() {
+ public Configuration run() {
+ if (params instanceof URIParameter) {
+ URIParameter uriParam = (URIParameter)params;
+ return new ConfigFile(uriParam.getURI());
+ }
+ return new ConfigFile();
+ }
+ });
+ }
+
+ public AppConfigurationEntry[] engineGetAppConfigurationEntry(String name) {
+ return c.getAppConfigurationEntry(name);
+ }
+}
diff --git a/test/javax/security/auth/login/Configuration/GetInstanceProvider.java b/test/javax/security/auth/login/Configuration/GetInstanceProvider.java
new file mode 100644
index 0000000..faa80ac
--- /dev/null
+++ b/test/javax/security/auth/login/Configuration/GetInstanceProvider.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import java.security.*;
+
+public class GetInstanceProvider extends Provider {
+
+ public GetInstanceProvider() {
+ super("GetInstanceProvider",
+ 1,
+ "GetInstanceProvider: Configuration.GetInstanceConfigSpi");
+
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ put("Configuration.GetInstanceConfigSpi",
+ "GetInstanceConfigSpi");
+ return null;
+ }
+ });
+ }
+}
diff --git a/test/javax/security/auth/login/Configuration/GetInstanceSecurity.grantedPolicy b/test/javax/security/auth/login/Configuration/GetInstanceSecurity.grantedPolicy
new file mode 100644
index 0000000..816b7ff
--- /dev/null
+++ b/test/javax/security/auth/login/Configuration/GetInstanceSecurity.grantedPolicy
@@ -0,0 +1,11 @@
+grant codeBase "file:${{java.ext.dirs}}/*" {
+ permission java.security.AllPermission;
+};
+
+grant {
+ permission java.util.PropertyPermission "test.src", "read";
+ permission java.io.FilePermission "${test.src}${/}*", "read";
+
+ permission javax.security.auth.AuthPermission
+ "createLoginConfiguration.JavaLoginConfig";
+};
diff --git a/test/javax/security/auth/login/Configuration/GetInstanceSecurity.java b/test/javax/security/auth/login/Configuration/GetInstanceSecurity.java
new file mode 100644
index 0000000..30e8ad5
--- /dev/null
+++ b/test/javax/security/auth/login/Configuration/GetInstanceSecurity.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6268315
+ * @summary Configuration should be provider-based
+ * @build GetInstanceConfigSpi GetInstanceProvider
+ * @run main/othervm/policy=GetInstanceSecurity.policy GetInstanceSecurity
+ */
+
+import java.io.File;
+import java.net.URI;
+import java.security.*;
+import javax.security.auth.login.*;
+
+import sun.net.www.ParseUtil;
+
+public class GetInstanceSecurity {
+
+ private static final String JAVA_CONFIG = "JavaLoginConfig";
+
+ public static void main(String[] args) throws Exception {
+ try {
+ Configuration c = Configuration.getInstance(JAVA_CONFIG, null);
+ throw new RuntimeException("did not catch security exception");
+ } catch (SecurityException se) {
+ // good
+ }
+
+ try {
+ Configuration c = Configuration.getInstance
+ (JAVA_CONFIG, null, "SUN");
+ throw new RuntimeException("did not catch security exception");
+ } catch (SecurityException se) {
+ // good
+ }
+
+ try {
+ Configuration c = Configuration.getInstance
+ (JAVA_CONFIG, null, Security.getProvider("SUN"));
+ throw new RuntimeException("did not catch security exception");
+ } catch (SecurityException se) {
+ // good
+ }
+
+ // set a new policy that grants the perms, and then re-check perms
+
+ File file = new File(System.getProperty("test.src", "."),
+ "GetInstanceSecurity.grantedPolicy");
+ URI uri = file.toURI();
+ URIParameter param = new URIParameter(uri);
+ Policy p = Policy.getInstance("JavaPolicy", param, "SUN");
+ Policy.setPolicy(p);
+
+ // retry operations
+
+ file = new File(System.getProperty("test.src", "."),
+ "GetInstance.config");
+ URIParameter uriParam = new URIParameter(file.toURI());
+
+ try {
+ Configuration c = Configuration.getInstance(JAVA_CONFIG, uriParam);
+ } catch (SecurityException se) {
+ throw new RuntimeException("unexpected SecurityException");
+ }
+
+ try {
+ Configuration c = Configuration.getInstance
+ (JAVA_CONFIG, uriParam, "SUN");
+ // good
+ } catch (SecurityException se) {
+ throw new RuntimeException("unexpected SecurityException");
+ }
+
+ try {
+ Configuration c = Configuration.getInstance
+ (JAVA_CONFIG, uriParam, Security.getProvider("SUN"));
+ // good
+ } catch (SecurityException se) {
+ throw new RuntimeException("unexpected SecurityException");
+ }
+
+ System.out.println("test passed");
+ }
+}
diff --git a/test/javax/security/auth/login/Configuration/GetInstanceSecurity.policy b/test/javax/security/auth/login/Configuration/GetInstanceSecurity.policy
new file mode 100644
index 0000000..8a51318
--- /dev/null
+++ b/test/javax/security/auth/login/Configuration/GetInstanceSecurity.policy
@@ -0,0 +1,18 @@
+grant codeBase "file:${{java.ext.dirs}}/*" {
+ permission java.security.AllPermission;
+};
+
+grant {
+
+ permission java.util.PropertyPermission "test.src", "read";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.net.www";
+ permission java.io.FilePermission
+ "${test.src}${/}GetInstanceSecurity.grantedPolicy", "read";
+ permission java.security.SecurityPermission "createPolicy.JavaPolicy";
+ permission java.security.SecurityPermission "setPolicy";
+
+ // do not grant this:
+ //
+ // permission javax.security.auth.AuthPermission
+ // "createLoginConfiguration.JavaLoginConfig";
+};
diff --git a/test/javax/security/auth/login/Configuration/Synchronize.config b/test/javax/security/auth/login/Configuration/Synchronize.config
new file mode 100644
index 0000000..eacd30e
--- /dev/null
+++ b/test/javax/security/auth/login/Configuration/Synchronize.config
@@ -0,0 +1,3 @@
+other {
+ com.sun.security.auth.UnixLoginModule required;
+};
diff --git a/test/javax/security/auth/login/Configuration/Synchronize.java b/test/javax/security/auth/login/Configuration/Synchronize.java
new file mode 100644
index 0000000..86cd8f5
--- /dev/null
+++ b/test/javax/security/auth/login/Configuration/Synchronize.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2001 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4464458
+ * @summary ConfigFile.refresh should be synchronized
+ *
+ * @run main/othervm -Djava.security.auth.login.config=file:${test.src}/Synchronize.config Synchronize
+ */
+
+import javax.security.auth.login.*;
+
+public class Synchronize extends Thread {
+
+ private static final int loop = 500;
+
+ public void run() {
+ try {
+ System.out.println("attempting to access configuration...");
+ Configuration config = Configuration.getConfiguration();
+ AppConfigurationEntry[] entries = config.getAppConfigurationEntry
+ ("Synchronize");
+ config.refresh();
+ System.out.println("done accessing configuration...");
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException();
+ }
+ }
+
+ public static void main(String[] args) {
+ try {
+ Synchronize[] threads = new Synchronize[loop];
+ for (int i = 0; i < loop; i++) {
+ threads[i] = new Synchronize();
+ }
+
+ for (int i = 0; i < loop; i++) {
+ threads[i].start();
+ }
+
+ for (int i = 0; i < loop; i++) {
+ threads[i].join();
+ }
+ System.out.println("test passed");
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.out.println("test failed");
+ throw new SecurityException(e.toString());
+ }
+ }
+}
diff --git a/test/javax/security/auth/login/Exceptions/NewExceptions.java b/test/javax/security/auth/login/Exceptions/NewExceptions.java
new file mode 100644
index 0000000..9ea33a1
--- /dev/null
+++ b/test/javax/security/auth/login/Exceptions/NewExceptions.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4469116
+ * @summary LoginException subclasses
+ */
+
+import javax.security.auth.login.*;
+
+public class NewExceptions {
+ public static void main(String[] args) throws Exception {
+ AccountException ac =
+ new AccountException("AccountException");
+ AccountExpiredException aee =
+ new AccountExpiredException("AccountExpiredException");
+ AccountLockedException ale =
+ new AccountLockedException("AccountLockedException");
+ AccountNotFoundException anfe =
+ new AccountNotFoundException("AccountNotFoundException");
+ CredentialException ce =
+ new CredentialException("CredentialException");
+ CredentialExpiredException cee =
+ new CredentialExpiredException("CredentialExpiredException");
+ CredentialNotFoundException cnfe =
+ new CredentialNotFoundException("CredentialNotFoundException");
+
+ if (! (ac instanceof LoginException) ||
+ ! (ce instanceof LoginException) ||
+ ! (aee instanceof AccountException) ||
+ ! (ale instanceof AccountException) ||
+ ! (anfe instanceof AccountException) ||
+ ! (cee instanceof CredentialException) ||
+ ! (cnfe instanceof CredentialNotFoundException)) {
+ throw new SecurityException("Test 1 failed");
+ }
+
+ if (!ac.getMessage().equals("AccountException") ||
+ !aee.getMessage().equals("AccountExpiredException") ||
+ !ale.getMessage().equals("AccountLockedException") ||
+ !anfe.getMessage().equals("AccountNotFoundException") ||
+ !ce.getMessage().equals("CredentialException") ||
+ !cee.getMessage().equals("CredentialExpiredException") ||
+ !cnfe.getMessage().equals("CredentialNotFoundException")) {
+ throw new SecurityException("Test 2 failed");
+ }
+ }
+}
diff --git a/test/javax/security/auth/login/LoginContext/ConfigConstructor.config b/test/javax/security/auth/login/LoginContext/ConfigConstructor.config
new file mode 100644
index 0000000..743fc62
--- /dev/null
+++ b/test/javax/security/auth/login/LoginContext/ConfigConstructor.config
@@ -0,0 +1,11 @@
+module3 {
+ ConfigConstructor$MyModule3 required;
+};
+
+module4 {
+ ConfigConstructor$MyModule4 required;
+};
+
+other {
+ ConfigConstructor$MyModule2 required;
+};
diff --git a/test/javax/security/auth/login/LoginContext/ConfigConstructor.java b/test/javax/security/auth/login/LoginContext/ConfigConstructor.java
new file mode 100644
index 0000000..7fd4a45
--- /dev/null
+++ b/test/javax/security/auth/login/LoginContext/ConfigConstructor.java
@@ -0,0 +1,297 @@
+/*
+ * Copyright 2003-2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 4703361
+ * @summary can not specify Configuration to LoginContext constructor
+ *
+ * @run main/othervm/policy=ConfigConstructor.policy -Djava.security.auth.login.config=file:${test.src}/ConfigConstructor.config ConfigConstructor
+ *
+ */
+
+/**
+ * This test shares the login config with ConfigConstructorNoPerm.
+ * This test has all necessary permissions configured in the policy
+ * (ConfigConstructorNoPerm has no perms and checks for SecurityExceptions).
+ */
+
+import java.util.Map;
+import javax.security.auth.*;
+import javax.security.auth.login.*;
+import javax.security.auth.spi.*;
+import javax.security.auth.callback.*;
+
+public class ConfigConstructor {
+
+ private static Subject s = new Subject();
+ private static CallbackHandler ch =
+ new com.sun.security.auth.callback.TextCallbackHandler();
+ private static Configuration c = new MyConfig();
+
+ public static void main(String[] args) throws Exception {
+
+ // test non-null behavior with provided config
+ LoginContext lc = new LoginContext
+ ("module1",
+ s,
+ ch,
+ c);
+ lc.login();
+ System.out.println("Test 1 Passed");
+
+ // test null behavior with provided config
+ LoginContext lc2 = new LoginContext
+ ("module2",
+ null,
+ null,
+ c);
+ lc2.login();
+ System.out.println("Test 2 Passed");
+
+ // test null config
+ LoginContext lc3 = new LoginContext
+ ("module3",
+ s,
+ ch,
+ null);
+ lc3.login();
+ System.out.println("Test 3 Passed");
+
+ // test null config
+ LoginContext lc4 = new LoginContext
+ ("module4",
+ null,
+ null,
+ null);
+ lc4.login();
+ System.out.println("Test 4 Passed");
+
+ // test security (without permission)
+ try {
+ LoginContext lc5 = new LoginContext
+ ("module5",
+ null,
+ null,
+ c);
+ lc5.login();
+ throw new SecurityException("test failed - security check failed");
+ } catch (LoginException le) {
+ if (le.getCause() instanceof SecurityException) {
+ // test passed
+ } else {
+ le.printStackTrace();
+ throw new SecurityException("test failed: " +
+ "LoginException did not have chained SecurityException");
+ }
+ }
+ System.out.println("Test 5 Passed");
+
+ // test security (with permission)
+ LoginContext lc6 = new LoginContext
+ ("module6",
+ null,
+ null,
+ c);
+ lc6.login();
+ System.out.println("Test 6 Passed");
+
+ // test other
+ LoginContext lc7 = new LoginContext
+ ("goToOther",
+ null,
+ null,
+ c);
+ lc7.login();
+ System.out.println("Test 7 Passed");
+
+ // test other old constructor
+ LoginContext lc8 = new LoginContext
+ ("goToOther");
+ lc8.login();
+ System.out.println("Test 8 Passed");
+ }
+
+ private static class MyConfig extends Configuration {
+ public MyConfig() { }
+ public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
+ java.util.HashMap map = new java.util.HashMap();
+ AppConfigurationEntry[] entries = new AppConfigurationEntry[1];
+
+ if (name.equals("module1")) {
+ AppConfigurationEntry entry = new AppConfigurationEntry
+ ("ConfigConstructor$MyModule1",
+ AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
+ map);
+ entries[0] = entry;
+ } else if (name.equals("module2")) {
+ AppConfigurationEntry entry = new AppConfigurationEntry
+ ("ConfigConstructor$MyModule2",
+ AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
+ map);
+ entries[0] = entry;
+ } else if (name.equals("module3")) {
+ AppConfigurationEntry entry = new AppConfigurationEntry
+ ("ConfigConstructor$MyModule3",
+ AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
+ map);
+ entries[0] = entry;
+ } else if (name.equals("module4")) {
+ AppConfigurationEntry entry = new AppConfigurationEntry
+ ("ConfigConstructor$MyModule4",
+ AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
+ map);
+ entries[0] = entry;
+ } else if (name.equals("module5")) {
+ AppConfigurationEntry entry = new AppConfigurationEntry
+ ("ConfigConstructor$MyModule5",
+ AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
+ map);
+ entries[0] = entry;
+ } else if (name.equals("module6")) {
+ AppConfigurationEntry entry = new AppConfigurationEntry
+ ("ConfigConstructor$MyModule6",
+ AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
+ map);
+ entries[0] = entry;
+ } else if (name.equalsIgnoreCase("other")) {
+ AppConfigurationEntry entry = new AppConfigurationEntry
+ ("ConfigConstructor$MyModule2",
+ AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
+ map);
+ entries[0] = entry;
+ } else {
+ entries = null;
+ }
+ return entries;
+ }
+ public void refresh() { }
+ }
+
+ public static class MyModule1 implements LoginModule {
+
+ public MyModule1() { }
+
+ public void initialize(Subject s, CallbackHandler ch,
+ Map<String,?> state, Map<String,?> options) {
+ if (s != ConfigConstructor.s ||
+ ch != ConfigConstructor.ch) {
+ throw new SecurityException("Module 1 failed");
+ }
+ }
+
+ public boolean login() throws LoginException { return true; }
+ public boolean commit() throws LoginException { return true; }
+ public boolean abort() throws LoginException { return true; }
+ public boolean logout() throws LoginException { return true; }
+ }
+
+ public static class MyModule2 implements LoginModule {
+
+ public MyModule2() { }
+
+ public void initialize(Subject s, CallbackHandler ch,
+ Map<String,?> state, Map<String,?> options) {
+ if (s == ConfigConstructor.s ||
+ ch != null) {
+ throw new SecurityException("Module 2 failed");
+ }
+ }
+
+ public boolean login() throws LoginException { return true; }
+ public boolean commit() throws LoginException { return true; }
+ public boolean abort() throws LoginException { return true; }
+ public boolean logout() throws LoginException { return true; }
+ }
+
+ public static class MyModule3 implements LoginModule {
+
+ public MyModule3() { }
+
+ public void initialize(Subject s, CallbackHandler ch,
+ Map<String,?> state, Map<String,?> options) {
+ if (s != ConfigConstructor.s ||
+ ch == null ||
+ ch == ConfigConstructor.ch) {
+ throw new SecurityException("Module 3 failed");
+ }
+ }
+
+ public boolean login() throws LoginException { return true; }
+ public boolean commit() throws LoginException { return true; }
+ public boolean abort() throws LoginException { return true; }
+ public boolean logout() throws LoginException { return true; }
+ }
+
+ public static class MyModule4 implements LoginModule {
+
+ public MyModule4() { }
+
+ public void initialize(Subject s, CallbackHandler ch,
+ Map<String,?> state, Map<String,?> options) {
+ if (s == ConfigConstructor.s ||
+ ch != null) {
+ throw new SecurityException("Module 4 failed");
+ }
+ }
+
+ public boolean login() throws LoginException { return true; }
+ public boolean commit() throws LoginException { return true; }
+ public boolean abort() throws LoginException { return true; }
+ public boolean logout() throws LoginException { return true; }
+ }
+
+ public static class MyModule5 implements LoginModule {
+
+ public MyModule5() { }
+
+ public void initialize(Subject s, CallbackHandler ch,
+ Map<String,?> state, Map<String,?> options) { }
+
+ public boolean login() throws LoginException {
+ // do something security-sensitive
+ System.out.println(System.getProperty("user.name"));
+ return true;
+ }
+ public boolean commit() throws LoginException { return true; }
+ public boolean abort() throws LoginException { return true; }
+ public boolean logout() throws LoginException { return true; }
+ }
+
+ public static class MyModule6 implements LoginModule {
+
+ public MyModule6() { }
+
+ public void initialize(Subject s, CallbackHandler ch,
+ Map<String,?> state, Map<String,?> options) { }
+
+ public boolean login() throws LoginException {
+ // do something security-sensitive
+ System.out.println(System.getProperty("user.home"));
+ return true;
+ }
+ public boolean commit() throws LoginException { return true; }
+ public boolean abort() throws LoginException { return true; }
+ public boolean logout() throws LoginException { return true; }
+ }
+}
diff --git a/test/javax/security/auth/login/LoginContext/ConfigConstructor.policy b/test/javax/security/auth/login/LoginContext/ConfigConstructor.policy
new file mode 100644
index 0000000..16d88ec
--- /dev/null
+++ b/test/javax/security/auth/login/LoginContext/ConfigConstructor.policy
@@ -0,0 +1,7 @@
+grant {
+ permission java.util.PropertyPermission "user.home", "read";
+ permission javax.security.auth.AuthPermission "createLoginContext.module3";
+ permission javax.security.auth.AuthPermission "createLoginContext.module4";
+ permission javax.security.auth.AuthPermission "createLoginContext.goToOther";
+ permission javax.security.auth.AuthPermission "createLoginContext.other";
+};
diff --git a/test/javax/security/auth/login/LoginContext/ConfigConstructorNoPerm.java b/test/javax/security/auth/login/LoginContext/ConfigConstructorNoPerm.java
new file mode 100644
index 0000000..654555a
--- /dev/null
+++ b/test/javax/security/auth/login/LoginContext/ConfigConstructorNoPerm.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 4703361
+ * @summary can not specify Configuration to LoginContext constructor
+ *
+ * @run main/othervm/policy=ConfigConstructorNoPerm.policy -Djava.security.auth.login.config=file:${test.src}/ConfigConstructor.config ConfigConstructorNoPerm
+ */
+
+/**
+ * This test shares the login config with ConfigConstructor.
+ * This test has no configured permissions
+ * (ConfigConstructor tests code with perms configured).
+ */
+
+import java.util.Map;
+import javax.security.auth.*;
+import javax.security.auth.login.*;
+import javax.security.auth.spi.*;
+import javax.security.auth.callback.*;
+
+public class ConfigConstructorNoPerm {
+
+ private static Subject s = new Subject();
+ private static CallbackHandler ch =
+ new com.sun.security.auth.callback.TextCallbackHandler();
+ private static Configuration c = new MyConfig();
+
+ public static void main(String[] args) throws Exception {
+
+ // test old constructor with no permission
+ try {
+ LoginContext lc1 = new LoginContext
+ ("module1",
+ s,
+ ch);
+ throw new RuntimeException("Test 1 Failed");
+ } catch (SecurityException se) {
+ // test passed
+ }
+ System.out.println("Test 1 Succeeded");
+
+ // test new constructor (null config) with no permission
+ try {
+ LoginContext lc2 = new LoginContext
+ ("module1",
+ s,
+ ch,
+ null);
+ throw new RuntimeException("Test 2 Failed");
+ } catch (SecurityException se) {
+ // test passed
+ }
+ System.out.println("Test 2 Succeeded");
+
+ // test new constructor (config) - no permission needed
+ // (and none configured)
+ LoginContext lc3 = new LoginContext
+ ("module1",
+ s,
+ ch,
+ c);
+ System.out.println("Test 3 Succeeded");
+
+ // test old constructor with no permission for other
+ try {
+ LoginContext lc4 = new LoginContext
+ ("goToOther",
+ s,
+ ch);
+ throw new RuntimeException("Test 4 Failed");
+ } catch (SecurityException se) {
+ // test passed
+ }
+ System.out.println("Test 4 Succeeded");
+
+ // test new constructor with no permission for other
+ try {
+ LoginContext lc5 = new LoginContext
+ ("goToOther",
+ s,
+ ch,
+ null);
+ throw new RuntimeException("Test 5 Failed");
+ } catch (SecurityException se) {
+ // test passed
+ }
+ System.out.println("Test 5 Succeeded");
+ }
+
+ private static class MyConfig extends Configuration {
+ public MyConfig() { }
+ public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
+ java.util.HashMap map = new java.util.HashMap();
+ AppConfigurationEntry[] entries = new AppConfigurationEntry[1];
+
+ if (name.equals("module1")) {
+ AppConfigurationEntry entry = new AppConfigurationEntry
+ ("ConfigConstructor$MyModule1",
+ AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
+ map);
+ entries[0] = entry;
+ } else {
+ entries = null;
+ }
+ return entries;
+ }
+ public void refresh() { }
+ }
+}
diff --git a/test/javax/security/auth/login/LoginContext/ConfigConstructorNoPerm.policy b/test/javax/security/auth/login/LoginContext/ConfigConstructorNoPerm.policy
new file mode 100644
index 0000000..88167dd
--- /dev/null
+++ b/test/javax/security/auth/login/LoginContext/ConfigConstructorNoPerm.policy
@@ -0,0 +1,3 @@
+grant {
+ permission javax.security.auth.AuthPermission "createLoginContext.goToOther";
+};
diff --git a/test/javax/security/auth/login/LoginContext/DefaultHandler.config b/test/javax/security/auth/login/LoginContext/DefaultHandler.config
new file mode 100644
index 0000000..614e71f
--- /dev/null
+++ b/test/javax/security/auth/login/LoginContext/DefaultHandler.config
@@ -0,0 +1,3 @@
+other {
+ DefaultHandlerModule required;
+};
diff --git a/test/javax/security/auth/login/LoginContext/DefaultHandler.java b/test/javax/security/auth/login/LoginContext/DefaultHandler.java
new file mode 100644
index 0000000..62031ac
--- /dev/null
+++ b/test/javax/security/auth/login/LoginContext/DefaultHandler.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2000-2001 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4377181
+ * @summary Provide default configurable CallbackHandlers
+ *
+ * @build DefaultHandler DefaultHandlerImpl DefaultHandlerModule
+ * @run main/othervm -Djava.security.auth.login.config=file:${test.src}/DefaultHandler.config DefaultHandler
+ */
+
+import javax.security.auth.*;
+import javax.security.auth.login.*;
+
+public class DefaultHandler {
+
+ public static void main(String[] args) {
+
+ // first test if a default is not provided.
+ // we should get an exception
+
+ LoginContext lc = null;
+ try {
+ lc = new LoginContext("SampleLogin");
+ } catch (LoginException le) {
+ System.out.println
+ ("DefaultHandler test failed - login construction failed");
+ throw new SecurityException(le.getMessage());
+ }
+
+ try {
+ lc.login();
+ throw new SecurityException
+ ("DefaultHandler test failed: got a handler!");
+ } catch (LoginException le) {
+ // good!
+ System.out.println
+ ("Good: CallbackHandler implementation not found");
+ le.printStackTrace();
+ }
+
+ // set the security property for the default handler
+ java.security.Security.setProperty("auth.login.defaultCallbackHandler",
+ "DefaultHandlerImpl");
+
+ // now test to see if the default handler is picked up.
+ // this should succeed.
+
+ LoginContext lc2 = null;
+ try {
+ lc2 = new LoginContext("SampleLogin");
+ } catch (LoginException le) {
+ System.out.println
+ ("DefaultHandler test failed - constructing LoginContext");
+ throw new SecurityException(le.getMessage());
+ }
+
+ try {
+ lc2.login();
+ } catch (LoginException le) {
+ System.out.println
+ ("DefaultHandler test failed - login method");
+ throw new SecurityException(le.getMessage());
+ }
+
+ System.out.println("DefaultHandler test succeeded");
+ }
+}
diff --git a/test/javax/security/auth/login/LoginContext/DefaultHandlerImpl.java b/test/javax/security/auth/login/LoginContext/DefaultHandlerImpl.java
new file mode 100644
index 0000000..1d5abe0
--- /dev/null
+++ b/test/javax/security/auth/login/LoginContext/DefaultHandlerImpl.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2000 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import java.io.*;
+import java.util.Arrays;
+import javax.security.auth.callback.*;
+
+/**
+ * A default CallbackHandler implementation.
+ */
+public class DefaultHandlerImpl implements CallbackHandler {
+
+ /**
+ * Invoke an array of Callbacks.
+ *
+ * <p>
+ *
+ * @param callbacks an array of <code>Callback</code> objects which contain
+ * the information requested by an underlying security
+ * service to be retrieved or displayed.
+ *
+ * @exception java.io.IOException if an input or output error occurs. <p>
+ *
+ * @exception UnsupportedCallbackException if the implementation of this
+ * method does not support one or more of the Callbacks
+ * specified in the <code>callbacks</code> parameter.
+ */
+ public void handle(Callback[] callbacks)
+ throws IOException, UnsupportedCallbackException {
+
+ for (int i = 0; i < callbacks.length; i++) {
+ if (callbacks[i] instanceof TextOutputCallback) {
+
+ // display the message according to the specified type
+ TextOutputCallback toc = (TextOutputCallback)callbacks[i];
+ switch (toc.getMessageType()) {
+ case TextOutputCallback.INFORMATION:
+ System.out.println(toc.getMessage());
+ break;
+ case TextOutputCallback.ERROR:
+ System.out.println("ERROR: " + toc.getMessage());
+ break;
+ case TextOutputCallback.WARNING:
+ System.out.println("WARNING: " + toc.getMessage());
+ break;
+ default:
+ throw new IOException("Unsupported message type: " +
+ toc.getMessageType());
+ }
+
+ } else if (callbacks[i] instanceof NameCallback) {
+
+ // prompt the user for a username
+ NameCallback nc = (NameCallback)callbacks[i];
+
+ // ignore the provided defaultName
+ System.err.print(nc.getPrompt());
+ System.err.flush();
+ nc.setName((new BufferedReader
+ (new InputStreamReader(System.in))).readLine());
+
+ } else if (callbacks[i] instanceof PasswordCallback) {
+
+ // prompt the user for sensitive information
+ PasswordCallback pc = (PasswordCallback)callbacks[i];
+ System.err.print(pc.getPrompt());
+ System.err.flush();
+ pc.setPassword(readPassword(System.in));
+
+ } else {
+ throw new UnsupportedCallbackException
+ (callbacks[i], "Unrecognized Callback");
+ }
+ }
+ }
+
+ // Reads user password from given input stream.
+ private char[] readPassword(InputStream in) throws IOException {
+
+ char[] lineBuffer;
+ char[] buf;
+ int i;
+
+ buf = lineBuffer = new char[128];
+
+ int room = buf.length;
+ int offset = 0;
+ int c;
+
+loop: while (true) {
+ switch (c = in.read()) {
+ case -1:
+ case '\n':
+ break loop;
+
+ case '\r':
+ int c2 = in.read();
+ if ((c2 != '\n') && (c2 != -1)) {
+ if (!(in instanceof PushbackInputStream)) {
+ in = new PushbackInputStream(in);
+ }
+ ((PushbackInputStream)in).unread(c2);
+ } else
+ break loop;
+
+ default:
+ if (--room < 0) {
+ buf = new char[offset + 128];
+ room = buf.length - offset - 1;
+ System.arraycopy(lineBuffer, 0, buf, 0, offset);
+ Arrays.fill(lineBuffer, ' ');
+ lineBuffer = buf;
+ }
+ buf[offset++] = (char) c;
+ break;
+ }
+ }
+
+ if (offset == 0) {
+ return null;
+ }
+
+ char[] ret = new char[offset];
+ System.arraycopy(buf, 0, ret, 0, offset);
+ Arrays.fill(buf, ' ');
+
+ return ret;
+ }
+}
diff --git a/test/javax/security/auth/login/LoginContext/DefaultHandlerModule.java b/test/javax/security/auth/login/LoginContext/DefaultHandlerModule.java
new file mode 100644
index 0000000..0824406
--- /dev/null
+++ b/test/javax/security/auth/login/LoginContext/DefaultHandlerModule.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2000-2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import java.util.*;
+import java.io.IOException;
+import javax.security.auth.*;
+import javax.security.auth.callback.*;
+import javax.security.auth.login.*;
+import javax.security.auth.spi.*;
+
+public class DefaultHandlerModule implements LoginModule {
+
+ // initial state
+ private Subject subject;
+ private CallbackHandler callbackHandler;
+ private Map sharedState;
+ private Map options;
+
+ // username and password
+ private String username;
+ private char[] password;
+
+ public void initialize(Subject subject, CallbackHandler callbackHandler,
+ Map<String,?> sharedState, Map<String,?> options) {
+
+ this.subject = subject;
+ this.callbackHandler = callbackHandler;
+ this.sharedState = sharedState;
+ this.options = options;
+ }
+
+ public boolean login() throws LoginException {
+
+ // prompt for a username and password
+ if (callbackHandler == null) {
+ throw new LoginException("Error: no CallbackHandler available " +
+ "to garner authentication information from the user");
+ } else {
+ System.out.println("DefaultHandlerModule got CallbackHandler: " +
+ callbackHandler.toString());
+ }
+
+ return true;
+ }
+
+ public boolean commit() throws LoginException {
+ return true;
+ }
+
+ public boolean abort() throws LoginException {
+ return true;
+ }
+
+ public boolean logout() throws LoginException {
+ return true;
+ }
+}
diff --git a/test/javax/security/auth/login/LoginContext/ModuleSubject.config b/test/javax/security/auth/login/LoginContext/ModuleSubject.config
new file mode 100644
index 0000000..82e05cf
--- /dev/null
+++ b/test/javax/security/auth/login/LoginContext/ModuleSubject.config
@@ -0,0 +1,3 @@
+other {
+ ModuleSubjectModule required;
+};
diff --git a/test/javax/security/auth/login/LoginContext/ModuleSubject.java b/test/javax/security/auth/login/LoginContext/ModuleSubject.java
new file mode 100644
index 0000000..61cbe2d
--- /dev/null
+++ b/test/javax/security/auth/login/LoginContext/ModuleSubject.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2000-2001 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4378100
+ * @summary LoginContext doesn't reinit modules with new Subject
+ * if authentication fails
+ *
+ * @build ModuleSubject ModuleSubjectModule
+ * @run main/othervm -Djava.security.auth.login.config=file:${test.src}/ModuleSubject.config ModuleSubject
+ */
+
+import javax.security.auth.*;
+import javax.security.auth.login.*;
+import java.security.Principal;
+
+public class ModuleSubject {
+
+ public static void main(String[] args) {
+
+ LoginContext lc = null;
+ try {
+ lc = new LoginContext("SampleLogin");
+ } catch (LoginException le) {
+ System.out.println
+ ("ModuleSubject test failed - login construction failed");
+ throw new SecurityException(le.getMessage());
+ }
+
+ // first attempt must fail
+ try {
+ lc.login();
+ throw new SecurityException
+ ("ModuleSubject test failed: 1st login attempt did not fail!");
+ } catch (LoginException le) {
+ // good!
+ System.out.println
+ ("Good: first attempt failed");
+ le.printStackTrace();
+ }
+
+ if (lc.getSubject() != null) {
+ throw new SecurityException
+ ("ModuleSubject test failed - " +
+ "Subject after failed attempt not null: " +
+ lc.getSubject().toString());
+ }
+
+ // second attempt succeeds, and the correct subject comes back
+ try {
+ lc.login();
+ java.util.Set principals = lc.getSubject().getPrincipals();
+
+ if (principals.size() != 1) {
+ throw new SecurityException("ModuleSubject test failed: " +
+ "corrupted subject");
+ }
+ java.util.Iterator i = principals.iterator();
+ while (i.hasNext()) {
+ Principal p = (Principal)i.next();
+ System.out.println("principal after authentication = " +
+ p.toString());
+ }
+ } catch (LoginException le) {
+ System.out.println
+ ("ModuleSubject test failed - 2nd login attempt failed");
+ throw new SecurityException(le.getMessage());
+ }
+
+ System.out.println("ModuleSubject test succeeded");
+ }
+}
diff --git a/test/javax/security/auth/login/LoginContext/ModuleSubjectModule.java b/test/javax/security/auth/login/LoginContext/ModuleSubjectModule.java
new file mode 100644
index 0000000..c492631
--- /dev/null
+++ b/test/javax/security/auth/login/LoginContext/ModuleSubjectModule.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2000-2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import java.util.*;
+import java.io.IOException;
+import javax.security.auth.*;
+import javax.security.auth.callback.*;
+import javax.security.auth.login.*;
+import javax.security.auth.spi.*;
+
+public class ModuleSubjectModule implements LoginModule {
+
+ // initial state
+ private Subject subject;
+ private CallbackHandler callbackHandler;
+ private Map sharedState;
+ private Map options;
+
+ // username and password
+ private String username;
+ private char[] password;
+
+ // first attempt, fail. second attempt, succeed
+ private int attemptNumber = 1;
+
+ public void initialize(Subject subject, CallbackHandler callbackHandler,
+ Map<String,?> sharedState, Map<String,?> options) {
+
+ this.subject = subject;
+ this.callbackHandler = callbackHandler;
+ this.sharedState = sharedState;
+ this.options = options;
+ }
+
+ public boolean login() throws LoginException {
+
+ if (attemptNumber == 1) {
+ attemptNumber = 2;
+ throw new LoginException("attempt 1 fails");
+ }
+ return true;
+ }
+
+ public boolean commit() throws LoginException {
+
+ com.sun.security.auth.NTUserPrincipal p = new
+ com.sun.security.auth.NTUserPrincipal("testPrincipal");
+ subject.getPrincipals().add(p);
+ return true;
+ }
+
+ public boolean abort() throws LoginException {
+ return true;
+ }
+
+ public boolean logout() throws LoginException {
+ return true;
+ }
+}
diff --git a/test/javax/security/auth/login/LoginContext/ResetConfigModule.java b/test/javax/security/auth/login/LoginContext/ResetConfigModule.java
new file mode 100644
index 0000000..31ade4d
--- /dev/null
+++ b/test/javax/security/auth/login/LoginContext/ResetConfigModule.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2002-2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4633622
+ * @summary bug in LoginContext when Configuration is subclassed
+ *
+ * @build ResetConfigModule ResetModule
+ * @run main ResetConfigModule
+ */
+
+import javax.security.auth.*;
+import javax.security.auth.login.*;
+import javax.security.auth.spi.*;
+import javax.security.auth.callback.*;
+import java.util.*;
+
+public class ResetConfigModule {
+
+ public static void main(String[] args) throws Exception {
+
+ Configuration.setConfiguration(new MyConfig());
+
+ LoginContext lc = new LoginContext("test");
+ try {
+ lc.login();
+ throw new SecurityException("test 1 failed");
+ } catch (LoginException le) {
+ if (le.getCause() != null &&
+ le.getCause() instanceof SecurityException) {
+ System.out.println("good so far");
+ } else {
+ throw le;
+ }
+ }
+
+ LoginContext lc2 = new LoginContext("test2");
+ try {
+ lc2.login();
+ throw new SecurityException("test 2 failed");
+ } catch (LoginException le) {
+ if (le.getCause() != null &&
+ le.getCause() instanceof SecurityException) {
+ System.out.println("test succeeded");
+ } else {
+ throw le;
+ }
+ }
+ }
+}
+
+class MyConfig extends Configuration {
+ private AppConfigurationEntry[] entries = {
+ new AppConfigurationEntry("ResetModule",
+ AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
+ new HashMap()) };
+ public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
+ return entries;
+ }
+ public void refresh() { }
+}
diff --git a/test/javax/security/auth/login/LoginContext/ResetModule.java b/test/javax/security/auth/login/LoginContext/ResetModule.java
new file mode 100644
index 0000000..4e826a1
--- /dev/null
+++ b/test/javax/security/auth/login/LoginContext/ResetModule.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2002-2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import javax.security.auth.*;
+import javax.security.auth.login.*;
+import javax.security.auth.spi.*;
+import javax.security.auth.callback.*;
+import java.util.*;
+
+public class ResetModule implements LoginModule {
+ public ResetModule() { }
+ public void initialize(Subject s, CallbackHandler h,
+ Map<String,?> ss, Map<String,?> options) {
+ throw new SecurityException("INITIALIZE");
+ }
+ public boolean login() throws LoginException { return true; }
+ public boolean commit() throws LoginException { return true; }
+ public boolean abort() throws LoginException { return true; }
+ public boolean logout() throws LoginException { return true; }
+}
diff --git a/test/javax/security/auth/x500/X500Principal/DerIsConstructor.java b/test/javax/security/auth/x500/X500Principal/DerIsConstructor.java
new file mode 100644
index 0000000..f17badd
--- /dev/null
+++ b/test/javax/security/auth/x500/X500Principal/DerIsConstructor.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2001 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4426033
+ * @summary Should add an X500Principal(InputStream) constructor
+ */
+
+import java.io.*;
+import javax.security.auth.x500.X500Principal;
+
+public class DerIsConstructor {
+ public static void main(String[] args) {
+
+ try {
+
+ // create 2 different X500Principals
+ X500Principal p = new X500Principal("o=sun, cn=duke");
+ X500Principal p2 = new X500Principal("o=sun, cn=dukette");
+
+ // get the encoded bytes for the 2 principals
+ byte[] encoded = p.getEncoded();
+ byte[] encoded2 = p2.getEncoded();
+
+ // create a ByteArrayInputStream with the
+ // encodings from the 2 principals
+ byte[] all = new byte[encoded.length + encoded2.length];
+ System.arraycopy(encoded, 0, all, 0, encoded.length);
+ System.arraycopy(encoded2, 0, all, encoded.length, encoded2.length);
+ ByteArrayInputStream bais = new ByteArrayInputStream(all);
+
+ // create 2 new X500Principals from the ByteArrayInputStream
+ X500Principal pp = new X500Principal(bais);
+ X500Principal pp2 = new X500Principal(bais);
+
+ // sanity check the 2 new principals
+ if (p.equals(pp) && p2.equals(pp2) && !pp.equals(pp2)) {
+ System.out.println("Test 1 passed");
+ } else {
+ throw new SecurityException("Test 1 failed");
+ }
+
+ // corrupt the ByteArrayInputStream and see if the
+ // mark/reset worked
+ byte[] all2 = new byte[all.length];
+ System.arraycopy(all, 0, all2, 0, all.length);
+ all2[encoded.length + 2] = (byte)-1;
+ bais = new ByteArrayInputStream(all2);
+
+ // this should work
+ X500Principal ppp = new X500Principal(bais);
+
+ // this should throw an IOException due to stream corruption
+ int origAvailable = bais.available();
+ try {
+ X500Principal ppp2 = new X500Principal(bais);
+ throw new SecurityException("Test 2 (part a) failed");
+ } catch (IllegalArgumentException iae) {
+ if (bais.available() == origAvailable) {
+ System.out.println("Test 2 passed");
+ } else {
+ throw new SecurityException("Test 2 (part b) failed");
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new SecurityException(e.getMessage());
+ }
+ }
+}
diff --git a/test/javax/security/auth/x500/X500Principal/Equals.java b/test/javax/security/auth/x500/X500Principal/Equals.java
new file mode 100644
index 0000000..34243f7
--- /dev/null
+++ b/test/javax/security/auth/x500/X500Principal/Equals.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2000-2001 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4385031
+ * @bug 4459925
+ * @summary X500Principal.equals can be optimized,
+ * equals and hashcode are underspecified
+ */
+
+import javax.security.auth.x500.X500Principal;
+
+public class Equals {
+
+ private static final String p1String =
+ "O=sun, Ou=eng,cn=Test 1, EMAILADDRESS=duke@sun.com, UID=1 ";
+
+ private static final String p2String =
+ " o=SUN,OU=eng, cn=test 1,emailaddress = duke@sun.com,UID=1";
+
+ private static final String p3String =
+ " o = SUN, cn=test 1+ emailaddress = duke@sun.com + uId =5";
+
+ private static final String p4String =
+ "o=SUN,uid=5 + emailaddress = duke@sun.com +cn=test 1";
+
+ private static final String p5String =
+ "emailaddress = duke@sun.com + SURNAME=blah";
+
+ private static final String p6String =
+ "surname=blah+ emailAddress = duke@sun.com ";
+
+ private static final String p7String =
+ "o=sun, ou=esc\\\"quote, cn=duke";
+
+ private static final String p8String =
+ "o=sun, ou= esc\\\"quote,cn=duke";
+
+ public static void main(String[] args) {
+
+ // test regular equals
+ X500Principal p1 = new X500Principal(p1String);
+ X500Principal p2 = new X500Principal(p2String);
+
+ printName("Principal 1:", p1String, p1);
+ printName("Principal 2:", p2String, p2);
+
+ if (!p1.equals(p2))
+ throw new SecurityException("Equals test failed: #1");
+
+ X500Principal notEqual = new X500Principal("cn=test2");
+ if (p1.equals(notEqual))
+ throw new SecurityException("Equals test failed: #2");
+
+ if (p1.equals(null))
+ throw new SecurityException("Equals test failed: #3");
+
+ if (p1.hashCode() != p2.hashCode())
+ throw new SecurityException("Equals test failed: #4");
+
+ // test multiple AVA's in an RDN
+ X500Principal p3 = new X500Principal(p3String);
+ X500Principal p4 = new X500Principal(p4String);
+
+ printName("Principal 3:", p3String, p3);
+ printName("Principal 4:", p4String, p4);
+
+ if (!p3.equals(p4))
+ throw new SecurityException("Equals test failed: #5");
+
+ if (p1.equals(p3) || p2.equals(p3))
+ throw new SecurityException("Equals test failed: #6");
+
+ if (p3.hashCode() != p4.hashCode())
+ throw new SecurityException("Equals test failed: #7");
+
+ X500Principal p5 = new X500Principal(p5String);
+ X500Principal p6 = new X500Principal(p6String);
+
+ printName("Principal 5:", p5String, p5);
+ printName("Principal 6:", p6String, p6);
+
+ if (!p5.equals(p6))
+ throw new SecurityException("Equals test failed: #8");
+
+ if (p5.hashCode() != p6.hashCode())
+ throw new SecurityException("Equals test failed: #9");
+
+ X500Principal p7 = new X500Principal(p7String);
+ X500Principal p8 = new X500Principal(p8String);
+
+ printName("Principal 7:", p7String, p7);
+ printName("Principal 8:", p8String, p8);
+
+ if (!p7.equals(p8))
+ throw new SecurityException("Equals test failed: #10");
+
+ if (p7.hashCode() != p8.hashCode())
+ throw new SecurityException("Equals test failed: #11");
+
+ System.out.println("Equals test passed");
+ }
+
+ static void printName(String heading, String input, X500Principal p) {
+ System.out.println(heading);
+ System.out.println(" input:\t\t" + input);
+ System.out.println();
+ System.out.println(" toString:\t" + p.toString());
+ System.out.println();
+ System.out.println(" getName:\t" + p.getName());
+ System.out.println();
+ System.out.println(" getName 1779:\t" + p.getName("rfc1779"));
+ System.out.println();
+ System.out.println(" getName 2253:\t" + p.getName("rfc2253"));
+ System.out.println();
+ System.out.println(" getName canon:\t" + p.getName("canonical"));
+ System.out.println();
+ }
+}
diff --git a/test/javax/security/auth/x500/X500Principal/EscapedChars.java b/test/javax/security/auth/x500/X500Principal/EscapedChars.java
new file mode 100644
index 0000000..3002607
--- /dev/null
+++ b/test/javax/security/auth/x500/X500Principal/EscapedChars.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2001-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 4505053
+ * @summary make sure X500Principal CANONICAL format escapes leading '#' in
+ * attribute values of type String.
+ */
+import javax.security.auth.x500.X500Principal;
+
+public class EscapedChars {
+
+ public static void main(String[] args) throws Exception {
+
+ String dn="CN=\\#user";
+ X500Principal xp = new X500Principal(dn);
+
+ System.out.println("RFC2253 DN is " +
+ xp.getName(X500Principal.RFC2253));
+ System.out.println("CANONICAL DN is is " +
+ xp.getName(X500Principal.CANONICAL));
+
+ String dn1 = xp.getName(X500Principal.CANONICAL);
+ if (!(dn1.substring(3,5).equals("\\#")))
+ throw new Exception("Leading # not escaped");
+
+ X500Principal xp1 = new X500Principal(dn1);
+ System.out.println("CANONICAL DN is " +
+ xp1.getName(X500Principal.CANONICAL));
+ }
+}
diff --git a/test/javax/security/auth/x500/X500Principal/InvalidConstructorInput.java b/test/javax/security/auth/x500/X500Principal/InvalidConstructorInput.java
new file mode 100644
index 0000000..026edd2
--- /dev/null
+++ b/test/javax/security/auth/x500/X500Principal/InvalidConstructorInput.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2001 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4475278
+ * @summary X500Principal, X509Certificate and X509CRL
+ * unnecessarily throw checked exception
+ */
+
+import java.io.*;
+import javax.security.auth.x500.X500Principal;
+
+public class InvalidConstructorInput {
+
+ public static void main(String[] args) {
+
+ try {
+ byte[] bytes = { 'a' };
+ X500Principal p = new X500Principal(bytes);
+ throw new SecurityException("test failed: #1");
+ } catch (RuntimeException re) {
+ }
+
+ try {
+ String dir = System.getProperty("test.src");
+ if (dir == null)
+ dir = ".";
+
+ FileInputStream fis = new FileInputStream
+ (dir + "/InvalidConstructorInput.java");
+ X500Principal p = new X500Principal(fis);
+ throw new SecurityException("test failed: #2.1");
+ } catch (FileNotFoundException fnfe) {
+ throw new SecurityException("test failed: #2.2");
+ } catch (RuntimeException re) {
+ }
+
+ System.out.println("Test passed");
+ }
+}
diff --git a/test/javax/security/auth/x500/X500Principal/KeywordMap.java b/test/javax/security/auth/x500/X500Principal/KeywordMap.java
new file mode 100644
index 0000000..9d024c8
--- /dev/null
+++ b/test/javax/security/auth/x500/X500Principal/KeywordMap.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2005-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6181936
+ * @summary Test basic functionality of X500Principal(String, Map) constructor
+ * @author Sean Mullan
+ */
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import javax.security.auth.x500.X500Principal;
+
+public class KeywordMap {
+
+ public static void main(String[] args) throws Exception {
+
+ X500Principal p = null;
+ Map<String, String> m = null;
+
+ // test null keywordMap
+ try {
+ p = new X500Principal("CN=user", null);
+ throw new Exception
+ ("expected NullPointerException for null keywordMap");
+ } catch (NullPointerException npe) {}
+
+ // test improperly specified OID
+ m = Collections.singletonMap("FOO", "FOO");
+ try {
+ p = new X500Principal("FOO=user", m);
+ throw new Exception
+ ("expected IllegalArgumentException for bad OID");
+ } catch (IllegalArgumentException iae) {}
+
+ // ignore improperly specified keyword
+ m = Collections.singletonMap("?*&", "FOO");
+ p = new X500Principal("CN=user", m);
+
+ // throw exception if no mapping for keyword
+ m = Collections.singletonMap("BAR", "1.2.3");
+ try {
+ p = new X500Principal("FOO=user", m);
+ throw new Exception
+ ("expected IllegalArgumentExc for keyword with no mapping");
+ } catch (IllegalArgumentException iae) {}
+
+ // don't match keyword in lower-case
+ m = Collections.singletonMap("foo", "1.2.3");
+ try {
+ p = new X500Principal("FOO=user", m);
+ throw new Exception
+ ("expected IllegalArgumentExc for wrong-case keyword mapping");
+ } catch (IllegalArgumentException iae) {}
+
+ // allow duplicate OID mappings
+ m = new HashMap<String, String>();
+ m.put("FOO", "1.2.3");
+ m.put("BAR", "1.2.3");
+ p = new X500Principal("BAR=user", m);
+
+ // override builtin keywords
+ m = Collections.singletonMap("CN", "1.2.3");
+ p = new X500Principal("CN=user", m);
+ if (!p.getName().startsWith("1.2.3")) {
+ throw new Exception("mapping did not override builtin keyword");
+ }
+
+ // override builtin OIDs
+ m = Collections.singletonMap("FOO", "2.5.4.3");
+ p = new X500Principal("FOO=sean", m);
+ if (!p.getName().startsWith("CN")) {
+ throw new Exception("mapping did not override builtin OID");
+ }
+ }
+}
diff --git a/test/javax/security/auth/x500/X500Principal/OIDMap.java b/test/javax/security/auth/x500/X500Principal/OIDMap.java
new file mode 100644
index 0000000..f5de5a1
--- /dev/null
+++ b/test/javax/security/auth/x500/X500Principal/OIDMap.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2005-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6181936
+ * @summary Test basic functionality of X500Principal.getName(String, Map)
+ * @author Sean Mullan
+ */
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import javax.security.auth.x500.X500Principal;
+
+public class OIDMap {
+
+ public static void main(String[] args) throws Exception {
+
+ X500Principal p = null;
+ Map<String, String> m1, m2 = null;
+
+ // test null oidMap
+ p = new X500Principal("CN=user");
+ try {
+ p.getName("RFC2253", null);
+ throw new Exception
+ ("expected NullPointerException for null oidMap");
+ } catch (NullPointerException npe) {}
+
+ // test improperly specified keyword
+ m1 = Collections.singletonMap("FOO", "1.2.3");
+ m2 = Collections.singletonMap("1.2.3", "*&$");
+ p = new X500Principal("FOO=user", m1);
+ try {
+ p.getName("RFC2253", m2);
+ throw new Exception
+ ("expected IllegalArgumentException for bad keyword");
+ } catch (IllegalArgumentException iae) {}
+ try {
+ m2 = Collections.singletonMap("1.2.3", "1abc");
+ p.getName("RFC2253", m2);
+ throw new Exception
+ ("expected IllegalArgumentException for bad keyword");
+ } catch (IllegalArgumentException iae) {}
+ try {
+ m2 = Collections.singletonMap("1.2.3", "");
+ p.getName("RFC2253", m2);
+ throw new Exception
+ ("expected IllegalArgumentException for bad keyword");
+ } catch (IllegalArgumentException iae) {}
+ try {
+ m2 = Collections.singletonMap("1.2.3", "a1_b)a");
+ p.getName("RFC2253", m2);
+ throw new Exception
+ ("expected IllegalArgumentException for bad keyword");
+ } catch (IllegalArgumentException iae) {}
+
+ // ignore improperly specified OID
+ m1 = Collections.singletonMap("*&D", "FOO");
+ p = new X500Principal("CN=user");
+ p.getName("RFC2253", m1);
+
+ // override builtin OIDs
+ m1 = Collections.singletonMap("2.5.4.3", "FOO");
+ p = new X500Principal("CN=user");
+ if (!p.getName("RFC2253", m1).startsWith("FOO")) {
+ throw new Exception("mapping did not override builtin OID");
+ }
+
+ // disallow CANONICAL format
+ try {
+ p.getName("CANONICAL", m1);
+ throw new Exception
+ ("expected IllegalArgumentException for CANONICAL format");
+ } catch (IllegalArgumentException iae) {}
+ // disallow invalid format
+ try {
+ p.getName("YABBADABBADOO", m1);
+ throw new Exception
+ ("expected IllegalArgumentException for invalid format");
+ } catch (IllegalArgumentException iae) {}
+
+ // map OIDs
+ m1 = Collections.singletonMap("1.1", "BAR");
+ p = new X500Principal("1.1=sean");
+ System.out.println(p.getName("RFC1779", m1));
+ System.out.println(p.getName("RFC2253", m1));
+ // FIXME: 1779 format is broken!
+ if (!p.getName("RFC1779", m1).startsWith("BAR")) {
+ throw new Exception("mapping did not override builtin OID");
+ }
+ }
+}
diff --git a/test/javax/security/sasl/Sasl/PassSysProps.java b/test/javax/security/sasl/Sasl/PassSysProps.java
new file mode 100644
index 0000000..2c7b261
--- /dev/null
+++ b/test/javax/security/sasl/Sasl/PassSysProps.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2005-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @author Vincent Ryan
+ * @bug 6228412
+ * @summary Check that a Properties object can be passed to the Sasl create
+ * client and create server methods.
+ */
+
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Properties;
+import javax.security.sasl.*;
+import javax.security.auth.callback.*;
+import org.ietf.jgss.GSSException;
+
+public class PassSysProps {
+
+ private static final String PLAIN = "PLAIN";
+ private static final String DIGEST = "DIGEST-MD5";
+ private static final String CRAM = "CRAM-MD5";
+ private static final String EXTERNAL = "EXTERNAL";
+ private static final String GSSAPI = "GSSAPI";
+
+ public static void main(String[] args) throws Exception {
+
+ String authorizationId = null;
+ String protocol = "ldap";
+ String serverName = "server1";
+
+ CallbackHandler callbackHandler = new CallbackHandler(){
+ public void handle(Callback[] callbacks) {
+ }
+ };
+
+ // pass in system properties
+
+ Properties sysprops = System.getProperties();
+
+ SaslClient client1 =
+ Sasl.createSaslClient(new String[]{DIGEST, PLAIN}, authorizationId,
+ protocol, serverName, (Map) sysprops, callbackHandler);
+ System.out.println(client1);
+
+ SaslServer server1 =
+ Sasl.createSaslServer(DIGEST, protocol, serverName, (Map) sysprops,
+ callbackHandler);
+ System.out.println(server1);
+
+ // pass in string-valued props
+
+ Map<String, String> stringProps = new Hashtable<String, String>();
+ stringProps.put(Sasl.POLICY_NOPLAINTEXT, "true");
+
+ try {
+
+ SaslClient client2 =
+ Sasl.createSaslClient(new String[]{GSSAPI, PLAIN},
+ authorizationId, protocol, serverName, stringProps,
+ callbackHandler);
+ System.out.println(client2);
+
+ SaslServer server2 =
+ Sasl.createSaslServer(GSSAPI, protocol, serverName,
+ stringProps, callbackHandler);
+ System.out.println(server2);
+
+ } catch (SaslException se) {
+ Throwable t = se.getCause();
+ if (t instanceof GSSException) {
+ // allow GSSException because kerberos has not been initialized
+
+ } else {
+ throw se;
+ }
+ }
+
+ // pass in object-valued props
+
+ Map<String, Object> objProps = new Hashtable<String, Object>();
+ objProps.put("some.object.valued.property", System.err);
+
+ SaslClient client3 =
+ Sasl.createSaslClient(new String[]{EXTERNAL, CRAM}, authorizationId,
+ protocol, serverName, objProps, callbackHandler);
+ System.out.println(client3);
+
+ SaslServer server3 =
+ Sasl.createSaslServer(CRAM, protocol, serverName, objProps,
+ callbackHandler);
+ System.out.println(server3);
+
+ // pass in raw-type props
+
+ Map rawProps = new Hashtable();
+ rawProps.put(Sasl.POLICY_NOPLAINTEXT, "true");
+ rawProps.put("some.object.valued.property", System.err);
+
+ SaslClient client4 =
+ Sasl.createSaslClient(new String[]{EXTERNAL, CRAM}, authorizationId,
+ protocol, serverName, rawProps, callbackHandler);
+ System.out.println(client4);
+
+ SaslServer server4 =
+ Sasl.createSaslServer(CRAM, protocol, serverName, rawProps,
+ callbackHandler);
+ System.out.println(server4);
+
+ }
+}
diff --git a/test/javax/smartcardio/HistoricalBytes.java b/test/javax/smartcardio/HistoricalBytes.java
new file mode 100644
index 0000000..714bafe
--- /dev/null
+++ b/test/javax/smartcardio/HistoricalBytes.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6445367
+ * @summary Verify that ATR.getHistoricalBytes() works
+ * @author Andreas Sterbenz
+**/
+
+import java.util.Arrays;
+
+import javax.smartcardio.*;
+
+public class HistoricalBytes {
+
+ public static String toString(byte[] b) {
+ return Serialize.toString(b);
+ }
+
+ public static byte[] parse(String s) {
+ return Serialize.parse(s);
+ }
+
+ // generated using ATR_analysis from pcsc-tools
+
+ private final static String[] ATRS = {
+ "3B 7F 18 00 00 00 31 C0 73 9E 01 0B 64 52 D9 04 00 82 90 00",
+ "3B 65 00 00 9C 02 02 07 02",
+ "3B 95 18 40 FF 62 01 02 01 04",
+ "3B 86 40 20 68 01 01 02 04 AC",
+ "3B 9F 96 80 1F C3 80 31 E0 73 FE 21 1B B3 E2 02 7E 83 0F 90 00 82",
+ "3B FF 13 00 FF 81 31 FE 5D 80 25 A0 00 00 00 56 57 44 4B 33 32 30 05 00 3F",
+ "3F 6D 00 00 80 31 80 65 B0 05 01 02 5E 83 00 90 00",
+ "3F 65 35 64 02 04 6C 90 40",
+ "3B 9F 96 80 1F C3 80 31 E0 73 FE 21 1B B3 E2 02 7E 83 0F 90 00 82 11",
+ "3F 65 35 64 02 04 6C 90 40 55 55", // invalid
+ };
+
+ private final static String[] HIST = {
+ "00 31 C0 73 9E 01 0B 64 52 D9 04 00 82 90 00",
+ "9C 02 02 07 02",
+ "62 01 02 01 04",
+ "68 01 01 02 04 AC",
+ "80 31 E0 73 FE 21 1B B3 E2 02 7E 83 0F 90 00",
+ "80 25 A0 00 00 00 56 57 44 4B 33 32 30 05 00",
+ "80 31 80 65 B0 05 01 02 5E 83 00 90 00",
+ "02 04 6C 90 40",
+ "",
+ "",
+ };
+
+ public static void main(String[] args) throws Exception {
+ for (int i = 0; i < ATRS.length; i++) {
+ ATR atr = new ATR(parse(ATRS[i]));
+ byte[] hist = parse(HIST[i]);
+ byte[] b = atr.getHistoricalBytes();
+ if (!Arrays.equals(b, hist)) {
+ throw new Exception("mismatch: " + toString(b) + " != " + toString(hist));
+ }
+ }
+ System.out.println("OK");
+ }
+
+}
diff --git a/test/javax/smartcardio/Serialize.java b/test/javax/smartcardio/Serialize.java
new file mode 100644
index 0000000..6b9dc64
--- /dev/null
+++ b/test/javax/smartcardio/Serialize.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6445367
+ * @summary make sure serialization works
+ * @author Andreas Sterbenz
+ */
+
+import java.io.*;
+
+import javax.smartcardio.*;
+
+public class Serialize {
+
+ public static void main(String[] args) throws Exception {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ ObjectOutputStream oout = new ObjectOutputStream(bout);
+
+ CommandAPDU c1 = new CommandAPDU(parse("00 A4 04 00 07 A0 00 00 00 62 81 01 00"));
+ ResponseAPDU r1 = new ResponseAPDU(parse("07 A0 00 00 00 62 81 01 04 01 00 00 24 05 00 0B 04 B0 25 90 00"));
+ ATR a1 = new ATR(parse("3B 7F 18 00 00 00 31 C0 73 9E 01 0B 64 52 D9 04 00 82 90 00"));
+
+ oout.writeObject(c1);
+ oout.writeObject(r1);
+ oout.writeObject(a1);
+ oout.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream oin = new ObjectInputStream(bin);
+
+ CommandAPDU c2 = (CommandAPDU)oin.readObject();
+ ResponseAPDU r2 = (ResponseAPDU)oin.readObject();
+ ATR a2 = (ATR)oin.readObject();
+
+ if (!c2.equals(c1)) {
+ throw new Exception("CommandAPDU not equal");
+ }
+ if (c2.getNc() != 7) {
+ throw new Exception("Nc mismatch: " + c2.getNc());
+ }
+ if (c2.getNe() != 256) {
+ throw new Exception("Ne mismatch: " + c2.getNe());
+ }
+ if (c2.getINS() != 0xA4) {
+ throw new Exception("INS mismatch: " + c2.getINS());
+ }
+ if (!r2.equals(r1)) {
+ throw new Exception("ResponseAPDU not equal");
+ }
+ if (r2.getSW1() != 0x90) {
+ throw new Exception("SW1 mismatch: " + r2.getSW1());
+ }
+ if (!a2.equals(a1)) {
+ throw new Exception("ATR not equal");
+ }
+ if (!java.util.Arrays.equals(a2.getHistoricalBytes(), a1.getHistoricalBytes())) {
+ throw new Exception("Historical bytes mismatch");
+ }
+ System.out.println("OK");
+ }
+
+ private final static char[] hexDigits = "0123456789abcdef".toCharArray();
+
+ public static String toString(byte[] b) {
+ StringBuffer sb = new StringBuffer(b.length * 3);
+ for (int i = 0; i < b.length; i++) {
+ int k = b[i] & 0xff;
+ if (i != 0) {
+ sb.append(':');
+ }
+ sb.append(hexDigits[k >>> 4]);
+ sb.append(hexDigits[k & 0xf]);
+ }
+ return sb.toString();
+ }
+
+ public static byte[] parse(String s) {
+ try {
+ int n = s.length();
+ ByteArrayOutputStream out = new ByteArrayOutputStream(n >> 1);
+ StringReader r = new StringReader(s);
+ while (true) {
+ int b1 = nextNibble(r);
+ if (b1 < 0) {
+ break;
+ }
+ int b2 = nextNibble(r);
+ if (b2 < 0) {
+ throw new RuntimeException("Invalid string " + s);
+ }
+ int b = (b1 << 4) | b2;
+ out.write(b);
+ }
+ return out.toByteArray();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static int nextNibble(StringReader r) throws IOException {
+ while (true) {
+ int ch = r.read();
+ if (ch == -1) {
+ return -1;
+ } else if ((ch >= '0') && (ch <= '9')) {
+ return ch - '0';
+ } else if ((ch >= 'a') && (ch <= 'f')) {
+ return ch - 'a' + 10;
+ } else if ((ch >= 'A') && (ch <= 'F')) {
+ return ch - 'A' + 10;
+ }
+ }
+ }
+
+}
diff --git a/test/javax/smartcardio/TestCardPermission.java b/test/javax/smartcardio/TestCardPermission.java
new file mode 100644
index 0000000..adf6508
--- /dev/null
+++ b/test/javax/smartcardio/TestCardPermission.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6293767
+ * @summary Test for the CardPermission class
+ * @author Andreas Sterbenz
+ */
+
+import javax.smartcardio.*;
+
+public class TestCardPermission {
+
+ public static void main(String[] args) throws Exception {
+ CardPermission perm;
+
+ test("*");
+ test("connect");
+ test("reset");
+ test("exclusive");
+ test("transmitControl");
+ test("getBasicChannel");
+ test("openLogicalChannel");
+
+ test("connect,reset");
+ test("Reset,coNnect", "connect,reset");
+ test("exclusive,*,connect", "*");
+ test("connect,reset,exclusive,transmitControl,getBasicChannel,openLogicalChannel", "*");
+
+ invalid(null);
+ invalid("");
+ invalid("foo");
+ invalid("connect, reset");
+ invalid("connect,,reset");
+ invalid("connect,");
+ invalid(",connect");
+ invalid("");
+ }
+
+ private static void invalid(String s) throws Exception {
+ try {
+ CardPermission c = new CardPermission("*", s);
+ throw new Exception("Created invalid action: " + c);
+ } catch (IllegalArgumentException e) {
+ System.out.println("OK: " + e);
+ }
+ }
+
+ private static void test(String actions) throws Exception {
+ test(actions, actions);
+ }
+
+ private static void test(String actions, String canon) throws Exception {
+ CardPermission p = new CardPermission("*", actions);
+ System.out.println(p);
+ String a = p.getActions();
+ if (canon.equals(a) == false) {
+ throw new Exception("Canonical actions mismatch: " + canon + " != " + a);
+ }
+ }
+
+}
diff --git a/test/javax/smartcardio/TestCommandAPDU.java b/test/javax/smartcardio/TestCommandAPDU.java
new file mode 100644
index 0000000..90c74b1
--- /dev/null
+++ b/test/javax/smartcardio/TestCommandAPDU.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6293767
+ * @summary Test for the CommandAPDU class
+ * @author Andreas Sterbenz
+ */
+
+import java.util.*;
+
+import javax.smartcardio.*;
+
+public class TestCommandAPDU {
+
+ private static final Random random = new Random();
+
+ private static void test(int nc, int ne) throws Exception {
+ System.out.println("nc = " + nc + ", ne = " + ne);
+ byte[] data = new byte[nc];
+ random.nextBytes(data);
+ CommandAPDU apdu = new CommandAPDU((byte)0, (byte)0, (byte)0, (byte)0, data, ne);
+ //System.out.println(apdu);
+ if (apdu.getNc() != nc) {
+ throw new Exception("dataLength does not match");
+ }
+ if (Arrays.equals(data, apdu.getData()) == false) {
+ throw new Exception("data does not match");
+ }
+ if (apdu.getNe() != ne) {
+ throw new Exception("ne does not match");
+ }
+ byte[] apduBytes = apdu.getBytes();
+ CommandAPDU apdu2 = new CommandAPDU(apduBytes);
+ //System.out.println(apdu2);
+ if (Arrays.equals(apduBytes, apdu2.getBytes()) == false) {
+ throw new Exception("apduBytes do not match");
+ }
+ if (apdu2.getNc() != nc) {
+ throw new Exception("dataLength does not match");
+ }
+ if (Arrays.equals(data, apdu2.getData()) == false) {
+ throw new Exception("data does not match");
+ }
+ if (apdu2.getNe() != ne) {
+ throw new Exception("ne does not match");
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ int[] t = {0, 42, 0x81, 255, 256, 4242, 0x8181, 65535, 65536};
+ for (int nc : t) {
+ if (nc == 65536) {
+ continue;
+ }
+ for (int ne : t) {
+ test(nc, ne);
+ }
+ }
+ System.out.println("OK");
+ }
+}
diff --git a/test/javax/swing/JColorChooser/Test6524757.java b/test/javax/swing/JColorChooser/Test6524757.java
new file mode 100644
index 0000000..0389efc
--- /dev/null
+++ b/test/javax/swing/JColorChooser/Test6524757.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6524757
+ * @summary Tests different locales
+ * @author Sergey Malenkov
+ */
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import javax.swing.JButton;
+import javax.swing.JColorChooser;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.UIManager;
+import javax.swing.WindowConstants;
+import javax.swing.colorchooser.AbstractColorChooserPanel;
+
+import sun.swing.SwingUtilities2;
+
+public class Test6524757 {
+ private static final String[] KEYS = {
+ "ColorChooser.okText", // NON-NLS: string key from JColorChooser
+ "ColorChooser.cancelText", // NON-NLS: string key from JColorChooser
+ "ColorChooser.resetText", // NON-NLS: string key from JColorChooser
+ "ColorChooser.resetMnemonic", // NON-NLS: int key from JColorChooser
+
+//NotAvail: "ColorChooser.sampleText", // NON-NLS: string key from DefaultPreviewPanel
+
+ "ColorChooser.swatchesNameText", // NON-NLS: string key from DefaultSwatchChooserPanel
+ "ColorChooser.swatchesMnemonic", // NON-NLS: string key from DefaultSwatchChooserPanel:int
+ "ColorChooser.swatchesDisplayedMnemonicIndex", // NON-NLS: int key from DefaultSwatchChooserPanel
+ "ColorChooser.swatchesSwatchSize", // NON-NLS: dimension key from DefaultSwatchChooserPanel
+ "ColorChooser.swatchesRecentText", // NON-NLS: string key from DefaultSwatchChooserPanel
+ "ColorChooser.swatchesRecentSwatchSize", // NON-NLS: dimension key from DefaultSwatchChooserPanel
+//NotAvail: "ColorChooser.swatchesDefaultRecentColor", // NON-NLS: color key from DefaultSwatchChooserPanel
+
+ "ColorChooser.hsbNameText", // NON-NLS: string key from DefaultHSBChooserPanel
+ "ColorChooser.hsbMnemonic", // NON-NLS: int key from DefaultHSBChooserPanel
+ "ColorChooser.hsbDisplayedMnemonicIndex", // NON-NLS: int key from DefaultHSBChooserPanel
+ "ColorChooser.hsbHueText", // NON-NLS: string key from DefaultHSBChooserPanel
+ "ColorChooser.hsbSaturationText", // NON-NLS: string key from DefaultHSBChooserPanel
+ "ColorChooser.hsbBrightnessText", // NON-NLS: string key from DefaultHSBChooserPanel
+ "ColorChooser.hsbRedText", // NON-NLS: string key from DefaultHSBChooserPanel
+ "ColorChooser.hsbGreenText", // NON-NLS: string key from DefaultHSBChooserPanel
+ "ColorChooser.hsbBlueText", // NON-NLS: string key from DefaultHSBChooserPanel
+
+ "ColorChooser.rgbNameText", // NON-NLS: string key from DefaultRGBChooserPanel
+ "ColorChooser.rgbMnemonic", // NON-NLS: int key from DefaultRGBChooserPanel
+ "ColorChooser.rgbDisplayedMnemonicIndex", // NON-NLS: int key from DefaultRGBChooserPanel
+ "ColorChooser.rgbRedText", // NON-NLS: string key from DefaultRGBChooserPanel
+ "ColorChooser.rgbGreenText", // NON-NLS: string key from DefaultRGBChooserPanel
+ "ColorChooser.rgbBlueText", // NON-NLS: string key from DefaultRGBChooserPanel
+ "ColorChooser.rgbRedMnemonic", // NON-NLS: int key from DefaultRGBChooserPanel
+ "ColorChooser.rgbGreenMnemonic", // NON-NLS: int key from DefaultRGBChooserPanel
+ "ColorChooser.rgbBlueMnemonic", // NON-NLS: int key from DefaultRGBChooserPanel
+ };
+ private static final Object[] KOREAN = convert(Locale.KOREAN, KEYS);
+ private static final Object[] FRENCH = convert(Locale.FRENCH, KEYS);
+
+ public static void main(String[] args) {
+ // it affects Swing because it is not initialized
+ Locale.setDefault(Locale.KOREAN);
+ Object[] korean = create();
+
+ // it does not affect Swing because it is initialized
+ Locale.setDefault(Locale.CANADA);
+ Object[] canada = create();
+
+ // it definitely should affect Swing
+ JComponent.setDefaultLocale(Locale.FRENCH);
+ Object[] french = create();
+
+ validate(KOREAN, korean);
+ validate(KOREAN, canada);
+ validate(FRENCH, french);
+ }
+
+ private static void validate(Object[] expected, Object[] actual) {
+ int count = expected.length;
+ if (count != actual.length) {
+ throw new Error("different size: " + count + " <> " + actual.length);
+ }
+ for (int i = 0; i < count; i++) {
+ if (!expected[i].equals(actual[i])) {
+ throw new Error("unexpected value for key: " + KEYS[i]);
+ }
+ }
+ }
+
+ private static Object[] convert(Locale locale, String[] keys) {
+ int count = keys.length;
+ Object[] array = new Object[count];
+ for (int i = 0; i < count; i++) {
+ array[i] = convert(locale, keys[i]);
+ }
+ return array;
+ }
+
+ private static Object convert(Locale locale, String key) {
+ if (key.endsWith("Text")) { // NON-NLS: suffix for text message
+ return UIManager.getString(key, locale);
+ }
+ if (key.endsWith("Size")) { // NON-NLS: suffix for dimension
+ return UIManager.getDimension(key, locale);
+ }
+ if (key.endsWith("Color")) { // NON-NLS: suffix for color
+ return UIManager.getColor(key, locale);
+ }
+ int value = SwingUtilities2.getUIDefaultsInt(key, locale, -1);
+ return Integer.valueOf(value);
+ }
+
+ private static Object[] create() {
+ JFrame frame = new JFrame();
+ frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
+ frame.setVisible(true);
+
+ // show color chooser
+ JColorChooser chooser = new JColorChooser();
+ JDialog dialog = JColorChooser.createDialog(frame, null, false, chooser, null, null);
+ dialog.setVisible(true);
+
+ // process all values
+ List<Object> list = new ArrayList<Object>(KEYS.length);
+ addMain(list, dialog);
+ addSwatch(list, chooser);
+ addHSB(list, chooser);
+ addRGB(list, chooser);
+
+ // close dialog
+ dialog.setVisible(false);
+ dialog.dispose();
+
+ // close frame
+ frame.setVisible(false);
+ frame.dispose();
+
+ return list.toArray();
+ }
+
+ private static void addMain(List<Object> list, JDialog dialog) {
+ Component component = getC(getC(dialog.getLayeredPane(), 0), 1);
+ JButton ok = (JButton) getC(component, 0);
+ JButton cancel = (JButton) getC(component, 1);
+ JButton reset = (JButton) getC(component, 2);
+ list.add(ok.getText());
+ list.add(cancel.getText());
+ list.add(reset.getText());
+ list.add(Integer.valueOf(reset.getMnemonic()));
+ }
+
+ private static void addSwatch(List<Object> list, JColorChooser chooser) {
+ Component component = addPanel(list, chooser, 0);
+ JLabel label = (JLabel) getC(getC(component, 0), 1);
+ JPanel upper = (JPanel) getC(getC(getC(component, 0), 0), 0);
+ JPanel lower = (JPanel) getC(getC(getC(component, 0), 2), 0);
+ addSize(list, upper, 1, 1, 31, 9);
+ list.add(label.getText());
+ addSize(list, lower, 1, 1, 5, 7);
+ }
+
+ private static void addHSB(List<Object> list, JColorChooser chooser) {
+ Component component = addPanel(list, chooser, 1);
+ JRadioButton h = (JRadioButton) getC(getC(getC(component, 1), 0), 0);
+ JRadioButton s = (JRadioButton) getC(getC(getC(component, 1), 0), 2);
+ JRadioButton b = (JRadioButton) getC(getC(getC(component, 1), 0), 4);
+ list.add(h.getText());
+ list.add(s.getText());
+ list.add(b.getText());
+ JLabel red = (JLabel) getC(getC(getC(component, 1), 2), 0);
+ JLabel green = (JLabel) getC(getC(getC(component, 1), 2), 2);
+ JLabel blue = (JLabel) getC(getC(getC(component, 1), 2), 4);
+ list.add(red.getText());
+ list.add(green.getText());
+ list.add(blue.getText());
+ }
+
+ private static void addRGB(List<Object> list, JColorChooser chooser) {
+ Component component = addPanel(list, chooser, 2);
+ JLabel red = (JLabel) getC(getC(component, 0), 0);
+ JLabel green = (JLabel) getC(getC(component, 0), 3);
+ JLabel blue = (JLabel) getC(getC(component, 0), 6);
+ list.add(red.getText());
+ list.add(green.getText());
+ list.add(blue.getText());
+ list.add(Integer.valueOf(red.getDisplayedMnemonic()));
+ list.add(Integer.valueOf(green.getDisplayedMnemonic()));
+ list.add(Integer.valueOf(blue.getDisplayedMnemonic()));
+ }
+
+ private static void addSize(List<Object> list, Component component, int x, int y, int w, int h) {
+ Dimension size = component.getPreferredSize();
+ int width = (size.width + 1) / w - x;
+ int height = (size.height + 1) / h - y;
+ list.add(new Dimension(width, height));
+ }
+
+ private static Component addPanel(List<Object> list, JColorChooser chooser, int index) {
+ AbstractColorChooserPanel panel = (AbstractColorChooserPanel) getC(getC(getC(chooser, 0), index), 0);
+ list.add(panel.getDisplayName());
+ list.add(Integer.valueOf(panel.getMnemonic()));
+ list.add(Integer.valueOf(panel.getDisplayedMnemonicIndex()));
+ return panel;
+ }
+
+ private static Component getC(Component component, int index) {
+ Container container = (Container) component;
+ return container.getComponent(index);
+ }
+}
diff --git a/test/javax/swing/JColorChooser/Test6541987.java b/test/javax/swing/JColorChooser/Test6541987.java
new file mode 100644
index 0000000..bf00acf
--- /dev/null
+++ b/test/javax/swing/JColorChooser/Test6541987.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2005-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6541987
+ * @summary Tests closing by ESC
+ * @author Sergey Malenkov
+ */
+
+import java.awt.AWTException;
+import java.awt.Color;
+import java.awt.Robot;
+import java.awt.Toolkit;
+import java.awt.Window;
+import java.awt.event.KeyEvent;
+
+import javax.swing.JColorChooser;
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+
+import sun.awt.SunToolkit;
+
+public class Test6541987 implements Runnable {
+ private static final SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+ private static Robot robot;
+
+ public static void main(String[] args) throws AWTException {
+ robot = new Robot();
+ // test escape after selection
+ start();
+ click(KeyEvent.VK_ESCAPE);
+ toolkit.realSync();
+ // test double escape after editing
+ start();
+ click(KeyEvent.VK_1);
+ click(KeyEvent.VK_0);
+ click(KeyEvent.VK_ESCAPE);
+ click(KeyEvent.VK_ESCAPE);
+ toolkit.realSync();
+ // all windows should be closed
+ for (Window window : Window.getWindows()) {
+ if (window.isVisible()) {
+ throw new Error("found visible window: " + window.getName());
+ }
+ }
+ }
+
+ private static void start() {
+ SwingUtilities.invokeLater(new Test6541987());
+ click(KeyEvent.VK_ALT, KeyEvent.VK_H);
+ click(KeyEvent.VK_TAB);
+ click(KeyEvent.VK_TAB);
+ click(KeyEvent.VK_TAB);
+ click(KeyEvent.VK_TAB);
+ }
+
+ private static void click(int...keys) {
+ toolkit.realSync();
+ for (int key : keys) {
+ robot.keyPress(key);
+ }
+ for (int key : keys) {
+ robot.keyRelease(key);
+ }
+ }
+
+ public void run() {
+ String title = getClass().getName();
+ JFrame frame = new JFrame(title);
+ frame.setVisible(true);
+
+ Color color = JColorChooser.showDialog(frame, title, Color.BLACK);
+ if (color != null) {
+ throw new Error("unexpected color: " + color);
+ }
+ frame.setVisible(false);
+ frame.dispose();
+ }
+}
diff --git a/test/javax/swing/JLabel/6501991/bug6501991.java b/test/javax/swing/JLabel/6501991/bug6501991.java
new file mode 100644
index 0000000..5fb58d6
--- /dev/null
+++ b/test/javax/swing/JLabel/6501991/bug6501991.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ *
+ * @bug 6501991
+ * @author Igor Kushnirskiy
+ * @summary tests if ArrayIndexOutOfBoundsException is thrown on painting
+ * JLabel with i18n text in case JLabel has smaller width than needed.
+ */
+
+import java.awt.image.*;
+import javax.swing.*;
+
+public class bug6501991 {
+ public static void main(String[] args) {
+ try {
+ JLabel l = new JLabel("\u0634\u0634\u0634\u0634\u0634\u0634\u0634");
+ l.setSize(5, 22);
+
+ BufferedImage image =
+ new BufferedImage(50, 50, BufferedImage.TYPE_INT_RGB);
+ l.paint(image.createGraphics());
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new RuntimeException("failed");
+ }
+ }
+}
diff --git a/test/javax/swing/JPopupMenu/Separator/6547087/bug6547087.java b/test/javax/swing/JPopupMenu/Separator/6547087/bug6547087.java
new file mode 100644
index 0000000..65e89dc
--- /dev/null
+++ b/test/javax/swing/JPopupMenu/Separator/6547087/bug6547087.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ *
+ * @bug 6547087
+ * @author Igor Kushnirskiy
+ * @summary tests if JPopupMenu.Separator.getPreferredSize() does not throw NLP before the UI is set
+ */
+import java.util.concurrent.*;
+import javax.swing.*;
+
+public class bug6547087 {
+ public static void main(String[] args) throws Exception {
+ try {
+ invokeAndWait(
+ new Callable<Void>() {
+ public Void call() throws Exception {
+ test();
+ return null;
+ }
+ });
+ } catch (ExecutionException e) {
+ if (e.getCause() instanceof NullPointerException) {
+ throw new RuntimeException("failed");
+ }
+ }
+ }
+ static void test() throws Exception {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ JPopupMenu.Separator separator = new JPopupMenu.Separator();
+ separator.getPreferredSize();
+ }
+ static <T> T invokeAndWait(Callable<T> callable) throws Exception {
+ FutureTask<T> future = new FutureTask<T>(callable);
+ SwingUtilities.invokeLater(future);
+ return future.get();
+ }
+}
diff --git a/test/javax/swing/JSpinner/6463712/bug6463712.java b/test/javax/swing/JSpinner/6463712/bug6463712.java
new file mode 100644
index 0000000..e7227ec
--- /dev/null
+++ b/test/javax/swing/JSpinner/6463712/bug6463712.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import javax.swing.JSpinner;
+import javax.swing.SpinnerDateModel;
+import javax.swing.SpinnerNumberModel;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+/*
+ * @test
+ * @bug 6463712
+ * @summary Events forwarded from previous model
+ */
+public class bug6463712 implements ChangeListener {
+
+ public bug6463712() {
+ SpinnerNumberModel m1 = new SpinnerNumberModel();
+ JSpinner s = new JSpinner(m1);
+ s.addChangeListener(this);
+ SpinnerDateModel m2 = new SpinnerDateModel();
+ s.setModel(m2);
+
+ // m1 is no longer linked to the JSpinner (it has been replaced by m2), so
+ // the following should not trigger a call to our stateChanged() method...
+ m1.setValue(new Integer(1));
+ }
+
+ public void stateChanged(ChangeEvent e) {
+ throw new RuntimeException("Should not receive this event.");
+ }
+
+ public static void main(String[] args) {
+ bug6463712 bug = new bug6463712();
+ }
+}
diff --git a/test/javax/swing/SwingWorker/6432565/bug6432565.java b/test/javax/swing/SwingWorker/6432565/bug6432565.java
new file mode 100644
index 0000000..6d867b2
--- /dev/null
+++ b/test/javax/swing/SwingWorker/6432565/bug6432565.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @bug 6432565
+ * @summary Tests if no ArrayStoreException is thrown
+ * @author Igor Kushnirskiy
+ */
+import java.awt.*;
+import javax.swing.SwingWorker;
+import java.util.concurrent.atomic.*;
+
+
+public class bug6432565 {
+ private final static AtomicReference<Throwable> throwable =
+ new AtomicReference<Throwable>(null);
+ private final static AtomicBoolean isDone = new AtomicBoolean(false);
+ public static void main(String[] args) throws Exception {
+ Toolkit.getDefaultToolkit().getSystemEventQueue().push(new EventProcessor());
+
+ SwingWorker<Void, CharSequence> swingWorker =
+ new SwingWorker<Void,CharSequence>() {
+ @Override
+ protected Void doInBackground() {
+ publish(new String[] {"hello"});
+ publish(new StringBuilder("world"));
+ return null;
+ }
+ @Override
+ protected void done() {
+ isDone.set(true);
+ }
+ };
+ swingWorker.execute();
+
+ while (! isDone.get()) {
+ Thread.sleep(100);
+ }
+ if (throwable.get() instanceof ArrayStoreException) {
+ throw new RuntimeException("Test failed");
+ }
+ }
+ private final static class EventProcessor extends EventQueue {
+ @Override
+ protected void dispatchEvent(AWTEvent event) {
+ try {
+ super.dispatchEvent(event);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ throwable.set(e);
+ }
+ }
+ }
+}
diff --git a/test/javax/swing/SwingWorker/6480289/bug6480289.java b/test/javax/swing/SwingWorker/6480289/bug6480289.java
new file mode 100644
index 0000000..a9c1504
--- /dev/null
+++ b/test/javax/swing/SwingWorker/6480289/bug6480289.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ *
+ * @bug 6480289
+ * @author Igor Kushnirskiy
+ * @summary tests if consequent workers are executed on the same thread and that VM can exit.
+ */
+
+import java.util.*;
+import javax.swing.SwingWorker;
+
+public class bug6480289 {
+ private static final int ITERATIONS = 5;
+ private static final Map<Thread, Integer> threadMap =
+ Collections.synchronizedMap(new HashMap<Thread, Integer>());
+ public static void main(String[] args) throws Exception {
+
+ for (int i = 0; i < ITERATIONS; i++) {
+ if (i != 0) {
+ Thread.sleep(1000 * 5);
+ }
+ SwingWorker<?,?> worker =
+ new SwingWorker<Void, Void>() {
+ @Override
+ protected Void doInBackground() {
+ Integer value = threadMap.get(Thread.currentThread());
+ value = Integer.valueOf(
+ ((value == null) ? 0 : value.intValue())
+ + 1);
+ threadMap.put(Thread.currentThread(), value);
+ return null;
+ }
+ };
+ worker.execute();
+ }
+ if (threadMap.keySet().size() != 1) {
+ throw new RuntimeException("failed. More than one thread.");
+ }
+ }
+}
diff --git a/test/javax/swing/SwingWorker/6493680/bug6493680.java b/test/javax/swing/SwingWorker/6493680/bug6493680.java
new file mode 100644
index 0000000..7a19ead
--- /dev/null
+++ b/test/javax/swing/SwingWorker/6493680/bug6493680.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @bug 6493680
+ * @summary Tests if notifications are received in expected order
+ * @author Igor Kushnirskiy
+ */
+
+import javax.swing.*;
+import java.beans.*;
+import java.util.concurrent.atomic.*;
+import java.util.concurrent.*;
+
+
+public class bug6493680 {
+ /*
+ * because timing is involved in this bug we will run the test
+ * NUMBER_OF_TRIES times.
+ * the test passes if it does not fail once.
+ */
+ private final static int NUMBER_OF_TRIES = 50;
+
+ public static void main(String[] args) throws Exception {
+ for (int i = 0; i < NUMBER_OF_TRIES; i++) {
+ if (! (new Test()).test()) {
+ throw new RuntimeException("failed");
+ }
+ }
+ }
+
+ private static class Test {
+ private final AtomicInteger lastProgressValue = new AtomicInteger(-1);
+ private final Exchanger<Boolean> exchanger = new Exchanger<Boolean>();
+
+ boolean test() throws Exception {
+ TestSwingWorker swingWorker = new TestSwingWorker();
+ swingWorker.addPropertyChangeListener(
+ new PropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent evt) {
+ if ("progress" == evt.getPropertyName()) {
+ lastProgressValue.set((Integer) evt.getNewValue());
+ }
+ }
+ });
+
+ swingWorker.execute();
+ return exchanger.exchange(true);
+ }
+
+ private class TestSwingWorker extends SwingWorker<Void, Void> {
+ @Override
+ protected Void doInBackground() throws Exception {
+ for (int i = 0; i <= 100; i++) {
+ Thread.sleep(1);
+ setProgress(i);
+ }
+ return null;
+ }
+ @Override
+ protected void done() {
+ boolean isPassed = (lastProgressValue.get() == 100);
+ try {
+ exchanger.exchange(isPassed);
+ } catch (Exception ingore) {
+ }
+ }
+ }
+ }
+
+}
diff --git a/test/javax/swing/border/Test4856008.java b/test/javax/swing/border/Test4856008.java
new file mode 100644
index 0000000..1b045eb
--- /dev/null
+++ b/test/javax/swing/border/Test4856008.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4856008
+ * @summary Tests border insets
+ * @author Sergey Malenkov
+ */
+
+import com.sun.java.swing.plaf.motif.MotifBorders;
+import com.sun.java.swing.plaf.windows.WindowsBorders;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Insets;
+
+import javax.swing.JComponent;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JPopupMenu;
+import javax.swing.JToggleButton;
+import javax.swing.JToolBar;
+import javax.swing.border.AbstractBorder;
+import javax.swing.border.BevelBorder;
+import javax.swing.border.Border;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.EtchedBorder;
+import javax.swing.border.LineBorder;
+import javax.swing.border.MatteBorder;
+import javax.swing.border.SoftBevelBorder;
+import javax.swing.border.TitledBorder;
+import javax.swing.plaf.BorderUIResource;
+import javax.swing.plaf.synth.SynthLookAndFeel;
+import javax.swing.plaf.basic.BasicBorders;
+import javax.swing.plaf.basic.BasicToolBarUI;
+import javax.swing.plaf.metal.MetalBorders;
+import javax.swing.plaf.metal.MetalComboBoxEditor;
+
+import sun.swing.plaf.synth.SynthFileChooserUI;
+import sun.tools.jconsole.BorderedComponent;
+
+public class Test4856008 {
+ private static final JLabel LABEL = new JLabel();
+ private static final JPopupMenu POPUP = new JPopupMenu();
+ private static final JToolBar TOOLBAR = new JToolBar();
+
+ private static final Border[] BORDERS = {
+ new MotifBorders.BevelBorder(true, Color.BLACK, Color.WHITE),
+ new MotifBorders.ButtonBorder(Color.CYAN, Color.MAGENTA, Color.YELLOW, Color.BLACK),
+ new MotifBorders.FocusBorder(Color.BLACK, Color.WHITE),
+ new MotifBorders.FrameBorder(LABEL),
+ new MotifBorders.MenuBarBorder(Color.CYAN, Color.MAGENTA, Color.YELLOW, Color.BLACK),
+ new MotifBorders.MotifPopupMenuBorder(new Font(null, Font.PLAIN, 10), Color.CYAN, Color.MAGENTA, Color.YELLOW, Color.BLACK),
+ new MotifBorders.ToggleButtonBorder(Color.CYAN, Color.MAGENTA, Color.YELLOW, Color.BLACK),
+
+ new WindowsBorders.ProgressBarBorder(Color.BLACK, Color.WHITE),
+ new WindowsBorders.ToolBarBorder(Color.BLACK, Color.WHITE),
+ //- WindowsInternalFrameUI.XPBorder is not accessible: check it visually
+ //? WindowsTableHeaderUI.IconBorder is not accessible: check it visually
+ //- XPStyle.XPEmptyBorder is not accessible: check it visually
+ //- XPStyle.XPFillBorder is not accessible: check it visually
+ //- XPStyle.XPImageBorder is not accessible: check it visually
+
+ new BevelBorder(BevelBorder.RAISED),
+ new CompoundBorder(),
+ new EmptyBorder(1, 2, 3, 4),
+ new EtchedBorder(),
+ new LineBorder(Color.BLACK, 2, true),
+ new MatteBorder(1, 2, 3, 4, Color.BLACK),
+ new SoftBevelBorder(BevelBorder.LOWERED),
+ new TitledBorder("4856008"),
+
+ new BorderUIResource(new EmptyBorder(1, 2, 3, 4)),
+
+ new BasicBorders.ButtonBorder(Color.CYAN, Color.MAGENTA, Color.YELLOW, Color.BLACK),
+ new BasicBorders.FieldBorder(Color.CYAN, Color.MAGENTA, Color.YELLOW, Color.BLACK),
+ new BasicBorders.MarginBorder(),
+ new BasicBorders.MenuBarBorder(Color.BLACK, Color.WHITE),
+ new BasicBorders.RadioButtonBorder(Color.CYAN, Color.MAGENTA, Color.YELLOW, Color.BLACK),
+ //+ BasicBorders.RolloverMarginBorder:
+ new ToolBar().getRolloverMarginBorder(),
+ new BasicBorders.SplitPaneBorder(Color.BLACK, Color.WHITE),
+ //+ BasicBorders.SplitPaneDividerBorder:
+ BasicBorders.getSplitPaneDividerBorder(),
+ new BasicBorders.ToggleButtonBorder(Color.CYAN, Color.MAGENTA, Color.YELLOW, Color.BLACK),
+
+ new MetalBorders.ButtonBorder(),
+ //- MetalBorders.DialogBorder is not accessible: check it visually
+ new MetalBorders.Flush3DBorder(),
+ //- MetalBorders.FrameBorder is not accessible: check it visually
+ new MetalBorders.InternalFrameBorder(),
+ new MetalBorders.MenuBarBorder(),
+ new MetalBorders.MenuItemBorder(),
+ new MetalBorders.OptionDialogBorder(),
+ new MetalBorders.PaletteBorder(),
+ new MetalBorders.PopupMenuBorder(),
+ //- MetalBorders.RolloverMarginBorder is not accessible: check it visually
+ new MetalBorders.ScrollPaneBorder(),
+ new MetalBorders.TableHeaderBorder(),
+ new MetalBorders.ToolBarBorder(),
+ //+ MetalComboBoxEditor.EditorBorder:
+ new MetalEditor().getEditorBorder(),
+
+ //- SynthBorder is not accessible: check it visually
+ //- SynthScrollPaneUI.ViewportBorder is not accessible: check it visually
+
+ //? CSSBorder is not accessible: check it visually
+ //? CommentView.CommentBorder is not accessible: check it visually
+ //- HiddenTagView.EndTagBorder is not accessible: check it visually
+ //- HiddenTagView.StartTagBorder is not accessible: check it visually
+
+ //+ SynthFileChooserUI.UIBorder:
+ new SynthFileChooser().getUIBorder(),
+
+ //+ BorderedComponent.FocusBorder:
+ getBorder(false),
+ //+ BorderedComponent.LabeledBorder:
+ getBorder(true),
+ };
+
+ public static void main(String[] args) {
+ for (Border border : BORDERS) {
+ System.out.println(border.getClass());
+ test(border, border.getBorderInsets(getComponent(border)));
+ if (border instanceof AbstractBorder) {
+ test((AbstractBorder) border);
+ }
+ }
+ }
+
+ private static void test(AbstractBorder border) {
+ Insets insets = new Insets(0, 0, 0, 0);
+ if (insets != border.getBorderInsets(getComponent(border), insets)) {
+ throw new Error("both instances are differ for " + border.getClass());
+ }
+ test(border, insets);
+ }
+
+ private static void test(Border border, Insets insets) {
+ Insets result = border.getBorderInsets(getComponent(border));
+ if (insets == result) {
+ throw new Error("both instances are the same for " + border.getClass());
+ }
+ if (!insets.equals(result)) {
+ throw new Error("both insets are not equal for " + border.getClass());
+ }
+ }
+
+ private static JComponent getComponent(Border border) {
+ Class type = border.getClass();
+ if (type.equals(MotifBorders.MotifPopupMenuBorder.class)) {
+ return POPUP;
+ }
+ if (type.equals(WindowsBorders.ToolBarBorder.class)) {
+ return TOOLBAR;
+ }
+ if (type.equals(MetalBorders.ToolBarBorder.class)) {
+ return TOOLBAR;
+ }
+ return LABEL;
+ }
+
+ // This method is used to get the border from BorderedComponent
+ private static Border getBorder(boolean labeled) {
+ JComponent component = new BorderedComponent("4856008", null, true);
+ CompoundBorder border = (CompoundBorder) component.getBorder();
+ return labeled
+ ? border.getInsideBorder()
+ : border.getOutsideBorder();
+ }
+
+ // This class is used to get the instance of BasicBorders.RolloverMarginBorder
+ private static class ToolBar extends BasicToolBarUI {
+ private Border getRolloverMarginBorder() {
+ JToggleButton button = new JToggleButton();
+ CompoundBorder border = (CompoundBorder) getNonRolloverBorder(button);
+ return border.getInsideBorder();
+ }
+ }
+
+ // This class is used to get the instance of MetalComboBoxEditor.EditorBorder
+ private static class MetalEditor extends MetalComboBoxEditor {
+ private Border getEditorBorder() {
+ return editor.getBorder();
+ }
+ }
+
+ // This class is used to get the instance of SynthFileChooserUI.UIBorder
+ private static class SynthFileChooser extends SynthFileChooserUI {
+ private static final JFileChooser CHOOSER = new JFileChooser();
+ private String name;
+
+ private SynthFileChooser() {
+ super(CHOOSER);
+ }
+
+ private Border getUIBorder() {
+ new SynthLookAndFeel().initialize();
+ CHOOSER.setBorder(null);
+ installDefaults(CHOOSER);
+ return CHOOSER.getBorder();
+ }
+
+ @Override
+ public String getFileName() {
+ return this.name;
+ }
+
+ @Override
+ public void setFileName(String name) {
+ this.name = name;
+ }
+ }
+}
diff --git a/test/javax/xml/crypto/dsig/GenerationTests.java b/test/javax/xml/crypto/dsig/GenerationTests.java
new file mode 100644
index 0000000..dea5335
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/GenerationTests.java
@@ -0,0 +1,1090 @@
+/*
+ * Copyright 2005-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 4635230
+ * @bug 6283345
+ * @bug 6303830
+ * @summary Basic unit tests for generating XML Signatures with JSR 105
+ * @compile -XDignore.symbol.file KeySelectors.java SignatureValidator.java
+ * X509KeySelector.java GenerationTests.java
+ * @run main GenerationTests
+ * @author Sean Mullan
+ */
+
+import java.io.*;
+import java.math.BigInteger;
+import java.security.Key;
+import java.security.KeyFactory;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.security.cert.X509CRL;
+import java.security.spec.KeySpec;
+import java.security.spec.DSAPrivateKeySpec;
+import java.security.spec.DSAPublicKeySpec;
+import java.security.spec.RSAPrivateKeySpec;
+import java.security.spec.RSAPublicKeySpec;
+import java.util.*;
+import javax.crypto.SecretKey;
+import javax.xml.XMLConstants;
+import javax.xml.parsers.*;
+import org.w3c.dom.*;
+import javax.xml.crypto.Data;
+import javax.xml.crypto.KeySelector;
+import javax.xml.crypto.OctetStreamData;
+import javax.xml.crypto.URIDereferencer;
+import javax.xml.crypto.URIReference;
+import javax.xml.crypto.URIReferenceException;
+import javax.xml.crypto.XMLCryptoContext;
+import javax.xml.crypto.XMLStructure;
+import javax.xml.crypto.dsig.*;
+import javax.xml.crypto.dom.*;
+import javax.xml.crypto.dsig.dom.DOMSignContext;
+import javax.xml.crypto.dsig.dom.DOMValidateContext;
+import javax.xml.crypto.dsig.keyinfo.*;
+import javax.xml.crypto.dsig.spec.*;
+import javax.xml.transform.*;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+/**
+ * Test that recreates merlin-xmldsig-twenty-three test vectors but with
+ * different keys and X.509 data.
+ */
+public class GenerationTests {
+
+ private static XMLSignatureFactory fac;
+ private static KeyInfoFactory kifac;
+ private static DocumentBuilder db;
+ private static CanonicalizationMethod withoutComments;
+ private static SignatureMethod dsaSha1, rsaSha1, rsaSha256, rsaSha384, rsaSha512;
+ private static DigestMethod sha1, sha256, sha384, sha512;
+ private static KeyInfo dsa, rsa, rsa1024;
+ private static KeySelector kvks = new KeySelectors.KeyValueKeySelector();
+ private static KeySelector sks;
+ private static Key signingKey;
+ private static PublicKey validatingKey;
+ private static Certificate signingCert;
+ private static KeyStore ks;
+ private final static String DIR = System.getProperty("test.src", ".");
+ private final static String DATA_DIR =
+ DIR + System.getProperty("file.separator") + "data";
+ private final static String KEYSTORE =
+ DATA_DIR + System.getProperty("file.separator") + "certs" +
+ System.getProperty("file.separator") + "test.jks";
+ private final static String CRL =
+ DATA_DIR + System.getProperty("file.separator") + "certs" +
+ System.getProperty("file.separator") + "crl";
+ private final static String ENVELOPE =
+ DATA_DIR + System.getProperty("file.separator") + "envelope.xml";
+ private static URIDereferencer httpUd = null;
+ private final static String STYLESHEET =
+ "http://www.w3.org/TR/xml-stylesheet";
+ private final static String STYLESHEET_B64 =
+ "http://www.w3.org/Signature/2002/04/xml-stylesheet.b64";
+
+ public static void main(String args[]) throws Exception {
+ setup();
+ test_create_signature_enveloped_dsa();
+ test_create_signature_enveloping_b64_dsa();
+ test_create_signature_enveloping_dsa();
+ test_create_signature_enveloping_hmac_sha1_40();
+ test_create_signature_enveloping_hmac_sha256();
+ test_create_signature_enveloping_hmac_sha384();
+ test_create_signature_enveloping_hmac_sha512();
+ test_create_signature_enveloping_rsa();
+ test_create_signature_external_b64_dsa();
+ test_create_signature_external_dsa();
+ test_create_signature_keyname();
+ test_create_signature_retrievalmethod_rawx509crt();
+ test_create_signature_x509_crt_crl();
+ test_create_signature_x509_crt();
+ test_create_signature_x509_is();
+ test_create_signature_x509_ski();
+ test_create_signature_x509_sn();
+// test_create_signature();
+ test_create_exc_signature();
+ test_create_sign_spec();
+ test_create_signature_enveloping_sha256_dsa();
+ test_create_signature_enveloping_sha384_rsa_sha256();
+ test_create_signature_enveloping_sha512_rsa_sha384();
+ test_create_signature_enveloping_sha512_rsa_sha512();
+ }
+
+ private static void setup() throws Exception {
+ fac = XMLSignatureFactory.getInstance();
+ kifac = fac.getKeyInfoFactory();
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ db = dbf.newDocumentBuilder();
+
+ // get key & self-signed certificate from keystore
+ FileInputStream fis = new FileInputStream(KEYSTORE);
+ ks = KeyStore.getInstance("JKS");
+ ks.load(fis, "changeit".toCharArray());
+ signingKey = ks.getKey("user", "changeit".toCharArray());
+ signingCert = ks.getCertificate("user");
+ validatingKey = signingCert.getPublicKey();
+
+ // create common objects
+ withoutComments = fac.newCanonicalizationMethod
+ (CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec)null);
+ dsaSha1 = fac.newSignatureMethod(SignatureMethod.DSA_SHA1, null);
+ sha1 = fac.newDigestMethod(DigestMethod.SHA1, null);
+ sha256 = fac.newDigestMethod(DigestMethod.SHA256, null);
+ sha384 = fac.newDigestMethod
+ ("http://www.w3.org/2001/04/xmldsig-more#sha384", null);
+ sha512 = fac.newDigestMethod(DigestMethod.SHA512, null);
+ dsa = kifac.newKeyInfo(Collections.singletonList
+ (kifac.newKeyValue(validatingKey)));
+ rsa = kifac.newKeyInfo(Collections.singletonList
+ (kifac.newKeyValue(getPublicKey("RSA"))));
+ rsa1024 = kifac.newKeyInfo(Collections.singletonList
+ (kifac.newKeyValue(getPublicKey("RSA", 1024))));
+ rsaSha1 = fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null);
+ rsaSha256 = fac.newSignatureMethod
+ ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", null);
+ rsaSha384 = fac.newSignatureMethod
+ ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha384", null);
+ rsaSha512 = fac.newSignatureMethod
+ ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", null);
+ sks = new KeySelectors.SecretKeySelector("secret".getBytes("ASCII"));
+
+ httpUd = new HttpURIDereferencer();
+ }
+
+ static void test_create_signature_enveloped_dsa() throws Exception {
+ System.out.println("* Generating signature-enveloped-dsa.xml");
+ // create SignedInfo
+ SignedInfo si = fac.newSignedInfo
+ (withoutComments, dsaSha1, Collections.singletonList
+ (fac.newReference
+ ("", sha1, Collections.singletonList
+ (fac.newTransform(Transform.ENVELOPED,
+ (TransformParameterSpec) null)),
+ null, null)));
+
+ // create XMLSignature
+ XMLSignature sig = fac.newXMLSignature(si, dsa);
+
+ Document doc = db.newDocument();
+ Element envelope = doc.createElementNS
+ ("http://example.org/envelope", "Envelope");
+ envelope.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI,
+ "xmlns", "http://example.org/envelope");
+ doc.appendChild(envelope);
+
+ DOMSignContext dsc = new DOMSignContext(signingKey, envelope);
+
+ sig.sign(dsc);
+
+ DOMValidateContext dvc = new DOMValidateContext
+ (kvks, envelope.getFirstChild());
+ XMLSignature sig2 = fac.unmarshalXMLSignature(dvc);
+
+ if (sig.equals(sig2) == false) {
+ throw new Exception
+ ("Unmarshalled signature is not equal to generated signature");
+ }
+
+ if (sig2.validate(dvc) == false) {
+ throw new Exception("Validation of generated signature failed");
+ }
+ System.out.println();
+ }
+
+ static void test_create_signature_enveloping_b64_dsa() throws Exception {
+ System.out.println("* Generating signature-enveloping-b64-dsa.xml");
+ test_create_signature_enveloping
+ (sha1, dsaSha1, dsa, signingKey, kvks, true);
+ System.out.println();
+ }
+
+ static void test_create_signature_enveloping_dsa() throws Exception {
+ System.out.println("* Generating signature-enveloping-dsa.xml");
+ test_create_signature_enveloping
+ (sha1, dsaSha1, dsa, signingKey, kvks, false);
+ System.out.println();
+ }
+
+ static void test_create_signature_enveloping_sha256_dsa() throws Exception {
+ System.out.println("* Generating signature-enveloping-sha256-dsa.xml");
+ test_create_signature_enveloping
+ (sha256, dsaSha1, dsa, signingKey, kvks, false);
+ System.out.println();
+ }
+
+ static void test_create_signature_enveloping_hmac_sha1_40()
+ throws Exception {
+ System.out.println("* Generating signature-enveloping-hmac-sha1-40.xml");
+ SignatureMethod hmacSha1 = fac.newSignatureMethod
+ (SignatureMethod.HMAC_SHA1, new HMACParameterSpec(40));
+ test_create_signature_enveloping(sha1, hmacSha1, null,
+ getSecretKey("secret".getBytes("ASCII")), sks, false);
+ System.out.println();
+ }
+
+ static void test_create_signature_enveloping_hmac_sha256()
+ throws Exception {
+ System.out.println("* Generating signature-enveloping-hmac-sha256.xml");
+ SignatureMethod hmacSha256 = fac.newSignatureMethod
+ ("http://www.w3.org/2001/04/xmldsig-more#hmac-sha256", null);
+ test_create_signature_enveloping(sha1, hmacSha256, null,
+ getSecretKey("secret".getBytes("ASCII")), sks, false);
+ System.out.println();
+ }
+
+ static void test_create_signature_enveloping_hmac_sha384()
+ throws Exception {
+ System.out.println("* Generating signature-enveloping-hmac-sha384.xml");
+ SignatureMethod hmacSha384 = fac.newSignatureMethod
+ ("http://www.w3.org/2001/04/xmldsig-more#hmac-sha384", null);
+ test_create_signature_enveloping(sha1, hmacSha384, null,
+ getSecretKey("secret".getBytes("ASCII")), sks, false);
+ System.out.println();
+ }
+
+ static void test_create_signature_enveloping_hmac_sha512()
+ throws Exception {
+ System.out.println("* Generating signature-enveloping-hmac-sha512.xml");
+ SignatureMethod hmacSha512 = fac.newSignatureMethod
+ ("http://www.w3.org/2001/04/xmldsig-more#hmac-sha512", null);
+ test_create_signature_enveloping(sha1, hmacSha512, null,
+ getSecretKey("secret".getBytes("ASCII")), sks, false);
+ System.out.println();
+ }
+
+ static void test_create_signature_enveloping_rsa() throws Exception {
+ System.out.println("* Generating signature-enveloping-rsa.xml");
+ test_create_signature_enveloping(sha1, rsaSha1, rsa,
+ getPrivateKey("RSA"), kvks, false);
+ System.out.println();
+ }
+
+ static void test_create_signature_enveloping_sha384_rsa_sha256()
+ throws Exception {
+ System.out.println("* Generating signature-enveloping-sha384-rsa_sha256.xml");
+ test_create_signature_enveloping(sha384, rsaSha256, rsa,
+ getPrivateKey("RSA"), kvks, false);
+ System.out.println();
+ }
+
+ static void test_create_signature_enveloping_sha512_rsa_sha384()
+ throws Exception {
+ System.out.println("* Generating signature-enveloping-sha512-rsa_sha384.xml");
+ test_create_signature_enveloping(sha512, rsaSha384, rsa1024,
+ getPrivateKey("RSA", 1024), kvks, false);
+ System.out.println();
+ }
+
+ static void test_create_signature_enveloping_sha512_rsa_sha512()
+ throws Exception {
+ System.out.println("* Generating signature-enveloping-sha512-rsa_sha512.xml");
+ test_create_signature_enveloping(sha512, rsaSha512, rsa1024,
+ getPrivateKey("RSA", 1024), kvks, false);
+ System.out.println();
+ }
+
+ static void test_create_signature_external_b64_dsa() throws Exception {
+ System.out.println("* Generating signature-external-b64-dsa.xml");
+ test_create_signature_external(dsaSha1, dsa, signingKey, kvks, true);
+ System.out.println();
+ }
+
+ static void test_create_signature_external_dsa() throws Exception {
+ System.out.println("* Generating signature-external-dsa.xml");
+ test_create_signature_external(dsaSha1, dsa, signingKey, kvks, false);
+ System.out.println();
+ }
+
+ static void test_create_signature_keyname() throws Exception {
+ System.out.println("* Generating signature-keyname.xml");
+ KeyInfo kn = kifac.newKeyInfo(Collections.singletonList
+ (kifac.newKeyName("user")));
+ test_create_signature_external(dsaSha1, kn, signingKey,
+ new X509KeySelector(ks), false);
+ System.out.println();
+ }
+
+ static void test_create_signature_retrievalmethod_rawx509crt()
+ throws Exception {
+ System.out.println(
+ "* Generating signature-retrievalmethod-rawx509crt.xml");
+ KeyInfo rm = kifac.newKeyInfo(Collections.singletonList
+ (kifac.newRetrievalMethod
+ ("certs/user.crt", X509Data.RAW_X509_CERTIFICATE_TYPE, null)));
+ test_create_signature_external(dsaSha1, rm, signingKey,
+ new X509KeySelector(ks), false);
+ System.out.println();
+ }
+
+ static void test_create_signature_x509_crt_crl() throws Exception {
+ System.out.println("* Generating signature-x509-crt-crl.xml");
+ List<Object> xds = new ArrayList<Object>();
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ xds.add(signingCert);
+ FileInputStream fis = new FileInputStream(CRL);
+ X509CRL crl = (X509CRL) cf.generateCRL(fis);
+ fis.close();
+ xds.add(crl);
+ KeyInfo crt_crl = kifac.newKeyInfo(Collections.singletonList
+ (kifac.newX509Data(xds)));
+
+ test_create_signature_external(dsaSha1, crt_crl, signingKey,
+ new X509KeySelector(ks), false);
+ System.out.println();
+ }
+
+ static void test_create_signature_x509_crt() throws Exception {
+ System.out.println("* Generating signature-x509-crt.xml");
+ KeyInfo crt = kifac.newKeyInfo(Collections.singletonList
+ (kifac.newX509Data(Collections.singletonList(signingCert))));
+
+ test_create_signature_external(dsaSha1, crt, signingKey,
+ new X509KeySelector(ks), false);
+ System.out.println();
+ }
+
+ static void test_create_signature_x509_is() throws Exception {
+ System.out.println("* Generating signature-x509-is.xml");
+ KeyInfo is = kifac.newKeyInfo(Collections.singletonList
+ (kifac.newX509Data(Collections.singletonList
+ (kifac.newX509IssuerSerial
+ ("CN=User", new BigInteger("45ef2729", 16))))));
+ test_create_signature_external(dsaSha1, is, signingKey,
+ new X509KeySelector(ks), false);
+ System.out.println();
+ }
+
+ static void test_create_signature_x509_ski() throws Exception {
+ System.out.println("* Generating signature-x509-ski.xml");
+ KeyInfo ski = kifac.newKeyInfo(Collections.singletonList
+ (kifac.newX509Data(Collections.singletonList
+ ("keyid".getBytes("ASCII")))));
+
+ test_create_signature_external(dsaSha1, ski, signingKey,
+ KeySelector.singletonKeySelector(validatingKey), false);
+ System.out.println();
+ }
+
+ static void test_create_signature_x509_sn() throws Exception {
+ System.out.println("* Generating signature-x509-sn.xml");
+ KeyInfo sn = kifac.newKeyInfo(Collections.singletonList
+ (kifac.newX509Data(Collections.singletonList("CN=User"))));
+
+ test_create_signature_external(dsaSha1, sn, signingKey,
+ new X509KeySelector(ks), false);
+ System.out.println();
+ }
+
+ static void test_create_signature() throws Exception {
+ System.out.println("* Generating signature.xml");
+
+ // create references
+ List<Reference> refs = new ArrayList<Reference>();
+
+ // Reference 1
+ refs.add(fac.newReference(STYLESHEET, sha1));
+
+ // Reference 2
+ refs.add(fac.newReference
+ (STYLESHEET_B64,
+ sha1, Collections.singletonList
+ (fac.newTransform(Transform.BASE64,
+ (TransformParameterSpec) null)), null, null));
+
+ // Reference 3
+ refs.add(fac.newReference("#object-1", sha1, Collections.singletonList
+ (fac.newTransform(Transform.XPATH,
+ new XPathFilterParameterSpec("self::text()"))),
+ XMLObject.TYPE, null));
+
+ // Reference 4
+ String expr = "\n"
+ + " ancestor-or-self::dsig:SignedInfo " + "\n"
+ + " and " + "\n"
+ + " count(ancestor-or-self::dsig:Reference | " + "\n"
+ + " here()/ancestor::dsig:Reference[1]) > " + "\n"
+ + " count(ancestor-or-self::dsig:Reference) " + "\n"
+ + " or " + "\n"
+ + " count(ancestor-or-self::node() | " + "\n"
+ + " id('notaries')) = " + "\n"
+ + " count(ancestor-or-self::node()) " + "\n";
+
+ XPathFilterParameterSpec xfp = new XPathFilterParameterSpec(expr,
+ Collections.singletonMap("dsig", XMLSignature.XMLNS));
+ refs.add(fac.newReference("", sha1, Collections.singletonList
+ (fac.newTransform(Transform.XPATH, xfp)),
+ XMLObject.TYPE, null));
+
+ // Reference 5
+ refs.add(fac.newReference("#object-2", sha1, Collections.singletonList
+ (fac.newTransform
+ (Transform.BASE64, (TransformParameterSpec) null)),
+ XMLObject.TYPE, null));
+
+ // Reference 6
+ refs.add(fac.newReference
+ ("#manifest-1", sha1, null, Manifest.TYPE, null));
+
+ // Reference 7
+ refs.add(fac.newReference("#signature-properties-1", sha1, null,
+ SignatureProperties.TYPE, null));
+
+ // Reference 8
+ List<Transform> transforms = new ArrayList<Transform>();
+ transforms.add(fac.newTransform
+ (Transform.ENVELOPED, (TransformParameterSpec) null));
+ refs.add(fac.newReference("", sha1, transforms, null, null));
+
+ // Reference 9
+ transforms.add(fac.newTransform
+ (CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS,
+ (TransformParameterSpec) null));
+ refs.add(fac.newReference("", sha1, transforms, null, null));
+
+ // Reference 10
+ Transform env = fac.newTransform
+ (Transform.ENVELOPED, (TransformParameterSpec) null);
+ refs.add(fac.newReference("#xpointer(/)",
+ sha1, Collections.singletonList(env), null, null));
+
+ // Reference 11
+ transforms.clear();
+ transforms.add(fac.newTransform
+ (Transform.ENVELOPED, (TransformParameterSpec) null));
+ transforms.add(fac.newTransform
+ (CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS,
+ (TransformParameterSpec) null));
+ refs.add(fac.newReference("#xpointer(/)", sha1, transforms,
+ null, null));
+
+ // Reference 12
+ refs.add
+ (fac.newReference("#object-3", sha1, null, XMLObject.TYPE, null));
+
+ // Reference 13
+ Transform withComments = fac.newTransform
+ (CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS,
+ (TransformParameterSpec) null);
+ refs.add(fac.newReference("#object-3", sha1,
+ Collections.singletonList(withComments), XMLObject.TYPE, null));
+
+ // Reference 14
+ refs.add(fac.newReference("#xpointer(id('object-3'))", sha1, null,
+ XMLObject.TYPE, null));
+
+ // Reference 15
+ withComments = fac.newTransform
+ (CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS,
+ (TransformParameterSpec) null);
+ refs.add(fac.newReference("#xpointer(id('object-3'))", sha1,
+ Collections.singletonList(withComments), XMLObject.TYPE, null));
+
+ // Reference 16
+ refs.add(fac.newReference("#reference-2", sha1));
+
+ // Reference 17
+ refs.add(fac.newReference("#manifest-reference-1", sha1, null,
+ null, "reference-1"));
+
+ // Reference 18
+ refs.add(fac.newReference("#reference-1", sha1, null, null,
+ "reference-2"));
+
+ // create SignedInfo
+ SignedInfo si = fac.newSignedInfo(withoutComments, dsaSha1, refs);
+
+ // create keyinfo
+ XPathFilterParameterSpec xpf = new XPathFilterParameterSpec(
+ "ancestor-or-self::dsig:X509Data",
+ Collections.singletonMap("dsig", XMLSignature.XMLNS));
+ RetrievalMethod rm = kifac.newRetrievalMethod("#object-4",
+ X509Data.TYPE, Collections.singletonList(fac.newTransform
+ (Transform.XPATH, xpf)));
+ KeyInfo ki = kifac.newKeyInfo(Collections.singletonList(rm), null);
+
+ Document doc = db.newDocument();
+
+ // create objects
+ List<XMLStructure> objs = new ArrayList<XMLStructure>();
+
+ // Object 1
+ objs.add(fac.newXMLObject(Collections.singletonList
+ (new DOMStructure(doc.createTextNode("I am the text."))),
+ "object-1", "text/plain", null));
+
+ // Object 2
+ objs.add(fac.newXMLObject(Collections.singletonList
+ (new DOMStructure(doc.createTextNode("SSBhbSB0aGUgdGV4dC4="))),
+ "object-2", "text/plain", Transform.BASE64));
+
+ // Object 3
+ Element nc = doc.createElementNS(null, "NonCommentandus");
+ nc.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "");
+ nc.appendChild(doc.createComment(" Commentandum "));
+ objs.add(fac.newXMLObject(Collections.singletonList
+ (new DOMStructure(nc)), "object-3", null, null));
+
+ // Manifest
+ List<Reference> manRefs = new ArrayList<Reference>();
+
+ // Manifest Reference 1
+ manRefs.add(fac.newReference(STYLESHEET,
+ sha1, null, null, "manifest-reference-1"));
+
+ // Manifest Reference 2
+ manRefs.add(fac.newReference("#reference-1", sha1));
+
+ // Manifest Reference 3
+ List<Transform> manTrans = new ArrayList<Transform>();
+ String xslt = ""
+ + "<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform'\n"
+ + " xmlns='http://www.w3.org/TR/xhtml1/strict' \n"
+ + " exclude-result-prefixes='foo' \n"
+ + " version='1.0'>\n"
+ + " <xsl:output encoding='UTF-8' \n"
+ + " indent='no' \n"
+ + " method='xml' />\n"
+ + " <xsl:template match='/'>\n"
+ + " <html>\n"
+ + " <head>\n"
+ + " <title>Notaries</title>\n"
+ + " </head>\n"
+ + " <body>\n"
+ + " <table>\n"
+ + " <xsl:for-each select='Notaries/Notary'>\n"
+ + " <tr>\n"
+ + " <th>\n"
+ + " <xsl:value-of select='@name' />\n"
+ + " </th>\n"
+ + " </tr>\n"
+ + " </xsl:for-each>\n"
+ + " </table>\n"
+ + " </body>\n"
+ + " </html>\n"
+ + " </xsl:template>\n"
+ + "</xsl:stylesheet>\n";
+ Document docxslt = db.parse(new ByteArrayInputStream(xslt.getBytes()));
+ Node xslElem = docxslt.getDocumentElement();
+
+ manTrans.add(fac.newTransform(Transform.XSLT,
+ new XSLTTransformParameterSpec(new DOMStructure(xslElem))));
+ manTrans.add(fac.newTransform(CanonicalizationMethod.INCLUSIVE,
+ (TransformParameterSpec) null));
+ manRefs.add(fac.newReference("#notaries", sha1, manTrans, null, null));
+
+ objs.add(fac.newXMLObject(Collections.singletonList
+ (fac.newManifest(manRefs, "manifest-1")), null, null, null));
+
+ // SignatureProperties
+ Element sa = doc.createElementNS("urn:demo", "SignerAddress");
+ sa.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "urn:demo");
+ Element ip = doc.createElementNS("urn:demo", "IP");
+ ip.appendChild(doc.createTextNode("192.168.21.138"));
+ sa.appendChild(ip);
+ SignatureProperty sp = fac.newSignatureProperty
+ (Collections.singletonList(new DOMStructure(sa)),
+ "#signature", null);
+ SignatureProperties sps = fac.newSignatureProperties
+ (Collections.singletonList(sp), "signature-properties-1");
+ objs.add(fac.newXMLObject(Collections.singletonList(sps), null,
+ null, null));
+
+ // Object 4
+ List<Object> xds = new ArrayList<Object>();
+ xds.add("CN=User");
+ xds.add(kifac.newX509IssuerSerial
+ ("CN=User", new BigInteger("45ef2729", 16)));
+ xds.add(signingCert);
+ objs.add(fac.newXMLObject(Collections.singletonList
+ (kifac.newX509Data(xds)), "object-4", null, null));
+
+ // create XMLSignature
+ XMLSignature sig = fac.newXMLSignature(si, ki, objs, "signature", null);
+
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ dbf.setValidating(false);
+ Document envDoc = dbf.newDocumentBuilder().parse
+ (new FileInputStream(ENVELOPE));
+ Element ys = (Element)
+ envDoc.getElementsByTagName("YoursSincerely").item(0);
+
+ DOMSignContext dsc = new DOMSignContext(signingKey, ys);
+
+ sig.sign(dsc);
+
+// StringWriter sw = new StringWriter();
+// dumpDocument(envDoc, sw);
+
+ NodeList nl =
+ envDoc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
+ if (nl.getLength() == 0) {
+ throw new Exception("Couldn't find signature Element");
+ }
+ Element sigElement = (Element) nl.item(0);
+
+ DOMValidateContext dvc = new DOMValidateContext
+ (new X509KeySelector(ks), sigElement);
+ File f = new File(
+ System.getProperty("dir.test.vector.baltimore") +
+ System.getProperty("file.separator") +
+ "merlin-xmldsig-twenty-three" +
+ System.getProperty("file.separator"));
+ dvc.setBaseURI(f.toURI().toString());
+
+ XMLSignature sig2 = fac.unmarshalXMLSignature(dvc);
+
+ if (sig.equals(sig2) == false) {
+ throw new Exception
+ ("Unmarshalled signature is not equal to generated signature");
+ }
+ if (sig2.validate(dvc) == false) {
+ throw new Exception("Validation of generated signature failed");
+ }
+ System.out.println();
+ }
+
+ private static void dumpDocument(Document doc, Writer w) throws Exception {
+ TransformerFactory tf = TransformerFactory.newInstance();
+ Transformer trans = tf.newTransformer();
+// trans.setOutputProperty(OutputKeys.INDENT, "yes");
+ trans.transform(new DOMSource(doc), new StreamResult(w));
+ }
+
+ private static void test_create_signature_external
+ (SignatureMethod sm, KeyInfo ki, Key signingKey, KeySelector ks,
+ boolean b64) throws Exception {
+
+ // create reference
+ Reference ref;
+ if (b64) {
+ ref = fac.newReference
+ (STYLESHEET_B64,
+ sha1, Collections.singletonList
+ (fac.newTransform(Transform.BASE64,
+ (TransformParameterSpec) null)), null, null);
+ } else {
+ ref = fac.newReference(STYLESHEET, sha1);
+ }
+
+ // create SignedInfo
+ SignedInfo si = fac.newSignedInfo(withoutComments, sm,
+ Collections.singletonList(ref));
+
+ Document doc = db.newDocument();
+
+ // create XMLSignature
+ XMLSignature sig = fac.newXMLSignature(si, ki);
+
+ DOMSignContext dsc = new DOMSignContext(signingKey, doc);
+ dsc.setURIDereferencer(httpUd);
+
+ sig.sign(dsc);
+
+ DOMValidateContext dvc = new DOMValidateContext
+ (ks, doc.getDocumentElement());
+ File f = new File(DATA_DIR);
+ dvc.setBaseURI(f.toURI().toString());
+ dvc.setURIDereferencer(httpUd);
+
+ XMLSignature sig2 = fac.unmarshalXMLSignature(dvc);
+
+ if (sig.equals(sig2) == false) {
+ throw new Exception
+ ("Unmarshalled signature is not equal to generated signature");
+ }
+ if (sig2.validate(dvc) == false) {
+ throw new Exception("Validation of generated signature failed");
+ }
+ }
+
+ private static void test_create_signature_enveloping
+ (DigestMethod dm, SignatureMethod sm, KeyInfo ki, Key signingKey,
+ KeySelector ks, boolean b64) throws Exception {
+
+ // create reference
+ Reference ref;
+ if (b64) {
+ ref = fac.newReference("#object", dm, Collections.singletonList
+ (fac.newTransform(Transform.BASE64,
+ (TransformParameterSpec) null)), null, null);
+ } else {
+ ref = fac.newReference("#object", dm);
+ }
+
+ // create SignedInfo
+ SignedInfo si = fac.newSignedInfo(withoutComments, sm,
+ Collections.singletonList(ref));
+
+ Document doc = db.newDocument();
+ // create Objects
+ String text = b64 ? "c29tZSB0ZXh0" : "some text";
+ XMLObject obj = fac.newXMLObject(Collections.singletonList
+ (new DOMStructure(doc.createTextNode(text))),
+ "object", null, null);
+
+ // create XMLSignature
+ XMLSignature sig = fac.newXMLSignature
+ (si, ki, Collections.singletonList(obj), null, null);
+
+ DOMSignContext dsc = new DOMSignContext(signingKey, doc);
+
+ sig.sign(dsc);
+
+// dumpDocument(doc, new FileWriter("/tmp/foo.xml"));
+
+ DOMValidateContext dvc = new DOMValidateContext
+ (ks, doc.getDocumentElement());
+ XMLSignature sig2 = fac.unmarshalXMLSignature(dvc);
+
+ if (sig.equals(sig2) == false) {
+ throw new Exception
+ ("Unmarshalled signature is not equal to generated signature");
+ }
+ if (sig2.validate(dvc) == false) {
+ throw new Exception("Validation of generated signature failed");
+ }
+ }
+
+ static void test_create_exc_signature() throws Exception {
+ System.out.println("* Generating exc_signature.xml");
+ List<Reference> refs = new ArrayList<Reference>(4);
+
+ // create reference 1
+ refs.add(fac.newReference
+ ("#xpointer(id('to-be-signed'))",
+ fac.newDigestMethod(DigestMethod.SHA1, null),
+ Collections.singletonList
+ (fac.newTransform(CanonicalizationMethod.EXCLUSIVE,
+ (TransformParameterSpec) null)),
+ null, null));
+
+ // create reference 2
+ List<String> prefixList = new ArrayList<String>(2);
+ prefixList.add("bar");
+ prefixList.add("#default");
+ ExcC14NParameterSpec params = new ExcC14NParameterSpec(prefixList);
+ refs.add(fac.newReference
+ ("#xpointer(id('to-be-signed'))",
+ fac.newDigestMethod(DigestMethod.SHA1, null),
+ Collections.singletonList
+ (fac.newTransform(CanonicalizationMethod.EXCLUSIVE, params)),
+ null, null));
+
+ // create reference 3
+ refs.add(fac.newReference
+ ("#xpointer(id('to-be-signed'))",
+ fac.newDigestMethod(DigestMethod.SHA1, null),
+ Collections.singletonList(fac.newTransform
+ (CanonicalizationMethod.EXCLUSIVE_WITH_COMMENTS,
+ (TransformParameterSpec) null)),
+ null, null));
+
+ // create reference 4
+ prefixList = new ArrayList<String>(2);
+ prefixList.add("bar");
+ prefixList.add("#default");
+ params = new ExcC14NParameterSpec(prefixList);
+ refs.add(fac.newReference
+ ("#xpointer(id('to-be-signed'))",
+ fac.newDigestMethod(DigestMethod.SHA1, null),
+ Collections.singletonList(fac.newTransform
+ (CanonicalizationMethod.EXCLUSIVE_WITH_COMMENTS, params)),
+ null, null));
+
+ // create SignedInfo
+ SignedInfo si = fac.newSignedInfo(
+ fac.newCanonicalizationMethod
+ (CanonicalizationMethod.EXCLUSIVE,
+ (C14NMethodParameterSpec) null),
+ fac.newSignatureMethod(SignatureMethod.DSA_SHA1, null), refs);
+
+ // create KeyInfo
+ List<XMLStructure> kits = new ArrayList<XMLStructure>(2);
+ kits.add(kifac.newKeyValue(validatingKey));
+ KeyInfo ki = kifac.newKeyInfo(kits);
+
+ // create Objects
+ Document doc = db.newDocument();
+ Element baz = doc.createElementNS("urn:bar", "bar:Baz");
+ Comment com = doc.createComment(" comment ");
+ baz.appendChild(com);
+ XMLObject obj = fac.newXMLObject(Collections.singletonList
+ (new DOMStructure(baz)), "to-be-signed", null, null);
+
+ // create XMLSignature
+ XMLSignature sig = fac.newXMLSignature
+ (si, ki, Collections.singletonList(obj), null, null);
+
+ Element foo = doc.createElementNS("urn:foo", "Foo");
+ foo.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "urn:foo");
+ foo.setAttributeNS
+ ("http://www.w3.org/2000/xmlns/", "xmlns:bar", "urn:bar");
+ doc.appendChild(foo);
+
+ DOMSignContext dsc = new DOMSignContext(signingKey, foo);
+ dsc.putNamespacePrefix(XMLSignature.XMLNS, "dsig");
+
+ sig.sign(dsc);
+
+// dumpDocument(doc, new FileWriter("/tmp/foo.xml"));
+
+ DOMValidateContext dvc = new DOMValidateContext
+ (new KeySelectors.KeyValueKeySelector(), foo.getLastChild());
+ XMLSignature sig2 = fac.unmarshalXMLSignature(dvc);
+
+ if (sig.equals(sig2) == false) {
+ throw new Exception
+ ("Unmarshalled signature is not equal to generated signature");
+ }
+ if (sig2.validate(dvc) == false) {
+ throw new Exception("Validation of generated signature failed");
+ }
+ System.out.println();
+ }
+
+ static void test_create_sign_spec() throws Exception {
+ System.out.println("* Generating sign-spec.xml");
+ List<Reference> refs = new ArrayList<Reference>(2);
+
+ // create reference 1
+ List<XPathType> types = new ArrayList<XPathType>(3);
+ types.add(new XPathType(" //ToBeSigned ", XPathType.Filter.INTERSECT));
+ types.add(new XPathType(" //NotToBeSigned ",
+ XPathType.Filter.SUBTRACT));
+ types.add(new XPathType(" //ReallyToBeSigned ",
+ XPathType.Filter.UNION));
+ XPathFilter2ParameterSpec xp1 = new XPathFilter2ParameterSpec(types);
+ refs.add(fac.newReference
+ ("", fac.newDigestMethod(DigestMethod.SHA1, null),
+ Collections.singletonList(fac.newTransform(Transform.XPATH2, xp1)),
+ null, null));
+
+ // create reference 2
+ List<Transform> trans2 = new ArrayList<Transform>(2);
+ trans2.add(fac.newTransform(Transform.ENVELOPED,
+ (TransformParameterSpec) null));
+ XPathFilter2ParameterSpec xp2 = new XPathFilter2ParameterSpec
+ (Collections.singletonList
+ (new XPathType(" / ", XPathType.Filter.UNION)));
+ trans2.add(fac.newTransform(Transform.XPATH2, xp2));
+ refs.add(fac.newReference("#signature-value",
+ fac.newDigestMethod(DigestMethod.SHA1, null), trans2, null, null));
+
+ // create SignedInfo
+ SignedInfo si = fac.newSignedInfo(
+ fac.newCanonicalizationMethod
+ (CanonicalizationMethod.INCLUSIVE,
+ (C14NMethodParameterSpec) null),
+ fac.newSignatureMethod(SignatureMethod.DSA_SHA1, null), refs);
+
+ // create KeyInfo
+ List<XMLStructure> kits = new ArrayList<XMLStructure>(2);
+ kits.add(kifac.newKeyValue(validatingKey));
+ List<Object> xds = new ArrayList<Object>(2);
+ xds.add("CN=User");
+ xds.add(signingCert);
+ kits.add(kifac.newX509Data(xds));
+ KeyInfo ki = kifac.newKeyInfo(kits);
+
+ // create XMLSignature
+ XMLSignature sig = fac.newXMLSignature
+ (si, ki, null, null, "signature-value");
+
+ Document doc = db.newDocument();
+ Element tbs1 = doc.createElementNS(null, "ToBeSigned");
+ Comment tbs1Com = doc.createComment(" comment ");
+ Element tbs1Data = doc.createElementNS(null, "Data");
+ Element tbs1ntbs = doc.createElementNS(null, "NotToBeSigned");
+ Element tbs1rtbs = doc.createElementNS(null, "ReallyToBeSigned");
+ Comment tbs1rtbsCom = doc.createComment(" comment ");
+ Element tbs1rtbsData = doc.createElementNS(null, "Data");
+ tbs1rtbs.appendChild(tbs1rtbsCom);
+ tbs1rtbs.appendChild(tbs1rtbsData);
+ tbs1ntbs.appendChild(tbs1rtbs);
+ tbs1.appendChild(tbs1Com);
+ tbs1.appendChild(tbs1Data);
+ tbs1.appendChild(tbs1ntbs);
+
+ Element tbs2 = doc.createElementNS(null, "ToBeSigned");
+ Element tbs2Data = doc.createElementNS(null, "Data");
+ Element tbs2ntbs = doc.createElementNS(null, "NotToBeSigned");
+ Element tbs2ntbsData = doc.createElementNS(null, "Data");
+ tbs2ntbs.appendChild(tbs2ntbsData);
+ tbs2.appendChild(tbs2Data);
+ tbs2.appendChild(tbs2ntbs);
+
+ Element document = doc.createElementNS(null, "Document");
+ document.appendChild(tbs1);
+ document.appendChild(tbs2);
+ doc.appendChild(document);
+
+ DOMSignContext dsc = new DOMSignContext(signingKey, document);
+
+ sig.sign(dsc);
+
+// dumpDocument(doc, new FileWriter("/tmp/foo.xml"));
+
+ DOMValidateContext dvc = new DOMValidateContext
+ (new KeySelectors.KeyValueKeySelector(), document.getLastChild());
+ XMLSignature sig2 = fac.unmarshalXMLSignature(dvc);
+
+ if (sig.equals(sig2) == false) {
+ throw new Exception
+ ("Unmarshalled signature is not equal to generated signature");
+ }
+ if (sig2.validate(dvc) == false) {
+ throw new Exception("Validation of generated signature failed");
+ }
+ System.out.println();
+ }
+
+ private static final String DSA_Y =
+ "070662842167565771936588335128634396171789331656318483584455493822" +
+ "400811200853331373030669235424928346190274044631949560438023934623" +
+ "71310375123430985057160";
+ private static final String DSA_P =
+ "013232376895198612407547930718267435757728527029623408872245156039" +
+ "757713029036368719146452186041204237350521785240337048752071462798" +
+ "273003935646236777459223";
+ private static final String DSA_Q =
+ "0857393771208094202104259627990318636601332086981";
+ private static final String DSA_G =
+ "054216440574364751416096484883257051280474283943804743768346673007" +
+ "661082626139005426812890807137245973106730741193551360857959820973" +
+ "90670890367185141189796";
+ private static final String DSA_X =
+ "0527140396812450214498055937934275626078768840117";
+ private static final String RSA_MOD =
+ "010800185049102889923150759252557522305032794699952150943573164381" +
+ "936603255999071981574575044810461362008102247767482738822150129277" +
+ "490998033971789476107463";
+ private static final String RSA_PRIV =
+ "016116973584421969795445996229612671947635798429212816611707210835" +
+ "915586591340598683996088487065438751488342251960069575392056288063" +
+ "6800379454345804879553";
+ private static final String RSA_PUB = "065537";
+ private static final String RSA_1024_MOD = "098871307553789439961130765" +
+ "909423744508062468450669519128736624058048856940468016843888594585" +
+ "322862378444314635412341974900625010364163960238734457710620107530" +
+ "573945081856371709138380902553309075505688814637544923038853658690" +
+ "857672483016239697038853418682988686871489963827000080098971762923" +
+ "833614557257607521";
+ private static final String RSA_1024_PRIV = "03682574144968491431483287" +
+ "297021581096848810374110568017963075809477047466189822987258068867" +
+ "704855380407747867998863645890602646601140183818953428006646987710" +
+ "237008997971129772408397621801631622129297063463868593083106979716" +
+ "204903524890556839550490384015324575598723478554854070823335021842" +
+ "210112348400928769";
+
+ private static PublicKey getPublicKey(String algo) throws Exception {
+ return getPublicKey(algo, 512);
+ }
+
+ private static PublicKey getPublicKey(String algo, int keysize)
+ throws Exception {
+ KeyFactory kf = KeyFactory.getInstance(algo);
+ KeySpec kspec;
+ if (algo.equalsIgnoreCase("DSA")) {
+ kspec = new DSAPublicKeySpec(new BigInteger(DSA_Y),
+ new BigInteger(DSA_P),
+ new BigInteger(DSA_Q),
+ new BigInteger(DSA_G));
+ } else if (algo.equalsIgnoreCase("RSA")) {
+ if (keysize == 512) {
+ kspec = new RSAPublicKeySpec(new BigInteger(RSA_MOD),
+ new BigInteger(RSA_PUB));
+ } else {
+ kspec = new RSAPublicKeySpec(new BigInteger(RSA_1024_MOD),
+ new BigInteger(RSA_PUB));
+ }
+ } else throw new RuntimeException("Unsupported key algorithm " + algo);
+ return kf.generatePublic(kspec);
+ }
+
+ private static PrivateKey getPrivateKey(String algo) throws Exception {
+ return getPrivateKey(algo, 512);
+ }
+
+ private static PrivateKey getPrivateKey(String algo, int keysize)
+ throws Exception {
+ KeyFactory kf = KeyFactory.getInstance(algo);
+ KeySpec kspec;
+ if (algo.equalsIgnoreCase("DSA")) {
+ kspec = new DSAPrivateKeySpec
+ (new BigInteger(DSA_X), new BigInteger(DSA_P),
+ new BigInteger(DSA_Q), new BigInteger(DSA_G));
+ } else if (algo.equalsIgnoreCase("RSA")) {
+ if (keysize == 512) {
+ kspec = new RSAPrivateKeySpec
+ (new BigInteger(RSA_MOD), new BigInteger(RSA_PRIV));
+ } else {
+ kspec = new RSAPrivateKeySpec(new BigInteger(RSA_1024_MOD),
+ new BigInteger(RSA_1024_PRIV));
+ }
+ } else throw new RuntimeException("Unsupported key algorithm " + algo);
+ return kf.generatePrivate(kspec);
+ }
+
+ private static SecretKey getSecretKey(final byte[] secret) {
+ return new SecretKey() {
+ public String getFormat() { return "RAW"; }
+ public byte[] getEncoded() { return secret; }
+ public String getAlgorithm(){ return "SECRET"; }
+ };
+ }
+
+ /**
+ * This URIDereferencer returns locally cached copies of http content to
+ * avoid test failures due to network glitches, etc.
+ */
+ private static class HttpURIDereferencer implements URIDereferencer {
+ private URIDereferencer defaultUd;
+
+ HttpURIDereferencer() {
+ defaultUd = XMLSignatureFactory.getInstance().getURIDereferencer();
+ }
+
+ public Data dereference(final URIReference ref, XMLCryptoContext ctx)
+ throws URIReferenceException {
+ String uri = ref.getURI();
+ if (uri.equals(STYLESHEET) || uri.equals(STYLESHEET_B64)) {
+ try {
+ FileInputStream fis = new FileInputStream(new File
+ (DATA_DIR, uri.substring(uri.lastIndexOf('/'))));
+ return new OctetStreamData(fis,ref.getURI(),ref.getType());
+ } catch (Exception e) { throw new URIReferenceException(e); }
+ }
+
+ // fallback on builtin deref
+ return defaultUd.dereference(ref, ctx);
+ }
+ }
+}
diff --git a/test/javax/xml/crypto/dsig/KeySelectors.java b/test/javax/xml/crypto/dsig/KeySelectors.java
new file mode 100644
index 0000000..b0a72a6
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/KeySelectors.java
@@ -0,0 +1,412 @@
+/*
+ * Copyright 2005-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import java.io.*;
+import java.security.*;
+import java.security.cert.*;
+import java.util.*;
+import javax.crypto.SecretKey;
+import javax.xml.crypto.*;
+import javax.xml.crypto.dsig.*;
+import javax.xml.crypto.dom.*;
+import javax.xml.crypto.dsig.keyinfo.*;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.DocumentBuilder;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.Element;
+import org.w3c.dom.traversal.*;
+import sun.security.util.DerValue;
+import sun.security.x509.X500Name;
+
+/**
+ * This is a class which supplies several KeySelector implementations
+ */
+class KeySelectors {
+
+ /**
+ * KeySelector which would always return the secret key specified in its
+ * constructor.
+ */
+ static class SecretKeySelector extends KeySelector {
+ private SecretKey key;
+ SecretKeySelector(byte[] bytes) {
+ key = wrapBytes(bytes);
+ }
+ SecretKeySelector(SecretKey key) {
+ this.key = key;
+ }
+
+ public KeySelectorResult select(KeyInfo ki,
+ KeySelector.Purpose purpose,
+ AlgorithmMethod method,
+ XMLCryptoContext context)
+ throws KeySelectorException {
+ return new SimpleKSResult(key);
+ }
+
+ private SecretKey wrapBytes(final byte[] bytes) {
+ return new SecretKey() {
+ public String getFormat() {
+ return "RAW";
+ }
+
+ public String getAlgorithm() {
+ return "Secret key";
+ }
+
+ public byte[] getEncoded() {
+ return (byte[]) bytes.clone();
+ }
+ };
+ }
+ }
+
+ /**
+ * KeySelector which would retrieve the X509Certificate out of the
+ * KeyInfo element and return the public key.
+ * NOTE: If there is an X509CRL in the KeyInfo element, then revoked
+ * certificate will be ignored.
+ */
+ static class RawX509KeySelector extends KeySelector {
+
+ public KeySelectorResult select(KeyInfo keyInfo,
+ KeySelector.Purpose purpose,
+ AlgorithmMethod method,
+ XMLCryptoContext context)
+ throws KeySelectorException {
+ if (keyInfo == null) {
+ throw new KeySelectorException("Null KeyInfo object!");
+ }
+ // search for X509Data in keyinfo
+ Iterator iter = keyInfo.getContent().iterator();
+ while (iter.hasNext()) {
+ XMLStructure kiType = (XMLStructure) iter.next();
+ if (kiType instanceof X509Data) {
+ X509Data xd = (X509Data) kiType;
+ Object[] entries = xd.getContent().toArray();
+ X509CRL crl = null;
+ // Looking for CRL before finding certificates
+ for (int i = 0; (i<entries.length&&crl != null); i++) {
+ if (entries[i] instanceof X509CRL) {
+ crl = (X509CRL) entries[i];
+ }
+ }
+ Iterator xi = xd.getContent().iterator();
+ boolean hasCRL = false;
+ while (xi.hasNext()) {
+ Object o = xi.next();
+ // skip non-X509Certificate entries
+ if (o instanceof X509Certificate) {
+ if ((purpose != KeySelector.Purpose.VERIFY) &&
+ (crl != null) &&
+ crl.isRevoked((X509Certificate)o)) {
+ continue;
+ } else {
+ return new SimpleKSResult
+ (((X509Certificate)o).getPublicKey());
+ }
+ }
+ }
+ }
+ }
+ throw new KeySelectorException("No X509Certificate found!");
+ }
+ }
+
+ /**
+ * KeySelector which would retrieve the public key out of the
+ * KeyValue element and return it.
+ * NOTE: If the key algorithm doesn't match signature algorithm,
+ * then the public key will be ignored.
+ */
+ static class KeyValueKeySelector extends KeySelector {
+ public KeySelectorResult select(KeyInfo keyInfo,
+ KeySelector.Purpose purpose,
+ AlgorithmMethod method,
+ XMLCryptoContext context)
+ throws KeySelectorException {
+ if (keyInfo == null) {
+ throw new KeySelectorException("Null KeyInfo object!");
+ }
+ SignatureMethod sm = (SignatureMethod) method;
+ List list = keyInfo.getContent();
+
+ for (int i = 0; i < list.size(); i++) {
+ XMLStructure xmlStructure = (XMLStructure) list.get(i);
+ if (xmlStructure instanceof KeyValue) {
+ PublicKey pk = null;
+ try {
+ pk = ((KeyValue)xmlStructure).getPublicKey();
+ } catch (KeyException ke) {
+ throw new KeySelectorException(ke);
+ }
+ // make sure algorithm is compatible with method
+ if (algEquals(sm.getAlgorithm(), pk.getAlgorithm())) {
+ return new SimpleKSResult(pk);
+ }
+ }
+ }
+ throw new KeySelectorException("No KeyValue element found!");
+ }
+
+ //@@@FIXME: this should also work for key types other than DSA/RSA
+ static boolean algEquals(String algURI, String algName) {
+ if (algName.equalsIgnoreCase("DSA") &&
+ algURI.equals(SignatureMethod.DSA_SHA1)) {
+ return true;
+ } else if (algName.equalsIgnoreCase("RSA") &&
+ (algURI.equals(SignatureMethod.RSA_SHA1) ||
+ algURI.equals
+ ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256") ||
+ algURI.equals
+ ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha384") ||
+ algURI.equals
+ ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"))) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ /**
+ * KeySelector which would perform special lookup as documented
+ * by the ie/baltimore/merlin-examples testcases and return the
+ * matching public key.
+ */
+ static class CollectionKeySelector extends KeySelector {
+ private CertificateFactory certFac;
+ private File certDir;
+ private Vector certs;
+ private static final int MATCH_SUBJECT = 0;
+ private static final int MATCH_ISSUER = 1;
+ private static final int MATCH_SERIAL = 2;
+ private static final int MATCH_SUBJECT_KEY_ID = 3;
+ private static final int MATCH_CERTIFICATE = 4;
+
+ CollectionKeySelector(File dir) {
+ certDir = dir;
+ try {
+ certFac = CertificateFactory.getInstance("X509");
+ } catch (CertificateException ex) {
+ // not going to happen
+ }
+ certs = new Vector();
+ File[] files = new File(certDir, "certs").listFiles();
+ for (int i = 0; i < files.length; i++) {
+ try {
+ certs.add(certFac.generateCertificate
+ (new FileInputStream(files[i])));
+ } catch (Exception ex) { }
+ }
+ }
+
+ Vector match(int matchType, Object value, Vector pool) {
+ Vector matchResult = new Vector();
+ for (int j=0; j < pool.size(); j++) {
+ X509Certificate c = (X509Certificate) pool.get(j);
+ switch (matchType) {
+ case MATCH_SUBJECT:
+ try {
+ if (c.getSubjectDN().equals(new X500Name((String)value))) {
+ matchResult.add(c);
+ }
+ } catch (IOException ioe) { }
+ break;
+ case MATCH_ISSUER:
+ try {
+ if (c.getIssuerDN().equals(new X500Name((String)value))) {
+ matchResult.add(c);
+ }
+ } catch (IOException ioe) { }
+ break;
+ case MATCH_SERIAL:
+ if (c.getSerialNumber().equals(value)) {
+ matchResult.add(c);
+ }
+
+ break;
+ case MATCH_SUBJECT_KEY_ID:
+ byte[] extension = c.getExtensionValue("2.5.29.14");
+ if (extension != null) {
+ try {
+ DerValue derValue = new DerValue(extension);
+ DerValue derValue2 = new DerValue(derValue.getOctetString());
+ byte[] extVal = derValue2.getOctetString();
+
+ if (Arrays.equals(extVal, (byte[]) value)) {
+ matchResult.add(c);
+ }
+ } catch (IOException ex) { }
+ }
+ break;
+ case MATCH_CERTIFICATE:
+ if (c.equals(value)) {
+ matchResult.add(c);
+ }
+ break;
+ }
+ }
+ return matchResult;
+ }
+
+ public KeySelectorResult select(KeyInfo keyInfo,
+ KeySelector.Purpose purpose,
+ AlgorithmMethod method,
+ XMLCryptoContext context)
+ throws KeySelectorException {
+ if (keyInfo == null) {
+ throw new KeySelectorException("Null KeyInfo object!");
+ }
+ Iterator iter = keyInfo.getContent().iterator();
+ while (iter.hasNext()) {
+ XMLStructure xmlStructure = (XMLStructure) iter.next();
+ try {
+ if (xmlStructure instanceof KeyName) {
+ String name = ((KeyName)xmlStructure).getName();
+ PublicKey pk = null;
+ try {
+ // Lookup the public key using the key name 'Xxx',
+ // i.e. the public key is in "certs/xxx.crt".
+ File certFile = new File(new File(certDir, "certs"),
+ name.toLowerCase()+".crt");
+ X509Certificate cert = (X509Certificate)
+ certFac.generateCertificate
+ (new FileInputStream(certFile));
+ pk = cert.getPublicKey();
+ } catch (FileNotFoundException e) {
+ // assume KeyName contains subject DN and search
+ // collection of certs for match
+ Vector result =
+ match(MATCH_SUBJECT, name, certs);
+ int numOfMatches = (result==null? 0:result.size());
+ if (numOfMatches != 1) {
+ throw new KeySelectorException
+ ((numOfMatches==0?"No":"More than one") +
+ " match found");
+ }
+ pk =((X509Certificate)result.get(0)).getPublicKey();
+ }
+ return new SimpleKSResult(pk);
+ } else if (xmlStructure instanceof RetrievalMethod) {
+ // Lookup the public key using the retrievel method.
+ // NOTE: only X509Certificate type is supported.
+ RetrievalMethod rm = (RetrievalMethod) xmlStructure;
+ String type = rm.getType();
+ if (type.equals(X509Data.RAW_X509_CERTIFICATE_TYPE)) {
+ String uri = rm.getURI();
+ X509Certificate cert = (X509Certificate)
+ certFac.generateCertificate
+ (new FileInputStream(new File(certDir, uri)));
+ return new SimpleKSResult(cert.getPublicKey());
+ } else {
+ throw new KeySelectorException
+ ("Unsupported RetrievalMethod type");
+ }
+ } else if (xmlStructure instanceof X509Data) {
+ List content = ((X509Data)xmlStructure).getContent();
+ int size = content.size();
+ Vector result = null;
+ // Lookup the public key using the information
+ // specified in X509Data element, i.e. searching
+ // over the collection of certificate files under
+ // "certs" subdirectory and return those match.
+ for (int k = 0; k<size; k++) {
+ Object obj = content.get(k);
+ if (obj instanceof String) {
+ result = match(MATCH_SUBJECT, obj, certs);
+ } else if (obj instanceof byte[]) {
+ result = match(MATCH_SUBJECT_KEY_ID, obj,
+ certs);
+ } else if (obj instanceof X509Certificate) {
+ result = match(MATCH_CERTIFICATE, obj, certs);
+ } else if (obj instanceof X509IssuerSerial) {
+ X509IssuerSerial is = (X509IssuerSerial) obj;
+ result = match(MATCH_SERIAL,
+ is.getSerialNumber(), certs);
+ result = match(MATCH_ISSUER,
+ is.getIssuerName(), result);
+ } else {
+ throw new KeySelectorException("Unsupported X509Data: " + obj);
+ }
+ }
+ int numOfMatches = (result==null? 0:result.size());
+ if (numOfMatches != 1) {
+ throw new KeySelectorException
+ ((numOfMatches==0?"No":"More than one") +
+ " match found");
+ }
+ return new SimpleKSResult(((X509Certificate)
+ result.get(0)).getPublicKey());
+ }
+ } catch (Exception ex) {
+ throw new KeySelectorException(ex);
+ }
+ }
+ throw new KeySelectorException("No matching key found!");
+ }
+ }
+
+ static class ByteUtil {
+
+ private static String mapping = "0123456789ABCDEF";
+ private static int numBytesPerRow = 6;
+
+ private static String getHex(byte value) {
+ int low = value & 0x0f;
+ int high = ((value >> 4) & 0x0f);
+ char[] res = new char[2];
+ res[0] = mapping.charAt(high);
+ res[1] = mapping.charAt(low);
+ return new String(res);
+ }
+
+ static String dumpArray(byte[] in) {
+ int numDumped = 0;
+ StringBuffer buf = new StringBuffer(512);
+ buf.append("{");
+ for (int i=0;i<(in.length/numBytesPerRow); i++) {
+ for (int j=0; j<(numBytesPerRow); j++) {
+ buf.append("(byte)0x" + getHex(in[i*numBytesPerRow+j]) +
+ ", ");
+ }
+ numDumped += numBytesPerRow;
+ }
+ while (numDumped < in.length) {
+ buf.append("(byte)0x" + getHex(in[numDumped]) + " ");
+ numDumped += 1;
+ }
+ buf.append("}");
+ return buf.toString();
+ }
+ }
+}
+
+class SimpleKSResult implements KeySelectorResult {
+ private final Key key;
+
+ SimpleKSResult(Key key) { this.key = key; }
+
+ public Key getKey() { return key; }
+}
diff --git a/test/javax/xml/crypto/dsig/SecurityManager/XMLDSigWithSecMgr.java b/test/javax/xml/crypto/dsig/SecurityManager/XMLDSigWithSecMgr.java
new file mode 100644
index 0000000..e3e9a39
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/SecurityManager/XMLDSigWithSecMgr.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6436919 6460930
+ * @summary check that XML Signatures can be generated and validated with
+ * SecurityManager enabled and default policy
+ * @author Sean Mullan
+ */
+import java.io.*;
+import java.net.*;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.Policy;
+import java.security.URIParameter;
+import java.util.ArrayList;
+import java.util.Collections;
+import javax.xml.crypto.dsig.*;
+import javax.xml.crypto.dsig.dom.DOMSignContext;
+import javax.xml.crypto.dsig.dom.DOMValidateContext;
+import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
+import javax.xml.crypto.dsig.spec.TransformParameterSpec;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class XMLDSigWithSecMgr implements Runnable {
+
+ private XMLSignatureFactory fac;
+ private DigestMethod sha1;
+ private CanonicalizationMethod withoutComments;
+ private DocumentBuilder db;
+
+ private ServerSocket ss;
+
+ private void setup() throws Exception {
+ ss = new ServerSocket(0);
+ Thread thr = new Thread(this);
+ thr.start();
+
+ fac = XMLSignatureFactory.getInstance();
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ db = dbf.newDocumentBuilder();
+ sha1 = fac.newDigestMethod(DigestMethod.SHA1, null);
+ withoutComments = fac.newCanonicalizationMethod
+ (CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec)null);
+ }
+
+ public void run() {
+ try {
+
+ for (int i=0; i<2; i++) {
+ Socket s = ss.accept();
+ s.setTcpNoDelay(true);
+
+ PrintStream out = new PrintStream(
+ new BufferedOutputStream(
+ s.getOutputStream() ));
+
+ out.print("HTTP/1.1 200 OK\r\n");
+ out.print("Content-Length: 11\r\n");
+ out.print("Content-Type: text/plain\r\n");
+ out.print("\r\n");
+ out.print("l;ajfdjafd\n");
+ out.flush();
+
+ // don't close the connection immediately as otherwise
+ // the http headers may not have been received and the
+ // http client will re-connect.
+ Thread.currentThread().sleep(2000);
+
+ s.close();
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ XMLDSigWithSecMgr() throws Exception {
+ setup();
+ Document doc = db.newDocument();
+ Element envelope = doc.createElementNS
+ ("http://example.org/envelope", "Envelope");
+ envelope.setAttributeNS("http://www.w3.org/2000/xmlns/",
+ "xmlns", "http://example.org/envelope");
+ doc.appendChild(envelope);
+
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
+ KeyPair kp = kpg.genKeyPair();
+
+ // the policy only grants this test SocketPermission to accept, resolve
+ // and connect to localhost so that it can dereference 2nd reference
+ URI policyURI =
+ new File(System.getProperty("test.src", "."), "policy").toURI();
+ Policy.setPolicy
+ (Policy.getInstance("JavaPolicy", new URIParameter(policyURI)));
+ System.setSecurityManager(new SecurityManager());
+
+ try {
+ // generate a signature with SecurityManager enabled
+ ArrayList refs = new ArrayList();
+ refs.add(fac.newReference
+ ("", sha1,
+ Collections.singletonList
+ (fac.newTransform(Transform.ENVELOPED,
+ (TransformParameterSpec) null)), null, null));
+ refs.add(fac.newReference("http://localhost:" + ss.getLocalPort()
+ + "/anything.txt", sha1));
+ SignedInfo si = fac.newSignedInfo(withoutComments,
+ fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null), refs);
+ XMLSignature sig = fac.newXMLSignature(si, null);
+ DOMSignContext dsc = new DOMSignContext(kp.getPrivate(), envelope);
+ sig.sign(dsc);
+
+ // validate a signature with SecurityManager enabled
+ DOMValidateContext dvc = new DOMValidateContext
+ (kp.getPublic(), envelope.getFirstChild());
+ sig = fac.unmarshalXMLSignature(dvc);
+ if (!sig.validate(dvc)) {
+ throw new Exception
+ ("XMLDSigWithSecMgr signature validation FAILED");
+ }
+ } catch (SecurityException se) {
+ throw new Exception("XMLDSigWithSecMgr FAILED", se);
+ }
+ ss.close();
+ }
+
+ public static void main(String[] args) throws Exception {
+ new XMLDSigWithSecMgr();
+ }
+}
diff --git a/test/javax/xml/crypto/dsig/SecurityManager/policy b/test/javax/xml/crypto/dsig/SecurityManager/policy
new file mode 100644
index 0000000..52565bf
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/SecurityManager/policy
@@ -0,0 +1,3 @@
+grant {
+ permission java.net.SocketPermission "localhost", "accept,connect,resolve";
+};
diff --git a/test/javax/xml/crypto/dsig/SignatureValidator.java b/test/javax/xml/crypto/dsig/SignatureValidator.java
new file mode 100644
index 0000000..74e02e6
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/SignatureValidator.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2005-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import java.io.*;
+import java.util.*;
+import java.security.MessageDigest;
+import javax.xml.crypto.*;
+import javax.xml.crypto.dsig.*;
+import javax.xml.crypto.dsig.dom.DOMValidateContext;
+import javax.xml.crypto.dom.*;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.DocumentBuilder;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Element;
+
+/**
+ * This is a class which performs xml signature validation upon request
+ */
+class SignatureValidator {
+
+ private File dir;
+
+ SignatureValidator(File base) {
+ dir = base;
+ }
+
+ boolean validate(String fn, KeySelector ks, boolean cache)
+ throws Exception {
+ return validate(fn, ks, null, cache);
+ }
+
+ boolean validate(String fn, KeySelector ks, URIDereferencer ud,
+ boolean cache) throws Exception {
+
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ dbf.setValidating(false);
+ Document doc = dbf.newDocumentBuilder().parse(new File(dir, fn));
+ NodeList nl =
+ doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
+ if (nl.getLength() == 0) {
+ throw new Exception("Couldn't find signature Element");
+ }
+ Element sigElement = (Element) nl.item(0);
+ DOMValidateContext vc = new DOMValidateContext(ks, sigElement);
+ vc.setBaseURI(dir.toURI().toString());
+ if (cache) {
+ vc.setProperty("javax.xml.crypto.dsig.cacheReference", Boolean.TRUE);
+ }
+ XMLSignatureFactory factory = XMLSignatureFactory.getInstance();
+ XMLSignature signature = factory.unmarshalXMLSignature(vc);
+ if (ud != null) {
+ vc.setURIDereferencer(ud);
+ }
+ boolean coreValidity = signature.validate(vc);
+
+ // Check reference cache
+ if (cache) {
+ Iterator i = signature.getSignedInfo().getReferences().iterator();
+ for (int j=0; i.hasNext(); j++) {
+ Reference ref = (Reference) i.next();
+ if (!digestInputEqual(ref)) {
+ throw new Exception
+ ("cached data for Reference[" + j + "] is not correct");
+ }
+ // check that dereferenced data does not contain comment nodes
+ if (ref.getURI() == "") {
+ System.out.println("checking deref data");
+ NodeSetData data = (NodeSetData) ref.getDereferencedData();
+ Iterator ni = data.iterator();
+ while (ni.hasNext()) {
+ Node n = (Node) ni.next();
+ if (n.getNodeType() == Node.COMMENT_NODE) {
+ throw new Exception("dereferenced data for " +
+ " Reference[" + j + " contains comment node");
+ }
+ }
+ }
+ }
+ }
+ return coreValidity;
+ }
+
+ private boolean digestInputEqual(Reference ref) throws Exception {
+ MessageDigest md = MessageDigest.getInstance("SHA1");
+ InputStream is = ref.getDigestInputStream();
+ int nbytes;
+ byte[] buf = new byte[256];
+ while ((nbytes = is.read(buf, 0, buf.length)) != -1) {
+ md.update(buf, 0, nbytes);
+ }
+ return Arrays.equals(md.digest(), ref.getDigestValue());
+ }
+}
diff --git a/test/javax/xml/crypto/dsig/ValidationTests.java b/test/javax/xml/crypto/dsig/ValidationTests.java
new file mode 100644
index 0000000..0934de7
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/ValidationTests.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2005-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 4635230
+ * @bug 6365103
+ * @bug 6366054
+ * @summary Basic unit tests for validating XML Signatures with JSR 105
+ * @compile -XDignore.symbol.file KeySelectors.java SignatureValidator.java
+ * X509KeySelector.java ValidationTests.java
+ * @run main ValidationTests
+ * @author Sean Mullan
+ */
+import java.io.File;
+import java.io.FileInputStream;
+import java.security.*;
+import javax.xml.crypto.Data;
+import javax.xml.crypto.KeySelector;
+import javax.xml.crypto.OctetStreamData;
+import javax.xml.crypto.URIDereferencer;
+import javax.xml.crypto.URIReference;
+import javax.xml.crypto.URIReferenceException;
+import javax.xml.crypto.XMLCryptoContext;
+import javax.xml.crypto.dsig.XMLSignatureFactory;
+
+/**
+ * This is a testcase to validate all "merlin-xmldsig-twenty-three"
+ * testcases from Baltimore
+ */
+public class ValidationTests {
+
+ private static SignatureValidator validator;
+ private final static String DIR = System.getProperty("test.src", ".");
+ private final static String DATA_DIR =
+ DIR + System.getProperty("file.separator") + "data";
+ private final static String KEYSTORE =
+ DATA_DIR + System.getProperty("file.separator") + "certs" +
+ System.getProperty("file.separator") + "xmldsig.jks";
+ private final static String STYLESHEET =
+ "http://www.w3.org/TR/xml-stylesheet";
+ private final static String STYLESHEET_B64 =
+ "http://www.w3.org/Signature/2002/04/xml-stylesheet.b64";
+
+ private final static String[] FILES = {
+ "signature-enveloped-dsa.xml",
+ "signature-enveloping-b64-dsa.xml",
+ "signature-enveloping-dsa.xml",
+ "signature-enveloping-rsa.xml",
+ "signature-enveloping-hmac-sha1.xml",
+ "signature-enveloping-hmac-sha1-40.xml",
+ "signature-external-dsa.xml",
+ "signature-external-b64-dsa.xml",
+ "signature-retrievalmethod-rawx509crt.xml",
+ "signature-keyname.xml",
+ "signature-x509-crt-crl.xml",
+ "signature-x509-crt.xml",
+ "signature-x509-is.xml",
+ "signature-x509-ski.xml",
+ "signature-x509-sn.xml",
+// "signature.xml",
+ "exc-signature.xml",
+ "sign-spec.xml"
+ };
+
+ static KeySelector skks;
+ static {
+ try {
+ skks =
+ new KeySelectors.SecretKeySelector("secret".getBytes("ASCII"));
+ } catch (Exception e) {
+ //should not occur
+ }
+ }
+ private final static KeySelector SKKS = skks;
+ private final static KeySelector KVKS =
+ new KeySelectors.KeyValueKeySelector();
+ private final static KeySelector CKS =
+ new KeySelectors.CollectionKeySelector(new File(DATA_DIR));
+ private final static KeySelector RXKS =
+ new KeySelectors.RawX509KeySelector();
+ private final static KeySelector XKS = null;
+ private final static KeySelector[] KEY_SELECTORS = {
+ KVKS,
+ KVKS,
+ KVKS,
+ KVKS,
+ SKKS,
+ SKKS,
+ KVKS,
+ KVKS,
+ CKS,
+ CKS,
+ RXKS,
+ RXKS,
+ CKS,
+ CKS,
+ CKS,
+// XKS,
+ KVKS,
+ RXKS
+ };
+ private static URIDereferencer httpUd = null;
+
+ public static void main(String args[]) throws Exception {
+ httpUd = new HttpURIDereferencer();
+
+ validator = new SignatureValidator(new File(DATA_DIR));
+
+ boolean atLeastOneFailed = false;
+ for (int i=0; i < FILES.length; i++) {
+ System.out.println("Validating " + FILES[i]);
+ if (test_signature(FILES[i], KEY_SELECTORS[i])) {
+ System.out.println("PASSED");
+ } else {
+ System.out.println("FAILED");
+ atLeastOneFailed = true;
+ }
+ }
+ // test with reference caching enabled
+ System.out.println("Validating sign-spec.xml with caching enabled");
+ if (test_signature("sign-spec.xml", RXKS, true)) {
+ System.out.println("PASSED");
+ } else {
+ System.out.println("FAILED");
+ atLeastOneFailed = true;
+ }
+
+ if (atLeastOneFailed) {
+ throw new Exception
+ ("At least one signature did not validate as expected");
+ }
+ }
+
+ public static boolean test_signature(String file, KeySelector ks)
+ throws Exception {
+ return test_signature(file, ks, false);
+ }
+
+ public static boolean test_signature(String file, KeySelector ks,
+ boolean cache) throws Exception {
+ if (ks == null) {
+ KeyStore keystore = KeyStore.getInstance("JKS");
+ keystore.load
+ (new FileInputStream(KEYSTORE), "changeit".toCharArray());
+ ks = new X509KeySelector(keystore, false);
+ }
+ return validator.validate(file, ks, httpUd, cache);
+ }
+
+ /**
+ * This URIDereferencer returns locally cached copies of http content to
+ * avoid test failures due to network glitches, etc.
+ */
+ private static class HttpURIDereferencer implements URIDereferencer {
+ private URIDereferencer defaultUd;
+
+ HttpURIDereferencer() {
+ defaultUd = XMLSignatureFactory.getInstance().getURIDereferencer();
+ }
+
+ public Data dereference(final URIReference ref, XMLCryptoContext ctx)
+ throws URIReferenceException {
+ String uri = ref.getURI();
+ if (uri.equals(STYLESHEET) || uri.equals(STYLESHEET_B64)) {
+ try {
+ FileInputStream fis = new FileInputStream(new File
+ (DATA_DIR, uri.substring(uri.lastIndexOf('/'))));
+ return new OctetStreamData(fis,ref.getURI(),ref.getType());
+ } catch (Exception e) { throw new URIReferenceException(e); }
+ }
+
+ // fallback on builtin deref
+ return defaultUd.dereference(ref, ctx);
+ }
+ }
+}
diff --git a/test/javax/xml/crypto/dsig/X509KeySelector.java b/test/javax/xml/crypto/dsig/X509KeySelector.java
new file mode 100644
index 0000000..40df3e4
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/X509KeySelector.java
@@ -0,0 +1,372 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.security.Key;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.PublicKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.cert.CertSelector;
+import java.security.cert.X509Certificate;
+import java.security.cert.X509CertSelector;
+import java.util.*;
+import javax.security.auth.x500.X500Principal;
+import javax.xml.crypto.*;
+import javax.xml.crypto.dsig.*;
+import javax.xml.crypto.dom.*;
+import javax.xml.crypto.dsig.keyinfo.*;
+
+import org.jcp.xml.dsig.internal.dom.DOMRetrievalMethod;
+
+/**
+ * A <code>KeySelector</code> that returns {@link PublicKey}s. If the
+ * selector is created as trusted, it only returns public keys of trusted
+ * {@link X509Certificate}s stored in a {@link KeyStore}. Otherwise, it
+ * returns trusted or untrusted public keys (it doesn't care as long
+ * as it finds one).
+ *
+ * <p>This <code>KeySelector</code> uses the specified <code>KeyStore</code>
+ * to find a trusted <code>X509Certificate</code> that matches information
+ * specified in the {@link KeyInfo} passed to the {@link #select} method.
+ * The public key from the first match is returned. If no match,
+ * <code>null</code> is returned. See the <code>select</code> method for more
+ * information.
+ *
+ * @author Sean Mullan
+ */
+class X509KeySelector extends KeySelector {
+
+ private KeyStore ks;
+ private boolean trusted = true;
+
+ /**
+ * Creates a trusted <code>X509KeySelector</code>.
+ *
+ * @param keyStore the keystore
+ * @throws KeyStoreException if the keystore has not been initialized
+ * @throws NullPointerException if <code>keyStore</code> is
+ * <code>null</code>
+ */
+ X509KeySelector(KeyStore keyStore) throws KeyStoreException {
+ this(keyStore, true);
+ }
+
+ X509KeySelector(KeyStore keyStore, boolean trusted)
+ throws KeyStoreException {
+ if (keyStore == null) {
+ throw new NullPointerException("keyStore is null");
+ }
+ this.trusted = trusted;
+ this.ks = keyStore;
+ // test to see if KeyStore has been initialized
+ this.ks.size();
+ }
+
+ /**
+ * Finds a key from the keystore satisfying the specified constraints.
+ *
+ * <p>This method compares data contained in {@link KeyInfo} entries
+ * with information stored in the <code>KeyStore</code>. The implementation
+ * iterates over the KeyInfo types and returns the first {@link PublicKey}
+ * of an X509Certificate in the keystore that is compatible with the
+ * specified AlgorithmMethod according to the following rules for each
+ * keyinfo type:
+ *
+ * X509Data X509Certificate: if it contains a <code>KeyUsage</code>
+ * extension that asserts the <code>digitalSignature</code> bit and
+ * matches an <code>X509Certificate</code> in the <code>KeyStore</code>.
+ * X509Data X509IssuerSerial: if the serial number and issuer DN match an
+ * <code>X509Certificate</code> in the <code>KeyStore</code>.
+ * X509Data X509SubjectName: if the subject DN matches an
+ * <code>X509Certificate</code> in the <code>KeyStore</code>.
+ * X509Data X509SKI: if the subject key identifier matches an
+ * <code>X509Certificate</code> in the <code>KeyStore</code>.
+ * KeyName: if the keyname matches an alias in the <code>KeyStore</code>.
+ * RetrievalMethod: supports rawX509Certificate and X509Data types. If
+ * rawX509Certificate type, it must match an <code>X509Certificate</code>
+ * in the <code>KeyStore</code>.
+ *
+ * @param keyInfo a <code>KeyInfo</code> (may be <code>null</code>)
+ * @param purpose the key's purpose
+ * @param method the algorithm method that this key is to be used for.
+ * Only keys that are compatible with the algorithm and meet the
+ * constraints of the specified algorithm should be returned.
+ * @param an <code>XMLCryptoContext</code> that may contain additional
+ * useful information for finding an appropriate key
+ * @return a key selector result
+ * @throws KeySelectorException if an exceptional condition occurs while
+ * attempting to find a key. Note that an inability to find a key is not
+ * considered an exception (<code>null</code> should be
+ * returned in that case). However, an error condition (ex: network
+ * communications failure) that prevented the <code>KeySelector</code>
+ * from finding a potential key should be considered an exception.
+ * @throws ClassCastException if the data type of <code>method</code>
+ * is not supported by this key selector
+ */
+ public KeySelectorResult select(KeyInfo keyInfo,
+ KeySelector.Purpose purpose, AlgorithmMethod method,
+ XMLCryptoContext context) throws KeySelectorException {
+
+ SignatureMethod sm = (SignatureMethod) method;
+
+ try {
+ // return null if keyinfo is null or keystore is empty
+ if (keyInfo == null || ks.size() == 0) {
+ return new SimpleKeySelectorResult(null);
+ }
+
+ // Iterate through KeyInfo types
+ Iterator i = keyInfo.getContent().iterator();
+ while (i.hasNext()) {
+ XMLStructure kiType = (XMLStructure) i.next();
+ // check X509Data
+ if (kiType instanceof X509Data) {
+ X509Data xd = (X509Data) kiType;
+ KeySelectorResult ksr = x509DataSelect(xd, sm);
+ if (ksr != null) {
+ return ksr;
+ }
+ // check KeyName
+ } else if (kiType instanceof KeyName) {
+ KeyName kn = (KeyName) kiType;
+ Certificate cert = ks.getCertificate(kn.getName());
+ if (cert != null && algEquals(sm.getAlgorithm(),
+ cert.getPublicKey().getAlgorithm())) {
+ return new SimpleKeySelectorResult(cert.getPublicKey());
+ }
+ // check RetrievalMethod
+ } else if (kiType instanceof RetrievalMethod) {
+ RetrievalMethod rm = (RetrievalMethod) kiType;
+ try {
+ KeySelectorResult ksr = null;
+ if (rm.getType().equals
+ (X509Data.RAW_X509_CERTIFICATE_TYPE)) {
+ OctetStreamData data = (OctetStreamData)
+ rm.dereference(context);
+ CertificateFactory cf =
+ CertificateFactory.getInstance("X.509");
+ X509Certificate cert = (X509Certificate)
+ cf.generateCertificate(data.getOctetStream());
+ ksr = certSelect(cert, sm);
+ } else if (rm.getType().equals(X509Data.TYPE)) {
+ X509Data xd = (X509Data) ((DOMRetrievalMethod) rm).
+ dereferenceAsXMLStructure(context);
+ ksr = x509DataSelect(xd, sm);
+ } else {
+ // skip; keyinfo type is not supported
+ continue;
+ }
+ if (ksr != null) {
+ return ksr;
+ }
+ } catch (Exception e) {
+ throw new KeySelectorException(e);
+ }
+ }
+ }
+ } catch (KeyStoreException kse) {
+ // throw exception if keystore is uninitialized
+ throw new KeySelectorException(kse);
+ }
+
+ // return null since no match could be found
+ return new SimpleKeySelectorResult(null);
+ }
+
+ /**
+ * Searches the specified keystore for a certificate that matches the
+ * criteria specified in the CertSelector.
+ *
+ * @return a KeySelectorResult containing the cert's public key if there
+ * is a match; otherwise null
+ */
+ private KeySelectorResult keyStoreSelect(CertSelector cs)
+ throws KeyStoreException {
+ Enumeration aliases = ks.aliases();
+ while (aliases.hasMoreElements()) {
+ String alias = (String) aliases.nextElement();
+ Certificate cert = ks.getCertificate(alias);
+ if (cert != null && cs.match(cert)) {
+ return new SimpleKeySelectorResult(cert.getPublicKey());
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Searches the specified keystore for a certificate that matches the
+ * specified X509Certificate and contains a public key that is compatible
+ * with the specified SignatureMethod.
+ *
+ * @return a KeySelectorResult containing the cert's public key if there
+ * is a match; otherwise null
+ */
+ private KeySelectorResult certSelect(X509Certificate xcert,
+ SignatureMethod sm) throws KeyStoreException {
+ // skip non-signer certs
+ boolean[] keyUsage = xcert.getKeyUsage();
+ if (keyUsage != null && keyUsage[0] == false) {
+ return null;
+ }
+ String alias = ks.getCertificateAlias(xcert);
+ if (alias != null) {
+ PublicKey pk = ks.getCertificate(alias).getPublicKey();
+ // make sure algorithm is compatible with method
+ if (algEquals(sm.getAlgorithm(), pk.getAlgorithm())) {
+ return new SimpleKeySelectorResult(pk);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns an OID of a public-key algorithm compatible with the specified
+ * signature algorithm URI.
+ */
+ private String getPKAlgorithmOID(String algURI) {
+ if (algURI.equalsIgnoreCase(SignatureMethod.DSA_SHA1)) {
+ return "1.2.840.10040.4.1";
+ } else if (algURI.equalsIgnoreCase(SignatureMethod.RSA_SHA1)) {
+ return "1.2.840.113549.1.1";
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * A simple KeySelectorResult containing a public key.
+ */
+ private static class SimpleKeySelectorResult implements KeySelectorResult {
+ private final Key key;
+ SimpleKeySelectorResult(Key key) { this.key = key; }
+ public Key getKey() { return key; }
+ }
+
+ /**
+ * Checks if a JCA/JCE public key algorithm name is compatible with
+ * the specified signature algorithm URI.
+ */
+ //@@@FIXME: this should also work for key types other than DSA/RSA
+ private boolean algEquals(String algURI, String algName) {
+ if (algName.equalsIgnoreCase("DSA") &&
+ algURI.equalsIgnoreCase(SignatureMethod.DSA_SHA1)) {
+ return true;
+ } else if (algName.equalsIgnoreCase("RSA") &&
+ algURI.equalsIgnoreCase(SignatureMethod.RSA_SHA1)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Searches the specified keystore for a certificate that matches an
+ * entry of the specified X509Data and contains a public key that is
+ * compatible with the specified SignatureMethod.
+ *
+ * @return a KeySelectorResult containing the cert's public key if there
+ * is a match; otherwise null
+ */
+ private KeySelectorResult x509DataSelect(X509Data xd, SignatureMethod sm)
+ throws KeyStoreException, KeySelectorException {
+
+ // convert signature algorithm to compatible public-key alg OID
+ String algOID = getPKAlgorithmOID(sm.getAlgorithm());
+ X509CertSelector subjectcs = new X509CertSelector();
+ try {
+ subjectcs.setSubjectPublicKeyAlgID(algOID);
+ } catch (IOException ioe) {
+ throw new KeySelectorException(ioe);
+ }
+ Collection certs = new ArrayList();
+
+ Iterator xi = xd.getContent().iterator();
+ while (xi.hasNext()) {
+ Object o = xi.next();
+ // check X509IssuerSerial
+ if (o instanceof X509IssuerSerial) {
+ X509IssuerSerial xis = (X509IssuerSerial) o;
+ try {
+ subjectcs.setSerialNumber(xis.getSerialNumber());
+ String issuer = new X500Principal(xis.getIssuerName()).getName();
+ // strip off newline
+ if (issuer.endsWith("\n")) {
+ issuer = new String
+ (issuer.toCharArray(), 0, issuer.length()-1);
+ }
+ subjectcs.setIssuer(issuer);
+ } catch (IOException ioe) {
+ throw new KeySelectorException(ioe);
+ }
+ // check X509SubjectName
+ } else if (o instanceof String) {
+ String sn = (String) o;
+ try {
+ String subject = new X500Principal(sn).getName();
+ // strip off newline
+ if (subject.endsWith("\n")) {
+ subject = new String
+ (subject.toCharArray(), 0, subject.length()-1);
+ }
+ subjectcs.setSubject(subject);
+ } catch (IOException ioe) {
+ throw new KeySelectorException(ioe);
+ }
+ // check X509SKI
+ } else if (o instanceof byte[]) {
+ byte[] ski = (byte[]) o;
+ // DER-encode ski - required by X509CertSelector
+ byte[] encodedSki = new byte[ski.length+2];
+ encodedSki[0] = 0x04; // OCTET STRING tag value
+ encodedSki[1] = (byte) ski.length; // length
+ System.arraycopy(ski, 0, encodedSki, 2, ski.length);
+ subjectcs.setSubjectKeyIdentifier(encodedSki);
+ } else if (o instanceof X509Certificate) {
+ certs.add((X509Certificate) o);
+ // check X509CRL
+ // not supported: should use CertPath API
+ } else {
+ // skip all other entries
+ continue;
+ }
+ }
+ KeySelectorResult ksr = keyStoreSelect(subjectcs);
+ if (ksr != null) {
+ return ksr;
+ }
+ if (!certs.isEmpty() && !trusted) {
+ // try to find public key in certs in X509Data
+ Iterator i = certs.iterator();
+ while (i.hasNext()) {
+ X509Certificate cert = (X509Certificate) i.next();
+ if (subjectcs.match(cert)) {
+ return new SimpleKeySelectorResult(cert.getPublicKey());
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/test/javax/xml/crypto/dsig/data/certs/badb.crt b/test/javax/xml/crypto/dsig/data/certs/badb.crt
new file mode 100644
index 0000000..2d0dec6
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/certs/badb.crt
Binary files differ
diff --git a/test/javax/xml/crypto/dsig/data/certs/balor.crt b/test/javax/xml/crypto/dsig/data/certs/balor.crt
new file mode 100644
index 0000000..806d59d
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/certs/balor.crt
Binary files differ
diff --git a/test/javax/xml/crypto/dsig/data/certs/bres.crt b/test/javax/xml/crypto/dsig/data/certs/bres.crt
new file mode 100644
index 0000000..c0953f4
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/certs/bres.crt
Binary files differ
diff --git a/test/javax/xml/crypto/dsig/data/certs/ca.crt b/test/javax/xml/crypto/dsig/data/certs/ca.crt
new file mode 100644
index 0000000..00861d0
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/certs/ca.crt
Binary files differ
diff --git a/test/javax/xml/crypto/dsig/data/certs/crl b/test/javax/xml/crypto/dsig/data/certs/crl
new file mode 100644
index 0000000..a84e7ef
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/certs/crl
@@ -0,0 +1,11 @@
+-----BEGIN CRL-----
+MIIBJDCB5AIBATAJBgcqhkjOOAQDMHYxCzAJBgNVBAYTAklFMQ8wDQYDVQQIEwZE
+dWJsaW4xJDAiBgNVBAoTG0JhbHRpbW9yZSBUZWNobm9sb2dpZXMgTHRkLjERMA8G
+A1UECxMIWC9TZWN1cmUxHTAbBgNVBAMTFEFub3RoZXIgVHJhbnNpZW50IENBFw0w
+MjA0MDQwMjE2NThaFw0xMTA0MDIwMjE2NThaMBkwFwIGAOz5Id5/Fw0wMjA0MDQw
+MjE2NThaoCMwITATBgNVHSMEDDAKgAiKHFYwWjISfTAKBgNVHRQEAwIBADAJBgcq
+hkjOOAQDAzAAMC0CFCEIm38fvGzSJHms284hUs9dNB8nAhUAjEtZr0TGgc6sVRVk
+krEgltdo7Jw=
+-----END CRL-----
+
+
diff --git a/test/javax/xml/crypto/dsig/data/certs/lugh.crt b/test/javax/xml/crypto/dsig/data/certs/lugh.crt
new file mode 100644
index 0000000..2109edf
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/certs/lugh.crt
Binary files differ
diff --git a/test/javax/xml/crypto/dsig/data/certs/macha.crt b/test/javax/xml/crypto/dsig/data/certs/macha.crt
new file mode 100644
index 0000000..484ddc2
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/certs/macha.crt
Binary files differ
diff --git a/test/javax/xml/crypto/dsig/data/certs/morigu.crt b/test/javax/xml/crypto/dsig/data/certs/morigu.crt
new file mode 100644
index 0000000..ef0d415
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/certs/morigu.crt
Binary files differ
diff --git a/test/javax/xml/crypto/dsig/data/certs/nemain.crt b/test/javax/xml/crypto/dsig/data/certs/nemain.crt
new file mode 100644
index 0000000..f4b62ae
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/certs/nemain.crt
Binary files differ
diff --git a/test/javax/xml/crypto/dsig/data/certs/test.jks b/test/javax/xml/crypto/dsig/data/certs/test.jks
new file mode 100644
index 0000000..fd150d7
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/certs/test.jks
Binary files differ
diff --git a/test/javax/xml/crypto/dsig/data/certs/user.crt b/test/javax/xml/crypto/dsig/data/certs/user.crt
new file mode 100644
index 0000000..5bf28aa
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/certs/user.crt
Binary files differ
diff --git a/test/javax/xml/crypto/dsig/data/certs/xmldsig.jks b/test/javax/xml/crypto/dsig/data/certs/xmldsig.jks
new file mode 100644
index 0000000..9702fce
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/certs/xmldsig.jks
Binary files differ
diff --git a/test/javax/xml/crypto/dsig/data/envelope.xml b/test/javax/xml/crypto/dsig/data/envelope.xml
new file mode 100644
index 0000000..170f2ce
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/envelope.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Envelope [
+ <!ENTITY dsig 'http://www.w3.org/2000/09/xmldsig#'>
+ <!ENTITY c14n 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315'>
+ <!ENTITY xpath 'http://www.w3.org/TR/1999/REC-xpath-19991116'>
+ <!ENTITY xslt 'http://www.w3.org/TR/1999/REC-xslt-19991116'>
+ <!ATTLIST Notaries Id ID #IMPLIED>
+]>
+<!-- Preamble -->
+<Envelope xmlns:foo="http://example.org/foo" xmlns="http://example.org/usps">
+ <DearSir>foo</DearSir>
+ <Body>bar</Body>
+ <YoursSincerely>
+ </YoursSincerely>
+ <PostScript>bar</PostScript>
+ <Notaries xmlns="" Id="notaries">
+ <Notary name="Great, A. T." />
+ <Notary name="Hun, A. T." />
+ </Notaries>
+ <!-- Commentary -->
+</Envelope>
+<!-- Postamble -->
diff --git a/test/javax/xml/crypto/dsig/data/exc-signature.xml b/test/javax/xml/crypto/dsig/data/exc-signature.xml
new file mode 100644
index 0000000..e805940
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/exc-signature.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Foo xmlns:bar="urn:bar" xmlns="urn:foo" xml:space="preserve">
+ <dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
+ <dsig:SignedInfo>
+ <dsig:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
+ <dsig:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1" />
+ <dsig:Reference URI="#xpointer(id('to-be-signed'))">
+ <dsig:Transforms>
+ <dsig:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
+ </dsig:Transforms>
+ <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <dsig:DigestValue>7yOTjUu+9oEhShgyIIXDLjQ08aY=</dsig:DigestValue>
+ </dsig:Reference>
+ <dsig:Reference URI="#xpointer(id('to-be-signed'))">
+ <dsig:Transforms>
+ <dsig:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
+ <InclusiveNamespaces xmlns="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="bar #default" />
+ </dsig:Transform>
+ </dsig:Transforms>
+ <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <dsig:DigestValue>09xMy0RTQM1Q91demYe/0F6AGXo=</dsig:DigestValue>
+ </dsig:Reference>
+ <dsig:Reference URI="#xpointer(id('to-be-signed'))">
+ <dsig:Transforms>
+ <dsig:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#WithComments" />
+ </dsig:Transforms>
+ <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <dsig:DigestValue>ZQH+SkCN8c5y0feAr+aRTZDwyvY=</dsig:DigestValue>
+ </dsig:Reference>
+ <dsig:Reference URI="#xpointer(id('to-be-signed'))">
+ <dsig:Transforms>
+ <dsig:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#WithComments">
+ <InclusiveNamespaces xmlns="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="bar #default" />
+ </dsig:Transform>
+ </dsig:Transforms>
+ <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <dsig:DigestValue>a1cTqBgbqpUt6bMJN4C6zFtnoyo=</dsig:DigestValue>
+ </dsig:Reference>
+ </dsig:SignedInfo>
+ <dsig:SignatureValue>
+ Kv1e7Kjhz4gFtOZKgvC5cLYtMQNIn99fyLBa6D//bBokTxTUEkMwaA==
+ </dsig:SignatureValue>
+ <dsig:KeyInfo>
+ <dsig:KeyValue>
+ <dsig:DSAKeyValue>
+ <dsig:P>
+ 8FkJgwdyizV5Vd0m6DA/DZsdweJdnkueYVUd7L8aA4JpZxrlCI/M7mDE/OGhEhgB
+ nFzSTrBjSFpT7DG66uy7oJeE+RgkXO7EWWOEglMPwaZgGgi1oZarv95VOx3uO8W8
+ L7+S/3AuHNUZQD4b5bpdYAmjXFwz6dl0mKiXAvVuP9E=
+ </dsig:P>
+ <dsig:Q>
+ mFf8DiMVNFXy0vag9oNGNW/g4u0=
+ </dsig:Q>
+ <dsig:G>
+ g8gRdNlq9EOTR2TjmVApqCAZAq3jEjOIxXbs8JBiZ+U7dV9geeXEy13GbYoP23Qr
+ apZQo+35diw+cMYPHjN+iUCwUkiGWv7/piAK+Ootfw03etL8XiVWjtL5NBof2CNp
+ wmAw7mrwmNG092y1e6HXSGMMZpaoth/P8xhsxCQsqI8=
+ </dsig:G>
+ <dsig:Y>
+ j0V14dc/I+okDAeG4ZbWUzb3HTFkEOC6feOMo5Dk218GcPqEKroVHaDBF9CmRV1v
+ B8MUOExB+6ZNHfcs5Vaw0HVn62YiEBzrmKikx6SxO4Dg9L8I5WbHn37vxUKvHs8r
+ 7+rma3kpZQftTMiBpJ8XK8Z6jg8VhuJqo9yZZO+p3I0=
+ </dsig:Y>
+ </dsig:DSAKeyValue>
+ </dsig:KeyValue>
+ </dsig:KeyInfo>
+ <dsig:Object Id="to-be-signed">
+ <bar:Baz>
+ <!-- comment -->
+ </bar:Baz>
+ </dsig:Object>
+ </dsig:Signature>
+</Foo>
diff --git a/test/javax/xml/crypto/dsig/data/sign-spec.xml b/test/javax/xml/crypto/dsig/data/sign-spec.xml
new file mode 100644
index 0000000..dd5dfd7
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/sign-spec.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Document>
+ <ToBeSigned>
+ <!-- comment -->
+ <Data />
+ <NotToBeSigned>
+ <ReallyToBeSigned>
+ <!-- comment -->
+ <Data />
+ </ReallyToBeSigned>
+ </NotToBeSigned>
+ </ToBeSigned>
+ <ToBeSigned>
+ <Data />
+ <NotToBeSigned>
+ <Data />
+ </NotToBeSigned>
+ </ToBeSigned>
+ <dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
+ <dsig:SignedInfo>
+ <dsig:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
+ <dsig:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1" />
+ <dsig:Reference URI="">
+ <dsig:Transforms>
+ <dsig:Transform Algorithm="http://www.w3.org/2002/06/xmldsig-filter2">
+ <XPath xmlns="http://www.w3.org/2002/06/xmldsig-filter2" Filter="intersect"> //ToBeSigned </XPath>
+ <XPath xmlns="http://www.w3.org/2002/06/xmldsig-filter2" Filter="subtract"> //NotToBeSigned </XPath>
+ <XPath xmlns="http://www.w3.org/2002/06/xmldsig-filter2" Filter="union"> //ReallyToBeSigned </XPath>
+ </dsig:Transform>
+ </dsig:Transforms>
+ <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <dsig:DigestValue>p6/HaYIdxbEdYX8/8zNfjED4H5Y=</dsig:DigestValue>
+ </dsig:Reference>
+ <dsig:Reference URI="#signature-value">
+ <dsig:Transforms>
+ <dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
+ <dsig:Transform Algorithm="http://www.w3.org/2002/06/xmldsig-filter2">
+ <XPath xmlns="http://www.w3.org/2002/06/xmldsig-filter2" Filter="union"> /</XPath>
+ </dsig:Transform>
+ </dsig:Transforms>
+ <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <dsig:DigestValue>2jmj7l5rSw0yVb/vlWAYkK/YBwk=</dsig:DigestValue>
+ </dsig:Reference>
+ </dsig:SignedInfo>
+ <dsig:SignatureValue Id="signature-value">
+ Ft7PdmEYSC8GwxffIa4xiobr1iEaUf3LGNfPLiQnJBJI/1Cp5WiEiQ==
+ </dsig:SignatureValue>
+ <dsig:KeyInfo>
+ <dsig:KeyValue>
+ <dsig:DSAKeyValue>
+ <dsig:P>
+ 3eOeAvqnEyFpW+uTSgrdj7YLjaTkpyHecKFIoLu8QZNkGTQI1ciITBH0lqfIkdCH
+ Si8fiUC3DTq3J9FsJef4YVtDF7JpUvHTOQqtq7Zgx6KC8Wxkz6rQCxOr7F0ApOYi
+ 89zLRoe4MkDGe6ux0+WtyOTQoVIGNTDDUFXrUQNbLrE=
+ </dsig:P>
+ <dsig:Q>hDLcFK0GO/Hz1arxOOvsgM/VLyU=</dsig:Q>
+ <dsig:G>
+ nnx7hbdWozGbtnFgnbFnopfRl7XRacpkPJRGf5P2IUgVspEUSUoN6i1fDBfBg43z
+ Kt7dlEaQL7b5+JTZt3MhZNPosxsgxVuT7Ts/g5k7EnpdYv0a5hw5Bw29fjbGHfgM
+ 8d2rhd2Ui0xHbk0D451nhLxVWulviOSPhzKKvXrbySA=
+ </dsig:G>
+ <dsig:Y>
+ cfYpihpAQeepbNFS4MAbQRhdXpDi5wLrwxE5hIvoYqo1L8BQVu8fY1TFAPtoae1i
+ Bg/GIJyP3iLfyuBJaDvJJLP30wBH9i/s5J3656PevpOVdTfi777Fi9Gj6y/ib2Vv
+ +OZfJkkp4L50+p5TUhPmQLJtREsgtl+tnIOyJT++G9U=
+ </dsig:Y>
+ </dsig:DSAKeyValue>
+ </dsig:KeyValue>
+ <dsig:X509Data>
+ <dsig:X509SubjectName>
+ CN=Merlin Hughes,OU=X/Secure,O=Baltimore Technologies Ltd.,ST=Dublin,C=IE
+ </dsig:X509SubjectName>
+ <dsig:X509IssuerSerial>
+ <dsig:X509IssuerName>
+ CN=Transient CA,OU=X/Secure,O=Baltimore Technologies Ltd.,ST=Dublin,C=IE
+ </dsig:X509IssuerName>
+ <dsig:X509SerialNumber>1017788370348</dsig:X509SerialNumber>
+ </dsig:X509IssuerSerial>
+ <dsig:X509Certificate>
+ MIIDUDCCAxCgAwIBAgIGAOz46g2sMAkGByqGSM44BAMwbjELMAkGA1UEBhMCSUUx
+ DzANBgNVBAgTBkR1YmxpbjEkMCIGA1UEChMbQmFsdGltb3JlIFRlY2hub2xvZ2ll
+ cyBMdGQuMREwDwYDVQQLEwhYL1NlY3VyZTEVMBMGA1UEAxMMVHJhbnNpZW50IENB
+ MB4XDTAyMDQwMjIyNTkzMFoXDTEyMDQwMjIxNTkyNVowbzELMAkGA1UEBhMCSUUx
+ DzANBgNVBAgTBkR1YmxpbjEkMCIGA1UEChMbQmFsdGltb3JlIFRlY2hub2xvZ2ll
+ cyBMdGQuMREwDwYDVQQLEwhYL1NlY3VyZTEWMBQGA1UEAxMNTWVybGluIEh1Z2hl
+ czCCAbcwggEsBgcqhkjOOAQBMIIBHwKBgQDd454C+qcTIWlb65NKCt2PtguNpOSn
+ Id5woUigu7xBk2QZNAjVyIhMEfSWp8iR0IdKLx+JQLcNOrcn0Wwl5/hhW0MXsmlS
+ 8dM5Cq2rtmDHooLxbGTPqtALE6vsXQCk5iLz3MtGh7gyQMZ7q7HT5a3I5NChUgY1
+ MMNQVetRA1susQIVAIQy3BStBjvx89Wq8Tjr7IDP1S8lAoGBAJ58e4W3VqMxm7Zx
+ YJ2xZ6KX0Ze10WnKZDyURn+T9iFIFbKRFElKDeotXwwXwYON8yre3ZRGkC+2+fiU
+ 2bdzIWTT6LMbIMVbk+07P4OZOxJ6XWL9GuYcOQcNvX42xh34DPHdq4XdlItMR25N
+ A+OdZ4S8VVrpb4jkj4cyir1628kgA4GEAAKBgHH2KYoaQEHnqWzRUuDAG0EYXV6Q
+ 4ucC68MROYSL6GKqNS/AUFbvH2NUxQD7aGntYgYPxiCcj94i38rgSWg7ySSz99MA
+ R/Yv7OSd+uej3r6TlXU34u++xYvRo+sv4m9lb/jmXyZJKeC+dPqeU1IT5kCybURL
+ ILZfrZyDsiU/vhvVozowODAOBgNVHQ8BAf8EBAMCB4AwEQYDVR0OBAoECIatY7SE
+ lXEOMBMGA1UdIwQMMAqACIOGPkB2MuKTMAkGByqGSM44BAMDLwAwLAIUSvT02iQj
+ Q5da4Wpe0Bvs7GuCcVsCFCEcQpbjUfnxXFXNWiFyQ49ZrWqn
+ </dsig:X509Certificate>
+ <dsig:X509Certificate>
+ MIIDSzCCAwugAwIBAgIGAOz46fwJMAkGByqGSM44BAMwbjELMAkGA1UEBhMCSUUx
+ DzANBgNVBAgTBkR1YmxpbjEkMCIGA1UEChMbQmFsdGltb3JlIFRlY2hub2xvZ2ll
+ cyBMdGQuMREwDwYDVQQLEwhYL1NlY3VyZTEVMBMGA1UEAxMMVHJhbnNpZW50IENB
+ MB4XDTAyMDQwMjIyNTkyNVoXDTEyMDQwMjIxNTkyNVowbjELMAkGA1UEBhMCSUUx
+ DzANBgNVBAgTBkR1YmxpbjEkMCIGA1UEChMbQmFsdGltb3JlIFRlY2hub2xvZ2ll
+ cyBMdGQuMREwDwYDVQQLEwhYL1NlY3VyZTEVMBMGA1UEAxMMVHJhbnNpZW50IENB
+ MIIBtzCCASwGByqGSM44BAEwggEfAoGBAN3jngL6pxMhaVvrk0oK3Y+2C42k5Kch
+ 3nChSKC7vEGTZBk0CNXIiEwR9JanyJHQh0ovH4lAtw06tyfRbCXn+GFbQxeyaVLx
+ 0zkKrau2YMeigvFsZM+q0AsTq+xdAKTmIvPcy0aHuDJAxnursdPlrcjk0KFSBjUw
+ w1BV61EDWy6xAhUAhDLcFK0GO/Hz1arxOOvsgM/VLyUCgYEAnnx7hbdWozGbtnFg
+ nbFnopfRl7XRacpkPJRGf5P2IUgVspEUSUoN6i1fDBfBg43zKt7dlEaQL7b5+JTZ
+ t3MhZNPosxsgxVuT7Ts/g5k7EnpdYv0a5hw5Bw29fjbGHfgM8d2rhd2Ui0xHbk0D
+ 451nhLxVWulviOSPhzKKvXrbySADgYQAAoGAfag+HCABIJadDD9Aarhgc2QR3Lp7
+ PpMOh0lAwLiIsvkO4UlbeOS0IJC8bcqLjM1fVw6FGSaxmq+4y1ag2m9k6IdE0Qh5
+ NxB/xFkmdwqXFRIJVp44OeUygB47YK76NmUIYG3DdfiPPU3bqzjvtOtETiCHvo25
+ 4D6UjwPpYErXRUajNjA0MA4GA1UdDwEB/wQEAwICBDAPBgNVHRMECDAGAQH/AgEA
+ MBEGA1UdDgQKBAiDhj5AdjLikzAJBgcqhkjOOAQDAy8AMCwCFELu0nuweqW7Wf0s
+ gk/CAGGL0BGKAhRNdgQGr5iyZKoH4oqPm0VJ9TjXLg==
+ </dsig:X509Certificate>
+ </dsig:X509Data>
+ </dsig:KeyInfo>
+ </dsig:Signature>
+</Document>
diff --git a/test/javax/xml/crypto/dsig/data/signature-enveloped-dsa.xml b/test/javax/xml/crypto/dsig/data/signature-enveloped-dsa.xml
new file mode 100644
index 0000000..f5ff1f5
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/signature-enveloped-dsa.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Envelope xmlns="http://example.org/envelope">
+ <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+ <SignedInfo>
+ <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
+ <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1" />
+ <Reference URI="">
+ <Transforms>
+ <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
+ </Transforms>
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>fdy6S2NLpnT4fMdokUHSHsmpcvo=</DigestValue>
+ </Reference>
+ </SignedInfo>
+ <SignatureValue>
+ Z4pBb+o+XOKWME7CpLyXuNqyIYdXOcGvthfUf+ZDLL5immPx+3tK8Q==
+ </SignatureValue>
+ <KeyInfo>
+ <KeyValue>
+ <DSAKeyValue>
+ <P>
+ 3eOeAvqnEyFpW+uTSgrdj7YLjaTkpyHecKFIoLu8QZNkGTQI1ciITBH0lqfIkdCH
+ Si8fiUC3DTq3J9FsJef4YVtDF7JpUvHTOQqtq7Zgx6KC8Wxkz6rQCxOr7F0ApOYi
+ 89zLRoe4MkDGe6ux0+WtyOTQoVIGNTDDUFXrUQNbLrE=
+ </P>
+ <Q>
+ hDLcFK0GO/Hz1arxOOvsgM/VLyU=
+ </Q>
+ <G>
+ nnx7hbdWozGbtnFgnbFnopfRl7XRacpkPJRGf5P2IUgVspEUSUoN6i1fDBfBg43z
+ Kt7dlEaQL7b5+JTZt3MhZNPosxsgxVuT7Ts/g5k7EnpdYv0a5hw5Bw29fjbGHfgM
+ 8d2rhd2Ui0xHbk0D451nhLxVWulviOSPhzKKvXrbySA=
+ </G>
+ <Y>
+ cfYpihpAQeepbNFS4MAbQRhdXpDi5wLrwxE5hIvoYqo1L8BQVu8fY1TFAPtoae1i
+ Bg/GIJyP3iLfyuBJaDvJJLP30wBH9i/s5J3656PevpOVdTfi777Fi9Gj6y/ib2Vv
+ +OZfJkkp4L50+p5TUhPmQLJtREsgtl+tnIOyJT++G9U=
+ </Y>
+ </DSAKeyValue>
+ </KeyValue>
+ </KeyInfo>
+ </Signature>
+</Envelope>
diff --git a/test/javax/xml/crypto/dsig/data/signature-enveloping-b64-dsa.xml b/test/javax/xml/crypto/dsig/data/signature-enveloping-b64-dsa.xml
new file mode 100644
index 0000000..4e924b0
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/signature-enveloping-b64-dsa.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+ <SignedInfo>
+ <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
+ <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1" />
+ <Reference URI="#object">
+ <Transforms>
+ <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#base64" />
+ </Transforms>
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>N6pjx3OY2VRHMmLhoAV8HmMu2nc=</DigestValue>
+ </Reference>
+ </SignedInfo>
+ <SignatureValue>
+ KgAeq8e0yUNfFz+mFlZ3QgyQNMciV+Z3BoDQDvQNker7pazEnJmOIA==
+ </SignatureValue>
+ <KeyInfo>
+ <KeyValue>
+ <DSAKeyValue>
+ <P>
+ 3eOeAvqnEyFpW+uTSgrdj7YLjaTkpyHecKFIoLu8QZNkGTQI1ciITBH0lqfIkdCH
+ Si8fiUC3DTq3J9FsJef4YVtDF7JpUvHTOQqtq7Zgx6KC8Wxkz6rQCxOr7F0ApOYi
+ 89zLRoe4MkDGe6ux0+WtyOTQoVIGNTDDUFXrUQNbLrE=
+ </P>
+ <Q>
+ hDLcFK0GO/Hz1arxOOvsgM/VLyU=
+ </Q>
+ <G>
+ nnx7hbdWozGbtnFgnbFnopfRl7XRacpkPJRGf5P2IUgVspEUSUoN6i1fDBfBg43z
+ Kt7dlEaQL7b5+JTZt3MhZNPosxsgxVuT7Ts/g5k7EnpdYv0a5hw5Bw29fjbGHfgM
+ 8d2rhd2Ui0xHbk0D451nhLxVWulviOSPhzKKvXrbySA=
+ </G>
+ <Y>
+ cfYpihpAQeepbNFS4MAbQRhdXpDi5wLrwxE5hIvoYqo1L8BQVu8fY1TFAPtoae1i
+ Bg/GIJyP3iLfyuBJaDvJJLP30wBH9i/s5J3656PevpOVdTfi777Fi9Gj6y/ib2Vv
+ +OZfJkkp4L50+p5TUhPmQLJtREsgtl+tnIOyJT++G9U=
+ </Y>
+ </DSAKeyValue>
+ </KeyValue>
+ </KeyInfo>
+ <Object Id="object">c29tZSB0ZXh0</Object>
+</Signature>
diff --git a/test/javax/xml/crypto/dsig/data/signature-enveloping-dsa.xml b/test/javax/xml/crypto/dsig/data/signature-enveloping-dsa.xml
new file mode 100644
index 0000000..488ac26
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/signature-enveloping-dsa.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+ <SignedInfo>
+ <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
+ <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1" />
+ <Reference URI="#object">
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>7/XTsHaBSOnJ/jXD5v0zL6VKYsk=</DigestValue>
+ </Reference>
+ </SignedInfo>
+ <SignatureValue>
+ PfD92lkxKgc2OKvF4p0ba6cJj6d1eqIDx5Q1hvVYTviotje23Snunw==
+ </SignatureValue>
+ <KeyInfo>
+ <KeyValue>
+ <DSAKeyValue>
+ <P>
+ 3eOeAvqnEyFpW+uTSgrdj7YLjaTkpyHecKFIoLu8QZNkGTQI1ciITBH0lqfIkdCH
+ Si8fiUC3DTq3J9FsJef4YVtDF7JpUvHTOQqtq7Zgx6KC8Wxkz6rQCxOr7F0ApOYi
+ 89zLRoe4MkDGe6ux0+WtyOTQoVIGNTDDUFXrUQNbLrE=
+ </P>
+ <Q>
+ hDLcFK0GO/Hz1arxOOvsgM/VLyU=
+ </Q>
+ <G>
+ nnx7hbdWozGbtnFgnbFnopfRl7XRacpkPJRGf5P2IUgVspEUSUoN6i1fDBfBg43z
+ Kt7dlEaQL7b5+JTZt3MhZNPosxsgxVuT7Ts/g5k7EnpdYv0a5hw5Bw29fjbGHfgM
+ 8d2rhd2Ui0xHbk0D451nhLxVWulviOSPhzKKvXrbySA=
+ </G>
+ <Y>
+ cfYpihpAQeepbNFS4MAbQRhdXpDi5wLrwxE5hIvoYqo1L8BQVu8fY1TFAPtoae1i
+ Bg/GIJyP3iLfyuBJaDvJJLP30wBH9i/s5J3656PevpOVdTfi777Fi9Gj6y/ib2Vv
+ +OZfJkkp4L50+p5TUhPmQLJtREsgtl+tnIOyJT++G9U=
+ </Y>
+ </DSAKeyValue>
+ </KeyValue>
+ </KeyInfo>
+ <Object Id="object">some text</Object>
+</Signature>
diff --git a/test/javax/xml/crypto/dsig/data/signature-enveloping-hmac-sha1-40.xml b/test/javax/xml/crypto/dsig/data/signature-enveloping-hmac-sha1-40.xml
new file mode 100644
index 0000000..4904d79
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/signature-enveloping-hmac-sha1-40.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+ <SignedInfo>
+ <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
+ <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1">
+ <HMACOutputLength>40</HMACOutputLength>
+ </SignatureMethod>
+ <Reference URI="#object">
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>7/XTsHaBSOnJ/jXD5v0zL6VKYsk=</DigestValue>
+ </Reference>
+ </SignedInfo>
+ <SignatureValue>
+ HHiqvCU=
+ </SignatureValue>
+ <Object Id="object">some text</Object>
+</Signature>
diff --git a/test/javax/xml/crypto/dsig/data/signature-enveloping-hmac-sha1.xml b/test/javax/xml/crypto/dsig/data/signature-enveloping-hmac-sha1.xml
new file mode 100644
index 0000000..c0c8343
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/signature-enveloping-hmac-sha1.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+ <SignedInfo>
+ <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
+ <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1" />
+ <Reference URI="#object">
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>7/XTsHaBSOnJ/jXD5v0zL6VKYsk=</DigestValue>
+ </Reference>
+ </SignedInfo>
+ <SignatureValue>
+ JElPttIT4Am7Q+MNoMyv+WDfAZw=
+ </SignatureValue>
+ <Object Id="object">some text</Object>
+</Signature>
diff --git a/test/javax/xml/crypto/dsig/data/signature-enveloping-rsa.xml b/test/javax/xml/crypto/dsig/data/signature-enveloping-rsa.xml
new file mode 100644
index 0000000..1580d83
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/signature-enveloping-rsa.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+ <SignedInfo>
+ <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
+ <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
+ <Reference URI="#object">
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>7/XTsHaBSOnJ/jXD5v0zL6VKYsk=</DigestValue>
+ </Reference>
+ </SignedInfo>
+ <SignatureValue>
+ ov3HOoPN0w71N3DdGNhN+dSzQm6NJFUB5qGKRp9Q986nVzMb8wCIVxCQu+x3vMtq
+ p4/R3KEcPtEJSaoR+thGq++GPIh2mZXyWJs3xHy9P4xmoTVwli7/l7s8ebDSmnbZ
+ 7xZU4Iy1BSMZSxGKnRG+Z/0GJIfTz8jhH6wCe3l03L4=
+ </SignatureValue>
+ <KeyInfo>
+ <KeyValue>
+ <RSAKeyValue>
+ <Modulus>
+ q07hpxA5DGFfvJFZueFl/LI85XxQxrvqgVugL25V090A9MrlLBg5PmAsxFTe+G6a
+ xvWJQwYOVHj/nuiCnNLa9a7uAtPFiTtW+v5H3wlLaY3ws4atRBNOQlYkIBp38sTf
+ QBkk4i8PEU1GQ2M0CLIJq4/2Akfv1wxzSQ9+8oWkArc=
+ </Modulus>
+ <Exponent>
+ AQAB
+ </Exponent>
+ </RSAKeyValue>
+ </KeyValue>
+ </KeyInfo>
+ <Object Id="object">some text</Object>
+</Signature>
diff --git a/test/javax/xml/crypto/dsig/data/signature-external-b64-dsa.xml b/test/javax/xml/crypto/dsig/data/signature-external-b64-dsa.xml
new file mode 100644
index 0000000..1fb5663
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/signature-external-b64-dsa.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+ <SignedInfo>
+ <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
+ <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1" />
+ <Reference URI="http://www.w3.org/Signature/2002/04/xml-stylesheet.b64">
+ <Transforms>
+ <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#base64" />
+ </Transforms>
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>60NvZvtdTB+7UnlLp/H24p7h4bs=</DigestValue>
+ </Reference>
+ </SignedInfo>
+ <SignatureValue>
+ IhOlAjMFaZtkEju5R5bi528h1HpDa4A21sudZynhJRRLjZuQIHZ3eQ==
+ </SignatureValue>
+ <KeyInfo>
+ <KeyValue>
+ <DSAKeyValue>
+ <P>
+ 3eOeAvqnEyFpW+uTSgrdj7YLjaTkpyHecKFIoLu8QZNkGTQI1ciITBH0lqfIkdCH
+ Si8fiUC3DTq3J9FsJef4YVtDF7JpUvHTOQqtq7Zgx6KC8Wxkz6rQCxOr7F0ApOYi
+ 89zLRoe4MkDGe6ux0+WtyOTQoVIGNTDDUFXrUQNbLrE=
+ </P>
+ <Q>
+ hDLcFK0GO/Hz1arxOOvsgM/VLyU=
+ </Q>
+ <G>
+ nnx7hbdWozGbtnFgnbFnopfRl7XRacpkPJRGf5P2IUgVspEUSUoN6i1fDBfBg43z
+ Kt7dlEaQL7b5+JTZt3MhZNPosxsgxVuT7Ts/g5k7EnpdYv0a5hw5Bw29fjbGHfgM
+ 8d2rhd2Ui0xHbk0D451nhLxVWulviOSPhzKKvXrbySA=
+ </G>
+ <Y>
+ cfYpihpAQeepbNFS4MAbQRhdXpDi5wLrwxE5hIvoYqo1L8BQVu8fY1TFAPtoae1i
+ Bg/GIJyP3iLfyuBJaDvJJLP30wBH9i/s5J3656PevpOVdTfi777Fi9Gj6y/ib2Vv
+ +OZfJkkp4L50+p5TUhPmQLJtREsgtl+tnIOyJT++G9U=
+ </Y>
+ </DSAKeyValue>
+ </KeyValue>
+ </KeyInfo>
+</Signature>
diff --git a/test/javax/xml/crypto/dsig/data/signature-external-dsa.xml b/test/javax/xml/crypto/dsig/data/signature-external-dsa.xml
new file mode 100644
index 0000000..34d3e6a
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/signature-external-dsa.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+ <SignedInfo>
+ <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
+ <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1" />
+ <Reference URI="http://www.w3.org/TR/xml-stylesheet">
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>60NvZvtdTB+7UnlLp/H24p7h4bs=</DigestValue>
+ </Reference>
+ </SignedInfo>
+ <SignatureValue>
+ LaL1/t/XodYvDJDgSEbq47GX8ltnlx3FFURdi7o+UFVi+zLf0WyWaQ==
+ </SignatureValue>
+ <KeyInfo>
+ <KeyValue>
+ <DSAKeyValue>
+ <P>
+ 3eOeAvqnEyFpW+uTSgrdj7YLjaTkpyHecKFIoLu8QZNkGTQI1ciITBH0lqfIkdCH
+ Si8fiUC3DTq3J9FsJef4YVtDF7JpUvHTOQqtq7Zgx6KC8Wxkz6rQCxOr7F0ApOYi
+ 89zLRoe4MkDGe6ux0+WtyOTQoVIGNTDDUFXrUQNbLrE=
+ </P>
+ <Q>
+ hDLcFK0GO/Hz1arxOOvsgM/VLyU=
+ </Q>
+ <G>
+ nnx7hbdWozGbtnFgnbFnopfRl7XRacpkPJRGf5P2IUgVspEUSUoN6i1fDBfBg43z
+ Kt7dlEaQL7b5+JTZt3MhZNPosxsgxVuT7Ts/g5k7EnpdYv0a5hw5Bw29fjbGHfgM
+ 8d2rhd2Ui0xHbk0D451nhLxVWulviOSPhzKKvXrbySA=
+ </G>
+ <Y>
+ cfYpihpAQeepbNFS4MAbQRhdXpDi5wLrwxE5hIvoYqo1L8BQVu8fY1TFAPtoae1i
+ Bg/GIJyP3iLfyuBJaDvJJLP30wBH9i/s5J3656PevpOVdTfi777Fi9Gj6y/ib2Vv
+ +OZfJkkp4L50+p5TUhPmQLJtREsgtl+tnIOyJT++G9U=
+ </Y>
+ </DSAKeyValue>
+ </KeyValue>
+ </KeyInfo>
+</Signature>
diff --git a/test/javax/xml/crypto/dsig/data/signature-keyname.xml b/test/javax/xml/crypto/dsig/data/signature-keyname.xml
new file mode 100644
index 0000000..a7c60a3
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/signature-keyname.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+ <SignedInfo>
+ <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
+ <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1" />
+ <Reference URI="http://www.w3.org/TR/xml-stylesheet">
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>60NvZvtdTB+7UnlLp/H24p7h4bs=</DigestValue>
+ </Reference>
+ </SignedInfo>
+ <SignatureValue>
+ JkJ3GplEU0iDbqSv7ZOXhvv3zeM1KmP+CLphhoc+NPYqpGYQiW6O6w==
+ </SignatureValue>
+ <KeyInfo>
+ <KeyName>Lugh</KeyName>
+ </KeyInfo>
+</Signature>
diff --git a/test/javax/xml/crypto/dsig/data/signature-retrievalmethod-rawx509crt.xml b/test/javax/xml/crypto/dsig/data/signature-retrievalmethod-rawx509crt.xml
new file mode 100644
index 0000000..2e861d9
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/signature-retrievalmethod-rawx509crt.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+ <SignedInfo>
+ <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
+ <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1" />
+ <Reference URI="http://www.w3.org/TR/xml-stylesheet">
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>60NvZvtdTB+7UnlLp/H24p7h4bs=</DigestValue>
+ </Reference>
+ </SignedInfo>
+ <SignatureValue>
+ SNB5FI193RFXoG2j8Z9bXWgW7BMPICqNob4Hjh08oou4tkhGxz4+pg==
+ </SignatureValue>
+ <KeyInfo>
+ <RetrievalMethod Type="http://www.w3.org/2000/09/xmldsig#rawX509Certificate" URI="certs/balor.crt" />
+ </KeyInfo>
+</Signature>
diff --git a/test/javax/xml/crypto/dsig/data/signature-x509-crt-crl.xml b/test/javax/xml/crypto/dsig/data/signature-x509-crt-crl.xml
new file mode 100644
index 0000000..fe01797
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/signature-x509-crt-crl.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+ <SignedInfo>
+ <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
+ <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1" />
+ <Reference URI="http://www.w3.org/TR/xml-stylesheet">
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>60NvZvtdTB+7UnlLp/H24p7h4bs=</DigestValue>
+ </Reference>
+ </SignedInfo>
+ <SignatureValue>
+ WF6EaX66f8CdGE6NafmzdLpb/1OVYX4kBNsqgGIqHR5JZAu4HpbVQQ==
+ </SignatureValue>
+ <KeyInfo>
+ <X509Data>
+ <X509Certificate>
+ MIIDTjCCAw6gAwIBAgIGAOz5Id5/MAkGByqGSM44BAMwdjELMAkGA1UEBhMCSUUx
+ DzANBgNVBAgTBkR1YmxpbjEkMCIGA1UEChMbQmFsdGltb3JlIFRlY2hub2xvZ2ll
+ cyBMdGQuMREwDwYDVQQLEwhYL1NlY3VyZTEdMBsGA1UEAxMUQW5vdGhlciBUcmFu
+ c2llbnQgQ0EwHhcNMDIwNDAzMDAwMDI4WhcNMTIwNDAyMjI1OTQ2WjBmMQswCQYD
+ VQQGEwJJRTEPMA0GA1UECBMGRHVibGluMSQwIgYDVQQKExtCYWx0aW1vcmUgVGVj
+ aG5vbG9naWVzIEx0ZC4xETAPBgNVBAsTCFgvU2VjdXJlMQ0wCwYDVQQDEwRCcmVz
+ MIIBtjCCASsGByqGSM44BAEwggEeAoGBAISKsEonjNGgHs/uh+9YKgnwZ8Bt3T7u
+ yQBJW9dxpMF0cPUXz4dFbSFY4QyW8igCLswpOa+eHHEYsWvE0Nr1lcKHUPXq7u41
+ JJwHNq1RAFeZiU6wa+1FL3v1/T1rAgzepV7xS4iafz4vxdHMlfwgKfoyKfq6JU1z
+ oVM/ahI5xWDDAhUAmEv6eIJrB4KN0fPRABPx3NHYclkCgYAlhuYZ/AzPta7+bE5C
+ QasmSVzc8uM/e+LN7ABlEXwQRk6QfZBcX8TbePNE8ZFng4Uft/QzAOUxALET7kKA
+ ek4Jeytpzc0XYCYyuGJATm4F9ZY1pAJ5yQmUmwvDYdlaZJ4ldGzO/R57Evngn/G4
+ tqjjoi0sx3jq7czvDwdGHnky0AOBhAACgYBgvDFxw1U6Ou2G6P/+347Jfk2wPB1/
+ atr4p3JUVLuT0ExZG6np+rKiXmcBbYKbAhMY37zVkroR9bwo+NgaJGubQ4ex5Y1X
+ N2Q5gIHNhNfKr8G4LPVqWGxf/lFPDYxX3ezqBJPpJCJTREX7s6Hp/VTV2SpQlySv
+ +GRcFKJFPlhD9aM6MDgwDgYDVR0PAQH/BAQDAgeAMBEGA1UdDgQKBAiC+5gx0MHL
+ hTATBgNVHSMEDDAKgAiKHFYwWjISfTAJBgcqhkjOOAQDAy8AMCwCFDTcM5i61uqq
+ /aveERhOJ6NG/LubAhREVDtAeNbTEywXr4O7KvEEvFLUjg==
+ </X509Certificate>
+ <X509CRL>
+ MIIBJDCB5AIBATAJBgcqhkjOOAQDMHYxCzAJBgNVBAYTAklFMQ8wDQYDVQQIEwZE
+ dWJsaW4xJDAiBgNVBAoTG0JhbHRpbW9yZSBUZWNobm9sb2dpZXMgTHRkLjERMA8G
+ A1UECxMIWC9TZWN1cmUxHTAbBgNVBAMTFEFub3RoZXIgVHJhbnNpZW50IENBFw0w
+ MjA0MDQwMjE2NThaFw0xMTA0MDIwMjE2NThaMBkwFwIGAOz5Id5/Fw0wMjA0MDQw
+ MjE2NThaoCMwITATBgNVHSMEDDAKgAiKHFYwWjISfTAKBgNVHRQEAwIBADAJBgcq
+ hkjOOAQDAzAAMC0CFCEIm38fvGzSJHms284hUs9dNB8nAhUAjEtZr0TGgc6sVRVk
+ krEgltdo7Jw=
+ </X509CRL>
+ </X509Data>
+ </KeyInfo>
+</Signature>
diff --git a/test/javax/xml/crypto/dsig/data/signature-x509-crt.xml b/test/javax/xml/crypto/dsig/data/signature-x509-crt.xml
new file mode 100644
index 0000000..2048fd2
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/signature-x509-crt.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+ <SignedInfo>
+ <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
+ <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1" />
+ <Reference URI="http://www.w3.org/TR/xml-stylesheet">
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>60NvZvtdTB+7UnlLp/H24p7h4bs=</DigestValue>
+ </Reference>
+ </SignedInfo>
+ <SignatureValue>
+ GCQVmBq+1H7e9IjvKfe+egLM1Jlp3L1JCGkl9SlJ0eaDh2MKYUUnHA==
+ </SignatureValue>
+ <KeyInfo>
+ <X509Data>
+ <X509Certificate>
+ MIIDUDCCAxCgAwIBAgIGAOz5IVHTMAkGByqGSM44BAMwdjELMAkGA1UEBhMCSUUx
+ DzANBgNVBAgTBkR1YmxpbjEkMCIGA1UEChMbQmFsdGltb3JlIFRlY2hub2xvZ2ll
+ cyBMdGQuMREwDwYDVQQLEwhYL1NlY3VyZTEdMBsGA1UEAxMUQW5vdGhlciBUcmFu
+ c2llbnQgQ0EwHhcNMDIwNDAyMjM1OTUyWhcNMTIwNDAyMjI1OTQ2WjBoMQswCQYD
+ VQQGEwJJRTEPMA0GA1UECBMGRHVibGluMSQwIgYDVQQKExtCYWx0aW1vcmUgVGVj
+ aG5vbG9naWVzIEx0ZC4xETAPBgNVBAsTCFgvU2VjdXJlMQ8wDQYDVQQDEwZNb3Jp
+ Z3UwggG2MIIBKwYHKoZIzjgEATCCAR4CgYEAhIqwSieM0aAez+6H71gqCfBnwG3d
+ Pu7JAElb13GkwXRw9RfPh0VtIVjhDJbyKAIuzCk5r54ccRixa8TQ2vWVwodQ9eru
+ 7jUknAc2rVEAV5mJTrBr7UUve/X9PWsCDN6lXvFLiJp/Pi/F0cyV/CAp+jIp+rol
+ TXOhUz9qEjnFYMMCFQCYS/p4gmsHgo3R89EAE/Hc0dhyWQKBgCWG5hn8DM+1rv5s
+ TkJBqyZJXNzy4z974s3sAGURfBBGTpB9kFxfxNt480TxkWeDhR+39DMA5TEAsRPu
+ QoB6Tgl7K2nNzRdgJjK4YkBObgX1ljWkAnnJCZSbC8Nh2VpkniV0bM79HnsS+eCf
+ 8bi2qOOiLSzHeOrtzO8PB0YeeTLQA4GEAAKBgH1NBJ9Az5TwY4tDE0dPYVHHABt+
+ yLspnT3k9G6YWUMFhZ/+3RuqEPjnKrPfUoXTTJGIACgPU3/PkqwrPVD0JMdpOcnZ
+ LHiJ/P7QRQeMwDRoBrs7genB1bDd4pSJrEUcjrkA5uRrIj2Z5fL+UuLiLGPO2rM7
+ BNQRIq3QFPdX++NuozowODAOBgNVHQ8BAf8EBAMCB4AwEQYDVR0OBAoECIK7Ljjh
+ +EsfMBMGA1UdIwQMMAqACIocVjBaMhJ9MAkGByqGSM44BAMDLwAwLAIUEJJCOHw8
+ ppxoRyz3s+Vmb4NKIfMCFDgJoZn9zh/3WoYNBURODwLvyBOy
+ </X509Certificate>
+ </X509Data>
+ </KeyInfo>
+</Signature>
diff --git a/test/javax/xml/crypto/dsig/data/signature-x509-is.xml b/test/javax/xml/crypto/dsig/data/signature-x509-is.xml
new file mode 100644
index 0000000..b7a01f8
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/signature-x509-is.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+ <SignedInfo>
+ <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
+ <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1" />
+ <Reference URI="http://www.w3.org/TR/xml-stylesheet">
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>60NvZvtdTB+7UnlLp/H24p7h4bs=</DigestValue>
+ </Reference>
+ </SignedInfo>
+ <SignatureValue>
+ bmKMy/w1DO9dHA6E7Dt0B8IFkYAj1/UD3TqcdqIcfkMT7evE8+NBgg==
+ </SignatureValue>
+ <KeyInfo>
+ <X509Data>
+ <X509IssuerSerial>
+ <X509IssuerName>
+ CN=Another Transient CA,OU=X/Secure,O=Baltimore Technologies Ltd.,ST=Dublin,C=IE
+ </X509IssuerName>
+ <X509SerialNumber>1017792003066</X509SerialNumber>
+ </X509IssuerSerial>
+ </X509Data>
+ </KeyInfo>
+</Signature>
diff --git a/test/javax/xml/crypto/dsig/data/signature-x509-ski.xml b/test/javax/xml/crypto/dsig/data/signature-x509-ski.xml
new file mode 100644
index 0000000..c71bfce
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/signature-x509-ski.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+ <SignedInfo>
+ <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
+ <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1" />
+ <Reference URI="http://www.w3.org/TR/xml-stylesheet">
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>60NvZvtdTB+7UnlLp/H24p7h4bs=</DigestValue>
+ </Reference>
+ </SignedInfo>
+ <SignatureValue>
+ F9nEU1Us48iKTml8n7E4wt7HtFJ5gaLIgox0J9WbujGndW0oQJbeGg==
+ </SignatureValue>
+ <KeyInfo>
+ <X509Data>
+ <X509SKI>
+ hf10xKfSnIg=
+ </X509SKI>
+ </X509Data>
+ </KeyInfo>
+</Signature>
diff --git a/test/javax/xml/crypto/dsig/data/signature-x509-sn.xml b/test/javax/xml/crypto/dsig/data/signature-x509-sn.xml
new file mode 100644
index 0000000..d5b0808
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/signature-x509-sn.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+ <SignedInfo>
+ <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
+ <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1" />
+ <Reference URI="http://www.w3.org/TR/xml-stylesheet">
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>60NvZvtdTB+7UnlLp/H24p7h4bs=</DigestValue>
+ </Reference>
+ </SignedInfo>
+ <SignatureValue>
+ MUOjiqG0dbjvR6+qYYPL85nKSt2FeZGQBQkYudv48KyJhJLG1Bp+bA==
+ </SignatureValue>
+ <KeyInfo>
+ <X509Data>
+ <X509SubjectName>
+ CN=Badb,OU=X/Secure,O=Baltimore Technologies Ltd.,ST=Dublin,C=IE
+ </X509SubjectName>
+ </X509Data>
+ </KeyInfo>
+</Signature>
diff --git a/test/javax/xml/crypto/dsig/data/signature.xml b/test/javax/xml/crypto/dsig/data/signature.xml
new file mode 100644
index 0000000..504fbe1
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/signature.xml
@@ -0,0 +1,269 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Envelope [
+ <!ENTITY dsig 'http://www.w3.org/2000/09/xmldsig#'>
+ <!ENTITY c14n 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315'>
+ <!ENTITY xpath 'http://www.w3.org/TR/1999/REC-xpath-19991116'>
+ <!ENTITY xslt 'http://www.w3.org/TR/1999/REC-xslt-19991116'>
+ <!ATTLIST Notaries Id ID #IMPLIED>
+]>
+<!-- Preamble -->
+<Envelope xmlns:foo="http://example.org/foo" xmlns="http://example.org/usps">
+ <DearSir>foo</DearSir>
+ <Body>bar</Body>
+ <YoursSincerely>
+ <Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="signature">
+ <SignedInfo>
+ <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
+ <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1" />
+ <Reference URI="http://www.w3.org/TR/xml-stylesheet">
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>60NvZvtdTB+7UnlLp/H24p7h4bs=</DigestValue>
+ </Reference>
+ <Reference URI="http://www.w3.org/Signature/2002/04/xml-stylesheet.b64">
+ <Transforms>
+ <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#base64" />
+ </Transforms>
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>60NvZvtdTB+7UnlLp/H24p7h4bs=</DigestValue>
+ </Reference>
+ <Reference Type="http://www.w3.org/2000/09/xmldsig#Object" URI="#object-1">
+ <Transforms>
+ <Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
+ <XPath>
+ self::text()
+ </XPath>
+ </Transform>
+ </Transforms>
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>zyjp8GJOX69990Kkqw8ioPXGExk=</DigestValue>
+ </Reference>
+ <Reference Type="http://www.w3.org/2000/09/xmldsig#Object" URI="">
+ <Transforms>
+ <Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
+ <XPath xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
+ ancestor-or-self::dsig:SignedInfo
+ and
+ count(ancestor-or-self::dsig:Reference |
+ here()/ancestor::dsig:Reference[1]) >
+ count(ancestor-or-self::dsig:Reference)
+ or
+ count(ancestor-or-self::node() |
+ id('notaries')) =
+ count(ancestor-or-self::node())
+ </XPath>
+ </Transform>
+ </Transforms>
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>tQiE3GUKiBenPyp3J0Ei6rJMFv4=</DigestValue>
+ </Reference>
+ <Reference Type="http://www.w3.org/2000/09/xmldsig#Object" URI="#object-2">
+ <Transforms>
+ <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#base64" />
+ </Transforms>
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>zyjp8GJOX69990Kkqw8ioPXGExk=</DigestValue>
+ </Reference>
+ <Reference Type="http://www.w3.org/2000/09/xmldsig#Manifest" URI="#manifest-1">
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>qg4HFwsN+/WX32uH85WlJU9l45k=</DigestValue>
+ </Reference>
+ <Reference Type="http://www.w3.org/2000/09/xmldsig#SignatureProperties" URI="#signature-properties-1">
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>ETlEI3y7hvvAtMe9wQSz7LhbHEE=</DigestValue>
+ </Reference>
+ <Reference URI="">
+ <Transforms>
+ <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
+ </Transforms>
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>J/O0HhdaPXxx49fgGWMESL09GpA=</DigestValue>
+ </Reference>
+ <Reference URI="">
+ <Transforms>
+ <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
+ <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments" />
+ </Transforms>
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>J/O0HhdaPXxx49fgGWMESL09GpA=</DigestValue>
+ </Reference>
+ <Reference URI="#xpointer(/)">
+ <Transforms>
+ <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
+ </Transforms>
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>J/O0HhdaPXxx49fgGWMESL09GpA=</DigestValue>
+ </Reference>
+ <Reference URI="#xpointer(/)">
+ <Transforms>
+ <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
+ <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments" />
+ </Transforms>
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>MkL9CX8yeABBth1RChyPx58Ls8w=</DigestValue>
+ </Reference>
+ <Reference Type="http://www.w3.org/2000/09/xmldsig#Object" URI="#object-3">
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>yamSIokKmjA3hB/s3Fu07wDO3vM=</DigestValue>
+ </Reference>
+ <Reference Type="http://www.w3.org/2000/09/xmldsig#Object" URI="#object-3">
+ <Transforms>
+ <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments" />
+ </Transforms>
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>yamSIokKmjA3hB/s3Fu07wDO3vM=</DigestValue>
+ </Reference>
+ <Reference Type="http://www.w3.org/2000/09/xmldsig#Object" URI="#xpointer(id('object-3'))">
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>yamSIokKmjA3hB/s3Fu07wDO3vM=</DigestValue>
+ </Reference>
+ <Reference Type="http://www.w3.org/2000/09/xmldsig#Object" URI="#xpointer(id('object-3'))">
+ <Transforms>
+ <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments" />
+ </Transforms>
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>419CYgyTWOTGYGBhzieWklNf7Bk=</DigestValue>
+ </Reference>
+ <Reference URI="#reference-2">
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>VzK45P9Ksjqq5oXlKQpkGgB2CNY=</DigestValue>
+ </Reference>
+ <Reference Id="reference-1" URI="#manifest-reference-1">
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>7/9fR+NIDz9owc1Lfsxu1JBr8uo=</DigestValue>
+ </Reference>
+ <Reference Id="reference-2" URI="#reference-1">
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>qURlo3LSq4TWQtygBZJ0iXQ9E14=</DigestValue>
+ </Reference>
+ </SignedInfo>
+ <SignatureValue>
+ WvZUJAJ/3QNqzQvwne2vvy7U5Pck8ZZ5UTa6pIwR7GE+PoGi6A1kyw==
+ </SignatureValue>
+ <KeyInfo>
+ <RetrievalMethod Type="http://www.w3.org/2000/09/xmldsig#X509Data" URI="#object-4">
+ <Transforms>
+ <Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
+ <XPath xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
+ ancestor-or-self::dsig:X509Data
+ </XPath>
+ </Transform>
+ </Transforms>
+ </RetrievalMethod>
+ </KeyInfo>
+ <Object Id="object-1" MimeType="text/plain">I am the text.</Object>
+ <Object Encoding="http://www.w3.org/2000/09/xmldsig#base64" Id="object-2" MimeType="text/plain">SSBhbSB0aGUgdGV4dC4=</Object>
+ <Object Id="object-3">
+ <NonCommentandus xmlns=""><!-- Commentandum --></NonCommentandus>
+ </Object>
+ <Object>
+ <Manifest Id="manifest-1">
+ <Reference Id="manifest-reference-1" URI="http://www.w3.org/TR/xml-stylesheet">
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>60NvZvtdTB+7UnlLp/H24p7h4bs=</DigestValue>
+ </Reference>
+ <Reference URI="#reference-1">
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>qURlo3LSq4TWQtygBZJ0iXQ9E14=</DigestValue>
+ </Reference>
+ <Reference URI="#notaries">
+ <Transforms>
+ <Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116">
+ <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/TR/xhtml1/strict" exclude-result-prefixes="foo" version="1.0">
+ <xsl:output encoding="UTF-8" indent="no" method="xml" />
+ <xsl:template match="/">
+ <html>
+ <head>
+ <title>Notaries</title>
+ </head>
+ <body>
+ <table>
+ <xsl:for-each select="Notaries/Notary">
+ <tr>
+ <th>
+ <xsl:value-of select="@name" />
+ </th>
+ </tr>
+ </xsl:for-each>
+ </table>
+ </body>
+ </html>
+ </xsl:template>
+ </xsl:stylesheet>
+ </Transform>
+ <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
+ </Transforms>
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue>c7wq5XKos6RqNVJyFy7/fl6+sAs=</DigestValue>
+ </Reference>
+ </Manifest>
+ </Object>
+ <Object>
+ <SignatureProperties Id="signature-properties-1">
+ <SignatureProperty Target="#signature">
+ <SignerAddress xmlns="urn:demo"><IP>192.168.21.138</IP></SignerAddress>
+ </SignatureProperty>
+ </SignatureProperties>
+ </Object>
+ <Object Id="object-4">
+ <X509Data>
+ <X509SubjectName>
+ CN=Merlin Hughes,OU=X/Secure,O=Baltimore Technologies Ltd.,ST=Dublin,C=IE
+ </X509SubjectName>
+ <X509IssuerSerial>
+ <X509IssuerName>
+ CN=Transient CA,OU=X/Secure,O=Baltimore Technologies Ltd.,ST=Dublin,C=IE
+ </X509IssuerName>
+ <X509SerialNumber>1017788370348</X509SerialNumber>
+ </X509IssuerSerial>
+ <X509Certificate>
+ MIIDUDCCAxCgAwIBAgIGAOz46g2sMAkGByqGSM44BAMwbjELMAkGA1UEBhMCSUUx
+ DzANBgNVBAgTBkR1YmxpbjEkMCIGA1UEChMbQmFsdGltb3JlIFRlY2hub2xvZ2ll
+ cyBMdGQuMREwDwYDVQQLEwhYL1NlY3VyZTEVMBMGA1UEAxMMVHJhbnNpZW50IENB
+ MB4XDTAyMDQwMjIyNTkzMFoXDTEyMDQwMjIxNTkyNVowbzELMAkGA1UEBhMCSUUx
+ DzANBgNVBAgTBkR1YmxpbjEkMCIGA1UEChMbQmFsdGltb3JlIFRlY2hub2xvZ2ll
+ cyBMdGQuMREwDwYDVQQLEwhYL1NlY3VyZTEWMBQGA1UEAxMNTWVybGluIEh1Z2hl
+ czCCAbcwggEsBgcqhkjOOAQBMIIBHwKBgQDd454C+qcTIWlb65NKCt2PtguNpOSn
+ Id5woUigu7xBk2QZNAjVyIhMEfSWp8iR0IdKLx+JQLcNOrcn0Wwl5/hhW0MXsmlS
+ 8dM5Cq2rtmDHooLxbGTPqtALE6vsXQCk5iLz3MtGh7gyQMZ7q7HT5a3I5NChUgY1
+ MMNQVetRA1susQIVAIQy3BStBjvx89Wq8Tjr7IDP1S8lAoGBAJ58e4W3VqMxm7Zx
+ YJ2xZ6KX0Ze10WnKZDyURn+T9iFIFbKRFElKDeotXwwXwYON8yre3ZRGkC+2+fiU
+ 2bdzIWTT6LMbIMVbk+07P4OZOxJ6XWL9GuYcOQcNvX42xh34DPHdq4XdlItMR25N
+ A+OdZ4S8VVrpb4jkj4cyir1628kgA4GEAAKBgHH2KYoaQEHnqWzRUuDAG0EYXV6Q
+ 4ucC68MROYSL6GKqNS/AUFbvH2NUxQD7aGntYgYPxiCcj94i38rgSWg7ySSz99MA
+ R/Yv7OSd+uej3r6TlXU34u++xYvRo+sv4m9lb/jmXyZJKeC+dPqeU1IT5kCybURL
+ ILZfrZyDsiU/vhvVozowODAOBgNVHQ8BAf8EBAMCB4AwEQYDVR0OBAoECIatY7SE
+ lXEOMBMGA1UdIwQMMAqACIOGPkB2MuKTMAkGByqGSM44BAMDLwAwLAIUSvT02iQj
+ Q5da4Wpe0Bvs7GuCcVsCFCEcQpbjUfnxXFXNWiFyQ49ZrWqn
+ </X509Certificate>
+ <X509Certificate>
+ MIIDSzCCAwugAwIBAgIGAOz46fwJMAkGByqGSM44BAMwbjELMAkGA1UEBhMCSUUx
+ DzANBgNVBAgTBkR1YmxpbjEkMCIGA1UEChMbQmFsdGltb3JlIFRlY2hub2xvZ2ll
+ cyBMdGQuMREwDwYDVQQLEwhYL1NlY3VyZTEVMBMGA1UEAxMMVHJhbnNpZW50IENB
+ MB4XDTAyMDQwMjIyNTkyNVoXDTEyMDQwMjIxNTkyNVowbjELMAkGA1UEBhMCSUUx
+ DzANBgNVBAgTBkR1YmxpbjEkMCIGA1UEChMbQmFsdGltb3JlIFRlY2hub2xvZ2ll
+ cyBMdGQuMREwDwYDVQQLEwhYL1NlY3VyZTEVMBMGA1UEAxMMVHJhbnNpZW50IENB
+ MIIBtzCCASwGByqGSM44BAEwggEfAoGBAN3jngL6pxMhaVvrk0oK3Y+2C42k5Kch
+ 3nChSKC7vEGTZBk0CNXIiEwR9JanyJHQh0ovH4lAtw06tyfRbCXn+GFbQxeyaVLx
+ 0zkKrau2YMeigvFsZM+q0AsTq+xdAKTmIvPcy0aHuDJAxnursdPlrcjk0KFSBjUw
+ w1BV61EDWy6xAhUAhDLcFK0GO/Hz1arxOOvsgM/VLyUCgYEAnnx7hbdWozGbtnFg
+ nbFnopfRl7XRacpkPJRGf5P2IUgVspEUSUoN6i1fDBfBg43zKt7dlEaQL7b5+JTZ
+ t3MhZNPosxsgxVuT7Ts/g5k7EnpdYv0a5hw5Bw29fjbGHfgM8d2rhd2Ui0xHbk0D
+ 451nhLxVWulviOSPhzKKvXrbySADgYQAAoGAfag+HCABIJadDD9Aarhgc2QR3Lp7
+ PpMOh0lAwLiIsvkO4UlbeOS0IJC8bcqLjM1fVw6FGSaxmq+4y1ag2m9k6IdE0Qh5
+ NxB/xFkmdwqXFRIJVp44OeUygB47YK76NmUIYG3DdfiPPU3bqzjvtOtETiCHvo25
+ 4D6UjwPpYErXRUajNjA0MA4GA1UdDwEB/wQEAwICBDAPBgNVHRMECDAGAQH/AgEA
+ MBEGA1UdDgQKBAiDhj5AdjLikzAJBgcqhkjOOAQDAy8AMCwCFELu0nuweqW7Wf0s
+ gk/CAGGL0BGKAhRNdgQGr5iyZKoH4oqPm0VJ9TjXLg==
+ </X509Certificate>
+ </X509Data>
+ </Object>
+ </Signature>
+ </YoursSincerely>
+ <PostScript>bar</PostScript>
+ <Notaries xmlns="" Id="notaries">
+ <Notary name="Great, A. T." />
+ <Notary name="Hun, A. T." />
+ </Notaries>
+ <!-- Commentary -->
+</Envelope>
+<!-- Postamble -->
diff --git a/test/javax/xml/crypto/dsig/data/xml-stylesheet b/test/javax/xml/crypto/dsig/data/xml-stylesheet
new file mode 100644
index 0000000..de8e119
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/xml-stylesheet
@@ -0,0 +1,341 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+<title>Associating Style Sheets with XML documents</title>
+<link rel="stylesheet" type="text/css" href="http://www.w3.org/StyleSheets/TR/W3C-REC">
+<style type="text/css">code { font-family: monospace }</style>
+</head>
+<body>
+<div class="head">
+<a href="http://www.w3.org/"><img src="http://www.w3.org/Icons/WWW/w3c_home" alt="W3C" height="48" width="72"></a>
+<h1>Associating Style Sheets with XML documents<br>Version 1.0</h1>
+<h2>W3C Recommendation 29 June 1999</h2>
+<dl>
+<dt>This version:</dt>
+<dd>
+<a href="http://www.w3.org/1999/06/REC-xml-stylesheet-19990629">http://www.w3.org/1999/06/REC-xml-stylesheet-19990629</a>
+<br>
+</dd>
+<dt>Latest version:</dt>
+<dd>
+<a href="http://www.w3.org/TR/xml-stylesheet">http://www.w3.org/TR/xml-stylesheet</a>
+<br>
+</dd>
+<dt>Previous version:</dt>
+<dd>
+<a href="http://www.w3.org/TR/1999/xml-stylesheet-19990428">http://www.w3.org/TR/1999/xml-stylesheet-19990428</a>
+<br>
+</dd>
+<dt>Editor:</dt>
+<dd>
+
+James Clark
+<a href="mailto:jjc@jclark.com"><jjc@jclark.com></a>
+<br>
+</dd>
+</dl>
+<p class="copyright">
+<a href="http://www.w3.org/Consortium/Legal/ipr-notice.html#Copyright">
+ Copyright</a> © 1999 <a href="http://www.w3.org">W3C</a>
+ (<a href="http://www.lcs.mit.edu">MIT</a>,
+ <a href="http://www.inria.fr/">INRIA</a>,
+ <a href="http://www.keio.ac.jp/">Keio</a> ), All Rights Reserved. W3C
+ <a href="http://www.w3.org/Consortium/Legal/ipr-notice.html#Legal Disclaimer">liability,</a><a href="http://www.w3.org/Consortium/Legal/ipr-notice.html#W3C Trademarks">trademark</a>,
+ <a href="http://www.w3.org/Consortium/Legal/copyright-documents.html">document use </a>and
+ <a href="http://www.w3.org/Consortium/Legal/copyright-software.html">software licensing </a>rules apply.
+ </p>
+<hr title="Separator for header">
+</div>
+<h2>
+<a name="abstract">Abstract</a>
+</h2>
+
+<p>This document allows a style sheet to be associated with an XML
+document by including one or more processing instructions with a
+target of <code>xml-stylesheet</code> in the document's prolog.</p>
+
+<h2>
+<a name="status">Status of this document</a>
+</h2>
+
+<p>This document has been reviewed by W3C Members and other interested
+parties and has been endorsed by the Director as a W3C <a href="http://www.w3.org/Consortium/Process/#RecsW3C">Recommendation</a>. It
+is a stable document and may be used as reference material or cited as
+a normative reference from other documents. W3C's role in making the
+Recommendation is to draw attention to the specification and to
+promote its widespread deployment. This enhances the functionality and
+interoperability of the Web.</p>
+
+<p>The list of known errors in this specifications is available at
+<a href="http://www.w3.org/1999/06/REC-xml-stylesheet-19990629/errata">http://www.w3.org/TR/1999/xml-stylesheet-19990629/errata</a>.</p>
+
+<p>Comments on this specification may be sent to <<a href="mailto:www-xml-stylesheet-comments@w3.org">www-xml-stylesheet-comments@w3.org</a>>. The archive of public
+comments is available at <a href="http://www.w3.org/Archives/Public/www-xml-stylesheet-comments">http://w3.org/Archives/Public/www-xml-stylesheet-comments</a>.</p>
+
+<p>A list of current W3C Recommendations and other technical documents
+can be found at <a href="http://www.w3.org/TR">http://www.w3.org/TR</a>.</p>
+
+<p>The Working Group expects additional mechanisms for linking style
+sheets to XML document to be defined in a future specification.</p>
+
+<p>The use of XML processing instructions in this specification should
+not be taken as a precedent. The W3C does not anticipate recommending
+the use of processing instructions in any future specification. The
+<a href="#rationale">Rationale</a> explains why they were used in
+this specification.</p>
+
+<p>This document was produced as part of the <a href="http://www.w3.org/XML/Activity">W3C XML Activity</a>.</p>
+
+
+<h2>
+<a name="contents">Table of contents</a>
+</h2>1 <a href="#The xml-stylesheet processing instruction">The xml-stylesheet processing instruction</a>
+<br>
+<h3>Appendices</h3>A <a href="#References">References</a>
+<br>B <a href="#rationale">Rationale</a>
+<br>
+<hr>
+
+<h2>
+<a name="The xml-stylesheet processing instruction"></a>1 The <code>xml-stylesheet</code> processing instruction</h2>
+
+<p>Style Sheets can be associated with an XML<a href="#XML">[XML10]</a>
+document by using a processing instruction whose target is
+<code>xml-stylesheet</code>. This processing instruction follows the
+behaviour of the HTML 4.0 <code><LINK
+REL="stylesheet"></code><a href="#HTML">[HTML40]</a>.</p>
+
+<p>The <code>xml-stylesheet</code> processing instruction is parsed in
+the same way as a start-tag, with the exception that entities other
+than predefined entities must not be referenced.</p>
+
+<p>The following grammar is given using the same notation as the
+grammar in the XML Recommendation<a href="#XML">[XML10]</a>. Symbols in the
+grammar that are not defined here are defined in the XML
+Recommendation.</p>
+
+<h5>xml-stylesheet processing instruction</h5>
+<table class="scrap">
+<tbody>
+<tr valign="baseline">
+<td>
+<a name="NT-StyleSheetPI"></a>[1] </td>
+<td>StyleSheetPI</td>
+<td> ::= </td>
+<td>'<?xml-stylesheet' (<a href="http://www.w3.org/TR/REC-xml#NT-S">S</a> <a href="#NT-PseudoAtt">PseudoAtt</a>)* <a href="http://www.w3.org/TR/REC-xml#NT-S">S</a>? '?>'</td>
+<td>
+</td>
+</tr>
+<tr valign="baseline">
+<td>
+<a name="NT-PseudoAtt"></a>[2] </td>
+<td>PseudoAtt</td>
+<td> ::= </td>
+<td>
+<a href="http://www.w3.org/TR/REC-xml#NT-Name">Name</a> <a href="http://www.w3.org/TR/REC-xml#NT-S">S</a>? '=' <a href="http://www.w3.org/TR/REC-xml#NT-S">S</a>? <a href="#NT-PseudoAttValue">PseudoAttValue</a>
+</td>
+<td>
+</td>
+</tr>
+<tr valign="baseline">
+<td>
+<a name="NT-PseudoAttValue"></a>[3] </td>
+<td>PseudoAttValue</td>
+<td> ::= </td>
+<td>('"' ([^"<&] | <a href="http://www.w3.org/TR/REC-xml#NT-CharRef">CharRef</a> | <a href="#NT-PredefEntityRef">PredefEntityRef</a>)* '"'</td>
+<td>
+</td>
+</tr>
+<tr valign="baseline">
+<td>
+</td>
+<td>
+</td>
+<td>
+</td>
+<td>| "'" ([^'<&] | <a href="http://www.w3.org/TR/REC-xml#NT-CharRef">CharRef</a> | <a href="#NT-PredefEntityRef">PredefEntityRef</a>)* "'")</td>
+<td>
+</td>
+</tr>
+<tr valign="baseline">
+<td>
+</td>
+<td>
+</td>
+<td>
+</td>
+<td>- (<a href="http://www.w3.org/TR/REC-xml#NT-Char">Char</a>* '?>' <a href="http://www.w3.org/TR/REC-xml#NT-Char">Char</a>*)</td>
+<td>
+</td>
+</tr>
+<tr valign="baseline">
+<td>
+<a name="NT-PredefEntityRef"></a>[4] </td>
+<td>PredefEntityRef</td>
+<td> ::= </td>
+<td>'&amp;' | '&lt;' | '&gt;' | '&quot;' | '&apos;'</td>
+<td>
+</td>
+</tr>
+</tbody>
+</table>
+
+<p>In <a href="#NT-PseudoAttValue">PseudoAttValue</a>, a <a href="http://www.w3.org/TR/REC-xml#NT-CharRef">CharRef</a> or a <a href="#NT-PredefEntityRef">PredefEntityRef</a> is interpreted in the
+same manner as in a normal XML attribute value. The actual value of
+the pseudo-attribute is the value after each reference is replaced by
+the character it references. This replacement is not performed
+automatically by an XML processor.</p>
+
+<p>The <code>xml-stylesheet</code> processing instruction is allowed
+only in the prolog of an XML document. The syntax of XML constrains
+where processing instructions are allowed in the prolog; the
+<code>xml-stylesheet</code> processing instruction is allowed anywhere
+in the prolog that meets these constraints.</p>
+
+<blockquote>
+<b>NOTE: </b>If the <code>xml-stylesheet</code> processing instruction
+occurs in the external DTD subset or in a parameter entity, it is
+possible that it may not be processed by a non-validating XML
+processor (see <a href="#XML">[XML10]</a>).</blockquote>
+
+<p>The following pseudo attributes are defined</p>
+
+<pre>href CDATA #REQUIRED
+type CDATA #REQUIRED
+title CDATA #IMPLIED
+media CDATA #IMPLIED
+charset CDATA #IMPLIED
+alternate (yes|no) "no"</pre>
+
+<p>The semantics of the pseudo-attributes are exactly as with
+<code><LINK REL="stylesheet"></code> in HTML 4.0, with the
+exception of the <code>alternate</code> pseudo-attribute. If
+<code>alternate="yes"</code> is specified, then the processing
+instruction has the semantics of <code><LINK REL="alternate
+stylesheet"></code> instead of <code><LINK
+REL="stylesheet"></code>.</p>
+
+<blockquote>
+<b>NOTE: </b>Since the value of the <code>href</code> attribute is a URI
+reference, it may be a relative URI and it may contain a fragment
+identifier. In particular the URI reference may contain only a
+fragment identifier. Such a URI reference is a reference to a part of
+the document containing the <code>xml-stylesheet</code> processing
+instruction (see <a href="#RFC2396">[RFC2396]</a>). The consequence is that the
+<code>xml-stylesheet</code> processing instruction allows style sheets
+to be embedded in the same document as the <code>xml-stylesheet</code>
+processing instruction.</blockquote>
+
+<p>In some cases, style sheets may be linked with an XML document by
+means external to the document. For example, earlier versions of HTTP
+<a href="#RFC2068">[RFC2068]</a> (section 19.6.2.4) allowed style sheets to be
+associated with XML documents by means of the <code>Link</code>
+header. Any links to style sheets that are specified externally to the
+document are considered to occur before the links specified by the
+<code>xml-stylesheet</code> processing instructions. This is the same
+as in HTML 4.0 (see <a href="http://www.w3.org/TR/REC-html40/present/styles.html#h-14.6">section
+14.6</a>).</p>
+
+<p>Here are some examples from HTML 4.0 with the corresponding
+processing instruction:</p>
+
+<pre><LINK href="mystyle.css" rel="style sheet" type="text/css">
+<?xml-stylesheet href="mystyle.css" type="text/css"?>
+
+<LINK href="mystyle.css" title="Compact" rel="stylesheet"
+type="text/css">
+<?xml-stylesheet href="mystyle.css" title="Compact" type="text/css"?>
+
+<LINK href="mystyle.css" title="Medium" rel="alternate stylesheet"
+type="text/css">
+<?xml-stylesheet alternate="yes" href="mystyle.css" title="Medium"
+type="text/css"?></pre>
+
+<p>Multiple <code>xml-stylesheet</code> processing instructions are
+also allowed with exactly the same semantics as with <code>LINK
+REL="stylesheet"</code>. For example,</p>
+
+<pre><LINK rel="alternate stylesheet" title="compact" href="small-base.css"
+type="text/css">
+<LINK rel="alternate stylesheet" title="compact" href="small-extras.css"
+type="text/css">
+<LINK rel="alternate stylesheet" title="big print" href="bigprint.css"
+type="text/css">
+<LINK rel="stylesheet" href="common.css" type="text/css"></pre>
+
+<p>would be equivalent to:</p>
+
+<pre><?xml-stylesheet alternate="yes" title="compact" href="small-base.css"
+type="text/css"?>
+<?xml-stylesheet alternate="yes" title="compact" href="small-extras.css"
+type="text/css"?>
+<?xml-stylesheet alternate="yes" title="big print" href="bigprint.css"
+type="text/css"?>
+<?xml-stylesheet href="common.css" type="text/css"?></pre>
+
+
+
+<hr title="Separator from footer">
+
+<h2>
+<a name="References"></a>A References</h2>
+
+<dl>
+
+<dt>
+<a name="HTML">HTML40</a>
+</dt>
+<dd>World Wide Web
+Consortium. <i>HTML 4.0 Specification.</i> W3C Recommendation. See
+<a href="http://www.w3.org/TR/REC-html40">http://www.w3.org/TR/REC-html40</a>
+</dd>
+
+<dt>
+<a name="RFC2068">RFC2068</a>
+</dt>
+<dd>R. Fielding, J. Gettys, J. Mogul,
+H. Frystyk Nielsen, and T. Berners-Lee. <i>Hypertext Transfer
+Protocol -- HTTP/1.1.</i>. IETF RFC 2068. See <a href="http://www.ietf.org/rfc/rfc2068.txt">http://www.ietf.org/rfc/rfc2068.txt</a>.</dd>
+
+<dt>
+<a name="RFC2396">RFC2396</a>
+</dt>
+<dd>T. Berners-Lee, R. Fielding, and
+L. Masinter. <i>Uniform Resource Identifiers (URI): Generic
+Syntax</i>. IETF RFC 2396. See <a href="http://www.ietf.org/rfc/rfc2396.txt">http://www.ietf.org/rfc/rfc2396.txt</a>.</dd>
+
+<dt>
+<a name="XML">XML10</a>
+</dt>
+<dd>World Wide Web Consortium. <i>Extensible
+Markup Language (XML) 1.0.</i> W3C Recommendation. See <a href="http://www.w3.org/TR/1998/REC-xml-19980210">http://www.w3.org/TR/1998/REC-xml-19980210</a>
+</dd>
+
+</dl>
+
+
+
+
+<h2>
+<a name="rationale"></a>B Rationale</h2>
+
+<p>There was an urgent requirement for a specification for style sheet
+linking that could be completed in time for the next release from
+major browser vendors. Only by choosing a simple mechanism closely
+based on a proven existing mechanism could the specification be
+completed in time to meet this requirement.</p>
+
+<p>Use of a processing instruction avoids polluting the main document
+structure with application specific processing information.</p>
+
+<p>The mechanism chosen for this version of the specification is not a
+constraint on the additional mechanisms planned for future versions.
+There is no expectation that these will use processing instructions;
+indeed they may not include the linking information in the source
+document.</p>
+
+
+
+
+</body>
+</html>
diff --git a/test/javax/xml/crypto/dsig/data/xml-stylesheet.b64 b/test/javax/xml/crypto/dsig/data/xml-stylesheet.b64
new file mode 100644
index 0000000..eb9a11a
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/data/xml-stylesheet.b64
@@ -0,0 +1,274 @@
+PCFET0NUWVBFIGh0bWwgUFVCTElDICItLy9XM0MvL0RURCBIVE1MIDQuMCBUcmFu
+c2l0aW9uYWwvL0VOIj4KPGh0bWw+CjxoZWFkPgo8dGl0bGU+QXNzb2NpYXRpbmcg
+U3R5bGUgU2hlZXRzIHdpdGggWE1MIGRvY3VtZW50czwvdGl0bGU+CjxsaW5rIHJl
+bD0ic3R5bGVzaGVldCIgdHlwZT0idGV4dC9jc3MiIGhyZWY9Imh0dHA6Ly93d3cu
+dzMub3JnL1N0eWxlU2hlZXRzL1RSL1czQy1SRUMiPgo8c3R5bGUgdHlwZT0idGV4
+dC9jc3MiPmNvZGUgeyBmb250LWZhbWlseTogbW9ub3NwYWNlIH08L3N0eWxlPgo8
+L2hlYWQ+Cjxib2R5Pgo8ZGl2IGNsYXNzPSJoZWFkIj4KPGEgaHJlZj0iaHR0cDov
+L3d3dy53My5vcmcvIj48aW1nIHNyYz0iaHR0cDovL3d3dy53My5vcmcvSWNvbnMv
+V1dXL3czY19ob21lIiBhbHQ9IlczQyIgaGVpZ2h0PSI0OCIgd2lkdGg9IjcyIj48
+L2E+CjxoMT5Bc3NvY2lhdGluZyBTdHlsZSBTaGVldHMgd2l0aCBYTUwgZG9jdW1l
+bnRzPGJyPlZlcnNpb24gMS4wPC9oMT4KPGgyPlczQyBSZWNvbW1lbmRhdGlvbiAy
+OSBKdW5lIDE5OTk8L2gyPgo8ZGw+CjxkdD5UaGlzIHZlcnNpb246PC9kdD4KPGRk
+Pgo8YSBocmVmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzA2L1JFQy14bWwtc3R5
+bGVzaGVldC0xOTk5MDYyOSI+aHR0cDovL3d3dy53My5vcmcvMTk5OS8wNi9SRUMt
+eG1sLXN0eWxlc2hlZXQtMTk5OTA2Mjk8L2E+Cjxicj4KPC9kZD4KPGR0PkxhdGVz
+dCB2ZXJzaW9uOjwvZHQ+CjxkZD4KPGEgaHJlZj0iaHR0cDovL3d3dy53My5vcmcv
+VFIveG1sLXN0eWxlc2hlZXQiPmh0dHA6Ly93d3cudzMub3JnL1RSL3htbC1zdHls
+ZXNoZWV0PC9hPgo8YnI+CjwvZGQ+CjxkdD5QcmV2aW91cyB2ZXJzaW9uOjwvZHQ+
+CjxkZD4KPGEgaHJlZj0iaHR0cDovL3d3dy53My5vcmcvVFIvMTk5OS94bWwtc3R5
+bGVzaGVldC0xOTk5MDQyOCI+aHR0cDovL3d3dy53My5vcmcvVFIvMTk5OS94bWwt
+c3R5bGVzaGVldC0xOTk5MDQyODwvYT4KPGJyPgo8L2RkPgo8ZHQ+RWRpdG9yOjwv
+ZHQ+CjxkZD4KCkphbWVzIENsYXJrCjxhIGhyZWY9Im1haWx0bzpqamNAamNsYXJr
+LmNvbSI+Jmx0O2pqY0BqY2xhcmsuY29tJmd0OzwvYT4KPGJyPgo8L2RkPgo8L2Rs
+Pgo8cCBjbGFzcz0iY29weXJpZ2h0Ij4KPGEgaHJlZj0iaHR0cDovL3d3dy53My5v
+cmcvQ29uc29ydGl1bS9MZWdhbC9pcHItbm90aWNlLmh0bWwjQ29weXJpZ2h0Ij4K
+CQlDb3B5cmlnaHQ8L2E+ICZuYnNwOyZjb3B5OyZuYnNwOyAxOTk5IDxhIGhyZWY9
+Imh0dHA6Ly93d3cudzMub3JnIj5XM0M8L2E+CgkJKDxhIGhyZWY9Imh0dHA6Ly93
+d3cubGNzLm1pdC5lZHUiPk1JVDwvYT4sCgkJPGEgaHJlZj0iaHR0cDovL3d3dy5p
+bnJpYS5mci8iPklOUklBPC9hPiwKCQk8YSBocmVmPSJodHRwOi8vd3d3LmtlaW8u
+YWMuanAvIj5LZWlvPC9hPiApLCBBbGwgUmlnaHRzIFJlc2VydmVkLiBXM0MKCQk8
+YSBocmVmPSJodHRwOi8vd3d3LnczLm9yZy9Db25zb3J0aXVtL0xlZ2FsL2lwci1u
+b3RpY2UuaHRtbCNMZWdhbCBEaXNjbGFpbWVyIj5saWFiaWxpdHksPC9hPjxhIGhy
+ZWY9Imh0dHA6Ly93d3cudzMub3JnL0NvbnNvcnRpdW0vTGVnYWwvaXByLW5vdGlj
+ZS5odG1sI1czQyBUcmFkZW1hcmtzIj50cmFkZW1hcms8L2E+LAoJCTxhIGhyZWY9
+Imh0dHA6Ly93d3cudzMub3JnL0NvbnNvcnRpdW0vTGVnYWwvY29weXJpZ2h0LWRv
+Y3VtZW50cy5odG1sIj5kb2N1bWVudCB1c2UgPC9hPmFuZAoJCTxhIGhyZWY9Imh0
+dHA6Ly93d3cudzMub3JnL0NvbnNvcnRpdW0vTGVnYWwvY29weXJpZ2h0LXNvZnR3
+YXJlLmh0bWwiPnNvZnR3YXJlIGxpY2Vuc2luZyA8L2E+cnVsZXMgYXBwbHkuCgk8
+L3A+CjxociB0aXRsZT0iU2VwYXJhdG9yIGZvciBoZWFkZXIiPgo8L2Rpdj4KPGgy
+Pgo8YSBuYW1lPSJhYnN0cmFjdCI+QWJzdHJhY3Q8L2E+CjwvaDI+Cgo8cD5UaGlz
+IGRvY3VtZW50IGFsbG93cyBhIHN0eWxlIHNoZWV0IHRvIGJlIGFzc29jaWF0ZWQg
+d2l0aCBhbiBYTUwKZG9jdW1lbnQgYnkgaW5jbHVkaW5nIG9uZSBvciBtb3JlIHBy
+b2Nlc3NpbmcgaW5zdHJ1Y3Rpb25zIHdpdGggYQp0YXJnZXQgb2YgPGNvZGU+eG1s
+LXN0eWxlc2hlZXQ8L2NvZGU+IGluIHRoZSBkb2N1bWVudCdzIHByb2xvZy48L3A+
+Cgo8aDI+CjxhIG5hbWU9InN0YXR1cyI+U3RhdHVzIG9mIHRoaXMgZG9jdW1lbnQ8
+L2E+CjwvaDI+Cgo8cD5UaGlzIGRvY3VtZW50IGhhcyBiZWVuIHJldmlld2VkIGJ5
+IFczQyBNZW1iZXJzIGFuZCBvdGhlciBpbnRlcmVzdGVkCnBhcnRpZXMgYW5kIGhh
+cyBiZWVuIGVuZG9yc2VkIGJ5IHRoZSBEaXJlY3RvciBhcyBhIFczQyA8YSBocmVm
+PSJodHRwOi8vd3d3LnczLm9yZy9Db25zb3J0aXVtL1Byb2Nlc3MvI1JlY3NXM0Mi
+PlJlY29tbWVuZGF0aW9uPC9hPi4gSXQKaXMgYSBzdGFibGUgZG9jdW1lbnQgYW5k
+IG1heSBiZSB1c2VkIGFzIHJlZmVyZW5jZSBtYXRlcmlhbCBvciBjaXRlZCBhcwph
+IG5vcm1hdGl2ZSByZWZlcmVuY2UgZnJvbSBvdGhlciBkb2N1bWVudHMuIFczQydz
+IHJvbGUgaW4gbWFraW5nIHRoZQpSZWNvbW1lbmRhdGlvbiBpcyB0byBkcmF3IGF0
+dGVudGlvbiB0byB0aGUgc3BlY2lmaWNhdGlvbiBhbmQgdG8KcHJvbW90ZSBpdHMg
+d2lkZXNwcmVhZCBkZXBsb3ltZW50LiBUaGlzIGVuaGFuY2VzIHRoZSBmdW5jdGlv
+bmFsaXR5IGFuZAppbnRlcm9wZXJhYmlsaXR5IG9mIHRoZSBXZWIuPC9wPgoKPHA+
+VGhlIGxpc3Qgb2Yga25vd24gZXJyb3JzIGluIHRoaXMgc3BlY2lmaWNhdGlvbnMg
+aXMgYXZhaWxhYmxlIGF0CjxhIGhyZWY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkv
+MDYvUkVDLXhtbC1zdHlsZXNoZWV0LTE5OTkwNjI5L2VycmF0YSI+aHR0cDovL3d3
+dy53My5vcmcvVFIvMTk5OS94bWwtc3R5bGVzaGVldC0xOTk5MDYyOS9lcnJhdGE8
+L2E+LjwvcD4KCjxwPkNvbW1lbnRzIG9uIHRoaXMgc3BlY2lmaWNhdGlvbiBtYXkg
+YmUgc2VudCB0byAmbHQ7PGEgaHJlZj0ibWFpbHRvOnd3dy14bWwtc3R5bGVzaGVl
+dC1jb21tZW50c0B3My5vcmciPnd3dy14bWwtc3R5bGVzaGVldC1jb21tZW50c0B3
+My5vcmc8L2E+Jmd0Oy4gVGhlIGFyY2hpdmUgb2YgcHVibGljCmNvbW1lbnRzIGlz
+IGF2YWlsYWJsZSBhdCA8YSBocmVmPSJodHRwOi8vd3d3LnczLm9yZy9BcmNoaXZl
+cy9QdWJsaWMvd3d3LXhtbC1zdHlsZXNoZWV0LWNvbW1lbnRzIj5odHRwOi8vdzMu
+b3JnL0FyY2hpdmVzL1B1YmxpYy93d3cteG1sLXN0eWxlc2hlZXQtY29tbWVudHM8
+L2E+LjwvcD4KCjxwPkEgbGlzdCBvZiBjdXJyZW50IFczQyBSZWNvbW1lbmRhdGlv
+bnMgYW5kIG90aGVyIHRlY2huaWNhbCBkb2N1bWVudHMKY2FuIGJlIGZvdW5kIGF0
+IDxhIGhyZWY9Imh0dHA6Ly93d3cudzMub3JnL1RSIj5odHRwOi8vd3d3LnczLm9y
+Zy9UUjwvYT4uPC9wPgoKPHA+VGhlIFdvcmtpbmcgR3JvdXAgZXhwZWN0cyBhZGRp
+dGlvbmFsIG1lY2hhbmlzbXMgZm9yIGxpbmtpbmcgc3R5bGUKc2hlZXRzIHRvIFhN
+TCBkb2N1bWVudCB0byBiZSBkZWZpbmVkIGluIGEgZnV0dXJlIHNwZWNpZmljYXRp
+b24uPC9wPgoKPHA+VGhlIHVzZSBvZiBYTUwgcHJvY2Vzc2luZyBpbnN0cnVjdGlv
+bnMgaW4gdGhpcyBzcGVjaWZpY2F0aW9uIHNob3VsZApub3QgYmUgdGFrZW4gYXMg
+YSBwcmVjZWRlbnQuICBUaGUgVzNDIGRvZXMgbm90IGFudGljaXBhdGUgcmVjb21t
+ZW5kaW5nCnRoZSB1c2Ugb2YgcHJvY2Vzc2luZyBpbnN0cnVjdGlvbnMgaW4gYW55
+IGZ1dHVyZSBzcGVjaWZpY2F0aW9uLiAgVGhlCjxhIGhyZWY9IiNyYXRpb25hbGUi
+PlJhdGlvbmFsZTwvYT4gZXhwbGFpbnMgd2h5IHRoZXkgd2VyZSB1c2VkIGluCnRo
+aXMgc3BlY2lmaWNhdGlvbi48L3A+Cgo8cD5UaGlzIGRvY3VtZW50IHdhcyBwcm9k
+dWNlZCBhcyBwYXJ0IG9mIHRoZSA8YSBocmVmPSJodHRwOi8vd3d3LnczLm9yZy9Y
+TUwvQWN0aXZpdHkiPlczQyBYTUwgQWN0aXZpdHk8L2E+LjwvcD4KCgo8aDI+Cjxh
+IG5hbWU9ImNvbnRlbnRzIj5UYWJsZSBvZiBjb250ZW50czwvYT4KPC9oMj4xIDxh
+IGhyZWY9IiNUaGUgeG1sLXN0eWxlc2hlZXQgcHJvY2Vzc2luZyBpbnN0cnVjdGlv
+biI+VGhlIHhtbC1zdHlsZXNoZWV0IHByb2Nlc3NpbmcgaW5zdHJ1Y3Rpb248L2E+
+Cjxicj4KPGgzPkFwcGVuZGljZXM8L2gzPkEgPGEgaHJlZj0iI1JlZmVyZW5jZXMi
+PlJlZmVyZW5jZXM8L2E+Cjxicj5CIDxhIGhyZWY9IiNyYXRpb25hbGUiPlJhdGlv
+bmFsZTwvYT4KPGJyPgo8aHI+Cgo8aDI+CjxhIG5hbWU9IlRoZSB4bWwtc3R5bGVz
+aGVldCBwcm9jZXNzaW5nIGluc3RydWN0aW9uIj48L2E+MSBUaGUgPGNvZGU+eG1s
+LXN0eWxlc2hlZXQ8L2NvZGU+IHByb2Nlc3NpbmcgaW5zdHJ1Y3Rpb248L2gyPgoK
+PHA+U3R5bGUgU2hlZXRzIGNhbiBiZSBhc3NvY2lhdGVkIHdpdGggYW4gWE1MPGEg
+aHJlZj0iI1hNTCI+W1hNTDEwXTwvYT4KZG9jdW1lbnQgYnkgdXNpbmcgYSBwcm9j
+ZXNzaW5nIGluc3RydWN0aW9uIHdob3NlIHRhcmdldCBpcwo8Y29kZT54bWwtc3R5
+bGVzaGVldDwvY29kZT4uICBUaGlzIHByb2Nlc3NpbmcgaW5zdHJ1Y3Rpb24gZm9s
+bG93cyB0aGUKYmVoYXZpb3VyIG9mIHRoZSBIVE1MIDQuMCA8Y29kZT4mbHQ7TElO
+SwpSRUw9InN0eWxlc2hlZXQiJmd0OzwvY29kZT48YSBocmVmPSIjSFRNTCI+W0hU
+TUw0MF08L2E+LjwvcD4KCjxwPlRoZSA8Y29kZT54bWwtc3R5bGVzaGVldDwvY29k
+ZT4gcHJvY2Vzc2luZyBpbnN0cnVjdGlvbiBpcyBwYXJzZWQgaW4KdGhlIHNhbWUg
+d2F5IGFzIGEgc3RhcnQtdGFnLCB3aXRoIHRoZSBleGNlcHRpb24gdGhhdCBlbnRp
+dGllcyBvdGhlcgp0aGFuIHByZWRlZmluZWQgZW50aXRpZXMgbXVzdCBub3QgYmUg
+cmVmZXJlbmNlZC48L3A+Cgo8cD5UaGUgZm9sbG93aW5nIGdyYW1tYXIgaXMgZ2l2
+ZW4gdXNpbmcgdGhlIHNhbWUgbm90YXRpb24gYXMgdGhlCmdyYW1tYXIgaW4gdGhl
+IFhNTCBSZWNvbW1lbmRhdGlvbjxhIGhyZWY9IiNYTUwiPltYTUwxMF08L2E+LiAg
+U3ltYm9scyBpbiB0aGUKZ3JhbW1hciB0aGF0IGFyZSBub3QgZGVmaW5lZCBoZXJl
+IGFyZSBkZWZpbmVkIGluIHRoZSBYTUwKUmVjb21tZW5kYXRpb24uPC9wPgoKPGg1
+PnhtbC1zdHlsZXNoZWV0IHByb2Nlc3NpbmcgaW5zdHJ1Y3Rpb248L2g1Pgo8dGFi
+bGUgY2xhc3M9InNjcmFwIj4KPHRib2R5Pgo8dHIgdmFsaWduPSJiYXNlbGluZSI+
+Cjx0ZD4KPGEgbmFtZT0iTlQtU3R5bGVTaGVldFBJIj48L2E+WzFdJm5ic3A7Jm5i
+c3A7Jm5ic3A7PC90ZD4KPHRkPlN0eWxlU2hlZXRQSTwvdGQ+Cjx0ZD4mbmJzcDsm
+bmJzcDsmbmJzcDs6Oj0mbmJzcDsmbmJzcDsmbmJzcDs8L3RkPgo8dGQ+JyZsdDs/
+eG1sLXN0eWxlc2hlZXQnICg8YSBocmVmPSJodHRwOi8vd3d3LnczLm9yZy9UUi9S
+RUMteG1sI05ULVMiPlM8L2E+IDxhIGhyZWY9IiNOVC1Qc2V1ZG9BdHQiPlBzZXVk
+b0F0dDwvYT4pKiA8YSBocmVmPSJodHRwOi8vd3d3LnczLm9yZy9UUi9SRUMteG1s
+I05ULVMiPlM8L2E+PyAnPyZndDsnPC90ZD4KPHRkPgo8L3RkPgo8L3RyPgo8dHIg
+dmFsaWduPSJiYXNlbGluZSI+Cjx0ZD4KPGEgbmFtZT0iTlQtUHNldWRvQXR0Ij48
+L2E+WzJdJm5ic3A7Jm5ic3A7Jm5ic3A7PC90ZD4KPHRkPlBzZXVkb0F0dDwvdGQ+
+Cjx0ZD4mbmJzcDsmbmJzcDsmbmJzcDs6Oj0mbmJzcDsmbmJzcDsmbmJzcDs8L3Rk
+Pgo8dGQ+CjxhIGhyZWY9Imh0dHA6Ly93d3cudzMub3JnL1RSL1JFQy14bWwjTlQt
+TmFtZSI+TmFtZTwvYT4gPGEgaHJlZj0iaHR0cDovL3d3dy53My5vcmcvVFIvUkVD
+LXhtbCNOVC1TIj5TPC9hPj8gJz0nIDxhIGhyZWY9Imh0dHA6Ly93d3cudzMub3Jn
+L1RSL1JFQy14bWwjTlQtUyI+UzwvYT4/IDxhIGhyZWY9IiNOVC1Qc2V1ZG9BdHRW
+YWx1ZSI+UHNldWRvQXR0VmFsdWU8L2E+CjwvdGQ+Cjx0ZD4KPC90ZD4KPC90cj4K
+PHRyIHZhbGlnbj0iYmFzZWxpbmUiPgo8dGQ+CjxhIG5hbWU9Ik5ULVBzZXVkb0F0
+dFZhbHVlIj48L2E+WzNdJm5ic3A7Jm5ic3A7Jm5ic3A7PC90ZD4KPHRkPlBzZXVk
+b0F0dFZhbHVlPC90ZD4KPHRkPiZuYnNwOyZuYnNwOyZuYnNwOzo6PSZuYnNwOyZu
+YnNwOyZuYnNwOzwvdGQ+Cjx0ZD4oJyInIChbXiImbHQ7JmFtcDtdIHwgPGEgaHJl
+Zj0iaHR0cDovL3d3dy53My5vcmcvVFIvUkVDLXhtbCNOVC1DaGFyUmVmIj5DaGFy
+UmVmPC9hPiB8IDxhIGhyZWY9IiNOVC1QcmVkZWZFbnRpdHlSZWYiPlByZWRlZkVu
+dGl0eVJlZjwvYT4pKiAnIic8L3RkPgo8dGQ+CjwvdGQ+CjwvdHI+Cjx0ciB2YWxp
+Z249ImJhc2VsaW5lIj4KPHRkPgo8L3RkPgo8dGQ+CjwvdGQ+Cjx0ZD4KPC90ZD4K
+PHRkPnwgIiciIChbXicmbHQ7JmFtcDtdIHwgPGEgaHJlZj0iaHR0cDovL3d3dy53
+My5vcmcvVFIvUkVDLXhtbCNOVC1DaGFyUmVmIj5DaGFyUmVmPC9hPiB8IDxhIGhy
+ZWY9IiNOVC1QcmVkZWZFbnRpdHlSZWYiPlByZWRlZkVudGl0eVJlZjwvYT4pKiAi
+JyIpPC90ZD4KPHRkPgo8L3RkPgo8L3RyPgo8dHIgdmFsaWduPSJiYXNlbGluZSI+
+Cjx0ZD4KPC90ZD4KPHRkPgo8L3RkPgo8dGQ+CjwvdGQ+Cjx0ZD4tICg8YSBocmVm
+PSJodHRwOi8vd3d3LnczLm9yZy9UUi9SRUMteG1sI05ULUNoYXIiPkNoYXI8L2E+
+KiAnPyZndDsnIDxhIGhyZWY9Imh0dHA6Ly93d3cudzMub3JnL1RSL1JFQy14bWwj
+TlQtQ2hhciI+Q2hhcjwvYT4qKTwvdGQ+Cjx0ZD4KPC90ZD4KPC90cj4KPHRyIHZh
+bGlnbj0iYmFzZWxpbmUiPgo8dGQ+CjxhIG5hbWU9Ik5ULVByZWRlZkVudGl0eVJl
+ZiI+PC9hPls0XSZuYnNwOyZuYnNwOyZuYnNwOzwvdGQ+Cjx0ZD5QcmVkZWZFbnRp
+dHlSZWY8L3RkPgo8dGQ+Jm5ic3A7Jm5ic3A7Jm5ic3A7Ojo9Jm5ic3A7Jm5ic3A7
+Jm5ic3A7PC90ZD4KPHRkPicmYW1wO2FtcDsnIHwgJyZhbXA7bHQ7JyB8ICcmYW1w
+O2d0OycgfCAnJmFtcDtxdW90OycgfCAnJmFtcDthcG9zOyc8L3RkPgo8dGQ+Cjwv
+dGQ+CjwvdHI+CjwvdGJvZHk+CjwvdGFibGU+Cgo8cD5JbiA8YSBocmVmPSIjTlQt
+UHNldWRvQXR0VmFsdWUiPlBzZXVkb0F0dFZhbHVlPC9hPiwgYSA8YSBocmVmPSJo
+dHRwOi8vd3d3LnczLm9yZy9UUi9SRUMteG1sI05ULUNoYXJSZWYiPkNoYXJSZWY8
+L2E+IG9yIGEgPGEgaHJlZj0iI05ULVByZWRlZkVudGl0eVJlZiI+UHJlZGVmRW50
+aXR5UmVmPC9hPiBpcyBpbnRlcnByZXRlZCBpbiB0aGUKc2FtZSBtYW5uZXIgYXMg
+aW4gYSBub3JtYWwgWE1MIGF0dHJpYnV0ZSB2YWx1ZS4gIFRoZSBhY3R1YWwgdmFs
+dWUgb2YKdGhlIHBzZXVkby1hdHRyaWJ1dGUgaXMgdGhlIHZhbHVlIGFmdGVyIGVh
+Y2ggcmVmZXJlbmNlIGlzIHJlcGxhY2VkIGJ5CnRoZSBjaGFyYWN0ZXIgaXQgcmVm
+ZXJlbmNlcy4gIFRoaXMgcmVwbGFjZW1lbnQgaXMgbm90IHBlcmZvcm1lZAphdXRv
+bWF0aWNhbGx5IGJ5IGFuIFhNTCBwcm9jZXNzb3IuPC9wPgoKPHA+VGhlIDxjb2Rl
+PnhtbC1zdHlsZXNoZWV0PC9jb2RlPiBwcm9jZXNzaW5nIGluc3RydWN0aW9uIGlz
+IGFsbG93ZWQKb25seSBpbiB0aGUgcHJvbG9nIG9mIGFuIFhNTCBkb2N1bWVudC4g
+VGhlIHN5bnRheCBvZiBYTUwgY29uc3RyYWlucwp3aGVyZSBwcm9jZXNzaW5nIGlu
+c3RydWN0aW9ucyBhcmUgYWxsb3dlZCBpbiB0aGUgcHJvbG9nOyB0aGUKPGNvZGU+
+eG1sLXN0eWxlc2hlZXQ8L2NvZGU+IHByb2Nlc3NpbmcgaW5zdHJ1Y3Rpb24gaXMg
+YWxsb3dlZCBhbnl3aGVyZQppbiB0aGUgcHJvbG9nIHRoYXQgbWVldHMgdGhlc2Ug
+Y29uc3RyYWludHMuPC9wPgoKPGJsb2NrcXVvdGU+CjxiPk5PVEU6IDwvYj5JZiB0
+aGUgPGNvZGU+eG1sLXN0eWxlc2hlZXQ8L2NvZGU+IHByb2Nlc3NpbmcgaW5zdHJ1
+Y3Rpb24Kb2NjdXJzIGluIHRoZSBleHRlcm5hbCBEVEQgc3Vic2V0IG9yIGluIGEg
+cGFyYW1ldGVyIGVudGl0eSwgaXQgaXMKcG9zc2libGUgdGhhdCBpdCBtYXkgbm90
+IGJlIHByb2Nlc3NlZCBieSBhIG5vbi12YWxpZGF0aW5nIFhNTApwcm9jZXNzb3Ig
+KHNlZSA8YSBocmVmPSIjWE1MIj5bWE1MMTBdPC9hPikuPC9ibG9ja3F1b3RlPgoK
+PHA+VGhlIGZvbGxvd2luZyBwc2V1ZG8gYXR0cmlidXRlcyBhcmUgZGVmaW5lZDwv
+cD4KCjxwcmU+aHJlZiBDREFUQSAjUkVRVUlSRUQKdHlwZSBDREFUQSAjUkVRVUlS
+RUQKdGl0bGUgQ0RBVEEgI0lNUExJRUQKbWVkaWEgQ0RBVEEgI0lNUExJRUQKY2hh
+cnNldCBDREFUQSAjSU1QTElFRAphbHRlcm5hdGUgKHllc3xubykgIm5vIjwvcHJl
+PgoKPHA+VGhlIHNlbWFudGljcyBvZiB0aGUgcHNldWRvLWF0dHJpYnV0ZXMgYXJl
+IGV4YWN0bHkgYXMgd2l0aAo8Y29kZT4mbHQ7TElOSyBSRUw9InN0eWxlc2hlZXQi
+Jmd0OzwvY29kZT4gaW4gSFRNTCA0LjAsIHdpdGggdGhlCmV4Y2VwdGlvbiBvZiB0
+aGUgPGNvZGU+YWx0ZXJuYXRlPC9jb2RlPiBwc2V1ZG8tYXR0cmlidXRlLiAgSWYK
+PGNvZGU+YWx0ZXJuYXRlPSJ5ZXMiPC9jb2RlPiBpcyBzcGVjaWZpZWQsIHRoZW4g
+dGhlIHByb2Nlc3NpbmcKaW5zdHJ1Y3Rpb24gaGFzIHRoZSBzZW1hbnRpY3Mgb2Yg
+PGNvZGU+Jmx0O0xJTksgUkVMPSJhbHRlcm5hdGUKc3R5bGVzaGVldCImZ3Q7PC9j
+b2RlPiBpbnN0ZWFkIG9mIDxjb2RlPiZsdDtMSU5LClJFTD0ic3R5bGVzaGVldCIm
+Z3Q7PC9jb2RlPi48L3A+Cgo8YmxvY2txdW90ZT4KPGI+Tk9URTogPC9iPlNpbmNl
+IHRoZSB2YWx1ZSBvZiB0aGUgPGNvZGU+aHJlZjwvY29kZT4gYXR0cmlidXRlIGlz
+IGEgVVJJCnJlZmVyZW5jZSwgaXQgbWF5IGJlIGEgcmVsYXRpdmUgVVJJIGFuZCBp
+dCBtYXkgY29udGFpbiBhIGZyYWdtZW50CmlkZW50aWZpZXIuIEluIHBhcnRpY3Vs
+YXIgdGhlIFVSSSByZWZlcmVuY2UgbWF5IGNvbnRhaW4gb25seSBhCmZyYWdtZW50
+IGlkZW50aWZpZXIuICBTdWNoIGEgVVJJIHJlZmVyZW5jZSBpcyBhIHJlZmVyZW5j
+ZSB0byBhIHBhcnQgb2YKdGhlIGRvY3VtZW50IGNvbnRhaW5pbmcgdGhlIDxjb2Rl
+PnhtbC1zdHlsZXNoZWV0PC9jb2RlPiBwcm9jZXNzaW5nCmluc3RydWN0aW9uIChz
+ZWUgPGEgaHJlZj0iI1JGQzIzOTYiPltSRkMyMzk2XTwvYT4pLiBUaGUgY29uc2Vx
+dWVuY2UgaXMgdGhhdCB0aGUKPGNvZGU+eG1sLXN0eWxlc2hlZXQ8L2NvZGU+IHBy
+b2Nlc3NpbmcgaW5zdHJ1Y3Rpb24gYWxsb3dzIHN0eWxlIHNoZWV0cwp0byBiZSBl
+bWJlZGRlZCBpbiB0aGUgc2FtZSBkb2N1bWVudCBhcyB0aGUgPGNvZGU+eG1sLXN0
+eWxlc2hlZXQ8L2NvZGU+CnByb2Nlc3NpbmcgaW5zdHJ1Y3Rpb24uPC9ibG9ja3F1
+b3RlPgoKPHA+SW4gc29tZSBjYXNlcywgc3R5bGUgc2hlZXRzIG1heSBiZSBsaW5r
+ZWQgd2l0aCBhbiBYTUwgZG9jdW1lbnQgYnkKbWVhbnMgZXh0ZXJuYWwgdG8gdGhl
+IGRvY3VtZW50LiBGb3IgZXhhbXBsZSwgZWFybGllciB2ZXJzaW9ucyBvZiBIVFRQ
+CjxhIGhyZWY9IiNSRkMyMDY4Ij5bUkZDMjA2OF08L2E+IChzZWN0aW9uIDE5LjYu
+Mi40KSBhbGxvd2VkIHN0eWxlIHNoZWV0cyB0byBiZQphc3NvY2lhdGVkIHdpdGgg
+WE1MIGRvY3VtZW50cyBieSBtZWFucyBvZiB0aGUgPGNvZGU+TGluazwvY29kZT4K
+aGVhZGVyLiAgQW55IGxpbmtzIHRvIHN0eWxlIHNoZWV0cyB0aGF0IGFyZSBzcGVj
+aWZpZWQgZXh0ZXJuYWxseSB0byB0aGUKZG9jdW1lbnQgYXJlIGNvbnNpZGVyZWQg
+dG8gb2NjdXIgYmVmb3JlIHRoZSBsaW5rcyBzcGVjaWZpZWQgYnkgdGhlCjxjb2Rl
+PnhtbC1zdHlsZXNoZWV0PC9jb2RlPiBwcm9jZXNzaW5nIGluc3RydWN0aW9ucy4g
+IFRoaXMgaXMgdGhlIHNhbWUKYXMgaW4gSFRNTCA0LjAgKHNlZSA8YSBocmVmPSJo
+dHRwOi8vd3d3LnczLm9yZy9UUi9SRUMtaHRtbDQwL3ByZXNlbnQvc3R5bGVzLmh0
+bWwjaC0xNC42Ij5zZWN0aW9uCjE0LjY8L2E+KS48L3A+Cgo8cD5IZXJlIGFyZSBz
+b21lIGV4YW1wbGVzIGZyb20gSFRNTCA0LjAgd2l0aCB0aGUgY29ycmVzcG9uZGlu
+Zwpwcm9jZXNzaW5nIGluc3RydWN0aW9uOjwvcD4KCjxwcmU+Jmx0O0xJTksgaHJl
+Zj0ibXlzdHlsZS5jc3MiIHJlbD0ic3R5bGUgc2hlZXQiIHR5cGU9InRleHQvY3Nz
+IiZndDsKJmx0Oz94bWwtc3R5bGVzaGVldCBocmVmPSJteXN0eWxlLmNzcyIgdHlw
+ZT0idGV4dC9jc3MiPyZndDsKCiZsdDtMSU5LIGhyZWY9Im15c3R5bGUuY3NzIiB0
+aXRsZT0iQ29tcGFjdCIgcmVsPSJzdHlsZXNoZWV0Igp0eXBlPSJ0ZXh0L2NzcyIm
+Z3Q7CiZsdDs/eG1sLXN0eWxlc2hlZXQgaHJlZj0ibXlzdHlsZS5jc3MiIHRpdGxl
+PSJDb21wYWN0IiB0eXBlPSJ0ZXh0L2NzcyI/Jmd0OwoKJmx0O0xJTksgaHJlZj0i
+bXlzdHlsZS5jc3MiIHRpdGxlPSJNZWRpdW0iIHJlbD0iYWx0ZXJuYXRlIHN0eWxl
+c2hlZXQiCnR5cGU9InRleHQvY3NzIiZndDsKJmx0Oz94bWwtc3R5bGVzaGVldCBh
+bHRlcm5hdGU9InllcyIgaHJlZj0ibXlzdHlsZS5jc3MiIHRpdGxlPSJNZWRpdW0i
+CnR5cGU9InRleHQvY3NzIj8mZ3Q7PC9wcmU+Cgo8cD5NdWx0aXBsZSA8Y29kZT54
+bWwtc3R5bGVzaGVldDwvY29kZT4gcHJvY2Vzc2luZyBpbnN0cnVjdGlvbnMgYXJl
+CmFsc28gYWxsb3dlZCB3aXRoIGV4YWN0bHkgdGhlIHNhbWUgc2VtYW50aWNzIGFz
+IHdpdGggPGNvZGU+TElOSwpSRUw9InN0eWxlc2hlZXQiPC9jb2RlPi4gRm9yIGV4
+YW1wbGUsPC9wPgoKPHByZT4mbHQ7TElOSyByZWw9ImFsdGVybmF0ZSBzdHlsZXNo
+ZWV0IiB0aXRsZT0iY29tcGFjdCIgaHJlZj0ic21hbGwtYmFzZS5jc3MiCnR5cGU9
+InRleHQvY3NzIiZndDsKJmx0O0xJTksgcmVsPSJhbHRlcm5hdGUgc3R5bGVzaGVl
+dCIgdGl0bGU9ImNvbXBhY3QiIGhyZWY9InNtYWxsLWV4dHJhcy5jc3MiCnR5cGU9
+InRleHQvY3NzIiZndDsKJmx0O0xJTksgcmVsPSJhbHRlcm5hdGUgc3R5bGVzaGVl
+dCIgdGl0bGU9ImJpZyBwcmludCIgaHJlZj0iYmlncHJpbnQuY3NzIgp0eXBlPSJ0
+ZXh0L2NzcyImZ3Q7CiZsdDtMSU5LIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iY29t
+bW9uLmNzcyIgdHlwZT0idGV4dC9jc3MiJmd0OzwvcHJlPgoKPHA+d291bGQgYmUg
+ZXF1aXZhbGVudCB0bzo8L3A+Cgo8cHJlPiZsdDs/eG1sLXN0eWxlc2hlZXQgYWx0
+ZXJuYXRlPSJ5ZXMiIHRpdGxlPSJjb21wYWN0IiBocmVmPSJzbWFsbC1iYXNlLmNz
+cyIKdHlwZT0idGV4dC9jc3MiPyZndDsKJmx0Oz94bWwtc3R5bGVzaGVldCBhbHRl
+cm5hdGU9InllcyIgdGl0bGU9ImNvbXBhY3QiIGhyZWY9InNtYWxsLWV4dHJhcy5j
+c3MiCnR5cGU9InRleHQvY3NzIj8mZ3Q7CiZsdDs/eG1sLXN0eWxlc2hlZXQgYWx0
+ZXJuYXRlPSJ5ZXMiIHRpdGxlPSJiaWcgcHJpbnQiIGhyZWY9ImJpZ3ByaW50LmNz
+cyIKdHlwZT0idGV4dC9jc3MiPyZndDsKJmx0Oz94bWwtc3R5bGVzaGVldCBocmVm
+PSJjb21tb24uY3NzIiB0eXBlPSJ0ZXh0L2NzcyI/Jmd0OzwvcHJlPgoKCgo8aHIg
+dGl0bGU9IlNlcGFyYXRvciBmcm9tIGZvb3RlciI+Cgo8aDI+CjxhIG5hbWU9IlJl
+ZmVyZW5jZXMiPjwvYT5BIFJlZmVyZW5jZXM8L2gyPgoKPGRsPgoKPGR0Pgo8YSBu
+YW1lPSJIVE1MIj5IVE1MNDA8L2E+CjwvZHQ+CjxkZD5Xb3JsZCBXaWRlIFdlYgpD
+b25zb3J0aXVtLiA8aT5IVE1MIDQuMCBTcGVjaWZpY2F0aW9uLjwvaT4gVzNDIFJl
+Y29tbWVuZGF0aW9uLiBTZWUKPGEgaHJlZj0iaHR0cDovL3d3dy53My5vcmcvVFIv
+UkVDLWh0bWw0MCI+aHR0cDovL3d3dy53My5vcmcvVFIvUkVDLWh0bWw0MDwvYT4K
+PC9kZD4KCjxkdD4KPGEgbmFtZT0iUkZDMjA2OCI+UkZDMjA2ODwvYT4KPC9kdD4K
+PGRkPlIuIEZpZWxkaW5nLCBKLiBHZXR0eXMsIEouIE1vZ3VsLApILiBGcnlzdHlr
+IE5pZWxzZW4sIGFuZCBULiBCZXJuZXJzLUxlZS4gIDxpPkh5cGVydGV4dCBUcmFu
+c2ZlcgpQcm90b2NvbCAtLSBIVFRQLzEuMS48L2k+LiBJRVRGIFJGQyAyMDY4LiBT
+ZWUgPGEgaHJlZj0iaHR0cDovL3d3dy5pZXRmLm9yZy9yZmMvcmZjMjA2OC50eHQi
+Pmh0dHA6Ly93d3cuaWV0Zi5vcmcvcmZjL3JmYzIwNjgudHh0PC9hPi48L2RkPgoK
+PGR0Pgo8YSBuYW1lPSJSRkMyMzk2Ij5SRkMyMzk2PC9hPgo8L2R0Pgo8ZGQ+VC4g
+QmVybmVycy1MZWUsIFIuIEZpZWxkaW5nLCBhbmQKTC4gTWFzaW50ZXIuICA8aT5V
+bmlmb3JtIFJlc291cmNlIElkZW50aWZpZXJzIChVUkkpOiBHZW5lcmljClN5bnRh
+eDwvaT4uIElFVEYgUkZDIDIzOTYuIFNlZSA8YSBocmVmPSJodHRwOi8vd3d3Lmll
+dGYub3JnL3JmYy9yZmMyMzk2LnR4dCI+aHR0cDovL3d3dy5pZXRmLm9yZy9yZmMv
+cmZjMjM5Ni50eHQ8L2E+LjwvZGQ+Cgo8ZHQ+CjxhIG5hbWU9IlhNTCI+WE1MMTA8
+L2E+CjwvZHQ+CjxkZD5Xb3JsZCBXaWRlIFdlYiBDb25zb3J0aXVtLiA8aT5FeHRl
+bnNpYmxlCk1hcmt1cCBMYW5ndWFnZSAoWE1MKSAxLjAuPC9pPiBXM0MgUmVjb21t
+ZW5kYXRpb24uIFNlZSA8YSBocmVmPSJodHRwOi8vd3d3LnczLm9yZy9UUi8xOTk4
+L1JFQy14bWwtMTk5ODAyMTAiPmh0dHA6Ly93d3cudzMub3JnL1RSLzE5OTgvUkVD
+LXhtbC0xOTk4MDIxMDwvYT4KPC9kZD4KCjwvZGw+CgoKCgo8aDI+CjxhIG5hbWU9
+InJhdGlvbmFsZSI+PC9hPkIgUmF0aW9uYWxlPC9oMj4KCjxwPlRoZXJlIHdhcyBh
+biB1cmdlbnQgcmVxdWlyZW1lbnQgZm9yIGEgc3BlY2lmaWNhdGlvbiBmb3Igc3R5
+bGUgc2hlZXQKbGlua2luZyB0aGF0IGNvdWxkIGJlIGNvbXBsZXRlZCBpbiB0aW1l
+IGZvciB0aGUgbmV4dCByZWxlYXNlIGZyb20KbWFqb3IgYnJvd3NlciB2ZW5kb3Jz
+LiAgT25seSBieSBjaG9vc2luZyBhIHNpbXBsZSBtZWNoYW5pc20gY2xvc2VseQpi
+YXNlZCBvbiBhIHByb3ZlbiBleGlzdGluZyBtZWNoYW5pc20gY291bGQgdGhlIHNw
+ZWNpZmljYXRpb24gYmUKY29tcGxldGVkIGluIHRpbWUgdG8gbWVldCB0aGlzIHJl
+cXVpcmVtZW50LjwvcD4KCjxwPlVzZSBvZiBhIHByb2Nlc3NpbmcgaW5zdHJ1Y3Rp
+b24gYXZvaWRzIHBvbGx1dGluZyB0aGUgbWFpbiBkb2N1bWVudApzdHJ1Y3R1cmUg
+d2l0aCBhcHBsaWNhdGlvbiBzcGVjaWZpYyBwcm9jZXNzaW5nIGluZm9ybWF0aW9u
+LjwvcD4KCjxwPlRoZSBtZWNoYW5pc20gY2hvc2VuIGZvciB0aGlzIHZlcnNpb24g
+b2YgdGhlIHNwZWNpZmljYXRpb24gaXMgbm90IGEKY29uc3RyYWludCBvbiB0aGUg
+YWRkaXRpb25hbCBtZWNoYW5pc21zIHBsYW5uZWQgZm9yIGZ1dHVyZSB2ZXJzaW9u
+cy4KVGhlcmUgaXMgbm8gZXhwZWN0YXRpb24gdGhhdCB0aGVzZSB3aWxsIHVzZSBw
+cm9jZXNzaW5nIGluc3RydWN0aW9uczsKaW5kZWVkIHRoZXkgbWF5IG5vdCBpbmNs
+dWRlIHRoZSBsaW5raW5nIGluZm9ybWF0aW9uIGluIHRoZSBzb3VyY2UKZG9jdW1l
+bnQuPC9wPgoKCgoKPC9ib2R5Pgo8L2h0bWw+Cg==
diff --git a/test/javax/xml/crypto/dsig/keyinfo/KeyInfo/Marshal.java b/test/javax/xml/crypto/dsig/keyinfo/KeyInfo/Marshal.java
new file mode 100644
index 0000000..a0c53e7
--- /dev/null
+++ b/test/javax/xml/crypto/dsig/keyinfo/KeyInfo/Marshal.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6372500
+ * @summary Test that KeyInfo.marshal works correctly
+ * @compile -XDignore.symbol.file Marshal.java
+ * @run main Marshal
+ * @author Sean Mullan
+ */
+
+import java.util.Collections;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.crypto.dom.DOMStructure;
+import javax.xml.crypto.dsig.keyinfo.KeyInfo;
+import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.jcp.xml.dsig.internal.dom.DOMUtils;
+
+public class Marshal {
+
+ public static void main(String[] args) throws Exception {
+ KeyInfoFactory fac = KeyInfoFactory.getInstance();
+ KeyInfo ki = fac.newKeyInfo
+ (Collections.singletonList(fac.newKeyName("foo")), "keyid");
+ try {
+ ki.marshal(null, null);
+ throw new Exception("Should raise a NullPointerException");
+ } catch (NullPointerException npe) {}
+
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ Document doc = dbf.newDocumentBuilder().newDocument();
+ Element elem = doc.createElementNS("http://acme.org", "parent");
+ doc.appendChild(elem);
+ DOMStructure parent = new DOMStructure(elem);
+ ki.marshal(parent, null);
+
+ Element kiElem = DOMUtils.getFirstChildElement(elem);
+ if (!kiElem.getLocalName().equals("KeyInfo")) {
+ throw new Exception
+ ("Should be KeyInfo element: " + kiElem.getLocalName());
+ }
+ Element knElem = DOMUtils.getFirstChildElement(kiElem);
+ if (!knElem.getLocalName().equals("KeyName")) {
+ throw new Exception
+ ("Should be KeyName element: " + knElem.getLocalName());
+ }
+ }
+}