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.Hashtable;
027: import javax.management.MalformedObjectNameException;
028: import javax.management.ObjectName;
029: import javax.management.MBeanServer;
030: import javax.naming.InitialContext;
031:
032: import org.jboss.invocation.Invoker;
033: import org.jboss.invocation.InvokerInterceptor;
034: import org.jboss.invocation.http.interfaces.ClientMethodInterceptorHA;
035: import org.jboss.invocation.http.interfaces.HttpInvokerProxyHA;
036: import org.jboss.system.server.ServerConfigUtil;
037: import org.jboss.ha.framework.interfaces.LoadBalancePolicy;
038: import org.jboss.ha.framework.interfaces.HAPartition;
039: import org.jboss.ha.framework.server.HATarget;
040:
041: /** An extension of HttpProxyFactory that supports clustering of invoker proxies.
042: * It does this by creating a HATarget that monitors the replication of the
043: * invoker url and creates a HAInvokerWrapper that handles wrapping the
044: * underlying invocation result with changes to the HATarget replication
045: * view.
046: *
047: * @author <a href="mailto:scott.stark@jboss.org">Scott Stark</a>
048: * @version $Revision: 57188 $
049: */
050: public class HttpProxyFactoryHA extends HttpProxyFactory implements
051: HttpProxyFactoryHAMBean {
052: private ObjectName realJmxInvokerName;
053: private ObjectName wrappedJmxInvokerName;
054: private String partitionName = ServerConfigUtil
055: .getDefaultPartitionName();
056: private Class policyClass;
057: private HAInvokerWrapper invokerWrapper;
058: private HATarget invokerTarget;
059:
060: /** Get the server side mbean that exposes the invoke operation for the
061: exported interface */
062: public Class getLoadBalancePolicy() {
063: return this .policyClass;
064: }
065:
066: /** Set the server side mbean that exposes the invoke operation for the
067: exported interface */
068: public void setLoadBalancePolicy(Class policyClass) {
069: this .policyClass = policyClass;
070: }
071:
072: /** Get the name of the cluster partition the invoker is deployed in
073: */
074: public String getPartitionName() {
075: return this .partitionName;
076: }
077:
078: /** Set the name of the cluster partition the invoker is deployed in
079: */
080: public void setPartitionName(String name) {
081: this .partitionName = name;
082: }
083:
084: /** Override the superclass method to create a wrapped ObjectName for the
085: * HAInvokerWrapper mbean. This will be the name of the invoker as known
086: * by the proxy. The HAInvokerWrapper is the HttpProxyFactoryHA name +
087: * wrapperType=httpHA
088: *
089: * @param jmxInvokerName
090: */
091: public void setInvokerName(ObjectName jmxInvokerName) {
092: realJmxInvokerName = jmxInvokerName;
093: ObjectName factoryName = getServiceName();
094: Hashtable props = factoryName.getKeyPropertyList();
095: props.put("wrapperType", "httpHA");
096: try {
097: wrappedJmxInvokerName = new ObjectName(factoryName
098: .getDomain(), props);
099: super .setInvokerName(wrappedJmxInvokerName);
100: } catch (MalformedObjectNameException e) {
101: throw new IllegalStateException(
102: "Was not able to create wrapped ObjectName");
103: }
104: }
105:
106: /**
107: * @return the ObjectName the HAInvokerWrapper delegates to
108: */
109: public ObjectName getRealJmxInvokerName() {
110: return realJmxInvokerName;
111: }
112:
113: /**
114: *
115: */
116: protected ArrayList defineInterceptors() {
117: ArrayList interceptorClasses = new ArrayList();
118: interceptorClasses.add(ClientMethodInterceptorHA.class);
119: interceptorClasses.add(InvokerInterceptor.class);
120: return interceptorClasses;
121: }
122:
123: /** Override the HttpProxyFactory method to create a HttpInvokerProxyHA.
124: * @return
125: * @throws Exception
126: */
127: protected Invoker createInvoker() throws Exception {
128: InitialContext iniCtx = new InitialContext();
129: HAPartition partition = (HAPartition) iniCtx
130: .lookup("/HAPartition/" + partitionName);
131:
132: /* Create a HATarget for the local invoker mbean stub. The name passed
133: to the HATarget must be the wrappedJmxInvokerName so that different
134: more than one HttpProxyFactoryHA may be configured for the same
135: realJmxInvokerName.
136: */
137: checkInvokerURL();
138: Serializable invokerStub = super .getInvokerURL();
139: invokerTarget = new HATarget(partition, wrappedJmxInvokerName
140: .toString(), invokerStub,
141: HATarget.MAKE_INVOCATIONS_WAIT);
142: log.debug("Created invoker: " + invokerTarget);
143: // Create and register the invoker wrapper
144: MBeanServer mbeanServer = super .getServer();
145: invokerWrapper = new HAInvokerWrapper(mbeanServer,
146: realJmxInvokerName, invokerTarget);
147: mbeanServer
148: .registerMBean(invokerWrapper, wrappedJmxInvokerName);
149:
150: // Create the LoadBalancePolicy instance
151: LoadBalancePolicy policy = (LoadBalancePolicy) policyClass
152: .newInstance();
153:
154: // Finally, create the invoker proxy, a HttpInvokerProxyHA
155: String clusterFamilyName = partitionName + "/"
156: + wrappedJmxInvokerName.toString();
157: Invoker delegateInvoker = new HttpInvokerProxyHA(invokerTarget
158: .getReplicants(), invokerTarget.getCurrentViewId(),
159: policy, clusterFamilyName);
160: return delegateInvoker;
161: }
162:
163: /** Override the HttpProxyFactory stop to unregister the HAInvokerWrapper
164: * mbean
165: *
166: * @throws Exception
167: */
168: protected void stopService() throws Exception {
169: try {
170: MBeanServer mbeanServer = super .getServer();
171: mbeanServer.unregisterMBean(wrappedJmxInvokerName);
172: } catch (Exception e) {
173: log.debug("Failed to unregister HAInvokerWrapper: "
174: + wrappedJmxInvokerName, e);
175: }
176: super .stopService();
177: }
178:
179: /** Destroys the HATarget
180: */
181: public void destroy() {
182: super .destroy();
183: try {
184: invokerTarget.destroy();
185: } catch (Exception ignore) {
186: }
187: }
188:
189: }
|