001: /*
002: * Copyright 2002 Sun Microsystems, Inc. All
003: * rights reserved. Use of this product is subject
004: * to license terms. Federal Acquisitions:
005: * Commercial Software -- Government Users
006: * Subject to Standard License Terms and
007: * Conditions.
008: *
009: * Sun, Sun Microsystems, the Sun logo, and Sun ONE
010: * are trademarks or registered trademarks of Sun Microsystems,
011: * Inc. in the United States and other countries.
012: */
013:
014: package com.sun.portal.portlet.impl;
015:
016: import java.util.ArrayList;
017: import java.util.Collections;
018: import java.util.Enumeration;
019:
020: import javax.portlet.PortletContext;
021: import javax.portlet.PortletSession;
022: import javax.servlet.http.HttpSession;
023:
024: /**
025: * The <code>PortletSessionImpl</code> class provides a default
026: * implementation for the <code>PortletSession</code> interface.
027: *
028: */
029:
030: public class PortletSessionImpl implements PortletSession {
031:
032: // constants
033: // fabricated attribute name: javax.portlet.w.<ID>?<ATTRIBUTE_NAME>
034: private static final String PORTLET_SCOPE_ATTR_PREFIX = "javax.portlet.p.";
035: private static int LENGTH_OF_PORTLET_SCOPE_ATTR_PREFIX = 16;
036:
037: //private data members
038: private HttpSession _httpSession;
039: private PortletContext _portletContext; // TBD: transient???
040:
041: // constructor
042: public PortletSessionImpl(HttpSession session, PortletContext pc) {
043:
044: _httpSession = session;
045: _portletContext = pc;
046: }
047:
048: /**
049: * Returns the object bound with the specified name in this session
050: * under the <code>PORTLET_SCOPE</code>, or <code>null</code> if no
051: * object is bound under the name in that scope.
052: *
053: * @param name a string specifying the name of the object
054: *
055: * @return the object with the specified name for
056: * the <code>PORTLET_SCOPE</code>.
057: *
058: * @exception java.lang.IllegalStateException if this method is called on an
059: * invalidated session.
060: * @exception java.lang.IllegalArgumentException
061: * if name is <code>null</code>.
062: */
063: public java.lang.Object getAttribute(java.lang.String name)
064: throws IllegalArgumentException {
065:
066: if (name == null) {
067: throw new IllegalArgumentException(
068: "The given attribute name is null");
069: }
070: return _httpSession.getAttribute(getEncodedAttrName(name,
071: PORTLET_SCOPE));
072: }
073:
074: /**
075: * Returns the object bound with the specified name in this session,
076: * or <code>null</code> if no object is bound under the name in the given scope.
077: *
078: * @param name a string specifying the name of the object
079: * @param scope session scope of this attribute
080: *
081: * @return the object with the specified name
082: *
083: * @exception java.lang.IllegalStateException if this method is called on an
084: * invalidated session
085: * @exception java.lang.IllegalArgumentException
086: * if name is <code>null</code>.
087: */
088: public Object getAttribute(String name, int scope)
089: throws IllegalArgumentException {
090:
091: if (name == null) {
092: throw new IllegalArgumentException(
093: "The given attribute name is null");
094: }
095: return _httpSession
096: .getAttribute(getEncodedAttrName(name, scope));
097: }
098:
099: /**
100: * Returns an <code>Enumeration</code> of String objects containing the names of
101: * all the objects bound to this session under the <code>PORTLET_SCOPE</code>, or an
102: * empty <code>Enumeration</code> if no attributes are available.
103: *
104: * @return an <code>Enumeration</code> of
105: * <code>String</code> objects specifying the
106: * names of all the objects bound to
107: * this session, or an empty <code>Enumeration</code>
108: * if no attributes are available.
109: *
110: * @exception java.lang.IllegalStateException if this method is called on an
111: * invalidated session
112: */
113:
114: public java.util.Enumeration getAttributeNames() {
115:
116: return getAttributeNames(PORTLET_SCOPE);
117: }
118:
119: /**
120: * Returns an <code>Enumeration</code> of String objects containing the names of
121: * all the objects bound to this session in the given scope, or an
122: * empty <code>Enumeration</code> if no attributes are available in the
123: * given scope.
124: *
125: * @param scope session scope of the attribute names
126: *
127: * @return an <code>Enumeration</code> of
128: * <code>String</code> objects specifying the
129: * names of all the objects bound to
130: * this session, or an empty <code>Enumeration</code>
131: * if no attributes are available in the given scope.
132: *
133: * @exception java.lang.IllegalStateException if this method is called on an
134: * invalidated session
135: */
136: public Enumeration getAttributeNames(int scope) {
137:
138: Enumeration enum = _httpSession.getAttributeNames();
139: ArrayList attrs = new ArrayList();
140:
141: if (scope == APPLICATION_SCOPE) {
142: while (enum.hasMoreElements()) {
143: String attrName = (String)enum.nextElement();
144: if (!attrName.startsWith(PORTLET_SCOPE_ATTR_PREFIX)) {
145: attrs.add(attrName);
146: }
147: }
148: } else { // PORTLET_SCOPE
149: while (enum.hasMoreElements()) {
150: String attrName = (String)enum.nextElement();
151: if (isTargetPortletID(attrName)) {
152: attrs.add(getDecodedAttrName(attrName));
153: }
154: }
155: }
156: return Collections.enumeration(attrs);
157: }
158:
159: /**
160: * Returns the time when this session was created, measured in
161: * milliseconds since midnight January 1, 1970 GMT.
162: *
163: * @return a <code>long</code> specifying
164: * when this session was created,
165: * expressed in
166: * milliseconds since 1/1/1970 GMT
167: *
168: * @exception java.lang.IllegalStateException if this method is called on an
169: * invalidated session
170: */
171: public long getCreationTime() {
172:
173: return _httpSession.getCreationTime();
174: }
175:
176: /**
177: * Returns a string containing the unique identifier assigned to this session.
178: *
179: * @return a string specifying the identifier
180: * assigned to this session
181: */
182: public String getId() {
183:
184: return _httpSession.getId();
185: }
186:
187: /**
188: * Returns the last time the client sent a request associated with this session,
189: * as the number of milliseconds since midnight January 1, 1970 GMT.
190: *
191: * <p>Actions that your portlet takes, such as getting or setting
192: * a value associated with the session, do not affect the access
193: * time.
194: *
195: * @return a <code>long</code>
196: * representing the last time
197: * the client sent a request associated
198: * with this session, expressed in
199: * milliseconds since 1/1/1970 GMT
200: */
201: public long getLastAccessedTime() {
202:
203: return _httpSession.getLastAccessedTime();
204: }
205:
206: /**
207: * Returns the maximum time interval, in seconds, for which the portlet container
208: * keeps this session open between client accesses. After this interval,
209: * the portlet container invalidates the session. The maximum time
210: * interval can be set
211: * with the <code>setMaxInactiveInterval</code> method.
212: * A negative time indicates the session should never timeout.
213: *
214: * @return an integer specifying the number of
215: * seconds this session remains open
216: * between client requests
217: *
218: * @see #setMaxInactiveInterval
219: */
220: public int getMaxInactiveInterval() {
221:
222: return _httpSession.getMaxInactiveInterval();
223: }
224:
225: /**
226: * Invalidates this session (all scopes) and unbinds any objects bound to it.
227: * <p>
228: * Invalidating the portlet session will result in invalidating the underlying
229: * <code>HttpSession</code>
230: *
231: * @exception java.lang.IllegalStateException if this method is called on a
232: * session which has already been invalidated
233: */
234: public void invalidate() {
235:
236: _httpSession.invalidate();
237: }
238:
239: /**
240: * Returns true if the client does not yet know about the session or
241: * if the client chooses not to join the session.
242: *
243: * @return <code>true</code> if the
244: * server has created a session,
245: * but the client has not joined yet.
246: *
247: * @exception java.lang.IllegalStateException if this method is called on a
248: * session which has already been invalidated
249: *
250: */
251: public boolean isNew() {
252:
253: return _httpSession.isNew();
254: }
255:
256: /**
257: * Removes the object bound with the specified name under
258: * the <code>PORTLET_SCOPE</code> from
259: * this session. If the session does not have an object
260: * bound with the specified name, this method does nothing.
261: *
262: * @param name the name of the object to be
263: * removed from this session in the
264: * <code> PORTLET_SCOPE</code>.
265: *
266: * @exception java.lang.IllegalStateException
267: * if this method is called on a
268: * session which has been invalidated
269: * @exception java.lang.IllegalArgumentException
270: * if name is <code>null</code>.
271: */
272: public void removeAttribute(String name)
273: throws IllegalArgumentException {
274:
275: if (name == null) {
276: throw new IllegalArgumentException(
277: "The given attribute name is null");
278: }
279: _httpSession.removeAttribute(getEncodedAttrName(name,
280: PORTLET_SCOPE));
281: }
282:
283: /**
284: * Removes the object bound with the specified name and the given scope from
285: * this session. If the session does not have an object
286: * bound with the specified name, this method does nothing.
287: *
288: * @param name the name of the object to be
289: * removed from this session
290: * @param scope session scope of this attribute
291: *
292: * @exception java.lang.IllegalStateException
293: * if this method is called on a
294: * session which has been invalidated
295: * @exception java.lang.IllegalArgumentException
296: * if name is <code>null</code>.
297: */
298: public void removeAttribute(String name, int scope)
299: throws IllegalArgumentException {
300:
301: if (name == null) {
302: throw new IllegalArgumentException(
303: "The given attribute name is null");
304: }
305: _httpSession.removeAttribute(getEncodedAttrName(name, scope));
306: }
307:
308: /**
309: * Binds an object to this session under the <code>PORTLET_SCOPE</code>, using the name specified.
310: * If an object of the same name in this scope is already bound to the session,
311: * that object is replaced.
312: *
313: * <p>After this method has been executed, and if the new object
314: * implements <code>HttpSessionBindingListener</code>,
315: * the container calls
316: * <code>HttpSessionBindingListener.valueBound</code>. The container then
317: * notifies any <code>HttpSessionAttributeListeners</code> in the web
318: * application.
319: * <p>If an object was already bound to this session
320: * that implements <code>HttpSessionBindingListener</code>, its
321: * <code>HttpSessionBindingListener.valueUnbound</code> method is called.
322: *
323: * <p>If the value is <code>null</code>, this has the same effect as calling
324: * <code>removeAttribute()</code>.
325: *
326: *
327: * @param name the name to which the object is bound under
328: * the <code>PORTLET_SCOPE</code>;
329: * this cannot be <code>null</code>.
330: * @param value the object to be bound
331: *
332: * @exception java.lang.IllegalStateException if this method is called on a
333: * session which has been invalidated
334: * @exception java.lang.IllegalArgumentException
335: * if name is <code>null</code>.
336: */
337: public void setAttribute(String name, Object value)
338: throws IllegalArgumentException {
339:
340: if (name == null) {
341: throw new IllegalArgumentException(
342: "The given attribute name is null");
343: }
344: _httpSession.setAttribute(getEncodedAttrName(name,
345: PORTLET_SCOPE), value);
346: }
347:
348: /**
349: * Binds an object to this session in the given scope, using the name specified.
350: * If an object of the same name in this scope is already bound to the session,
351: * that object is replaced.
352: *
353: * <p>After this method has been executed, and if the new object
354: * implements <code>HttpSessionBindingListener</code>,
355: * the container calls
356: * <code>HttpSessionBindingListener.valueBound</code>. The container then
357: * notifies any <code>HttpSessionAttributeListeners</code> in the web
358: * application.
359: * <p>If an object was already bound to this session
360: * that implements <code>HttpSessionBindingListener</code>, its
361: * <code>HttpSessionBindingListener.valueUnbound</code> method is called.
362: *
363: * <p>If the value is <code>null</code>, this has the same effect as calling
364: * <code>removeAttribute()</code>.
365: *
366: *
367: * @param name the name to which the object is bound;
368: * this cannot be <code>null</code>.
369: * @param value the object to be bound
370: * @param scope session scope of this attribute
371: *
372: * @exception java.lang.IllegalStateException if this method is called on a
373: * session which has been invalidated
374: * @exception java.lang.IllegalArgumentException
375: * if name is <code>null</code>.
376: */
377: public void setAttribute(String name, Object value, int scope)
378: throws IllegalArgumentException {
379:
380: if (name == null) {
381: throw new IllegalArgumentException(
382: "The given attribute name is null");
383: }
384: _httpSession.setAttribute(getEncodedAttrName(name, scope),
385: value);
386: }
387:
388: /**
389: * Specifies the time, in seconds, between client requests, before the
390: * portlet container invalidates this session. A negative time
391: * indicates the session should never timeout.
392: *
393: * @param interval An integer specifying the number
394: * of seconds
395: */
396: public void setMaxInactiveInterval(int interval) {
397:
398: _httpSession.setMaxInactiveInterval(interval);
399: }
400:
401: /**
402: * Returns the portlet application context associated with this session.
403: *
404: * @return the portlet application context
405: */
406: public PortletContext getPortletContext() {
407:
408: return _portletContext;
409: }
410:
411: private String getEncodedAttrName(String name, int scope) {
412:
413: String encodedName = null;
414:
415: if (scope == APPLICATION_SCOPE) {
416: encodedName = name;
417: } else { // PORTLET_SCOPE
418: String portletID = EntityIDThreadLocal.getEntityID();
419: StringBuffer sb = new StringBuffer();
420: sb.append(PORTLET_SCOPE_ATTR_PREFIX);
421: sb.append(portletID);
422: sb.append("?");
423: sb.append(name);
424: encodedName = sb.toString();
425: }
426:
427: return encodedName;
428: }
429:
430: // Get <ATTRIBUTE_NAME> from the fabricated attribute name:
431: // "javax.portlet.w.<ID>?<ATTRIBUTE_NAME>". The assumption
432: // here is the encoding of fabricated attribute name hase been
433: // checked.
434: private String getDecodedAttrName(String attrName) {
435:
436: return attrName.substring(attrName.indexOf("?") + 1);
437: }
438:
439: // This method does the following two checkings:
440: // 1. Check if the encoded PORTLET_SCOPE attribute name is valid.
441: // The correct fabricated attributename shoule be like:
442: // "javax.portlet.w.<ID>?<ATTRIBUTE_NAME>" where <ID> is the
443: // unique identifier for the portlet window that must not
444: // contain a "?" chanrater.
445: // 2. Check if this PORTLET_SCOPE attribute belongs to the current
446: // target window. This can only be done if the attribute name
447: // in correct PORTLET_SCOPE name format.
448: private boolean isTargetPortletID(String name) {
449:
450: boolean valid = true;
451:
452: if (!name.startsWith(PORTLET_SCOPE_ATTR_PREFIX)
453: || (name.indexOf("?") != name.lastIndexOf("?"))) {
454: valid = false;
455: } else {
456: String targetPortletID = EntityIDThreadLocal.getEntityID();
457: String portletID = name.substring(
458: LENGTH_OF_PORTLET_SCOPE_ATTR_PREFIX, name
459: .indexOf("?"));
460: if (!portletID.equals(targetPortletID)) {
461: valid = false;
462: }
463: }
464: return valid;
465: }
466: }
|