001 /* 002 * LAPIS lightweight structured text processing system 003 * 004 * Copyright (C) 1998-2002 Carnegie Mellon University, 005 * Copyright (C) 2003 Massachusetts Institute of Technology. 006 * All rights reserved. 007 * 008 * This library is free software; you can redistribute it 009 * and/or modify it under the terms of the GNU General 010 * Public License as published by the Free Software 011 * Foundation, version 2. 012 * 013 * LAPIS homepage: http://graphics.lcs.mit.edu/lapis/ 014 */ 015 016 package lapisx.net; 017 018 import java.net.*; 019 import java.io.*; 020 import java.util.*; 021 import lapisx.util.Exec; 022 import lapisx.util.Debug; 023 024 public class LocalFormURL extends FormURL { 025 public static Debug debug = Debug.QUIET; 026 027 /** 028 * Create a query using a given method (get or post) and query data. 029 * @param method "get" or "post" (case-insensitive). 030 * @param url URL to send query to. Must be file: 031 * @param query Name/value pairs to simulate submitting a form. Names and values may be arbitrary objects; this method uses toString() to convert them to strings, then URL-encodes them before sending to the web server. Pass null if no form data is desired. 032 */ 033 public LocalFormURL (String method, URL url, Vector query) { 034 super (method, url, query); 035 } 036 037 /** 038 * Open a URL using a given method (get or post) and query data. 039 * @param method "get" or "post" (case-insensitive). 040 * @param url URL to open. Must be file: 041 * @param query URL-encoded name/value pairs, or null if no query desired 042 */ 043 public LocalFormURL (String method, URL url, String query) { 044 super (method, url, query); 045 } 046 047 /** 048 * Open a connection ready to submit query and retrieve its results. 049 * @return URLConnection (set up for connection but not yet connected) 050 */ 051 public URLConnection openConnection () throws IOException { 052 String protocol = url.getProtocol (); 053 if (!"file".equals (protocol)) 054 throw new IOException ("local form URL must be file:"); 055 056 CGIConnection conn = new CGIConnection (method, url); 057 058 // handle POST method 059 if ("post".equals (method)) { 060 conn.setDoOutput (true); 061 conn.setRequestProperty ("Content-type", 062 "application/x-www-form-urlencoded"); 063 conn.setRequestProperty ("Content-length", String.valueOf (queryString.length())); 064 065 // commence request 066 PrintWriter out = null; 067 try { 068 out = new PrintWriter (new OutputStreamWriter 069 (conn.getOutputStream ())); 070 out.print (queryString); 071 out.flush (); 072 } finally { 073 if (out != null) 074 out.close (); 075 } 076 } 077 078 conn.connect (); 079 return conn; 080 } 081 082 static class CGIConnection extends URLConnection { 083 Process process; 084 String method; 085 String contentType = "text/plain"; 086 long contentLength = 0; 087 088 public CGIConnection (String method, URL url) { 089 super (url); 090 this.method = (method != null) ? method.toUpperCase () : "GET"; 091 } 092 093 public void setRequestProperty (String name, String value) { 094 if ("Content-type".equalsIgnoreCase (name)) 095 contentType = value; 096 else if ("Content-length".equalsIgnoreCase (name)) 097 contentLength = Long.valueOf (value).longValue (); 098 } 099 100 public void connect () throws IOException { 101 if (connected) 102 return; 103 104 URL serviceURL = URLUtil.getServiceURL (this.url); 105 String command = serviceURL.getFile (); 106 String query = URLUtil.getQuery (this.url); 107 if (query.startsWith ("?")) 108 query = query.substring (1); 109 110 String[] env = { 111 "GATEWAY_INTERFACE=CGI/1.1", 112 "SERVER_SOFTWARE=LAPIS", 113 "SERVER_NAME=localhost", 114 "SERVER_PORT=0", 115 "REMOTE_ADDR=127.0.0.1", 116 "REMOTE_HOST=localhost", 117 "REQUEST_METHOD=" + method, 118 "CONTENT_LENGTH=" + contentLength, 119 "CONTENT_TYPE=" + contentType, 120 "SCRIPT_NAME=" + command, 121 "QUERY_STRING=" + query, 122 "SERVER_PROTOCOL=HTTP/1.1", 123 // "PATH_INFO=", 124 // "PATH_TRANSLATED=", 125 // "REMOTE_USER=", 126 // "AUTH_TYPE=" 127 }; 128 129 debug.println ("Connecting to " + this.url); 130 debug.println ("Executing local CGI script '" + command + "'"); 131 debug.println (lapisx.util.Str.join (env, "\n")); 132 133 process = Exec.exec (new String[] { command }, env); 134 connected = true; 135 136 // Close output stream if unneeded (to keep subprocess from reading from it) 137 if (!doOutput) 138 getOutputStream ().close (); 139 } 140 141 public InputStream getInputStream () throws IOException { 142 connect (); 143 return process.getInputStream (); 144 } 145 146 public OutputStream getOutputStream () throws IOException { 147 connect (); 148 return process.getOutputStream (); 149 } 150 151 } 152 }