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.io.Serializable;
025: import java.util.ArrayList;
026: import java.util.HashMap;
027:
028: import javax.management.JMException;
029: import javax.management.ObjectName;
030:
031: import org.jboss.mx.util.JMXExceptionDecoder;
032: import org.jboss.ha.framework.interfaces.HARMIResponse;
033: import org.jboss.ha.framework.server.HATarget;
034: import org.jboss.ha.framework.interfaces.LoadBalancePolicy;
035: import org.jboss.ha.framework.interfaces.GenericClusteringException;
036: import org.jboss.invocation.http.interfaces.HttpInvokerProxyHA;
037: import org.jboss.invocation.Invocation;
038: import org.jboss.invocation.Invoker;
039: import org.jboss.invocation.InvokerHA;
040: import org.jboss.system.Registry;
041:
042: /** An extension of the HttpInvoker and supports clustering of HTTP invokers.
043: *
044: * @author <a href="mailto:scott.stark@jboss.org>Scott Stark</a>
045: * @version $Revision: 57188 $
046: */
047: public class HttpInvokerHA extends HttpInvoker implements InvokerHA {
048: protected HashMap targetMap = new HashMap();
049:
050: // Public --------------------------------------------------------
051:
052: protected void startService() throws Exception {
053: // Export the Invoker interface
054: ObjectName name = super .getServiceName();
055: Registry.bind(name, this );
056: // Make sure the invoker URL is valid
057: super .checkInvokerURL();
058: log.debug("Bound HttpHA invoker for JMX node");
059: }
060:
061: protected void stopService() {
062: // Unxport the Invoker interface
063: ObjectName name = super .getServiceName();
064: Registry.unbind(name);
065: log.debug("Unbound HttpHA invoker for JMX node");
066: }
067:
068: protected void destroyService() {
069: // Export references to the bean
070: Registry.unbind(serviceName);
071: }
072:
073: public void registerBean(ObjectName targetName, HATarget target)
074: throws Exception {
075: Integer hash = new Integer(targetName.hashCode());
076: log.debug("Registered targetName(" + targetName + "), hash="
077: + hash + ", target=" + target);
078: if (targetMap.containsKey(hash)) {
079: throw new IllegalStateException("Duplicate targetName("
080: + targetName + ") hashCode: " + hash);
081: }
082: targetMap.put(hash, target);
083: }
084:
085: public void unregisterBean(ObjectName targetName) throws Exception {
086: Integer hash = new Integer(targetName.hashCode());
087: targetMap.remove(hash);
088: log.debug("Unregistered targetName(" + targetName + "), hash="
089: + hash);
090: }
091:
092: public Invoker createProxy(ObjectName targetName,
093: LoadBalancePolicy policy, String proxyFamilyName)
094: throws Exception {
095: Integer hash = new Integer(targetName.hashCode());
096: HATarget target = (HATarget) targetMap.get(hash);
097: if (target == null) {
098: throw new IllegalStateException("The targetName("
099: + targetName + "), hashCode(" + hash
100: + ") not found");
101: }
102: Invoker proxy = new HttpInvokerProxyHA(target.getReplicants(),
103: target.getCurrentViewId(), policy, proxyFamilyName);
104: return proxy;
105: }
106:
107: public Serializable getStub() {
108: return super .getInvokerURL();
109: }
110:
111: /**
112: * Invoke a Remote interface method.
113: */
114: public Object invoke(Invocation invocation) throws Exception {
115: ClassLoader oldCl = Thread.currentThread()
116: .getContextClassLoader();
117: try {
118: Integer nameHash = (Integer) invocation.getObjectName();
119: ObjectName mbean = (ObjectName) Registry.lookup(nameHash);
120:
121: // The cl on the thread should be set in another interceptor
122: Object[] args = { invocation };
123: String[] sig = { "org.jboss.invocation.Invocation" };
124: Object rtn = super .getServer().invoke(mbean, "invoke",
125: args, sig);
126:
127: // Update the targets list if the client view is out of date
128: Long clientViewId = (Long) invocation
129: .getValue("CLUSTER_VIEW_ID");
130: HARMIResponse rsp = new HARMIResponse();
131: HATarget target = (HATarget) targetMap.get(nameHash);
132: if (target == null) {
133: throw new IllegalStateException(
134: "The name for hashCode(" + nameHash
135: + ") was not found");
136: }
137: if (clientViewId.longValue() != target.getCurrentViewId()) {
138: rsp.newReplicants = new ArrayList(target
139: .getReplicants());
140: rsp.currentViewId = target.getCurrentViewId();
141: }
142: rsp.response = rtn;
143:
144: // Return the raw object and let the http layer marshall it
145: return rsp;
146: } catch (Exception e) {
147: // Unwrap any JMX exceptions
148: e = (Exception) JMXExceptionDecoder.decode(e);
149: // Don't send JMX exception back to client to avoid needing jmx
150: if (e instanceof JMException)
151: e = new GenericClusteringException(
152: GenericClusteringException.COMPLETED_NO, e
153: .getMessage());
154:
155: // Only log errors if trace is enabled
156: if (log.isTraceEnabled())
157: log.trace("operation failed", e);
158: throw e;
159: } finally {
160: Thread.currentThread().setContextClassLoader(oldCl);
161: }
162: }
163: }
|