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.text.DateFormat;
020import java.text.SimpleDateFormat;
021import java.util.Arrays;
022import java.util.Collections;
023import java.util.Date;
024import java.util.Enumeration;
025import java.util.HashMap;
026import java.util.List;
027import java.util.Locale;
028import java.util.Map;
029
030import jakarta.servlet.http.HttpServletRequest;
031import jakarta.servlet.http.HttpServletRequestWrapper;
032
033/**
034 * See <a href="http://code.google.com/p/xebia-france/wiki/XForwardedFilter">XForwardedFilter</a>
035 * 
036 * @author Juergen Donnerstag
037 */
038public class XForwardedRequestWrapper extends HttpServletRequestWrapper
039{
040        private SimpleDateFormat[] dateFormats = new SimpleDateFormat[] {
041                        new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US),
042                        new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US),
043                        new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US) };
044
045        private Map<String, List<String>> headers;
046
047        private String remoteAddr;
048
049        private String remoteHost;
050
051        private String scheme;
052
053        private boolean secure;
054
055        private int serverPort;
056
057        /**
058         * Construct.
059         * 
060         * @param request
061         */
062        @SuppressWarnings("unchecked")
063        public XForwardedRequestWrapper(final HttpServletRequest request)
064        {
065                super(request);
066
067                remoteAddr = request.getRemoteAddr();
068                remoteHost = request.getRemoteHost();
069                scheme = request.getScheme();
070                secure = request.isSecure();
071                serverPort = request.getServerPort();
072
073                headers = new HashMap<String, List<String>>();
074                Enumeration<?> headerNames = request.getHeaderNames();
075                while (headerNames.hasMoreElements())
076                {
077                        String header = (String)headerNames.nextElement();
078                        headers.put(header, Collections.list(request.getHeaders(header)));
079                }
080        }
081
082        /**
083         * @see jakarta.servlet.http.HttpServletRequestWrapper#getDateHeader(java.lang.String)
084         */
085        @Override
086        public long getDateHeader(final String name)
087        {
088                String value = getHeader(name);
089                if (value == null)
090                {
091                        return -1;
092                }
093
094                Date date = null;
095                for (int i = 0; ((i < dateFormats.length) && (date == null)); i++)
096                {
097                        DateFormat dateFormat = dateFormats[i];
098                        try
099                        {
100                                date = dateFormat.parse(value);
101                        }
102                        catch (Exception ignored)
103                        {
104                                ; // noop
105                        }
106                }
107
108                if (date == null)
109                {
110                        throw new IllegalArgumentException(value);
111                }
112                else
113                {
114                        return date.getTime();
115                }
116        }
117
118        /**
119         * @see jakarta.servlet.http.HttpServletRequestWrapper#getHeader(java.lang.String)
120         */
121        @Override
122        public String getHeader(final String name)
123        {
124                Map.Entry<String, List<String>> header = getHeaderEntry(name);
125                if (header == null || header.getValue() == null || header.getValue().isEmpty())
126                {
127                        return null;
128                }
129                else
130                {
131                        return header.getValue().get(0);
132                }
133        }
134
135        /**
136         * 
137         * @param name
138         * @return The map entry for 'name'
139         */
140        private Map.Entry<String, List<String>> getHeaderEntry(final String name)
141        {
142                for (Map.Entry<String, List<String>> entry : headers.entrySet())
143                {
144                        if (entry.getKey().equalsIgnoreCase(name))
145                        {
146                                return entry;
147                        }
148                }
149                return null;
150        }
151
152        /**
153         * @see jakarta.servlet.http.HttpServletRequestWrapper#getHeaderNames()
154         */
155        @Override
156        public Enumeration<String> getHeaderNames()
157        {
158                return Collections.enumeration(headers.keySet());
159        }
160
161        /**
162         * @see jakarta.servlet.http.HttpServletRequestWrapper#getHeaders(java.lang.String)
163         */
164        @Override
165        public Enumeration<String> getHeaders(final String name)
166        {
167                Map.Entry<String, List<String>> header = getHeaderEntry(name);
168                if (header == null || header.getValue() == null)
169                {
170                        return Collections.enumeration(Collections.<String>emptyList());
171                }
172                else
173                {
174                        return Collections.enumeration(header.getValue());
175                }
176        }
177
178        /**
179         * @see jakarta.servlet.http.HttpServletRequestWrapper#getIntHeader(java.lang.String)
180         */
181        @Override
182        public int getIntHeader(final String name)
183        {
184                String value = getHeader(name);
185                if (value == null)
186                {
187                        return -1;
188                }
189                else
190                {
191                        return Integer.parseInt(value);
192                }
193        }
194
195        /**
196         * @see jakarta.servlet.ServletRequestWrapper#getRemoteAddr()
197         */
198        @Override
199        public String getRemoteAddr()
200        {
201                return remoteAddr;
202        }
203
204        /**
205         * @see jakarta.servlet.ServletRequestWrapper#getRemoteHost()
206         */
207        @Override
208        public String getRemoteHost()
209        {
210                return remoteHost;
211        }
212
213        /**
214         * @see jakarta.servlet.ServletRequestWrapper#getScheme()
215         */
216        @Override
217        public String getScheme()
218        {
219                return scheme;
220        }
221
222        /**
223         * @see jakarta.servlet.ServletRequestWrapper#getServerPort()
224         */
225        @Override
226        public int getServerPort()
227        {
228                return serverPort;
229        }
230
231        /**
232         * @see jakarta.servlet.ServletRequestWrapper#isSecure()
233         */
234        @Override
235        public boolean isSecure()
236        {
237                return secure;
238        }
239
240        /**
241         * @param name
242         */
243        public void removeHeader(final String name)
244        {
245                Map.Entry<String, List<String>> header = getHeaderEntry(name);
246                if (header != null)
247                {
248                        headers.remove(header.getKey());
249                }
250        }
251
252        /**
253         * 
254         * @param name
255         * @param value
256         */
257        public void setHeader(final String name, final String value)
258        {
259                List<String> values = Arrays.asList(value);
260                Map.Entry<String, List<String>> header = getHeaderEntry(name);
261                if (header == null)
262                {
263                        headers.put(name, values);
264                }
265                else
266                {
267                        header.setValue(values);
268                }
269        }
270
271        /**
272         * 
273         * @param remoteAddr
274         */
275        public void setRemoteAddr(final String remoteAddr)
276        {
277                this.remoteAddr = remoteAddr;
278        }
279
280        /**
281         * 
282         * @param remoteHost
283         */
284        public void setRemoteHost(final String remoteHost)
285        {
286                this.remoteHost = remoteHost;
287        }
288
289        /**
290         * 
291         * @param scheme
292         */
293        public void setScheme(final String scheme)
294        {
295                this.scheme = scheme;
296        }
297
298        /**
299         * 
300         * @param secure
301         */
302        public void setSecure(final boolean secure)
303        {
304                this.secure = secure;
305        }
306
307        /**
308         * 
309         * @param serverPort
310         */
311        public void setServerPort(final int serverPort)
312        {
313                this.serverPort = serverPort;
314        }
315}