2 * shortener - Page.java - Copyright © 2010 David Roden
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 package net.pterodactylus.sone.web.page;
20 import java.io.ByteArrayInputStream;
21 import java.io.InputStream;
22 import java.io.UnsupportedEncodingException;
24 import java.util.HashMap;
27 import freenet.clients.http.ToadletContext;
28 import freenet.support.api.HTTPRequest;
31 * A page is responsible for handling HTTP requests and creating appropriate
34 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
36 public interface Page {
39 * Returns the path of this toadlet.
41 * @return The path of this toadlet
43 public String getPath();
49 * The request to handle
50 * @return The response
52 public Response handleRequest(Request request);
55 * Container for request data.
57 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
59 public class Request {
62 * Enumeration for all possible HTTP request methods.
64 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’
92 /** The URI that was accessed. */
93 private final URI uri;
95 /** The HTTP method that was used. */
96 private final Method method;
98 /** The HTTP request. */
99 private final HTTPRequest httpRequest;
101 /** The toadlet context. */
102 private final ToadletContext toadletContext;
105 * Creates a new request that holds the given data.
108 * The URI of the request
110 * The HTTP method of the request
113 * @param toadletContext
114 * The toadlet context of the request
116 public Request(URI uri, Method method, HTTPRequest httpRequest, ToadletContext toadletContext) {
118 this.method = method;
119 this.httpRequest = httpRequest;
120 this.toadletContext = toadletContext;
124 * Returns the URI that was accessed.
126 * @return The accessed URI
128 public URI getUri() {
133 * Returns the HTTP method that was used to access the page.
135 * @return The HTTP method
137 public Method getMethod() {
142 * Returns the HTTP request.
144 * @return The HTTP request
146 public HTTPRequest getHttpRequest() {
151 * Returns the toadlet context.
153 * @return The toadlet context
155 public ToadletContext getToadletContext() {
156 return toadletContext;
162 * Container for the HTTP response of a {@link Page}.
164 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
166 public class Response {
168 /** The HTTP status code of the response. */
169 private final int statusCode;
171 /** The HTTP status text of the response. */
172 private final String statusText;
174 /** The content type of the response. */
175 private final String contentType;
177 /** The headers of the response. */
178 private final Map<String, String> headers;
180 /** The content of the response body. */
181 private final InputStream content;
184 * Creates a new response.
187 * The HTTP status code of the response
189 * The HTTP status text of the response
191 * The content type of the response
193 * The text in the response body
195 public Response(int statusCode, String statusText, String contentType, String text) {
196 this(statusCode, statusText, contentType, getBytes(text));
200 * Creates a new response.
203 * The HTTP status code of the response
205 * The HTTP status text of the response
207 * The content type of the response
209 * The content of the reponse body
211 public Response(int statusCode, String statusText, String contentType, byte[] content) {
212 this(statusCode, statusText, contentType, new HashMap<String, String>(), content);
216 * Creates a new response.
219 * The HTTP status code of the response
221 * The HTTP status text of the response
223 * The content type of the response
225 * The headers of the response
227 public Response(int statusCode, String statusText, String contentType, Map<String, String> headers) {
228 this(statusCode, statusText, contentType, headers, (InputStream) null);
232 * Creates a new response.
235 * The HTTP status code of the response
237 * The HTTP status text of the response
239 * The content type of the response
241 * The headers of the response
243 * The content of the reponse body
245 public Response(int statusCode, String statusText, String contentType, Map<String, String> headers, byte[] content) {
246 this(statusCode, statusText, contentType, headers, new ByteArrayInputStream(content));
250 * Creates a new response.
253 * The HTTP status code of the response
255 * The HTTP status text of the response
257 * The content type of the response
259 * The headers of the response
261 * The content of the reponse body
263 public Response(int statusCode, String statusText, String contentType, Map<String, String> headers, InputStream content) {
264 this.statusCode = statusCode;
265 this.statusText = statusText;
266 this.contentType = contentType;
267 this.headers = headers;
268 this.content = content;
272 * Returns the HTTP status code of the response.
274 * @return The HTTP status code
276 public int getStatusCode() {
281 * Returns the HTTP status text.
283 * @return The HTTP status text
285 public String getStatusText() {
290 * Returns the content type of the response.
292 * @return The content type of the reponse
294 public String getContentType() {
299 * Returns HTTP headers of the response. May be {@code null} if no
300 * headers are returned.
302 * @return The response headers, or {@code null} if there are no
305 public Map<String, String> getHeaders() {
310 * Sets the HTTP header with the given name to the given value. Multiple
311 * headers with the same name are not implemented so that latest call to
312 * {@link #setHeader(String, String)} determines what is sent to the
316 * The name of the header
318 * The value of the header
320 public void setHeader(String name, String value) {
321 headers.put(name, value);
325 * Returns the content of the response body. May be {@code null} if the
326 * response does not have a body.
328 * @return The content of the response body
330 public InputStream getContent() {
339 * Returns the UTF-8 representation of the given text.
343 * @return The encoded text
345 private static byte[] getBytes(String text) {
347 return text.getBytes("UTF-8");
348 } catch (UnsupportedEncodingException uee1) {
349 /* every JVM needs to support UTF-8. */
355 * Creates a header map containing a single header.
358 * The name of the header
360 * The value of the header
361 * @return The map containing the single header
363 protected static Map<String, String> createHeader(String name, String value) {
364 Map<String, String> headers = new HashMap<String, String>();
365 headers.put(name, value);
372 * {@link Response} implementation that performs an HTTP redirect.
374 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
376 public class RedirectResponse extends Response {
379 * Creates a new redirect response to the new location.
384 public RedirectResponse(String newLocation) {
385 this(newLocation, true);
389 * Creates a new redirect response to the new location.
394 * Whether the redirect should be marked as permanent
396 public RedirectResponse(String newLocation, boolean permanent) {
397 super(permanent ? 302 : 307, "Redirected", null, createHeader("Location", newLocation));