Java tutorial
/*- * Copyright 2011 TAKEUCHI Hideyuki (chimerast) * * 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. */ package org.seasar.wicket; import java.io.IOException; import java.net.URL; import java.util.Enumeration; 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.apache.wicket.Application; import org.apache.wicket.RuntimeConfigurationType; import org.apache.wicket.application.ReloadingClassLoader; import org.apache.wicket.protocol.http.ReloadingWicketFilter; import org.apache.wicket.protocol.http.WebApplication; import org.seasar.framework.container.ExternalContext; import org.seasar.framework.container.S2Container; import org.seasar.framework.container.deployer.ComponentDeployerFactory; import org.seasar.framework.container.deployer.ExternalComponentDeployerProvider; import org.seasar.framework.container.external.servlet.HttpServletExternalContext; import org.seasar.framework.container.external.servlet.HttpServletExternalContextComponentDefRegister; import org.seasar.framework.container.factory.S2ContainerFactory; import org.seasar.framework.container.factory.SingletonS2ContainerFactory; import org.seasar.framework.container.filter.S2ContainerFilter; import org.seasar.framework.container.util.SmartDeployUtil; import org.seasar.framework.exception.EmptyRuntimeException; import org.seasar.wicket.debug.S2DebugPage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * S2Container????WicketFilter * <p> * web.xml???????Wicket??S2Container?????????? * WicketFilter??S2ContainerFilter?????????? * </p> * <p> * Wicket?<b>development????</b>?????? * </p> * <dl> * <dt>?(HotDeploy)</dt> * <dd>web.xml???reloadingClassPattern????????</dd> * <dt>?</dt> * <dd>????????? * ?????????????</dd> * </dl> * <h4>?</h4> * <dl> * <dt>applicationClassName</dt> * <dd>Wicket?WebApplication????</dd> * <dt>configuration</dt> * <dd>Wicket?deployment??????development????? * ?????development()????</dd> * <dt>debug</dt> * <dd>S2Container??????</dd> * <dt>reloadingClassPattern</dt> * <dd>Wicket??development??????? * ?????????????","??? * ??"*"??????????"-"?????? * ???????????convention.dicon???rootPackageName???</dd> * <dl> * <h4>web.xml</h4> * * <pre> * <filter> * <filter-name>s2wicketfilter</filter-name> * <filter-class>org.seasar.wicket.S2WicketFilter</filter-class> * <init-param> * <!-- Wicket? --> * <param-name>applicationClassName</param-name> * <param-value>org.seasar.wicket.example.ExampleApplication</param-value> * </init-param> * <init-param> * <!-- Wicket???development --> * <!-- development????? --> * <param-name>configuration</param-name> * <param-value>deployment</param-value> * </init-param> * <init-param> * <!-- S2Container??? --> * <param-name>debug</param-name> * <param-value>/debug</param-value> * </init-param> * <init-param> * <!-- ???development?? --> * <param-name>reloadingClassPattern</param-name> * <param-value>org.seasar.wicket.example.*</param-value> * </init-param> * </filter> * <filter-mapping> * <filter-name>s2wicketfilter</filter-name> * <url-pattern>/*</url-pattern> * </filter-mapping> * </pre> * * @author TAKEUCHI Hideyuki (chimerast) */ public class S2WicketFilter extends ReloadingWicketFilter { protected final Logger logger = LoggerFactory.getLogger(getClass()); // ? private static final String SESSION_LOADER = "s2wicket$loader"; /** Wicket? */ private String configuration; /** S2Container??dicon?(: app.dicon) */ private String configPath; /** S2Container??URL */ private String debug; /** Hot Deploy ??(Wicket?Matcher??) */ private String reloadingClassPattern; /** ReloadingClassLoader????? */ private boolean useReloadingClassLoader; /** ?(DEPLOYMENT, DEVELOPMENT) */ private RuntimeConfigurationType applicationConfigType; /** ? */ private String applicationEncoding; @Override public void init(final boolean isServlet, FilterConfig filterConfig) throws ServletException { try { initInternal(isServlet, filterConfig); } catch (RuntimeException e) { logger.error("[init] error on initializing filter.", e); throw e; } catch (Error e) { logger.error("[init] error on initializing filter.", e); throw e; } catch (ServletException e) { logger.error("[init] error on initializing filter.", e); throw e; } } private void initInternal(final boolean isServlet, FilterConfig filterConfig) throws ServletException { // ???????????? destroy(); // ??? configuration = getInitParameter(filterConfig, "configuration", "development").toUpperCase(); configPath = getInitParameter(filterConfig, "configPath", "app.dicon"); debug = getInitParameter(filterConfig, "debug", null); reloadingClassPattern = getInitParameter(filterConfig, "reloadingClassPattern", null); useReloadingClassLoader = RuntimeConfigurationType.DEVELOPMENT.name().equalsIgnoreCase(configuration) && reloadingClassPattern != null; if (logger.isInfoEnabled()) { logger.info("[config] configuration='{}'", configuration); logger.info("[config] configPath='{}'", configPath); logger.info("[config] debug='{}'", debug); logger.info("[config] reloadingClassPattern='{}'", reloadingClassPattern); } if (RuntimeConfigurationType.DEVELOPMENT == RuntimeConfigurationType.valueOf(configuration) && reloadingClassPattern != null) { ReloadingClassLoader.getPatterns().clear(); // ?????????? // ??????????? for (String classPattern : reloadingClassPattern.split(",")) { if (!classPattern.startsWith("-")) { ReloadingClassLoader.includePattern(classPattern); } else { ReloadingClassLoader.excludePattern(classPattern.substring(1)); } } for (URL str : ReloadingClassLoader.getLocations()) { logger.info("[classpath] {}", str); } for (String str : ReloadingClassLoader.getPatterns()) { logger.info("[pattern] {}", str); } } ComponentDeployerFactory.setProvider(new ExternalComponentDeployerProvider()); S2Container s2container = S2ContainerFactory.create(configPath, getClassLoader()); s2container.setExternalContext(new HttpServletExternalContext()); s2container.setExternalContextComponentDefRegister(new HttpServletExternalContextComponentDefRegister()); s2container.getExternalContext().setApplication(filterConfig.getServletContext()); s2container.init(); SingletonS2ContainerFactory.setContainer(s2container); if (SmartDeployUtil.isHotdeployMode(SingletonS2ContainerFactory.getContainer())) { throw new ServletException("S2Wicket does not support HOT deploy mode."); } // Application???getHomePage()?????? // ???????????? super.init(isServlet, filterConfig); // ???WebApplication????????? WebApplication webApplication = (WebApplication) Application.get(filterConfig.getFilterName()); webApplication.getComponentInstantiationListeners().add(new ComponentInjectionListener()); applicationConfigType = webApplication.getConfigurationType(); applicationEncoding = webApplication.getRequestCycleSettings().getResponseRequestEncoding(); if (RuntimeConfigurationType.DEVELOPMENT == RuntimeConfigurationType.valueOf(configuration)) { webApplication.getFrameworkSettings() .setSerializer(new ReloadingJavaSerializer(webApplication.getApplicationKey())); if (debug != null) { webApplication.mountPage(debug, S2DebugPage.class); } } } @Override public void destroy() { if (SingletonS2ContainerFactory.hasContainer()) { SingletonS2ContainerFactory.destroy(); } super.destroy(); } @Override protected ClassLoader getClassLoader() { if (useReloadingClassLoader) { return super.getClassLoader(); } else { return Thread.currentThread().getContextClassLoader(); } } @SuppressWarnings("unchecked") @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (RuntimeConfigurationType.DEVELOPMENT == applicationConfigType) { if (request instanceof HttpServletRequest) { // ??????? HttpSession session = ((HttpServletRequest) request).getSession(); ClassLoader previousLoader = (ClassLoader) session.getAttribute(SESSION_LOADER); if (previousLoader != getClassLoader()) { logger.info("[reload] invalidate old session attributes ..."); Enumeration<String> names = session.getAttributeNames(); while (names.hasMoreElements()) { String name = names.nextElement(); Object obj = session.getAttribute(name); ClassLoader objectLoader = obj != null ? obj.getClass().getClassLoader() : null; if (previousLoader == null || objectLoader == previousLoader) { session.removeAttribute(name); } } } session.setAttribute(SESSION_LOADER, getClassLoader()); } } if (request.getCharacterEncoding() == null) { request.setCharacterEncoding(applicationEncoding); } // S2ContainerFilter????? S2Container container = SingletonS2ContainerFactory.getContainer(); ExternalContext externalContext = container.getExternalContext(); if (externalContext == null) { throw new EmptyRuntimeException("externalContext"); } final ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); final Object originalRequest = externalContext.getRequest(); final Object originalResponse = externalContext.getResponse(); try { Thread.currentThread().setContextClassLoader(getClassLoader()); externalContext.setRequest(request); externalContext.setResponse(response); super.doFilter(request, response, chain); } finally { externalContext.setRequest(originalRequest); externalContext.setResponse(originalResponse); Thread.currentThread().setContextClassLoader(originalClassLoader); invalidateSession(request); } } /* * ???????? */ private String getInitParameter(FilterConfig filterConfig, String key, String def) { String value = filterConfig.getInitParameter(key); return value != null ? value : def; } /* * ??#INVALIDATE_SESSION?Boolean#TRUE??????? * HttpSession??? */ private void invalidateSession(final ServletRequest request) { final Object invalidateSession = request.getAttribute(S2ContainerFilter.INVALIDATE_SESSION); if (Boolean.TRUE.equals(invalidateSession)) { final HttpSession session = ((HttpServletRequest) request).getSession(false); if (session != null) { session.invalidate(); } } } }