001: package org.objectweb.celtix.tools.processors.wsdl2.internal;
002:
003: import java.util.HashMap;
004: import java.util.Iterator;
005: import java.util.List;
006: import java.util.Map;
007: import java.util.logging.Level;
008:
009: import javax.jws.soap.SOAPBinding;
010: import javax.wsdl.Fault;
011: import javax.wsdl.Message;
012: import javax.wsdl.Operation;
013: import javax.wsdl.OperationType;
014: import javax.wsdl.Part;
015: import javax.xml.namespace.QName;
016:
017: import org.objectweb.celtix.common.util.StringUtils;
018: import org.objectweb.celtix.tools.common.ProcessorEnvironment;
019: import org.objectweb.celtix.tools.common.ToolConstants;
020: import org.objectweb.celtix.tools.common.ToolException;
021: import org.objectweb.celtix.tools.common.model.JavaAnnotation;
022: import org.objectweb.celtix.tools.common.model.JavaInterface;
023: import org.objectweb.celtix.tools.common.model.JavaMethod;
024: import org.objectweb.celtix.tools.common.model.JavaParameter;
025: import org.objectweb.celtix.tools.common.model.JavaReturn;
026: import org.objectweb.celtix.tools.extensions.jaxws.CustomizationParser;
027: import org.objectweb.celtix.tools.extensions.jaxws.JAXWSBinding;
028: import org.objectweb.celtix.tools.utils.ProcessorUtil;
029: import org.objectweb.celtix.tools.utils.SOAPBindingUtil;
030:
031: public class OperationProcessor extends AbstractProcessor {
032:
033: private JavaParameter wrapperRequest;
034: private JavaParameter wrapperResponse;
035:
036: public OperationProcessor(ProcessorEnvironment penv) {
037: super (penv);
038: }
039:
040: @SuppressWarnings("unchecked")
041: public void process(JavaInterface intf, Operation operation)
042: throws ToolException {
043: JavaMethod method = new JavaMethod(intf);
044: method.setName(ProcessorUtil.mangleNameToVariableName(operation
045: .getName()));
046: method.setOperationName(operation.getName());
047: method.setStyle(operation.getStyle());
048: if (method.getStyle() == null) {
049: if (operation.getOutput() == null) {
050: method.setStyle(OperationType.ONE_WAY);
051: } else {
052: method.setStyle(OperationType.REQUEST_RESPONSE);
053: }
054: }
055:
056: method.setWrapperStyle(isWrapperStyle(operation));
057: method.setJAXWSBinding(customizing(intf, operation));
058: processMethod(method, operation);
059: Map<String, Fault> faults = operation.getFaults();
060: FaultProcessor faultProcessor = new FaultProcessor(env);
061: faultProcessor.process(method, faults);
062:
063: intf.addMethod(method);
064: }
065:
066: @SuppressWarnings("unchecked")
067: public void processMethod(JavaMethod method, Operation operation)
068: throws ToolException {
069: List<String> parameterOrder = operation.getParameterOrdering();
070: Message inputMessage = operation.getInput() == null ? null
071: : operation.getInput().getMessage();
072: Message outputMessage = operation.getOutput() == null ? null
073: : operation.getOutput().getMessage();
074:
075: if (inputMessage == null) {
076: LOG.log(Level.WARNING, "NO_INPUT_MESSAGE",
077: new Object[] { operation.getName(),
078: operation.getInput().getName() });
079: }
080:
081: ParameterProcessor paramProcessor = new ParameterProcessor(env);
082: method.clear();
083: paramProcessor.process(method, inputMessage, outputMessage,
084: isRequestResponse(operation), parameterOrder);
085: isWrapperStyle(operation);
086: addWebMethodAnnotation(method);
087: addWrapperAnnotation(method, operation);
088: addWebResultAnnotation(method);
089: addSOAPBindingAnnotation(method);
090: if (!method.isOneWay()
091: && method.getJAXWSBinding().isEnableAsyncMapping()) {
092: addAsyncMethod(method);
093: }
094: }
095:
096: private void addSOAPBindingAnnotation(JavaMethod method) {
097: if (method.getSoapStyle() == SOAPBinding.Style.DOCUMENT
098: && !method.isWrapperStyle()) {
099: JavaAnnotation bindingAnnotation = new JavaAnnotation(
100: "SOAPBinding");
101: bindingAnnotation.addArgument("parameterStyle",
102: SOAPBindingUtil.getBindingAnnotation("BARE"), "");
103: method.addAnnotation("SOAPBinding", bindingAnnotation);
104: }
105: }
106:
107: private void addWebMethodAnnotation(JavaMethod method) {
108: addWebMethodAnnotation(method, method.getOperationName());
109: }
110:
111: private void addWebMethodAnnotation(JavaMethod method,
112: String operationName) {
113: JavaAnnotation methodAnnotation = new JavaAnnotation(
114: "WebMethod");
115: methodAnnotation.addArgument("operationName", operationName);
116: if (!StringUtils.isEmpty(method.getSoapAction())) {
117: methodAnnotation.addArgument("action", method
118: .getSoapAction());
119: }
120: method.addAnnotation("WebMethod", methodAnnotation);
121: method.getInterface().addImport("javax.jws.WebMethod");
122: }
123:
124: private void addWebResultAnnotation(JavaMethod method) {
125: if (method.isOneWay()) {
126: JavaAnnotation oneWayAnnotation = new JavaAnnotation(
127: "Oneway");
128: method.addAnnotation("Oneway", oneWayAnnotation);
129: method.getInterface().addImport("javax.jws.Oneway");
130: return;
131: }
132:
133: if ("void".equals(method.getReturn().getType())) {
134: return;
135: }
136: JavaAnnotation resultAnnotation = new JavaAnnotation(
137: "WebResult");
138: String targetNamespace = method.getReturn()
139: .getTargetNamespace();
140: String name = "return";
141:
142: if (method.getSoapStyle() == SOAPBinding.Style.DOCUMENT
143: && !method.isWrapperStyle()) {
144: name = method.getName() + "Response";
145: }
146:
147: if (method.getSoapStyle() == SOAPBinding.Style.RPC) {
148: name = method.getReturn().getName();
149: targetNamespace = method.getInterface().getNamespace();
150: }
151: if (method.getSoapStyle() == SOAPBinding.Style.DOCUMENT) {
152: if (method.getReturn().getQName() != null) {
153: name = method.getReturn().getQName().getLocalPart();
154: }
155: targetNamespace = method.getReturn().getTargetNamespace();
156: }
157:
158: resultAnnotation.addArgument("name", name);
159: resultAnnotation
160: .addArgument("targetNamespace", targetNamespace);
161:
162: if (method.getSoapStyle() == SOAPBinding.Style.RPC
163: || (method.getSoapStyle() == SOAPBinding.Style.DOCUMENT && !method
164: .isWrapperStyle())) {
165: resultAnnotation.addArgument("partName", method.getReturn()
166: .getName());
167: }
168:
169: method.addAnnotation("WebResult", resultAnnotation);
170: method.getInterface().addImport("javax.jws.WebResult");
171: }
172:
173: protected void addWrapperAnnotation(JavaMethod method,
174: Operation operation) {
175: if (!isWrapperStyle(operation)) {
176: return;
177: }
178:
179: if (wrapperRequest != null) {
180: JavaAnnotation wrapperRequestAnnotation = new JavaAnnotation(
181: "RequestWrapper");
182: wrapperRequestAnnotation.addArgument("localName",
183: wrapperRequest.getType());
184: wrapperRequestAnnotation.addArgument("targetNamespace",
185: wrapperRequest.getTargetNamespace());
186: wrapperRequestAnnotation.addArgument("className",
187: wrapperRequest.getClassName());
188: method.addAnnotation("RequestWrapper",
189: wrapperRequestAnnotation);
190: method.getInterface().addImport(
191: "javax.xml.ws.RequestWrapper");
192: }
193: if (wrapperResponse != null) {
194: JavaAnnotation wrapperResponseAnnotation = new JavaAnnotation(
195: "ResponseWrapper");
196: wrapperResponseAnnotation.addArgument("localName",
197: wrapperResponse.getType());
198: wrapperResponseAnnotation.addArgument("targetNamespace",
199: wrapperResponse.getTargetNamespace());
200: wrapperResponseAnnotation.addArgument("className",
201: wrapperResponse.getClassName());
202: method.addAnnotation("ResponseWrapper",
203: wrapperResponseAnnotation);
204: method.getInterface().addImport(
205: "javax.xml.ws.ResponseWrapper");
206: }
207:
208: }
209:
210: @SuppressWarnings("unchecked")
211: private boolean isWrapperStyle(Operation operation) {
212:
213: Message inputMessage = operation.getInput() == null ? null
214: : operation.getInput().getMessage();
215: Message outputMessage = operation.getOutput() == null ? null
216: : operation.getOutput().getMessage();
217:
218: Map<String, Part> inputParts = new HashMap<String, Part>();
219: Map<String, Part> outputParts = new HashMap<String, Part>();
220:
221: if (inputMessage != null) {
222: inputParts = inputMessage.getParts();
223: }
224: if (outputMessage != null) {
225: outputParts = outputMessage.getParts();
226: }
227:
228: //
229: // RULE No.1:
230: // The operation's input and output message (if present) each contain only a single part
231: //
232: if (inputParts.size() > 1 || outputParts.size() > 1) {
233: return false;
234: }
235:
236: //
237: // RULE No.2:
238: // The input message part refers to a global element decalration whose localname
239: // is equal to the operation name
240: //
241: Part inputPart = null;
242: if (inputParts.size() == 1) {
243: inputPart = inputParts.values().iterator().next();
244: if (inputPart != null) {
245: QName inputElement = inputPart.getElementName();
246: if (inputElement == null) {
247: return false;
248: } else if (!operation.getName().equals(
249: inputElement.getLocalPart())) {
250: return false;
251: }
252: }
253: }
254: //
255: // RULE No.3:
256: // The output message part refers to a global element decalration
257: //
258: Part outputPart = null;
259: if (outputParts.size() == 1) {
260: outputPart = outputParts.values().iterator().next();
261: if (outputPart != null) {
262: QName outputElement = outputPart.getElementName();
263: if (outputElement == null) {
264: return false;
265: }
266: }
267: }
268:
269: //
270: // RULE No.4 and No5:
271: // wrapper element should be pure complex type
272: //
273: if (ProcessorUtil.getBlock(inputPart, env) == null
274: || ProcessorUtil.getBlock(outputPart, env) == null) {
275: return false;
276: }
277:
278: if (inputPart != null) {
279: wrapperRequest = new JavaParameter();
280: wrapperRequest.setName(ProcessorUtil
281: .resolvePartName(inputPart));
282: wrapperRequest
283: .setType(ProcessorUtil.getPartType(inputPart));
284: wrapperRequest.setTargetNamespace(ProcessorUtil
285: .resolvePartNamespace(inputPart));
286:
287: wrapperRequest.setClassName(ProcessorUtil.getFullClzName(
288: inputPart, this .env, this .collector));
289:
290: }
291: if (outputPart != null) {
292: wrapperResponse = new JavaParameter();
293: wrapperResponse.setName(ProcessorUtil
294: .resolvePartName(outputPart));
295: wrapperResponse.setType(ProcessorUtil
296: .getPartType(outputPart));
297: wrapperResponse.setTargetNamespace(ProcessorUtil
298: .resolvePartNamespace(outputPart));
299:
300: wrapperResponse.setClassName(ProcessorUtil.getFullClzName(
301: outputPart, this .env, this .collector));
302:
303: }
304:
305: return true;
306: }
307:
308: private boolean isRequestResponse(Operation operation) {
309: if (operation.getStyle() == null) {
310: return operation.getOutput() != null;
311: }
312: return OperationType.REQUEST_RESPONSE.equals(operation
313: .getStyle());
314: }
315:
316: private JAXWSBinding customizing(JavaInterface intf,
317: Operation operation) {
318: JAXWSBinding binding = null;
319: List extElements = operation.getExtensibilityElements();
320: if (extElements.size() > 0) {
321: Iterator iterator = extElements.iterator();
322: while (iterator.hasNext()) {
323: Object obj = iterator.next();
324: if (obj instanceof JAXWSBinding) {
325: binding = (JAXWSBinding) obj;
326: }
327: }
328: } else {
329: String portTypeName = intf.getWebServiceName();
330: String operationName = operation.getName();
331: binding = CustomizationParser.getInstance()
332: .getPortTypeOperationExtension(portTypeName,
333: operationName);
334: }
335:
336: if (binding == null) {
337: binding = new JAXWSBinding();
338: }
339: if (!binding.isSetAsyncMapping()
340: && (intf.getJavaModel().getJAXWSBinding()
341: .isEnableAsyncMapping() || intf
342: .getJAXWSBinding().isEnableAsyncMapping())) {
343: binding.setEnableAsyncMapping(true);
344: }
345: return binding;
346: }
347:
348: private void addAsyncMethod(JavaMethod method) throws ToolException {
349: addPollingMethod(method);
350: addCallbackMethod(method);
351:
352: method.getInterface().addImport("javax.xml.ws.AsyncHandler");
353: method.getInterface().addImport("java.util.concurrent.Future");
354: method.getInterface().addImport("javax.xml.ws.Response");
355: }
356:
357: private void addPollingMethod(JavaMethod method)
358: throws ToolException {
359: JavaMethod pollingMethod = new JavaMethod(method.getInterface());
360: pollingMethod.setName(method.getName()
361: + ToolConstants.ASYNC_METHOD_SUFFIX);
362: pollingMethod.setStyle(method.getStyle());
363: pollingMethod.setWrapperStyle(method.isWrapperStyle());
364: pollingMethod.setSoapAction(method.getSoapAction());
365:
366: JavaReturn future = new JavaReturn();
367: future.setClassName("Future<?>");
368: pollingMethod.setReturn(future);
369:
370: addWebMethodAnnotation(pollingMethod, method.getOperationName());
371: pollingMethod.addAnnotation("ResponseWrapper", method
372: .getAnnotationMap().get("ResponseWrapper"));
373: pollingMethod.addAnnotation("RequestWrapper", method
374: .getAnnotationMap().get("RequestWrapper"));
375: pollingMethod.addAnnotation("SOAPBinding", method
376: .getAnnotationMap().get("SOAPBinding"));
377:
378: for (Iterator iter = method.getParameters().iterator(); iter
379: .hasNext();) {
380: pollingMethod.addParameter((JavaParameter) iter.next());
381: }
382:
383: JavaParameter asyncHandler = new JavaParameter();
384: asyncHandler.setName("asyncHandler");
385: asyncHandler.setClassName(getAsyncClassName(method,
386: "AsyncHandler"));
387: JavaAnnotation asyncHandlerAnnotation = new JavaAnnotation(
388: "WebParam");
389: asyncHandlerAnnotation.addArgument("name", "asyncHandler");
390: asyncHandlerAnnotation.addArgument("targetNamespace", "");
391: asyncHandler.setAnnotation(asyncHandlerAnnotation);
392:
393: pollingMethod.addParameter(asyncHandler);
394:
395: method.getInterface().addMethod(pollingMethod);
396: }
397:
398: private void addCallbackMethod(JavaMethod method)
399: throws ToolException {
400: JavaMethod callbackMethod = new JavaMethod(method
401: .getInterface());
402: callbackMethod.setName(method.getName()
403: + ToolConstants.ASYNC_METHOD_SUFFIX);
404: callbackMethod.setStyle(method.getStyle());
405: callbackMethod.setWrapperStyle(method.isWrapperStyle());
406: callbackMethod.setSoapAction(method.getSoapAction());
407:
408: JavaReturn response = new JavaReturn();
409: response.setClassName(getAsyncClassName(method, "Response"));
410: callbackMethod.setReturn(response);
411:
412: addWebMethodAnnotation(callbackMethod, method
413: .getOperationName());
414: callbackMethod.addAnnotation("RequestWrapper", method
415: .getAnnotationMap().get("RequestWrapper"));
416: callbackMethod.addAnnotation("ResponseWrapper", method
417: .getAnnotationMap().get("ResponseWrapper"));
418: callbackMethod.addAnnotation("SOAPBinding", method
419: .getAnnotationMap().get("SOAPBinding"));
420:
421: for (Iterator iter = method.getParameters().iterator(); iter
422: .hasNext();) {
423: callbackMethod.addParameter((JavaParameter) iter.next());
424: }
425:
426: method.getInterface().addMethod(callbackMethod);
427: }
428:
429: private String getAsyncClassName(JavaMethod method, String clzName) {
430: String response;
431: if (wrapperResponse != null) {
432: response = wrapperResponse.getClassName();
433: } else {
434: response = method.getReturn().getClassName();
435: }
436:
437: StringBuffer sb = new StringBuffer();
438: sb.append(clzName);
439: sb.append("<");
440: sb.append(response);
441: sb.append(">");
442: return sb.toString();
443: }
444: }
|