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     */
017    package org.apache.geronimo.clustering.wadi;
018    
019    import java.util.HashMap;
020    import java.util.HashSet;
021    import java.util.Iterator;
022    import java.util.Map;
023    import java.util.Set;
024    import java.util.concurrent.CopyOnWriteArrayList;
025    
026    import org.apache.commons.logging.Log;
027    import org.apache.commons.logging.LogFactory;
028    import org.apache.geronimo.clustering.Node;
029    import org.apache.geronimo.clustering.Session;
030    import org.apache.geronimo.clustering.SessionAlreadyExistException;
031    import org.apache.geronimo.clustering.SessionListener;
032    import org.apache.geronimo.clustering.SessionManager;
033    import org.apache.geronimo.gbean.GBeanInfo;
034    import org.apache.geronimo.gbean.GBeanInfoBuilder;
035    import org.apache.geronimo.gbean.GBeanLifecycle;
036    import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
037    import org.codehaus.wadi.core.assembler.StackContext;
038    import org.codehaus.wadi.core.manager.Manager;
039    import org.codehaus.wadi.core.manager.SessionMonitor;
040    import org.codehaus.wadi.group.Dispatcher;
041    import org.codehaus.wadi.group.Peer;
042    import org.codehaus.wadi.replication.strategy.BackingStrategyFactory;
043    import org.codehaus.wadi.servicespace.ServiceSpace;
044    import org.codehaus.wadi.servicespace.ServiceSpaceName;
045    
046    /**
047     * 
048     * @version $Rev$ $Date$
049     */
050    public class BasicWADISessionManager implements GBeanLifecycle, SessionManager, WADISessionManager {
051        private static final Log log = LogFactory.getLog(BasicWADISessionManager.class);
052    
053        private final ClassLoader cl;
054        private final WADICluster cluster;
055        private final WADISessionManagerConfigInfo configInfo;
056        private final BackingStrategyFactory backingStrategyFactory;
057        private final CopyOnWriteArrayList<SessionListener> listeners;
058    
059        private Manager manager;
060        private SessionMonitor sessionMonitor;
061        private ServiceSpace serviceSpace;
062    
063    
064        public BasicWADISessionManager(ClassLoader cl,
065                WADISessionManagerConfigInfo configInfo,
066                WADICluster cluster,
067                BackingStrategyFactory backingStrategyFactory) {
068            this.cl = cl;
069            this.configInfo = configInfo;
070            this.cluster = cluster;
071            this.backingStrategyFactory = backingStrategyFactory;
072    
073            listeners = new CopyOnWriteArrayList<SessionListener>();
074        }
075    
076        public void doStart() throws Exception {
077            Dispatcher underlyingDisp = cluster.getCluster().getDispatcher();
078            
079            ServiceSpaceName serviceSpaceName = new ServiceSpaceName(configInfo.getServiceSpaceURI());
080            StackContext stackContext = new StackContext(cl,
081                    serviceSpaceName,
082                    underlyingDisp,
083                    configInfo.getSessionTimeoutSeconds(),
084                    configInfo.getNumPartitions(),
085                    configInfo.getSweepInterval(),
086                    backingStrategyFactory);
087            stackContext.build();
088    
089            serviceSpace = stackContext.getServiceSpace();
090            manager = stackContext.getManager();
091    
092            sessionMonitor = stackContext.getSessionMonitor();
093            sessionMonitor.addSessionListener(new SessionListenerAdapter());
094            
095            serviceSpace.start();
096        }
097    
098        public void doStop() throws Exception {
099            serviceSpace.stop();
100        }
101    
102        public void doFail() {
103            try {
104                serviceSpace.stop();
105            } catch (Exception e) {
106                log.error(e);
107            }
108        }
109    
110        public Session createSession(String sessionId) throws SessionAlreadyExistException {
111            org.codehaus.wadi.core.session.Session session;
112            try {
113                session = manager.createWithName(sessionId);
114            } catch (org.codehaus.wadi.core.manager.SessionAlreadyExistException e) {
115                throw new SessionAlreadyExistException("Session " + sessionId + " already exists", e);
116            }
117            return new WADISessionAdaptor(session);
118        }
119    
120        public Manager getManager() {
121            return manager;
122        }
123    
124        public Node getNode() {
125            return cluster.getLocalNode();
126        }
127    
128        public Set<Node> getRemoteNodes() {
129            Map<Peer, RemoteNode> peerToRemoteNode = new HashMap<Peer, RemoteNode>();
130            Set<Node> clusterNodes = cluster.getRemoteNodes();
131            for (Iterator<Node> iterator = clusterNodes.iterator(); iterator.hasNext();) {
132                RemoteNode remoteNode = (RemoteNode) iterator.next();
133                peerToRemoteNode.put(remoteNode.getPeer(), remoteNode);
134            }
135            
136            Set<Node> nodes = new HashSet<Node>();
137            Set<Peer> peers = serviceSpace.getHostingPeers();
138            for (Peer peer : peers) {
139                RemoteNode remoteNode = peerToRemoteNode.get(peer);
140                if (null == remoteNode) {
141                    throw new AssertionError("remoteNode is null");
142                }
143                nodes.add(remoteNode);
144            }
145            return nodes;
146        }
147    
148        public void registerListener(SessionListener listener) {
149            listeners.add(listener);
150        }
151    
152        public void unregisterListener(SessionListener listener) {
153            listeners.remove(listener);
154        }
155    
156        private void notifyInboundSessionMigration(org.codehaus.wadi.core.session.Session session) {
157            for (SessionListener listener : listeners) {
158                listener.notifyInboundSessionMigration(new WADISessionAdaptor(session));
159            }
160        }
161    
162        private void notifyOutboundSessionMigration(org.codehaus.wadi.core.session.Session session) {
163            for (SessionListener listener : listeners) {
164                listener.notifyOutboundSessionMigration(new WADISessionAdaptor(session));
165            }
166        }
167    
168        private void notifySessionDestruction(org.codehaus.wadi.core.session.Session session) {
169            for (SessionListener listener : listeners) {
170                listener.notifySessionDestruction(new WADISessionAdaptor(session));
171            }
172        }
173    
174        private class SessionListenerAdapter implements org.codehaus.wadi.core.manager.SessionListener {
175    
176            public void onSessionCreation(org.codehaus.wadi.core.session.Session session) {
177            }
178    
179            public void onSessionDestruction(org.codehaus.wadi.core.session.Session session) {
180                notifySessionDestruction(session);
181            }
182            
183            public void onInboundSessionMigration(org.codehaus.wadi.core.session.Session session) {
184                notifyInboundSessionMigration(session);
185            }
186            
187            public void onOutbountSessionMigration(org.codehaus.wadi.core.session.Session session) {
188                notifyOutboundSessionMigration(session);
189            }
190            
191        }
192    
193        public static final GBeanInfo GBEAN_INFO;
194    
195        public static final String GBEAN_ATTR_WADI_CONFIG_INFO = "wadiConfigInfo";
196    
197        public static final String GBEAN_REF_CLUSTER = "Cluster";
198        public static final String GBEAN_REF_BACKING_STRATEGY_FACTORY = "BackingStrategyFactory";
199    
200        static {
201            GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic("WADI Session Manager",
202                    BasicWADISessionManager.class, NameFactory.GERONIMO_SERVICE);
203    
204            infoBuilder.addAttribute("classLoader", ClassLoader.class, false);
205            infoBuilder.addAttribute(GBEAN_ATTR_WADI_CONFIG_INFO, WADISessionManagerConfigInfo.class, true);
206    
207            infoBuilder.addReference(GBEAN_REF_CLUSTER, WADICluster.class, NameFactory.GERONIMO_SERVICE);
208            infoBuilder.addReference(GBEAN_REF_BACKING_STRATEGY_FACTORY, BackingStrategyFactory.class,
209                    NameFactory.GERONIMO_SERVICE);
210    
211            infoBuilder.addInterface(SessionManager.class);
212            infoBuilder.addInterface(WADISessionManager.class);
213    
214            infoBuilder.setConstructor(new String[] { "classLoader", 
215                    GBEAN_ATTR_WADI_CONFIG_INFO,
216                    GBEAN_REF_CLUSTER, 
217                    GBEAN_REF_BACKING_STRATEGY_FACTORY });
218    
219            GBEAN_INFO = infoBuilder.getBeanInfo();
220        }
221    
222        public static GBeanInfo getGBeanInfo() {
223            return GBEAN_INFO;
224        }
225    
226    }