🔀 Merge branch 'release/v82'
[Sone.git] / page / PageToadlet.java
1 /*
2  * shortener - PageToadlet.java - Copyright Â© 2010 David Roden
3  *
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.
8  *
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.
13  *
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/>.
16  */
17
18 package net.pterodactylus.sone.web.page;
19
20 import java.io.IOException;
21 import java.net.URI;
22 import java.util.Map.Entry;
23
24 import net.pterodactylus.sone.web.page.Page.Request.Method;
25 import freenet.client.HighLevelSimpleClient;
26 import freenet.clients.http.LinkEnabledCallback;
27 import freenet.clients.http.Toadlet;
28 import freenet.clients.http.ToadletContext;
29 import freenet.clients.http.ToadletContextClosedException;
30 import freenet.support.MultiValueTable;
31 import freenet.support.api.Bucket;
32 import freenet.support.api.HTTPRequest;
33 import freenet.support.io.BucketTools;
34 import freenet.support.io.Closer;
35
36 /**
37  * {@link Toadlet} implementation that is wrapped around a {@link Page}.
38  *
39  * @author <a href="mailto:bombe@pterodactylus.net">David â€˜Bombe’ Roden</a>
40  */
41 public class PageToadlet extends Toadlet implements LinkEnabledCallback {
42
43         /** The name of the menu item. */
44         private final String menuName;
45
46         /** The page that handles processing. */
47         private final Page page;
48
49         /** The path prefix for the page. */
50         private final String pathPrefix;
51
52         /**
53          * Creates a new toadlet that hands off processing to a {@link Page}.
54          *
55          * @param highLevelSimpleClient
56          * @param menuName
57          *            The name of the menu item
58          * @param page
59          *            The page to handle processing
60          * @param pathPrefix
61          *            Prefix that is prepended to all {@link Page#getPath()} return
62          *            values
63          */
64         protected PageToadlet(HighLevelSimpleClient highLevelSimpleClient, String menuName, Page page, String pathPrefix) {
65                 super(highLevelSimpleClient);
66                 this.menuName = menuName;
67                 this.page = page;
68                 this.pathPrefix = pathPrefix;
69         }
70
71         /**
72          * Returns the name to display in the menu.
73          *
74          * @return The name in the menu
75          */
76         public String getMenuName() {
77                 return menuName;
78         }
79
80         /**
81          * {@inheritDoc}
82          */
83         @Override
84         public String path() {
85                 return pathPrefix + page.getPath();
86         }
87
88         /**
89          * Handles a HTTP GET request.
90          *
91          * @param uri
92          *            The URI of the request
93          * @param httpRequest
94          *            The HTTP request
95          * @param toadletContext
96          *            The toadlet context
97          * @throws IOException
98          *             if an I/O error occurs
99          * @throws ToadletContextClosedException
100          *             if the toadlet context is closed
101          */
102         public void handleMethodGET(URI uri, HTTPRequest httpRequest, ToadletContext toadletContext) throws IOException, ToadletContextClosedException {
103                 handleRequest(new Page.Request(uri, Method.GET, httpRequest, toadletContext));
104         }
105
106         /**
107          * Handles a HTTP POST request.
108          *
109          * @param uri
110          *            The URI of the request
111          * @param httpRequest
112          *            The HTTP request
113          * @param toadletContext
114          *            The toadlet context
115          * @throws IOException
116          *             if an I/O error occurs
117          * @throws ToadletContextClosedException
118          *             if the toadlet context is closed
119          */
120         public void handleMethodPOST(URI uri, HTTPRequest httpRequest, ToadletContext toadletContext) throws IOException, ToadletContextClosedException {
121                 handleRequest(new Page.Request(uri, Method.POST, httpRequest, toadletContext));
122         }
123
124         /**
125          * {@inheritDoc}
126          */
127         @Override
128         public String toString() {
129                 return getClass().getName() + "[path=" + path() + ",page=" + page + "]";
130         }
131
132         /**
133          * Handles a HTTP request.
134          *
135          * @param pageRequest
136          *            The request to handle
137          * @throws IOException
138          *             if an I/O error occurs
139          * @throws ToadletContextClosedException
140          *             if the toadlet context is closed
141          */
142         private void handleRequest(Page.Request pageRequest) throws IOException, ToadletContextClosedException {
143                 Bucket data = null;
144                 try {
145                         Page.Response pageResponse = page.handleRequest(pageRequest);
146                         MultiValueTable<String, String> headers = new MultiValueTable<String, String>();
147                         if (pageResponse.getHeaders() != null) {
148                                 for (Entry<String, String> headerEntry : pageResponse.getHeaders().entrySet()) {
149                                         headers.put(headerEntry.getKey(), headerEntry.getValue());
150                                 }
151                         }
152                         data = pageRequest.getToadletContext().getBucketFactory().makeBucket(-1);
153                         if (pageResponse.getContent() != null) {
154                                 try {
155                                         BucketTools.copyFrom(data, pageResponse.getContent(), -1);
156                                 } finally {
157                                         Closer.close(pageResponse.getContent());
158                                 }
159                         } else {
160                                 /* get an OutputStream and close it immediately. */
161                                 Closer.close(data.getOutputStream());
162                         }
163                         writeReply(pageRequest.getToadletContext(), pageResponse.getStatusCode(), pageResponse.getContentType(), pageResponse.getStatusText(), headers, data);
164                 } catch (Throwable t1) {
165                         writeInternalError(t1, pageRequest.getToadletContext());
166                 } finally {
167                         Closer.close(data);
168                 }
169         }
170
171         /**
172          * {@inheritDoc}
173          */
174         @Override
175         public boolean isEnabled(ToadletContext toadletContext) {
176                 if (page instanceof LinkEnabledCallback) {
177                         return ((LinkEnabledCallback) page).isEnabled(toadletContext);
178                 }
179                 return true;
180         }
181
182 }