KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > webapps > session > components > DefaultSessionManager


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.webapps.session.components;
17
18 import org.apache.avalon.framework.activity.Disposable;
19 import org.apache.avalon.framework.component.Component;
20 import org.apache.avalon.framework.context.Context;
21 import org.apache.avalon.framework.context.ContextException;
22 import org.apache.avalon.framework.context.Contextualizable;
23 import org.apache.avalon.framework.logger.AbstractLogEnabled;
24 import org.apache.avalon.framework.service.ServiceException;
25 import org.apache.avalon.framework.service.ServiceManager;
26 import org.apache.avalon.framework.service.Serviceable;
27 import org.apache.avalon.framework.thread.ThreadSafe;
28 import org.apache.cocoon.ProcessingException;
29 import org.apache.cocoon.components.ContextHelper;
30 import org.apache.cocoon.environment.Request;
31 import org.apache.cocoon.environment.Session;
32 import org.apache.cocoon.webapps.session.ContextManager;
33 import org.apache.cocoon.webapps.session.SessionConstants;
34 import org.apache.cocoon.webapps.session.SessionManager;
35 import org.apache.cocoon.webapps.session.context.SessionContext;
36 import org.apache.cocoon.xml.XMLConsumer;
37 import org.apache.cocoon.xml.XMLUtils;
38 import org.apache.cocoon.xml.dom.DOMUtil;
39 import org.w3c.dom.DocumentFragment JavaDoc;
40 import org.w3c.dom.Element JavaDoc;
41 import org.w3c.dom.Node JavaDoc;
42 import org.w3c.dom.NodeList JavaDoc;
43 import org.xml.sax.SAXException JavaDoc;
44
45 /**
46  * This is the default implementation of the session manager
47  *
48  * @author <a HREF="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
49  * @version CVS $Id: DefaultSessionManager.java 30932 2004-07-29 17:35:38Z vgritsenko $
50 */

