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 }