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 }