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.proxy.ejb;
023:
024: import java.util.List;
025: import javax.management.ObjectName;
026: import javax.naming.InitialContext;
027: import org.jboss.system.Registry;
028: import org.jboss.logging.Logger;
029: import org.jboss.ha.framework.interfaces.LoadBalancePolicy;
030: import org.jboss.ha.framework.interfaces.DistributedReplicantManager;
031: import org.jboss.ha.framework.interfaces.HAPartition;
032: import org.jboss.ha.framework.server.HATarget;
033:
034: import javax.management.AttributeChangeNotificationFilter;
035: import javax.management.NotificationListener;
036: import javax.management.AttributeChangeNotification;
037: import javax.management.Notification;
038: import org.jboss.invocation.InvokerProxyHA;
039: import org.jboss.invocation.InvokerHA;
040: import org.jboss.system.ServiceMBean;
041: import org.jboss.naming.Util;
042:
043: /**
044: * ProxyFactory for Clustering
045: *
046: * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
047: * @author Scott.Stark@jboss.org
048: * @version $Revision: 57188 $
049: */
050: public class ProxyFactoryHA extends ProxyFactory implements
051: DistributedReplicantManager.ReplicantListener,
052: ClusterProxyFactory {
053:
054: protected static Logger log = Logger.getLogger(ProxyFactory.class);
055: protected String replicantName = null;
056: protected InvokerHA jrmp;
057: protected HATarget target;
058:
059: protected DistributedReplicantManager drm = null;
060:
061: public void create() throws Exception {
062: super .create();
063:
064: // we register our inner-class to retrieve STATE notifications from our container
065: //
066: AttributeChangeNotificationFilter filter = new AttributeChangeNotificationFilter();
067: filter.enableAttribute("State");
068:
069: // ************************************************************************
070: // NOTE: We could also subscribe for the container service events instead of the
071: // ejbModule service events. This problem comes from beans using other beans
072: // in the same ejbModule: we may receive an IllegalStateException thrown
073: // by the Container implementation. Using ejbModule events solve this
074: // problem.
075: // ************************************************************************
076: this .container.getServer().addNotificationListener(
077: this .container.getEjbModule().getServiceName(),
078: new ProxyFactoryHA.StateChangeListener(), filter, null);
079: }
080:
081: public void start() throws Exception {
082: super .start();
083: }
084:
085: protected void setupInvokers() throws Exception {
086: String partitionName = container.getBeanMetaData()
087: .getClusterConfigMetaData().getPartitionName();
088: InitialContext ctx = new InitialContext();
089: HAPartition partition = (HAPartition) ctx
090: .lookup("/HAPartition/" + partitionName);
091: this .drm = partition.getDistributedReplicantManager();
092:
093: replicantName = jmxName.toString();
094:
095: ObjectName oname = new ObjectName(invokerMetaData
096: .getInvokerMBean());
097: jrmp = (InvokerHA) Registry.lookup(oname);
098: if (jrmp == null)
099: throw new RuntimeException("home JRMPInvokerHA is null: "
100: + oname);
101:
102: target = new HATarget(partition, replicantName, jrmp.getStub(),
103: HATarget.MAKE_INVOCATIONS_WAIT);
104: jrmp.registerBean(jmxName, target);
105:
106: String clusterFamilyName = partitionName + "/" + jmxName + "/";
107:
108: // make ABSOLUTLY sure we do register with the DRM AFTER the HATarget
109: // otherwise we will refresh the *old* home in JNDI (ie before the proxy
110: // is re-generated)
111: //
112: drm.registerListener(replicantName, this );
113:
114: ClassLoader cl = Thread.currentThread().getContextClassLoader();
115: Class clazz;
116: LoadBalancePolicy policy;
117:
118: clazz = cl.loadClass(container.getBeanMetaData()
119: .getClusterConfigMetaData().getHomeLoadBalancePolicy());
120: policy = (LoadBalancePolicy) clazz.newInstance();
121: homeInvoker = jrmp.createProxy(jmxName, policy,
122: clusterFamilyName + "H");
123: // (Re-)Bind the home invoker in the JNDI naming space
124: String homeName = jndiBinding + "-HomeInvoker";
125: log.debug("(re-)Binding Home invoker under: " + homeName);
126: Util.rebind(ctx,
127: // Jndi name
128: homeName,
129: // The home invoker
130: homeInvoker);
131:
132: clazz = cl.loadClass(container.getBeanMetaData()
133: .getClusterConfigMetaData().getBeanLoadBalancePolicy());
134: policy = (LoadBalancePolicy) clazz.newInstance();
135: beanInvoker = jrmp.createProxy(jmxName, policy,
136: clusterFamilyName + "R");
137: // (Re-)Bind the remote invoker in the JNDI naming space
138: String beanName = jndiBinding + "-RemoteInvoker";
139: log.debug("(re-)Binding Remote invoker under: " + beanName);
140: Util.rebind(ctx,
141: // Jndi name
142: beanName,
143: // The bean invoker
144: beanInvoker);
145: }
146:
147: public void destroy() {
148: super .destroy();
149:
150: try {
151: jrmp.unregisterBean(jmxName);
152: target.destroy();
153: } catch (Exception ignored) {
154: // ignore.
155: }
156: try {
157: InitialContext ctx = new InitialContext();
158: String homeInvokerName = jndiBinding + "-HomeInvoker";
159: ctx.unbind(homeInvokerName);
160: } catch (Exception ignored) {
161: }
162: try {
163: InitialContext ctx = new InitialContext();
164: String beanInvokerName = jndiBinding + "-RemoteInvoker";
165: ctx.unbind(beanInvokerName);
166: } catch (Exception ignored) {
167: }
168:
169: if (drm != null)
170: drm.unregisterListener(replicantName, this );
171: }
172:
173: protected void containerIsFullyStarted() {
174: if (target != null)
175: target
176: .setInvocationsAuthorization(HATarget.ENABLE_INVOCATIONS);
177: }
178:
179: protected void containerIsAboutToStop() {
180: if (target != null) {
181: target
182: .setInvocationsAuthorization(HATarget.DISABLE_INVOCATIONS);
183: target.disable();
184: }
185: }
186:
187: // synchronized keyword added when it became possible for DRM to issue
188: // concurrent replicantsChanged notifications. JBAS-2169.
189: public synchronized void replicantsChanged(String key,
190: List newReplicants, int newReplicantsViewId) {
191: try {
192: if (homeInvoker instanceof InvokerProxyHA) {
193: ((InvokerProxyHA) homeInvoker).updateClusterInfo(target
194: .getReplicants(), target.getCurrentViewId());
195: }
196: if (beanInvoker instanceof InvokerProxyHA) {
197: ((InvokerProxyHA) beanInvoker).updateClusterInfo(target
198: .getReplicants(), target.getCurrentViewId());
199: }
200:
201: log.debug("Rebinding in JNDI... " + key);
202: rebindHomeProxy();
203: } catch (Exception none) {
204: log.debug(none);
205: }
206: }
207:
208: // inner-classes
209:
210: class StateChangeListener implements NotificationListener {
211:
212: public void handleNotification(Notification notification,
213: java.lang.Object handback) {
214: if (notification instanceof AttributeChangeNotification) {
215: AttributeChangeNotification notif = (AttributeChangeNotification) notification;
216: int value = ((Integer) notif.getNewValue()).intValue();
217:
218: if (value == ServiceMBean.STARTED) {
219: log
220: .debug("Container fully started: enabling HA-RMI access to bean");
221: containerIsFullyStarted();
222: } else if (value == ServiceMBean.STOPPING) {
223: log
224: .debug("Container about to stop: disabling HA-RMI access to bean");
225: containerIsAboutToStop();
226: }
227: }
228: }
229:
230: }
231: }
|