|
|||||||||||||||||||
| 30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover | |||||||||||||||||||
| Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
| BexeeProvider.java | 54.5% | 48.8% | 57.1% | 50.4% |
|
||||||||||||||
| 1 |
/*
|
|
| 2 |
* $Id: BexeeProvider.java,v 1.1 2004/12/15 14:18:15 patforna Exp $
|
|
| 3 |
*
|
|
| 4 |
* Copyright (c) 2004 Patric Fornasier, Pawel Kowalski
|
|
| 5 |
* Berne University of Applied Sciences
|
|
| 6 |
* School of Engineering and Information Technology
|
|
| 7 |
* All rights reserved.
|
|
| 8 |
*/
|
|
| 9 |
package bexee.axis;
|
|
| 10 |
|
|
| 11 |
import java.util.HashMap;
|
|
| 12 |
import java.util.Iterator;
|
|
| 13 |
import java.util.Map;
|
|
| 14 |
import java.util.Vector;
|
|
| 15 |
|
|
| 16 |
import javax.wsdl.Definition;
|
|
| 17 |
import javax.wsdl.WSDLException;
|
|
| 18 |
import javax.wsdl.factory.WSDLFactory;
|
|
| 19 |
import javax.wsdl.xml.WSDLWriter;
|
|
| 20 |
import javax.xml.namespace.QName;
|
|
| 21 |
import javax.xml.soap.SOAPException;
|
|
| 22 |
|
|
| 23 |
import org.apache.axis.AxisFault;
|
|
| 24 |
import org.apache.axis.Message;
|
|
| 25 |
import org.apache.axis.MessageContext;
|
|
| 26 |
import org.apache.axis.description.OperationDesc;
|
|
| 27 |
import org.apache.axis.description.ServiceDesc;
|
|
| 28 |
import org.apache.axis.handlers.soap.SOAPService;
|
|
| 29 |
import org.apache.axis.message.RPCElement;
|
|
| 30 |
import org.apache.axis.message.RPCParam;
|
|
| 31 |
import org.apache.axis.message.SOAPEnvelope;
|
|
| 32 |
import org.apache.axis.providers.BasicProvider;
|
|
| 33 |
import org.w3c.dom.Document;
|
|
| 34 |
import org.w3c.dom.Element;
|
|
| 35 |
import org.xml.sax.SAXException;
|
|
| 36 |
|
|
| 37 |
import bexee.core.BexeeMessage;
|
|
| 38 |
import bexee.core.Dispatcher;
|
|
| 39 |
import bexee.core.DispatcherException;
|
|
| 40 |
import bexee.dao.BPELProcessDAO;
|
|
| 41 |
import bexee.dao.DAOException;
|
|
| 42 |
import bexee.dao.DAOFactory;
|
|
| 43 |
import bexee.model.process.BPELProcess;
|
|
| 44 |
import bexee.wsdl.WSDLBindingFactory;
|
|
| 45 |
import bexee.wsdl.extensions.partnerlinktype.PartnerLinkTypeExtensionRegistry;
|
|
| 46 |
|
|
| 47 |
/**
|
|
| 48 |
* This is the Axis provider (also commonly called pivot handler) used by all
|
|
| 49 |
* deployed BPEL process web services.
|
|
| 50 |
* <p>
|
|
| 51 |
* This provider takes the incoming SOAP message, performs a number of checks
|
|
| 52 |
* (e.g. verifying whether the requested operation can actually be performed by
|
|
| 53 |
* our <code>ProcessController</code>), puts all the necessary information
|
|
| 54 |
* into a new <code>BexeeMessage</code> and dispatches it to
|
|
| 55 |
* <code>Dispatcher</code>.
|
|
| 56 |
* <p>
|
|
| 57 |
* As soon as the provider receives the result back from the dispatcher, it will
|
|
| 58 |
* create a new SOAP response and hand it back to the Axis response flow, from
|
|
| 59 |
* where it will eventually be sent back to the client that invoked the service.
|
|
| 60 |
*
|
|
| 61 |
* @version $Revision: 1.1 $, $Date: 2004/12/15 14:18:15 $
|
|
| 62 |
* @author Patric Fornasier
|
|
| 63 |
* @author Pawel Kowalski
|
|
| 64 |
*/
|
|
| 65 |
public class BexeeProvider extends BasicProvider { |
|
| 66 |
|
|
| 67 |
/**
|
|
| 68 |
* The default URL for services
|
|
| 69 |
*/
|
|
| 70 |
private static final String DEFAULT_SERVICES_URL = "http://localhost/bexee/services/"; |
|
| 71 |
|
|
| 72 | 44 |
public void initServiceDesc(SOAPService service, MessageContext msgContext) |
| 73 |
throws AxisFault {
|
|
| 74 |
// nothing to do here
|
|
| 75 |
} |
|
| 76 |
|
|
| 77 |
/**
|
|
| 78 |
* Creates a <code>BexeeMessage</code> from an incoming SOAP message and
|
|
| 79 |
* passes it to the {@link Dispatcher}from where it will be dispatched to
|
|
| 80 |
* the {@link bexee.core.ProcessController}.
|
|
| 81 |
* <p>
|
|
| 82 |
* Once the processing is completed, the result from the {@link Dispatcher}
|
|
| 83 |
* is taken and put back into a SOAP message and passed back into the Axis
|
|
| 84 |
* response flow.
|
|
| 85 |
* <p>
|
|
| 86 |
* Right now and Object of type {@link Element}is passed back into the
|
|
| 87 |
* response flow, because we don't generate Java objects from complex XML
|
|
| 88 |
* types.
|
|
| 89 |
* <p>
|
|
| 90 |
* TODO: This class needs some work, especially the message type stuff
|
|
| 91 |
* (possible improvements: code generation from wsdl, serializing and
|
|
| 92 |
* deserializing into Java objects)
|
|
| 93 |
*/
|
|
| 94 | 12 |
public void invoke(MessageContext ctx) throws AxisFault { |
| 95 |
|
|
| 96 | 12 |
RPCElement body = null;
|
| 97 | 12 |
String operation = null;
|
| 98 |
|
|
| 99 |
// initialize some variables
|
|
| 100 | 12 |
String service = ctx.getTargetService(); |
| 101 | 12 |
SOAPEnvelope reqEnv = ctx.getRequestMessage().getSOAPEnvelope(); |
| 102 | 12 |
ServiceDesc serviceDesc = ctx.getService().getServiceDescription(); |
| 103 | 12 |
OperationDesc operationDesc = ctx.getOperation(); |
| 104 |
|
|
| 105 |
// find the first 'root' body element, which is the RPC call
|
|
| 106 | 12 |
Vector bodies = reqEnv.getBodyElements(); |
| 107 | 12 |
for (int i = 0; body == null && i < bodies.size(); i++) { |
| 108 | 12 |
if (bodies.get(i) instanceof RPCElement) { |
| 109 | 12 |
body = (RPCElement) bodies.get(i); |
| 110 |
} |
|
| 111 |
} |
|
| 112 |
|
|
| 113 |
// if we didn't find anything, throw an exception
|
|
| 114 | 12 |
if (body == null) { |
| 115 | 0 |
throw new AxisFault("No RPCElement found in SOAP message"); |
| 116 |
} |
|
| 117 |
|
|
| 118 |
// check if that service provides the requested operation
|
|
| 119 | 12 |
if (operationDesc == null) { |
| 120 | 2 |
QName qname = new QName(body.getNamespaceURI(), body.getName());
|
| 121 | 2 |
operationDesc = serviceDesc.getOperationByElementQName(qname); |
| 122 |
} |
|
| 123 |
|
|
| 124 |
// if not, throw an exception
|
|
| 125 | 12 |
if (operationDesc == null) { |
| 126 | 2 |
throw new AxisFault("No such operation"); |
| 127 |
} |
|
| 128 |
|
|
| 129 |
// get RPC parameters (parts) (checks also for too many params)
|
|
| 130 | 10 |
Vector params = null;
|
| 131 | 10 |
try {
|
| 132 | 10 |
params = body.getParams(); |
| 133 |
} catch (SAXException e) {
|
|
| 134 | 2 |
throw new AxisFault("Possible cause: too many parameters", e); |
| 135 |
} |
|
| 136 |
|
|
| 137 |
// check if enough params provided
|
|
| 138 | 8 |
if (operationDesc.getNumParams() > params.size()) {
|
| 139 | 2 |
throw new AxisFault("Wrong number of parameters passed in"); |
| 140 |
} |
|
| 141 |
|
|
| 142 |
// TODO check if parameter types match
|
|
| 143 |
|
|
| 144 |
// looks ok, get name of invoked operation
|
|
| 145 | 6 |
operation = body.getMethodName(); |
| 146 |
|
|
| 147 |
// create message for bexee engine and dispatch
|
|
| 148 | 6 |
BexeeMessage message = createBexeeMessage(service, operation, params); |
| 149 | 6 |
Object result; |
| 150 | 6 |
try {
|
| 151 | 6 |
result = dispatch(message); |
| 152 |
} catch (DispatcherException e) {
|
|
| 153 | 6 |
throw new AxisFault("Unable to dispatch message", e); |
| 154 |
} |
|
| 155 |
// create RPC response element
|
|
| 156 | 0 |
RPCElement resBody = new RPCElement(operation + "Response"); |
| 157 | 0 |
resBody.setPrefix(body.getPrefix()); |
| 158 | 0 |
resBody.setNamespaceURI(body.getNamespaceURI()); |
| 159 | 0 |
try {
|
| 160 | 0 |
resBody.setEncodingStyle(ctx.getEncodingStyle()); |
| 161 |
} catch (SOAPException e) {
|
|
| 162 | 0 |
throw AxisFault.makeFault(e);
|
| 163 |
} |
|
| 164 |
|
|
| 165 |
// create RPC parameter containing result and add it to result body
|
|
| 166 | 0 |
RPCParam param = new RPCParam(operationDesc.getReturnQName(), result);
|
| 167 | 0 |
resBody.addParam(param); |
| 168 |
|
|
| 169 |
// set up a SOAP envelope with appropriate SOAP and schema versions
|
|
| 170 | 0 |
SOAPEnvelope resEnv = new SOAPEnvelope();
|
| 171 | 0 |
resEnv.setSoapConstants(ctx.getSOAPConstants()); |
| 172 | 0 |
resEnv.setSchemaVersion(ctx.getSchemaVersion()); |
| 173 |
|
|
| 174 |
// add the result body to the SOAP response envelope
|
|
| 175 | 0 |
resEnv.addBodyElement(resBody); |
| 176 |
|
|
| 177 |
// create the response message and put it into the message context
|
|
| 178 | 0 |
ctx.setResponseMessage(new Message(resEnv));
|
| 179 |
} |
|
| 180 |
|
|
| 181 |
/**
|
|
| 182 |
* Gets WSDL associated with requested BPEL process from DAO and adds
|
|
| 183 |
* binding information on the fly.
|
|
| 184 |
* <p>
|
|
| 185 |
* If the target service endpoint URL can not be determined, a constant
|
|
| 186 |
* value with the default services root is assumed.
|
|
| 187 |
*/
|
|
| 188 | 0 |
public void generateWSDL(MessageContext ctx) throws AxisFault { |
| 189 |
|
|
| 190 |
// the WSDL Document
|
|
| 191 | 0 |
Document doc = null;
|
| 192 |
|
|
| 193 |
// get the service location url used for binding
|
|
| 194 | 0 |
String url = getLocationURL(ctx); |
| 195 |
|
|
| 196 |
// get WSDL from BPEL process
|
|
| 197 | 0 |
BPELProcessDAO dao = DAOFactory.getInstance().createBPELProcessDAO(); |
| 198 | 0 |
BPELProcess process; |
| 199 | 0 |
String name = getServiceName(ctx); |
| 200 | 0 |
try {
|
| 201 | 0 |
process = dao.find(name); |
| 202 |
} catch (DAOException e) {
|
|
| 203 | 0 |
throw new AxisFault("Error trying to find process", e); |
| 204 |
} |
|
| 205 |
|
|
| 206 | 0 |
if (process == null) { |
| 207 | 0 |
throw new AxisFault("No process " + name + " found"); |
| 208 |
} |
|
| 209 |
|
|
| 210 | 0 |
Definition wsdlAbstract = process.getWSDL(); |
| 211 |
|
|
| 212 | 0 |
try {
|
| 213 |
// add binding information to wsdl
|
|
| 214 | 0 |
WSDLBindingFactory bindingFactory = new WSDLBindingFactory();
|
| 215 | 0 |
Definition wsdl = bindingFactory.addBinding(wsdlAbstract, url); |
| 216 |
|
|
| 217 |
// convert into org.w3c.dom.Document
|
|
| 218 | 0 |
WSDLWriter writer = WSDLFactory.newInstance().newWSDLWriter(); |
| 219 | 0 |
wsdl.setExtensionRegistry(new PartnerLinkTypeExtensionRegistry());
|
| 220 | 0 |
doc = writer.getDocument(wsdl); |
| 221 |
} catch (WSDLException e) {
|
|
| 222 | 0 |
throw AxisFault.makeFault(e);
|
| 223 |
} |
|
| 224 |
|
|
| 225 |
// save WSDL Document in message context
|
|
| 226 | 0 |
ctx.setProperty("WSDL", doc);
|
| 227 |
} |
|
| 228 |
|
|
| 229 |
/**
|
|
| 230 |
* Gets the service location URL.
|
|
| 231 |
*
|
|
| 232 |
* @return a <code>String</code>
|
|
| 233 |
*/
|
|
| 234 | 0 |
protected String getLocationURL(MessageContext ctx) {
|
| 235 |
// location URL is whatever is explicitly set in the MC
|
|
| 236 | 0 |
String url = ctx.getStrProp(MessageContext.WSDLGEN_SERV_LOC_URL); |
| 237 |
|
|
| 238 |
// If nothing, try what's explicitly set in the ServiceDesc
|
|
| 239 | 0 |
if (url == null) { |
| 240 | 0 |
url = ctx.getService().getServiceDescription().getEndpointURL(); |
| 241 |
} |
|
| 242 |
|
|
| 243 |
// If nothing, use the actual transport URL
|
|
| 244 | 0 |
if (url == null) { |
| 245 | 0 |
url = ctx.getStrProp(MessageContext.TRANS_URL); |
| 246 |
} |
|
| 247 |
|
|
| 248 |
// if everything fails, hardcode it
|
|
| 249 | 0 |
if (url == null) { |
| 250 | 0 |
url = DEFAULT_SERVICES_URL + getServiceName(ctx); |
| 251 |
} |
|
| 252 |
|
|
| 253 | 0 |
return url;
|
| 254 |
} |
|
| 255 |
|
|
| 256 | 0 |
protected String getServiceName(MessageContext ctx) {
|
| 257 | 0 |
String name = ctx.getService().getServiceDescription().getName(); |
| 258 | 0 |
return name;
|
| 259 |
} |
|
| 260 |
|
|
| 261 |
/**
|
|
| 262 |
* Helper method to create the <code>BexeeMessage</code>
|
|
| 263 |
*/
|
|
| 264 | 6 |
protected BexeeMessage createBexeeMessage(String service, String operation,
|
| 265 |
Vector params) throws AxisFault {
|
|
| 266 |
|
|
| 267 | 6 |
BexeeMessage message = new BexeeMessage();
|
| 268 |
|
|
| 269 |
// create parts map
|
|
| 270 | 6 |
Map parts = new HashMap();
|
| 271 | 6 |
for (Iterator iter = params.iterator(); iter.hasNext();) {
|
| 272 | 18 |
RPCParam rpcParam = (RPCParam) iter.next(); |
| 273 |
|
|
| 274 |
// get the value out of the RPC param
|
|
| 275 | 18 |
Object value = rpcParam.getObjectValue(); |
| 276 |
|
|
| 277 |
// get the name we defined in the service description (we do not
|
|
| 278 |
// care how the parameter was really called in the RPC call)
|
|
| 279 | 18 |
String name = rpcParam.getParamDesc().getName(); |
| 280 |
|
|
| 281 |
// store object
|
|
| 282 | 18 |
parts.put(name, value); |
| 283 |
} |
|
| 284 |
|
|
| 285 |
// set fields on BexeeMessage
|
|
| 286 | 6 |
message.setService(service); |
| 287 | 6 |
message.setOperation(operation); |
| 288 | 6 |
message.setParts(parts); |
| 289 |
|
|
| 290 | 6 |
return message;
|
| 291 |
} |
|
| 292 |
|
|
| 293 |
/**
|
|
| 294 |
* Call dispatcher to kick off the process controller and return result
|
|
| 295 |
*
|
|
| 296 |
* @return the result from the {@link Dispatcher}
|
|
| 297 |
*/
|
|
| 298 | 6 |
protected Object dispatch(BexeeMessage message) throws DispatcherException { |
| 299 |
|
|
| 300 | 6 |
Dispatcher dispatcher = new Dispatcher(message);
|
| 301 | 6 |
return dispatcher.dispatch();
|
| 302 |
} |
|
| 303 |
|
|
| 304 |
} |
|
||||||||||