/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.vfny.geoserver.wfs.servlets;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLDecoder;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.codec.binary.Base64;
import org.geoserver.config.GeoServer;
import org.geoserver.ows.util.ResponseUtils;
import org.geoserver.platform.GeoServerExtensions;
import org.geotools.util.logging.Logging;
/**
* Simple tester for WFS post requests. Can be called two ways. If called with
* no parameters, it displays the form, otherwise it displays the result page.
*
* @author Doug Cates: Moxi Media Inc.
* @version 1.0
*/
public class TestWfsPost extends HttpServlet {
/**
* The path at which TestWfsPost is exposed. Used to find the full location of GeoServer
* without doing complex and error prone string building
*/
static final String TEST_WFS_POST_PATH = "/TestWfsPost";
static final Logger LOGGER = Logging.getLogger(TestWfsPost.class);
/**
* Initializes the servlet.
*
* @param config DOCUMENT ME!
*
* @throws ServletException DOCUMENT ME!
*/
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
/**
* Destroys the servlet.
*/
public void destroy() {
}
/**
* Handles the HTTP <code>GET</code> method.
*
* @param request servlet request
* @param response servlet response
*
* @throws ServletException DOCUMENT ME!
* @throws IOException DOCUMENT ME!
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Handles the HTTP <code>POST</code> method.
*
* @param request servlet request
* @param response servlet response
*
* @throws ServletException DOCUMENT ME!
* @throws IOException DOCUMENT ME!
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Returns a short description of the servlet.
*
* @return DOCUMENT ME!
*/
public String getServletInfo() {
return "Tests a WFS post request using a form entry.";
}
/**
* Processes requests for both HTTP <code>GET</code> and <code>POST</code>
* methods.
*
* @param request servlet request
* @param response servlet response
*
* @throws ServletException DOCUMENT ME!
* @throws IOException DOCUMENT ME!
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String requestString = request.getParameter("body");
String urlString = request.getParameter("url");
boolean doGet = (requestString == null) || requestString.trim().equals("");
if ((urlString == null)) {
PrintWriter out = response.getWriter();
StringBuffer urlInfo = request.getRequestURL();
if (urlInfo.indexOf("?") != -1) {
urlInfo.delete(urlInfo.indexOf("?"), urlInfo.length());
}
String geoserverUrl = urlInfo.substring(0, urlInfo.indexOf("/", 8))
+ request.getContextPath();
response.setContentType("text/html");
out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">");
out.println("<html>");
out.println("<head>");
out.println("<title>TestWfsPost</title>");
out.println("</head>");
out.println("<script language=\"JavaScript\">");
out.println("function doNothing() {");
out.println("}");
out.println("function sendRequest() {");
out.println(" if (checkURL()==true) {");
out.print(" document.frm.action = \"");
out.print(urlInfo.toString());
out.print("\";\n");
out.println(" document.frm.target = \"_blank\";");
out.println(" document.frm.submit();");
out.println(" }");
out.println("}");
out.println("function checkURL() {");
out.println(" if (document.frm.url.value==\"\") {");
out.println(" alert(\"Please give URL before you sumbit this form!\");");
out.println(" return false;");
out.println(" } else {");
out.println(" return true;");
out.println(" }");
out.println("}");
out.println("function clearRequest() {");
out.println("document.frm.body.value = \"\";");
out.println("}");
out.println("</script>");
out.println("<body>");
out.println("<form name=\"frm\" action=\"JavaScript:doNothing()\" method=\"POST\">");
out.println("<table align=\"center\" cellspacing=\"2\" cellpadding=\"2\" border=\"0\">");
out.println("<tr>");
out.println("<td><b>URL:</b></td>");
out.print("<td><input name=\"url\" value=\"");
out.print(geoserverUrl);
out.print("/wfs/GetFeature\" size=\"70\" MAXLENGTH=\"100\"/></td>\n");
out.println("</tr>");
out.println("<tr>");
out.println("<td><b>Request:</b></td>");
out.println("<td><textarea cols=\"60\" rows=\"24\" name=\"body\"></textarea></td>");
out.println("</tr>");
out.println("</table>");
out.println("<table align=\"center\">");
out.println("<tr>");
out.println(
"<td><input type=\"button\" value=\"Clear\" onclick=\"clearRequest()\"></td>");
out.println(
"<td><input type=\"button\" value=\"Submit\" onclick=\"sendRequest()\"></td>");
out.println("<td></td>");
out.println("</tr>");
out.println("</table>");
out.println("</form>");
out.println("</body>");
out.println("</html>");
out.close();
} else {
response.setContentType("application/xml");
BufferedReader xmlIn = null;
PrintWriter xmlOut = null;
StringBuffer sbf = new StringBuffer();
String resp = null;
try {
URL u = new URL(urlString);
validateURL(request, urlString, getProxyBaseURL() );
java.net.HttpURLConnection acon = (java.net.HttpURLConnection) u.openConnection();
acon.setAllowUserInteraction(false);
if (!doGet) {
//System.out.println("set to post");
acon.setRequestMethod("POST");
acon.setRequestProperty("Content-Type", "application/xml");
} else {
//System.out.println("set to get");
acon.setRequestMethod("GET");
}
acon.setDoOutput(true);
acon.setDoInput(true);
acon.setUseCaches(false);
//SISfixed - if there was authentication info in the request,
// Pass it along the way to the target URL
//DJB: applied patch in GEOS-335
String authHeader = request.getHeader("Authorization");
String username = request.getParameter("username");
if ((username != null) && !username.trim().equals("")) {
String password = request.getParameter("password");
String up = username + ":" + password;
byte[] encoded = Base64.encodeBase64(up.getBytes());
authHeader = "Basic " + new String(encoded);
}
if (authHeader != null) {
acon.setRequestProperty("Authorization", authHeader);
}
if (!doGet) {
xmlOut = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(acon.getOutputStream())));
xmlOut = new java.io.PrintWriter(acon.getOutputStream());
xmlOut.write(requestString);
xmlOut.flush();
}
// Above 400 they're all error codes, see:
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
if (acon.getResponseCode() >= 400) {
PrintWriter out = response.getWriter();
out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
out.println("<servlet-exception>");
out.println("HTTP response: " + acon.getResponseCode() + "\n"
+ URLDecoder.decode(acon.getResponseMessage(), "UTF-8"));
out.println("</servlet-exception>");
out.close();
} else {
// xmlIn = new BufferedReader(new InputStreamReader(
// acon.getInputStream()));
// String line;
// System.out.println("got encoding from acon: "
// + acon.getContentType());
response.setContentType(acon.getContentType());
response.setHeader("Content-disposition",
acon.getHeaderField("Content-disposition"));
OutputStream output = response.getOutputStream();
int c;
InputStream in = acon.getInputStream();
while ((c = in.read()) != -1)
output.write(c);
in.close();
output.close();
}
//while ((line = xmlIn.readLine()) != null) {
// out.print(line);
//}
} catch (Exception e) {
LOGGER.log(Level.FINE, "Failure dealing with the request", e);
PrintWriter out = response.getWriter();
out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
out.println("<servlet-exception>");
out.println(ResponseUtils.encodeXML(e.toString()));
out.println("</servlet-exception>");
out.close();
} finally {
try {
if (xmlIn != null) {
xmlIn.close();
}
} catch (Exception e1) {
LOGGER.log(Level.FINE, "Internal failure dealing with the request", e1);
PrintWriter out = response.getWriter();
out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
out.println("<servlet-exception>");
out.println(ResponseUtils.encodeXML(e1.toString()));
out.println("</servlet-exception>");
out.close();
}
try {
if (xmlOut != null) {
xmlOut.close();
}
} catch (Exception e2) {
LOGGER.log(Level.FINE, "Internal failure dealing with the request", e2);
PrintWriter out = response.getWriter();
out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
out.println("<servlet-exception>");
out.println(ResponseUtils.encodeXML(e2.toString()));
out.println("</servlet-exception>");
out.close();
}
}
}
}
String getProxyBaseURL() {
GeoServer geoServer = (GeoServer) GeoServerExtensions.bean("geoServer");
if( geoServer != null ){
geoServer.getGlobal().getSettings().getProxyBaseUrl();
}
return null;
}
void validateURL(HttpServletRequest request, String url, String proxyBase) {
if(proxyBase != null) {
if(!url.startsWith(proxyBase)) {
throw new IllegalArgumentException("Invalid url requested, the demo requests should be hitting: " + proxyBase);
}
} else {
// use the requested url then, and remove the TestWfsPort
String requestedUrl = request.getRequestURL().toString();
// this should not happen, but let's not make it an open proxy if it does
if(!requestedUrl.endsWith(TEST_WFS_POST_PATH)) {
throw new IllegalStateException("Unepected, the TestWfsPost was accessed by a path not ending with TestWfsPost: " + requestedUrl);
}
String base = requestedUrl.substring(0, requestedUrl.lastIndexOf(TEST_WFS_POST_PATH));
if(!url.startsWith(base)) {
throw new IllegalArgumentException("Invalid url requested, the demo requests should be hitting: " + base);
}
}
}
}