/*******************************************************************************
* Copyright (c) 2008-2009, G. Weirich and Elexis
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* G. Weirich - initial implementation
*
*******************************************************************************/
package ch.rgw.tools;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.CharArrayReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import ch.rgw.crypt.Base64Coder;
/**
* We try to make a simple converter from and to SOAP without the huge overhead of Axis... This
* implementation deals only with a limited number of variable types.
*
* @author Gerry
*
*/
public class SoapConverter {
public static final Namespace ns = Namespace.getNamespace("soap",
"http://www.w3.org/2001/12/soap-envelope");
public static final String TYPE_STRING = "string";
public static final String TYPE_INTEGRAL = "integral";
public static final String TYPE_FLOAT = "float";
public static final String TYPE_ARRAY = "array";
public static final String TYPE_MAP = "map";
public static final String TYPE_SERIALIZED = "serializedPOJO";
public static final String TYPE_SIGNATURE = "signature";
private Document doc;
private Element eRoot;
private Element eBody;
private boolean bValid;
public SoapConverter(){}
public boolean load(byte[] input){
SAXBuilder builder = new SAXBuilder();
ByteArrayInputStream bais = new ByteArrayInputStream(input);
try {
doc = builder.build(bais);
eRoot = doc.getRootElement();
bValid = true;
} catch (Exception ex) {
ExHandler.handle(ex);
bValid = false;
}
return bValid;
}
public Document getXML(){
return doc;
}
public boolean load(String input){
SAXBuilder builder = new SAXBuilder();
try {
CharArrayReader car = new CharArrayReader(input.toCharArray());
doc = builder.build(car);
eRoot = doc.getRootElement();
bValid = true;
} catch (Exception e) {
ExHandler.handle(e);
bValid = false;
}
return bValid;
}
public Element getParameter(String name){
if (bValid) {
Element body = eRoot.getChild("Body", ns);
List<Element> params = body.getChildren("parameter", ns);
for (Element el : params) {
if (el.getAttributeValue("name").equalsIgnoreCase(name)) {
return el;
}
}
}
return null;
}
public Map<String, Serializable> loadHash(Element parm){
HashMap<String, Serializable> ret = new HashMap<String, Serializable>();
List<Element> params = parm.getChildren("parameter", ns);
for (Element param : params) {
String type = param.getAttributeValue("type");
String s = param.getText();
Serializable res = null;
try {
if (type.equals(TYPE_STRING)) {
res = s;
} else if (type.equals(TYPE_INTEGRAL)) {
res = Long.parseLong(s);
} else if (type.equals(TYPE_FLOAT)) {
res = Double.parseDouble(s);
} else if (type.equals(TYPE_ARRAY)) {
res = Base64Coder.decode(s);
} else if (type.equals(TYPE_MAP)) {
res = (Serializable) loadHash(param);
} else if (type.equals(TYPE_SERIALIZED)) {
byte[] barr = Base64Coder.decode(s);
ByteArrayInputStream bais = new ByteArrayInputStream(barr);
ObjectInputStream ois = new ObjectInputStream(bais);
res = (Serializable) ois.readObject();
bais.close();
ois.close();
} else {
res = "** unsupported type ** " + type;
}
} catch (Exception ex) {
ExHandler.handle(ex);
res = "** parse error **";
}
ret.put(param.getAttributeValue("name"), res);
}
return ret;
}
public Map<String, Serializable> getParameters(){
if (bValid) {
Element body = eRoot.getChild("Body", ns);
return loadHash(body);
}
return null;
}
public void create(String creator, String version, String provider){
eRoot = new Element("Envelope", ns);
Element eHeader = new Element("Header", ns);
Element eID = new Element("Creator", ns);
eID.setAttribute("name", creator);
eID.setAttribute("version", version);
eID.setAttribute("provider", provider);
eHeader.addContent(eID);
eRoot.addContent(eHeader);
eBody = new Element("Body", ns);
eRoot.addContent(eBody);
doc = new Document(eRoot);
bValid = true;
}
public String toString(){
if (doc != null && eRoot != null) {
Format format = Format.getPrettyFormat();
format.setEncoding("utf-8");
XMLOutputter xmlo = new XMLOutputter(format);
return xmlo.outputString(doc);
}
return null;
}
private Element createParameter(Element parent, String name, String type){
if (parent == null) {
parent = eBody;
}
Element ret = new Element("parameter", ns);
ret.setAttribute("type", type);
ret.setAttribute("name", name);
parent.addContent(ret);
return ret;
}
public void addString(String name, String s){
createParameter(eBody, name, TYPE_STRING).setText(s);
}
public void addIntegral(String name, long x){
createParameter(eBody, name, TYPE_INTEGRAL).setText(Long.toString(x));
}
public void addFloat(String name, double x){
createParameter(eBody, name, TYPE_FLOAT).setText(Double.toString(x));
}
public void addArray(String name, byte[] arr){
String res = new String(Base64Coder.encode(arr));
createParameter(eBody, name, TYPE_ARRAY).setText(res);
}
public void addObject(Element parent, String name, Serializable obj) throws Exception{
if (obj != null) {
if (obj instanceof String) {
createParameter(parent, name, TYPE_STRING).setText((String) obj);
} else if ((obj instanceof Double) || (obj instanceof Float)) {
createParameter(parent, name, TYPE_FLOAT).setText(Double.toString((Double) obj));
} else if ((obj instanceof Integer) || (obj instanceof Long) || (obj instanceof Byte)) {
createParameter(parent, name, TYPE_INTEGRAL).setText(obj.toString());
} else if (obj instanceof byte[]) {
String res = new String(Base64Coder.encode((byte[]) obj));
createParameter(parent, name, TYPE_ARRAY).setText(res);
} else if (obj instanceof HashMap) {
addMap(parent, name, (Map<String, Serializable>) obj);
} else if (obj instanceof Serializable) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(baos);
os.writeObject(obj);
os.close();
baos.close();
byte[] barr = baos.toByteArray();
createParameter(parent, name, TYPE_SERIALIZED).setText(
new String(Base64Coder.encode(barr)));
} else {
throw new Exception("Invalid type for SoapConverter: " + obj.getClass().getName());
}
}
}
public void addMap(Element parent, String name, Map<String, Serializable> map) throws Exception{
Element ret = createParameter(parent, name, TYPE_MAP);
Set<Entry<String, Serializable>> entries = map.entrySet();
for (Entry<String, Serializable> entry : entries) {
addObject(ret, entry.getKey(), entry.getValue());
}
}
}