001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.geronimo.clustering.wadi;
017:
018: import java.util.Collection;
019: import java.util.HashSet;
020: import java.util.IdentityHashMap;
021: import java.util.Set;
022:
023: import org.apache.geronimo.clustering.Cluster;
024: import org.apache.geronimo.clustering.ClusterListener;
025: import org.apache.geronimo.clustering.Node;
026: import org.apache.geronimo.gbean.GBeanInfo;
027: import org.apache.geronimo.gbean.GBeanInfoBuilder;
028: import org.apache.geronimo.gbean.GBeanLifecycle;
029: import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
030: import org.codehaus.wadi.group.Peer;
031:
032: /**
033: *
034: * @version $Rev$ $Date$
035: */
036: public class BasicWADICluster implements GBeanLifecycle, WADICluster {
037: private final Node node;
038: private final DispatcherHolder dispatcherHolder;
039: private final NodeFactory nodeFactory;
040: private final IdentityHashMap<ClusterListener, org.codehaus.wadi.group.ClusterListener> listenerToWADIListener;
041: private final org.codehaus.wadi.group.ClusterListener wrapNodeAsPeerListener;
042:
043: private org.codehaus.wadi.group.Cluster cluster;
044:
045: public BasicWADICluster(Node node, DispatcherHolder dispatcherHolder) {
046: this (node, dispatcherHolder, new NodeProxyFactory());
047: }
048:
049: public BasicWADICluster(Node node,
050: DispatcherHolder dispatcherHolder, NodeFactory nodeFactory) {
051: if (null == node) {
052: throw new IllegalArgumentException("node is required");
053: } else if (null == dispatcherHolder) {
054: throw new IllegalArgumentException(
055: "dispatcherHolder is required");
056: }
057: this .node = node;
058: this .dispatcherHolder = dispatcherHolder;
059: this .nodeFactory = nodeFactory;
060:
061: listenerToWADIListener = new IdentityHashMap<ClusterListener, org.codehaus.wadi.group.ClusterListener>();
062:
063: wrapNodeAsPeerListener = new org.codehaus.wadi.group.ClusterListener() {
064: public void onListenerRegistration(
065: org.codehaus.wadi.group.Cluster cluster,
066: Set existing) {
067: wrapAsNode(existing);
068: }
069:
070: public void onMembershipChanged(
071: org.codehaus.wadi.group.Cluster cluster,
072: Set joiners, Set leavers) {
073: wrapAsNode(joiners);
074: }
075: };
076: }
077:
078: public void doStart() throws Exception {
079: cluster = dispatcherHolder.getDispatcher().getCluster();
080:
081: cluster.addClusterListener(wrapNodeAsPeerListener);
082: }
083:
084: public void doStop() throws Exception {
085: cluster.removeClusterListener(wrapNodeAsPeerListener);
086:
087: clearListeners();
088: }
089:
090: public void doFail() {
091: cluster.removeClusterListener(wrapNodeAsPeerListener);
092:
093: clearListeners();
094: }
095:
096: public org.codehaus.wadi.group.Cluster getCluster() {
097: return cluster;
098: }
099:
100: public String getName() {
101: return cluster.getClusterName();
102: }
103:
104: public Node getLocalNode() {
105: return node;
106: }
107:
108: public Set<Node> getRemoteNodes() {
109: Collection<Peer> peers = cluster.getRemotePeers().values();
110: Set<Node> nodes = wrapAsNode(peers);
111: return nodes;
112: }
113:
114: public void addClusterListener(ClusterListener listener) {
115: if (null == listener) {
116: throw new IllegalArgumentException("listener is required");
117: }
118: GeronimoClusterListenerAdaptor wadiListener = new GeronimoClusterListenerAdaptor(
119: listener);
120: listenerToWADIListener.put(listener, wadiListener);
121: cluster.addClusterListener(wadiListener);
122: }
123:
124: public void removeClusterListener(ClusterListener listener) {
125: org.codehaus.wadi.group.ClusterListener wadiListener = listenerToWADIListener
126: .remove(listener);
127: if (null == wadiListener) {
128: throw new IllegalArgumentException(listener
129: + " is not registered");
130: }
131: cluster.removeClusterListener(wadiListener);
132: }
133:
134: protected void clearListeners() {
135: for (org.codehaus.wadi.group.ClusterListener wadiListener : listenerToWADIListener
136: .values()) {
137: cluster.removeClusterListener(wadiListener);
138: }
139:
140: listenerToWADIListener.clear();
141: }
142:
143: protected Set<Node> wrapAsNode(Collection<Peer> peers) {
144: Set<Node> nodes = new HashSet<Node>();
145: for (Peer peer : peers) {
146: Node node = wrapAsNode(peer);
147: nodes.add(node);
148: }
149: return nodes;
150: }
151:
152: protected Node wrapAsNode(Peer peer) {
153: Node node = RemoteNode.retrieveOptionalAdaptor(peer);
154: if (null == node) {
155: node = newRemoteNode(peer);
156: }
157: return node;
158: }
159:
160: protected Node newRemoteNode(Peer peer) {
161: return nodeFactory.newNode(cluster, peer);
162: }
163:
164: protected class GeronimoClusterListenerAdaptor implements
165: org.codehaus.wadi.group.ClusterListener {
166: private final ClusterListener listener;
167:
168: public GeronimoClusterListenerAdaptor(ClusterListener listener) {
169: this .listener = listener;
170: }
171:
172: public void onListenerRegistration(
173: org.codehaus.wadi.group.Cluster cluster, Set existing) {
174: Set<Node> existingNodes = wrapAsNode(existing);
175: listener.onListenerRegistration(BasicWADICluster.this ,
176: existingNodes);
177: }
178:
179: public void onMembershipChanged(
180: org.codehaus.wadi.group.Cluster cluster, Set joiners,
181: Set leavers) {
182: Set<Node> joinerNodes = wrapAsNode(joiners);
183: Set<Node> leaverNodes = wrapAsNode(leavers);
184: listener.onMembershipChanged(BasicWADICluster.this ,
185: joinerNodes, leaverNodes);
186: }
187:
188: }
189:
190: public static final GBeanInfo GBEAN_INFO;
191:
192: public static final String GBEAN_REF_NODE = "Node";
193: public static final String GBEAN_REF_DISPATCHER_HOLDER = "DispatcherHolder";
194:
195: static {
196: GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(
197: "WADI Cluster", BasicWADICluster.class,
198: NameFactory.GERONIMO_SERVICE);
199:
200: infoBuilder.addReference(GBEAN_REF_NODE, Node.class,
201: NameFactory.GERONIMO_SERVICE);
202: infoBuilder.addReference(GBEAN_REF_DISPATCHER_HOLDER,
203: DispatcherHolder.class, NameFactory.GERONIMO_SERVICE);
204:
205: infoBuilder.addInterface(Cluster.class);
206:
207: infoBuilder.setConstructor(new String[] { GBEAN_REF_NODE,
208: GBEAN_REF_DISPATCHER_HOLDER });
209:
210: GBEAN_INFO = infoBuilder.getBeanInfo();
211: }
212:
213: public static GBeanInfo getGBeanInfo() {
214: return GBEAN_INFO;
215: }
216:
217: }
|