1 /*2 * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved3 *4 * This file is part of Resin(R) Open Source5 *6 * Each copy or derived work must preserve the copyright notice and this7 * notice unmodified.8 *9 * Resin Open Source is free software; you can redistribute it and/or modify10 * it under the terms of the GNU General Public License as published by11 * the Free Software Foundation; either version 2 of the License, or12 * (at your option) any later version.13 *14 * Resin Open Source is distributed in the hope that it will be useful,15 * but WITHOUT ANY WARRANTY; without even the implied warranty of16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty17 * of NON-INFRINGEMENT. See the GNU General Public License for more18 * details.19 *20 * You should have received a copy of the GNU General Public License21 * along with Resin Open Source; if not, write to the22 *23 * Free Software Foundation, Inc.24 * 59 Temple Place, Suite 33025 * Boston, MA 02111-1307 USA26 *27 * @author Emil Ong28 */29 30 package com.caucho.soap.skeleton;31 32 import com.caucho.jaxb.JAXBContextImpl;33 import com.caucho.soap.wsdl.SOAPBody;34 import com.caucho.soap.wsdl.SOAPHeader;35 import com.caucho.soap.wsdl.SOAPUseChoice;36 import com.caucho.soap.wsdl.WSDLOperationInput;37 import com.caucho.soap.wsdl.WSDLOperationOutput;38 import com.caucho.soap.wsdl.WSDLPart;39 import com.caucho.util.L10N;40 41 import javax.jws.WebParam;42 import javax.jws.WebResult;43 import javax.xml.bind.Marshaller;44 import javax.xml.bind.Unmarshaller;45 import javax.xml.bind.JAXBException;46 import javax.xml.namespace.QName ;47 import javax.xml.ws.Holder;48 import javax.xml.ws.WebServiceException;49 import java.lang.annotation.Annotation ;50 import java.lang.reflect.Method ;51 import java.lang.reflect.Type ;52 import java.util.Map ;53 import java.util.logging.Logger ;54 55 /**56 * Invokes a SOAP request on a Java POJO method.57 *58 * This class handles the document-literal bare (i.e. non-wrapped) style59 * which JAX-WS maps to methods of at most one input and one output 60 * argument. Non-void return values count as an output argument and61 * INOUT arguments count as both one input and one output.62 */63 public class DocumentBareAction extends AbstractAction {64 private final static Logger log = 65 Logger.getLogger(DocumentBareAction.class.getName());66 private static final L10N L = new L10N(DocumentBareAction.class);67 68 private static final String TARGET_NAMESPACE_PREFIX = "tns";69 70 public DocumentBareAction(Method method, 71 JAXBContextImpl jaxbContext, 72 String targetNamespace,73 Marshaller marshaller,74 Unmarshaller unmarshaller)75 throws JAXBException, WebServiceException76 {77 super(method, jaxbContext, targetNamespace);78 /*79 80 //81 // Create marshallers and message/parts for the arguments/return values82 //83 84 Type[] genericParams = _method.getGenericParameterTypes();85 Class[] params = _method.getParameterTypes();86 Annotation[][] annotations = _method.getParameterAnnotations();87 88 WSDLPart inputPart = null;89 WSDLPart outputPart = null;90 91 for (int i = 0; i < params.length; i++) {92 QName name = null;93 String localName = "arg" + i;94 Marshall marshall = null;95 96 WebParam webParam = (WebParam) _method.getAnnotation(WebParam.class);97 98 if (webParam != null) {99 String partName = null;100 101 if (! "".equals(webParam.partName()))102 partName = webParam.partName();103 104 if (! "".equals(webParam.name()))105 localName = webParam.name();106 107 if (! "".equals(webParam.targetNamespace()))108 name = new QName(webParam.targetNamespace(), localName);109 else110 name = new QName(localName);111 112 if (webParam.mode() == WebParam.Mode.OUT) {113 if (outputPart != null)114 throw new WebServiceException(L.l("Document bare services cannot have more than 1 input and 1 output parameter"));115 116 if ("".equals(webParam.name()))117 throw new WebServiceException(L.l("Document bare services must set the name of OUT parameters"));118 119 if (! params[i].equals(Holder.class))120 throw new WebServiceException(L.l("Output parameters must be Holder<T>s"));121 122 outputPart = new WSDLPart();123 outputPart.setName(partName);124 125 Class parameterType = getHolderValueType(genericParams[i]);126 marshall = factory.createSerializer(parameterType, _jaxbContext);127 }128 else if (webParam.mode() == WebParam.Mode.INOUT) {129 if (inputPart != null || outputPart != null)130 throw new WebServiceException(L.l("Document bare services cannot have more than 1 input and 1 output parameter"));131 132 if ("".equals(webParam.name()))133 throw new WebServiceException(L.l("Document bare services must set the name of INOUT parameters"));134 135 if (! params[i].equals(Holder.class))136 throw new WebServiceException(L.l("Output parameters must be Holder<T>s"));137 138 inputPart = new WSDLPart();139 inputPart.setName(partName);140 141 outputPart = new WSDLPart();142 outputPart.setName(partName);143 144 Class parameterType = getHolderValueType(genericParams[i]);145 marshall = factory.createSerializer(parameterType, _jaxbContext);146 }147 else {148 if (inputPart != null)149 throw new WebServiceException(L.l("Document bare services cannot have more than 1 input and 1 output parameter"));150 151 inputPart = new WSDLPart();152 inputPart.setName(partName);153 154 marshall = factory.createSerializer(params[i], _jaxbContext);155 }156 157 ParameterMarshall paramMarshall = 158 new ParameterMarshall(i, marshall, name, webParam.mode());159 160 if (webParam.header()) {161 _headerArguments.put(localName, paramMarshall);162 163 if (webParam.mode() == WebParam.Mode.OUT || 164 webParam.mode() == WebParam.Mode.INOUT)165 _headerOutputs = 1;166 }167 else {168 _bodyArguments.put(localName, paramMarshall);169 170 if (webParam.mode() == WebParam.Mode.OUT || 171 webParam.mode() == WebParam.Mode.INOUT)172 _bodyOutputs = 1;173 }174 }175 else {176 // 177 // No @WebParam annotation found... assume this is an input178 //179 180 if (inputPart != null)181 throw new WebServiceException(L.l("Document bare services cannot have more than 1 input and 1 output parameter"));182 183 inputPart = new WSDLPart();184 inputPart.setName(localName);185 name = new QName(localName);186 187 marshall = factory.createSerializer(params[i], _jaxbContext);188 189 ParameterMarshall paramMarshall = 190 new ParameterMarshall(i, marshall, name, WebParam.Mode.IN);191 192 // no annotation => this goes in the body193 _bodyArguments.put(localName, paramMarshall);194 }195 }196 197 // Check the return value198 199 if (! _method.getReturnType().equals(Void.class) &&200 ! _method.getReturnType().equals(void.class)) {201 if (outputPart != null)202 throw new WebServiceException(L.l("Document bare services cannot have more than 1 input and 1 output parameter"));203 204 outputPart = new WSDLPart();205 Marshall marshall = 206 factory.createSerializer(_method.getReturnType(), _jaxbContext);207 208 WebResult webResult = (WebResult) _method.getAnnotation(WebResult.class);209 210 QName name = null;211 String partName = null;212 String localName = _responseName; // XXX???213 214 if (webResult != null) {215 if (! "".equals(webResult.partName()))216 partName = webResult.partName();217 218 if (! "".equals(webResult.name()))219 localName = webResult.name();220 221 if (! "".equals(webResult.targetNamespace()))222 name = new QName(webResult.targetNamespace(), localName);223 else 224 name = new QName(localName);225 226 outputPart.setName(partName);227 outputPart.setType(marshall.getXmlSchemaDatatype());228 229 ParameterMarshall paramMarshall = 230 new ParameterMarshall(-1, marshall, name, WebParam.Mode.OUT);231 232 if (webResult.header()) {233 _headerArguments.put(localName, paramMarshall);234 _headerOutputs = 1;235 }236 else {237 _bodyArguments.put(localName, paramMarshall); 238 _bodyOutputs = 1;239 }240 }241 else {242 name = new QName(localName);243 244 outputPart.setName(localName);245 246 ParameterMarshall paramMarshall247 = new ParameterMarshall(-1, marshall, name, WebParam.Mode.OUT);248 249 _bodyArguments.put(localName, paramMarshall);250 }251 }252 253 // SOAP Binding -> binding/operation254 255 if (_headerArguments.size() == 0 && _bodyArguments.size() > 0) {256 SOAPBody soapBody = new SOAPBody();257 soapBody.addEncodingStyle(SOAP_ENCODING_STYLE);258 soapBody.setUse(SOAPUseChoice.LITERAL);259 soapBody.setNamespace(targetNamespace);260 261 if (_bodyArguments.size() - _bodyOutputs > 0)262 _wsdlBindingOperation.getInput().addAny(soapBody);263 264 if (_bodyOutputs > 0)265 _wsdlBindingOperation.getOutput().addAny(soapBody);266 }267 else if (_bodyArguments.size() == 0 && _headerArguments.size() > 0) {268 SOAPHeader soapHeader = new SOAPHeader();269 soapHeader.addEncodingStyle(SOAP_ENCODING_STYLE);270 soapHeader.setUse(SOAPUseChoice.LITERAL);271 soapHeader.setNamespace(targetNamespace);272 273 if (_headerArguments.size() - _headerOutputs > 0)274 _wsdlBindingOperation.getInput().addAny(soapHeader);275 276 if (_headerOutputs > 0)277 _wsdlBindingOperation.getOutput().addAny(soapHeader);278 }279 else if (_bodyArguments.size() == 1 && _headerArguments.size() == 1) {280 SOAPBody soapBody = new SOAPBody();281 soapBody.addEncodingStyle(SOAP_ENCODING_STYLE);282 soapBody.setUse(SOAPUseChoice.LITERAL);283 soapBody.setNamespace(targetNamespace);284 285 SOAPHeader soapHeader = new SOAPHeader();286 soapHeader.addEncodingStyle(SOAP_ENCODING_STYLE);287 soapHeader.setUse(SOAPUseChoice.LITERAL);288 soapHeader.setNamespace(targetNamespace);289 290 if (_headerOutputs > 0) {291 _wsdlBindingOperation.getInput().addAny(soapBody);292 _wsdlBindingOperation.getOutput().addAny(soapHeader);293 }294 else {295 _wsdlBindingOperation.getInput().addAny(soapHeader);296 _wsdlBindingOperation.getOutput().addAny(soapBody);297 }298 }299 300 // portType/operation/input301 302 WSDLOperationInput opInput = new WSDLOperationInput();303 opInput.setMessage(new QName(targetNamespace, 304 _inputMessage.getName(), 305 TARGET_NAMESPACE_PREFIX));306 _wsdlOperation.addOperationPart(opInput);307 308 // portType/operation/output309 310 WSDLOperationOutput opOutput = new WSDLOperationOutput();311 opOutput.setMessage(new QName(targetNamespace, 312 _outputMessage.getName(), 313 TARGET_NAMESPACE_PREFIX));314 _wsdlOperation.addOperationPart(opOutput);315 316 // message/part 317 if (inputPart != null) {318 _inputMessage.addPart(inputPart);319 320 ParameterMarshall marshall = _bodyArguments.get(inputPart.getName());321 322 if (marshall == null)323 marshall = _headerArguments.get(inputPart.getName());324 }325 326 if (outputPart != null) {327 _outputMessage.addPart(outputPart);328 329 ParameterMarshall marshall = _bodyArguments.get(outputPart.getName());330 331 if (marshall == null)332 marshall = _headerArguments.get(outputPart.getName());333 }334 335 336 //337 // Exceptions -> faults338 //339 340 Class[] exceptions = _method.getExceptionTypes();341 342 // XXX multiple exceptions -> multiple faults?343 //344 for (Class exception : exceptions) {345 }*/346 }347 }348