    001// Licensed under the Apache License, Version 2.0 (the "License");
    002// you may not use this file except in compliance with the License.
    003// You may obtain a copy of the License at
    004//
    005// http://www.apache.org/licenses/LICENSE-2.0
    006//
    007// Unless required by applicable law or agreed to in writing, software
    008// distributed under the License is distributed on an "AS IS" BASIS,
    009// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    010// See the License for the specific language governing permissions and
    011// limitations under the License.
    012
    013package org.apache.tapestry5.internal.services;
    014
    015import org.apache.tapestry5.ioc.internal.util.InternalUtils;
    016import org.apache.tapestry5.services.Request;
    017import org.apache.tapestry5.services.Session;
    018
    019import javax.servlet.http.HttpServletRequest;
    020import java.io.UnsupportedEncodingException;
    021import java.util.List;
    022import java.util.Locale;
    023
    024/**
    025 * Basic implementation of {@link org.apache.tapestry5.services.Request} that wraps around an
    026 * {@link javax.servlet.http.HttpServletRequest}. This is not threadsafe, nor should it need to be (each Request is
    027 * handled by its own Thread).
    028 */
    029public class RequestImpl implements Request
    030{
    031    static final String REQUESTED_WITH_HEADER = "X-Requested-With";
    032
    033    static final String XML_HTTP_REQUEST = "XMLHttpRequest";
    034
    035    static final String X_FORWARDED_PROTO_HEADER = "X-Forwarded-Proto";
    036    static final String X_FORWARDED_PROTO_HTTPS = "https";
    037
    038    private final HttpServletRequest request;
    039
    040    private final String applicationCharset;
    041
    042    private final TapestrySessionFactory sessionFactory;
    043
    044    private boolean encodingSet;
    045
    046    private Session session;
    047
    048    public RequestImpl(
    049            HttpServletRequest request,
    050            String applicationCharset,
    051            TapestrySessionFactory sessionFactory)
    052    {
    053        this.request = request;
    054        this.applicationCharset = applicationCharset;
    055        this.sessionFactory = sessionFactory;
    056    }
    057
    058    public List<String> getParameterNames()
    059    {
    060        setupEncoding();
    061
    062        return InternalUtils.toList(request.getParameterNames());
    063    }
    064
    065    public List<String> getHeaderNames()
    066    {
    067        return InternalUtils.toList(request.getHeaderNames());
    068    }
    069
    070    public String getParameter(String name)
    071    {
    072        setupEncoding();
    073
    074        return request.getParameter(name);
    075    }
    076
    077    public String[] getParameters(String name)
    078    {
    079        setupEncoding();
    080
    081        return request.getParameterValues(name);
    082    }
    083
    084    public String getHeader(String name)
    085    {
    086        return request.getHeader(name);
    087    }
    088
    089    public String getPath()
    090    {
    091        String pathInfo = request.getPathInfo();
    092
    093        if (pathInfo == null)
    094            return request.getServletPath();
    095
    096        // Websphere 6.1 is a bit wonky (see TAPESTRY-1713), and tends to return the empty string
    097        // for the servlet path, and return the true path in pathInfo.
    098
    099        return pathInfo.length() == 0 ? "/" : pathInfo;
    100    }
    101
    102    public String getContextPath()
    103    {
    104        return request.getContextPath();
    105    }
    106
    107
    108    public boolean isSessionInvalidated()
    109    {
    110        // Double check to ensure that the session exists, but don't create it.
    111        if (session == null)
    112        {
    113            session = sessionFactory.getSession(false);
    114        }
    115
    116        return session != null && session.isInvalidated();
    117    }
    118
    119    public Session getSession(boolean create)
    120    {
    121        if (session != null && session.isInvalidated())
    122        {
    123            session = null;
    124        }
    125
    126        if (session == null)
    127        {
    128            // TAP5-1489 - Re-storage of session attributes at end of request should be configurable
    129            session = sessionFactory.getSession(create);
    130        }
    131
    132        return session;
    133    }
    134
    135    public Locale getLocale()
    136    {
    137        return request.getLocale();
    138    }
    139
    140    public long getDateHeader(String name)
    141    {
    142        return request.getDateHeader(name);
    143    }
    144
    145    private void setupEncoding()
    146    {
    147        if (encodingSet)
    148        {
    149            return;
    150        }
    151
    152        // The request may specify an encoding, which is better than the application, which can only
    153        // guess at what the client is doing!
    154
    155        String requestEncoding = request.getCharacterEncoding();
    156
    157        try
    158        {
    159            request.setCharacterEncoding(requestEncoding != null ? requestEncoding : applicationCharset);
    160        } catch (UnsupportedEncodingException ex)
    161        {
    162            throw new RuntimeException(ex);
    163        }
    164
    165        encodingSet = true;
    166    }
    167
    168    public boolean isXHR()
    169    {
    170        return XML_HTTP_REQUEST.equals(request.getHeader(REQUESTED_WITH_HEADER));
    171    }
    172
    173    public boolean isSecure()
    174    {
    175        return request.isSecure() ||
    176                X_FORWARDED_PROTO_HTTPS.equals(request.getHeader(X_FORWARDED_PROTO_HEADER));
    177    }
    178
    179    public boolean isRequestedSessionIdValid()
    180    {
    181        return request.isRequestedSessionIdValid();
    182    }
    183
    184    public Object getAttribute(String name)
    185    {
    186        return request.getAttribute(name);
    187    }
    188
    189    public List<String> getAttributeNames()
    190    {
    191        setupEncoding();
    192
    193        return InternalUtils.toList(request.getAttributeNames());
    194    }
    195
    196    public void setAttribute(String name, Object value)
    197    {
    198        request.setAttribute(name, value);
    199    }
    200
    201    public String getMethod()
    202    {
    203        return request.getMethod();
    204    }
    205
    206    public String getServerName()
    207    {
    208        return request.getServerName();
    209    }
    210
    211    public int getLocalPort()
    212    {
    213        return request.getLocalPort();
    214    }
    215
    216    /**
    217     * @since 5.2.5
    218     */
    219    public int getServerPort()
    220    {
    221        return request.getServerPort();
    222    }
    223
    224    public String getRemoteHost()
    225    {
    226        return request.getRemoteHost();
    227    }
    228
    229}