1 /*
2 * Copyright 2002-2007 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 package javax.management.remote.rmi;
27
28 import static com.sun.jmx.mbeanserver.Util.cast;
29 import com.sun.jmx.remote.internal.ServerCommunicatorAdmin;
30 import com.sun.jmx.remote.internal.ServerNotifForwarder;
31 import com.sun.jmx.remote.security.JMXSubjectDomainCombiner;
32 import com.sun.jmx.remote.security.SubjectDelegator;
33 import com.sun.jmx.remote.util.ClassLoaderWithRepository;
34 import com.sun.jmx.remote.util.ClassLogger;
35 import com.sun.jmx.remote.util.EnvHelp;
36 import com.sun.jmx.remote.util.OrderClassLoaders;
37
38 import java.io.IOException;
39 import java.rmi.MarshalledObject;
40 import java.rmi.UnmarshalException;
41 import java.rmi.server.Unreferenced;
42 import java.security.AccessControlContext;
43 import java.security.AccessController;
44 import java.security.PrivilegedAction;
45 import java.security.PrivilegedActionException;
46 import java.security.PrivilegedExceptionAction;
47 import java.util.Arrays;
48 import java.util.Collections;
49 import java.util.Map;
50 import java.util.Set;
51
52 import javax.management.Attribute;
53 import javax.management.AttributeList;
54 import javax.management.AttributeNotFoundException;
55 import javax.management.InstanceAlreadyExistsException;
56 import javax.management.InstanceNotFoundException;
57 import javax.management.IntrospectionException;
58 import javax.management.InvalidAttributeValueException;
59 import javax.management.ListenerNotFoundException;
60 import javax.management.MBeanException;
61 import javax.management.MBeanInfo;
62 import javax.management.MBeanRegistrationException;
63 import javax.management.MBeanServer;
64 import javax.management.NotCompliantMBeanException;
65 import javax.management.NotificationFilter;
66 import javax.management.ObjectInstance;
67 import javax.management.ObjectName;
68 import javax.management.QueryExp;
69 import javax.management.ReflectionException;
70 import javax.management.RuntimeOperationsException;
71 import javax.management.loading.ClassLoaderRepository;
72 import javax.management.remote.JMXServerErrorException;
73 import javax.management.remote.NotificationResult;
74 import javax.management.remote.TargetedNotification;
75 import javax.security.auth.Subject;
76
77 /**
78 * <p>Implementation of the {@link RMIConnection} interface. User
79 * code will not usually reference this class.</p>
80 *
81 * @since 1.5
82 */
83 /*
84 * Notice that we omit the type parameter from MarshalledObject everywhere,
85 * even though it would add useful information to the documentation. The
86 * reason is that it was only added in Mustang (Java SE 6), whereas versions
87 * 1.4 and 2.0 of the JMX API must be implementable on Tiger per our
88 * commitments for JSR 255.
89 */
90 public class RMIConnectionImpl implements RMIConnection, Unreferenced {
91
92 /**
93 * Constructs a new {@link RMIConnection}. This connection can be
94 * used with either the JRMP or IIOP transport. This object does
95 * not export itself: it is the responsibility of the caller to
96 * export it appropriately (see {@link
97 * RMIJRMPServerImpl#makeClient(String,Subject)} and {@link
98 * RMIIIOPServerImpl#makeClient(String,Subject)}.
99 *
100 * @param rmiServer The RMIServerImpl object for which this
101 * connection is created. The behavior is unspecified if this
102 * parameter is null.
103 * @param connectionId The ID for this connection. The behavior
104 * is unspecified if this parameter is null.
105 * @param defaultClassLoader The default ClassLoader to be used
106 * when deserializing marshalled objects. Can be null, to signify
107 * the bootstrap class loader.
108 * @param subject the authenticated subject to be used for
109 * authorization. Can be null, to signify that no subject has
110 * been authenticated.
111 * @param env the environment containing attributes for the new
112 * <code>RMIServerImpl</code>. Can be null, equivalent to an
113 * empty map.
114 */
115 public RMIConnectionImpl(RMIServerImpl rmiServer,
116 String connectionId,
117 ClassLoader defaultClassLoader,
118 Subject subject,
119 Map<String,?> env) {
120 if (rmiServer == null || connectionId == null)
121 throw new NullPointerException("Illegal null argument");
122 if (env == null)
123 env = Collections.emptyMap();
124 this.rmiServer = rmiServer;
125 this.connectionId = connectionId;
126 this.defaultClassLoader = defaultClassLoader;
127
128 this.subjectDelegator = new SubjectDelegator();
129 this.subject = subject;
130 if (subject == null) {
131 this.acc = null;
132 this.removeCallerContext = false;
133 } else {
134 this.removeCallerContext =
135 SubjectDelegator.checkRemoveCallerContext(subject);
136 if (this.removeCallerContext) {
137 this.acc =
138 JMXSubjectDomainCombiner.getDomainCombinerContext(subject);
139 } else {
140 this.acc =
141 JMXSubjectDomainCombiner.getContext(subject);
142 }
143 }
144 this.mbeanServer = rmiServer.getMBeanServer();
145
146 final ClassLoader dcl = defaultClassLoader;
147 this.classLoaderWithRepository =
148 AccessController.doPrivileged(
149 new PrivilegedAction<ClassLoaderWithRepository>() {
150 public ClassLoaderWithRepository run() {
151 return new ClassLoaderWithRepository(
152 getClassLoaderRepository(),
153 dcl);
154 }
155 });
156
157 serverCommunicatorAdmin = new
158 RMIServerCommunicatorAdmin(EnvHelp.getServerConnectionTimeout(env));
159
160 this.env = env;
161 }
162
163 private synchronized ServerNotifForwarder getServerNotifFwd() {
164 // Lazily created when first use. Mainly when
165 // addNotificationListener is first called.
166 if (serverNotifForwarder == null)
167 serverNotifForwarder =
168 new ServerNotifForwarder(mbeanServer,
169 env,
170 rmiServer.getNotifBuffer(),
171 connectionId);
172 return serverNotifForwarder;
173 }
174
175 public String getConnectionId() throws IOException {
176 // We should call reqIncomming() here... shouldn't we?
177 return connectionId;
178 }
179
180 public void close() throws IOException {
181 final boolean debug = logger.debugOn();
182 final String idstr = (debug?"["+this.toString()+"]":null);
183
184 synchronized (this) {
185 if (terminated) {
186 if (debug) logger.debug("close",idstr + " already terminated.");
187 return;
188 }
189
190 if (debug) logger.debug("close",idstr + " closing.");
191
192 terminated = true;
193
194 if (serverCommunicatorAdmin != null) {
195 serverCommunicatorAdmin.terminate();
196 }
197
198 if (serverNotifForwarder != null) {
199 serverNotifForwarder.terminate();
200 }
201 }
202
203 rmiServer.clientClosed(this);
204
205 if (debug) logger.debug("close",idstr + " closed.");
206 }
207
208 public void unreferenced() {
209 logger.debug("unreferenced", "called");
210 try {
211 close();
212 logger.debug("unreferenced", "done");
213 } catch (IOException e) {
214 logger.fine("unreferenced", e);
215 }
216 }
217
218 //-------------------------------------------------------------------------
219 // MBeanServerConnection Wrapper
220 //-------------------------------------------------------------------------
221
222 public ObjectInstance createMBean(String className,
223 ObjectName name,
224 Subject delegationSubject)
225 throws
226 ReflectionException,
227 InstanceAlreadyExistsException,
228 MBeanRegistrationException,
229 MBeanException,
230 NotCompliantMBeanException,
231 IOException {
232 try {
233 final Object params[] =
234 new Object[] { className, name };
235
236 if (logger.debugOn())
237 logger.debug("createMBean(String,ObjectName)",
238 "connectionId=" + connectionId +", className=" +
239 className+", name=" + name);
240
241 return (ObjectInstance)
242 doPrivilegedOperation(
243 CREATE_MBEAN,
244 params,
245 delegationSubject);
246 } catch (PrivilegedActionException pe) {
247 Exception e = extractException(pe);
248 if (e instanceof ReflectionException)
249 throw (ReflectionException) e;
250 if (e instanceof InstanceAlreadyExistsException)
251 throw (InstanceAlreadyExistsException) e;
252 if (e instanceof MBeanRegistrationException)
253 throw (MBeanRegistrationException) e;
254 if (e instanceof MBeanException)
255 throw (MBeanException) e;
256 if (e instanceof NotCompliantMBeanException)
257 throw (NotCompliantMBeanException) e;
258 if (e instanceof IOException)
259 throw (IOException) e;
260 throw newIOException("Got unexpected server exception: " + e, e);
261 }
262 }
263
264 public ObjectInstance createMBean(String className,
265 ObjectName name,
266 ObjectName loaderName,
267 Subject delegationSubject)
268 throws
269 ReflectionException,
270 InstanceAlreadyExistsException,
271 MBeanRegistrationException,
272 MBeanException,
273 NotCompliantMBeanException,
274 InstanceNotFoundException,
275 IOException {
276 try {
277 final Object params[] =
278 new Object[] { className, name, loaderName };
279
280 if (logger.debugOn())
281 logger.debug("createMBean(String,ObjectName,ObjectName)",
282 "connectionId=" + connectionId
283 +", className=" + className
284 +", name=" + name
285 +", loaderName=" + loaderName);
286
287 return (ObjectInstance)
288 doPrivilegedOperation(
289 CREATE_MBEAN_LOADER,
290 params,
291 delegationSubject);
292 } catch (PrivilegedActionException pe) {
293 Exception e = extractException(pe);
294 if (e instanceof ReflectionException)
295 throw (ReflectionException) e;
296 if (e instanceof InstanceAlreadyExistsException)
297 throw (InstanceAlreadyExistsException) e;
298 if (e instanceof MBeanRegistrationException)
299 throw (MBeanRegistrationException) e;
300 if (e instanceof MBeanException)
301 throw (MBeanException) e;
302 if (e instanceof NotCompliantMBeanException)
303 throw (NotCompliantMBeanException) e;
304 if (e instanceof InstanceNotFoundException)
305 throw (InstanceNotFoundException) e;
306 if (e instanceof IOException)
307 throw (IOException) e;
308 throw newIOException("Got unexpected server exception: " + e, e);
309 }
310 }
311
312 public ObjectInstance createMBean(String className,
313 ObjectName name,
314 MarshalledObject params,
315 String signature[],
316 Subject delegationSubject)
317 throws
318 ReflectionException,
319 InstanceAlreadyExistsException,
320 MBeanRegistrationException,
321 MBeanException,
322 NotCompliantMBeanException,
323 IOException {
324
325 final Object[] values;
326 final boolean debug = logger.debugOn();
327
328 if (debug) logger.debug(
329 "createMBean(String,ObjectName,Object[],String[])",
330 "connectionId=" + connectionId
331 +", unwrapping parameters using classLoaderWithRepository.");
332
333 values =
334 nullIsEmpty(unwrap(params, classLoaderWithRepository, Object[].class));
335
336 try {
337 final Object params2[] =
338 new Object[] { className, name, values,
339 nullIsEmpty(signature) };
340
341 if (debug)
342 logger.debug("createMBean(String,ObjectName,Object[],String[])",
343 "connectionId=" + connectionId
344 +", className=" + className
345 +", name=" + name
346 +", params=" + objects(values)
347 +", signature=" + strings(signature));
348
349 return (ObjectInstance)
350 doPrivilegedOperation(
351 CREATE_MBEAN_PARAMS,
352 params2,
353 delegationSubject);
354 } catch (PrivilegedActionException pe) {
355 Exception e = extractException(pe);
356 if (e instanceof ReflectionException)
357 throw (ReflectionException) e;
358 if (e instanceof InstanceAlreadyExistsException)
359 throw (InstanceAlreadyExistsException) e;
360 if (e instanceof MBeanRegistrationException)
361 throw (MBeanRegistrationException) e;
362 if (e instanceof MBeanException)
363 throw (MBeanException) e;
364 if (e instanceof NotCompliantMBeanException)
365 throw (NotCompliantMBeanException) e;
366 if (e instanceof IOException)
367 throw (IOException) e;
368 throw newIOException("Got unexpected server exception: " + e, e);
369 }
370 }
371
372 public ObjectInstance createMBean(String className,
373 ObjectName name,
374 ObjectName loaderName,
375 MarshalledObject params,
376 String signature[],
377 Subject delegationSubject)
378 throws
379 ReflectionException,
380 InstanceAlreadyExistsException,
381 MBeanRegistrationException,
382 MBeanException,
383 NotCompliantMBeanException,
384 InstanceNotFoundException,
385 IOException {
386
387 final Object[] values;
388 final boolean debug = logger.debugOn();
389
390 if (debug) logger.debug(
391 "createMBean(String,ObjectName,ObjectName,Object[],String[])",
392 "connectionId=" + connectionId
393 +", unwrapping params with MBean extended ClassLoader.");
394
395 values = nullIsEmpty(unwrap(params,
396 getClassLoader(loaderName),
397 defaultClassLoader,
398 Object[].class));
399
400 try {
401 final Object params2[] =
402 new Object[] { className, name, loaderName, values,
403 nullIsEmpty(signature) };
404
405 if (debug) logger.debug(
406 "createMBean(String,ObjectName,ObjectName,Object[],String[])",
407 "connectionId=" + connectionId
408 +", className=" + className
409 +", name=" + name
410 +", loaderName=" + loaderName
411 +", params=" + objects(values)
412 +", signature=" + strings(signature));
413
414 return (ObjectInstance)
415 doPrivilegedOperation(
416 CREATE_MBEAN_LOADER_PARAMS,
417 params2,
418 delegationSubject);
419 } catch (PrivilegedActionException pe) {
420 Exception e = extractException(pe);
421 if (e instanceof ReflectionException)
422 throw (ReflectionException) e;
423 if (e instanceof InstanceAlreadyExistsException)
424 throw (InstanceAlreadyExistsException) e;
425 if (e instanceof MBeanRegistrationException)
426 throw (MBeanRegistrationException) e;
427 if (e instanceof MBeanException)
428 throw (MBeanException) e;
429 if (e instanceof NotCompliantMBeanException)
430 throw (NotCompliantMBeanException) e;
431 if (e instanceof InstanceNotFoundException)
432 throw (InstanceNotFoundException) e;
433 if (e instanceof IOException)
434 throw (IOException) e;
435 throw newIOException("Got unexpected server exception: " + e, e);
436 }
437 }
438
439 public void unregisterMBean(ObjectName name, Subject delegationSubject)
440 throws
441 InstanceNotFoundException,
442 MBeanRegistrationException,
443 IOException {
444 try {
445 final Object params[] = new Object[] { name };
446
447 if (logger.debugOn()) logger.debug("unregisterMBean",
448 "connectionId=" + connectionId
449 +", name="+name);
450
451 doPrivilegedOperation(
452 UNREGISTER_MBEAN,
453 params,
454 delegationSubject);
455 } catch (PrivilegedActionException pe) {
456 Exception e = extractException(pe);
457 if (e instanceof InstanceNotFoundException)
458 throw (InstanceNotFoundException) e;
459 if (e instanceof MBeanRegistrationException)
460 throw (MBeanRegistrationException) e;
461 if (e instanceof IOException)
462 throw (IOException) e;
463 throw newIOException("Got unexpected server exception: " + e, e);
464 }
465 }
466
467 public ObjectInstance getObjectInstance(ObjectName name,
468 Subject delegationSubject)
469 throws
470 InstanceNotFoundException,
471 IOException {
472
473 checkNonNull("ObjectName", name);
474
475 try {
476 final Object params[] = new Object[] { name };
477
478 if (logger.debugOn()) logger.debug("getObjectInstance",
479 "connectionId=" + connectionId
480 +", name="+name);
481
482 return (ObjectInstance)
483 doPrivilegedOperation(
484 GET_OBJECT_INSTANCE,
485 params,
486 delegationSubject);
487 } catch (PrivilegedActionException pe) {
488 Exception e = extractException(pe);
489 if (e instanceof InstanceNotFoundException)
490 throw (InstanceNotFoundException) e;
491 if (e instanceof IOException)
492 throw (IOException) e;
493 throw newIOException("Got unexpected server exception: " + e, e);
494 }
495 }
496
497 public Set<ObjectInstance>
498 queryMBeans(ObjectName name,
499 MarshalledObject query,
500 Subject delegationSubject)
501 throws IOException {
502 final QueryExp queryValue;
503 final boolean debug=logger.debugOn();
504
505 if (debug) logger.debug("queryMBeans",
506 "connectionId=" + connectionId
507 +" unwrapping query with defaultClassLoader.");
508
509 queryValue = unwrap(query, defaultClassLoader, QueryExp.class);
510
511 try {
512 final Object params[] = new Object[] { name, queryValue };
513
514 if (debug) logger.debug("queryMBeans",
515 "connectionId=" + connectionId
516 +", name="+name +", query="+query);
517
518 return cast(
519 doPrivilegedOperation(
520 QUERY_MBEANS,
521 params,
522 delegationSubject));
523 } catch (PrivilegedActionException pe) {
524 Exception e = extractException(pe);
525 if (e instanceof IOException)
526 throw (IOException) e;
527 throw newIOException("Got unexpected server exception: " + e, e);
528 }
529 }
530
531 public Set<ObjectName>
532 queryNames(ObjectName name,
533 MarshalledObject query,
534 Subject delegationSubject)
535 throws IOException {
536 final QueryExp queryValue;
537 final boolean debug=logger.debugOn();
538
539 if (debug) logger.debug("queryNames",
540 "connectionId=" + connectionId
541 +" unwrapping query with defaultClassLoader.");
542
543 queryValue = unwrap(query, defaultClassLoader, QueryExp.class);
544
545 try {
546 final Object params[] = new Object[] { name, queryValue };
547
548 if (debug) logger.debug("queryNames",
549 "connectionId=" + connectionId
550 +", name="+name +", query="+query);
551
552 return cast(
553 doPrivilegedOperation(
554 QUERY_NAMES,
555 params,
556 delegationSubject));
557 } catch (PrivilegedActionException pe) {
558 Exception e = extractException(pe);
559 if (e instanceof IOException)
560 throw (IOException) e;
561 throw newIOException("Got unexpected server exception: " + e, e);
562 }
563 }
564
565 public boolean isRegistered(ObjectName name,
566 Subject delegationSubject) throws IOException {
567 try {
568 final Object params[] = new Object[] { name };
569 return ((Boolean)
570 doPrivilegedOperation(
571 IS_REGISTERED,
572 params,
573 delegationSubject)).booleanValue();
574 } catch (PrivilegedActionException pe) {
575 Exception e = extractException(pe);
576 if (e instanceof IOException)
577 throw (IOException) e;
578 throw newIOException("Got unexpected server exception: " + e, e);
579 }
580 }
581
582 public Integer getMBeanCount(Subject delegationSubject)
583 throws IOException {
584 try {
585 final Object params[] = new Object[] { };
586
587 if (logger.debugOn()) logger.debug("getMBeanCount",
588 "connectionId=" + connectionId);
589
590 return (Integer)
591 doPrivilegedOperation(
592 GET_MBEAN_COUNT,
593 params,
594 delegationSubject);
595 } catch (PrivilegedActionException pe) {
596 Exception e = extractException(pe);
597 if (e instanceof IOException)
598 throw (IOException) e;
599 throw newIOException("Got unexpected server exception: " + e, e);
600 }
601 }
602
603 public Object getAttribute(ObjectName name,
604 String attribute,
605 Subject delegationSubject)
606 throws
607 MBeanException,
608 AttributeNotFoundException,
609 InstanceNotFoundException,
610 ReflectionException,
611 IOException {
612 try {
613 final Object params[] = new Object[] { name, attribute };
614 if (logger.debugOn()) logger.debug("getAttribute",
615 "connectionId=" + connectionId
616 +", name=" + name
617 +", attribute="+ attribute);
618
619 return
620 doPrivilegedOperation(
621 GET_ATTRIBUTE,
622 params,
623 delegationSubject);
624 } catch (PrivilegedActionException pe) {
625 Exception e = extractException(pe);
626 if (e instanceof MBeanException)
627 throw (MBeanException) e;
628 if (e instanceof AttributeNotFoundException)
629 throw (AttributeNotFoundException) e;
630 if (e instanceof InstanceNotFoundException)
631 throw (InstanceNotFoundException) e;
632 if (e instanceof ReflectionException)
633 throw (ReflectionException) e;
634 if (e instanceof IOException)
635 throw (IOException) e;
636 throw newIOException("Got unexpected server exception: " + e, e);
637 }
638 }
639
640 public AttributeList getAttributes(ObjectName name,
641 String[] attributes,
642 Subject delegationSubject)
643 throws
644 InstanceNotFoundException,
645 ReflectionException,
646 IOException {
647 try {
648 final Object params[] = new Object[] { name, attributes };
649
650 if (logger.debugOn()) logger.debug("getAttributes",
651 "connectionId=" + connectionId
652 +", name=" + name
653 +", attributes="+ strings(attributes));
654
655 return (AttributeList)
656 doPrivilegedOperation(
657 GET_ATTRIBUTES,
658 params,
659 delegationSubject);
660 } catch (PrivilegedActionException pe) {
661 Exception e = extractException(pe);
662 if (e instanceof InstanceNotFoundException)
663 throw (InstanceNotFoundException) e;
664 if (e instanceof ReflectionException)
665 throw (ReflectionException) e;
666 if (e instanceof IOException)
667 throw (IOException) e;
668 throw newIOException("Got unexpected server exception: " + e, e);
669 }
670 }
671
672 public void setAttribute(ObjectName name,
673 MarshalledObject attribute,
674 Subject delegationSubject)
675 throws
676 InstanceNotFoundException,
677 AttributeNotFoundException,
678 InvalidAttributeValueException,
679 MBeanException,
680 ReflectionException,
681 IOException {
682 final Attribute attr;
683 final boolean debug=logger.debugOn();
684
685 if (debug) logger.debug("setAttribute",
686 "connectionId=" + connectionId
687 +" unwrapping attribute with MBean extended ClassLoader.");
688
689 attr = unwrap(attribute,
690 getClassLoaderFor(name),
691 defaultClassLoader,
692 Attribute.class);
693
694 try {
695 final Object params[] = new Object[] { name, attr };
696
697 if (debug) logger.debug("setAttribute",
698 "connectionId=" + connectionId
699 +", name="+name
700 +", attribute="+attr);
701
702 doPrivilegedOperation(
703 SET_ATTRIBUTE,
704 params,
705 delegationSubject);
706 } catch (PrivilegedActionException pe) {
707 Exception e = extractException(pe);
708 if (e instanceof InstanceNotFoundException)
709 throw (InstanceNotFoundException) e;
710 if (e instanceof AttributeNotFoundException)
711 throw (AttributeNotFoundException) e;
712 if (e instanceof InvalidAttributeValueException)
713 throw (InvalidAttributeValueException) e;
714 if (e instanceof MBeanException)
715 throw (MBeanException) e;
716 if (e instanceof ReflectionException)
717 throw (ReflectionException) e;
718 if (e instanceof IOException)
719 throw (IOException) e;
720 throw newIOException("Got unexpected server exception: " + e, e);
721 }
722 }
723
724 public AttributeList setAttributes(ObjectName name,
725 MarshalledObject attributes,
726 Subject delegationSubject)
727 throws
728 InstanceNotFoundException,
729 ReflectionException,
730 IOException {
731 final AttributeList attrlist;
732 final boolean debug=logger.debugOn();
733
734 if (debug) logger.debug("setAttributes",
735 "connectionId=" + connectionId
736 +" unwrapping attributes with MBean extended ClassLoader.");
737
738 attrlist =
739 unwrap(attributes,
740 getClassLoaderFor(name),
741 defaultClassLoader,
742 AttributeList.class);
743
744 try {
745 final Object params[] = new Object[] { name, attrlist };
746
747 if (debug) logger.debug("setAttributes",
748 "connectionId=" + connectionId
749 +", name="+name
750 +", attributes="+attrlist);
751
752 return (AttributeList)
753 doPrivilegedOperation(
754 SET_ATTRIBUTES,
755 params,
756 delegationSubject);
757 } catch (PrivilegedActionException pe) {
758 Exception e = extractException(pe);
759 if (e instanceof InstanceNotFoundException)
760 throw (InstanceNotFoundException) e;
761 if (e instanceof ReflectionException)
762 throw (ReflectionException) e;
763 if (e instanceof IOException)
764 throw (IOException) e;
765 throw newIOException("Got unexpected server exception: " + e, e);
766 }
767 }
768
769 public Object invoke(ObjectName name,
770 String operationName,
771 MarshalledObject params,
772 String signature[],
773 Subject delegationSubject)
774 throws
775 InstanceNotFoundException,
776 MBeanException,
777 ReflectionException,
778 IOException {
779
780 checkNonNull("ObjectName", name);
781 checkNonNull("Operation name", operationName);
782
783 final Object[] values;
784 final boolean debug=logger.debugOn();
785
786 if (debug) logger.debug("invoke",
787 "connectionId=" + connectionId
788 +" unwrapping params with MBean extended ClassLoader.");
789
790 values = nullIsEmpty(unwrap(params,
791 getClassLoaderFor(name),
792 defaultClassLoader,
793 Object[].class));
794
795 try {
796 final Object params2[] =
797 new Object[] { name, operationName, values,
798 nullIsEmpty(signature) };
799
800 if (debug) logger.debug("invoke",
801 "connectionId=" + connectionId
802 +", name="+name
803 +", operationName="+operationName
804 +", params="+objects(values)
805 +", signature="+strings(signature));
806
807 return
808 doPrivilegedOperation(
809 INVOKE,
810 params2,
811 delegationSubject);
812 } catch (PrivilegedActionException pe) {
813 Exception e = extractException(pe);
814 if (e instanceof InstanceNotFoundException)
815 throw (InstanceNotFoundException) e;
816 if (e instanceof MBeanException)
817 throw (MBeanException) e;
818 if (e instanceof ReflectionException)
819 throw (ReflectionException) e;
820 if (e instanceof IOException)
821 throw (IOException) e;
822 throw newIOException("Got unexpected server exception: " + e, e);
823 }
824 }
825
826 public String getDefaultDomain(Subject delegationSubject)
827 throws IOException {
828 try {
829 final Object params[] = new Object[] { };
830
831 if (logger.debugOn()) logger.debug("getDefaultDomain",
832 "connectionId=" + connectionId);
833
834 return (String)
835 doPrivilegedOperation(
836 GET_DEFAULT_DOMAIN,
837 params,
838 delegationSubject);
839 } catch (PrivilegedActionException pe) {
840 Exception e = extractException(pe);
841 if (e instanceof IOException)
842 throw (IOException) e;
843 throw newIOException("Got unexpected server exception: " + e, e);
844 }
845 }
846
847 public String[] getDomains(Subject delegationSubject) throws IOException {
848 try {
849 final Object params[] = new Object[] { };
850
851 if (logger.debugOn()) logger.debug("getDomains",
852 "connectionId=" + connectionId);
853
854 return (String[])
855 doPrivilegedOperation(
856 GET_DOMAINS,
857 params,
858 delegationSubject);
859 } catch (PrivilegedActionException pe) {
860 Exception e = extractException(pe);
861 if (e instanceof IOException)
862 throw (IOException) e;
863 throw newIOException("Got unexpected server exception: " + e, e);
864 }
865 }
866
867 public MBeanInfo getMBeanInfo(ObjectName name, Subject delegationSubject)
868 throws
869 InstanceNotFoundException,
870 IntrospectionException,
871 ReflectionException,
872 IOException {
873
874 checkNonNull("ObjectName", name);
875
876 try {
877 final Object params[] = new Object[] { name };
878
879 if (logger.debugOn()) logger.debug("getMBeanInfo",
880 "connectionId=" + connectionId
881 +", name="+name);
882
883 return (MBeanInfo)
884 doPrivilegedOperation(
885 GET_MBEAN_INFO,
886 params,
887 delegationSubject);
888 } catch (PrivilegedActionException pe) {
889 Exception e = extractException(pe);
890 if (e instanceof InstanceNotFoundException)
891 throw (InstanceNotFoundException) e;
892 if (e instanceof IntrospectionException)
893 throw (IntrospectionException) e;
894 if (e instanceof ReflectionException)
895 throw (ReflectionException) e;
896 if (e instanceof IOException)
897 throw (IOException) e;
898 throw newIOException("Got unexpected server exception: " + e, e);
899 }
900 }
901
902 public boolean isInstanceOf(ObjectName name,
903 String className,
904 Subject delegationSubject)
905 throws InstanceNotFoundException, IOException {
906
907 checkNonNull("ObjectName", name);
908
909 try {
910 final Object params[] = new Object[] { name, className };
911
912 if (logger.debugOn()) logger.debug("isInstanceOf",
913 "connectionId=" + connectionId
914 +", name="+name
915 +", className="+className);
916
917 return ((Boolean)
918 doPrivilegedOperation(
919 IS_INSTANCE_OF,
920 params,
921 delegationSubject)).booleanValue();
922 } catch (PrivilegedActionException pe) {
923 Exception e = extractException(pe);
924 if (e instanceof InstanceNotFoundException)
925 throw (InstanceNotFoundException) e;
926 if (e instanceof IOException)
927 throw (IOException) e;
928 throw newIOException("Got unexpected server exception: " + e, e);
929 }
930 }
931
932 public Integer[] addNotificationListeners(ObjectName[] names,
933 MarshalledObject[] filters,
934 Subject[] delegationSubjects)
935 throws InstanceNotFoundException, IOException {
936
937 if (names == null || filters == null) {
938 throw new IllegalArgumentException("Got null arguments.");
939 }
940
941 Subject[] sbjs = (delegationSubjects != null) ? delegationSubjects :
942 new Subject[names.length];
943 if (names.length != filters.length || filters.length != sbjs.length) {
944 final String msg =
945 "The value lengths of 3 parameters are not same.";
946 throw new IllegalArgumentException(msg);
947 }
948
949 for (int i=0; i<names.length; i++) {
950 if (names[i] == null) {
951 throw new IllegalArgumentException("Null Object name.");
952 }
953 }
954
955 int i=0;
956 ClassLoader targetCl;
957 NotificationFilter[] filterValues =
958 new NotificationFilter[names.length];
959 Object params[];
960 Integer[] ids = new Integer[names.length];
961 final boolean debug=logger.debugOn();
962
963 try {
964 for (; i<names.length; i++) {
965 targetCl = getClassLoaderFor(names[i]);
966
967 if (debug) logger.debug("addNotificationListener"+
968 "(ObjectName,NotificationFilter)",
969 "connectionId=" + connectionId +
970 " unwrapping filter with target extended ClassLoader.");
971
972 filterValues[i] =
973 unwrap(filters[i], targetCl, defaultClassLoader,
974 NotificationFilter.class);
975
976 if (debug) logger.debug("addNotificationListener"+
977 "(ObjectName,NotificationFilter)",
978 "connectionId=" + connectionId
979 +", name=" + names[i]
980 +", filter=" + filterValues[i]);
981
982 ids[i] = (Integer)
983 doPrivilegedOperation(ADD_NOTIFICATION_LISTENERS,
984 new Object[] { names[i],
985 filterValues[i] },
986 sbjs[i]);
987 }
988
989 return ids;
990 } catch (Exception e) {
991 // remove all registered listeners
992 for (int j=0; j<i; j++) {
993 try {
994 getServerNotifFwd().removeNotificationListener(names[j],
995 ids[j]);
996 } catch (Exception eee) {
997 // strange
998 }
999 }
1000
1001 if (e instanceof PrivilegedActionException) {
1002 e = extractException(e);
1003 }
1004
1005 if (e instanceof ClassCastException) {
1006 throw (ClassCastException) e;
1007 } else if (e instanceof IOException) {
1008 throw (IOException)e;
1009 } else if (e instanceof InstanceNotFoundException) {
1010 throw (InstanceNotFoundException) e;
1011 } else if (e instanceof RuntimeException) {
1012 throw (RuntimeException) e;
1013 } else {
1014 throw newIOException("Got unexpected server exception: "+e,e);
1015 }
1016 }
1017 }
1018
1019 public void addNotificationListener(ObjectName name,
1020 ObjectName listener,
1021 MarshalledObject filter,
1022 MarshalledObject handback,
1023 Subject delegationSubject)
1024 throws InstanceNotFoundException, IOException {
1025
1026 checkNonNull("Target MBean name", name);
1027 checkNonNull("Listener MBean name", listener);
1028
1029 final NotificationFilter filterValue;
1030 final Object handbackValue;
1031 final boolean debug=logger.debugOn();
1032
1033 final ClassLoader targetCl = getClassLoaderFor(name);
1034
1035 if (debug) logger.debug("addNotificationListener"+
1036 "(ObjectName,ObjectName,NotificationFilter,Object)",
1037 "connectionId=" + connectionId
1038 +" unwrapping filter with target extended ClassLoader.");
1039
1040 filterValue =
1041 unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class);
1042
1043 if (debug) logger.debug("addNotificationListener"+
1044 "(ObjectName,ObjectName,NotificationFilter,Object)",
1045 "connectionId=" + connectionId
1046 +" unwrapping handback with target extended ClassLoader.");
1047
1048 handbackValue =
1049 unwrap(handback, targetCl, defaultClassLoader, Object.class);
1050
1051 try {
1052 final Object params[] =
1053 new Object[] { name, listener, filterValue, handbackValue };
1054
1055 if (debug) logger.debug("addNotificationListener"+
1056 "(ObjectName,ObjectName,NotificationFilter,Object)",
1057 "connectionId=" + connectionId
1058 +", name=" + name
1059 +", listenerName=" + listener
1060 +", filter=" + filterValue
1061 +", handback=" + handbackValue);
1062
1063 doPrivilegedOperation(
1064 ADD_NOTIFICATION_LISTENER_OBJECTNAME,
1065 params,
1066 delegationSubject);
1067 } catch (PrivilegedActionException pe) {
1068 Exception e = extractException(pe);
1069 if (e instanceof InstanceNotFoundException)
1070 throw (InstanceNotFoundException) e;
1071 if (e instanceof IOException)
1072 throw (IOException) e;
1073 throw newIOException("Got unexpected server exception: " + e, e);
1074 }
1075 }
1076
1077 public void removeNotificationListeners(ObjectName name,
1078 Integer[] listenerIDs,
1079 Subject delegationSubject)
1080 throws
1081 InstanceNotFoundException,
1082 ListenerNotFoundException,
1083 IOException {
1084
1085 if (name == null || listenerIDs == null)
1086 throw new IllegalArgumentException("Illegal null parameter");
1087
1088 for (int i = 0; i < listenerIDs.length; i++) {
1089 if (listenerIDs[i] == null)
1090 throw new IllegalArgumentException("Null listener ID");
1091 }
1092
1093 try {
1094 final Object params[] = new Object[] { name, listenerIDs };
1095
1096 if (logger.debugOn()) logger.debug("removeNotificationListener"+
1097 "(ObjectName,Integer[])",
1098 "connectionId=" + connectionId
1099 +", name=" + name
1100 +", listenerIDs=" + objects(listenerIDs));
1101
1102 doPrivilegedOperation(
1103 REMOVE_NOTIFICATION_LISTENER,
1104 params,
1105 delegationSubject);
1106 } catch (PrivilegedActionException pe) {
1107 Exception e = extractException(pe);
1108 if (e instanceof InstanceNotFoundException)
1109 throw (InstanceNotFoundException) e;
1110 if (e instanceof ListenerNotFoundException)
1111 throw (ListenerNotFoundException) e;
1112 if (e instanceof IOException)
1113 throw (IOException) e;
1114 throw newIOException("Got unexpected server exception: " + e, e);
1115 }
1116 }
1117
1118 public void removeNotificationListener(ObjectName name,
1119 ObjectName listener,
1120 Subject delegationSubject)
1121 throws
1122 InstanceNotFoundException,
1123 ListenerNotFoundException,
1124 IOException {
1125
1126 checkNonNull("Target MBean name", name);
1127 checkNonNull("Listener MBean name", listener);
1128
1129 try {
1130 final Object params[] = new Object[] { name, listener };
1131
1132 if (logger.debugOn()) logger.debug("removeNotificationListener"+
1133 "(ObjectName,ObjectName)",
1134 "connectionId=" + connectionId
1135 +", name=" + name
1136 +", listenerName=" + listener);
1137
1138 doPrivilegedOperation(
1139 REMOVE_NOTIFICATION_LISTENER_OBJECTNAME,
1140 params,
1141 delegationSubject);
1142 } catch (PrivilegedActionException pe) {
1143 Exception e = extractException(pe);
1144 if (e instanceof InstanceNotFoundException)
1145 throw (InstanceNotFoundException) e;
1146 if (e instanceof ListenerNotFoundException)
1147 throw (ListenerNotFoundException) e;
1148 if (e instanceof IOException)
1149 throw (IOException) e;
1150 throw newIOException("Got unexpected server exception: " + e, e);
1151 }
1152 }
1153
1154 public void removeNotificationListener(ObjectName name,
1155 ObjectName listener,
1156 MarshalledObject filter,
1157 MarshalledObject handback,
1158 Subject delegationSubject)
1159 throws
1160 InstanceNotFoundException,
1161 ListenerNotFoundException,
1162 IOException {
1163
1164 checkNonNull("Target MBean name", name);
1165 checkNonNull("Listener MBean name", listener);
1166
1167 final NotificationFilter filterValue;
1168 final Object handbackValue;
1169 final boolean debug=logger.debugOn();
1170
1171 final ClassLoader targetCl = getClassLoaderFor(name);
1172
1173 if (debug) logger.debug("removeNotificationListener"+
1174 "(ObjectName,ObjectName,NotificationFilter,Object)",
1175 "connectionId=" + connectionId
1176 +" unwrapping filter with target extended ClassLoader.");
1177
1178 filterValue =
1179 unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class);
1180
1181 if (debug) logger.debug("removeNotificationListener"+
1182 "(ObjectName,ObjectName,NotificationFilter,Object)",
1183 "connectionId=" + connectionId
1184 +" unwrapping handback with target extended ClassLoader.");
1185
1186 handbackValue =
1187 unwrap(handback, targetCl, defaultClassLoader, Object.class);
1188
1189 try {
1190 final Object params[] =
1191 new Object[] { name, listener, filterValue, handbackValue };
1192
1193 if (debug) logger.debug("removeNotificationListener"+
1194 "(ObjectName,ObjectName,NotificationFilter,Object)",
1195 "connectionId=" + connectionId
1196 +", name=" + name
1197 +", listenerName=" + listener
1198 +", filter=" + filterValue
1199 +", handback=" + handbackValue);
1200
1201 doPrivilegedOperation(
1202 REMOVE_NOTIFICATION_LISTENER_OBJECTNAME_FILTER_HANDBACK,
1203 params,
1204 delegationSubject);
1205 } catch (PrivilegedActionException pe) {
1206 Exception e = extractException(pe);
1207 if (e instanceof InstanceNotFoundException)
1208 throw (InstanceNotFoundException) e;
1209 if (e instanceof ListenerNotFoundException)
1210 throw (ListenerNotFoundException) e;
1211 if (e instanceof IOException)
1212 throw (IOException) e;
1213 throw newIOException("Got unexpected server exception: " + e, e);
1214 }
1215 }
1216
1217 public NotificationResult fetchNotifications(long clientSequenceNumber,
1218 int maxNotifications,
1219 long timeout)
1220 throws IOException {
1221
1222 if (logger.debugOn()) logger.debug("fetchNotifications",
1223 "connectionId=" + connectionId
1224 +", timeout=" + timeout);
1225
1226 if (maxNotifications < 0 || timeout < 0)
1227 throw new IllegalArgumentException("Illegal negative argument");
1228
1229 final boolean serverTerminated =
1230 serverCommunicatorAdmin.reqIncoming();
1231 try {
1232 if (serverTerminated) {
1233 // we must not call fetchNotifs() if the server is
1234 // terminated (timeout elapsed).
1235 //
1236 return new NotificationResult(0L, 0L,
1237 new TargetedNotification[0]);
1238
1239 }
1240 final long csn = clientSequenceNumber;
1241 final int mn = maxNotifications;
1242 final long t = timeout;
1243 PrivilegedAction<NotificationResult> action =
1244 new PrivilegedAction<NotificationResult>() {
1245 public NotificationResult run() {
1246 return getServerNotifFwd().fetchNotifs(csn, t, mn);
1247 }
1248 };
1249 if (acc == null)
1250 return action.run();
1251 else
1252 return AccessController.doPrivileged(action, acc);
1253 } finally {
1254 serverCommunicatorAdmin.rspOutgoing();
1255 }
1256 }
1257
1258 /**
1259 * <p>Returns a string representation of this object. In general,
1260 * the <code>toString</code> method returns a string that
1261 * "textually represents" this object. The result should be a
1262 * concise but informative representation that is easy for a
1263 * person to read.</p>
1264 *
1265 * @return a String representation of this object.
1266 **/
1267 public String toString() {
1268 return super.toString() + ": connectionId=" + connectionId;
1269 }
1270
1271 //------------------------------------------------------------------------
1272 // private classes
1273 //------------------------------------------------------------------------
1274
1275 private class PrivilegedOperation
1276 implements PrivilegedExceptionAction<Object> {
1277
1278 public PrivilegedOperation(int operation, Object[] params) {
1279 this.operation = operation;
1280 this.params = params;
1281 }
1282
1283 public Object run() throws Exception {
1284 return doOperation(operation, params);
1285 }
1286
1287 private int operation;
1288 private Object[] params;
1289 }
1290
1291 //------------------------------------------------------------------------
1292 // private classes
1293 //------------------------------------------------------------------------
1294 private class RMIServerCommunicatorAdmin extends ServerCommunicatorAdmin {
1295 public RMIServerCommunicatorAdmin(long timeout) {
1296 super(timeout);
1297 }
1298
1299 protected void doStop() {
1300 try {
1301 close();
1302 } catch (IOException ie) {
1303 logger.warning("RMIServerCommunicatorAdmin-doStop",
1304 "Failed to close: " + ie);
1305 logger.debug("RMIServerCommunicatorAdmin-doStop",ie);
1306 }
1307 }
1308
1309 }
1310
1311
1312 //------------------------------------------------------------------------
1313 // private methods
1314 //------------------------------------------------------------------------
1315
1316 private ClassLoaderRepository getClassLoaderRepository() {
1317 return
1318 AccessController.doPrivileged(
1319 new PrivilegedAction<ClassLoaderRepository>() {
1320 public ClassLoaderRepository run() {
1321 return mbeanServer.getClassLoaderRepository();
1322 }
1323 });
1324 }
1325
1326 private ClassLoader getClassLoader(final ObjectName name)
1327 throws InstanceNotFoundException {
1328 try {
1329 return
1330 AccessController.doPrivileged(
1331 new PrivilegedExceptionAction<ClassLoader>() {
1332 public ClassLoader run() throws InstanceNotFoundException {
1333 return mbeanServer.getClassLoader(name);
1334 }
1335 });
1336 } catch (PrivilegedActionException pe) {
1337 throw (InstanceNotFoundException) extractException(pe);
1338 }
1339 }
1340
1341 private ClassLoader getClassLoaderFor(final ObjectName name)
1342 throws InstanceNotFoundException {
1343 try {
1344 return (ClassLoader)
1345 AccessController.doPrivileged(
1346 new PrivilegedExceptionAction<Object>() {
1347 public Object run() throws InstanceNotFoundException {
1348 return mbeanServer.getClassLoaderFor(name);
1349 }
1350 });
1351 } catch (PrivilegedActionException pe) {
1352 throw (InstanceNotFoundException) extractException(pe);
1353 }
1354 }
1355
1356 private Object doPrivilegedOperation(final int operation,
1357 final Object[] params,
1358 final Subject delegationSubject)
1359 throws PrivilegedActionException, IOException {
1360
1361 serverCommunicatorAdmin.reqIncoming();
1362 try {
1363
1364 final AccessControlContext reqACC;
1365 if (delegationSubject == null)
1366 reqACC = acc;
1367 else {
1368 if (subject == null) {
1369 final String msg =
1370 "Subject delegation cannot be enabled unless " +
1371 "an authenticated subject is put in place";
1372 throw new SecurityException(msg);
1373 }
1374 reqACC = subjectDelegator.delegatedContext(
1375 acc, delegationSubject, removeCallerContext);
1376 }
1377
1378 PrivilegedOperation op =
1379 new PrivilegedOperation(operation, params);
1380 if (reqACC == null) {
1381 try {
1382 return op.run();
1383 } catch (Exception e) {
1384 if (e instanceof RuntimeException)
1385 throw (RuntimeException) e;
1386 throw new PrivilegedActionException(e);
1387 }
1388 } else {
1389 return AccessController.doPrivileged(op, reqACC);
1390 }
1391 } catch (Error e) {
1392 throw new JMXServerErrorException(e.toString(),e);
1393 } finally {
1394 serverCommunicatorAdmin.rspOutgoing();
1395 }
1396 }
1397
1398 private Object doOperation(int operation, Object[] params)
1399 throws Exception {
1400
1401 switch (operation) {
1402
1403 case CREATE_MBEAN:
1404 return mbeanServer.createMBean((String)params[0],
1405 (ObjectName)params[1]);
1406
1407 case CREATE_MBEAN_LOADER:
1408 return mbeanServer.createMBean((String)params[0],
1409 (ObjectName)params[1],
1410 (ObjectName)params[2]);
1411
1412 case CREATE_MBEAN_PARAMS:
1413 return mbeanServer.createMBean((String)params[0],
1414 (ObjectName)params[1],
1415 (Object[])params[2],
1416 (String[])params[3]);
1417
1418 case CREATE_MBEAN_LOADER_PARAMS:
1419 return mbeanServer.createMBean((String)params[0],
1420 (ObjectName)params[1],
1421 (ObjectName)params[2],
1422 (Object[])params[3],
1423 (String[])params[4]);
1424
1425 case GET_ATTRIBUTE:
1426 return mbeanServer.getAttribute((ObjectName)params[0],
1427 (String)params[1]);
1428
1429 case GET_ATTRIBUTES:
1430 return mbeanServer.getAttributes((ObjectName)params[0],
1431 (String[])params[1]);
1432
1433 case GET_DEFAULT_DOMAIN:
1434 return mbeanServer.getDefaultDomain();
1435
1436 case GET_DOMAINS:
1437 return mbeanServer.getDomains();
1438
1439 case GET_MBEAN_COUNT:
1440 return mbeanServer.getMBeanCount();
1441
1442 case GET_MBEAN_INFO:
1443 return mbeanServer.getMBeanInfo((ObjectName)params[0]);
1444
1445 case GET_OBJECT_INSTANCE:
1446 return mbeanServer.getObjectInstance((ObjectName)params[0]);
1447
1448 case INVOKE:
1449 return mbeanServer.invoke((ObjectName)params[0],
1450 (String)params[1],
1451 (Object[])params[2],
1452 (String[])params[3]);
1453
1454 case IS_INSTANCE_OF:
1455 return mbeanServer.isInstanceOf((ObjectName)params[0],
1456 (String)params[1])
1457 ? Boolean.TRUE : Boolean.FALSE;
1458
1459 case IS_REGISTERED:
1460 return mbeanServer.isRegistered((ObjectName)params[0])
1461 ? Boolean.TRUE : Boolean.FALSE;
1462
1463 case QUERY_MBEANS:
1464 return mbeanServer.queryMBeans((ObjectName)params[0],
1465 (QueryExp)params[1]);
1466
1467 case QUERY_NAMES:
1468 return mbeanServer.queryNames((ObjectName)params[0],
1469 (QueryExp)params[1]);
1470
1471 case SET_ATTRIBUTE:
1472 mbeanServer.setAttribute((ObjectName)params[0],
1473 (Attribute)params[1]);
1474 return null;
1475
1476 case SET_ATTRIBUTES:
1477 return mbeanServer.setAttributes((ObjectName)params[0],
1478 (AttributeList)params[1]);
1479
1480 case UNREGISTER_MBEAN:
1481 mbeanServer.unregisterMBean((ObjectName)params[0]);
1482 return null;
1483
1484 case ADD_NOTIFICATION_LISTENERS:
1485 return getServerNotifFwd().addNotificationListener(
1486 (ObjectName)params[0],
1487 (NotificationFilter)params[1]);
1488
1489 case ADD_NOTIFICATION_LISTENER_OBJECTNAME:
1490 mbeanServer.addNotificationListener((ObjectName)params[0],
1491 (ObjectName)params[1],
1492 (NotificationFilter)params[2],
1493 params[3]);
1494 return null;
1495
1496 case REMOVE_NOTIFICATION_LISTENER:
1497 getServerNotifFwd().removeNotificationListener(
1498 (ObjectName)params[0],
1499 (Integer[])params[1]);
1500 return null;
1501
1502 case REMOVE_NOTIFICATION_LISTENER_OBJECTNAME:
1503 mbeanServer.removeNotificationListener((ObjectName)params[0],
1504 (ObjectName)params[1]);
1505 return null;
1506
1507 case REMOVE_NOTIFICATION_LISTENER_OBJECTNAME_FILTER_HANDBACK:
1508 mbeanServer.removeNotificationListener(
1509 (ObjectName)params[0],
1510 (ObjectName)params[1],
1511 (NotificationFilter)params[2],
1512 params[3]);
1513 return null;
1514
1515 default:
1516 throw new IllegalArgumentException("Invalid operation");
1517 }
1518 }
1519
1520 private static <T> T unwrap(final MarshalledObject mo,
1521 final ClassLoader cl,
1522 final Class<T> wrappedClass)
1523 throws IOException {
1524 if (mo == null) {
1525 return null;
1526 }
1527 try {
1528 return AccessController.doPrivileged(
1529 new PrivilegedExceptionAction<T>() {
1530 public T run()
1531 throws IOException {
1532 final ClassLoader old =
1533 Thread.currentThread().getContextClassLoader();
1534 Thread.currentThread().setContextClassLoader(cl);
1535 try {
1536 return wrappedClass.cast(mo.get());
1537 } catch (ClassNotFoundException cnfe) {
1538 throw new UnmarshalException(cnfe.toString(), cnfe);
1539 } finally {
1540 Thread.currentThread().setContextClassLoader(old);
1541 }
1542 }
1543 });
1544 } catch (PrivilegedActionException pe) {
1545 Exception e = extractException(pe);
1546 if (e instanceof IOException) {
1547 throw (IOException) e;
1548 }
1549 if (e instanceof ClassNotFoundException) {
1550 throw new UnmarshalException(e.toString(), e);
1551 }
1552 logger.warning("unwrap", "Failed to unmarshall object: " + e);
1553 logger.debug("unwrap", e);
1554 }
1555 return null;
1556 }
1557
1558 private static <T> T unwrap(final MarshalledObject mo,
1559 final ClassLoader cl1,
1560 final ClassLoader cl2,
1561 final Class<T> wrappedClass)
1562 throws IOException {
1563 if (mo == null) {
1564 return null;
1565 }
1566 try {
1567 return AccessController.doPrivileged(
1568 new PrivilegedExceptionAction<T>() {
1569 public T run()
1570 throws IOException {
1571 return unwrap(mo, new OrderClassLoaders(cl1, cl2),
1572 wrappedClass);
1573 }
1574 });
1575 } catch (PrivilegedActionException pe) {
1576 Exception e = extractException(pe);
1577 if (e instanceof IOException) {
1578 throw (IOException) e;
1579 }
1580 if (e instanceof ClassNotFoundException) {
1581 throw new UnmarshalException(e.toString(), e);
1582 }
1583 logger.warning("unwrap", "Failed to unmarshall object: " + e);
1584 logger.debug("unwrap", e);
1585 }
1586 return null;
1587 }
1588
1589 /**
1590 * Construct a new IOException with a nested exception.
1591 * The nested exception is set only if JDK >= 1.4
1592 */
1593 private static IOException newIOException(String message,
1594 Throwable cause) {
1595 final IOException x = new IOException(message);
1596 return EnvHelp.initCause(x,cause);
1597 }
1598
1599 /**
1600 * Iterate until we extract the real exception
1601 * from a stack of PrivilegedActionExceptions.
1602 */
1603 private static Exception extractException(Exception e) {
1604 while (e instanceof PrivilegedActionException) {
1605 e = ((PrivilegedActionException)e).getException();
1606 }
1607 return e;
1608 }
1609
1610 private static final Object[] NO_OBJECTS = new Object[0];
1611 private static final String[] NO_STRINGS = new String[0];
1612
1613 /*
1614 * The JMX spec doesn't explicitly say that a null Object[] or
1615 * String[] in e.g. MBeanServer.invoke is equivalent to an empty
1616 * array, but the RI behaves that way. In the interests of
1617 * maximal interoperability, we make it so even when we're
1618 * connected to some other JMX implementation that might not do
1619 * that. This should be clarified in the next version of JMX.
1620 */
1621 private static Object[] nullIsEmpty(Object[] array) {
1622 return (array == null) ? NO_OBJECTS : array;
1623 }
1624
1625 private static String[] nullIsEmpty(String[] array) {
1626 return (array == null) ? NO_STRINGS : array;
1627 }
1628
1629 /*
1630 * Similarly, the JMX spec says for some but not all methods in
1631 * MBeanServer that take an ObjectName target, that if it's null
1632 * you get this exception. We specify it for all of them, and
1633 * make it so for the ones where it's not specified in JMX even if
1634 * the JMX implementation doesn't do so.
1635 */
1636 private static void checkNonNull(String what, Object x) {
1637 if (x == null) {
1638 RuntimeException wrapped =
1639 new IllegalArgumentException(what + " must not be null");
1640 throw new RuntimeOperationsException(wrapped);
1641 }
1642 }
1643
1644 //------------------------------------------------------------------------
1645 // private variables
1646 //------------------------------------------------------------------------
1647
1648 private final Subject subject;
1649
1650 private final SubjectDelegator subjectDelegator;
1651
1652 private final boolean removeCallerContext;
1653
1654 private final AccessControlContext acc;
1655
1656 private final RMIServerImpl rmiServer;
1657
1658 private final MBeanServer mbeanServer;
1659
1660 private final ClassLoader defaultClassLoader;
1661
1662 private final ClassLoaderWithRepository classLoaderWithRepository;
1663
1664 private boolean terminated = false;
1665
1666 private final String connectionId;
1667
1668 private final ServerCommunicatorAdmin serverCommunicatorAdmin;
1669
1670 // Method IDs for doOperation
1671 //---------------------------
1672
1673 private final static int
1674 ADD_NOTIFICATION_LISTENERS = 1;
1675 private final static int
1676 ADD_NOTIFICATION_LISTENER_OBJECTNAME = 2;
1677 private final static int
1678 CREATE_MBEAN = 3;
1679 private final static int
1680 CREATE_MBEAN_PARAMS = 4;
1681 private final static int
1682 CREATE_MBEAN_LOADER = 5;
1683 private final static int
1684 CREATE_MBEAN_LOADER_PARAMS = 6;
1685 private final static int
1686 GET_ATTRIBUTE = 7;
1687 private final static int
1688 GET_ATTRIBUTES = 8;
1689 private final static int
1690 GET_DEFAULT_DOMAIN = 9;
1691 private final static int
1692 GET_DOMAINS = 10;
1693 private final static int
1694 GET_MBEAN_COUNT = 11;
1695 private final static int
1696 GET_MBEAN_INFO = 12;
1697 private final static int
1698 GET_OBJECT_INSTANCE = 13;
1699 private final static int
1700 INVOKE = 14;
1701 private final static int
1702 IS_INSTANCE_OF = 15;
1703 private final static int
1704 IS_REGISTERED = 16;
1705 private final static int
1706 QUERY_MBEANS = 17;
1707 private final static int
1708 QUERY_NAMES = 18;
1709 private final static int
1710 REMOVE_NOTIFICATION_LISTENER = 19;
1711 private final static int
1712 REMOVE_NOTIFICATION_LISTENER_FILTER_HANDBACK = 20;
1713 private final static int
1714 REMOVE_NOTIFICATION_LISTENER_OBJECTNAME = 21;
1715 private final static int
1716 REMOVE_NOTIFICATION_LISTENER_OBJECTNAME_FILTER_HANDBACK = 22;
1717 private final static int
1718 SET_ATTRIBUTE = 23;
1719 private final static int
1720 SET_ATTRIBUTES = 24;
1721 private final static int
1722 UNREGISTER_MBEAN = 25;
1723
1724 // SERVER NOTIFICATION
1725 //--------------------
1726
1727 private ServerNotifForwarder serverNotifForwarder;
1728 private Map env;
1729
1730 // TRACES & DEBUG
1731 //---------------
1732
1733 private static String objects(final Object[] objs) {
1734 if (objs == null)
1735 return "null";
1736 else
1737 return Arrays.asList(objs).toString();
1738 }
1739
1740 private static String strings(final String[] strs) {
1741 return objects(strs);
1742 }
1743
1744 private static final ClassLogger logger =
1745 new ClassLogger("javax.management.remote.rmi", "RMIConnectionImpl");
1746 }