001: /* Copyright 2001 The JA-SIG Collaborative. All rights reserved.
002: * See license distributed with this file and
003: * available online at http://www.uportal.org/license.html
004: */
005:
006: package org.jasig.portal;
007:
008: import java.util.Collections;
009: import java.util.HashMap;
010: import java.util.Hashtable;
011: import java.util.Map;
012:
013: import javax.servlet.http.HttpServletRequest;
014: import javax.servlet.http.HttpServletResponse;
015: import javax.servlet.http.HttpSessionBindingEvent;
016: import javax.servlet.http.HttpSessionBindingListener;
017:
018: import org.jasig.portal.events.EventPublisherLocator;
019: import org.jasig.portal.events.support.UserSessionCreatedPortalEvent;
020: import org.jasig.portal.events.support.UserSessionDestroyedPortalEvent;
021: import org.jasig.portal.i18n.LocaleManager;
022: import org.jasig.portal.security.IPerson;
023: import org.apache.commons.logging.Log;
024: import org.apache.commons.logging.LogFactory;
025:
026: import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicInteger;
027:
028: /**
029: * A multithreaded version of a UserInstance.
030: * @author Peter Kharchenko {@link <a href="mailto:pkharchenko@interactivebusiness.com">pkharchenko@interactivebusiness.com</a>}
031: * @version $Revision: 36731 $
032: */
033: public class GuestUserInstance extends UserInstance implements
034: HttpSessionBindingListener {
035:
036: private static final Log log = LogFactory
037: .getLog(GuestUserInstance.class);
038: public static final AtomicInteger guestSessions = new AtomicInteger();
039:
040: // state class
041: private class IState {
042: private ChannelManager channelManager;
043: private LocaleManager localeManager;
044: private StandaloneChannelRenderer p_browserMapper;
045: private Object p_rendering_lock;
046:
047: public IState() {
048: channelManager = null;
049: p_rendering_lock = null;
050: p_browserMapper = null;
051: }
052: }
053:
054: Map stateTable;
055:
056: // manages layout and preferences
057: GuestUserPreferencesManager uLayoutManager;
058:
059: public GuestUserInstance(IPerson person) {
060: super (person);
061: // instantiate state table
062: stateTable = Collections.synchronizedMap(new HashMap());
063: uLayoutManager = new GuestUserPreferencesManager(person);
064: }
065:
066: /**
067: * Register arrival of a new session.
068: * Create and populate new state entry.
069: * @param req a <code>HttpServletRequest</code> value
070: */
071: public void registerSession(HttpServletRequest req)
072: throws PortalException {
073: IState newState = new IState();
074: newState.channelManager = new ChannelManager(
075: new GuestUserPreferencesManagerWrapper(uLayoutManager,
076: req.getSession(false).getId()));
077: newState.localeManager = new LocaleManager(person, req
078: .getHeader("Accept-Language"));
079: newState.p_rendering_lock = new Object();
080: uLayoutManager.setLocaleManager(newState.localeManager);
081: uLayoutManager.registerSession(req);
082: stateTable.put(req.getSession(false).getId(), newState);
083: }
084:
085: /**
086: * Unbinds a registered session.
087: * @param sessionId a <code>String</code> value
088: */
089: public void unbindSession(String sessionId) {
090: IState state = (IState) stateTable.get(sessionId);
091: if (state == null) {
092: log
093: .error("GuestUserInstance::unbindSession() : trying to envoke a method on a non-registered sessionId=\""
094: + sessionId + "\".");
095: return;
096: }
097: state.channelManager.finishedSession();
098: state.channelManager = null;
099: uLayoutManager.unbindSession(sessionId);
100: stateTable.remove(sessionId);
101: }
102:
103: /**
104: * This notifies UserInstance that it has been unbound from the session.
105: * Method triggers cleanup in ChannelManager.
106: *
107: * @param bindingEvent an <code>HttpSessionBindingEvent</code> value
108: */
109: public void valueUnbound(HttpSessionBindingEvent bindingEvent) {
110: this .unbindSession(bindingEvent.getSession().getId());
111: if (log.isDebugEnabled())
112: log.debug("GuestUserInstance::valueUnbound() : "
113: + "unbinding session \""
114: + bindingEvent.getSession().getId() + "\"");
115:
116: // Record the destruction of the session
117: EventPublisherLocator.getApplicationEventPublisher()
118: .publishEvent(
119: new UserSessionDestroyedPortalEvent(this ,
120: person));
121: guestSessions.decrementAndGet();
122: }
123:
124: /**
125: * Notifies UserInstance that it has been bound to a session.
126: *
127: * @param bindingEvent a <code>HttpSessionBindingEvent</code> value
128: */
129: public void valueBound(HttpSessionBindingEvent bindingEvent) {
130: if (log.isDebugEnabled())
131: log.debug("GuestUserInstance::valueBound() : "
132: + "instance bound to a new session \""
133: + bindingEvent.getSession().getId() + "\"");
134:
135: // Record the creation of the session
136: EventPublisherLocator
137: .getApplicationEventPublisher()
138: .publishEvent(
139: new UserSessionCreatedPortalEvent(this , person));
140: guestSessions.incrementAndGet();
141: }
142:
143: /**
144: * Prepares for and initates the rendering cycle.
145: * @param req the servlet request object
146: * @param res the servlet response object
147: */
148: public void writeContent(HttpServletRequest req,
149: HttpServletResponse res) throws PortalException {
150: String sessionId = req.getSession(false).getId();
151: IState state = (IState) stateTable.get(sessionId);
152: if (state == null) {
153: log
154: .error("GuestUserInstance::writeContent() : trying to envoke a method on a non-registered sessionId=\""
155: + sessionId + "\".");
156: return;
157: }
158: // instantiate user layout manager and check to see if the profile mapping has been established
159: if (state.p_browserMapper != null) {
160: try {
161: state.p_browserMapper.prepare(req);
162: } catch (Exception e) {
163: throw new PortalException(e);
164: }
165: }
166: if (uLayoutManager.isUserAgentUnmapped(sessionId)) {
167: uLayoutManager.unbindSession(sessionId);
168: uLayoutManager.registerSession(req);
169: } else {
170: // p_browserMapper is no longer needed
171: state.p_browserMapper = null;
172: }
173:
174: if (uLayoutManager.isUserAgentUnmapped(sessionId)) {
175: // unmapped browser
176: if (state.p_browserMapper == null) {
177: state.p_browserMapper = new org.jasig.portal.channels.CSelectSystemProfile();
178: state.p_browserMapper.initialize(new Hashtable(),
179: "CSelectSystemProfile", true, true, false,
180: 10000, getPerson());
181: }
182: try {
183: state.p_browserMapper.render(req, res);
184: } catch (PortalException pe) {
185: throw pe;
186: } catch (Throwable t) {
187: // something went wrong trying to show CSelectSystemProfileChannel
188: log
189: .error("GuestUserInstance::writeContent() : CSelectSystemProfileChannel.render() threw: "
190: + t);
191: throw new PortalException(
192: "CSelectSystemProfileChannel.render() threw: "
193: + t);
194: }
195: // don't go any further!
196: return;
197: }
198:
199: renderState(req, res, state.channelManager,
200: state.localeManager,
201: new GuestUserPreferencesManagerWrapper(uLayoutManager,
202: sessionId), state.p_rendering_lock);
203: }
204: }
|