/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.cxf.tools.wsdlto.frontend.jaxws.processor.internal; import java.util.Collection; import java.util.List; import java.util.logging.Level; import javax.jws.WebParam; import org.apache.cxf.common.jaxb.JAXBUtils; import org.apache.cxf.service.model.FaultInfo; import org.apache.cxf.service.model.MessageInfo; import org.apache.cxf.service.model.MessagePartInfo; import org.apache.cxf.service.model.OperationInfo; import org.apache.cxf.tools.common.ToolConstants; import org.apache.cxf.tools.common.ToolContext; import org.apache.cxf.tools.common.ToolException; import org.apache.cxf.tools.common.model.JAnnotation; import org.apache.cxf.tools.common.model.JAnnotationElement; import org.apache.cxf.tools.common.model.JavaInterface; import org.apache.cxf.tools.common.model.JavaMethod; import org.apache.cxf.tools.common.model.JavaParameter; import org.apache.cxf.tools.common.model.JavaReturn; import org.apache.cxf.tools.common.model.JavaType; import org.apache.cxf.tools.wsdlto.frontend.jaxws.customization.JAXWSBinding; import org.apache.cxf.tools.wsdlto.frontend.jaxws.processor.internal.annotator.WSActionAnnotator; import org.apache.cxf.tools.wsdlto.frontend.jaxws.processor.internal.annotator.WebMethodAnnotator; import org.apache.cxf.tools.wsdlto.frontend.jaxws.processor.internal.annotator.WebResultAnnotator; import org.apache.cxf.tools.wsdlto.frontend.jaxws.processor.internal.annotator.WrapperAnnotator; import org.apache.cxf.tools.wsdlto.frontend.jaxws.processor.internal.mapper.MethodMapper; public class OperationProcessor extends AbstractProcessor { private JavaParameter wrapperRequest; private JavaParameter wrapperResponse; public OperationProcessor(ToolContext c) { super(c); } public void process(JavaInterface intf, OperationInfo operation) throws ToolException { JavaMethod method = new MethodMapper().map(operation); method.setInterface(intf); processMethod(method, operation); Collection<FaultInfo> faults = operation.getFaults(); FaultProcessor faultProcessor = new FaultProcessor(context); faultProcessor.process(method, faults); method.annotate(new WSActionAnnotator(operation)); intf.addMethod(method); } void processMethod(JavaMethod method, OperationInfo operation) throws ToolException { if (isAsyncMethod(method)) { return; } MessageInfo inputMessage = operation.getInput(); MessageInfo outputMessage = operation.getOutput(); if (inputMessage == null) { LOG.log(Level.WARNING, "NO_INPUT_MESSAGE", new Object[] {operation.getName()}); org.apache.cxf.common.i18n.Message msg = new org.apache.cxf.common.i18n.Message("INVALID_MEP", LOG, new Object[] {operation.getName()}); throw new ToolException(msg); } ParameterProcessor paramProcessor = new ParameterProcessor(context); method.clear(); JAXWSBinding opBinding = operation.getExtensor(JAXWSBinding.class); JAXWSBinding ptBinding = operation.getInterface().getExtensor(JAXWSBinding.class); JAXWSBinding defBinding = operation.getInterface().getService() .getDescription().getExtensor(JAXWSBinding.class); boolean enableAsync = false; boolean enableMime = false; boolean enableWrapper = method.isWrapperStyle(); if (defBinding != null) { if (defBinding.isSetEnableMime()) { enableMime = defBinding.isEnableMime(); } if (defBinding.isSetEnableAsyncMapping()) { enableAsync = defBinding.isEnableAsyncMapping(); } if (defBinding.isSetEnableWrapperStyle()) { enableWrapper = defBinding.isEnableWrapperStyle(); } } if (ptBinding != null) { if (ptBinding.isSetEnableMime()) { enableMime = ptBinding.isEnableMime(); } if (ptBinding.isSetEnableAsyncMapping()) { enableAsync = ptBinding.isEnableAsyncMapping(); } if (ptBinding.isSetEnableWrapperStyle()) { enableWrapper = ptBinding.isEnableWrapperStyle(); } } if (opBinding != null) { if (opBinding.isSetEnableMime()) { enableMime = opBinding.isEnableMime(); } if (opBinding.isSetEnableAsyncMapping()) { enableAsync = opBinding.isEnableAsyncMapping(); } if (opBinding.isSetEnableWrapperStyle()) { enableWrapper = opBinding.isEnableWrapperStyle(); } } enableWrapper = checkEnableWrapper(enableWrapper, method); enableAsync = checkEnableAsync(enableAsync, method); enableMime = checkEnableMime(enableMime, method); method.setWrapperStyle(enableWrapper && method.isWrapperStyle()); paramProcessor.process(method, inputMessage, outputMessage, operation.getParameterOrdering()); if (method.isWrapperStyle()) { setWrapper(operation); method.annotate(new WrapperAnnotator(wrapperRequest, wrapperResponse)); } method.annotate(new WebMethodAnnotator()); method.annotate(new WebResultAnnotator()); if (!method.isOneWay() && enableAsync && !isAddedAsycMethod(method)) { addAsyncMethod(method); } if (enableMime) { method.setMimeEnable(true); } } private boolean checkArray(String[] ar, String n) { if (ar != null) { if (ar.length == 0) { return true; } for (String s : ar) { if (s.equals(n)) { return true; } } } return false; } private boolean checkEnableMime(boolean enableMime, JavaMethod method) { String o[] = context.getArray(ToolConstants.CFG_MIMEMETHODS); if (checkArray(o, method.getName())) { return true; } return enableMime; } private boolean checkEnableAsync(boolean enableAsync, JavaMethod method) { String o[] = context.getArray(ToolConstants.CFG_ASYNCMETHODS); if (checkArray(o, method.getName())) { return true; } return enableAsync; } private boolean checkEnableWrapper(boolean enableWrapper, JavaMethod method) { String o[] = context.getArray(ToolConstants.CFG_BAREMETHODS); if (checkArray(o, method.getName())) { return false; } return enableWrapper; } private void setWrapper(OperationInfo operation) { MessagePartInfo inputPart = null; if (operation.getInput() != null) { inputPart = operation.getInput().getFirstMessagePart(); } MessagePartInfo outputPart = null; if (operation.getOutput() != null) { outputPart = operation.getOutput().getFirstMessagePart(); } if (inputPart != null) { wrapperRequest = new JavaParameter(); wrapperRequest.setName(ProcessorUtil.resolvePartName(inputPart)); wrapperRequest.setType(ProcessorUtil.getPartType(inputPart)); wrapperRequest.setTargetNamespace(ProcessorUtil.resolvePartNamespace(inputPart)); wrapperRequest.setClassName(ProcessorUtil.getFullClzName(inputPart, context, false)); } if (outputPart != null) { wrapperResponse = new JavaParameter(); wrapperResponse.setName(ProcessorUtil.resolvePartName(outputPart)); wrapperResponse.setType(ProcessorUtil.getPartType(outputPart)); wrapperResponse.setTargetNamespace(ProcessorUtil.resolvePartNamespace(outputPart)); wrapperResponse.setClassName(ProcessorUtil.getFullClzName(outputPart, context, false)); } } private boolean isAsyncMethod(JavaMethod method) { if (method.getName().endsWith(ToolConstants.ASYNC_METHOD_SUFFIX) && method.getReturn() != null && method.getReturn().getClassName() != null) { if (method.getReturn().getClassName().startsWith("Response<")) { return true; } else if (method.getParameterCount() > 0 && method.getParameters().get(method.getParameterCount() - 1) .getClassName().startsWith("AsyncHandler<")) { return true; } } return false; } private void addAsyncMethod(JavaMethod method) throws ToolException { addPollingMethod(method); addCallbackMethod(method); method.getInterface().addImport("javax.xml.ws.AsyncHandler"); method.getInterface().addImport("java.util.concurrent.Future"); method.getInterface().addImport("javax.xml.ws.Response"); } private void addCallbackMethod(JavaMethod method) throws ToolException { JavaMethod callbackMethod = new JavaMethod(method.getInterface()); callbackMethod.setAsync(true); callbackMethod.setName(method.getName() + ToolConstants.ASYNC_METHOD_SUFFIX); callbackMethod.setStyle(method.getStyle()); callbackMethod.setWrapperStyle(method.isWrapperStyle()); callbackMethod.setSoapAction(method.getSoapAction()); callbackMethod.setOperationName(method.getOperationName()); JavaReturn future = new JavaReturn(); future.setClassName("Future<?>"); callbackMethod.setReturn(future); // REVISIT: test the operation name in the annotation callbackMethod.annotate(new WebMethodAnnotator()); callbackMethod.addAnnotation("ResponseWrapper", method.getAnnotationMap().get("ResponseWrapper")); callbackMethod.addAnnotation("RequestWrapper", method.getAnnotationMap().get("RequestWrapper")); callbackMethod.addAnnotation("SOAPBinding", method.getAnnotationMap().get("SOAPBinding")); boolean convertOutToAsync = !method.isWrapperStyle() && "void".equals(method.getReturn().getClassName()); String asyncCname = null; for (JavaParameter param : method.getParameters()) { if (convertOutToAsync) { if (param.isHolder()) { if (param.isINOUT()) { JavaParameter p2 = new JavaParameter(); p2.setName(param.getName()); p2.setClassName(param.getHolderName()); p2.setStyle(JavaType.Style.IN); callbackMethod.addParameter(p2); for (String s : param.getAnnotationTags()) { JAnnotation ann = param.getAnnotation(s); p2.addAnnotation(s, ann); } } else if (!param.isHeader() && asyncCname == null) { asyncCname = param.getClassName(); } } else { callbackMethod.addParameter(param); } } else { callbackMethod.addParameter(param); } } JavaParameter asyncHandler = new JavaParameter(); asyncHandler.setName("asyncHandler"); asyncHandler.setCallback(true); asyncHandler.setClassName(getAsyncClassName(method, "AsyncHandler", asyncCname)); asyncHandler.setStyle(JavaType.Style.IN); callbackMethod.addParameter(asyncHandler); JAnnotation asyncHandlerAnnotation = new JAnnotation(WebParam.class); asyncHandlerAnnotation.addElement(new JAnnotationElement("name", "asyncHandler")); asyncHandlerAnnotation.addElement(new JAnnotationElement("targetNamespace", "")); asyncHandler.addAnnotation("WebParam", asyncHandlerAnnotation); method.getInterface().addImport("javax.jws.WebParam"); method.getInterface().addMethod(callbackMethod); } private void addPollingMethod(JavaMethod method) throws ToolException { JavaMethod pollingMethod = new JavaMethod(method.getInterface()); pollingMethod.setAsync(true); pollingMethod.setName(method.getName() + ToolConstants.ASYNC_METHOD_SUFFIX); pollingMethod.setStyle(method.getStyle()); pollingMethod.setWrapperStyle(method.isWrapperStyle()); pollingMethod.setSoapAction(method.getSoapAction()); pollingMethod.setOperationName(method.getOperationName()); boolean convertOutToAsync = !method.isWrapperStyle() && "void".equals(method.getReturn().getClassName()); String asyncCname = null; for (JavaParameter param : method.getParameters()) { if (convertOutToAsync) { if (param.isHolder()) { if (param.isINOUT()) { JavaParameter p2 = new JavaParameter(); p2.setName(param.getName()); p2.setClassName(param.getHolderName()); p2.setStyle(JavaType.Style.IN); pollingMethod.addParameter(p2); for (String s : param.getAnnotationTags()) { JAnnotation ann = param.getAnnotation(s); p2.addAnnotation(s, ann); } } else if (!param.isHeader() && asyncCname == null) { asyncCname = param.getClassName(); } } else { pollingMethod.addParameter(param); } } else { pollingMethod.addParameter(param); } } JavaReturn response = new JavaReturn(); response.setClassName(getAsyncClassName(method, "Response", asyncCname)); pollingMethod.setReturn(response); // REVISIT: test the operation name in the annotation pollingMethod.annotate(new WebMethodAnnotator()); pollingMethod.addAnnotation("RequestWrapper", method.getAnnotationMap().get("RequestWrapper")); pollingMethod.addAnnotation("ResponseWrapper", method.getAnnotationMap().get("ResponseWrapper")); pollingMethod.addAnnotation("SOAPBinding", method.getAnnotationMap().get("SOAPBinding")); method.getInterface().addMethod(pollingMethod); } private String getAsyncClassName(JavaMethod method, String clzName, String name) { String response = name; if (response == null) { if (wrapperResponse != null) { response = wrapperResponse.getClassName(); } else { response = method.getReturn().getClassName(); } Class<?> mappedClass = JAXBUtils.holderClass(response); if (mappedClass != null) { response = mappedClass.getName(); } } StringBuilder sb = new StringBuilder(); sb.append(clzName); sb.append("<"); if ("void".equals(response)) { sb.append('?'); } else { sb.append(response); } sb.append(">"); return sb.toString(); } private boolean isAddedAsycMethod(JavaMethod method) { List<JavaMethod> jmethods = method.getInterface().getMethods(); int counter = 0; for (JavaMethod jm : jmethods) { if (jm.getOperationName().equals(method.getOperationName())) { counter++; } } return counter > 1 ? true : false; } }