package org.objectweb.celtix.js.rhino;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.ws.Endpoint;
import org.w3c.dom.Node;
import org.apache.xmlbeans.XmlObject;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.Wrapper;
public abstract class AbstractDOMProvider {
public static class JSDOMProviderException extends Exception {
public JSDOMProviderException(String reason) {
super(reason);
}
}
public static final String NO_WSDL_LOCATION = "no wsdlLocation property found";
public static final String NO_SERVICE_NAME = "no serviceName property found";
public static final String NO_PORT_NAME = "no portName property found";
public static final String NO_TGT_NAMESPACE = "no targetNamespace property found";
public static final String NO_INVOKE = "no invoke property found";
public static final String ILLEGAL_INVOKE_TYPE = "invoke property is not a Function type";
public static final String NO_EP_ADDR = "no endpoint address specified";
private Scriptable scriptScope;
private Scriptable webSvcProviderVar;
private String epAddress;
private boolean isBaseAddr;
private boolean isE4X;
private Function invokeFunc;
protected AbstractDOMProvider(Scriptable scope,
Scriptable wspVar, String epAddr,
boolean isBase, boolean e4x) {
scriptScope = scope;
webSvcProviderVar = wspVar;
epAddress = epAddr;
isBaseAddr = isBase;
isE4X = e4x;
}
public void publish() throws Exception {
String addr = epAddress;
String wsdlLoc = null;
String svcNm = null;
String portNm = null;
String tgtNmspc = null;
String binding = null;
Object obj = webSvcProviderVar.get("wsdlLocation", webSvcProviderVar);
if (obj == Scriptable.NOT_FOUND) {
throw new JSDOMProviderException(NO_WSDL_LOCATION);
}
if (obj instanceof String) {
wsdlLoc = (String)obj;
}
obj = webSvcProviderVar.get("serviceName", webSvcProviderVar);
if (obj == Scriptable.NOT_FOUND) {
throw new JSDOMProviderException(NO_SERVICE_NAME);
}
if (obj instanceof String) {
svcNm = (String)obj;
}
obj = webSvcProviderVar.get("portName", webSvcProviderVar);
if (obj == Scriptable.NOT_FOUND) {
throw new JSDOMProviderException(NO_PORT_NAME);
}
if (obj instanceof String) {
portNm = (String)obj;
}
obj = webSvcProviderVar.get("targetNamespace", webSvcProviderVar);
if (obj == Scriptable.NOT_FOUND) {
throw new JSDOMProviderException(NO_TGT_NAMESPACE);
}
if (obj instanceof String) {
tgtNmspc = (String)obj;
}
if (addr == null) {
obj = webSvcProviderVar.get("EndpointAddress", scriptScope);
if (obj != Scriptable.NOT_FOUND && obj instanceof String) {
addr = (String)obj;
isBaseAddr = false;
}
}
if (addr == null) {
throw new JSDOMProviderException(NO_EP_ADDR);
}
if (isBaseAddr) {
if (addr.endsWith("/")) {
addr += portNm;
} else {
addr = addr + "/" + portNm;
}
}
obj = webSvcProviderVar.get("BindingType", scriptScope);
if (obj != Scriptable.NOT_FOUND && obj instanceof String) {
binding = (String)obj;
}
obj = webSvcProviderVar.get("invoke", webSvcProviderVar);
if (obj == Scriptable.NOT_FOUND) {
throw new JSDOMProviderException(NO_INVOKE);
}
if (obj instanceof Function) {
invokeFunc = (Function)obj;
} else {
throw new JSDOMProviderException(ILLEGAL_INVOKE_TYPE);
}
Endpoint ep = Endpoint.create(binding, this);
List<Source> metadata = new ArrayList<Source>();
metadata.add(new StreamSource(wsdlLoc));
ep.setMetadata(metadata);
Map<String, Object> props = new HashMap<String, Object>();
props.put(Endpoint.WSDL_SERVICE, new QName(tgtNmspc, svcNm));
props.put(Endpoint.WSDL_PORT, new QName(tgtNmspc, portNm));
ep.setProperties(props);
ep.publish(addr);
}
public DOMSource invoke(DOMSource request) {
DOMSource response = new DOMSource();
Context cx = Context.enter();
try {
Scriptable scope = cx.newObject(scriptScope);
scope.setPrototype(scriptScope);
scope.setParentScope(null);
Node node = request.getNode();
Object inDoc = null;
if (isE4X) {
try {
Object xo = XmlObject.Factory.parse(node);
inDoc = Context.toObject(xo, scope);
Object[] args = {inDoc};
inDoc = cx.newObject(scriptScope, "XML", args);
} catch (Exception ex) {
ex.printStackTrace();
}
} else {
inDoc = Context.toObject(node, scope);
}
Object[] args = {inDoc};
Object jsResp = invokeFunc.call(cx, scope, scope, args);
if (isE4X) {
// need to check return type and throw exception
// if wrong type
Scriptable s = (Scriptable)jsResp;
Object out = ScriptableObject.callMethod(s,
"getXmlObject",
Context.emptyArgs);
Wrapper wrapped = (Wrapper)out;
XmlObject xml = (XmlObject)wrapped.unwrap();
node = xml.getDomNode();
response.setNode(node.getOwnerDocument());
} else {
if (jsResp instanceof Wrapper) {
jsResp = ((Wrapper)jsResp).unwrap();
}
if (jsResp instanceof Node) {
node = (Node)jsResp;
response.setNode(node);
}
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
Context.exit();
}
return response;
}
}