51 public final class DefaultSessionManager
52 extends AbstractLogEnabled
53 implements Serviceable, Component, ThreadSafe, SessionManager, Disposable, Contextualizable {
54
55     /** The context */
56     private Context context;
57     
58     /** The <code>ServiceManager</code> */
59     private ServiceManager manager;
60
61     /** The context manager */
62     private ContextManager contextManager;
63     
64     /**
65     * Avalon Serviceable Interface
66     */

67    public void service(ServiceManager manager)
68    throws ServiceException {
69        this.manager = manager;
70        this.contextManager = (ContextManager)this.manager.lookup(ContextManager.ROLE);
71    }
72
73     /**
74      * Avalon Disposable Interface
75      */

76     public void dispose() {
77         if (this.manager != null ) {
78             this.manager.release(this.contextManager);
79             this.manager = null;
80             this.contextManager = null;
81         }
82     }
83     /**
84      * Create a new session for the user.
85      * A new session is created for this user. If the user has already a session,
86      * no new session is created and the old one is returned.
87      */

88     public Session createSession() {
89         // synchronized
90
if (this.getLogger().isDebugEnabled() ) {
91             this.getLogger().debug("BEGIN createSession");
92         }
93         Session session = this.getSession(true);
94
95         if (this.getLogger().isDebugEnabled() ) {
96             this.getLogger().debug("END createSession session=" + session);
97         }
98         return session;
99     }
100
101     /**
102      * Get the session for the current user.
103      * If the user has no session right now, <CODE>null</CODE> is returned.
104      * If createFlag is true, the session is created if it does not exist.
105      */

106     public Session getSession(boolean createFlag) {
107         final Request request = ContextHelper.getRequest(this.context);
108
109         // synchronized
110
if (this.getLogger().isDebugEnabled() ) {
111             this.getLogger().debug("BEGIN getSession create=" + createFlag);
112         }
113         Session session = request.getSession(createFlag);
114
115         if (this.getLogger().isDebugEnabled() ) {
116             this.getLogger().debug("END getSession session=" + session);
117         }
118
119         return session;
120     }
121
122     /**
123      * Terminate the current session.
124      * If the user has a session, this session is terminated and all of its
125      * data is deleted.
126      * @param force If this is set to true the session is terminated, if
127      * it is set to false, the session is only terminated
128      * if no session context is available.
129      */

130     public void terminateSession(boolean force)
131     throws ProcessingException {
132         // synchronized
133
if (this.getLogger().isDebugEnabled() ) {
134             this.getLogger().debug("BEGIN terminateSession force="+force);
135         }
136
137         Session session = this.getSession( false );
138         if (session != null) {
139             if (force || this.contextManager.hasSessionContext() ) {
140                 synchronized(session) {
141                     session.invalidate();
142                 }
143             }
144         }
145         if (this.getLogger().isDebugEnabled()) {
146             this.getLogger().debug("END terminateSession");
147         }
148     }
149
150     /**
151      * Get information from the context.
152      * A document fragment containg the xml data stored in the session context
153      * with the given name is returned. If the information is not available,
154      * <CODE>null</CODE> is returned.
155      * @param contextName The name of the public context.
156      * @param path XPath expression specifying which data to get.
157      * @return A DocumentFragment containing the data or <CODE>null</CODE>
158      */

159     public DocumentFragment JavaDoc getContextFragment(String JavaDoc contextName,
160                                                      String JavaDoc path)
161     throws ProcessingException {
162         // synchronized via context
163
if (this.getLogger().isDebugEnabled() ) {
164             this.getLogger().debug("BEGIN getContextFragment name=" + contextName + ", path=" + path);
165         }
166
167         // test arguments
168
if (contextName == null) {
169             throw new ProcessingException("SessionManager.getContextFragment: Name is required");
170         }
171         if (path == null) {
172             throw new ProcessingException("SessionManager.getContextFragment: Path is required");
173         }
174
175         SessionContext context = this.contextManager.getContext( contextName );
176
177         if (context == null) {
178             throw new ProcessingException("SessionManager.getContextFragment: Context '" + contextName + "' not found.");
179         }
180
181         DocumentFragment JavaDoc frag;
182         frag = context.getXML(path);
183
184         if (this.getLogger().isDebugEnabled() ) {
185             this.getLogger().debug("END getContextFragment documentFragment=" + (frag == null ? "null" : XMLUtils.serializeNode(frag, XMLUtils.createPropertiesForXML(false))));
186         }
187         return frag;
188     }
189
190     /**
191      * Stream public context data.
192      * The document fragment containing the data from a path in the
193      * given context is streamed to the consumer.
194      *
195      * @param contextName The name of the public context.
196      * @param path XPath expression specifying which data to get.
197      *
198      * @return If the data is available <code>true</code> is returned,
199      * otherwise <code>false</code> is returned.
200      */

201     public boolean streamContextFragment(String JavaDoc contextName,
202                                            String JavaDoc path,
203                                            XMLConsumer consumer)
204     throws SAXException JavaDoc, ProcessingException {
205         // synchronized via context
206
if (this.getLogger().isDebugEnabled() ) {
207             this.getLogger().debug("BEGIN streamContextFragment name=" + contextName + ", path=" + path + ", consumer"+consumer);
208         }
209         boolean streamed = false;
210
211         // test arguments
212
if (contextName == null) {
213             throw new ProcessingException("SessionManager.streamContextFragment: Name is required");
214         }
215         if (path == null) {
216             throw new ProcessingException("SessionManager.streamContextFragment: Path is required");
217         }
218
219         SessionContext context = this.contextManager.getContext( contextName );
220
221         if (context == null) {
222             throw new ProcessingException("SessionManager.streamContextFragment: Context '" + contextName + "' not found.");
223         }
224
225         streamed = context.streamXML(path, consumer, consumer);
226
227         if (this.getLogger().isDebugEnabled() ) {
228             this.getLogger().debug("END streamContextFragment streamed=" + streamed);
229         }
230         return streamed;
231     }
232
233     /**
234      * Set data in a public context.
235      * The document fragment containing the data is set at the given path in the
236      * public session context.
237      *
238      * @param contextName The name of the public context.
239      * @param path XPath expression specifying where to set the data.
240      * @param fragment The DocumentFragment containing the data.
241      *
242      */

243     public void setContextFragment(String JavaDoc contextName,
244                                     String JavaDoc path,
245                                     DocumentFragment JavaDoc fragment)
246     throws ProcessingException {
247         // synchronized via context
248

249         if (this.getLogger().isDebugEnabled()) {
250             this.getLogger().debug("BEGIN setContextFragment name=" + contextName + ", path=" + path +
251                ", fragment=" + (fragment == null ? "null" : XMLUtils.serializeNode(fragment, XMLUtils.createPropertiesForXML(false))));
252         }
253         // test arguments
254
if (contextName == null) {
255             throw new ProcessingException("SessionManager.setContextFragment: Name is required");
256         }
257         if (path == null) {
258             throw new ProcessingException("SessionManager.setContextFragment: Path is required");
259         }
260         if (fragment == null) {
261             throw new ProcessingException("SessionManager.setContextFragment: Fragment is required");
262         }
263
264         // get context
265
SessionContext context = this.contextManager.getContext( contextName );
266
267         // check context
268
if (context == null) {
269             throw new ProcessingException("SessionManager.setContextFragment: Context '" + contextName + "' not found.");
270         }
271
272         context.setXML(path, fragment);
273
274         if (this.getLogger().isDebugEnabled() ) {
275             this.getLogger().debug("END setContextFragment");
276         }
277     }
278
279     /**
280      * Append data in a public context.
281      * The document fragment containing the data is appended at the given
282      * path in the public session context.
283      *
284      * @param contextName The name of the public context.
285      * @param path XPath expression specifying where to append the data.
286      * @param fragment The DocumentFragment containing the data.
287      *
288      */

289     public void appendContextFragment(String JavaDoc contextName,
290                                        String JavaDoc path,
291                                        DocumentFragment JavaDoc fragment)
292     throws ProcessingException {
293         // synchronized via context
294
if (this.getLogger().isDebugEnabled() ) {
295             this.getLogger().debug("BEGIN appendContextFragment name=" + contextName +
296                               ", path=" + path +
297                               ", fragment=" + (fragment == null ? "null" : XMLUtils.serializeNode(fragment, XMLUtils.createPropertiesForXML(false))));
298         }
299         // test arguments
300
if (contextName == null) {
301             throw new ProcessingException("SessionManager.appendContextFragment: Name is required");
302         }
303         if (path == null) {
304             throw new ProcessingException("SessionManager.appendContextFragment: Path is required");
305         }
306         if (fragment == null) {
307             throw new ProcessingException("SessionManager.appendContextFragment: Fragment is required");
308         }
309
310         // get context
311
SessionContext context = this.contextManager.getContext( contextName );
312
313         // check context
314
if (context == null) {
315             throw new ProcessingException("SessionManager.appendContextFragment: Context '" + contextName + "' not found.");
316         }
317
318         context.appendXML(path, fragment);
319
320         if (this.getLogger().isDebugEnabled() ) {
321             this.getLogger().debug("END appendContextFragment");
322         }
323     }
324
325     /**
326      * Merge data in a public context.
327      * The document fragment containing the data is merged at the given
328      * path in the public session context.
329      *
330      * @param contextName The name of the public context.
331      * @param path XPath expression specifying where to merge the data.
332      * @param fragment The DocumentFragment containing the data.
333      *
334      */

335     public void mergeContextFragment(String JavaDoc contextName,
336                                       String JavaDoc path,
337                                       DocumentFragment JavaDoc fragment)
338     throws ProcessingException {
339         // synchronized via context
340
if (this.getLogger().isDebugEnabled() ) {
341             this.getLogger().debug("BEGIN mergeContextFragment name=" + contextName + ", path=" + path +
342                 ", fragment=" + (fragment == null ? "null" : XMLUtils.serializeNode(fragment, XMLUtils.createPropertiesForXML(false))));
343         }
344
345         // test arguments
346
if (contextName == null) {
347             throw new ProcessingException("SessionManager.mergeContextFragment: Name is required");
348         }
349         if (path == null) {
350             throw new ProcessingException("SessionManager.mergeContextFragment: Path is required");
351         }
352         if (fragment == null) {
353             throw new ProcessingException("SessionManager.mergeContextFragment: Fragment is required");
354         }
355
356         // get context
357
SessionContext context = this.contextManager.getContext( contextName );
358
359         // check context
360
if (context == null) {
361             throw new ProcessingException("SessionManager.mergeContextFragment: Context '" + contextName + "' not found.");
362         }
363
364         Node JavaDoc contextNode = context.getSingleNode(path);
365         if (contextNode == null) {
366             // no merge required
367
context.setXML(path, fragment);
368         } else {
369             this.importNode(contextNode, fragment, false);
370             context.setNode(path, contextNode);
371         }
372
373         if (this.getLogger().isDebugEnabled()) {
374             this.getLogger().debug("END mergeContextFragment");
375         }
376     }
377
378     /**
379      * Remove data in a public context.
380      * The data specified by the path is removed from the public session context.
381      *
382      * @param contextName The name of the public context.
383      * @param path XPath expression specifying where to merge the data.
384      *
385      */

386     public void removeContextFragment(String JavaDoc contextName,
387                                         String JavaDoc path)
388     throws ProcessingException {
389         // synchronized via context
390
if (this.getLogger().isDebugEnabled() ) {
391             this.getLogger().debug("BEGIN removeContextFragment name=" + contextName + ", path=" + path);
392         }
393         // test arguments
394
if (contextName == null) {
395             throw new ProcessingException("SessionManager.removeContextFragment: Name is required");
396         }
397         if (path == null) {
398             throw new ProcessingException("SessionManager.removeContextFragment: Path is required");
399         }
400
401         // get context
402
SessionContext context = this.contextManager.getContext( contextName );
403
404         // check context
405
if (context == null) {
406             throw new ProcessingException("SessionManager.removeContextFragment: Context '" + contextName + "' not found.");
407         }
408
409         context.removeXML(path);
410
411         if (this.getLogger().isDebugEnabled() ) {
412             this.getLogger().debug("END removeContextFragment");
413         }
414     }
415
416     /**
417      * Import nodes. If preserve is set to true, the nodes
418      * marked with cocoon:preserve are always imported
419      * overwriting others!
420      */

421     private void importNode(Node JavaDoc profile, Node JavaDoc delta, boolean preserve) {
422         // no sync req
423
NodeList JavaDoc profileChilds = null;
424         NodeList JavaDoc deltaChilds = delta.getChildNodes();
425         int i, len;
426         int m, l;
427         boolean found;
428         Node JavaDoc currentDelta = null;
429         Node JavaDoc currentProfile = null;
430
431         len = deltaChilds.getLength();
432         for(i = 0; i < len; i++) {
433             currentDelta = deltaChilds.item(i);
434             if (currentDelta.getNodeType() == Node.ELEMENT_NODE) {
435                 // search the delta node in the profile
436
profileChilds = profile.getChildNodes();
437                 l = profileChilds.getLength();
438                 m = 0;
439                 found = false;
440                 while (found == false && m < l) {
441                     currentProfile = profileChilds.item(m);
442                     if (currentProfile.getNodeType() == Node.ELEMENT_NODE
443                         && currentProfile.getNodeName().equals(currentDelta.getNodeName()) == true) {
444
445                         // now we have found a node with the same name
446
// next: the attributes must match also
447
found = DOMUtil.compareAttributes((Element JavaDoc)currentProfile, (Element JavaDoc)currentDelta);
448                     }
449                     if (found == false) m++;
450                 }
451                 if (found == true) {
452                     // this is not new
453

454                     if (preserve == true
455                         && ((Element JavaDoc)currentDelta).hasAttributeNS(SessionConstants.SESSION_NAMESPACE_URI, "preserve")
456                         && ((Element JavaDoc)currentDelta).getAttributeNS(SessionConstants.SESSION_NAMESPACE_URI, "preserve").equalsIgnoreCase("true")) {
457                         // replace the original with the delta
458
profile.replaceChild(profile.getOwnerDocument().importNode(currentDelta, true),
459                                               currentProfile);
460                     } else {
461                         // do we have elements as children or text?
462
if (currentDelta.hasChildNodes() == true) {
463                             currentDelta.normalize();
464                             currentProfile.normalize();
465                             // do a recursive call for sub elements
466
this.importNode(currentProfile, currentDelta, preserve);
467                             // and now the text nodes: Remove all from the profile and add all
468
// of the delta
469
NodeList JavaDoc childs = currentProfile.getChildNodes();
470                             int index, max;
471                             max = childs.getLength();
472                             for(index = max - 1; index >= 0; index--) {
473                                 if (childs.item(index).getNodeType() == Node.TEXT_NODE) {
474                                     currentProfile.removeChild(childs.item(index));
475                                 }
476                             }
477                             childs = currentDelta.getChildNodes();
478                             max = childs.getLength();
479                             for(index = 0; index < max; index++) {
480                                 if (childs.item(index).getNodeType() == Node.TEXT_NODE) {
481                                     currentProfile.appendChild(currentProfile.getOwnerDocument()
482                                      .createTextNode(childs.item(index).getNodeValue()));
483                                 }
484                             }
485                         }
486                     }
487                 } else {
488                     profile.appendChild(profile.getOwnerDocument().importNode(currentDelta, true));
489                 }
490             }
491
492         }
493
494     }
495
496     /* (non-Javadoc)
497      * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
498      */

499     public void contextualize(Context context) throws ContextException {
500         this.context = context;
501     }
502
503 }
504
Popular Tags