Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. */ package bugs; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.List; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionBindingEvent; import javax.servlet.http.HttpSessionBindingListener; import org.apache.wicket.Application; import org.apache.wicket.Session; import org.apache.wicket.markup.MarkupParser; import org.apache.wicket.protocol.http.IRequestLogger; import org.apache.wicket.protocol.http.WebApplication; import org.apache.wicket.request.Request; import org.apache.wicket.request.http.WebRequest; import org.apache.wicket.session.ISessionStore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Implementation of {@link ISessionStore} that works with web applications and * provides some specific http servlet/ session related functionality. * * @author jcompagner * @author Eelco Hillenius * @author Matej Knopp */ public class HttpSessionStoreModified implements ISessionStore { /** log. */ private static final Logger log = LoggerFactory.getLogger(HttpSessionStoreModified.class); /** */ private final Set<UnboundListener> unboundListeners = new CopyOnWriteArraySet<UnboundListener>(); private final Set<BindListener> bindListeners = new CopyOnWriteArraySet<BindListener>(); /** * Construct. */ public HttpSessionStoreModified() { } /** * @param request * @return The http servlet request */ protected final HttpServletRequest getHttpServletRequest(final Request request) { Object containerRequest = request.getContainerRequest(); if (containerRequest == null || (containerRequest instanceof HttpServletRequest) == false) { throw new IllegalArgumentException("Request must be ServletWebRequest"); } return (HttpServletRequest) containerRequest; } /** * @see HttpServletRequest#getSession(boolean) * @param request * A Wicket request object * @param create * If true, a session will be created if it is not existing yet * @return The HttpSession associated with this request or null if * {@code create} is false and the {@code request} has no valid * session */ final HttpSession getHttpSession(final Request request, final boolean create) { return getHttpServletRequest(request).getSession(create); } /** * @see org.apache.wicket.session.ISessionStore#bind(Request, Session) */ @Override public final void bind(final Request request, final Session newSession) { if (getAttribute(request, Session.SESSION_ATTRIBUTE_NAME) != newSession) { // call template method onBind(request, newSession); for (BindListener listener : getBindListeners()) { listener.bindingSession(request, newSession); } HttpSession httpSession = getHttpSession(request, false); if (httpSession != null) { // register an unbinding listener for cleaning up String applicationKey = Application.get().getName(); httpSession.setAttribute("Wicket:SessionUnbindingListener-" + applicationKey, new SessionBindingListener(applicationKey, newSession)); // register the session object itself setAttribute(request, Session.SESSION_ATTRIBUTE_NAME, newSession); } } } @Override public void flushSession(Request request, Session session) { if (getAttribute(request, Session.SESSION_ATTRIBUTE_NAME) != session) { // this session is not yet bound, bind it bind(request, session); } else { setAttribute(request, Session.SESSION_ATTRIBUTE_NAME, session); } } /** * @see org.apache.wicket.session.ISessionStore#destroy() */ @Override public void destroy() { } /** * @see org.apache.wicket.session.ISessionStore#getSessionId(org.apache.wicket.request.Request, * boolean) */ @Override public String getSessionId(final Request request, final boolean create) { String id = null; HttpSession httpSession = getHttpSession(request, false); if (httpSession != null) { id = httpSession.getId(); } else if (create) { httpSession = getHttpSession(request, true); id = httpSession.getId(); IRequestLogger logger = Application.get().getRequestLogger(); if (logger != null) { logger.sessionCreated(id); } } return id; } /** * @see org.apache.wicket.session.ISessionStore#invalidate(Request) */ @Override public final void invalidate(final Request request) { HttpSession httpSession = getHttpSession(request, false); if (httpSession != null) { // tell the app server the session is no longer valid httpSession.invalidate(); } } /** * @see org.apache.wicket.session.ISessionStore#lookup(org.apache.wicket.request.Request) */ @Override public final Session lookup(final Request request) { String sessionId = getSessionId(request, false); if (sessionId != null) { return (Session) getAttribute(request, Session.SESSION_ATTRIBUTE_NAME); } return null; } /** * Template method that is called when a session is being bound to the * session store. It is called <strong>before</strong> the session object * itself is added to this store (which is done by calling * {@link ISessionStore#setAttribute(Request, String, Serializable)} with * key {@link Session#SESSION_ATTRIBUTE_NAME}. * * @param request * The request * @param newSession * The new session */ protected void onBind(final Request request, final Session newSession) { } /** * Template method that is called when the session is being detached from * the store, which typically happens when the {@link HttpSession} was * invalidated. * * @param sessionId * The session id of the session that was invalidated. */ protected void onUnbind(final String sessionId) { } /** * Gets the prefix for storing variables in the actual session (typically * {@link HttpSession}) for this application instance. * * @param request * the request * @return the prefix for storing variables in the actual session */ private String getSessionAttributePrefix(final Request request) { String sessionAttributePrefix = MarkupParser.WICKET; if (request instanceof WebRequest) { sessionAttributePrefix = WebApplication.get().getSessionAttributePrefix((WebRequest) request, null); } return sessionAttributePrefix; } /** * @see org.apache.wicket.session.ISessionStore#getAttribute(org.apache.wicket.request.Request, * java.lang.String) */ @Override public final Serializable getAttribute(final Request request, final String name) { HttpSession httpSession = getHttpSession(request, false); if (httpSession != null) { return getValueInternal(getSessionAttributePrefix(request) + name, httpSession); } return null; } protected Serializable getValueInternal(final String attributeName, HttpSession httpSession) { return (Serializable) httpSession.getAttribute(attributeName); } /** * @see org.apache.wicket.session.ISessionStore#getAttributeNames(org.apache.wicket.request.Request) */ @Override public final List<String> getAttributeNames(final Request request) { List<String> list = new ArrayList<String>(); HttpSession httpSession = getHttpSession(request, false); if (httpSession != null) { @SuppressWarnings("unchecked") final Enumeration<String> names = httpSession.getAttributeNames(); final String prefix = getSessionAttributePrefix(request); while (names.hasMoreElements()) { final String name = names.nextElement(); if (name.startsWith(prefix)) { list.add(name.substring(prefix.length())); } } } return list; } /** * @see org.apache.wicket.session.ISessionStore#removeAttribute(org.apache.wicket.request.Request, * java.lang.String) */ @Override public final void removeAttribute(final Request request, final String name) { HttpSession httpSession = getHttpSession(request, false); if (httpSession != null) { String attributeName = getSessionAttributePrefix(request) + name; IRequestLogger logger = Application.get().getRequestLogger(); if (logger != null) { Object value = httpSession.getAttribute(attributeName); if (value != null) { logger.objectRemoved(value); } } httpSession.removeAttribute(attributeName); } } /** * @see org.apache.wicket.session.ISessionStore#setAttribute(org.apache.wicket.request.Request, * java.lang.String, java.io.Serializable) */ @Override public final void setAttribute(final Request request, final String name, final Serializable value) { // ignore call if the session was marked invalid HttpSession httpSession = getHttpSession(request, false); if (httpSession != null) { String attributeName = getSessionAttributePrefix(request) + name; IRequestLogger logger = Application.get().getRequestLogger(); if (logger != null) { if (httpSession.getAttribute(attributeName) == null) { logger.objectCreated(value); } else { logger.objectUpdated(value); } } setValueInternal(httpSession, value, attributeName); } } protected void setValueInternal(HttpSession httpSession, final Serializable value, String attributeName) { httpSession.setAttribute(attributeName, value); } /** * @see org.apache.wicket.session.ISessionStore#registerUnboundListener(org.apache.wicket.session.ISessionStore.UnboundListener) */ @Override public final void registerUnboundListener(final UnboundListener listener) { unboundListeners.add(listener); } /** * @see org.apache.wicket.session.ISessionStore#unregisterUnboundListener(org.apache.wicket.session.ISessionStore.UnboundListener) */ @Override public final void unregisterUnboundListener(final UnboundListener listener) { unboundListeners.remove(listener); } /** * @see org.apache.wicket.session.ISessionStore#getUnboundListener() */ @Override public final Set<UnboundListener> getUnboundListener() { return Collections.unmodifiableSet(unboundListeners); } /** * Registers listener invoked when session is bound. * * @param listener */ @Override public void registerBindListener(BindListener listener) { bindListeners.add(listener); } /** * Unregisters listener invoked when session is bound. * * @param listener */ @Override public void unregisterBindListener(BindListener listener) { bindListeners.remove(listener); } /** * @return The list of registered bind listeners */ @Override public Set<BindListener> getBindListeners() { return Collections.unmodifiableSet(bindListeners); } /** * Reacts on unbinding from the session by cleaning up the session related * data. */ protected static final class SessionBindingListener implements HttpSessionBindingListener, Serializable { private static final long serialVersionUID = 1L; /** The unique key of the application within this web application. */ private final String applicationKey; /** * The Wicket Session associated with the expiring HttpSession */ private final Session wicketSession; /** * Constructor. * * @param applicationKey * The unique key of the application within this web * application * @deprecated Use #SessionBindingListener(String, Session) instead */ @Deprecated public SessionBindingListener(final String applicationKey) { this(applicationKey, Session.get()); } /** * Construct. * * @param applicationKey * The unique key of the application within this web * application * @param wicketSession * The Wicket Session associated with the expiring http * session */ public SessionBindingListener(final String applicationKey, final Session wicketSession) { this.applicationKey = applicationKey; this.wicketSession = wicketSession; } /** * @see javax.servlet.http.HttpSessionBindingListener#valueBound(javax.servlet.http.HttpSessionBindingEvent) */ @Override public void valueBound(final HttpSessionBindingEvent evg) { } /** * @see javax.servlet.http.HttpSessionBindingListener#valueUnbound(javax.servlet.http.HttpSessionBindingEvent) */ @Override public void valueUnbound(final HttpSessionBindingEvent evt) { String sessionId = evt.getSession().getId(); log.debug("Session unbound: {}", sessionId); if (wicketSession != null) { wicketSession.onInvalidate(); } Application application = Application.get(applicationKey); if (application == null) { log.debug("Wicket application with name '{}' not found.", applicationKey); return; } ISessionStore sessionStore = application.getSessionStore(); if (sessionStore != null) { if (sessionStore instanceof HttpSessionStoreModified) { ((HttpSessionStoreModified) sessionStore).onUnbind(sessionId); } for (UnboundListener listener : sessionStore.getUnboundListener()) { listener.sessionUnbound(sessionId); } } } } }