001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.management.mejb;
023:
024: import org.jboss.logging.Logger;
025: import org.jboss.management.j2ee.J2EEDomain;
026: import org.jboss.mx.util.MBeanServerLocator;
027:
028: import javax.ejb.CreateException;
029: import javax.ejb.EJBException;
030: import javax.ejb.SessionBean;
031: import javax.ejb.SessionContext;
032: import javax.management.*;
033: import javax.management.j2ee.ManagementHome;
034: import javax.naming.Context;
035: import javax.naming.InitialContext;
036: import javax.naming.NamingException;
037: import java.rmi.RemoteException;
038: import java.util.Set;
039:
040: /**
041: * Management Session Bean to enable the client to manage the
042: * server its is deployed on. This is the implementation of the
043: * JSR-77 specification MEJB.
044: *
045: * @author <a href="mailto:marc.fleury@jboss.org">Marc Fleury</a>
046: * @author Andreas Schaefer
047: * @author Scott.Stark@jboss.org
048: * @version $Revision: 57197 $
049: * @ejb:bean name="MEJB"
050: * display-name="JBoss Management EJB (MEJB)"
051: * type="Stateless"
052: * jndi-name="ejb/mgmt/MEJB"
053: * @ejb:interface extends="javax.management.j2ee.Management"
054: * @ejb:home generate="none"
055: * remote-class="javax.management.j2ee.ManagementHome"
056: * @ejb:env-entry description="JNDI-Name of the MBeanServer to be used to look it up. If 'null' the first of all listed local MBeanServer is taken"
057: * name="Server-Name"
058: * value="null"
059: * @ejb:transaction type="Supports"
060: */
061: public class ManagementBean implements SessionBean {
062: // -------------------------------------------------------------------------
063: // Static
064: // -------------------------------------------------------------------------
065: /**
066: * Logger to log. Can be used because this EJB is specific to JBoss
067: */
068: private static Logger log = Logger.getLogger(ManagementBean.class);
069:
070: // -------------------------------------------------------------------------
071: // Members
072: // -------------------------------------------------------------------------
073:
074: private SessionContext mContext;
075:
076: /**
077: * Reference to the MBeanServer all the methods of this Connector are
078: * forwarded to
079: */
080: private MBeanServer mbeanServer;
081: /**
082: * JMX Name of the HA Management Service used in a Cluster
083: */
084: private ObjectName mManagementService;
085:
086: // -------------------------------------------------------------------------
087: // Methods
088: // -------------------------------------------------------------------------
089:
090: /**
091: * @throws RemoteException Necessary for a EJB
092: * @ejb:interface-method view-type="remote"
093: */
094: public Object getAttribute(ObjectName pName, String pAttribute)
095: throws MBeanException, AttributeNotFoundException,
096: InstanceNotFoundException, ReflectionException,
097: RemoteException {
098: try {
099: if (mManagementService == null) {
100: return mbeanServer.getAttribute(pName, pAttribute);
101: } else {
102: return mbeanServer.invoke(mManagementService,
103: "getAttribute", new Object[] { pName,
104: pAttribute }, new String[] {
105: ObjectName.class.getName(),
106: String.class.getName() });
107: }
108: }
109: // The CTS expects an AttributeNotFoundException, but ModelMBeanInfoSupport
110: // throws IllegalArgumentException - we need to rethrow to make the CTS happy.
111: catch (RuntimeOperationsException e) {
112: if (e.getTargetException() instanceof IllegalArgumentException) {
113: throw new AttributeNotFoundException(
114: "MBean attribute not found: " + pAttribute);
115: }
116: throw e;
117: }
118: }
119:
120: /**
121: * @throws RemoteException Necessary for a EJB
122: * @ejb:interface-method view-type="remote"
123: */
124: public AttributeList getAttributes(ObjectName pName,
125: String[] pAttributes) throws InstanceNotFoundException,
126: ReflectionException, RemoteException {
127: if (mManagementService == null) {
128: return mbeanServer.getAttributes(pName, pAttributes);
129: } else {
130: try {
131: return (AttributeList) mbeanServer.invoke(
132: mManagementService, "getAttributes",
133: new Object[] { pName, pAttributes },
134: new String[] { ObjectName.class.getName(),
135: String[].class.getName() });
136: } catch (MBeanException me) {
137: log
138: .error(
139: "getAttributes() got exception from cluster service",
140: me);
141: // Should never happens
142: return null;
143: }
144: }
145: }
146:
147: /**
148: * @throws RemoteException Necessary for a EJB
149: * @ejb:interface-method view-type="remote"
150: */
151: public String getDefaultDomain() throws RemoteException {
152: if (mManagementService == null) {
153: return J2EEDomain.getDomainName();
154: } else {
155: try {
156: return (String) mbeanServer.getAttribute(
157: mManagementService, "DefaultDomain");
158: } catch (JMException jme) {
159: // Should never happen
160: log
161: .error(
162: "getDefaultDomain() got exception from cluster service",
163: jme);
164: return null;
165: }
166: }
167: }
168:
169: /**
170: * @throws RemoteException Necessary for a EJB
171: * @ejb:interface-method view-type="remote"
172: */
173: public Integer getMBeanCount() throws RemoteException {
174: if (mManagementService == null) {
175: try {
176: Set mbeans = this .queryNames(new ObjectName("*:*"),
177: null);
178: return new Integer(mbeans.size());
179: } catch (Exception e) {
180: }
181: return new Integer(0);
182: } else {
183: try {
184: return (Integer) mbeanServer.invoke(mManagementService,
185: "getMBeanCount", new Object[] {},
186: new String[] {});
187: } catch (JMException jme) {
188: log
189: .error(
190: "getMBeanCount() got exception from cluster service",
191: jme);
192: // Should never happen
193: return null;
194: }
195: }
196: }
197:
198: /**
199: * @throws RemoteException Necessary for a EJB
200: * @ejb:interface-method view-type="remote"
201: */
202: public MBeanInfo getMBeanInfo(ObjectName pName)
203: throws IntrospectionException, InstanceNotFoundException,
204: ReflectionException, RemoteException {
205: if (mManagementService == null) {
206: return mbeanServer.getMBeanInfo(pName);
207: } else {
208: try {
209: return (MBeanInfo) mbeanServer.invoke(
210: mManagementService, "getMBeanInfo",
211: new Object[] { pName },
212: new String[] { ObjectName.class.getName() });
213: } catch (MBeanException me) {
214: log
215: .error(
216: "getMBeanInfo() got exception from cluster service",
217: me);
218: // Should never happen
219: return null;
220: }
221: }
222: }
223:
224: /**
225: * @throws RemoteException Necessary for a EJB
226: * @ejb:interface-method view-type="remote"
227: */
228: public javax.management.j2ee.ListenerRegistration getListenerRegistry()
229: throws RemoteException {
230: return new ListenerRegistration((ManagementHome) mContext
231: .getEJBObject().getEJBHome(), new String[] {});
232: }
233:
234: /**
235: * @throws RemoteException Necessary for a EJB
236: * @ejb:interface-method view-type="remote"
237: */
238: public Object invoke(ObjectName pName, String pOperationName,
239: Object[] pParams, String[] pSignature)
240: throws InstanceNotFoundException, MBeanException,
241: ReflectionException, RemoteException {
242: // Convert start(), startRecursive() and stop() to the
243: // internal methods: mejbStart(), mejbStartRecursive() and mejbStop
244: if (pOperationName.equals("start")) {
245: pOperationName = "mejbStart";
246: } else if (pOperationName.equals("startRecursive")) {
247: pOperationName = "mejbStartRecursive";
248: } else if (pOperationName.equals("stop")) {
249: pOperationName = "mejbStop";
250: }
251: if (mManagementService == null) {
252: return mbeanServer.invoke(pName, pOperationName, pParams,
253: pSignature);
254: } else {
255: return mbeanServer.invoke(mManagementService, "invoke",
256: new Object[] { pName, pOperationName, pParams,
257: pSignature }, new String[] {
258: ObjectName.class.getName(),
259: String.class.getName(),
260: Object[].class.getName(),
261: String[].class.getName() });
262: }
263: }
264:
265: /**
266: * @throws RemoteException Necessary for a EJB
267: * @ejb:interface-method view-type="remote"
268: */
269: public boolean isRegistered(ObjectName pName)
270: throws RemoteException {
271: if (mManagementService == null) {
272: return mbeanServer.isRegistered(pName);
273: } else {
274: try {
275: Boolean lCheck = (Boolean) mbeanServer.invoke(
276: mManagementService, "isRegistered",
277: new Object[] { pName },
278: new String[] { ObjectName.class.getName() });
279: if (lCheck != null) {
280: return lCheck.booleanValue();
281: }
282: } catch (JMException jme) {
283: log
284: .error(
285: "isRegistered() got exception from cluster service",
286: jme);
287: // Should never happen
288: }
289: return false;
290: }
291: }
292:
293: /**
294: * @throws RemoteException Necessary for a EJB
295: * @ejb:interface-method view-type="remote"
296: */
297: public Set queryNames(ObjectName pName, QueryExp pQuery)
298: throws RemoteException {
299: if (mManagementService == null) {
300: return mbeanServer.queryNames(pName, pQuery);
301: } else {
302: try {
303: return (Set) mbeanServer.invoke(mManagementService,
304: "queryNames", new Object[] { pName, pQuery },
305: new String[] { ObjectName.class.getName(),
306: QueryExp.class.getName() });
307: } catch (JMException jme) {
308: log
309: .error(
310: "queryNames() got exception from cluster service",
311: jme);
312: // Should never happen
313: return null;
314: }
315: }
316: }
317:
318: /**
319: * @throws RemoteException Necessary for a EJB
320: * @ejb:interface-method view-type="remote"
321: */
322: public void setAttribute(ObjectName pName, Attribute pAttribute)
323: throws AttributeNotFoundException,
324: InstanceNotFoundException, InvalidAttributeValueException,
325: MBeanException, ReflectionException, RemoteException {
326: if (mManagementService == null) {
327: mbeanServer.setAttribute(pName, pAttribute);
328: } else {
329: mbeanServer.invoke(mManagementService, "setAttribute",
330: new Object[] { pName, pAttribute }, new String[] {
331: ObjectName.class.getName(),
332: String.class.getName() });
333: }
334: }
335:
336: /**
337: * @throws RemoteException Necessary for a EJB
338: * @ejb:interface-method view-type="remote"
339: */
340: public AttributeList setAttributes(ObjectName pName,
341: AttributeList pAttributes)
342: throws InstanceNotFoundException, ReflectionException,
343: RemoteException {
344: if (mManagementService == null) {
345: return mbeanServer.setAttributes(pName, pAttributes);
346: } else {
347: try {
348: return (AttributeList) mbeanServer.invoke(
349: mManagementService, "setAttributes",
350: new Object[] { pName, pAttributes },
351: new String[] { ObjectName.class.getName(),
352: AttributeList.class.getName() });
353: } catch (MBeanException me) {
354: log
355: .error(
356: "setAttributes() got exception from cluster service",
357: me);
358: // Should never happen
359: return null;
360: }
361: }
362: }
363:
364: /**
365: * @throws RemoteException Necessary for a EJB
366: * @ejb:interface-method view-type="remote"
367: */
368: public ObjectInstance createMBean(String pClass, ObjectName pName,
369: Object[] pParameters, String[] pSignature)
370: throws InstanceAlreadyExistsException, MBeanException,
371: MBeanRegistrationException, NotCompliantMBeanException,
372: ReflectionException, RemoteException {
373: if (mManagementService == null) {
374: return mbeanServer.createMBean(pClass, pName, pParameters,
375: pSignature);
376: } else {
377: try {
378: return (ObjectInstance) mbeanServer.invoke(
379: mManagementService, "createMBean",
380: new Object[] { pClass, pName, pParameters,
381: pSignature }, new String[] {
382: String.class.getName(),
383: ObjectName.class.getName(),
384: Object[].class.getName(),
385: String[].class.getName() });
386: } catch (InstanceNotFoundException infe) {
387: log
388: .error(
389: "createMBean() got exception from cluster service",
390: infe);
391: // Should never happen
392: return null;
393: }
394: }
395: }
396:
397: /**
398: * @throws RemoteException Necessary for a EJB
399: * @ejb:interface-method view-type="remote"
400: */
401: public void unregisterMBean(ObjectName pName)
402: throws InstanceNotFoundException,
403: MBeanRegistrationException, RemoteException {
404: if (mManagementService == null) {
405: mbeanServer.unregisterMBean(pName);
406: } else {
407: try {
408: mbeanServer.invoke(mManagementService,
409: "unregisterMBean", new Object[] { pName },
410: new String[] { ObjectName.class.getName() });
411: }
412: // Should never happen
413: catch (MBeanException me) {
414: log
415: .error(
416: "unregisterMBean() got exception from cluster service",
417: me);
418: } catch (ReflectionException re) {
419: log
420: .error(
421: "unregisterMBean() got exception from cluster service",
422: re);
423: }
424: }
425: }
426:
427: /**
428: * @throws RemoteException Necessary for a EJB
429: * @ejb:interface-method view-type="remote"
430: */
431: public void addNotificationListener(ObjectName pBroadcaster,
432: ObjectName pListener, NotificationFilter pFilter,
433: Object pHandback) throws InstanceNotFoundException,
434: RemoteException {
435: if (mManagementService == null) {
436: mbeanServer.addNotificationListener(pBroadcaster,
437: pListener, pFilter, pHandback);
438: } else {
439: try {
440: mbeanServer.invoke(mManagementService,
441: "addNotificationListener", new Object[] {
442: pBroadcaster, pListener, pFilter,
443: pHandback }, new String[] {
444: ObjectName.class.getName(),
445: ObjectName.class.getName(),
446: NotificationFilter.class.getName(),
447: Object.class.getName() });
448: }
449: // Should never happen
450: catch (MBeanException me) {
451: log
452: .error(
453: "addNotificationListener() got exception from cluster service",
454: me);
455: } catch (ReflectionException re) {
456: log
457: .error(
458: "addNotificationListener() got exception from cluster service",
459: re);
460: }
461: }
462: }
463:
464: /**
465: * @throws RemoteException Necessary for a EJB
466: * @ejb:interface-method view-type="remote"
467: */
468: public void removeNotificationListener(ObjectName pBroadcaster,
469: ObjectName pListener) throws InstanceNotFoundException,
470: ListenerNotFoundException, RemoteException {
471: if (mManagementService == null) {
472: mbeanServer.removeNotificationListener(pBroadcaster,
473: pListener);
474: } else {
475: try {
476: mbeanServer.invoke(mManagementService,
477: "removeNotificationListener", new Object[] {
478: pBroadcaster, pListener },
479: new String[] { ObjectName.class.getName(),
480: ObjectName.class.getName() });
481: }
482: // Should never happen
483: catch (MBeanException me) {
484: log
485: .error(
486: "removeNotificationListener() got exception from cluster service",
487: me);
488: } catch (ReflectionException re) {
489: log
490: .error(
491: "removeNotificationListener() got exception from cluster service",
492: re);
493: }
494: }
495: }
496:
497: /**
498: * Create the Session Bean which takes the first available
499: * MBeanServer as target server
500: *
501: * @throws CreateException
502: * @ejb:create-method
503: */
504: public void ejbCreate() throws CreateException {
505: if (mbeanServer == null) {
506: try {
507: Context jndiCtx = new InitialContext();
508: String serverName = (String) jndiCtx
509: .lookup("java:comp/env/Server-Name");
510: serverName = serverName.trim();
511: if (serverName == null || serverName.length() == 0
512: || serverName.equals("null")) {
513: try {
514: mbeanServer = MBeanServerLocator.locateJBoss();
515: } catch (IllegalStateException e) {
516: throw new CreateException(
517: "No local JMX MBeanServer available");
518: }
519: } else {
520: Object lServer = jndiCtx.lookup(serverName);
521: if (lServer != null) {
522: if (lServer instanceof MBeanServer) {
523: mbeanServer = (MBeanServer) lServer;
524: } else {
525: throw new CreateException("Server: "
526: + lServer
527: + " reference by Server-Name: "
528: + serverName
529: + " is not of type MBeanServer");
530: }
531: } else {
532: throw new CreateException(
533: "Server-Name "
534: + serverName
535: + " does not reference an Object in JNDI");
536: }
537: }
538: } catch (NamingException ne) {
539: throw new EJBException(ne);
540: }
541: }
542:
543: // Check to see if a HA-Management Service is available to be used
544: try {
545: ObjectName haManagement = new ObjectName(
546: "jboss:service=HAManagement");
547: ObjectInstance oi = mbeanServer
548: .getObjectInstance(haManagement);
549: mManagementService = oi.getObjectName();
550: } catch (Exception e) {
551: log
552: .debug(
553: "ejbCreate() failed to locate jboss:service=HAManagement",
554: e);
555: }
556: }
557:
558: /**
559: * Describes the instance and its content for debugging purpose
560: *
561: * @return Debugging information about the instance and its content
562: */
563: public String toString() {
564: return "Management [ " + " ]";
565: }
566:
567: // -------------------------------------------------------------------------
568: // Framework Callbacks
569: // -------------------------------------------------------------------------
570:
571: /**
572: * Set the associated session context. The container invokes this method on
573: * an instance after the instance has been created.
574: * <p>This method is called with no transaction context.
575: *
576: * @param aContext A SessionContext interface for the instance. The instance
577: * should store the reference to the context in an instance variable.
578: * @throws EJBException Should something go wrong while seting the context,
579: * an EJBException will be thrown.
580: */
581: public void setSessionContext(SessionContext aContext)
582: throws EJBException {
583: mContext = aContext;
584: }
585:
586: /**
587: * The activate method is called when the instance is activated from its
588: * "passive" state. The instance should acquire any resource that it has
589: * released earlier in the ejbPassivate() method.
590: * <p>This method is called with no transaction context.
591: *
592: * @throws EJBException Thrown by the method to indicate a failure caused
593: * by a system-level error
594: */
595: public void ejbActivate() throws EJBException {
596: }
597:
598: /**
599: * The passivate method is called before the instance enters the "passive"
600: * state. The instance should release any resources that it can re-acquire
601: * later in the ejbActivate() method.
602: * <p>After the passivate method completes, the instance must be in a state
603: * that allows the container to use the Java Serialization protocol to
604: * externalize and store away the instance's state.
605: * <p>This method is called with no transaction context.
606: *
607: * @throws EJBException Thrown by the method to indicate a failure caused
608: * by a system-level error
609: */
610: public void ejbPassivate() throws EJBException {
611: }
612:
613: /**
614: * A container invokes this method before it ends the life of the session
615: * object. This happens as a result of a client's invoking a remove
616: * operation, or when a container decides to terminate the session object
617: * after a timeout.
618: * <p>This method is called with no transaction context.
619: *
620: * @throws EJBException Thrown by the method to indicate a failure caused
621: * by a system-level error
622: */
623: public void ejbRemove() throws EJBException {
624: }
625:
626: }
|