001: /******************************************************************************
002: * JBoss, a division of Red Hat *
003: * Copyright 2006, Red Hat Middleware, LLC, and individual *
004: * contributors as indicated by the @authors tag. See the *
005: * copyright.txt in the distribution for a full listing of *
006: * individual contributors. *
007: * *
008: * This is free software; you can redistribute it and/or modify it *
009: * under the terms of the GNU Lesser General Public License as *
010: * published by the Free Software Foundation; either version 2.1 of *
011: * the License, or (at your option) any later version. *
012: * *
013: * This software is distributed in the hope that it will be useful, *
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of *
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
016: * Lesser General Public License for more details. *
017: * *
018: * You should have received a copy of the GNU Lesser General Public *
019: * License along with this software; if not, write to the Free *
020: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
021: * 02110-1301 USA, or see the FSF site: http://www.fsf.org. *
022: ******************************************************************************/package org.jboss.portal.jems.as.system;
023:
024: import org.apache.log4j.Logger;
025: import org.jboss.mx.interceptor.AbstractInterceptor;
026: import org.jboss.mx.interceptor.Interceptor;
027: import org.jboss.mx.modelmbean.ModelMBeanInvoker;
028: import org.jboss.mx.server.Invocation;
029: import org.jboss.mx.server.InvocationContext;
030: import org.jboss.mx.util.MBeanProxyExt;
031: import org.jboss.portal.common.mx.JavaBeanModelMBeanBuilder;
032: import org.jboss.portal.common.util.Tools;
033: import org.jboss.system.ServiceMBeanSupport;
034: import org.w3c.dom.Element;
035:
036: import javax.management.InstanceNotFoundException;
037: import javax.management.MBeanException;
038: import javax.management.MBeanInfo;
039: import javax.management.MBeanServer;
040: import javax.management.ObjectName;
041: import javax.management.modelmbean.InvalidTargetObjectTypeException;
042: import javax.management.modelmbean.ModelMBeanAttributeInfo;
043: import javax.management.modelmbean.ModelMBeanConstructorInfo;
044: import javax.management.modelmbean.ModelMBeanInfo;
045: import javax.management.modelmbean.ModelMBeanInfoSupport;
046: import javax.management.modelmbean.ModelMBeanNotificationInfo;
047: import javax.management.modelmbean.ModelMBeanOperationInfo;
048: import java.lang.reflect.InvocationTargetException;
049: import java.lang.reflect.Method;
050: import java.lang.reflect.Proxy;
051: import java.util.Iterator;
052: import java.util.List;
053:
054: /**
055: * @author <a href="mailto:julien@jboss.org">Julien Viet</a>
056: * @version $Revision: 8784 $
057: */
058: public class JBossServiceModelMBean extends ModelMBeanInvoker {
059:
060: // Attributes ----------------------------------------------------
061:
062: static {
063: try {
064: serviceMixinInfo = JavaBeanModelMBeanBuilder.build(
065: ServiceMixin.class, Object.class);
066: } catch (Exception e) {
067: throw new Error(e);
068: }
069: }
070:
071: /** . */
072: private static final ModelMBeanInfo serviceMixinInfo;
073:
074: /** . */
075: private static final Logger log = Logger
076: .getLogger(JBossServiceModelMBean.class);
077:
078: /** . */
079: public static final String PORTAL_KERNEL_NO_PROXIES = "portal.kernel.no_proxies";
080:
081: // Constructors --------------------------------------------------
082:
083: /** . */
084: private final boolean replaceProxies;
085:
086: /** . */
087: private final ServiceMixin serviceMixin;
088:
089: /** . */
090: private final POJOInjector injector;
091:
092: /** . */
093: private final boolean createExists;
094:
095: /** . */
096: private final boolean startExists;
097:
098: /** . */
099: private final boolean stopExists;
100:
101: /** . */
102: private final boolean destroyExists;
103:
104: /** . */
105: private final boolean getStateExists;
106:
107: /** . */
108: private final boolean getStateStringExists;
109:
110: /** . */
111: private final boolean getManagedResourceExists;
112:
113: public JBossServiceModelMBean(Object resource)
114: throws MBeanException {
115: this (resource, null, null);
116: }
117:
118: public JBossServiceModelMBean(Object resource, Element config,
119: String version) throws MBeanException {
120: try {
121: setManagedResource(resource, "ObjectReference");
122:
123: //
124: boolean pojo = !(resource instanceof ServiceMBeanSupport);
125:
126: // Build
127: ModelMBeanInfo info = JavaBeanModelMBeanBuilder.build(
128: resource.getClass(), pojo ? Object.class
129: : ServiceMBeanSupport.class);
130:
131: //
132: this .replaceProxies = "true".equals(System.getProperty(
133: PORTAL_KERNEL_NO_PROXIES, "true"));
134: this .injector = new POJOInjector();
135: this .serviceMixin = new ServiceMixin(resource);
136:
137: //
138: List mmois = Tools.toList(info.getOperations());
139: List mmais = Tools.toList(info.getAttributes());
140:
141: //
142: boolean createExists = false;
143: boolean startExists = false;
144: boolean stopExists = false;
145: boolean destroyExists = false;
146: boolean getStateExists = false;
147: boolean getStateStringExists = false;
148: boolean getManagedResourceExists = false;
149:
150: //
151: for (int i = 0; i < mmois.size(); i++) {
152: ModelMBeanOperationInfo mmoi = (ModelMBeanOperationInfo) mmois
153: .get(i);
154: if (mmoi.getSignature().length == 0) {
155: if (mmoi.getName().equals("create")) {
156: createExists = true;
157: } else if (mmoi.getName().equals("start")) {
158: startExists = true;
159: } else if (mmoi.getName().equals("stop")) {
160: stopExists = true;
161: } else if (mmoi.getName().equals("destroy")) {
162: destroyExists = true;
163: } else if (mmoi.getName().equals("getState")) {
164: getStateExists = true;
165: } else if (mmoi.getName().equals("getStateString")) {
166: getStateStringExists = true;
167: } else if (mmoi.getName().equals(
168: "getManagedResource")) {
169: getManagedResourceExists = true;
170: }
171: }
172: }
173:
174: //
175: this .createExists = createExists;
176: this .startExists = startExists;
177: this .stopExists = stopExists;
178: this .destroyExists = destroyExists;
179: this .getStateExists = getStateExists;
180: this .getStateStringExists = getStateStringExists;
181: this .getManagedResourceExists = getManagedResourceExists;
182:
183: //
184: if (!createExists) {
185: mmois.add(serviceMixinInfo.getOperation("create"));
186: }
187: if (!startExists) {
188: mmois.add(serviceMixinInfo.getOperation("start"));
189: }
190: if (!stopExists) {
191: mmois.add(serviceMixinInfo.getOperation("stop"));
192: }
193: if (!destroyExists) {
194: mmois.add(serviceMixinInfo.getOperation("destroy"));
195: }
196: if (!getStateExists) {
197: mmois.add(serviceMixinInfo.getOperation("getState"));
198: mmais.add(serviceMixinInfo.getAttribute("State"));
199: }
200: if (!getStateStringExists) {
201: mmois.add(serviceMixinInfo
202: .getOperation("getStateString"));
203: mmais.add(serviceMixinInfo.getAttribute("StateString"));
204: }
205: if (!getManagedResourceExists) {
206: mmois.add(serviceMixinInfo
207: .getOperation("getManagedResource"));
208: mmais.add(serviceMixinInfo
209: .getAttribute("ManagedResource"));
210: }
211:
212: //
213: info = new ModelMBeanInfoSupport(info.getClassName(), info
214: .getDescription(),
215: (ModelMBeanAttributeInfo[]) mmais
216: .toArray(new ModelMBeanAttributeInfo[mmais
217: .size()]),
218: (ModelMBeanConstructorInfo[]) info
219: .getConstructors(),
220: (ModelMBeanOperationInfo[]) mmois
221: .toArray(new ModelMBeanOperationInfo[mmois
222: .size()]),
223: (ModelMBeanNotificationInfo[]) info
224: .getNotifications());
225:
226: //
227: setModelMBeanInfo(info);
228: } catch (InstanceNotFoundException e) {
229: throw new MBeanException(e);
230: } catch (InvalidTargetObjectTypeException e) {
231: throw new MBeanException(e, "Unsupported resource type: "
232: + resourceType);
233: } catch (Exception e) {
234: throw new MBeanException(e);
235: }
236: }
237:
238: // ModelMBean implementation -------------------------------------
239:
240: public boolean isSupportedResourceType(Object resource,
241: String resourceType) {
242: return "ObjectReference".equals(resourceType);
243: }
244:
245: public MBeanInfo getMBeanInfo() {
246: return info;
247: }
248:
249: //
250:
251: protected void initDispatchers() {
252: super .initDispatchers();
253:
254: //
255: for (Iterator i = attributeContextMap.values().iterator(); i
256: .hasNext();) {
257: InvocationContext ctx = (InvocationContext) i.next();
258: if ("State".equals(ctx.getName())) {
259: ctx.setDispatcher(new AbstractInterceptor() {
260: public Object invoke(Invocation invocation)
261: throws Throwable {
262: return new Integer(serviceMixin.getState());
263: }
264: });
265: } else if ("StateString".equals(ctx.getName())) {
266: ctx.setDispatcher(new AbstractInterceptor() {
267: public Object invoke(Invocation invocation)
268: throws Throwable {
269: return serviceMixin.getStateString();
270: }
271: });
272: } else if ("ManagedResource".equals(ctx.getName())) {
273: ctx.setDispatcher(new AbstractInterceptor() {
274: public Object invoke(Invocation invocation)
275: throws Throwable {
276: return serviceMixin.getManagedResource();
277: }
278: });
279: } else if (replaceProxies) {
280: // Retrieve original dispatcher
281: final Interceptor dispatcher = ctx.getDispatcher();
282:
283: //
284: ctx.setDispatcher(new AbstractInterceptor() {
285: public Object invoke(Invocation invocation)
286: throws Throwable {
287: if (InvocationContext.OP_SETATTRIBUTE
288: .equals(invocation.getType())) {
289: Object value = invocation.getArgs()[0];
290: if (value != null
291: && Proxy.isProxyClass(value
292: .getClass())) {
293: Object handler = Proxy
294: .getInvocationHandler(value);
295: if (handler instanceof MBeanProxyExt) {
296: MBeanProxyExt pojoHandler = (MBeanProxyExt) handler;
297: POJOInjection injection = new POJOInjection(
298: pojoHandler, dispatcher,
299: invocation);
300: injector.addInjection(injection);
301: } else {
302: dispatcher.invoke(invocation);
303: }
304: } else {
305: dispatcher.invoke(invocation);
306: }
307:
308: //
309: return null;
310: } else {
311: return dispatcher.invoke(invocation);
312: }
313: }
314: });
315: }
316: }
317:
318: //
319: for (Iterator i = operationContextMap.values().iterator(); i
320: .hasNext();) {
321: InvocationContext ctx = (InvocationContext) i.next();
322: if ("create".equals(ctx.getName())) {
323: ctx.setDispatcher(new AbstractInterceptor() {
324: public Object invoke(Invocation invocation)
325: throws Throwable {
326: serviceMixin.create();
327: return null;
328: }
329: });
330: } else if ("start".equals(ctx.getName())) {
331: ctx.setDispatcher(new AbstractInterceptor() {
332: public Object invoke(Invocation invocation)
333: throws Throwable {
334: serviceMixin.start();
335: return null;
336: }
337: });
338: } else if ("stop".equals(ctx.getName())) {
339: ctx.setDispatcher(new AbstractInterceptor() {
340: public Object invoke(Invocation invocation)
341: throws Throwable {
342: serviceMixin.stop();
343: return null;
344: }
345: });
346: } else if ("destroy".equals(ctx.getName())) {
347: ctx.setDispatcher(new AbstractInterceptor() {
348: public Object invoke(Invocation invocation)
349: throws Throwable {
350: serviceMixin.destroy();
351: return null;
352: }
353: });
354: } else if ("getState".equals(ctx.getName())) {
355: ctx.setDispatcher(new AbstractInterceptor() {
356: public Object invoke(Invocation invocation)
357: throws Throwable {
358: return new Integer(serviceMixin.getState());
359: }
360: });
361: } else if ("getStateString".equals(ctx.getName())) {
362: ctx.setDispatcher(new AbstractInterceptor() {
363: public Object invoke(Invocation invocation)
364: throws Throwable {
365: return serviceMixin.getStateString();
366: }
367: });
368: } else if ("getManagedResource".equals(ctx.getName())) {
369: ctx.setDispatcher(new AbstractInterceptor() {
370: public Object invoke(Invocation invocation)
371: throws Throwable {
372: return serviceMixin.getManagedResource();
373: }
374: });
375: }
376: }
377: }
378:
379: private static class ServiceMixin extends ServiceMBeanSupport {
380:
381: /** . */
382: private final Object resource;
383:
384: public ServiceMixin(Object resource) {
385: this .resource = resource;
386: }
387:
388: protected void createService() throws Exception {
389: execute("create");
390: }
391:
392: protected void startService() throws Exception {
393: execute("start");
394: }
395:
396: protected void stopService() throws Exception {
397: execute("stop");
398: }
399:
400: protected void destroyService() throws Exception {
401: execute("destroy");
402: }
403:
404: public Object getManagedResource() {
405: return resource;
406: }
407:
408: private void execute(String lifecycle) throws Exception {
409: Method m = null;
410: try {
411: m = resource.getClass().getMethod(lifecycle,
412: new Class[0]);
413: } catch (NoSuchMethodException ignore) {
414: }
415:
416: //
417: if (m != null) {
418: try {
419: m.invoke(resource, new Object[0]);
420: } catch (IllegalAccessException e) {
421: throw new Error(e);
422: } catch (InvocationTargetException e) {
423: Throwable t = e.getTargetException();
424: if (t instanceof Exception) {
425: throw (Exception) t;
426: } else if (t instanceof Error) {
427: throw (Error) t;
428: } else {
429: throw new Error(t);
430: }
431: }
432: }
433: }
434: }
435:
436: // MBeanRegistration implementation *********************************************************************************
437:
438: public ObjectName preRegister(MBeanServer server, ObjectName name)
439: throws Exception {
440: name = super .preRegister(server, name);
441:
442: //
443: server.addNotificationListener(
444: JMXConstants.MBEAN_SERVER_DELEGATE, injector, null,
445: null);
446:
447: //
448: return name;
449: }
450:
451: public void postRegister(Boolean done) {
452: super .postRegister(done);
453: }
454:
455: public void preDeregister() throws Exception {
456: getServer().removeNotificationListener(
457: JMXConstants.MBEAN_SERVER_DELEGATE, injector);
458:
459: //
460: super .preDeregister();
461: }
462:
463: public void postDeregister() {
464: super.postDeregister();
465: }
466: }
|