001: /******************************************************************************
002: * JBoss, a division of Red Hat *
003: * Copyright 2006, Red Hat Middleware, LLC, and individual *
004: * contributors as indicated by the @authors tag. See the *
005: * copyright.txt in the distribution for a full listing of *
006: * individual contributors. *
007: * *
008: * This is free software; you can redistribute it and/or modify it *
009: * under the terms of the GNU Lesser General Public License as *
010: * published by the Free Software Foundation; either version 2.1 of *
011: * the License, or (at your option) any later version. *
012: * *
013: * This software is distributed in the hope that it will be useful, *
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of *
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
016: * Lesser General Public License for more details. *
017: * *
018: * You should have received a copy of the GNU Lesser General Public *
019: * License along with this software; if not, write to the Free *
020: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
021: * 02110-1301 USA, or see the FSF site: http://www.fsf.org. *
022: ******************************************************************************/package org.jboss.portal.portlet.session;
023:
024: import org.jboss.invocation.MarshalledValue;
025: import org.jboss.logging.Logger;
026:
027: import javax.servlet.http.HttpServletRequest;
028: import javax.servlet.http.HttpSession;
029: import java.io.Externalizable;
030: import java.io.IOException;
031: import java.io.ObjectInput;
032: import java.io.ObjectOutput;
033: import java.util.ArrayList;
034: import java.util.Collections;
035: import java.util.Enumeration;
036: import java.util.HashMap;
037: import java.util.Iterator;
038: import java.util.List;
039: import java.util.Map;
040: import java.util.Set;
041:
042: /**
043: * A subsession keep tracks of the content of a given portlet session.
044: *
045: * @author <a href="mailto:julien@jboss.org">Julien Viet</a>
046: * @version $Revision: 8784 $
047: */
048: public class SubSession implements Externalizable {
049:
050: /** The serialVersionUID */
051: private static final long serialVersionUID = -3584568048652090636L;
052:
053: /** . */
054: private static final Logger log = Logger
055: .getLogger(SubSession.class);
056:
057: /** . */
058: private boolean trace = log.isTraceEnabled();
059:
060: /** Signals that the session has been activated. */
061: private boolean activated;
062:
063: /** The session content. */
064: private Map map;
065:
066: /** The id. */
067: private String id;
068:
069: public SubSession(String id) {
070: if (id == null) {
071: throw new IllegalArgumentException();
072: }
073: this .id = id;
074: this .activated = false;
075: }
076:
077: public SubSession() {
078: }
079:
080: public String getId() {
081: return id;
082: }
083:
084: public boolean isActivated() {
085: return activated;
086: }
087:
088: public void setActivated(boolean activated) {
089: this .activated = activated;
090: }
091:
092: public Set getAttributeNames() {
093: if (map != null) {
094: return map.keySet();
095: } else {
096: return Collections.EMPTY_SET;
097: }
098: }
099:
100: public Object getAttribute(String name) {
101: trace("getAttribute: trying to get attribute named: '" + name
102: + "'");
103: if (map != null) {
104: return map.get(name);
105: } else {
106: trace("getAttribute: no existing attributes.");
107: return null;
108: }
109: }
110:
111: public void setAttribute(String name, Object value) {
112: if (map == null) {
113: map = new HashMap();
114: trace("setAttribute: no existing attributes, creating attribute map.");
115: }
116: if (name == null || name.length() == 0) {
117: throw new IllegalArgumentException(
118: "Must pass a valid, non-null attribute to set the attribute value.");
119: }
120: if (value == null) {
121: trace("setAttribute: removing attribute named: '" + name
122: + "'");
123: map.remove(name);
124: } else {
125: trace("setAttribute: set attribute named: '" + name
126: + "' to value: '" + value + "'");
127: map.put(name, value);
128: }
129: }
130:
131: public void create() {
132: trace("create");
133: if (map != null) {
134: trace("create: was expecting no map, had to clear it");
135: map.clear();
136: } else {
137: trace("create: attribute map created");
138: map = new HashMap();
139: }
140: }
141:
142: public void destroy() {
143: trace("destroy");
144: if (map == null) {
145: trace("destroy: was expecting an attribute map");
146: } else {
147: trace("destroy: attribute map destroyed");
148: map = null;
149: }
150: }
151:
152: /**
153: * @param portalRequest
154: * @param key
155: */
156: public void synchronizeWithPortalSession(
157: HttpServletRequest portalRequest, List modifications,
158: String key) {
159: // Apply changes
160: for (Iterator i = modifications.iterator(); i.hasNext();) {
161: Modification mod = (Modification) i.next();
162: if (mod instanceof AttributeModification) {
163: try {
164: AttributeModification attrMod = (AttributeModification) mod;
165: setAttribute(attrMod.getName(),
166: new MarshalledValue(attrMod.getValue()));
167: } catch (IOException e) {
168: e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
169: }
170: } else if (mod == SessionModification.SESSION_CREATED) {
171: create();
172: } else {
173: destroy();
174: }
175: }
176:
177: //
178: if (modifications.isEmpty() == false) {
179: // Performs an explicit set
180: HttpSession session = portalRequest.getSession();
181: session.setAttribute(key, this );
182: }
183: }
184:
185: /**
186: * Synchronize the content with the session held by the dispatched request. This method will use the thread context
187: * classloader to unserialize the content of the session.
188: *
189: * @param dispatchedRequest
190: */
191: public void synchronizeWithDispatchedSession(
192: HttpServletRequest dispatchedRequest) {
193: if (activated) {
194: trace("synchronizeWithDispatchedSession: session was activated, synchronizing...");
195: activated = false;
196:
197: //
198: HttpSession session = dispatchedRequest.getSession();
199:
200: //
201: trace("synchronizeWithDispatchedSession: removing existing attributes");
202: ArrayList names = new ArrayList();
203: for (Enumeration e = session.getAttributeNames(); e
204: .hasMoreElements();) {
205: String name = (String) e.nextElement();
206: names.add(name);
207: }
208: for (int i = 0; i < names.size(); i++) {
209: String name = (String) names.get(i);
210: trace("synchronizeWithDispatchedSession: removing attribute named: '"
211: + name
212: + "' with value: '"
213: + session.getAttribute(name)
214: + "' from existing session");
215: session.removeAttribute(name);
216: }
217:
218: //
219: for (Iterator i = map.entrySet().iterator(); i.hasNext();) {
220: Map.Entry entry = (Map.Entry) i.next();
221: String name = (String) entry.getKey();
222:
223: //
224: try {
225: MarshalledValue marshalledValue = (MarshalledValue) entry
226: .getValue();
227: Object value = marshalledValue.get();
228:
229: //
230: session.setAttribute(name, value);
231: trace("synchronizeWithDispatchedSession: setting attribute name: '"
232: + name + "' to value: '" + value + "'");
233: } catch (Exception e) {
234: log
235: .error(
236: "synchronizeWithDispatchedSession: couldn't unmarshall value for attribute named: '"
237: + name
238: + "'. Session won't be properly replicated!",
239: e);
240: }
241: }
242: } else {
243: trace("synchronizeWithDispatchedSession: session was not activated, did nothing");
244: }
245: }
246:
247: // private void marshallAttributesAndUpdateSessionIfNeeded(HttpSession session)
248: // {
249: // if (map != null)
250: // {
251: // for (Iterator i = map.entrySet().iterator(); i.hasNext();)
252: // {
253: // Map.Entry entry = (Map.Entry)i.next();
254: // String name = (String)entry.getKey();
255: // MarshalledValue marshalledValue = (MarshalledValue)entry.getValue();
256: //
257: // //
258: // try
259: // {
260: // Object value = marshalledValue.get();
261: // entry.setValue(value); // replace marshalled value by original one
262: // trace("synchronizeWithDispatchedSession: setting attribute name: '" + name + "' to value: '" + value
263: // + "'");
264: //
265: // // update session if requested
266: // if (session != null)
267: // {
268: // session.setAttribute(name, value);
269: // }
270: // }
271: // catch (Exception e)
272: // {
273: // log.error("synchronizeWithDispatchedSession: couldn't unmarshall value for attribute named: '" + name
274: // + "'. Session won't be properly replicated!", e);
275: // }
276: // }
277: // }
278: // }
279:
280: public void readExternal(ObjectInput in) throws IOException,
281: ClassNotFoundException {
282: id = in.readUTF();
283: map = (Map) in.readObject();
284: activated = true;
285: if (trace) {
286: log("SubSession deserialized");
287: }
288: }
289:
290: public void writeExternal(ObjectOutput out) throws IOException {
291: out.writeUTF(id);
292: out.writeObject(map);
293: if (trace) {
294: log("SubSession serialized");
295: }
296: }
297:
298: private void log(String prefix) {
299: StringBuffer tmp = new StringBuffer(prefix).append(" [");
300: for (Iterator i = map.keySet().iterator(); i.hasNext();) {
301: String key = (String) i.next();
302: tmp.append(key).append("(").append(map.get(key))
303: .append(")").append(i.hasNext() ? "," : "");
304: }
305: tmp.append("]");
306: trace(tmp.toString());
307: }
308:
309: private void trace(String message) {
310: if (trace) {
311: log.trace(message);
312: }
313: }
314: }
|