View Javadoc

1   /**
2    *
3    *  Licensed to the Apache Software Foundation (ASF) under one or more
4    *  contributor license agreements.  See the NOTICE file distributed with
5    *  this work for additional information regarding copyright ownership.
6    *  The ASF licenses this file to You under the Apache License, Version 2.0
7    *  (the "License"); you may not use this file except in compliance with
8    *  the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing, software
13   *  distributed under the License is distributed on an "AS IS" BASIS,
14   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   *  See the License for the specific language governing permissions and
16   *  limitations under the License.
17   */
18  package org.apache.geronimo.clustering.wadi;
19  
20  import java.util.Collections;
21  import java.util.HashMap;
22  import java.util.HashSet;
23  import java.util.Iterator;
24  import java.util.Map;
25  import java.util.Set;
26  import java.util.regex.Pattern;
27  
28  import javax.servlet.ServletContext;
29  
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  import org.apache.geronimo.clustering.Node;
33  import org.apache.geronimo.clustering.Session;
34  import org.apache.geronimo.clustering.SessionAlreadyExistException;
35  import org.apache.geronimo.clustering.SessionListener;
36  import org.apache.geronimo.clustering.SessionManager;
37  import org.apache.geronimo.gbean.GBeanInfo;
38  import org.apache.geronimo.gbean.GBeanInfoBuilder;
39  import org.apache.geronimo.gbean.GBeanLifecycle;
40  import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
41  import org.codehaus.wadi.Collapser;
42  import org.codehaus.wadi.Contextualiser;
43  import org.codehaus.wadi.Emoter;
44  import org.codehaus.wadi.Evicter;
45  import org.codehaus.wadi.Immoter;
46  import org.codehaus.wadi.Invocation;
47  import org.codehaus.wadi.InvocationException;
48  import org.codehaus.wadi.Manager;
49  import org.codehaus.wadi.ManagerConfig;
50  import org.codehaus.wadi.Motable;
51  import org.codehaus.wadi.PoolableInvocationWrapperPool;
52  import org.codehaus.wadi.SessionPool;
53  import org.codehaus.wadi.Streamer;
54  import org.codehaus.wadi.group.Dispatcher;
55  import org.codehaus.wadi.impl.AbsoluteEvicter;
56  import org.codehaus.wadi.impl.ClusterContextualiser;
57  import org.codehaus.wadi.impl.ClusteredManager;
58  import org.codehaus.wadi.impl.DummyContextualiser;
59  import org.codehaus.wadi.impl.DummyReplicaterFactory;
60  import org.codehaus.wadi.impl.HashingCollapser;
61  import org.codehaus.wadi.impl.HybridRelocater;
62  import org.codehaus.wadi.impl.MemoryContextualiser;
63  import org.codehaus.wadi.impl.SerialContextualiser;
64  import org.codehaus.wadi.impl.SerialContextualiserFrontingMemory;
65  import org.codehaus.wadi.impl.SimpleSessionPool;
66  import org.codehaus.wadi.impl.SimpleStreamer;
67  import org.codehaus.wadi.impl.SimpleValuePool;
68  import org.codehaus.wadi.impl.StatelessContextualiser;
69  import org.codehaus.wadi.replication.contextualizer.ReplicaAwareContextualiser;
70  import org.codehaus.wadi.replication.manager.ReplicaterAdapterFactory;
71  import org.codehaus.wadi.replication.manager.ReplicationManager;
72  import org.codehaus.wadi.replication.manager.ReplicationManagerFactory;
73  import org.codehaus.wadi.replication.manager.basic.SessionReplicationManager;
74  import org.codehaus.wadi.replication.storage.ReplicaStorage;
75  import org.codehaus.wadi.replication.storage.ReplicaStorageFactory;
76  import org.codehaus.wadi.replication.strategy.BackingStrategyFactory;
77  import org.codehaus.wadi.servicespace.ServiceRegistry;
78  import org.codehaus.wadi.servicespace.ServiceSpaceName;
79  import org.codehaus.wadi.servicespace.basic.BasicServiceSpace;
80  import org.codehaus.wadi.web.WebSession;
81  import org.codehaus.wadi.web.WebSessionPool;
82  import org.codehaus.wadi.web.impl.AtomicallyReplicableSessionFactory;
83  import org.codehaus.wadi.web.impl.DistributableAttributesFactory;
84  import org.codehaus.wadi.web.impl.DistributableValueFactory;
85  import org.codehaus.wadi.web.impl.DummyRouter;
86  import org.codehaus.wadi.web.impl.DummyStatefulHttpServletRequestWrapperPool;
87  import org.codehaus.wadi.web.impl.StandardSessionWrapperFactory;
88  import org.codehaus.wadi.web.impl.WebSessionToSessionPoolAdapter;
89  
90  import EDU.oswego.cs.dl.util.concurrent.Sync;
91  
92  /**
93   * 
94   * @version $Rev$ $Date$
95   */
96  public class BasicWADISessionManager implements GBeanLifecycle, SessionManager, WADISessionManager {
97      private static final Log log = LogFactory.getLog(BasicWADISessionManager.class);
98  
99      private final WADISessionManagerConfigInfo configInfo;
100     private final ReplicationManagerFactory repManagerFactory;
101     private final ReplicaStorageFactory repStorageFactory;
102     private final BackingStrategyFactory backingStrategyFactory;
103     private final DispatcherHolder dispatcherHolder;
104     private final Set listeners;
105 
106     private ClusteredManager manager;
107     private BasicServiceSpace serviceSpace;
108 
109     public BasicWADISessionManager(WADISessionManagerConfigInfo configInfo,
110             ReplicationManagerFactory repManagerFactory, ReplicaStorageFactory repStorageFactory,
111             BackingStrategyFactory backingStrategyFactory, DispatcherHolder dispatcherHolder) {
112         this.configInfo = configInfo;
113         this.dispatcherHolder = dispatcherHolder;
114         this.repManagerFactory = repManagerFactory;
115         this.repStorageFactory = repStorageFactory;
116         this.backingStrategyFactory = backingStrategyFactory;
117 
118         listeners = new HashSet();
119     }
120 
121     public void doStart() throws Exception {
122         Dispatcher underlyingDisp = dispatcherHolder.getDispatcher();
123 
124         serviceSpace = new BasicServiceSpace(new ServiceSpaceName(configInfo.getServiceSpaceURI()), underlyingDisp);
125         Dispatcher dispatcher = serviceSpace.getDispatcher();
126 
127         boolean strictOrdering = true;
128         Streamer streamer = new SimpleStreamer();
129         Collapser collapser = new HashingCollapser(1024, 10000);
130         Map mmap = Collections.synchronizedMap(new HashMap());
131         WebSessionPool sessionPool = new SimpleSessionPool(new AtomicallyReplicableSessionFactory());
132 
133         // end of contextualiser stack
134         Contextualiser contextualiser = new DummyContextualiser();
135 
136         // replica aware contextualiser
137 //         ReplicationManager replicationManager = repManagerFactory.factory(serviceSpace, backingStrategyFactory);
138 //         ReplicationManager sessionRepManager = new SessionReplicationManager(replicationManager, sessionPool);
139 //         contextualiser = new ReplicaAwareContextualiser(contextualiser, sessionRepManager);
140 
141         // cluster aware contextualiser
142         contextualiser = new ClusterContextualiser(contextualiser, collapser, new HybridRelocater(5000, 5000, true));
143 
144         contextualiser = new StatelessContextualiser(contextualiser, Pattern.compile("GET|POST", 2), true, Pattern
145                 .compile(".*\\.(JPG|JPEG|GIF|PNG|ICO|HTML|HTM)", 2), false);
146 
147         // serialize invocations bound to the same session id
148         contextualiser = new SerialContextualiser(contextualiser, collapser, mmap);
149 
150         // in-memory contextualiser
151         Evicter mevicter = new AbsoluteEvicter(configInfo.getSweepInterval(), strictOrdering,
152                 configInfo.getSessionTimeoutSeconds());
153         SessionPool contextPool = new WebSessionToSessionPoolAdapter(sessionPool);
154         PoolableInvocationWrapperPool requestPool = new DummyStatefulHttpServletRequestWrapperPool();
155         contextualiser = new MotionTracker(contextualiser, mevicter, mmap, streamer, contextPool, requestPool);
156 
157         contextualiser = new SerialContextualiserFrontingMemory(contextualiser, new HashingCollapser(1024, 10000));
158 
159         // Manager
160         manager = new ClusteredManager(sessionPool, 
161                 new DistributableAttributesFactory(), 
162                 new SimpleValuePool(new DistributableValueFactory()), 
163                 new StandardSessionWrapperFactory(), 
164                 null, 
165                 contextualiser,
166                 mmap, 
167                 new DummyRouter(), 
168                 false, 
169                 streamer, 
170                 true,
171                 new DummyReplicaterFactory(),
172 //                new ReplicaterAdapterFactory(replicationManager, sessionPool),
173                 null, 
174                 null, 
175                 dispatcher, 
176                 configInfo.getNumPartitions(), 
177                 collapser);
178 
179         manager.init(new ManagerConfig() {
180             public void callback(Manager manager) {
181             }
182 
183             public ServletContext getServletContext() {
184                 return null;
185             }
186         });
187 
188         ServiceRegistry serviceRegistry = serviceSpace.getServiceRegistry();
189 //        serviceRegistry.register(ReplicaStorage.NAME, repStorageFactory.factory(serviceSpace));
190 //        serviceRegistry.register(ReplicationManager.NAME, replicationManager);
191         serviceRegistry.register(ClusteredManager.NAME, manager);
192 
193         serviceSpace.start();
194     }
195 
196     public void doStop() throws Exception {
197         serviceSpace.stop();
198     }
199 
200     public void doFail() {
201         try {
202             serviceSpace.stop();
203         } catch (Exception e) {
204             log.error(e);
205         }
206     }
207 
208     public Session createSession(String sessionId) throws SessionAlreadyExistException {
209         WebSession session;
210         try {
211             session = manager.createWithName(sessionId);
212         } catch (org.codehaus.wadi.SessionAlreadyExistException e) {
213             throw new SessionAlreadyExistException(sessionId);
214         }
215         return new WADISessionAdaptor(session);
216     }
217 
218     public ClusteredManager getManager() {
219         return manager;
220     }
221 
222     public Node getNode() {
223         return dispatcherHolder.getNode();
224     }
225 
226     public void registerListener(SessionListener listener) {
227         synchronized (listeners) {
228             listeners.add(listener);
229         }
230     }
231 
232     public void unregisterListener(SessionListener listener) {
233         synchronized (listeners) {
234             listeners.remove(listener);
235         }
236     }
237 
238     private void notifyInboundSessionMigration(WebSession webSession) {
239         synchronized (listeners) {
240             for (Iterator iter = listeners.iterator(); iter.hasNext();) {
241                 SessionListener listener = (SessionListener) iter.next();
242                 listener.notifyInboundSessionMigration(new WADISessionAdaptor(webSession));
243             }
244         }
245     }
246 
247     private WebSession notifyOutboundSessionMigration(WebSession webSession) {
248         synchronized (listeners) {
249             for (Iterator iter = listeners.iterator(); iter.hasNext();) {
250                 SessionListener listener = (SessionListener) iter.next();
251                 listener.notifyOutboundSessionMigration(new WADISessionAdaptor(webSession));
252             }
253         }
254         return webSession;
255     }
256 
257     private class MotionTracker extends MemoryContextualiser {
258         private final Immoter immoter;
259 
260         private final Emoter emoter;
261 
262         public MotionTracker(Contextualiser next, Evicter evicter, Map map, Streamer streamer, SessionPool pool,
263                 PoolableInvocationWrapperPool requestPool) {
264             super(next, evicter, map, streamer, pool, requestPool);
265 
266             Immoter immoterDelegate = super.getImmoter();
267             immoter = new InboundSessionTracker(immoterDelegate);
268 
269             Emoter emoterDelegate = super.getEmoter();
270             emoter = new OutboundSessionTracker(emoterDelegate);
271         }
272 
273         public Immoter getPromoter(Immoter immoter) {
274             Immoter delegate = super.getPromoter(immoter);
275             if (null == immoter) {
276                 return new InboundSessionTracker(delegate);
277             } else {
278                 return delegate;
279             }
280         }
281 
282         public Immoter getImmoter() {
283             return immoter;
284         }
285 
286         public Emoter getEmoter() {
287             return emoter;
288         }
289     }
290 
291     private class OutboundSessionTracker implements Emoter {
292         private final Emoter delegate;
293 
294         public OutboundSessionTracker(Emoter delegate) {
295             this.delegate = delegate;
296         }
297 
298         public void commit(String arg0, Motable arg1) {
299             notifyOutboundSessionMigration((WebSession) arg1);
300             delegate.commit(arg0, arg1);
301         }
302 
303         public String getInfo() {
304             return delegate.getInfo();
305         }
306 
307         public boolean prepare(String arg0, Motable arg1, Motable arg2) {
308             return delegate.prepare(arg0, arg1, arg2);
309         }
310 
311         public void rollback(String arg0, Motable arg1) {
312             delegate.rollback(arg0, arg1);
313         }
314     }
315 
316     private class InboundSessionTracker implements Immoter {
317         private final Immoter delegate;
318 
319         public InboundSessionTracker(Immoter delegate) {
320             this.delegate = delegate;
321         }
322 
323         public void commit(String arg0, Motable arg1) {
324             notifyInboundSessionMigration((WebSession) arg1);
325             delegate.commit(arg0, arg1);
326         }
327 
328         public boolean contextualise(Invocation arg0, String arg1, Motable arg2, Sync arg3) throws InvocationException {
329             return delegate.contextualise(arg0, arg1, arg2, arg3);
330         }
331 
332         public String getInfo() {
333             return delegate.getInfo();
334         }
335 
336         public Motable nextMotable(String arg0, Motable arg1) {
337             return delegate.nextMotable(arg0, arg1);
338         }
339 
340         public boolean prepare(String arg0, Motable arg1, Motable arg2) {
341             return delegate.prepare(arg0, arg1, arg2);
342         }
343 
344         public void rollback(String arg0, Motable arg1) {
345             delegate.rollback(arg0, arg1);
346         }
347     }
348 
349     public static final GBeanInfo GBEAN_INFO;
350 
351     public static final String GBEAN_ATTR_WADI_CONFIG_INFO = "wadiConfigInfo";
352 
353     public static final String GBEAN_REF_REPLICATION_MANAGER_FACTORY = "ReplicationManagerFactory";
354     public static final String GBEAN_REF_REPLICA_STORAGE_FACTORY = "ReplicaStorageFactory";
355     public static final String GBEAN_REF_BACKING_STRATEGY_FACTORY = "BackingStrategyFactory";
356     public static final String GBEAN_REF_DISPATCHER_HOLDER = "DispatcherHolder";
357 
358     static {
359         GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic("WADI Session Manager",
360                 BasicWADISessionManager.class, NameFactory.GERONIMO_SERVICE);
361 
362         infoBuilder.addAttribute(GBEAN_ATTR_WADI_CONFIG_INFO, WADISessionManagerConfigInfo.class, true);
363 
364         infoBuilder.addReference(GBEAN_REF_REPLICATION_MANAGER_FACTORY, ReplicationManagerFactory.class,
365                 NameFactory.GERONIMO_SERVICE);
366         infoBuilder.addReference(GBEAN_REF_REPLICA_STORAGE_FACTORY, ReplicaStorageFactory.class,
367                 NameFactory.GERONIMO_SERVICE);
368         infoBuilder.addReference(GBEAN_REF_BACKING_STRATEGY_FACTORY, BackingStrategyFactory.class,
369                 NameFactory.GERONIMO_SERVICE);
370         infoBuilder.addReference(GBEAN_REF_DISPATCHER_HOLDER, DispatcherHolder.class, NameFactory.GERONIMO_SERVICE);
371 
372         infoBuilder.addInterface(SessionManager.class);
373         infoBuilder.addInterface(WADISessionManager.class);
374 
375         infoBuilder.setConstructor(new String[] { GBEAN_ATTR_WADI_CONFIG_INFO,
376                 GBEAN_REF_REPLICATION_MANAGER_FACTORY, 
377                 GBEAN_REF_REPLICA_STORAGE_FACTORY,
378                 GBEAN_REF_BACKING_STRATEGY_FACTORY, 
379                 GBEAN_REF_DISPATCHER_HOLDER });
380 
381         GBEAN_INFO = infoBuilder.getBeanInfo();
382     }
383 
384     public static GBeanInfo getGBeanInfo() {
385         return GBEAN_INFO;
386     }
387 }