/*
* Copyright (C) 2003-2007 eXo Platform SAS.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see<http://www.gnu.org/licenses/>.
*/
package org.etk.core.security.web;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.etk.common.logging.Logger;
import org.etk.core.security.ConversationRegistry;
import org.etk.core.security.ConversationState;
import org.etk.core.security.Identity;
import org.etk.core.security.IdentityRegistry;
import org.etk.core.security.StateKey;
import org.etk.kernel.container.KernelContainer;
import org.etk.kernel.container.KernelContainerContext;
/**
* Created by The eXo Platform SAS .
*
* @author <a href="mailto:gennady.azarenkov@exoplatform.com">Gennady
* Azarenkov</a>
* @version $Id: SimpleSessionFactoryInitializedFilter.java 7163 2006-07-19
* 07:30:39Z peterit $
*/
public class SetCurrentIdentityFilter implements Filter {
/**
* Under this name can be set portal container name, as filter
* <tt>init-param</tt> or application <tt>context-param</tt>. If both of
* parameters not set then application context-name used as container name.
*/
public static final String PORTAL_CONTAINER_NAME = "portalContainerName";
/**
* Logger.
*/
private static Logger log = Logger.getLogger(SetCurrentIdentityFilter.class);
/**
* Portal Container name.
*/
private String portalContainerName;
/**
* {@inheritDoc}
*/
public void init(FilterConfig config) throws ServletException {
// It is not possible to use application context name everywhere cause to
// problem with access to resources (CSS). Try to find container name in
// filter 'init-param' or in application 'context-param'. And only if both
// of
// parameters are not specified then use application context name.
// Check filter init-param first
portalContainerName = config.getInitParameter(PORTAL_CONTAINER_NAME);
// check application context-param
if (portalContainerName == null)
portalContainerName = config.getServletContext().getInitParameter(PORTAL_CONTAINER_NAME);
// if nothing set then use application context name, 'display-name' in
// web.xml
if (portalContainerName == null)
portalContainerName = config.getServletContext().getServletContextName();
// save container name as attribute
config.getServletContext().setAttribute(PORTAL_CONTAINER_NAME, portalContainerName);
}
/**
* Set current {@link ConversationState}, if it is not registered yet then
* create new one and register in {@link ConversationRegistry}. {@inheritDoc}
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
KernelContainer container = KernelContainerContext.getContainerByName(portalContainerName);
if (container == null) {
if (log.isDebugEnabled()) {
log.debug("Container " + portalContainerName + " not found.");
}
container = KernelContainerContext.getTopContainer();
}
try {
KernelContainerContext.setCurrentContainer(container);
ConversationState state = getCurrentState(container, httpRequest);
// NOTE may be set as null
ConversationState.setCurrent(state);
if (state != null && log.isDebugEnabled())
log.debug(">>> Memberships " + state.getIdentity().getMemberships());
chain.doFilter(request, response);
} finally {
try {
ConversationState.setCurrent(null);
} catch (Exception e) {
log.warn("An error occured while cleaning the ThreadLocal", e);
}
try {
KernelContainerContext.setCurrentContainer(null);
} catch (Exception e) {
log.warn("An error occured while cleaning the ThreadLocal", e);
}
}
}
/**
* Gives the current state
*/
private ConversationState getCurrentState(KernelContainer container, HttpServletRequest httpRequest) {
ConversationRegistry conversationRegistry = (ConversationRegistry) container.getComponentInstanceOfType(ConversationRegistry.class);
IdentityRegistry identityRegistry = (IdentityRegistry) container.getComponentInstanceOfType(IdentityRegistry.class);
ConversationState state = null;
String userId = httpRequest.getRemoteUser();
// only if user authenticated, otherwise there is no reason to do anythings
if (userId != null) {
HttpSession httpSession = httpRequest.getSession();
StateKey stateKey = new HttpSessionStateKey(httpSession);
if (log.isDebugEnabled()) {
log.debug("Looking for Conversation State " + httpSession.getId());
}
state = conversationRegistry.getState(stateKey);
if (state == null) {
if (log.isDebugEnabled()) {
log.debug("Conversation State not found, try create new one.");
}
Identity identity = identityRegistry.getIdentity(userId);
if (identity != null) {
state = new ConversationState(identity);
// keep subject as attribute in ConversationState
state.setAttribute(ConversationState.SUBJECT, identity.getSubject());
} else
log.error("Not found identity in IdentityRegistry for user " + userId
+ ", check Login Module.");
if (state != null) {
conversationRegistry.register(stateKey, state);
if (log.isDebugEnabled()) {
log.debug("Register Conversation state " + httpSession.getId());
}
}
}
}
return state;
}
/**
* {@inheritDoc}
*/
public void destroy() {
// nothing to do.
}
}