package org.myrobotlab.net;
/* Originally com.myjavatools.web; from http://www.devx.com/Java/Article/17679/1954 and heavily modified by Morgan Schweers */
/* Original license: http://www.myjavatools.com/license.txt */
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Random;
/**
* FIXME - Buffer the post with ByteArrayOutputStream so you dont need to write
* to the real output stream until you call the method post(new
* URL("http://blah/blah));
*
* and move to the Http class
*
*
*
* Description: this class helps to send POST HTTP requests with various form
* data, * including files. Cookies can be added to be included in the request.
*
*
* @author Vlad Patryshev
* @author Morgan Schweers
* @version 1.1
*/
public class HttpPost {
private URLConnection mConnection;
private OutputStream mOutput = null;
private Map mCookies = new HashMap();
private Map<String, Object> mParameters = new LinkedHashMap<String, Object>();
private String boundary;
private static Random random = new Random();
private static void pipe(InputStream in, OutputStream out) throws IOException {
byte[] buf = new byte[50000];
int nread;
while ((nread = in.read(buf, 0, buf.length)) >= 0) {
out.write(buf, 0, nread);
}
out.flush();
}
private static String randomString() {
return Long.toString(random.nextLong(), 36);
}
/**
* Creates a new multipart POST HTTP request for a specified URL
*
* @param url
* the URL to send request to
*/
public HttpPost(URL url) throws IOException {
this(url.openConnection());
}
/**
* Creates a new multipart POST HTTP request on a freshly opened URLConnection
*
* @param connection
* an already open URL connection
*/
public HttpPost(URLConnection connection) {
mConnection = connection;
((HttpURLConnection) mConnection).setInstanceFollowRedirects(true);
connection.setDoOutput(true);
boundary = "---------------------------" + randomString() + randomString() + randomString();
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
}
private void boundary() throws IOException {
write("--");
write(boundary);
}
private void newline() throws IOException {
write("\r\n");
}
/**
* posts the requests to the server, with all the cookies and parameters that
* were added
*
* @return input stream with the server response
*/
public HttpURLConnection post() throws IOException {
if (mOutput == null)
mOutput = mConnection.getOutputStream();
postCookies();
for (String key : mParameters.keySet()) {
Object value = mParameters.get(key);
if (value instanceof File)
writeParameter(key, (File) value);
else
writeParameter(key, value.toString());
}
boundary();
writeln("--");
mOutput.close();
return (HttpURLConnection) mConnection;
}
/**
* Creates a new multipart POST HTTP request for a specified URL string
*
* @ param urlString the string representation of the URL to send request to
*/
// public ClientHttpRequest(String urlString) throws IOException { this(new
// URL(urlString)); }
private void postCookies() {
StringBuffer cookieList = new StringBuffer();
for (Iterator i = mCookies.entrySet().iterator(); i.hasNext();) {
Map.Entry entry = (Map.Entry) (i.next());
cookieList.append(entry.getKey().toString()).append("=").append(entry.getValue());
if (i.hasNext()) {
cookieList.append("; ");
}
}
if (cookieList.length() > 0) {
mConnection.setRequestProperty("Cookie", cookieList.toString());
}
}
/**
* adds a parameter to the request; if the parameter is a File, the file is
* uploaded, otherwise the string value of the parameter is passed in the
* request
*
* @param name
* parameter name
* @param value
* parameter value, a File or anything else that can be stringified
*/
public void setParameter(String name, Object value) {
mParameters.put(name, value);
}
/**
* adds parameters to the request
*
* @param parameters
* "name-to-value" map of parameters; if a value is a file, the file
* is uploaded, otherwise it is stringified and sent in the request
*/
public void setParameters(Map parameters) {
if (parameters == null)
return;
mParameters.putAll(parameters);
}
private void write(char c) throws IOException {
mOutput.write(c);
}
private void write(String s) throws IOException {
mOutput.write(s.getBytes());
}
private void writeln(String s) throws IOException {
write(s);
newline();
}
private void writeName(String name) throws IOException {
newline();
write("Content-Disposition: form-data; name=\"");
write(name);
write('"');
}
/**
* adds a file parameter to the request
*
* @param name
* parameter name
* @param file
* the file to upload
*/
private void writeParameter(String name, File file) throws IOException {
writeParameter(name, file.getPath(), new FileInputStream(file));
}
/**
* adds a string parameter to the request
*
* @param name
* parameter name
* @param value
* parameter value
*/
private void writeParameter(String name, String value) throws IOException {
boundary();
writeName(name);
newline();
newline();
writeln(value);
}
/**
* adds a file parameter to the request
*
* @param name
* parameter name
* @param filename
* the name of the file
* @param is
* input stream to read the contents of the file from
*/
public void writeParameter(String name, String filename, InputStream is) throws IOException {
boundary();
writeName(name);
write("; filename=\"");
write(filename);
write('"');
newline();
write("Content-Type: ");
String type = URLConnection.guessContentTypeFromName(filename);
if (type == null)
type = "application/octet-stream";
writeln(type);
newline();
pipe(is, mOutput);
newline();
}
}