1 /* |
|
2 * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. |
|
8 * |
|
9 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
12 * version 2 for more details (a copy is included in the LICENSE file that |
|
13 * accompanied this code). |
|
14 * |
|
15 * You should have received a copy of the GNU General Public License version |
|
16 * 2 along with this work; if not, write to the Free Software Foundation, |
|
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
18 * |
|
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
20 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
21 * have any questions. |
|
22 */ |
|
23 |
|
24 /* |
|
25 * @test |
|
26 * @bug 6750008 |
|
27 * @summary Test JMX.getSpecificationVersion |
|
28 * @author Eamonn McManus |
|
29 */ |
|
30 |
|
31 import java.io.IOException; |
|
32 import java.util.Collections; |
|
33 import java.util.ListIterator; |
|
34 import java.util.Set; |
|
35 import javax.management.Attribute; |
|
36 import javax.management.AttributeList; |
|
37 import javax.management.AttributeNotFoundException; |
|
38 import javax.management.DynamicMBean; |
|
39 import javax.management.InstanceNotFoundException; |
|
40 import javax.management.InvalidAttributeValueException; |
|
41 import javax.management.JMX; |
|
42 import javax.management.MBeanException; |
|
43 import javax.management.MBeanInfo; |
|
44 import javax.management.MBeanServer; |
|
45 import javax.management.MBeanServerConnection; |
|
46 import javax.management.MBeanServerDelegate; |
|
47 import javax.management.MBeanServerDelegateMBean; |
|
48 import javax.management.MBeanServerFactory; |
|
49 import javax.management.ObjectName; |
|
50 import javax.management.ReflectionException; |
|
51 import javax.management.StandardMBean; |
|
52 import javax.management.namespace.JMXNamespace; |
|
53 import javax.management.namespace.JMXNamespaces; |
|
54 import javax.management.namespace.MBeanServerSupport; |
|
55 import javax.management.remote.JMXConnector; |
|
56 import javax.management.remote.JMXConnectorFactory; |
|
57 import javax.management.remote.JMXConnectorServer; |
|
58 import javax.management.remote.JMXConnectorServerFactory; |
|
59 import javax.management.remote.JMXServiceURL; |
|
60 |
|
61 public class JMXSpecVersionTest { |
|
62 private static String failure; |
|
63 private static final Object POISON_PILL = new Object(); |
|
64 |
|
65 private static class FakeDelegate implements DynamicMBean { |
|
66 private final Object specVersion; |
|
67 private final DynamicMBean delegate = new StandardMBean( |
|
68 new MBeanServerDelegate(), MBeanServerDelegateMBean.class, false); |
|
69 |
|
70 FakeDelegate(Object specVersion) { |
|
71 this.specVersion = specVersion; |
|
72 } |
|
73 |
|
74 public Object getAttribute(String attribute) |
|
75 throws AttributeNotFoundException, MBeanException, |
|
76 ReflectionException { |
|
77 if ("SpecificationVersion".equals(attribute)) { |
|
78 if (specVersion == POISON_PILL) |
|
79 throw new AttributeNotFoundException(attribute); |
|
80 else |
|
81 return specVersion; |
|
82 } else |
|
83 return delegate.getAttribute(attribute); |
|
84 } |
|
85 |
|
86 public void setAttribute(Attribute attribute) |
|
87 throws AttributeNotFoundException, InvalidAttributeValueException, |
|
88 MBeanException, ReflectionException { |
|
89 delegate.setAttribute(attribute); |
|
90 } |
|
91 |
|
92 public AttributeList getAttributes(String[] attributes) { |
|
93 AttributeList list = delegate.getAttributes(attributes); |
|
94 for (ListIterator<Attribute> it = list.asList().listIterator(); |
|
95 it.hasNext(); ) { |
|
96 Attribute attr = it.next(); |
|
97 if (attr.getName().equals("SpecificationVersion")) { |
|
98 it.remove(); |
|
99 if (specVersion != POISON_PILL) { |
|
100 attr = new Attribute(attr.getName(), specVersion); |
|
101 it.add(attr); |
|
102 } |
|
103 } |
|
104 } |
|
105 return list; |
|
106 } |
|
107 |
|
108 public AttributeList setAttributes(AttributeList attributes) { |
|
109 return delegate.setAttributes(attributes); |
|
110 } |
|
111 |
|
112 public Object invoke(String actionName, Object[] params, |
|
113 String[] signature) throws MBeanException, |
|
114 ReflectionException { |
|
115 return delegate.invoke(actionName, params, signature); |
|
116 } |
|
117 |
|
118 public MBeanInfo getMBeanInfo() { |
|
119 throw new UnsupportedOperationException("Not supported yet."); |
|
120 } |
|
121 } |
|
122 |
|
123 private static class MBeanServerWithVersion extends MBeanServerSupport { |
|
124 private final DynamicMBean delegate; |
|
125 |
|
126 public MBeanServerWithVersion(Object specVersion) { |
|
127 this.delegate = new FakeDelegate(specVersion); |
|
128 } |
|
129 |
|
130 @Override |
|
131 public DynamicMBean getDynamicMBeanFor(ObjectName name) |
|
132 throws InstanceNotFoundException { |
|
133 if (MBeanServerDelegate.DELEGATE_NAME.equals(name)) |
|
134 return delegate; |
|
135 else |
|
136 throw new InstanceNotFoundException(name); |
|
137 } |
|
138 |
|
139 @Override |
|
140 protected Set<ObjectName> getNames() { |
|
141 return Collections.singleton(MBeanServerDelegate.DELEGATE_NAME); |
|
142 } |
|
143 } |
|
144 |
|
145 private static class EmptyMBeanServer extends MBeanServerSupport { |
|
146 @Override |
|
147 public DynamicMBean getDynamicMBeanFor(ObjectName name) throws InstanceNotFoundException { |
|
148 throw new InstanceNotFoundException(name); |
|
149 } |
|
150 |
|
151 @Override |
|
152 protected Set<ObjectName> getNames() { |
|
153 return Collections.emptySet(); |
|
154 } |
|
155 } |
|
156 |
|
157 public static void main(String[] args) throws Exception { |
|
158 MBeanServer mbs = MBeanServerFactory.newMBeanServer(); |
|
159 JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///"); |
|
160 JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer( |
|
161 url, null, mbs); |
|
162 cs.start(); |
|
163 |
|
164 String realVersion = (String) mbs.getAttribute( |
|
165 MBeanServerDelegate.DELEGATE_NAME, "SpecificationVersion"); |
|
166 assertEquals("Reported local version", |
|
167 realVersion, JMX.getSpecificationVersion(mbs, null)); |
|
168 assertEquals("Reported local version >= \"2.0\"", |
|
169 true, (realVersion.compareTo("2.0") >= 0)); |
|
170 |
|
171 JMXConnector cc = JMXConnectorFactory.connect(cs.getAddress()); |
|
172 MBeanServerConnection mbsc = cc.getMBeanServerConnection(); |
|
173 assertEquals("Reported remote version", |
|
174 realVersion, JMX.getSpecificationVersion(mbsc, null)); |
|
175 |
|
176 cc.close(); |
|
177 try { |
|
178 String brokenVersion = JMX.getSpecificationVersion(mbsc, null); |
|
179 fail("JMX.getSpecificationVersion succeded over closed connection" + |
|
180 " (returned " + brokenVersion + ")"); |
|
181 } catch (Exception e) { |
|
182 assertEquals("Exception for closed connection", |
|
183 IOException.class, e.getClass()); |
|
184 } |
|
185 |
|
186 try { |
|
187 String brokenVersion = JMX.getSpecificationVersion( |
|
188 new EmptyMBeanServer(), null); |
|
189 fail("JMX.getSpecificationVersion succeded with empty MBean Server" + |
|
190 " (returned " + brokenVersion + ")"); |
|
191 } catch (Exception e) { |
|
192 assertEquals("Exception for empty MBean Server", |
|
193 IOException.class, e.getClass()); |
|
194 } |
|
195 |
|
196 try { |
|
197 String brokenVersion = JMX.getSpecificationVersion(null, null); |
|
198 fail("JMX.getSpecificationVersion succeded with null MBean Server" + |
|
199 " (returned " + brokenVersion + ")"); |
|
200 } catch (Exception e) { |
|
201 assertEquals("Exception for null MBean Server", |
|
202 IllegalArgumentException.class, e.getClass()); |
|
203 } |
|
204 |
|
205 MBeanServer mbs1_2 = new MBeanServerWithVersion("1.2"); |
|
206 String version1_2 = JMX.getSpecificationVersion(mbs1_2, null); |
|
207 assertEquals("Version for 1.2 MBean Server", "1.2", version1_2); |
|
208 |
|
209 // It's completely nutty for an MBean Server to return null as the |
|
210 // value of its spec version, and we don't actually say what happens |
|
211 // in that case, but in fact we return the null to the caller. |
|
212 MBeanServer mbs_null = new MBeanServerWithVersion(null); |
|
213 String version_null = JMX.getSpecificationVersion(mbs_null, null); |
|
214 assertEquals("Version for MBean Server that declares null spec version", |
|
215 null, version_null); |
|
216 |
|
217 try { |
|
218 MBeanServer mbs1_2_float = new MBeanServerWithVersion(1.2f); |
|
219 String version1_2_float = |
|
220 JMX.getSpecificationVersion(mbs1_2_float, null); |
|
221 fail("JMX.getSpecificationVersion succeeded with version 1.2f" + |
|
222 " (returned " + version1_2_float + ")"); |
|
223 } catch (Exception e) { |
|
224 assertEquals("Exception for non-string version (1.2f)", |
|
225 IOException.class, e.getClass()); |
|
226 } |
|
227 |
|
228 try { |
|
229 MBeanServer mbs_missing = new MBeanServerWithVersion(POISON_PILL); |
|
230 String version_missing = |
|
231 JMX.getSpecificationVersion(mbs_missing, null); |
|
232 fail("JMX.getSpecificationVersion succeeded with null version" + |
|
233 " (returned " + version_missing + ")"); |
|
234 } catch (Exception e) { |
|
235 assertEquals("Exception for missing version", |
|
236 IOException.class, e.getClass()); |
|
237 } |
|
238 |
|
239 ObjectName wildcardNamespaceName = new ObjectName("foo//*//bar//baz:k=v"); |
|
240 try { |
|
241 String brokenVersion = |
|
242 JMX.getSpecificationVersion(mbsc, wildcardNamespaceName); |
|
243 fail("JMX.getSpecificationVersion succeeded with wildcard namespace" + |
|
244 " (returned " + brokenVersion + ")"); |
|
245 } catch (Exception e) { |
|
246 assertEquals("Exception for wildcard namespace", |
|
247 IllegalArgumentException.class, e.getClass()); |
|
248 } |
|
249 |
|
250 String sub1_2namespace = "blibby"; |
|
251 JMXNamespace sub1_2 = new JMXNamespace(mbs1_2); |
|
252 ObjectName sub1_2name = |
|
253 JMXNamespaces.getNamespaceObjectName(sub1_2namespace); |
|
254 mbs.registerMBean(sub1_2, sub1_2name); |
|
255 String sub1_2namespaceHandlerVersion = |
|
256 JMX.getSpecificationVersion(mbs, sub1_2name); |
|
257 assertEquals("Spec version of namespace handler", |
|
258 realVersion, sub1_2namespaceHandlerVersion); |
|
259 // The namespace handler is in the top-level namespace so its |
|
260 // version should not be 1.2. |
|
261 |
|
262 for (String nameInSub : new String[] {"*:*", "d:k=v"}) { |
|
263 ObjectName subName = new ObjectName(sub1_2namespace + "//" + nameInSub); |
|
264 String subVersion = JMX.getSpecificationVersion(mbs, subName); |
|
265 assertEquals("Spec version in 1.2 namespace (" + nameInSub + ")", |
|
266 "1.2", subVersion); |
|
267 } |
|
268 |
|
269 mbs.unregisterMBean(sub1_2name); |
|
270 for (String noSuchNamespace : new String[] { |
|
271 sub1_2namespace + "//*:*", sub1_2namespace + "//d:k=v", |
|
272 }) { |
|
273 try { |
|
274 String brokenVersion = JMX.getSpecificationVersion( |
|
275 mbs, new ObjectName(noSuchNamespace)); |
|
276 fail("JMX.getSpecificationVersion succeeded with missing " + |
|
277 "namespace (" + noSuchNamespace + " -> " + |
|
278 brokenVersion); |
|
279 } catch (Exception e) { |
|
280 assertEquals("Exception for missing namespace", |
|
281 IOException.class, e.getClass()); |
|
282 } |
|
283 } |
|
284 |
|
285 if (failure != null) |
|
286 throw new Exception("TEST FAILED: " + failure); |
|
287 System.out.println("TEST PASSED"); |
|
288 } |
|
289 |
|
290 private static void assertEquals(String what, Object expect, Object actual) { |
|
291 if (equal(expect, actual)) |
|
292 System.out.println("OK: " + what + ": " + expect); |
|
293 else |
|
294 fail(what + ": expected " + expect + ", got " + actual); |
|
295 } |
|
296 |
|
297 private static boolean equal(Object x, Object y) { |
|
298 if (x == null) |
|
299 return (y == null); |
|
300 else |
|
301 return x.equals(y); |
|
302 } |
|
303 |
|
304 private static void fail(String why) { |
|
305 System.out.println("FAILED: " + why); |
|
306 failure = why; |
|
307 } |
|
308 } |
|