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.invocation.http.server;
023:
024: import java.util.ArrayList;
025: import javax.management.JMException;
026: import javax.management.MBeanServer;
027: import javax.management.MBeanException;
028: import javax.management.ObjectName;
029: import javax.management.ReflectionException;
030: import javax.management.MBeanInfo;
031: import javax.management.MBeanAttributeInfo;
032: import javax.management.MBeanConstructorInfo;
033: import javax.management.MBeanOperationInfo;
034: import javax.management.MBeanNotificationInfo;
035: import javax.management.MBeanParameterInfo;
036:
037: import org.jboss.ha.framework.interfaces.HARMIResponse;
038: import org.jboss.ha.framework.interfaces.GenericClusteringException;
039: import org.jboss.ha.framework.server.HATarget;
040: import org.jboss.invocation.Invocation;
041: import org.jboss.logging.Logger;
042: import org.jboss.mx.util.JMXExceptionDecoder;
043: import org.jboss.mx.util.DynamicMBeanSupport;
044:
045: /** This is an invoker that delegates to the target invoker and handles the
046: * wrapping of the response in an HARMIResponse with any updated HATarget info.
047: * @see HttpProxyFactoryHA
048: *
049: * @author <a href="mailto:scott.stark@jboss.org">Scott Stark</a>
050: * @version $Revision: 57188 $
051: */
052: public class HAInvokerWrapper extends DynamicMBeanSupport {
053: private static Logger log = Logger
054: .getLogger(HAInvokerWrapper.class);
055: private MBeanServer mbeanServer;
056: private MBeanInfo info;
057:
058: private ObjectName targetName;
059: private HATarget target;
060:
061: public HAInvokerWrapper(MBeanServer mbeanServer,
062: ObjectName targetName, HATarget target) {
063: this .mbeanServer = mbeanServer;
064: this .targetName = targetName;
065: this .target = target;
066: MBeanAttributeInfo[] attrInfo = null;
067: MBeanConstructorInfo[] ctorInfo = null;
068: MBeanParameterInfo[] sig = { new MBeanParameterInfo(
069: "invocation", Invocation.class.getName(),
070: "The invocation content information") };
071: MBeanOperationInfo[] opInfo = { new MBeanOperationInfo(
072: "invoke", "The detached invoker entry point", sig,
073: "java.lang.Object", MBeanOperationInfo.ACTION) };
074: MBeanNotificationInfo[] eventInfo = null;
075: this .info = new MBeanInfo(
076: getClass().getName(),
077: "A wrapper inovker that delegates to the target invoker",
078: attrInfo, ctorInfo, opInfo, eventInfo);
079: }
080:
081: /** The JMX DynamicMBean invoke entry point. This only handles the
082: * invoke(Invocation) operation.
083: *
084: * @param actionName
085: * @param params
086: * @param signature
087: * @return
088: * @throws MBeanException
089: * @throws ReflectionException
090: */
091: public Object invoke(String actionName, Object[] params,
092: String[] signature) throws MBeanException,
093: ReflectionException {
094: if (params == null || params.length != 1
095: || (params[0] instanceof Invocation) == false) {
096: NoSuchMethodException e = new NoSuchMethodException(
097: actionName);
098: throw new ReflectionException(e, actionName);
099: }
100:
101: Invocation invocation = (Invocation) params[0];
102: try {
103: Object value = invoke(invocation);
104: return value;
105: } catch (Exception e) {
106: throw new ReflectionException(e, "Invoke failure");
107: }
108: }
109:
110: /** The invoker entry point.
111: * @param invocation
112: * @return A HARMIResponse that wraps the result of calling invoke(Invocation)
113: * on the targetName MBean
114: * @throws Exception
115: */
116: public Object invoke(Invocation invocation) throws Exception {
117: ClassLoader oldCl = Thread.currentThread()
118: .getContextClassLoader();
119: try {
120: // The cl on the thread should be set in another interceptor
121: Object[] args = { invocation };
122: String[] sig = { "org.jboss.invocation.Invocation" };
123: Object rtn = mbeanServer.invoke(targetName, "invoke", args,
124: sig);
125:
126: // Update the targets list if the client view is out of date
127: Long clientViewId = (Long) invocation
128: .getValue("CLUSTER_VIEW_ID");
129: HARMIResponse rsp = new HARMIResponse();
130: if (clientViewId.longValue() != target.getCurrentViewId()) {
131: rsp.newReplicants = new ArrayList(target
132: .getReplicants());
133: rsp.currentViewId = target.getCurrentViewId();
134: }
135: rsp.response = rtn;
136:
137: // Return the raw object and let the http layer marshall it
138: return rsp;
139: } catch (Exception e) {
140: // Unwrap any JMX exceptions
141: e = (Exception) JMXExceptionDecoder.decode(e);
142: // Don't send JMX exception back to client to avoid needing jmx
143: if (e instanceof JMException)
144: e = new GenericClusteringException(
145: GenericClusteringException.COMPLETED_NO, e
146: .getMessage());
147:
148: // Only log errors if trace is enabled
149: if (log.isTraceEnabled())
150: log.trace("operation failed", e);
151: throw e;
152: } finally {
153: Thread.currentThread().setContextClassLoader(oldCl);
154: }
155: }
156:
157: public MBeanInfo getMBeanInfo() {
158: return info;
159: }
160: }
|