/* * (C) Copyright 2006-2008 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Contributors: * bstefanescu * * $Id$ */ package org.nuxeo.ecm.webengine.session; import java.security.Principal; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuxeo.ecm.webengine.jaxrs.context.RequestCleanupHandler; import org.nuxeo.ecm.webengine.jaxrs.context.RequestContext; /** * Used to store user session. This object is cached in a the HTTP session Principal, subject and credentials are * immutable per user session * * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> */ // TODO: should be synchronized? concurrent access may happen for the same // session public final class UserSession extends HashMap<String, Object> { private static final long serialVersionUID = 260562970988817064L; protected static final Log log = LogFactory.getLog(UserSession.class); protected Map<Class<?>, ComponentMap<?>> comps = new HashMap<Class<?>, ComponentMap<?>>(); protected HttpServletRequest request; protected UserSession(HttpServletRequest request) { this.request = request; } public static UserSession getCurrentSession(HttpServletRequest request) { String key = UserSession.class.getName(); HttpSession session = request.getSession(false); UserSession us = null; if (session != null) { us = (UserSession) session.getAttribute(key); } if (us == null) { us = (UserSession) request.getAttribute(key); } if (us == null) { us = new UserSession(request); if (session != null) { session.setAttribute(key, us); } else { request.setAttribute(key, us); } } return us; } public Principal getPrincipal() { return request.getUserPrincipal(); } /** * Register a cleanup handler that will be invoked when HTTP request terminate. This method is not thread safe. */ public static void addRequestCleanupHandler(HttpServletRequest request, RequestCleanupHandler handler) { RequestContext.getActiveContext(request).addRequestCleanupHandler(handler); } /** * Finds an existing component. * <p> * The component state will not be modified before being returned as in {@link #getComponent(Class, String)}. * <p> * If the component was not found in that session, returns null. */ @SuppressWarnings("unchecked") public synchronized <T extends Component> T findComponent(Class<T> type, String name) { ComponentMap<T> map = (ComponentMap<T>) comps.get(type); if (map == null) { return null; } if (name == null) { return map.getComponent(); } else { return type.cast(map.get(name)); } } /** * Gets a component given its class and an optional name. * <p> * If the component was not yet created in this session, it will be created and registered against the session. */ @SuppressWarnings("unchecked") public synchronized <T extends Component> T getComponent(Class<T> type, String name) throws SessionException { ComponentMap<T> map = (ComponentMap<T>) comps.get(type); T comp; if (map == null) { map = new ComponentMap<T>(); comps.put(type, map); } else { if (name == null) { comp = map.getComponent(); } else { comp = type.cast(map.get(name)); } if (comp != null) { return comp; } } // component not found try { comp = type.newInstance(); } catch (ReflectiveOperationException e) { throw new SessionException("Failed to instantiate component: " + type, e); } comp.initialize(this, name); if (name == null) { map.setComponent(comp); } else { map.put(name, comp); } return type.cast(comp); } public <T extends Component> T getComponent(Class<T> type) throws SessionException { return getComponent(type, null); } @SuppressWarnings("unchecked") public <T extends Component> T getComponent(String typeName, String name) throws SessionException { try { Class<T> type = (Class<T>) Class.forName(typeName); return getComponent(type, name); } catch (ClassNotFoundException e) { throw new SessionException("Could not find component class: " + typeName, e); } } /** * Gets component by ID. * <p> * The ID is of the form <code>type#name</code> for non-null names and <code>type</code> for null names. */ @SuppressWarnings("unchecked") public <T extends Component> T getComponent(String id) throws SessionException { int p = id.lastIndexOf('#'); if (p > -1) { return (T) getComponent(id.substring(0, p), id.substring(p + 1)); } else { return (T) getComponent(id, null); } } }