001/* 002 * #%L 003 * Netarchivesuite - harvester 004 * %% 005 * Copyright (C) 2005 - 2014 The Royal Danish Library, the Danish State and University Library, 006 * the National Library of France and the Austrian National Library. 007 * %% 008 * This program is free software: you can redistribute it and/or modify 009 * it under the terms of the GNU Lesser General Public License as 010 * published by the Free Software Foundation, either version 2.1 of the 011 * License, or (at your option) any later version. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Lesser Public License for more details. 017 * 018 * You should have received a copy of the GNU General Lesser Public 019 * License along with this program. If not, see 020 * <http://www.gnu.org/licenses/lgpl-2.1.html>. 021 * #L% 022 */ 023 024package dk.netarkivet.viewerproxy.distribute; 025 026import java.io.IOException; 027import java.net.URI; 028import java.util.Locale; 029import java.util.Set; 030 031import javax.servlet.http.HttpServletResponse; 032import javax.servlet.jsp.JspWriter; 033 034import org.slf4j.Logger; 035import org.slf4j.LoggerFactory; 036 037import dk.netarkivet.common.exceptions.ArgumentNotValid; 038import dk.netarkivet.common.exceptions.IOFailure; 039import dk.netarkivet.common.utils.I18n; 040import dk.netarkivet.common.utils.StringUtils; 041import dk.netarkivet.common.webinterface.HTMLUtils; 042import dk.netarkivet.viewerproxy.CommandResolver; 043import dk.netarkivet.viewerproxy.Constants; 044import dk.netarkivet.viewerproxy.Controller; 045 046/** 047 * Client side communication with http controller server. This class works on a specific response object, simply 048 * forwarding it to the given url. Thus an instance of this class is a use-once-object. 049 * <p> 050 * The class is supposed to be used in JSP pages in order to make sure that the remote URI is requested through the 051 * browser, so communication with the HTTPControllerServer is done to the one currently set as viewer proxy. 052 */ 053public class HTTPControllerClient implements Controller { 054 /** The response we are working on. */ 055 private HttpServletResponse response; 056 /** The JspWriter that the page gave us. */ 057 private JspWriter out; 058 /** The url to return to, for commands using this. */ 059 private String returnURL; 060 061 /** The I18n object associated with this class. */ 062 private static final I18n I18N = new I18n(Constants.TRANSLATIONS_BUNDLE); 063 064 /** The log. */ 065 private static final Logger log = LoggerFactory.getLogger(HTTPControllerClient.class); 066 067 068 /** 069 * Make an HTTP controller client. Commands are sent using redirect on the given http response object. For commands 070 * with no output, the page is then forwarded to the response url. 071 * 072 * @param response The response object to use for redirect. 073 * @param out The JspWriter used to communicate with the users. 074 * @param returnURL The URL to return to afterwards if no output is given. This must not be null or not empty if 075 * either startRecordingURIs, stopRecordingURIs, changeIndex or clearRecordedURIs are called. 076 */ 077 public HTTPControllerClient(HttpServletResponse response, JspWriter out, String returnURL) { 078 ArgumentNotValid.checkNotNull(response, "HttpServletResponse response"); 079 ArgumentNotValid.checkNotNull(out, "JspWriter out"); 080 081 this.response = response; 082 this.out = out; 083 this.returnURL = returnURL; 084 } 085 086 /** Start recording URIs and return to return URL. */ 087 public void startRecordingURIs() { 088 redirectForSimpleCommand(HTTPControllerServer.START_COMMAND, true); 089 } 090 091 /** Stop recording URIs and return to return URL. */ 092 public void stopRecordingURIs() { 093 String command = HTTPControllerServer.STOP_COMMAND; 094 redirectForSimpleCommand(command, true); 095 } 096 097 /** Clear recorded URIs and return to return URL. */ 098 public void clearRecordedURIs() { 099 redirectForSimpleCommand(HTTPControllerServer.CLEAR_COMMAND, true); 100 } 101 102 /** 103 * Perform the necessary redirection to execute a simple (parameterless) command. Checks, that the returnURL is 104 * neither null or not empty. 105 * 106 * @param command One of the three parameterless commands START_COMMAND, 107 * @param useReturnURL Whether to append the returnURL parameter 108 */ 109 protected void redirectForSimpleCommand(String command, boolean useReturnURL) { 110 try { 111 String url = "http://" + CommandResolver.VIEWERPROXY_COMMAND_NAME + command; 112 if (useReturnURL) { 113 ArgumentNotValid.checkNotNullOrEmpty(returnURL, "String returnURL"); 114 url += '?' + HTTPControllerServer.RETURN_URL_PARAMETER + '=' + HTMLUtils.encode(returnURL); 115 } 116 response.sendRedirect(url); 117 } catch (IOException e) { 118 throw new IOFailure("Unable to redirect to controller server", e); 119 } 120 } 121 122 /** 123 * Write recorded URIs to response. NOTE! This does not respect the Controller! The URIs are *not* returned! 124 * 125 * @return null in all cases. The URIs are written in response by the forwarded call instead. 126 */ 127 public Set<URI> getRecordedURIs() { 128 redirectForSimpleCommand(HTTPControllerServer.GET_RECORDED_URIS_COMMAND, false); 129 return null; 130 } 131 132 /** 133 * Change current index to work on these jobs. Then return to returnURL. 134 * <p> 135 * Since post data cannot be transferred through a regular redirect, we instead build a page that uses javascript to 136 * immediately repost the data to the url. 137 * 138 * @param jobList The list of jobs. 139 * @param label An arbitrary label that will be used to indicate this index 140 */ 141 public void changeIndex(Set<Long> jobList, String label) { 142 ArgumentNotValid.checkNotNull(jobList, "Set jobList"); 143 ArgumentNotValid.checkNotNullOrEmpty(label, "label"); 144 ArgumentNotValid.checkNotNullOrEmpty(returnURL, "String returnURL"); 145 StringBuffer url = new StringBuffer("http://" + CommandResolver.VIEWERPROXY_COMMAND_NAME 146 + HTTPControllerServer.CHANGE_INDEX_COMMAND); 147 log.info("Changing index to index for jobs {}, label {}, returnurl {}, url {}", StringUtils.conjoin(",", jobList), label, returnURL, url.toString()); 148 try { 149 out.println("<html><head><title>"); 150 out.println(I18N.getString(response.getLocale(), "redirecting")); 151 out.println("</title></head>"); 152 out.println("<body onload='document" + ".getElementById(\"form\").submit();'>"); 153 out.println("<form action=\"" + HTMLUtils.escapeHtmlValues(url.toString()) 154 + "\" method=\"POST\" id=\"form\">"); 155 out.println("<input type='hidden' name='" + HTTPControllerServer.RETURN_URL_PARAMETER + "' value='" 156 + HTMLUtils.escapeHtmlValues(returnURL) + "'/>"); 157 for (Long jobId : jobList) { 158 out.println("<input type='hidden' name='" + HTTPControllerServer.JOB_ID_PARAMETER + "' value='" + jobId 159 + "'/>"); 160 } 161 out.println("<input type='hidden' name='" + HTTPControllerServer.INDEX_LABEL_PARAMETER + "' value='" 162 + HTMLUtils.escapeHtmlValues(label) + "'/>"); 163 out.println("</form>"); 164 out.println("<p>"); 165 out.println(I18N.getString(response.getLocale(), "generating.index.0.for.jobs.1", 166 HTMLUtils.escapeHtmlValues(label), StringUtils.conjoin(", ", jobList))); 167 out.println("</body></html>"); 168 } catch (IOException e) { 169 throw new IOFailure("Unable to redirect to controller server", e); 170 } 171 } 172 173 /** 174 * Write the current status of viewerproxy to response. NOTE! This does not respect the Controller API! The URIs are 175 * *not* returned! 176 * 177 * @param locale The locale (da, en, ...) that the response should be written using. 178 * @return null. The status is written in response by the forwarded call instead. 179 */ 180 public String getStatus(Locale locale) { 181 ArgumentNotValid.checkNotNull(locale, "locale"); 182 try { 183 response.sendRedirect("http://" + CommandResolver.VIEWERPROXY_COMMAND_NAME 184 + HTTPControllerServer.GET_STATUS_COMMAND + "?" + HTTPControllerServer.LOCALE_PARAMETER + "=" 185 + HTMLUtils.encode(locale.toString())); 186 } catch (IOException e) { 187 throw new IOFailure("Unable to redirect to controller server", e); 188 } 189 return null; 190 } 191}