package gov.nist.registry.common2.soap;
import gov.nist.registry.common2.exception.HttpCodeException;
import gov.nist.registry.common2.exception.XdsInternalException;
import gov.nist.registry.common2.io.Io;
import gov.nist.registry.common2.registry.MetadataSupport;
import gov.nist.registry.common2.xml.Util;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMNamespace;
public class Swa {
String endpoint;
String protocol;
String service;
String port;
String host;
HttpURLConnection conn;
FilterInputStream in;
int response_code;
String response_content_type;
OMElement response;
HashMap<String, ArrayList<Object>> attachments = null;
String boundary = "MIMEBoundaryurn_uuid_30615C45AB8F5F79FF1200322399377";
String start = "0.urn:uuid:30615C45AB8F5F79FF1200322399378@nist.gov";
public Swa() {
}
void parse_endpoint() throws Exception {
String[] parts;
String rest;
parts = this.endpoint.split(":");
if (parts.length < 2)
throw new XdsInternalException("swa.parse_endpoint(): (" + endpoint + ") Cannot parse endpoint: cannot find http or https before :");
protocol = parts[0];
rest = endpoint.substring(protocol.length());
parts = rest.split("/");
if (parts.length < 4) {
StringBuffer buf = new StringBuffer();
for (int i=0; i<parts.length; i++)
buf.append(i + ") " + parts[i] + "\n");
throw new XdsInternalException("swa.parse_endpoint(): (" + endpoint + ") Cannot parse endpoint: cannot find machine and port (parts.length = " + parts.length +")\n" + buf.toString());
}
String host_port = parts[2];
this.service = "";
for (int i=3; i<parts.length; i++)
this.service += "/" + parts[i];
parts = host_port.split(":");
if (parts.length == 1) {
this.host = parts[0];
this.port = "80";
} else if (parts.length == 2) {
this.host = parts[0];
this.port = parts[1];
} else
throw new XdsInternalException("swa.parse_endpoint(): (" + endpoint + ") Cannot parse endpoint: cannot parse machine and port");
}
public void connect(String endpoint) throws Exception {
this.endpoint = endpoint;
parse_endpoint();
URL url = new URL(protocol, host, Integer.parseInt(port), service);
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
}
String getResponse()
throws HttpCodeException, IOException, XdsInternalException {
try {
String encoding =conn.getContentEncoding();
if (encoding == null) {
in = (FilterInputStream) conn.getInputStream();
} else {
Object o = conn.getContent();
in = (FilterInputStream) o;
}
} catch (java.io.IOException e) {
response_code = conn.getResponseCode();
//System.out.println("ERROR: code: " + String.valueOf(code) + " message: " + conn.getResponseMessage());
InputStream is = conn.getErrorStream();
if (is == null) {
String msg = conn.getResponseMessage();
URL url = conn.getURL();
conn.disconnect();
throw new XdsInternalException("Error retieving content of " + url.toString() + "; response was " + msg);
} else {
StringBuffer b = new StringBuffer();
byte[] by = new byte[256];
int cnt;
while ( (cnt=is.read(by, 0, 256)) > 0 )
b.append(new String(by, 0, cnt));
conn.disconnect();
String err_response = new String(b);
try {
OMElement err_xml = Util.parse_xml(err_response);
try {
in.close();
conn.disconnect();
} catch (Exception e2) {}
return err_response;
} catch (Exception e1 ) {
}
throw new HttpCodeException( "ERROR: HttpClient: code: " + String.valueOf(response_code)
+
"\nmessage: " + conn.getResponseMessage() +
"\n" + new String(b) + "\n"
);
}
}
response_content_type = conn.getHeaderField("Content-Type");
String rsp = Io.getStringFromInputStream(in);
in.close();
conn.disconnect();
return rsp;
}
public OMElement send(OMElement header_contents, OMElement body_contents) throws Exception {
OMNamespace soap = MetadataSupport.om_factory.createOMNamespace("http://schemas.xmlsoap.org/soap/envelope/", "soapenv");
OMElement envelope = MetadataSupport.om_factory.createOMElement("Envelope", soap);
OMElement header = MetadataSupport.om_factory.createOMElement("Header", soap);
OMElement body = MetadataSupport.om_factory.createOMElement("Body", soap);
if (header_contents != null)
header.addChild(header_contents);
if (body_contents != null)
body.addChild(body_contents);
envelope.addChild(header);
envelope.addChild(body);
return send(envelope);
}
public OMElement send(OMElement envelope) throws Exception {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("SOAPAction", "\"SubmitObjectsRequest\"");
if (attachments != null)
headers.put("Content-Type", "multipart/related; boundary=" + boundary + "; type=\"text/xml\"; start=\"<" + start + ">\"");
else
headers.put("Content-Type", "\"text/xml\"");
headers.put("User-Agent", "xdstest2");
StringBuffer msg = new StringBuffer();
if (attachments != null) {
msg.append("--" + boundary + "\r\n");
msg.append("Content-Type: text/xml; charset=UTF-8\r\n");
msg.append("Content-Transfer-Encoding: 8bit\r\n");
msg.append("Content-ID: <" + start + ">\r\n");
msg.append("\r\n");
}
msg.append(envelope.toString() + " \r\n");
if (attachments != null) {
for (String id : attachments.keySet()) {
ArrayList<Object> attachment = attachments.get(id);
byte[] content = (byte[]) attachment.get(0);
String mime_type = (String) attachment.get(1);
msg.append("\n--" + boundary + "\r\n");
msg.append("Content-Type: " + mime_type + "\r\n");
msg.append("Content-Transfer-Encoding: binary\r\n");
msg.append("Content-ID: <" + id + ">\r\n");
msg.append("\r\n");
msg.append(new String(content));
msg.append("\r\n");
}
msg.append("--" + boundary + "--\r\n");
}
String reply_str = post(headers, msg.toString());
OMElement reply_xml = Util.parse_xml(reply_str);
if (reply_xml == null || !reply_xml.getLocalName().equals("Envelope"))
throw new XdsInternalException("Reply is not SOAP Envelope: \n" + reply_str);
if (hasFault(reply_xml))
throw new XdsInternalException("Fault: " + getFaultMessage(reply_xml));
this.response = reply_xml;
return reply_xml;
}
boolean hasFault(OMElement reply) throws Exception {
OMElement body = MetadataSupport.firstChildWithLocalName(reply, "Body");
if (body == null)
throw new XdsInternalException("Swa: hasFault(): SOAP message has no body");
OMElement fault = MetadataSupport.firstChildWithLocalName(body, "Fault");
return fault != null;
}
String getFaultMessage(OMElement reply) {
OMElement body = MetadataSupport.firstChildWithLocalName(reply, "Body");
if (body == null) return "";
OMElement fault = MetadataSupport.firstChildWithLocalName(body, "Fault");
if (fault == null) return "";
OMElement faultstring = MetadataSupport.firstChildWithLocalName(fault, "faultstring");
if (faultstring == null) return "";
return faultstring.getText();
}
public String post(HashMap<String, String> headers, String body) throws Exception {
for (String name : headers.keySet()) {
String value = headers.get(name);
conn.setRequestProperty(name, value);
}
conn.setRequestProperty("Content-Length", String.valueOf(body.length()));
conn.connect();
OutputStream os = conn.getOutputStream();
os.write(body.getBytes());
os.close();
return getResponse();
}
public void addAttachment(byte[] content, String mime_type, String id) {
if (attachments == null)
attachments = new HashMap<String, ArrayList<Object>>();
ArrayList<Object> attachment = new ArrayList<Object>();
attachment.add(content);
attachment.add(mime_type);
attachments.put(id, attachment);
}
public OMElement getHeader() {
if (this.response == null)
return null;
return MetadataSupport.firstChildWithLocalName(this.response, "Header");
}
public OMElement getBody() {
if (this.response == null)
return null;
return MetadataSupport.firstChildWithLocalName(this.response, "Body");
}
}