001// Copyright 2004, 2005 The Apache Software Foundation
002//
003// Licensed under the Apache License, Version 2.0 (the "License");
004// you may not use this file except in compliance with the License.
005// You may obtain a copy of the License at
006//
007//     http://www.apache.org/licenses/LICENSE-2.0
008//
009// Unless required by applicable law or agreed to in writing, software
010// distributed under the License is distributed on an "AS IS" BASIS,
011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012// See the License for the specific language governing permissions and
013// limitations under the License.
014
015package org.apache.tapestry;
016
017import java.io.IOException;
018
019import javax.servlet.Filter;
020import javax.servlet.FilterChain;
021import javax.servlet.FilterConfig;
022import javax.servlet.ServletException;
023import javax.servlet.ServletRequest;
024import javax.servlet.ServletResponse;
025import javax.servlet.http.HttpServletRequest;
026import javax.servlet.http.HttpServletResponse;
027
028import org.apache.commons.logging.Log;
029import org.apache.commons.logging.LogFactory;
030import org.apache.hivemind.HiveMind;
031
032/**
033 * Filter used to redirect a root context URL (i.e., "/context" or "/context/" to the Tapestry
034 * application servlet (typically, "/context/app"). This servlet is mapped to "/" and must have a
035 * &lt;init-parameter&;gt; <code>redirect-path</code> that is the application servlet's path
036 * (i.e., "/app"). If no value is specified, then "/app" is used. The path is always relative to the
037 * servlet context, and should always begin with a leading slash.
038 * <p>
039 * Filters are only available in Servlet API 2.3 and above.
040 * <p>
041 * Servlet API 2.4 is expected to allow a servlets in the welcome list (equivalent to index.html or
042 * index.jsp), at which point this filter should no longer be necessary.
043 * 
044 * @author Howard Lewis Ship
045 * @since 3.0
046 */
047
048public class RedirectFilter implements Filter
049{
050    private static final Log LOG = LogFactory.getLog(RedirectFilter.class);
051
052    public static final String REDIRECT_PATH_PARAM = "redirect-path";
053
054    private String _redirectPath;
055
056    public void init(FilterConfig config) throws ServletException
057    {
058        _redirectPath = config.getInitParameter(REDIRECT_PATH_PARAM);
059
060        if (HiveMind.isBlank(_redirectPath))
061            _redirectPath = "/app";
062
063        if (LOG.isDebugEnabled())
064            LOG.debug(Tapestry.format("RedirectServlet.redirect-path", _redirectPath));
065    }
066
067    public void destroy()
068    {
069
070    }
071
072    /**
073     * This filter intercepts the so-called "default" servlet, whose job is to provide access to
074     * standard resources packaged within the web application context. This code is interested in
075     * only the very root, redirecting to the appropriate Tapestry application servlet. Other values
076     * are passed through unchanged.
077     */
078    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
079            throws IOException, ServletException
080    {
081        HttpServletRequest hrequest = (HttpServletRequest) request;
082        HttpServletResponse hresponse = (HttpServletResponse) response;
083
084        String servletPath = hrequest.getServletPath();
085        String pathInfo = hrequest.getPathInfo();
086
087        // Been experimenting with different servlet containers. In Jetty 4.2.8 and Tomcat 4.1,
088        // resources have a non-null servletPath. If JBossWeb 3.0.6, the servletPath is
089        // null and the pathInfo indicates the relative location of the resource.
090
091        if ((HiveMind.isBlank(servletPath) || servletPath.equals("/"))
092                && (HiveMind.isBlank(pathInfo) || pathInfo.equals("/")))
093        {
094            String path = hrequest.getContextPath() + _redirectPath;
095
096            if (LOG.isDebugEnabled())
097                LOG.debug(Tapestry.format("RedirectServlet.redirecting", path));
098
099            hresponse.sendRedirect(path);
100            return;
101        }
102
103        chain.doFilter(request, response);
104    }
105
106}