001: /*
002: * (C) Copyright 2006 Nabh Information Systems, Inc.
003: *
004: * This program is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU General Public License
006: * as published by the Free Software Foundation; either version 2
007: * of the License, or (at your option) any later version.
008: *
009: * This program is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU General Public License for more details.
013: *
014: * You should have received a copy of the GNU General Public License
015: * along with this program; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
017: *
018: */
019: package com.nabhinc.portal.core;
020:
021: import java.io.IOException;
022: import java.rmi.RemoteException;
023: import java.util.Collections;
024: import java.util.HashMap;
025: import java.util.Hashtable;
026: import java.util.List;
027: import java.util.Map;
028:
029: import javax.portlet.PortletRequest;
030: import javax.portlet.PreferencesValidator;
031: import javax.servlet.ServletException;
032: import javax.servlet.http.HttpServletRequest;
033: import javax.servlet.http.HttpServletResponse;
034: import javax.servlet.http.HttpSessionBindingEvent;
035: import javax.servlet.http.HttpSessionBindingListener;
036:
037: import org.apache.commons.logging.Log;
038: import org.apache.commons.logging.LogFactory;
039:
040: import com.nabhinc.portal.api.OrphanException;
041: import com.nabhinc.portal.api.PortalInformationStoreLocator;
042: import com.nabhinc.portal.container.ActionRequestImpl;
043: import com.nabhinc.portal.container.ActionResponseImpl;
044: import com.nabhinc.portal.container.PortletPreferencesImpl;
045: import com.nabhinc.portal.container.RenderRequestImpl;
046: import com.nabhinc.portal.container.RenderResponseImpl;
047: import com.nabhinc.portal.model.PortalApplication;
048: import com.nabhinc.portal.model.PortalApplicationView;
049: import com.nabhinc.portal.model.PortalConfiguration;
050: import com.nabhinc.portal.model.PortletWindow;
051: import com.nabhinc.portal.model.UserPreferences;
052: import com.nabhinc.portal.spi.UserAdminServiceLocator;
053: import com.nabhinc.spi.EntityExistsException;
054: import com.nabhinc.spi.NoSuchEntityException;
055: import com.nabhinc.util.StringUtil;
056: import com.nabhinc.ws.core.WebServiceSecurityException;
057:
058: /**
059: *
060: *
061: * @author Padmanabh Dabke
062: * (c) 2006 Nabh Information Systems, Inc. All Rights Reserved.
063: */
064: public class SessionCache implements HttpSessionBindingListener {
065: private transient Log scLogger = LogFactory
066: .getLog(SessionCache.class);
067: public transient boolean isPopulated = false;
068: public transient ClientInfo clientInfo = null;
069: public transient UserPreferences userPrefs = null;
070: public transient Map userInfoMap = null;
071: public transient HashMap<String, PortalApplicationView> portalAppViewMap = new HashMap<String, PortalApplicationView>();
072: private transient HashMap<String, PortletPreferencesImpl> prefMap = new HashMap<String, PortletPreferencesImpl>();
073:
074: public transient RenderRequestImpl renderRequest = null;
075: public transient RenderResponseImpl renderResponse = null;
076: public transient ActionRequestImpl actionRequest = null;
077: public transient ActionResponseImpl actionResponse = null;
078:
079: public SessionCache() {
080: }
081:
082: public SessionCache(boolean populated) {
083: this .isPopulated = populated;
084: }
085:
086: public static SessionCache getSessionCache(
087: HttpServletRequest request, HttpServletResponse response)
088: throws RemoteException, ServletException {
089: SessionCache sCache = (SessionCache) request.getSession()
090: .getAttribute(PortalConstants.SESSION_CACHE_ATTRIBUTE);
091: if (sCache == null) {
092: sCache = new SessionCache();
093: int sessionTimeout = PortalConfiguration.getInstance()
094: .getSessionTimeout();
095: if (sessionTimeout != 0)
096: request.getSession().setMaxInactiveInterval(
097: sessionTimeout * 60);
098: populateSessionCache(sCache, request, response);
099: if (sCache.clientInfo.userName != null) {
100: SessionManager.interceptLogin(
101: sCache.clientInfo.sessionId, sCache.clientInfo,
102: LoginInterceptor.LOGIN_GRANTED);
103: }
104: } else {
105: if (!sCache.isPopulated)
106: populateSessionCache(sCache, request, response);
107: }
108: if (sCache.userInfoMap != null)
109: request.setAttribute(PortletRequest.USER_INFO,
110: sCache.userInfoMap);
111: request.setAttribute(PortalConstants.PORTLET_REQUEST_ATTRIB,
112: sCache.renderRequest);
113: request.setAttribute(PortalConstants.PORTLET_RESPONSE_ATTRIB,
114: sCache.renderResponse);
115: request.setAttribute(PortalConstants.REMOTE_ADDR_ATTRIBUTE,
116: request.getRemoteAddr());
117: request.setAttribute(PortalConstants.REMOTE_HOST_ATTRIBUTE,
118: request.getRemoteHost());
119:
120: return sCache;
121: }
122:
123: private static void populateSessionCache(SessionCache sCache,
124: HttpServletRequest request, HttpServletResponse response)
125: throws RemoteException, ServletException {
126: sCache.isPopulated = true;
127: String userName = request.getRemoteUser();
128: if (userName != null) {
129: sCache.userPrefs = PortalInformationStoreLocator
130: .getPortalInformationStore().getUserPreferences(
131: userName);
132: sCache.setUserInfo(userName);
133: }
134: sCache.clientInfo = ClientInfo.createClientInfo(request,
135: sCache.userPrefs);
136: sCache.createRequestResponseObjects(request, response);
137: request.getSession().setAttribute(
138: PortalConstants.SESSION_CACHE_ATTRIBUTE, sCache);
139: SessionManager.insertSession(request, request.getSession(),
140: userName);
141: }
142:
143: protected PortalApplicationView getCachedPortalApplicationView(
144: String appPath) {
145: return this .portalAppViewMap.get(appPath);
146: }
147:
148: protected PortalApplicationView getPortalApplicationView(
149: String appPath, HttpServletRequest request,
150: HttpServletResponse response, boolean isAJAXRequest,
151: boolean isTopLevel) throws IOException, ServletException,
152: WebServiceSecurityException {
153: PortalApplicationView paView = this .portalAppViewMap
154: .get(appPath);
155: if (paView == null || paView.getPortalApplication().isStale()) {
156:
157: PortalApplication portalApp = PortalApplicationCache
158: .getInstance().getPortalApplication(appPath,
159: request);
160:
161: if (portalApp == null) {
162: if (isTopLevel)
163: portalApp = handleMissingPortalApplication(appPath,
164: request, response, isAJAXRequest);
165: if (portalApp == null)
166: return null;
167: }
168:
169: paView = portalApp.getPortalApplicationView(request,
170: this .clientInfo);
171: this .portalAppViewMap.put(appPath, paView);
172: }
173: return paView;
174:
175: }
176:
177: private void createRequestResponseObjects(HttpServletRequest req,
178: HttpServletResponse resp) {
179: this .renderRequest = new RenderRequestImpl(req, PortalServlet
180: .getInstance().getPortletContext(), PortalServlet
181: .getInstance().getPortalContext(),
182: this .clientInfo.currentLocales,
183: this .clientInfo.mimeType);
184:
185: this .renderResponse = new RenderResponseImpl(req, resp,
186: this .clientInfo.mimeType);
187: this .actionRequest = new ActionRequestImpl(req, PortalServlet
188: .getInstance().getPortletContext(), PortalServlet
189: .getInstance().getPortalContext(),
190: this .clientInfo.currentLocales,
191: this .clientInfo.mimeType);
192: this .actionResponse = new ActionResponseImpl(resp,
193: this .actionRequest);
194: }
195:
196: @SuppressWarnings("unchecked")
197: public void setUserInfo(String userName)
198: throws javax.servlet.ServletException {
199:
200: Map userInfo;
201: try {
202: userInfo = UserAdminServiceLocator.getUserAdminService()
203: .getUserInfo(userName);
204: } catch (RemoteException e) {
205: throw new ServletException(
206: "Communication exception in retrieving user info.",
207: e);
208: } catch (NoSuchEntityException e) {
209: throw new ServletException("User not found.", e);
210: }
211: this .userInfoMap = Collections.unmodifiableMap(userInfo);
212:
213: }
214:
215: protected void setRequestResponseObjects(
216: HttpServletRequest request, HttpServletResponse response) {
217: this .renderRequest.setHttpServletRequest(request);
218: this .renderResponse.setHttpServletResponse(response);
219: this .renderResponse.setServletRequest(request);
220: }
221:
222: private PortalApplication handleMissingPortalApplication(
223: String appPath, HttpServletRequest request,
224: HttpServletResponse response, boolean isAJAXRequest)
225: throws ServletException, IOException,
226: WebServiceSecurityException {
227: String requestType = null;
228: String userName = request.getRemoteUser();
229: if (userName == null) {
230: // response.setStatus(HttpServletResponse.SC_NOT_FOUND);
231: response.sendError(HttpServletResponse.SC_NOT_FOUND);
232: return null;
233: }
234: if (("/my/" + userName).equals(appPath)) {
235: try {
236: PortalInformationStoreLocator
237: .getPortalInformationStore()
238: .createPortalApplication(appPath, null);
239: return PortalApplicationCache.getInstance()
240: .getPortalApplication(appPath, request);
241: } catch (EntityExistsException e) {
242: // This should never happen
243: this .scLogger
244: .error(
245: "Psite under /my seems to exist even after checking it beforehand",
246: e);
247: } catch (OrphanException e) {
248: this .scLogger.error(
249: "Got OrphanException in creating a /my psite!",
250: e);
251: }
252: }
253: String parentPath = StringUtil.extractParentPath(appPath);
254: PortalApplicationView parentView = getPortalApplicationView(
255: parentPath, request, response, isAJAXRequest, false);
256: if (parentView == null) {
257: requestType = PortalConstants.REQUEST_TYPE_CREATE_PARENT;
258: } else {
259:
260: if (request.getRemoteUser() == null
261: && parentView.getPortalApplication()
262: .requiresLoginForAdmin()) {
263: requestType = PortalConstants.REQUEST_TYPE_LOG_IN;
264: } else {
265: if (parentView.isPsiteCreatable) {
266: requestType = PortalConstants.REQUEST_TYPE_CREATE_PSITE;
267: } else {
268: // response.setStatus(HttpServletResponse.SC_NOT_FOUND);
269: response
270: .sendError(HttpServletResponse.SC_NOT_FOUND);
271: return null;
272: }
273: }
274:
275: }
276: PortalApplicationView createAppView = getPortalApplicationView(
277: parentPath + "/create_psite", request, response,
278: isAJAXRequest, false);
279: if (createAppView == null)
280: createAppView = getPortalApplicationView("/create_psite",
281: request, response, isAJAXRequest, false);
282: String url = createAppView.getPageStates()[0].getPageURL()
283: + PortalConstants.PORTAL_ACTION_RENDER_DEFAULT + "?"
284: + PortalConstants.PAGE_PATH_PARAM + "=" + appPath
285: + "&request_type=" + requestType;
286: PortalUtil.redirectRequest(url, response, isAJAXRequest);
287: return null;
288: }
289:
290: public void valueBound(HttpSessionBindingEvent arg0) {
291: // Nothing to do here
292:
293: }
294:
295: public void valueUnbound(HttpSessionBindingEvent event) {
296: if (PortalConstants.SESSION_CACHE_ATTRIBUTE.equals(event
297: .getName())) {
298: SessionManager.removeSession(this .clientInfo.sessionId);
299: if (this .clientInfo.userName != null) {
300: try {
301: SessionManager.interceptLogin(
302: this .clientInfo.sessionId, this .clientInfo,
303: this .clientInfo.logoutType);
304: } catch (ServletException e) {
305: // Log and ignore
306: this .scLogger.error("Failed log logout event", e);
307: }
308: }
309: }
310:
311: }
312:
313: public PortletPreferencesImpl getPortletPreferences(
314: PortletWindow pWindow) {
315: PortletPreferencesImpl prefs = this .prefMap
316: .get(pWindow.getId());
317: if (prefs != null)
318: return prefs;
319: Hashtable<String, PortletPreferencesImpl.PrefInfo> origPrefs = pWindow
320: .getPortletConfigInfo().configuredPrefs;
321: PreferencesValidator val = pWindow.getPortletConfigInfo().prefValidator;
322: Hashtable<String, PortletPreferencesImpl.PrefInfo> userPrefs = null;
323: if (this .userPrefs != null) {
324: userPrefs = new Hashtable<String, PortletPreferencesImpl.PrefInfo>();
325: UserPreferences.PortletPreference pref = this .userPrefs
326: .getPortletPreference(pWindow.getId());
327: if (pref != null) {
328: List<UserPreferences.PortletPreferenceEntry> entryList = pref.prefList;
329: for (int i = 0; i < entryList.size(); i++) {
330: UserPreferences.PortletPreferenceEntry entry = entryList
331: .get(i);
332: userPrefs.put(entry.name,
333: new PortletPreferencesImpl.PrefInfo(
334: entry.name, true, entry.values));
335: }
336: }
337: }
338: prefs = new PortletPreferencesImpl(origPrefs, userPrefs,
339: pWindow, val, this.renderRequest);
340: this.prefMap.put(pWindow.getId(), prefs);
341: return prefs;
342: }
343:
344: }
|