001: /*
002: * Copyright 2005 jWic group (http://www.jwic.de)
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: *
016: * de.jwic.base.SessionContext
017: * $Id: SessionContext.java,v 1.6 2006/09/26 14:26:54 lordsam Exp $
018: */
019: package de.jwic.base;
020:
021: import java.io.Serializable;
022: import java.util.ArrayList;
023: import java.util.HashMap;
024: import java.util.Iterator;
025: import java.util.List;
026: import java.util.Locale;
027: import java.util.Map;
028: import java.util.Stack;
029: import java.util.StringTokenizer;
030:
031: import de.jwic.events.SessionEvent;
032: import de.jwic.events.SessionListener;
033:
034: /**
035: * Holds the configuration data for a specific application session. The lifecycle of
036: * the SessionContext is managed by the JWicRuntime.
037: *
038: * @author Florian Lippisch
039: */
040: public class SessionContext implements IControlContainer, Serializable {
041:
042: private static final long serialVersionUID = 6009335074727417445L;
043:
044: final static int AFTER_DESERIALIZATION = 0;
045: final static int BEFORE_SERIALIZATION = 1;
046: final static int SESSION_REUSED = 2;
047: final static int SESSION_STARTED = 3;
048: final static int SESSION_STOPPED = 4;
049:
050: public final static int STATE_NORMAL = 0;
051: public final static int STATE_DESTROYED = 1;
052: public final static int STATE_STORED = 2;
053:
054: public final static String PROP_NAME = "name";
055: public final static String PROP_CONTROL = "control";
056: public final static String PROP_APPID = "appid";
057: public final static String PROP_SERIALIZABLE = "serializable";
058: public final static String PROP_SINGLESESSION = "singlesession";
059: public final static String PROP_AUTHENTICATION = "authentication";
060:
061: private Map controls = new HashMap();
062: private Map layer = new HashMap();
063:
064: private String strRedirectToURL = null;
065: private boolean bolDoExit = false;
066: private String strCallBackURL = null;
067:
068: private String strExitURL = "";
069: private String strTopControlID = "";
070: private Stack stkTopControls = new Stack();
071:
072: private IApplication application = null;
073: private IApplicationSetup appSetup = null;
074: private Locale locale = null;
075:
076: private String clientId = null;
077: private String sessionId = null;
078:
079: private Map initParameter = null;
080: private List listeners = null;
081: private long requestTicket = 0;
082:
083: private boolean requireRedraw = true;
084:
085: private int state = STATE_NORMAL;
086: private UserAgentInfo userAgent = null;
087:
088: private transient IActionController actionController = new DefaultActionController();
089:
090: /**
091: * Creates a blank new SessionContext. The contstructor is just visible to
092: * the package.
093: */
094: SessionContext(IApplicationSetup appSetup, Locale locale) {
095: this .appSetup = appSetup;
096: this .locale = locale;
097: }
098:
099: /**
100: * Adds a SessionListener to this SessionContext.
101: * @param listener
102: */
103: public void addSessionListener(SessionListener listener) {
104: if (listeners == null) {
105: listeners = new ArrayList();
106: }
107: listeners.add(listener);
108: }
109:
110: /**
111: * Adds a SessionListener to this SessionContext.
112: * @param listener
113: */
114: public void removeSessionListener(SessionListener listener) {
115: if (listeners != null) {
116: listeners.remove(listener);
117: }
118: }
119:
120: /**
121: * Fire the specified event/method.
122: * @param event
123: * @param method
124: */
125: void fireEvent(SessionEvent event, int method) {
126:
127: if (method == AFTER_DESERIALIZATION) {
128: // recreate transient objects.
129: actionController = new DefaultActionController();
130: }
131:
132: event.setSessionContext(this );
133:
134: if (listeners != null) {
135: for (Iterator it = listeners.iterator(); it.hasNext();) {
136: SessionListener listener = (SessionListener) it.next();
137: switch (method) {
138: case AFTER_DESERIALIZATION:
139: listener.afterDeserialization(event);
140: break;
141: case BEFORE_SERIALIZATION:
142: listener.beforeSerialization(event);
143: break;
144: case SESSION_REUSED:
145: listener.sessionReused(event);
146: break;
147: case SESSION_STARTED:
148: listener.sessionStarted(event);
149: break;
150: case SESSION_STOPPED:
151: listener.sessionStopped(event);
152: break;
153: }
154: }
155: }
156: }
157:
158: /* (non-Javadoc)
159: * @see de.jwic.base.IControlContainer#adopt(de.jwic.base.Control)
160: */
161: public void adopt(Control control, String name) {
162:
163: // notify the old container that the control has been moved (remove it)
164: IControlContainer oldParent = control.getContainer();
165: if (oldParent == this ) {
166: return; // nothing to do
167: }
168: oldParent.unregisterControl(control);
169: registerControl(control, name);
170:
171: }
172:
173: /**
174: * Add a new FrameControl to this context. The name can not contain '.', ' ' or '_' characters.
175: */
176: public void registerControl(Control control, String name) {
177:
178: if (control.getContainer() != null) {
179: throw new JWicException(
180: "The control has already been registerd to a container.");
181: }
182:
183: if (name == null) {
184: int idx = controls.size();
185: name = "c" + idx;
186: while (controls.containsKey(name)) {
187: idx++;
188: name = "c" + idx;
189: }
190: }
191:
192: control.setSessionContext(this );
193: control.setContainer(this );
194: control.setName(name);
195: control.setControlID(control.getName());
196: controls.put(control.getName(), control);
197:
198: }
199:
200: /* (non-Javadoc)
201: * @see de.jwic.base.IControlContainer#unregisterControl(de.jwic.base.Control)
202: */
203: public void unregisterControl(Control control) {
204:
205: if (control.getContainer() == this ) {
206: controls.remove(control.getName());
207: }
208:
209: }
210:
211: /**
212: * Add a link to a control. A link can be used to render a control
213: * in a seperate frame.
214: *
215: * @param linkID
216: * @param control
217: */
218: public void addLayer(String layerID, Control control) {
219: layer.put(layerID, control);
220: }
221:
222: /**
223: * Stop the frame from redirecting to a previous specified URL.
224: */
225: public void clearRedirect() {
226:
227: strRedirectToURL = null;
228:
229: }
230:
231: /**
232: * Remove all controls in the context and destroy them.
233: *
234: */
235: public void destroy() {
236:
237: application.preDestroy();
238: if (state != STATE_DESTROYED) {
239: fireEvent(new SessionEvent(null), SESSION_STOPPED);
240: state = STATE_DESTROYED;
241: for (Iterator it = controls.values().iterator(); it
242: .hasNext();) {
243: Control control = (Control) it.next();
244: it.remove();
245: control.destroy();
246: }
247: }
248: JWicRuntime.getJWicRuntime().sessionDestroyed(this );
249: application.postDestroy();
250:
251: }
252:
253: /**
254: * Returns the IApplicationSetup this session is based upon.
255: * @return
256: */
257: public IApplicationSetup getApplicationSetup() {
258: return appSetup;
259: }
260:
261: /**
262: * Get the URL that will display the frame/session in the current state.
263: * @return java.lang.String
264: */
265: public java.lang.String getCallBackURL() {
266: return strCallBackURL;
267: }
268:
269: /**
270: * Returns the FrameControl specified by its name.
271: * @return FrameControl
272: */
273: public Control getControl(String ctrlName) {
274: return (Control) controls.get(ctrlName);
275: }
276:
277: /**
278: * Returns the FrameControl specified by a link.
279: * @return FrameControl
280: */
281: public Control getControlByLayerID(String layerID) {
282: return (Control) layer.get(layerID);
283: }
284:
285: /**
286: * Returns an Iterator for all FrameControl objects.
287: */
288: public Iterator getControls() {
289: return controls.values().iterator();
290: }
291:
292: /**
293: * Returns the URL a redirect should be sent to.
294: */
295: public String getRedirectToURL() {
296:
297: return strRedirectToURL;
298:
299: }
300:
301: /**
302: * Returns the control that is on top of the stack of visible controls.
303: * @return The top control.
304: */
305: public Control getTopControl() {
306: if (stkTopControls.empty()) {
307: return null;
308: }
309: return (Control) stkTopControls.lastElement();
310: }
311:
312: /**
313: * Returns the id of the control that is currently renderd.
314: * @return java.lang.String
315: */
316: public String getTopControlID() {
317: return strTopControlID;
318: }
319:
320: /**
321: * Returns the value for the specified key in the application
322: * properties.
323: * @param key
324: * @param defaultValue
325: * @return
326: */
327: public String getProperty(String key, String defaultValue) {
328: String value = appSetup.getProperty(key);
329: return value == null ? defaultValue : value;
330: }
331:
332: /**
333: * Returns true if the frameset should be left and the data should be purged.
334: */
335: public boolean isDoExit() {
336:
337: return bolDoExit;
338:
339: }
340:
341: /*
342: * (non-Javadoc)
343: * @see de.jwic.base.IControlContainer#isRenderingRelevant(de.jwic.base.Control)
344: */
345: public boolean isRenderingRelevant(Control childControl) {
346: return true;
347: }
348:
349: /**
350: * Remove the control from the stack of pushed top controls.
351: * @param control
352: */
353: void removeTopControl(Control control) {
354: if (stkTopControls.remove(control)) {
355: // control was pushed
356: if (!stkTopControls.empty()) {
357: Control fctrl = (Control) stkTopControls.lastElement();
358: strTopControlID = fctrl.getControlID();
359: } else {
360: strTopControlID = null;
361: }
362: }
363: }
364:
365: /**
366: * Remove the top control from the stack of visible controls.
367: *
368: */
369: public void popTopControl() {
370: Control frameControl = getTopControl();
371: stkTopControls.pop();
372: if (!stkTopControls.empty()) {
373: Control fctrl = (Control) stkTopControls.lastElement();
374: strTopControlID = fctrl.getControlID();
375: if (frameControl instanceof Page && fctrl instanceof Page) {
376: ((Page) frameControl).setClientSettings((Page) fctrl);
377: }
378: } else {
379: strTopControlID = null;
380: }
381: setRequireRedraw(true);
382: }
383:
384: /**
385: * Push a control on the stack of visible controls. The top control
386: * (including it's childs) is rendered only. Use popTopControl() to
387: * return to the previous control.
388: * @param frameControl
389: */
390: public void pushTopControl(Control frameControl) {
391: if (frameControl instanceof Page
392: && getTopControl() instanceof Page) {
393: ((Page) frameControl)
394: .setClientSettings((Page) getTopControl());
395: }
396: stkTopControls.push(frameControl);
397: strTopControlID = frameControl.getControlID();
398: frameControl.setVisible(true);
399: setRequireRedraw(true);
400: }
401:
402: /**
403: * Sends a redirect to the specified URL with the next page update
404: * sent to the client. If the isExit flag is true, all data is purged.
405: *
406: * @param sURL java.lang.String
407: * @param isExit boolean
408: */
409: public void redirectTo(String sURL, boolean isExit) {
410:
411: strRedirectToURL = sURL;
412: bolDoExit = isExit;
413: setRequireRedraw(true);
414:
415: }
416:
417: /**
418: * Remove a control from the container.
419: */
420: public void removeControl(String name) {
421: Control control = (Control) controls.get(name);
422: if (control != null) {
423: unregisterControl(control);
424: control.destroy();
425: }
426: }
427:
428: /**
429: * Remove the specified layer.
430: * @param layerId
431: */
432: public void removeLayer(String layerId) {
433: layer.remove(layerId);
434: }
435:
436: /**
437: * Set the URL that will display the frame/session in the current state.
438: * @param newCallBackURL java.lang.String
439: */
440: public void setCallBackURL(java.lang.String newCallBackURL) {
441: strCallBackURL = newCallBackURL;
442: }
443:
444: /**
445: * Get a control by its control ID.
446: * @param string
447: * @return
448: */
449: public Control getControlById(String ctrlID)
450: throws ControlNotFoundException {
451:
452: Control control = null;
453: StringTokenizer stk = new StringTokenizer(ctrlID, ".");
454: IControlContainer container = this ;
455: while (stk.hasMoreTokens()) {
456: String name = stk.nextToken();
457: control = container.getControl(name);
458: if (stk.hasMoreTokens()) {
459: if (control == null
460: || !(control instanceof IControlContainer))
461: throw new ControlNotFoundException(ctrlID);
462: container = (IControlContainer) control;
463: }
464: }
465: if (control == null)
466: throw new ControlNotFoundException(ctrlID);
467: return control;
468: }
469:
470: /**
471: * Returns the URL where the session context redirects to when the application exits.
472: * @return
473: */
474: public String getExitURL() {
475: return strExitURL;
476: }
477:
478: /**
479: * Set the URL where the session context redirects to when the application exits.
480: * @param string
481: */
482: public void setExitURL(String string) {
483: strExitURL = string;
484: }
485:
486: /**
487: * Exit the session and clean up all controls.
488: * @throws AgoraException
489: */
490: public void exit() {
491: if (strExitURL != null && strExitURL.length() != 0)
492: redirectTo(strExitURL, true);
493: else {
494: bolDoExit = true;
495: }
496: setRequireRedraw(true);
497: }
498:
499: /**
500: * @return Returns the actionController.
501: */
502: public IActionController getActionController() {
503: return actionController;
504: }
505:
506: /**
507: * @param actionController The actionController to set.
508: */
509: public void setActionController(IActionController actionController) {
510: this .actionController = actionController;
511: }
512:
513: /**
514: * @return Returns the locale.
515: */
516: public Locale getLocale() {
517: return locale;
518: }
519:
520: /**
521: * @return Returns the sessionId.
522: */
523: public String getClientId() {
524: return clientId;
525: }
526:
527: /**
528: * @param sessionId The sessionId to set.
529: */
530: void setClientId(String clientId) {
531: this .clientId = clientId;
532: }
533:
534: /**
535: * Returns the value of a parameter that was specified when the application
536: * has been started.
537: * @param key
538: * @return
539: */
540: public String getInitParameter(String key) {
541: if (initParameter != null) {
542: String[] str = (String[]) initParameter.get(key);
543: if (str != null) {
544: return str[0];
545: }
546: }
547: return null;
548: }
549:
550: /**
551: * Returns a map of parameters that have been specified when the application
552: * has been started.
553: * @return Returns the initParameter.
554: */
555: public Map getInitParameters() {
556: return initParameter;
557: }
558:
559: /**
560: * @param initParameter The initParameter to set.
561: */
562: void setInitParameters(Map initParameter) {
563: this .initParameter = initParameter;
564: }
565:
566: /**
567: * @return Returns the state.
568: */
569: public int getState() {
570: return state;
571: }
572:
573: /**
574: * Returns the current request ticket number.
575: * @return Returns the requestTicket.
576: */
577: public long getRequestTicket() {
578: return requestTicket;
579: }
580:
581: /**
582: * Validates if the ticket number equals the expected ticket number.
583: * If the numbers are equal, true is returned and the request ticket
584: * number is increased by one.
585: * @param ticket
586: * @return
587: */
588: public boolean validateTicket(long ticket) {
589: if (ticket == requestTicket) {
590: if (requestTicket == Long.MAX_VALUE) {
591: requestTicket = 0;
592: } else {
593: requestTicket++;
594: }
595: return true;
596: }
597: return false;
598: }
599:
600: /**
601: * Returns true if the page content has been changed since the last rendering
602: * and must be rendered again to reflect the last changes.
603: * @return Returns the requireRedraw.
604: */
605: public boolean isRequireRedraw() {
606: return requireRedraw;
607: }
608:
609: /**
610: * Set to true if the page content need to be rendered again to reflect the changes
611: * of the application since it was last rendered.
612: * @param requireRedraw The requireRedraw to set.
613: */
614: public void setRequireRedraw(boolean requireRedraw) {
615: this .requireRedraw = requireRedraw;
616: }
617:
618: /**
619: * @return Returns the application.
620: */
621: public IApplication getApplication() {
622: return application;
623: }
624:
625: /**
626: * @param application The application to set.
627: */
628: void setApplication(IApplication application) {
629: this .application = application;
630: }
631:
632: /**
633: * Set the Locale for this session.
634: * @param locale
635: */
636: public void setLocale(Locale locale) {
637: this .locale = locale;
638: }
639:
640: /**
641: * @return Returns the sessionId.
642: */
643: public String getSessionId() {
644: return sessionId;
645: }
646:
647: /**
648: * @param sessionId The sessionId to set.
649: */
650: public void setSessionId(String sessionId) {
651: this .sessionId = sessionId;
652: }
653:
654: /* (non-Javadoc)
655: * @see de.jwic.base.IControlContainer#getSessionContext()
656: */
657: public SessionContext getSessionContext() {
658: return this ;
659: }
660:
661: /**
662: * Returns Stack of pushed Control's.
663: * @return
664: */
665: public Stack getTopControls() {
666: return stkTopControls;
667: }
668:
669: /**
670: * @return Returns the userAgent.
671: */
672: public UserAgentInfo getUserAgent() {
673: return userAgent;
674: }
675:
676: /**
677: * @param userAgent The userAgent to set.
678: */
679: void setUserAgent(UserAgentInfo userAgent) {
680: this.userAgent = userAgent;
681: }
682:
683: }
|