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