package sample;
import java.net.*;
import java.io.*;
import java.util.Random;
import java.util.Properties;
import org.apache.log4j.*;
import com.intentia.ec.server.DocServer;
import com.intentia.ec.utility.Base64;
import com.intentia.ec.shared.IMessageSender;
import com.intentia.ec.shared.MessageSenderException;
import com.intentia.ec.shared.Manifest;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
import javax.net.ssl.HttpsURLConnection;
public class HTTPSOut implements IMessageSender {
// Property constants
/* Property for the host of the http server. */
public static final String HOST = "Host";
/* Property for the path of the POST-request. */
public static final String PATH = "Path";
/* Property for the user. */
public static final String USER = "User";
/* Property for the password. */
public static final String PASSWORD = "Password";
/* Property for the port of the http server. */
public static final String PORT = "Port";
/* Property for the trusted certificate store path. */
public static final String TRUST_STORE = "Trust store";
/* Property for the trusted certificate store password. */
public static final String TRUST_STORE_PWD = "Trust store pwd";
static Category cat = Category.getInstance
(HTTPSOut.class.getName());
// Create a boundary for the mulitiparts.
private static Random random = new Random();
String boundary = "---------------------------" +
Long.toString(random.nextLong(), 36) +
Long.toString(random.nextLong(), 36) +
Long.toString(random.nextLong(), 36);
/**
* Sends a message according to the properties in sendGroup.
* @param inStream The input stream to read the message from.
* @param manifest The delivery note
* @param props Container holding the send properties.
* @throws MessageSenderException
*/
public void send(InputStream inStream, Manifest manifest,
Properties props) throws MessageSenderException {
// Extract the needed properties.
int port = 0;
try {
port = Integer.parseInt(props.getProperty(PORT));
}
catch (Exception e) {
throw new MessageSenderException("Invalid port number: "
+ props.getProperty(PORT));}
String host = props.getProperty(HOST);
String path = props.getProperty(PATH);
String user = props.getProperty(USER);
String pwd = props.getProperty(PASSWORD);
String trustedStore = props.getProperty(TRUST_STORE);
String trustedStorePwd = props.getProperty(TRUST_STORE_PWD);
// Set the system properties for the certificate stores.
System.setProperty("javax.net.ssl.trustStore", trustedStore);
System.setProperty("javax.net.ssl.trustStorePassword",
trustedStorePwd);
path = path == null ? "/" : path;
if (!path.startsWith("/")) path = "/" + path;
user = user == null || user.length() == 0 ? null : user;
pwd = pwd == null || pwd.length() == 0 ? null : pwd;
URL url = null;
ClientHttpRequest client = null;
HttpsURLConnection urlConn = null;
//Build the URL
String strURL = "https://" + host + ":" + port + path;
try {
// Create the url object.
url = new URL(strURL);
// Get the URLConnection from the URL. Since the protocol
// is https we will be returned a HttpsURLConnection.
urlConn = (HttpsURLConnection)url.openConnection();
urlConn.setDoInput(true);
urlConn.setDoOutput(false);
urlConn.setUseCaches(false);
// During the SSL handshake the host specified host name
// will be verified against the certificate. This
// implementation accept whatever specified
// in the certificate.
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String s, SSLSession sslSession) {
return true;
}
};
urlConn.setHostnameVerifier(hv);
// Create the helper class for posting a message as multi-part.
client = new ClientHttpRequest(urlConn);
// If the user is specified, we encode the user and
// password as Base64.
if (user != null && user.length() > 0 && pwd !=
null && pwd.length() > 0)
{String to64 = user + ":" + ((pwd == null) ? "" : pwd);
urlConn.setRequestProperty("Authorization: Basic",
Base64.encode (to64, "ISO-8859-1"));}
urlConn.setRequestProperty("User-Agent",
"Movex Enterprise Collaborator v" + DocServer.VERSION);
client.setParameter("name", "output.xml", inStream);
// Posts the http message.
client.post();
}
catch (MalformedURLException e) {
String msg = "The message could not be written to
http address: " + strURL; msg += ".\nThe address does not
seems to be in a correct http-format.";
throw new MessageSenderException(msg, e);
}
catch (UnknownHostException e) {
String msg = "The message could not be written to
http address: " + strURL; msg += ".\nCould not
find the host.";
throw new MessageSenderException(msg, e);
}
catch (SocketException e) {
String msg = "The message could not be written to
http address: " + strURL; msg += ".\nFailed to connect
to host. Please verify that the host
is up and running.";
throw new MessageSenderException(msg, e);
}
catch (IOException e) {
String msg = "The message could not be written to
http address: " + strURL; msg += ".\nError while reading
or writing message.";
throw new MessageSenderException(msg, e);
}
finally {
// Make sure everything gets closed.
urlConn.disconnect();
try {
urlConn.getOutputStream().close();
}
catch (Exception e) {}
try {
urlConn.getInputStream().close();
}
catch (Exception e) {}
}
}
/**
* Helper class for creating a multi-part http message.
*/
protected class ClientHttpRequest {
URLConnection connection;
OutputStream os = null;
private ClientHttpRequest(URLConnection connection) {
this.connection = connection;
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type",
"multipart/form-data; boundary=" + boundary);
}
private void connect() throws IOException {
if (os == null) os = connection.getOutputStream();
}
private void write(char c) throws IOException {
connect();
os.write(c);
}
private void write(String s) throws IOException {
connect();
os.write(s.getBytes());
}
private void newline() throws IOException {
connect();
write("\r\n");
}
private void writeln(String s) throws IOException {
connect();
write(s);
newline();
}
private void boundary() throws IOException {
write("--");
write(boundary);
}
private void writeName(String name) throws IOException {
newline();
write("Content-Disposition: form-data; name=\"");
write(name);
write('"');
}
private void pipe(InputStream in) throws IOException {
connect();
byte[] buf = new byte[5000];
int nread;
synchronized (in) {
while ((nread = in.read(buf, 0, buf.length)) >= 0) {
os.write(buf, 0, nread);
}
}
os.flush();
buf = null;
}
public void setParameter(String name, String filename,
InputStream is)
throws IOException {
boundary();
writeName(name);
write("; filename=\"");
write(filename);
write('"');
newline();
write("Content-Type: ");
String type = connection.guessContentTypeFromName(filename);
if (type == null) type = "application/octet-stream";
writeln(type);
newline();
pipe(is);
newline();
}
public void post() throws IOException {
boundary();
writeln("--");
}
}
}