🔀 Merge branch 'release/v82'
[Sone.git] / web / 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          *            The high-level simple client
57          * @param menuName
58          *            The name of the menu item
59          * @param page
60          *            The page to handle processing
61          * @param pathPrefix
62          *            Prefix that is prepended to all {@link Page#getPath()} return
63          *            values
64          */
65         protected PageToadlet(HighLevelSimpleClient highLevelSimpleClient, String menuName, Page page, String pathPrefix) {
66                 super(highLevelSimpleClient);
67                 this.menuName = menuName;
68                 this.page = page;
69                 this.pathPrefix = pathPrefix;
70         }
71
72         /**
73          * Returns the name to display in the menu.
74          *
75          * @return The name in the menu
76          */
77         public String getMenuName() {
78                 return menuName;
79         }
80
81         /**
82          * {@inheritDoc}
83          */
84         @Override
85         public String path() {
86                 return pathPrefix + page.getPath();
87         }
88
89         /**
90          * Handles a HTTP GET request.
91          *
92          * @param uri
93          *            The URI of the request
94          * @param httpRequest
95          *            The HTTP request
96          * @param toadletContext
97          *            The toadlet context
98          * @throws IOException
99          *             if an I/O error occurs
100          * @throws ToadletContextClosedException
101          *             if the toadlet context is closed
102          */
103         public void handleMethodGET(URI uri, HTTPRequest httpRequest, ToadletContext toadletContext) throws IOException, ToadletContextClosedException {
104                 handleRequest(new Page.Request(uri, Method.GET, httpRequest, toadletContext));
105         }
106
107         /**
108          * Handles a HTTP POST request.
109          *
110          * @param uri
111          *            The URI of the request
112          * @param httpRequest
113          *            The HTTP request
114          * @param toadletContext
115          *            The toadlet context
116          * @throws IOException
117          *             if an I/O error occurs
118          * @throws ToadletContextClosedException
119          *             if the toadlet context is closed
120          */
121         public void handleMethodPOST(URI uri, HTTPRequest httpRequest, ToadletContext toadletContext) throws IOException, ToadletContextClosedException {
122                 handleRequest(new Page.Request(uri, Method.POST, httpRequest, toadletContext));
123         }
124
125         /**
126          * {@inheritDoc}
127          */
128         @Override
129         public String toString() {
130                 return getClass().getName() + "[path=" + path() + ",page=" + page + "]";
131         }
132
133         /**
134          * Handles a HTTP request.
135          *
136          * @param pageRequest
137          *            The request to handle
138          * @throws IOException
139          *             if an I/O error occurs
140          * @throws ToadletContextClosedException
141          *             if the toadlet context is closed
142          */
143         private void handleRequest(Page.Request pageRequest) throws IOException, ToadletContextClosedException {
144                 Bucket data = null;
145                 try {
146                         Page.Response pageResponse = page.handleRequest(pageRequest);
147                         MultiValueTable<String, String> headers = new MultiValueTable<String, String>();
148                         if (pageResponse.getHeaders() != null) {
149                                 for (Entry<String, String> headerEntry : pageResponse.getHeaders().entrySet()) {
150                                         headers.put(headerEntry.getKey(), headerEntry.getValue());
151                                 }
152                         }
153                         data = pageRequest.getToadletContext().getBucketFactory().makeBucket(-1);
154                         if (pageResponse.getContent() != null) {
155                                 try {
156                                         BucketTools.copyFrom(data, pageResponse.getContent(), -1);
157                                 } finally {
158                                         Closer.close(pageResponse.getContent());
159                                 }
160                         } else {
161                                 /* get an OutputStream and close it immediately. */
162                                 Closer.close(data.getOutputStream());
163                         }
164                         writeReply(pageRequest.getToadletContext(), pageResponse.getStatusCode(), pageResponse.getContentType(), pageResponse.getStatusText(), headers, data);
165                 } catch (Throwable t1) {
166                         writeInternalError(t1, pageRequest.getToadletContext());
167                 } finally {
168                         Closer.close(data);
169                 }
170         }
171
172         /**
173          * {@inheritDoc}
174          */
175         @Override
176         public boolean isEnabled(ToadletContext toadletContext) {
177                 if (page instanceof LinkEnabledCallback) {
178                         return ((LinkEnabledCallback) page).isEnabled(toadletContext);
179                 }
180                 return true;
181         }
182
183 }