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