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.request;
018
019import java.nio.charset.Charset;
020import java.util.Locale;
021
022import org.apache.wicket.request.parameter.CombinedRequestParametersAdapter;
023import org.apache.wicket.request.parameter.EmptyRequestParameters;
024import org.apache.wicket.request.parameter.UrlRequestParametersAdapter;
025
026/**
027 * Request object.
028 * 
029 * @author Matej Knopp
030 */
031public abstract class Request
032{
033        /**
034         * Returns the URL for this request. URL is relative to Wicket filter path.
035         * 
036         * @return Url instance
037         */
038        public abstract Url getUrl();
039
040        /**
041         * Returns the url against which the client, usually the browser, will resolve relative urls in
042         * the rendered markup. If the client is a browser this is the url in the browser's address bar.
043         * 
044         * <p>
045         * Under normal circumstances the client and request ({@link #getUrl()}) urls are the same.
046         * Handling an Ajax request, however, is a good example of when they may be different.
047         * Technologies such as XHR are free to request whatever url they wish <strong>without
048         * modifying</strong> the client url; however, any produced urls will be evaluated by the client
049         * against the client url - not against the request url.
050         * </p>
051         * <p>
052         * Lets take a simple example: <br>
053         * 
054         * Suppose we are on a client detail page. This page contains an Ajax link which opens a list of
055         * client's orders. Each order has a link that goes to the order detail page.
056         * 
057         * The client detail page is located at
058         * 
059         * <pre>
060         * /detail/customer/15
061         * </pre>
062         * 
063         * and the order detail page is located at
064         * 
065         * <pre>
066         * /order/22
067         * </pre>
068         * 
069         * The Ajax link which renders the detail section is located at
070         * 
071         * <pre>
072         *  /detail/wicket?page 3
073         * </pre>
074         * 
075         * Lets run through the execution and see what happens when the XHR request is processed:
076         * 
077         * <pre>
078         * request 1: /details/customer/15
079         * client url: details/customer/15 (the url in the browser's address bar)
080         * request url: details/customer/15
081         * Wicket renders relative Ajax details anchor as ../../wicket/page?3  
082         * 
083         * ../../wicket/page?3 resolved against current client url details/customer/15 yields:
084         * request 2: /wicket/page?3
085         * client url: customer/15 (unchanged since XHRs requests dont change it)
086         * request url: wicket/ajax/page?3
087         * 
088         * now Wicket has to render a relative url to /details/order/22. If Wicket renders 
089         * it against the request url it will be: ../order/22, and later evaluated on the
090         * client will result in /customer/order/22 which is incorrect.
091         * </pre>
092         * 
093         * This is why implementations of {@link Request} must track the client url, so that relative
094         * urls can be rendered against the same url they will be evaluated against on the client -
095         * which is not always the same as the request url. For example, Wicket's Ajax implementation
096         * always sends the current client url in a header along with the XHR request so that Wicket can
097         * correctly render relative urls against it.
098         * </p>
099         * 
100         * @return client url
101         */
102        public abstract Url getClientUrl();
103
104        /**
105         * In case this request has been created using {@link #cloneWithUrl(Url)}, this method should
106         * return the original URL.
107         * 
108         * @return original URL
109         */
110        public Url getOriginalUrl()
111        {
112                return getUrl();
113        }
114
115        /**
116         * @return POST request parameters for this request.
117         */
118        public IRequestParameters getPostParameters()
119        {
120                return EmptyRequestParameters.INSTANCE;
121        }
122
123        /**
124         * @return GET request parameters for this request.
125         */
126        public IRequestParameters getQueryParameters()
127        {
128                return new UrlRequestParametersAdapter(getUrl());
129        }
130
131        /**
132         * @return all request parameters for this request (both POST and GET parameters)
133         */
134        public IRequestParameters getRequestParameters()
135        {
136                return new CombinedRequestParametersAdapter(getPostParameters(), getQueryParameters());
137        }
138
139        /**
140         * Returns locale for this request.
141         * 
142         * @return locale
143         */
144        public abstract Locale getLocale();
145
146        /**
147         * Returns request with specified URL and same POST parameters as this request.
148         * 
149         * @param url
150         *            Url instance
151         * @return request with specified URL.
152         */
153        public Request cloneWithUrl(final Url url)
154        {
155                return new Request()
156                {
157                        @Override
158                        public Url getUrl()
159                        {
160                                return url;
161                        }
162
163                        @Override
164                        public Url getOriginalUrl()
165                        {
166                                return Request.this.getOriginalUrl();
167                        }
168
169                        @Override
170                        public Locale getLocale()
171                        {
172                                return Request.this.getLocale();
173                        }
174
175                        @Override
176                        public IRequestParameters getPostParameters()
177                        {
178                                return Request.this.getPostParameters();
179                        }
180
181                        @Override
182                        public Charset getCharset()
183                        {
184                                return Request.this.getCharset();
185                        }
186
187                        @Override
188                        public Url getClientUrl()
189                        {
190                                return Request.this.getClientUrl();
191                        }
192
193                        @Override
194                        public Object getContainerRequest()
195                        {
196                                return Request.this.getContainerRequest();
197                        }
198                };
199        }
200
201        /**
202         * Returns prefix from Wicket Filter mapping to context path. This method does not take the
203         * actual URL into account.
204         * <p>
205         * For example if Wicket filter is mapped to hello/* this method should return ../ regardless of
206         * actual URL (after Wicket filter)
207         * 
208         * @return prefix to context path for this request.
209         * 
210         */
211        public String getPrefixToContextPath()
212        {
213                return "";
214        }
215
216        /**
217         * Returns the context path or an empty string if the application is running under root context.
218         * Returned path, unless an empty string, will always start with a slash and will never end with
219         * a slash.
220         * 
221         * @return context path
222         */
223        public String getContextPath()
224        {
225                return "";
226        }
227
228        /**
229         * Returns the path to which wicket Filter is mapped or an empty string if the filter is mapped
230         * to {@code /*}. Returned path, unless an empty string, will always start with a slash and will
231         * never end with a slash.
232         * 
233         * @return filter path
234         */
235        public String getFilterPath()
236        {
237                return "";
238        }
239
240        /**
241         * Gets charset of the request
242         * 
243         * @return request charset
244         */
245        public abstract Charset getCharset();
246
247        /**
248         * Provides access to the low-level container request object that implementaion of this
249         * {@link Request} delegate to. This allows users to access features provided by the container
250         * requests but not by generalized Wicket {@link Request} objects.
251         * 
252         * @return low-level container request object, or {@code null} if none
253         */
254        public abstract Object getContainerRequest();
255}