2 * shortener - TemplatePage.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.StringWriter;
21 import java.util.Collection;
22 import java.util.Collections;
23 import java.util.logging.Level;
24 import java.util.logging.Logger;
26 import net.pterodactylus.sone.web.page.Page.Request.Method;
27 import net.pterodactylus.util.logging.Logging;
28 import net.pterodactylus.util.template.DataProvider;
29 import net.pterodactylus.util.template.Template;
30 import freenet.clients.http.LinkEnabledCallback;
31 import freenet.clients.http.PageMaker;
32 import freenet.clients.http.PageNode;
33 import freenet.clients.http.ToadletContext;
34 import freenet.l10n.BaseL10n;
37 * Base class for all {@link Page}s that are rendered with {@link Template}s.
39 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
41 public class TemplatePage implements Page, LinkEnabledCallback {
44 private static final Logger logger = Logging.getLogger(TemplatePage.class);
46 /** The path of the page. */
47 private final String path;
49 /** The template to render. */
50 private final Template template;
52 /** The L10n handler. */
53 private final BaseL10n l10n;
55 /** The l10n key for the page title. */
56 private final String pageTitleKey;
58 /** Where to redirect for invalid form passwords. */
59 private final String invalidFormPasswordRedirectTarget;
62 * Creates a new template page.
65 * The path of the page
67 * The template to render
71 * The l10n key of the title page
72 * @param invalidFormPasswordRedirectTarget
73 * The target to redirect to if a POST request does not contain
74 * the correct form password
76 public TemplatePage(String path, Template template, BaseL10n l10n, String pageTitleKey, String invalidFormPasswordRedirectTarget) {
78 this.template = template;
80 this.pageTitleKey = pageTitleKey;
81 this.invalidFormPasswordRedirectTarget = invalidFormPasswordRedirectTarget;
88 public String getPath() {
96 public Response handleRequest(Request request) {
97 String redirectTarget = getRedirectTarget(request);
98 if (redirectTarget != null) {
99 return new RedirectResponse(redirectTarget);
102 ToadletContext toadletContext = request.getToadletContext();
103 if (request.getMethod() == Method.POST) {
104 /* require form password. */
105 String formPassword = request.getHttpRequest().getPartAsStringFailsafe("formPassword", 32);
106 if (!formPassword.equals(toadletContext.getContainer().getFormPassword())) {
107 return new RedirectResponse(invalidFormPasswordRedirectTarget);
110 PageMaker pageMaker = toadletContext.getPageMaker();
111 PageNode pageNode = pageMaker.getPageNode(l10n.getString(pageTitleKey), toadletContext);
112 for (String styleSheet : getStyleSheets()) {
113 pageNode.addCustomStyleSheet(styleSheet);
115 String shortcutIcon = getShortcutIcon();
116 if (shortcutIcon != null) {
117 pageNode.addForwardLink("icon", shortcutIcon);
120 DataProvider dataProvider = template.createDataProvider();
122 long start = System.nanoTime();
123 processTemplate(request, dataProvider);
124 long finish = System.nanoTime();
125 logger.log(Level.FINEST, "Template was rendered in " + ((finish - start) / 1000) / 1000.0 + "ms.");
126 } catch (RedirectException re1) {
127 return new RedirectResponse(re1.getTarget());
130 StringWriter stringWriter = new StringWriter();
131 template.render(dataProvider, stringWriter);
132 pageNode.content.addChild("%", stringWriter.toString());
134 postProcess(request, dataProvider);
136 return new Response(200, "OK", "text/html", pageNode.outer.generate());
140 * Can be overridden to return a custom set of style sheets that are to be
141 * included in the page’s header.
143 * @return Additional style sheets to load
145 protected Collection<String> getStyleSheets() {
146 return Collections.emptySet();
150 * Returns the name of the shortcut icon to include in the page’s header.
152 * @return The URL of the shortcut icon, or {@code null} for no icon
154 protected String getShortcutIcon() {
159 * Can be overridden when extending classes need to set variables in the
160 * template before it is rendered.
163 * The request that is rendered
164 * @param dataProvider
165 * The data provider to set variables in
166 * @throws RedirectException
167 * if the processing page wants to redirect after processing
169 protected void processTemplate(Request request, DataProvider dataProvider) throws RedirectException {
174 * This method will be called after
175 * {@link #processTemplate(net.pterodactylus.sone.web.page.Page.Request, DataProvider)}
176 * has processed the template and the template was rendered. This method
177 * will not be called if
178 * {@link #processTemplate(net.pterodactylus.sone.web.page.Page.Request, DataProvider)}
179 * throws a {@link RedirectException}!
182 * The request being processed
183 * @param dataProvider
184 * The data provider that supplied the rendered data
186 protected void postProcess(Request request, DataProvider dataProvider) {
191 * Can be overridden to redirect the user to a different page, in case a log
192 * in is required, or something else is wrong.
195 * The request that is processed
196 * @return The URL to redirect to, or {@code null} to not redirect
198 protected String getRedirectTarget(Page.Request request) {
203 // INTERFACE LinkEnabledCallback
210 public boolean isEnabled(ToadletContext toadletContext) {
215 * Exception that can be thrown to signal that a subclassed {@link Page}
216 * wants to redirect the user during the
217 * {@link TemplatePage#processTemplate(net.pterodactylus.sone.web.page.Page.Request, DataProvider)}
220 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
222 public class RedirectException extends Exception {
224 /** The target to redirect to. */
225 private final String target;
228 * Creates a new redirect exception.
231 * The target of the redirect
233 public RedirectException(String target) {
234 this.target = target;
238 * Returns the target to redirect to.
240 * @return The target to redirect to
242 public String getTarget() {