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