1. /*
  2. * @(#)MBeanInstantiatorImpl.java 1.29 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.jmx.mbeanserver;
  8. import java.lang.reflect.Constructor;
  9. import java.lang.reflect.InvocationTargetException;
  10. import java.io.*;
  11. import javax.management.*;
  12. import javax.management.loading.ClassLoaderRepository;
  13. import com.sun.jmx.trace.Trace;
  14. /**
  15. * Implements the MBeanInstantiator interface. Provides methods for
  16. * instantiating objects, finding the class given its name and using
  17. * different class loaders, deserializing objects in the context of a
  18. * given class loader.
  19. *
  20. * @since 1.5
  21. * @since.unbundled JMX RI 1.2
  22. */
  23. public class MBeanInstantiatorImpl implements MBeanInstantiator {
  24. private final ModifiableClassLoaderRepository clr;
  25. // private MetaData meta = null;
  26. /** The name of this class to be used for tracing */
  27. private final static String dbgTag = "MBeanInstantiatorImpl";
  28. public MBeanInstantiatorImpl(ModifiableClassLoaderRepository clr) {
  29. this.clr = clr;
  30. }
  31. public void testCreation(Class c) throws NotCompliantMBeanException {
  32. Introspector.testCreation(c);
  33. }
  34. public Class findClassWithDefaultLoaderRepository(String className)
  35. throws ReflectionException {
  36. Class theClass;
  37. if (className == null) {
  38. throw new RuntimeOperationsException(new
  39. IllegalArgumentException("The class name cannot be null"),
  40. "Exception occured during object instantiation");
  41. }
  42. try {
  43. if (clr == null) throw new ClassNotFoundException(className);
  44. theClass = clr.loadClass(className);
  45. }
  46. catch (ClassNotFoundException ee) {
  47. throw new ReflectionException(ee,
  48. "The MBean class could not be loaded by the default loader repository");
  49. }
  50. return theClass;
  51. }
  52. public Class findClass(String className, ClassLoader loader)
  53. throws ReflectionException {
  54. return loadClass(className,loader);
  55. }
  56. public Class findClass(String className, ObjectName aLoader)
  57. throws ReflectionException, InstanceNotFoundException {
  58. Class theClass = null;
  59. if (aLoader == null)
  60. throw new RuntimeOperationsException(new
  61. IllegalArgumentException(), "Null loader passed in parameter");
  62. // Retrieve the class loader from the repository
  63. ClassLoader loader = null;
  64. synchronized(this) {
  65. if (clr!=null)
  66. loader = clr.getClassLoader(aLoader);
  67. }
  68. if (loader == null) {
  69. throw new InstanceNotFoundException("The loader named " +
  70. aLoader + " is not registered in the MBeanServer");
  71. }
  72. return findClass(className,loader);
  73. }
  74. public Class[] findSignatureClasses(String signature[],
  75. ClassLoader loader)
  76. throws ReflectionException {
  77. if (signature == null) return null;
  78. final ClassLoader aLoader = (ClassLoader) loader;
  79. final int length= signature.length;
  80. final Class tab[]=new Class[length];
  81. if (length == 0) return tab;
  82. try {
  83. for (int i= 0; i < length; i++) {
  84. // Start handling primitive types (int. boolean and so
  85. // forth)
  86. //
  87. final Class primCla =
  88. StandardMetaDataImpl.findClassForPrim(signature[i]);
  89. if (primCla != null) {
  90. tab[i] = primCla;
  91. continue;
  92. }
  93. // Ok we do not have a primitive type ! We need to build
  94. // the signature of the method
  95. //
  96. if (aLoader != null) {
  97. // We need to load the class through the class
  98. // loader of the target object.
  99. //
  100. tab[i] = Class.forName(signature[i], false, aLoader);
  101. } else {
  102. // Load through the default class loader
  103. //
  104. tab[i] = findClass(signature[i],
  105. this.getClass().getClassLoader());
  106. }
  107. }
  108. } catch (ClassNotFoundException e) {
  109. debugX("findSignatureClasses",e);
  110. throw new ReflectionException(e,
  111. "The parameter class could not be found");
  112. } catch (RuntimeException e) {
  113. debugX("findSignatureClasses",e);
  114. throw e;
  115. }
  116. return tab;
  117. }
  118. public Object instantiate(Class theClass)
  119. throws ReflectionException, MBeanException {
  120. Object moi = null;
  121. // ------------------------------
  122. // ------------------------------
  123. Constructor cons =
  124. StandardMetaDataImpl.findConstructor(theClass, null);
  125. if (cons == null) {
  126. throw new ReflectionException(new
  127. NoSuchMethodException("No such constructor"));
  128. }
  129. // Instantiate the new object
  130. try {
  131. moi= cons.newInstance(null);
  132. } catch (InvocationTargetException e) {
  133. // Wrap the exception.
  134. Throwable t = e.getTargetException();
  135. if (t instanceof RuntimeException) {
  136. throw new RuntimeMBeanException((RuntimeException)t,
  137. "RuntimeException thrown in the MBean's empty constructor");
  138. } else if (t instanceof Error) {
  139. throw new RuntimeErrorException((Error) t,
  140. "Error thrown in the MBean's empty constructor");
  141. } else {
  142. throw new MBeanException((Exception) t,
  143. "Exception thrown in the MBean's empty constructor");
  144. }
  145. } catch (NoSuchMethodError error) {
  146. throw new ReflectionException(new
  147. NoSuchMethodException("No constructor"),
  148. "No such constructor");
  149. } catch (InstantiationException e) {
  150. throw new ReflectionException(e,
  151. "Exception thrown trying to invoke the MBean's empty constructor");
  152. } catch (IllegalAccessException e) {
  153. throw new ReflectionException(e,
  154. "Exception thrown trying to invoke the MBean's empty constructor");
  155. } catch (IllegalArgumentException e) {
  156. throw new ReflectionException(e,
  157. "Exception thrown trying to invoke the MBean's empty constructor");
  158. }
  159. return moi;
  160. }
  161. public Object instantiate(Class theClass, Object params[],
  162. String signature[], ClassLoader loader)
  163. throws ReflectionException, MBeanException {
  164. // Instantiate the new object
  165. // ------------------------------
  166. // ------------------------------
  167. final Class[] tab;
  168. Object moi= null;
  169. try {
  170. // Build the signature of the method
  171. //
  172. ClassLoader aLoader= (ClassLoader) theClass.getClassLoader();
  173. // Build the signature of the method
  174. //
  175. tab =
  176. ((signature == null)?null:
  177. findSignatureClasses(signature,aLoader));
  178. }
  179. // Exception IllegalArgumentException raised in Jdk1.1.8
  180. catch (IllegalArgumentException e) {
  181. throw new ReflectionException(e,
  182. "The constructor parameter classes could not be loaded");
  183. }
  184. // Query the metadata service to get the right constructor
  185. Constructor cons = null;
  186. cons= StandardMetaDataImpl.findConstructor(theClass, tab);
  187. if (cons == null) {
  188. throw new ReflectionException(new
  189. NoSuchMethodException("No such constructor"));
  190. }
  191. try {
  192. moi = cons.newInstance(params);
  193. }
  194. catch (NoSuchMethodError error) {
  195. throw new ReflectionException(new
  196. NoSuchMethodException("No such constructor found"),
  197. "No such constructor" );
  198. }
  199. catch (InstantiationException e) {
  200. throw new ReflectionException(e,
  201. "Exception thrown trying to invoke the MBean's constructor");
  202. }
  203. catch (IllegalAccessException e) {
  204. throw new ReflectionException(e,
  205. "Exception thrown trying to invoke the MBean's constructor");
  206. }
  207. catch (InvocationTargetException e) {
  208. // Wrap the exception.
  209. Throwable th = e.getTargetException();
  210. if (th instanceof RuntimeException) {
  211. throw new RuntimeMBeanException((RuntimeException)th,
  212. "RuntimeException thrown in the MBean's constructor");
  213. } else if (th instanceof Error) {
  214. throw new RuntimeErrorException((Error) th,
  215. "Error thrown in the MBean's constructor");
  216. } else {
  217. throw new MBeanException((Exception) th,
  218. "Exception thrown in the MBean's constructor");
  219. }
  220. }
  221. return moi;
  222. }
  223. public ObjectInputStream deserialize(ClassLoader loader, byte[] data)
  224. throws OperationsException {
  225. // Check parameter validity
  226. if (data == null) {
  227. throw new RuntimeOperationsException(new
  228. IllegalArgumentException(), "Null data passed in parameter");
  229. }
  230. if (data.length == 0) {
  231. throw new RuntimeOperationsException(new
  232. IllegalArgumentException(), "Empty data passed in parameter");
  233. }
  234. // Object deserialization
  235. ByteArrayInputStream bIn;
  236. ObjectInputStream objIn;
  237. String typeStr;
  238. bIn = new ByteArrayInputStream(data);
  239. try {
  240. objIn = new ObjectInputStreamWithLoader(bIn,loader);
  241. } catch (IOException e) {
  242. throw new OperationsException(
  243. "An IOException occured trying to de-serialize the data");
  244. }
  245. return objIn;
  246. }
  247. public ObjectInputStream deserialize(String className,
  248. ObjectName loaderName,
  249. byte[] data,
  250. ClassLoader loader)
  251. throws InstanceNotFoundException,
  252. OperationsException,
  253. ReflectionException {
  254. // Check parameter validity
  255. if (data == null) {
  256. throw new RuntimeOperationsException(new
  257. IllegalArgumentException(), "Null data passed in parameter");
  258. }
  259. if (data.length == 0) {
  260. throw new RuntimeOperationsException(new
  261. IllegalArgumentException(), "Empty data passed in parameter");
  262. }
  263. if (className == null) {
  264. throw new RuntimeOperationsException(new
  265. IllegalArgumentException(), "Null className passed in parameter");
  266. }
  267. Class theClass = null;
  268. if (loaderName == null) {
  269. // Load the class using the agent class loader
  270. theClass = findClass(className, loader);
  271. } else {
  272. // Get the class loader MBean
  273. try {
  274. ClassLoader instance = null;
  275. if (clr!=null)
  276. instance = clr.getClassLoader(loaderName);
  277. if (instance == null)
  278. throw new ClassNotFoundException(className);
  279. theClass = Class.forName(className, false, instance);
  280. }
  281. catch (ClassNotFoundException e) {
  282. throw new ReflectionException(e,
  283. "The MBean class could not be loaded by the " +
  284. loaderName.toString() + " class loader");
  285. }
  286. }
  287. // Object deserialization
  288. ByteArrayInputStream bIn;
  289. ObjectInputStream objIn;
  290. String typeStr;
  291. bIn = new ByteArrayInputStream(data);
  292. try {
  293. objIn = new ObjectInputStreamWithLoader(bIn,
  294. theClass.getClassLoader());
  295. } catch (IOException e) {
  296. throw new OperationsException(
  297. "An IOException occured trying to de-serialize the data");
  298. }
  299. return objIn;
  300. }
  301. public Object instantiate(String className)
  302. throws ReflectionException,
  303. MBeanException {
  304. return instantiate(className, (Object[]) null, (String[]) null, null);
  305. }
  306. public Object instantiate(String className, ObjectName loaderName,
  307. ClassLoader loader)
  308. throws ReflectionException, MBeanException,
  309. InstanceNotFoundException {
  310. return instantiate(className, loaderName, (Object[]) null,
  311. (String[]) null, loader);
  312. }
  313. public Object instantiate(String className,
  314. Object params[],
  315. String signature[],
  316. ClassLoader loader)
  317. throws ReflectionException,
  318. MBeanException {
  319. Class theClass = findClassWithDefaultLoaderRepository(className);
  320. return instantiate(theClass, params, signature, loader);
  321. }
  322. public Object instantiate(String className,
  323. ObjectName loaderName,
  324. Object params[],
  325. String signature[],
  326. ClassLoader loader)
  327. throws ReflectionException,
  328. MBeanException,
  329. InstanceNotFoundException {
  330. // ------------------------------
  331. // ------------------------------
  332. Class theClass;
  333. if (loaderName == null) {
  334. theClass = findClass(className, loader);
  335. } else {
  336. theClass = findClass(className, loaderName);
  337. }
  338. return instantiate(theClass, params, signature, loader);
  339. }
  340. public ModifiableClassLoaderRepository getClassLoaderRepository() {
  341. return clr;
  342. }
  343. /**
  344. * Load a class with the specified loader, or with this object
  345. * class loader if the specified loader is null.
  346. **/
  347. static Class loadClass(String className, ClassLoader loader)
  348. throws ReflectionException {
  349. Class theClass = null;
  350. if (className == null) {
  351. throw new RuntimeOperationsException(new
  352. IllegalArgumentException("The class name cannot be null"),
  353. "Exception occured during object instantiation");
  354. }
  355. try {
  356. if (loader == null)
  357. loader = MBeanInstantiatorImpl.class.getClassLoader();
  358. if (loader != null) {
  359. theClass = Class.forName(className, false, loader);
  360. } else {
  361. theClass = Class.forName(className);
  362. }
  363. } catch (ClassNotFoundException e) {
  364. throw new ReflectionException(e,
  365. "The MBean class could not be loaded by the context classloader");
  366. }
  367. return theClass;
  368. }
  369. /**
  370. * Load the classes specified in the signature with the given loader,
  371. * or with this object class loader.
  372. **/
  373. static Class[] loadSignatureClasses(String signature[],
  374. ClassLoader loader)
  375. throws ReflectionException {
  376. if (signature == null) return null;
  377. final ClassLoader aLoader =
  378. (loader==null?MBeanInstantiatorImpl.class.getClassLoader():loader);
  379. final int length= signature.length;
  380. final Class tab[]=new Class[length];
  381. if (length == 0) return tab;
  382. try {
  383. for (int i= 0; i < length; i++) {
  384. // Start handling primitive types (int. boolean and so
  385. // forth)
  386. //
  387. final Class primCla =
  388. StandardMetaDataImpl.findClassForPrim(signature[i]);
  389. if (primCla != null) {
  390. tab[i] = primCla;
  391. continue;
  392. }
  393. // Ok we do not have a primitive type ! We need to build
  394. // the signature of the method
  395. //
  396. // We need to load the class through the class
  397. // loader of the target object.
  398. //
  399. tab[i] = Class.forName(signature[i], false, aLoader);
  400. }
  401. } catch (ClassNotFoundException e) {
  402. debugX("findSignatureClasses",e);
  403. throw new ReflectionException(e,
  404. "The parameter class could not be found");
  405. } catch (RuntimeException e) {
  406. debugX("findSignatureClasses",e);
  407. throw e;
  408. }
  409. return tab;
  410. }
  411. // TRACES & DEBUG
  412. //---------------
  413. private static boolean isTraceOn() {
  414. return Trace.isSelected(Trace.LEVEL_TRACE, Trace.INFO_MBEANSERVER);
  415. }
  416. private static void trace(String clz, String func, String info) {
  417. Trace.send(Trace.LEVEL_TRACE, Trace.INFO_MBEANSERVER, clz, func, info);
  418. }
  419. private static void trace(String func, String info) {
  420. trace(dbgTag, func, info);
  421. }
  422. private static boolean isDebugOn() {
  423. return Trace.isSelected(Trace.LEVEL_DEBUG, Trace.INFO_MBEANSERVER);
  424. }
  425. private static void debug(String clz, String func, String info) {
  426. Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_MBEANSERVER, clz, func, info);
  427. }
  428. private static void debug(String func, String info) {
  429. debug(dbgTag, func, info);
  430. }
  431. private static void debugX(String func,Throwable e) {
  432. if (isDebugOn()) {
  433. final StringWriter s = new StringWriter();
  434. e.printStackTrace(new PrintWriter(s));
  435. final String stack = s.toString();
  436. debug(dbgTag,func,"Exception caught in "+ func+"(): "+e);
  437. debug(dbgTag,func,stack);
  438. // java.lang.System.err.println("**** Exception caught in "+
  439. // func+"(): "+e);
  440. // java.lang.System.err.println(stack);
  441. }
  442. }
  443. }