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