001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.wicket.protocol.http.servlet; 018 019import java.io.IOException; 020 021import javax.servlet.Filter; 022import javax.servlet.FilterChain; 023import javax.servlet.FilterConfig; 024import javax.servlet.ServletException; 025import javax.servlet.ServletRequest; 026import javax.servlet.ServletResponse; 027import javax.servlet.http.HttpServletRequest; 028import javax.servlet.http.HttpSession; 029 030import org.apache.wicket.Application; 031import org.apache.wicket.Session; 032import org.apache.wicket.ThreadContext; 033import org.apache.wicket.protocol.http.WebApplication; 034import org.apache.wicket.protocol.http.WicketFilter; 035import org.slf4j.Logger; 036import org.slf4j.LoggerFactory; 037 038/** 039 * This filter can be used to make the Wicket {@link org.apache.wicket.protocol.http.WebSession} 040 * instances available to non-wicket servlets. 041 * <p> 042 * The following example shows how this filter is setup to for a servlet. You can find the example 043 * in the wicket-examples project. 044 * 045 * <pre> 046 * <!-- The WicketSesionFilter can be used to provide thread local access to servlets/ JSPs/ etc --> 047 * <filter> 048 * <filter-name>WicketSessionFilter</filter-name> 049 * <filter-class>org.apache.wicket.protocol.http.servlet.WicketSessionFilter</filter-class> 050 * <init-param> 051 * <param-name>filterName</param-name> 052 * <!-- expose the session of the input example app --> 053 * <param-value>FormInputApplication</param-value> 054 * </init-param> 055 * </filter> 056 * 057 * <!-- couple the session filter to the helloworld servlet --> 058 * <filter-mapping> 059 * <filter-name>WicketSessionFilter</filter-name> 060 * <url-pattern>/helloworldservlet/*</url-pattern> 061 * </filter-mapping> 062 * ... 063 * 064 * <servlet> 065 * <servlet-name>HelloWorldServlet</servlet-name> 066 * <servlet-class>org.apache.wicket.examples.HelloWorldServlet</servlet-class> 067 * </servlet> 068 * 069 * <servlet-mapping> 070 * <servlet-name>HelloWorldServlet</servlet-name> 071 * <url-pattern>/helloworldservlet/*</url-pattern> 072 * </servlet-mapping> 073 * </pre> 074 * 075 * Note: If both {@link WicketFilter} and {@link WicketSessionFilter} are mapped to the same url 076 * pattern, make sure to have the {@code <filter-mapping>} for {@link WicketFilter} first in your 077 * {@code web.xml}. 078 * <p> 079 * After that, you can get to the Wicket session in the usual fashion: 080 * 081 * <pre> 082 * if (Session.exists()) 083 * { 084 * Session wicketSession = Session.get(); 085 * } 086 * </pre> 087 * 088 * Make sure to test for session existence first, like the HelloWorldServlet does: 089 * 090 * <pre> 091 * public class HelloWorldServlet extends HttpServlet 092 * { 093 * public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, 094 * IOException 095 * { 096 * res.setContentType("text/html"); 097 * PrintWriter out = res.getWriter(); 098 * String message = "Hi. " + 099 * (Session.exists() ? " I know Wicket session " + Session.get() + "." 100 * : " I can't find a Wicket session."); 101 * out.println(message); 102 * out.close(); 103 * } 104 * } 105 * </pre> 106 * 107 * @author Eelco Hillenius 108 */ 109public class WicketSessionFilter implements Filter 110{ 111 /** log. */ 112 private static final Logger logger = LoggerFactory.getLogger(WicketSessionFilter.class); 113 114 /** the filter name/ application key. */ 115 private String filterName; 116 117 /** the session key where the Wicket session should be stored. */ 118 private String sessionKey; 119 120 /** 121 * Construct. 122 */ 123 public WicketSessionFilter() 124 { 125 } 126 127 /** 128 * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) 129 */ 130 @Override 131 public void init(FilterConfig filterConfig) throws ServletException 132 { 133 filterName = filterConfig.getInitParameter("filterName"); 134 135 if (filterName == null) 136 { 137 throw new ServletException( 138 "you must provide init parameter 'filterName if you want to use " + 139 getClass().getName()); 140 } 141 142 logger.debug("filterName/application key set to {}", filterName); 143 } 144 145 /** 146 * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, 147 * javax.servlet.ServletResponse, javax.servlet.FilterChain) 148 */ 149 @Override 150 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 151 throws IOException, ServletException 152 { 153 try 154 { 155 WebApplication application = bindApplication(); 156 bindSession(request, application); 157 chain.doFilter(request, response); 158 } 159 finally 160 { 161 cleanupBoundApplicationAndSession(); 162 } 163 } 164 165 private void cleanupBoundApplicationAndSession() 166 { 167 ThreadContext.detach(); 168 } 169 170 private void bindSession(ServletRequest request, WebApplication application) 171 { 172 // find wicket session and bind it to thread 173 174 HttpSession httpSession = ((HttpServletRequest)request).getSession(false); 175 Session session = getSession(httpSession, application); 176 if (session == null) 177 { 178 if (logger.isDebugEnabled()) 179 { 180 logger.debug("could not set Wicket session: key " + sessionKey + 181 " not found in http session for " + 182 ((HttpServletRequest)request).getContextPath() + "," + request.getServerName() + 183 ", or http session does not exist"); 184 } 185 } 186 else 187 { 188 ThreadContext.setSession(session); 189 } 190 } 191 192 private WebApplication bindApplication() 193 { 194 // find wicket application and bind it to thread 195 196 WebApplication application = (WebApplication)Application.get(filterName); 197 if (application == null) 198 { 199 throw new IllegalStateException("Could not find wicket application mapped to filter: " + 200 filterName + 201 ". Make sure you set filterName attribute to the name of the wicket filter " + 202 "for the wicket application whose session you want to access."); 203 } 204 ThreadContext.setApplication(application); 205 return application; 206 } 207 208 private Session getSession(HttpSession session, WebApplication application) 209 { 210 if (session != null) 211 { 212 if (sessionKey == null) 213 { 214 sessionKey = application.getSessionAttributePrefix(null, filterName) + 215 Session.SESSION_ATTRIBUTE_NAME; 216 217 logger.debug("will use {} as the session key to get the Wicket session", sessionKey); 218 } 219 220 return (Session)session.getAttribute(sessionKey); 221 } 222 return null; 223 } 224 225 /** 226 * @see javax.servlet.Filter#destroy() 227 */ 228 @Override 229 public void destroy() 230 { 231 } 232}