package com.vuzit;
import java.net.HttpURLConnection;
import java.io.InputStream;
import org.w3c.dom.*;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
/**
* Vuzit web client base class.
*/
public abstract class Base
{
/**
* Returns the child node text value of an element.
*/
protected static String nodeValue(Element element, String childName)
{
String result = null;
NodeList nameList = element.getElementsByTagName(childName);
if(nameList.getLength() > 0)
{
Element nameElement = (Element)nameList.item(0);
NodeList textList = nameElement.getChildNodes();
if(textList.getLength() > 0) {
result = ((Node)textList.item(0)).getNodeValue().trim();
}
}
return result;
}
/**
* Returns the child node integer value of an element.
*/
protected static int nodeValueInt(Element element, String childName)
{
String text = nodeValue(element, childName);
return (text == null) ? -1 : Integer.parseInt(text);
}
/**
* Returns the child node long value of an element.
*/
protected static long nodeValueLong(Element element, String childName)
{
String text = nodeValue(element, childName);
return (text == null) ? -1 : Long.parseLong(text);
}
/**
* Returns a HTTP connection based upon the URL and request method.
*/
protected static HttpURLConnection httpConnection(String url, String method)
{
HttpURLConnection result = null;
try {
java.net.URL address = new java.net.URL(url);
// Set the SSL parameters if needed
if(url.startsWith("https://")) {
com.vuzit.TrustManager xtm = new com.vuzit.TrustManager();
TrustManager tm[] = { xtm };
javax.net.ssl.SSLContext ctx = javax.net.ssl.SSLContext.getInstance("SSL");
ctx.init(null, tm, null);
javax.net.ssl.SSLSocketFactory sf = ctx.getSocketFactory();
javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sf);
}
result = (HttpURLConnection)address.openConnection();
result.setRequestProperty("User-agent", Service.getUserAgent());
result.setRequestMethod(method);
result.setDoOutput(true);
// 60 second timeout to prevent timeouts with large requests,
// a busy server or IIS delays
result.setReadTimeout(60 * 1000);
} catch (java.net.MalformedURLException e) {
e.printStackTrace();
} catch (java.net.ProtocolException e) {
e.printStackTrace();
} catch (java.security.NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (java.security.KeyManagementException e) {
e.printStackTrace();
} catch (java.io.IOException e) {
e.printStackTrace();
}
return result;
}
/**
* Converts a set of parameters to a URL.
*/
protected static String parametersToUrl(String baseUrl, OptionList params)
{
StringBuilder result = new StringBuilder();
result.append(Service.getServiceUrl()).append("/");
result.append(baseUrl).append("?");
for(java.util.Enumeration e = params.keys(); e.hasMoreElements() ;)
{
String key = (String)e.nextElement();
String value = (String)params.get(key);
// Do not add keys with null or empty values
// TODO: Check the length of the string as well
if(value != null)
{
try {
result.append(key).append("=");
value = java.net.URLEncoder.encode(value, "UTF-8");
result.append(value);
result.append("&");
}
catch(java.io.UnsupportedEncodingException uee) {
System.err.println(uee);
}
}
}
return result.toString();
}
/**
* Returns the default HTTP post parameters array.
*/
protected static OptionList postParameters(OptionList options, String method, String id)
{
// The keys must be set before this can function
if(Service.getPublicKey() == null) {
throw new ClientException("The public key cannot be null");
}
if(Service.getPrivateKey() == null) {
throw new ClientException("The private key cannot be null");
}
options.add("method", method);
options.add("key", Service.getPublicKey());
java.util.Date now = new java.util.Date();
String signature = Service.signature(method, id, now, options);
options.add("signature", signature);
options.add("timestamp", Long.toString(Service.epochTime(now)));
return options;
}
/**
* Uploads a file via an HTTP post operation. Returns the stream response
* from the HTTP server.
*/
protected static InputStream uploadFile(InputStream stream, String url,
String fileFormName, String contentType,
String fileName)
{
InputStream result = null;
java.io.DataOutputStream dos = null;
java.io.DataInputStream inStream = null;
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1 * 1024 * 1024;
if(contentType == null) {
contentType = "application/octet-stream";
}
HttpURLConnection connection = httpConnection(url, "POST");
try
{
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
// Set the timeout to 5 minutes since it's possibly a large file
connection.setReadTimeout(5 * 60 * 1000);
dos = new java.io.DataOutputStream(connection.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"" + fileFormName + "\";"
+ " filename=\"" + fileName +"\"" + lineEnd);
dos.writeBytes(lineEnd);
// Create a buffer of maximum size
bytesAvailable = stream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// Read file and write it into form...
bytesRead = stream.read(buffer, 0, bufferSize);
while (bytesRead > 0)
{
dos.write(buffer, 0, bufferSize);
bytesAvailable = stream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = stream.read(buffer, 0, bufferSize);
}
// Send multipart form data necesssary after file data...
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
stream.close();
dos.flush();
dos.close();
} catch(java.io.IOException ex) {
}
try {
result = connection.getInputStream();
} catch(java.io.IOException ex) {
result = null;
}
return result;
}
/**
* Traps and extracts web client errors for debugging purposes.
*/
protected static void webClientErrorCheck(HttpURLConnection connection)
{
org.w3c.dom.Document doc;
try
{
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
doc = docBuilder.parse(connection.getErrorStream());
doc.getDocumentElement().normalize();
}
catch(Exception e)
{
e.printStackTrace();
return;
}
NodeList errorList = doc.getElementsByTagName("err");
if(errorList.getLength() > 0)
{
Element errorNode = (Element)errorList.item(0);
throw new ClientException(nodeValue(errorNode, "msg"),
nodeValue(errorNode, "code"));
}
}
/**
* Loads the defined root node from a block of XML. Returns null if there is
* an issue or the root node could not be found.
*/
protected static Element xmlRootNode(InputStream stream, String nodeName)
{
Element result = null;
try {
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
org.w3c.dom.Document doc = docBuilder.parse(stream);
doc.getDocumentElement().normalize();
NodeList docList = doc.getElementsByTagName(nodeName);
for(int i = 0; i < docList.getLength(); i++)
{
Node firstNode = docList.item(i);
if(firstNode.getNodeType() == Node.ELEMENT_NODE)
{
result = (Element)firstNode;
break;
}
}
}
catch(Exception ex)
{
result = null;
}
return result;
}
}