0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common Development
0008: * and Distribution License("CDDL") (collectively, the "License"). You
0009: * may not use this file except in compliance with the License. You can obtain
0010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
0011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
0012: * language governing permissions and limitations under the License.
0013: *
0014: * When distributing the software, include this License Header Notice in each
0015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
0016: * Sun designates this particular file as subject to the "Classpath" exception
0017: * as provided by Sun in the GPL Version 2 section of the License file that
0018: * accompanied this code. If applicable, add the following below the License
0019: * Header, with the fields enclosed by brackets [] replaced by your own
0020: * identifying information: "Portions Copyrighted [year]
0021: * [name of copyright owner]"
0022: *
0023: * Contributor(s):
0024: *
0025: * If you wish your version of this file to be governed by only the CDDL or
0026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
0027: * elects to include this software in this distribution under the [CDDL or GPL
0028: * Version 2] license." If you don't indicate a single choice of license, a
0029: * recipient has the option to distribute your version of this file under
0030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
0031: * its licensees as provided above. However, if you add GPL Version 2 code
0032: * and therefore, elected the GPL Version 2 license, then the option applies
0033: * only if the new code is made subject to such option by the copyright
0034: * holder.
0035: */
0036: package com.sun.xml.ws.model;
0037:
0038: import com.sun.istack.NotNull;
0039: import com.sun.xml.bind.api.CompositeStructure;
0040: import com.sun.xml.bind.api.TypeReference;
0041: import com.sun.xml.bind.v2.model.nav.Navigator;
0042: import com.sun.xml.ws.api.BindingID;
0043: import com.sun.xml.ws.api.SOAPVersion;
0044: import com.sun.xml.ws.api.model.ExceptionType;
0045: import com.sun.xml.ws.api.model.MEP;
0046: import com.sun.xml.ws.api.model.Parameter;
0047: import com.sun.xml.ws.api.model.ParameterBinding;
0048: import com.sun.xml.ws.api.model.wsdl.WSDLPart;
0049: import com.sun.xml.ws.model.soap.SOAPBindingImpl;
0050: import com.sun.xml.ws.model.wsdl.WSDLBoundOperationImpl;
0051: import com.sun.xml.ws.model.wsdl.WSDLInputImpl;
0052: import com.sun.xml.ws.model.wsdl.WSDLPortImpl;
0053: import com.sun.xml.ws.resources.ModelerMessages;
0054: import com.sun.xml.ws.resources.ServerMessages;
0055: import com.sun.xml.ws.util.localization.Localizable;
0056:
0057: import javax.jws.Oneway;
0058: import javax.jws.WebMethod;
0059: import javax.jws.WebParam;
0060: import javax.jws.WebParam.Mode;
0061: import javax.jws.WebResult;
0062: import javax.jws.WebService;
0063: import javax.jws.soap.SOAPBinding;
0064: import static javax.jws.soap.SOAPBinding.ParameterStyle.WRAPPED;
0065: import javax.jws.soap.SOAPBinding.Style;
0066: import javax.xml.bind.annotation.XmlSeeAlso;
0067: import javax.xml.namespace.QName;
0068: import javax.xml.ws.Action;
0069: import javax.xml.ws.AsyncHandler;
0070: import javax.xml.ws.FaultAction;
0071: import javax.xml.ws.Holder;
0072: import javax.xml.ws.RequestWrapper;
0073: import javax.xml.ws.Response;
0074: import javax.xml.ws.ResponseWrapper;
0075: import javax.xml.ws.WebFault;
0076: import java.lang.annotation.Annotation;
0077: import java.lang.reflect.Method;
0078: import java.lang.reflect.Modifier;
0079: import java.lang.reflect.ParameterizedType;
0080: import java.lang.reflect.Type;
0081: import java.rmi.RemoteException;
0082: import java.security.AccessController;
0083: import java.security.PrivilegedAction;
0084: import java.util.HashMap;
0085: import java.util.Map;
0086: import java.util.StringTokenizer;
0087: import java.util.TreeMap;
0088: import java.util.concurrent.Future;
0089: import java.util.logging.Logger;
0090:
0091: /**
0092: * Creates a runtime model of a SEI (portClass).
0093: *
0094: * @author WS Developement Team
0095: */
0096: public class RuntimeModeler {
0097: private BindingID bindingId;
0098: private Class portClass;
0099: private AbstractSEIModelImpl model;
0100: private SOAPBindingImpl defaultBinding;
0101: // can be empty but never null
0102: private String packageName;
0103: private String targetNamespace;
0104: private boolean isWrapped = true;
0105: private boolean usesWebMethod = false;
0106: private ClassLoader classLoader = null;
0107: //private Object implementor;
0108: private final WSDLPortImpl binding;
0109: private QName serviceName;
0110: private QName portName;
0111: private Map<Class, Boolean> classUsesWebMethod = new HashMap<Class, Boolean>();
0112:
0113: /**
0114: *
0115: */
0116: public static final String PD_JAXWS_PACKAGE_PD = ".jaxws.";
0117: /**
0118: *
0119: */
0120: public static final String JAXWS_PACKAGE_PD = "jaxws.";
0121: public static final String RESPONSE = "Response";
0122: public static final String RETURN = "return";
0123: public static final String BEAN = "Bean";
0124: public static final String SERVICE = "Service";
0125: public static final String PORT = "Port";
0126: public static final Class HOLDER_CLASS = Holder.class;
0127: public static final Class<RemoteException> REMOTE_EXCEPTION_CLASS = RemoteException.class;
0128:
0129: /**
0130: * creates an instance of RunTimeModeler given a <code>portClass</code> and <code>bindingId</code>
0131: * @param portClass The SEI class to be modeled.
0132: * @param serviceName The ServiceName to use instead of one calculated from the implementation class
0133: * @param bindingId The binding identifier to be used when modeling the <code>portClass</code>.
0134: */
0135: public RuntimeModeler(@NotNull
0136: Class portClass, @NotNull
0137: QName serviceName, @NotNull
0138: BindingID bindingId) {
0139: this .portClass = portClass;
0140: this .serviceName = serviceName;
0141: this .binding = null;
0142: this .bindingId = bindingId;
0143: }
0144:
0145: /**
0146: *
0147: * creates an instance of RunTimeModeler given a <code>sei</code> and <code>binding</code>
0148: * @param sei The SEI class to be modeled.
0149: * @param serviceName The ServiceName to use instead of one calculated from the implementation class
0150: * @param wsdlPort {@link com.sun.xml.ws.api.model.wsdl.WSDLPort}
0151: */
0152: public RuntimeModeler(@NotNull
0153: Class sei, @NotNull
0154: QName serviceName, @NotNull
0155: WSDLPortImpl wsdlPort) {
0156: this .portClass = sei;
0157: this .serviceName = serviceName;
0158: this .bindingId = wsdlPort.getBinding().getBindingId();
0159:
0160: //If the bindingId is null lets default to SOAP 1.1 binding id. As it looks like this bindingId
0161: //is used latter on from model to generate binding on the WSDL. So defaulting to SOAP 1.1 maybe
0162: // safe to do.
0163: if (this .bindingId == null)
0164: this .bindingId = BindingID.SOAP11_HTTP;
0165:
0166: this .binding = wsdlPort;
0167: }
0168:
0169: /**
0170: * sets the classloader to be used when loading classes by the <code>RuntimeModeler</code>.
0171: * @param classLoader ClassLoader used to load classes
0172: */
0173: public void setClassLoader(ClassLoader classLoader) {
0174: this .classLoader = classLoader;
0175: }
0176:
0177: /**
0178: * sets the PortName to be used by the <code>RuntimeModeler</code>.
0179: * @param portName The PortName to be used instead of the PortName
0180: * retrieved via annotations
0181: */
0182: public void setPortName(QName portName) {
0183: this .portName = portName;
0184: }
0185:
0186: private static <T extends Annotation> T getPrivClassAnnotation(
0187: final Class<?> clazz, final Class<T> T) {
0188: return AccessController.doPrivileged(new PrivilegedAction<T>() {
0189: public T run() {
0190: return clazz.getAnnotation(T);
0191: }
0192: });
0193: }
0194:
0195: private static <T extends Annotation> T getPrivMethodAnnotation(
0196: final Method method, final Class<T> T) {
0197: return AccessController.doPrivileged(new PrivilegedAction<T>() {
0198: public T run() {
0199: return method.getAnnotation(T);
0200: }
0201: });
0202: }
0203:
0204: private static Annotation[][] getPrivParameterAnnotations(
0205: final Method method) {
0206: return AccessController
0207: .doPrivileged(new PrivilegedAction<Annotation[][]>() {
0208: public Annotation[][] run() {
0209: return method.getParameterAnnotations();
0210: }
0211: });
0212: }
0213:
0214: private static final Logger logger = Logger
0215: .getLogger(com.sun.xml.ws.util.Constants.LoggingDomain
0216: + ".server");
0217:
0218: //currently has many local vars which will be eliminated after debugging issues
0219: //first draft
0220: /**
0221: * builds the runtime model from the <code>portClass</code> using the binding ID <code>bindingId</code>.
0222: * @return the runtime model for the <code>portClass</code>.
0223: */
0224: public AbstractSEIModelImpl buildRuntimeModel() {
0225: model = new SOAPSEIModel();
0226: Class clazz = portClass;
0227: WebService webService = getPrivClassAnnotation(portClass,
0228: WebService.class);
0229: if (webService == null) {
0230: throw new RuntimeModelerException(
0231: "runtime.modeler.no.webservice.annotation",
0232: portClass.getCanonicalName());
0233: }
0234: if (webService.endpointInterface().length() > 0) {
0235: clazz = getClass(
0236: webService.endpointInterface(),
0237: ModelerMessages
0238: .localizableRUNTIME_MODELER_CLASS_NOT_FOUND(webService
0239: .endpointInterface()));
0240: WebService seiService = getPrivClassAnnotation(clazz,
0241: WebService.class);
0242: if (seiService == null) {
0243: throw new RuntimeModelerException(
0244: "runtime.modeler.endpoint.interface.no.webservice",
0245: webService.endpointInterface());
0246: }
0247:
0248: //check if @SOAPBinding is defined on the impl class
0249: SOAPBinding sbPortClass = getPrivClassAnnotation(portClass,
0250: SOAPBinding.class);
0251: SOAPBinding sbSei = getPrivClassAnnotation(clazz,
0252: SOAPBinding.class);
0253: if (sbPortClass != null) {
0254: if (sbSei == null
0255: || sbSei.style() != sbPortClass.style()
0256: || sbSei.use() != sbPortClass.use()) {
0257: logger.warning(ServerMessages
0258: .RUNTIMEMODELER_INVALIDANNOTATION_ON_IMPL(
0259: "@SOAPBinding",
0260: portClass.getName(), clazz
0261: .getName()));
0262: }
0263: }
0264: }
0265: if (serviceName == null)
0266: serviceName = getServiceName(portClass);
0267: model.setServiceQName(serviceName);
0268:
0269: String portLocalName = portClass.getSimpleName() + PORT;
0270: if (webService.portName().length() > 0) {
0271: portLocalName = webService.portName();
0272: } else if (webService.name().length() > 0) {
0273: portLocalName = webService.name() + PORT;
0274: }
0275:
0276: if (portName == null)
0277: portName = new QName(serviceName.getNamespaceURI(),
0278: portLocalName);
0279: if (!portName.getNamespaceURI().equals(
0280: serviceName.getNamespaceURI())) {
0281: throw new RuntimeModelerException(
0282: "runtime.modeler.portname.servicename.namespace.mismatch",
0283: serviceName, portName);
0284: }
0285: model.setPortName(portName);
0286:
0287: processClass(clazz);
0288: if (model.getJavaMethods().size() == 0)
0289: throw new RuntimeModelerException(
0290: "runtime.modeler.no.operations", portClass
0291: .getName());
0292: model.postProcess();
0293:
0294: // TODO: this needs to be fixed properly --
0295: // when we are building RuntimeModel first before building WSDLModel,
0296: // we still need to do this correctyl
0297: if (binding != null)
0298: model.freeze(binding);
0299:
0300: return model;
0301: }
0302:
0303: /**
0304: * utility method to load classes
0305: * @param className the name of the class to load
0306: * @param errorMessage
0307: * Error message to use when the resolution fails.
0308: * @return the class specified by <code>className</code>
0309: */
0310: private Class getClass(String className, Localizable errorMessage) {
0311: try {
0312: if (classLoader == null)
0313: return Thread.currentThread().getContextClassLoader()
0314: .loadClass(className);
0315: else
0316: return classLoader.loadClass(className);
0317: } catch (ClassNotFoundException e) {
0318: throw new RuntimeModelerException(errorMessage);
0319: }
0320: }
0321:
0322: protected void setUsesWebMethod(Class clazz, Boolean usesWebMethod) {
0323: // System.out.println("class: "+clazz.getName()+" uses WebMethod: "+usesWebMethod);
0324: classUsesWebMethod.put(clazz, usesWebMethod);
0325: }
0326:
0327: protected void determineWebMethodUse(Class clazz) {
0328: if (clazz == null)
0329: return;
0330: if (clazz.isInterface()) {
0331: setUsesWebMethod(clazz, false);
0332: } else {
0333: WebMethod webMethod;
0334: boolean hasWebMethod = false;
0335: for (Method method : clazz.getMethods()) {
0336: if (method.getDeclaringClass() != clazz)
0337: continue;
0338: webMethod = getPrivMethodAnnotation(method,
0339: WebMethod.class);
0340: if (webMethod != null && !webMethod.exclude()) {
0341: hasWebMethod = true;
0342: break;
0343: }
0344: }
0345: setUsesWebMethod(clazz, hasWebMethod);
0346: }
0347: determineWebMethodUse(clazz.getSuperclass());
0348: }
0349:
0350: void processClass(Class clazz) {
0351: determineWebMethodUse(clazz);
0352: WebService webService = getPrivClassAnnotation(clazz,
0353: WebService.class);
0354: String portTypeLocalName = clazz.getSimpleName();
0355: if (webService.name().length() > 0)
0356: portTypeLocalName = webService.name();
0357:
0358: targetNamespace = webService.targetNamespace();
0359: packageName = "";
0360: if (clazz.getPackage() != null)
0361: packageName = clazz.getPackage().getName();
0362: if (targetNamespace.length() == 0) {
0363: targetNamespace = getNamespace(packageName);
0364: }
0365: model.setTargetNamespace(targetNamespace);
0366: QName portTypeName = new QName(targetNamespace,
0367: portTypeLocalName);
0368: model.setPortTypeName(portTypeName);
0369: model.setWSDLLocation(webService.wsdlLocation());
0370:
0371: SOAPBinding soapBinding = getPrivClassAnnotation(clazz,
0372: SOAPBinding.class);
0373: if (soapBinding != null) {
0374: isWrapped = soapBinding.parameterStyle() == WRAPPED;
0375: }
0376: defaultBinding = createBinding(soapBinding);
0377: /*
0378: * if clazz != portClass then there is an SEI. If there is an
0379: * SEI, then all methods should be processed. However, if there is
0380: * no SEI, and the implementation class uses at least one
0381: * WebMethod annotation, then only methods with this annotation
0382: * will be processed.
0383: */
0384: /* if (clazz == portClass) {
0385: WebMethod webMethod;
0386: for (Method method : clazz.getMethods()) {
0387: webMethod = getPrivMethodAnnotation(method, WebMethod.class);
0388: if (webMethod != null &&
0389: !webMethod.exclude()) {
0390: usesWebMethod = true;
0391: break;
0392: }
0393: }
0394: }*/
0395:
0396: for (Method method : clazz.getMethods()) {
0397: if (method.getDeclaringClass() == Object.class
0398: || !isWebMethod(method, clazz)) {
0399: continue;
0400: }
0401: // TODO: binding can be null. We need to figure out how to post-process
0402: // RuntimeModel to link to WSDLModel
0403: processMethod(method, webService);
0404: }
0405: //Add additional jaxb classes referenced by {@link XmlSeeAlso}
0406: XmlSeeAlso xmlSeeAlso = getPrivClassAnnotation(clazz,
0407: XmlSeeAlso.class);
0408: if (xmlSeeAlso != null)
0409: model.addAdditionalClasses(xmlSeeAlso.value());
0410: }
0411:
0412: protected boolean isWebMethod(Method method, Class clazz) {
0413: if (clazz.isInterface()) {
0414: return true;
0415: }
0416: Class declClass = method.getDeclaringClass();
0417: boolean declHasWebService = getPrivClassAnnotation(declClass,
0418: WebService.class) != null;
0419: WebMethod webMethod = getPrivMethodAnnotation(method,
0420: WebMethod.class);
0421: if (webMethod != null && !webMethod.exclude()
0422: && declHasWebService) {
0423: return true;
0424: }
0425: return declHasWebService && !classUsesWebMethod.get(declClass);
0426: }
0427:
0428: /**
0429: * creates a runtime model <code>SOAPBinding</code> from a <code>javax.jws.soap.SOAPBinding</code> object
0430: * @param soapBinding the <code>javax.jws.soap.SOAPBinding</code> to model
0431: * @return returns the runtime model SOAPBinding corresponding to <code>soapBinding</code>
0432: */
0433: protected SOAPBindingImpl createBinding(SOAPBinding soapBinding) {
0434: SOAPBindingImpl rtSOAPBinding = new SOAPBindingImpl();
0435: Style style = soapBinding != null ? soapBinding.style()
0436: : Style.DOCUMENT;
0437: rtSOAPBinding.setStyle(style);
0438: assert bindingId != null;
0439: SOAPVersion soapVersion = bindingId.getSOAPVersion();
0440: rtSOAPBinding.setSOAPVersion(soapVersion);
0441: return rtSOAPBinding;
0442: }
0443:
0444: /**
0445: * gets the namespace <code>String</code> for a given <code>packageName</code>
0446: * @param packageName the name of the package used to find a namespace.
0447: * can be empty.
0448: * @return the namespace for the specified <code>packageName</code>
0449: */
0450: public static String getNamespace(@NotNull
0451: String packageName) {
0452: if (packageName.length() == 0)
0453: return null;
0454:
0455: StringTokenizer tokenizer = new StringTokenizer(packageName,
0456: ".");
0457: String[] tokens;
0458: if (tokenizer.countTokens() == 0) {
0459: tokens = new String[0];
0460: } else {
0461: tokens = new String[tokenizer.countTokens()];
0462: for (int i = tokenizer.countTokens() - 1; i >= 0; i--) {
0463: tokens[i] = tokenizer.nextToken();
0464: }
0465: }
0466: StringBuilder namespace = new StringBuilder("http://");
0467: for (int i = 0; i < tokens.length; i++) {
0468: if (i != 0)
0469: namespace.append('.');
0470: namespace.append(tokens[i]);
0471: }
0472: namespace.append('/');
0473: return namespace.toString();
0474: }
0475:
0476: /**
0477: * creates the runtime model for a method on the <code>portClass</code>
0478: * @param method the method to model
0479: * @param webService the instance of the <code>WebService</code> annotation on the <code>portClass</code>
0480: */
0481: protected void processMethod(Method method, WebService webService) {
0482: int mods = method.getModifiers();
0483: if (!Modifier.isPublic(mods) || Modifier.isStatic(mods)) {
0484: if (method.getAnnotation(WebMethod.class) != null) {
0485: // if the user put @WebMethod on these non-qualifying method,
0486: // it's an error
0487: if (Modifier.isStatic(mods))
0488: throw new RuntimeModelerException(
0489: ModelerMessages
0490: .localizableRUNTIME_MODELER_WEBMETHOD_MUST_BE_NONSTATIC(method));
0491: else
0492: throw new RuntimeModelerException(
0493: ModelerMessages
0494: .localizableRUNTIME_MODELER_WEBMETHOD_MUST_BE_PUBLIC(method));
0495: }
0496: return;
0497: }
0498:
0499: WebMethod webMethod = getPrivMethodAnnotation(method,
0500: WebMethod.class);
0501: if (webMethod != null && webMethod.exclude())
0502: return;
0503:
0504: // If one WebMethod is used, then only methods with WebMethod will be
0505: // processed.
0506: if (usesWebMethod && webMethod == null) {
0507: return;
0508: }
0509:
0510: JavaMethodImpl javaMethod;
0511: //Class implementorClass = portClass;
0512: if (method.getDeclaringClass() == portClass) {
0513: javaMethod = new JavaMethodImpl(model, method, method);
0514: } else {
0515: try {
0516: Method tmpMethod = portClass.getMethod(
0517: method.getName(), method.getParameterTypes());
0518: javaMethod = new JavaMethodImpl(model, tmpMethod,
0519: method);
0520: } catch (NoSuchMethodException e) {
0521: throw new RuntimeModelerException(
0522: "runtime.modeler.method.not.found", method
0523: .getName(), portClass.getName());
0524: }
0525: }
0526:
0527: String methodName = method.getName();
0528:
0529: //set MEP -oneway, async, req/resp
0530: MEP mep = getMEP(method);
0531: javaMethod.setMEP(mep);
0532:
0533: String action = null;
0534:
0535: String operationName = method.getName();
0536: if (webMethod != null) {
0537: action = webMethod.action();
0538: operationName = webMethod.operationName().length() > 0 ? webMethod
0539: .operationName()
0540: : operationName;
0541: }
0542:
0543: //override the @WebMethod.action value by the one from the WSDL
0544: if (binding != null) {
0545: WSDLBoundOperationImpl bo = binding.getBinding().get(
0546: new QName(targetNamespace, operationName));
0547: if (bo != null) {
0548: WSDLInputImpl wsdlInput = bo.getOperation().getInput();
0549: String wsaAction = wsdlInput.getAction();
0550: if (wsaAction != null && !wsdlInput.isDefaultAction())
0551: action = wsaAction;
0552: else
0553: action = bo.getSOAPAction();
0554: }
0555: }
0556:
0557: javaMethod.setOperationName(operationName);
0558: SOAPBinding methodBinding = method
0559: .getAnnotation(SOAPBinding.class);
0560: if (methodBinding == null
0561: && !method.getDeclaringClass().equals(portClass)) {
0562: if (!method.getDeclaringClass().isInterface()) {
0563: methodBinding = method.getDeclaringClass()
0564: .getAnnotation(SOAPBinding.class);
0565: }
0566: }
0567: boolean methodIsWrapped = isWrapped;
0568: Style style = defaultBinding.getStyle();
0569: if (methodBinding != null) {
0570: com.sun.xml.ws.model.soap.SOAPBindingImpl mySOAPBinding = createBinding(methodBinding);
0571: style = mySOAPBinding.getStyle();
0572: if (action != null)
0573: mySOAPBinding.setSOAPAction(action);
0574: methodIsWrapped = methodBinding.parameterStyle().equals(
0575: WRAPPED);
0576: javaMethod.setBinding(mySOAPBinding);
0577: } else {
0578: com.sun.xml.ws.model.soap.SOAPBindingImpl sb = new com.sun.xml.ws.model.soap.SOAPBindingImpl(
0579: defaultBinding);
0580: if (action != null)
0581: sb.setSOAPAction(action);
0582: else
0583: sb.setSOAPAction("");
0584: javaMethod.setBinding(sb);
0585: }
0586: if (!methodIsWrapped) {
0587: processDocBareMethod(javaMethod, methodName, webMethod,
0588: operationName, method, webService);
0589: } else if (style.equals(Style.DOCUMENT)) {
0590: processDocWrappedMethod(javaMethod, methodName, webMethod,
0591: operationName, method, webService);
0592: } else {
0593: processRpcMethod(javaMethod, methodName, webMethod,
0594: operationName, method, webService);
0595: }
0596: model.addJavaMethod(javaMethod);
0597: }
0598:
0599: private MEP getMEP(Method m) {
0600: if (m.isAnnotationPresent(Oneway.class)) {
0601: return MEP.ONE_WAY;
0602: }
0603: if (Response.class.isAssignableFrom(m.getReturnType())) {
0604: return MEP.ASYNC_POLL;
0605: } else if (Future.class.isAssignableFrom(m.getReturnType())) {
0606: return MEP.ASYNC_CALLBACK;
0607: }
0608: return MEP.REQUEST_RESPONSE;
0609: }
0610:
0611: /**
0612: * models a document/literal wrapped method
0613: * @param javaMethod the runtime model <code>JavaMethod</code> instance being created
0614: * @param methodName the runtime model <code>JavaMethod</code> instance being created
0615: * @param webMethod the runtime model <code>JavaMethod</code> instance being created
0616: * @param operationName the runtime model <code>JavaMethod</code> instance being created
0617: * @param method the <code>method</code> to model
0618: * @param webService The <code>WebService</code> annotation instance on the <code>portClass</code>
0619: */
0620: protected void processDocWrappedMethod(JavaMethodImpl javaMethod,
0621: String methodName, WebMethod webMethod,
0622: String operationName, Method method, WebService webService) {
0623: boolean isOneway = method.isAnnotationPresent(Oneway.class);
0624: RequestWrapper reqWrapper = method
0625: .getAnnotation(RequestWrapper.class);
0626: ResponseWrapper resWrapper = method
0627: .getAnnotation(ResponseWrapper.class);
0628: String beanPackage = packageName + PD_JAXWS_PACKAGE_PD;
0629: if (packageName == null
0630: || (packageName != null && packageName.length() == 0))
0631: beanPackage = JAXWS_PACKAGE_PD;
0632: String requestClassName;
0633: if (reqWrapper != null && reqWrapper.className().length() > 0) {
0634: requestClassName = reqWrapper.className();
0635: } else {
0636: requestClassName = beanPackage
0637: + capitalize(method.getName());
0638: }
0639:
0640: String responseClassName;
0641: if (resWrapper != null && resWrapper.className().length() > 0) {
0642: responseClassName = resWrapper.className();
0643: } else {
0644: responseClassName = beanPackage
0645: + capitalize(method.getName()) + RESPONSE;
0646: }
0647:
0648: Class requestClass = getClass(
0649: requestClassName,
0650: ModelerMessages
0651: .localizableRUNTIME_MODELER_WRAPPER_NOT_FOUND(requestClassName));
0652:
0653: String reqName = operationName;
0654: String reqNamespace = targetNamespace;
0655: if (reqWrapper != null) {
0656: if (reqWrapper.targetNamespace().length() > 0)
0657: reqNamespace = reqWrapper.targetNamespace();
0658: if (reqWrapper.localName().length() > 0)
0659: reqName = reqWrapper.localName();
0660: }
0661: QName reqElementName = new QName(reqNamespace, reqName);
0662:
0663: Class responseClass = null;
0664: String resName = operationName + "Response";
0665: String resNamespace = targetNamespace;
0666: if (!isOneway) {
0667: responseClass = getClass(
0668: responseClassName,
0669: ModelerMessages
0670: .localizableRUNTIME_MODELER_WRAPPER_NOT_FOUND(responseClassName));
0671: if (resWrapper != null) {
0672: if (resWrapper.targetNamespace().length() > 0)
0673: resNamespace = resWrapper.targetNamespace();
0674: if (resWrapper.localName().length() > 0)
0675: resName = resWrapper.localName();
0676: }
0677: }
0678: QName resElementName = new QName(resNamespace, resName);
0679:
0680: TypeReference typeRef = new TypeReference(reqElementName,
0681: requestClass);
0682: WrapperParameter requestWrapper = new WrapperParameter(
0683: javaMethod, typeRef, Mode.IN, 0);
0684: requestWrapper.setBinding(ParameterBinding.BODY);
0685: javaMethod.addParameter(requestWrapper);
0686: WrapperParameter responseWrapper = null;
0687: if (!isOneway) {
0688: typeRef = new TypeReference(resElementName, responseClass);
0689: responseWrapper = new WrapperParameter(javaMethod, typeRef,
0690: Mode.OUT, -1);
0691: javaMethod.addParameter(responseWrapper);
0692: responseWrapper.setBinding(ParameterBinding.BODY);
0693: }
0694:
0695: // return value
0696: String resultName = RETURN;
0697: String resultTNS = "";
0698: QName resultQName = null;
0699: WebResult webResult = method.getAnnotation(WebResult.class);
0700: Class returnType = method.getReturnType();
0701: boolean isResultHeader = false;
0702: if (webResult != null) {
0703: if (webResult.name().length() > 0)
0704: resultName = webResult.name();
0705: resultTNS = webResult.targetNamespace();
0706: isResultHeader = webResult.header();
0707: if (resultTNS.length() == 0 && webResult.header()) {
0708: // headers must have a namespace
0709: resultTNS = targetNamespace;
0710: }
0711: resultQName = new QName(resultTNS, resultName);
0712: } else if (!isOneway && !returnType.getName().equals("void")
0713: && !javaMethod.isAsync()) {
0714: if (resultQName == null) {
0715: resultQName = new QName(resultTNS, RETURN);
0716: }
0717: }
0718:
0719: if (javaMethod.isAsync()) {
0720: returnType = getAsyncReturnType(method, returnType);
0721: resultQName = new QName(RETURN);
0722: }
0723:
0724: if (!isOneway && (returnType != null)
0725: && (!returnType.getName().equals("void"))) {
0726: Annotation[] rann = method.getAnnotations();
0727: if (resultQName.getLocalPart() != null) {
0728: TypeReference rTypeReference = new TypeReference(
0729: resultQName, returnType, rann);
0730: ParameterImpl returnParameter = new ParameterImpl(
0731: javaMethod, rTypeReference, Mode.OUT, -1);
0732: if (isResultHeader) {
0733: returnParameter.setBinding(ParameterBinding.HEADER);
0734: javaMethod.addParameter(returnParameter);
0735: } else {
0736: returnParameter.setBinding(ParameterBinding.BODY);
0737: responseWrapper.addWrapperChild(returnParameter);
0738: }
0739: }
0740: }
0741:
0742: //get WebParam
0743: Class<?>[] parameterTypes = method.getParameterTypes();
0744: Type[] genericParameterTypes = method
0745: .getGenericParameterTypes();
0746: Annotation[][] pannotations = getPrivParameterAnnotations(method);
0747: int pos = 0;
0748: for (Class clazzType : parameterTypes) {
0749: String partName = null;
0750: String paramName = "arg" + pos;
0751: String paramNamespace = "";
0752: boolean isHeader = false;
0753:
0754: if (javaMethod.isAsync()
0755: && AsyncHandler.class.isAssignableFrom(clazzType)) {
0756: continue;
0757: }
0758:
0759: boolean isHolder = HOLDER_CLASS.isAssignableFrom(clazzType);
0760: //set the actual type argument of Holder in the TypeReference
0761: if (isHolder) {
0762: if (clazzType == Holder.class) {
0763: clazzType = Navigator.REFLECTION
0764: .erasure(((ParameterizedType) genericParameterTypes[pos])
0765: .getActualTypeArguments()[0]);
0766: }
0767: }
0768: Mode paramMode = isHolder ? Mode.INOUT : Mode.IN;
0769: for (Annotation annotation : pannotations[pos]) {
0770: if (annotation.annotationType() == WebParam.class) {
0771: WebParam webParam = (WebParam) annotation;
0772: if (webParam.name().length() > 0)
0773: paramName = webParam.name();
0774: isHeader = webParam.header();
0775: if (webParam.partName().length() > 0)
0776: partName = webParam.partName();
0777: else
0778: partName = paramName;
0779: if (isHeader) // headers cannot be in empty namespace
0780: paramNamespace = targetNamespace;
0781: if (!webParam.targetNamespace().equals("")) {
0782: paramNamespace = webParam.targetNamespace();
0783: }
0784: paramMode = webParam.mode();
0785: if (isHolder && paramMode == Mode.IN)
0786: paramMode = Mode.INOUT;
0787: break;
0788: }
0789: }
0790: QName paramQName = new QName(paramNamespace, paramName);
0791: typeRef = new TypeReference(paramQName, clazzType,
0792: pannotations[pos]);
0793: ParameterImpl param = new ParameterImpl(javaMethod,
0794: typeRef, paramMode, pos++);
0795:
0796: if (isHeader) {
0797: param.setBinding(ParameterBinding.HEADER);
0798: javaMethod.addParameter(param);
0799: param.setPartName(partName);
0800: } else {
0801: param.setBinding(ParameterBinding.BODY);
0802: if (paramMode != Mode.OUT) {
0803: requestWrapper.addWrapperChild(param);
0804: }
0805: if (paramMode != Mode.IN) {
0806: if (isOneway) {
0807: throw new RuntimeModelerException(
0808: "runtime.modeler.oneway.operation.no.out.parameters",
0809: portClass.getCanonicalName(),
0810: methodName);
0811: }
0812: responseWrapper.addWrapperChild(param);
0813: }
0814: }
0815: }
0816: processExceptions(javaMethod, method);
0817: }
0818:
0819: /**
0820: * models a rpc/literal method
0821: * @param javaMethod the runtime model <code>JavaMethod</code> instance being created
0822: * @param methodName the name of the <code>method</code> being modeled.
0823: * @param webMethod the <code>WebMethod</code> annotations instance on the <code>method</code>
0824: * @param operationName the WSDL operation name for this <code>method</code>
0825: * @param method the runtime model <code>JavaMethod</code> instance being created
0826: * @param webService the runtime model <code>JavaMethod</code> instance being created
0827: */
0828: protected void processRpcMethod(JavaMethodImpl javaMethod,
0829: String methodName, WebMethod webMethod,
0830: String operationName, Method method, WebService webService) {
0831: boolean isOneway = method.isAnnotationPresent(Oneway.class);
0832:
0833: // use Map to build parameters in the part order when they are known.
0834: // if part is unbound, we just put them at the end, and for that we
0835: // use a large index (10000+) to avoid colliding with ordered ones.
0836: // this assumes that there's no operation with # of parameters > 10000,
0837: // but I think it's a pretty safe assumption - KK.
0838: Map<Integer, ParameterImpl> resRpcParams = new TreeMap<Integer, ParameterImpl>();
0839: Map<Integer, ParameterImpl> reqRpcParams = new TreeMap<Integer, ParameterImpl>();
0840:
0841: //Lets take the service namespace and overwrite it with the one we get it from wsdl
0842: String reqNamespace = targetNamespace;
0843: String respNamespace = targetNamespace;
0844:
0845: if (binding != null && binding.getBinding().isRpcLit()) {
0846: QName opQName = new QName(binding.getBinding()
0847: .getPortTypeName().getNamespaceURI(), operationName);
0848: WSDLBoundOperationImpl op = binding.getBinding().get(
0849: opQName);
0850: if (op != null) {
0851: //it cant be null, but lets not fail and try to work with service namespce
0852: if (op.getRequestNamespace() != null) {
0853: reqNamespace = op.getRequestNamespace();
0854: }
0855:
0856: //it cant be null, but lets not fail and try to work with service namespce
0857: if (op.getResponseNamespace() != null) {
0858: respNamespace = op.getResponseNamespace();
0859: }
0860: }
0861: }
0862:
0863: QName reqElementName = new QName(reqNamespace, operationName);
0864: QName resElementName = null;
0865: if (!isOneway) {
0866: resElementName = new QName(respNamespace, operationName
0867: + RESPONSE);
0868: }
0869:
0870: Class wrapperType = CompositeStructure.class;
0871: TypeReference typeRef = new TypeReference(reqElementName,
0872: wrapperType);
0873: WrapperParameter requestWrapper = new WrapperParameter(
0874: javaMethod, typeRef, Mode.IN, 0);
0875: requestWrapper.setInBinding(ParameterBinding.BODY);
0876: javaMethod.addParameter(requestWrapper);
0877: WrapperParameter responseWrapper = null;
0878: if (!isOneway) {
0879: typeRef = new TypeReference(resElementName, wrapperType);
0880: responseWrapper = new WrapperParameter(javaMethod, typeRef,
0881: Mode.OUT, -1);
0882: responseWrapper.setOutBinding(ParameterBinding.BODY);
0883: javaMethod.addParameter(responseWrapper);
0884: }
0885:
0886: Class returnType = method.getReturnType();
0887: String resultName = RETURN;
0888: String resultTNS = targetNamespace;
0889: String resultPartName = resultName;
0890: boolean isResultHeader = false;
0891: WebResult webResult = method.getAnnotation(WebResult.class);
0892:
0893: if (webResult != null) {
0894: isResultHeader = webResult.header();
0895: if (webResult.name().length() > 0)
0896: resultName = webResult.name();
0897: if (webResult.partName().length() > 0) {
0898: resultPartName = webResult.partName();
0899: if (!isResultHeader)
0900: resultName = resultPartName;
0901: } else
0902: resultPartName = resultName;
0903: if (webResult.targetNamespace().length() > 0)
0904: resultTNS = webResult.targetNamespace();
0905: isResultHeader = webResult.header();
0906: }
0907: QName resultQName;
0908: if (isResultHeader)
0909: resultQName = new QName(resultTNS, resultName);
0910: else
0911: resultQName = new QName(resultName);
0912:
0913: if (javaMethod.isAsync()) {
0914: returnType = getAsyncReturnType(method, returnType);
0915: }
0916:
0917: if (!isOneway && returnType != null && returnType != void.class) {
0918: Annotation[] rann = method.getAnnotations();
0919: TypeReference rTypeReference = new TypeReference(
0920: resultQName, returnType, rann);
0921: ParameterImpl returnParameter = new ParameterImpl(
0922: javaMethod, rTypeReference, Mode.OUT, -1);
0923: returnParameter.setPartName(resultPartName);
0924: if (isResultHeader) {
0925: returnParameter.setBinding(ParameterBinding.HEADER);
0926: javaMethod.addParameter(returnParameter);
0927: } else {
0928: ParameterBinding rb = getBinding(operationName,
0929: resultPartName, false, Mode.OUT);
0930: returnParameter.setBinding(rb);
0931: if (rb.isBody()) {
0932: WSDLPart p = getPart(new QName(targetNamespace,
0933: operationName), resultPartName, Mode.OUT);
0934: if (p == null)
0935: resRpcParams.put(resRpcParams.size() + 10000,
0936: returnParameter);
0937: else
0938: resRpcParams.put(p.getIndex(), returnParameter);
0939: } else {
0940: javaMethod.addParameter(returnParameter);
0941: }
0942: }
0943: }
0944:
0945: //get WebParam
0946: Class<?>[] parameterTypes = method.getParameterTypes();
0947: Type[] genericParameterTypes = method
0948: .getGenericParameterTypes();
0949: Annotation[][] pannotations = getPrivParameterAnnotations(method);
0950: int pos = 0;
0951: for (Class clazzType : parameterTypes) {
0952: String paramName = "";
0953: String paramNamespace = "";
0954: String partName = "";
0955: boolean isHeader = false;
0956:
0957: if (javaMethod.isAsync()
0958: && AsyncHandler.class.isAssignableFrom(clazzType)) {
0959: continue;
0960: }
0961:
0962: boolean isHolder = HOLDER_CLASS.isAssignableFrom(clazzType);
0963: //set the actual type argument of Holder in the TypeReference
0964: if (isHolder) {
0965: if (clazzType == Holder.class)
0966: clazzType = Navigator.REFLECTION
0967: .erasure(((ParameterizedType) genericParameterTypes[pos])
0968: .getActualTypeArguments()[0]);
0969: }
0970: Mode paramMode = isHolder ? Mode.INOUT : Mode.IN;
0971: for (Annotation annotation : pannotations[pos]) {
0972: if (annotation.annotationType() == javax.jws.WebParam.class) {
0973: javax.jws.WebParam webParam = (javax.jws.WebParam) annotation;
0974: paramName = webParam.name();
0975: partName = webParam.partName();
0976: isHeader = webParam.header();
0977: WebParam.Mode mode = webParam.mode();
0978: paramNamespace = webParam.targetNamespace();
0979: if (isHolder && mode == Mode.IN)
0980: mode = Mode.INOUT;
0981: paramMode = mode;
0982: break;
0983: }
0984: }
0985:
0986: if (paramName.length() == 0) {
0987: paramName = "arg" + pos;
0988: }
0989: if (partName.length() == 0) {
0990: partName = paramName;
0991: } else if (!isHeader) {
0992: paramName = partName;
0993: }
0994: if (partName.length() == 0) {
0995: partName = paramName;
0996: }
0997:
0998: QName paramQName;
0999: if (!isHeader) {
1000: //its rpclit body param, set namespace to ""
1001: paramQName = new QName("", paramName);
1002: } else {
1003: if (paramNamespace.length() == 0)
1004: paramNamespace = targetNamespace;
1005: paramQName = new QName(paramNamespace, paramName);
1006: }
1007: typeRef = new TypeReference(paramQName, clazzType,
1008: pannotations[pos]);
1009:
1010: ParameterImpl param = new ParameterImpl(javaMethod,
1011: typeRef, paramMode, pos++);
1012: param.setPartName(partName);
1013:
1014: if (paramMode == Mode.INOUT) {
1015: ParameterBinding pb = getBinding(operationName,
1016: partName, isHeader, Mode.IN);
1017: param.setInBinding(pb);
1018: pb = getBinding(operationName, partName, isHeader,
1019: Mode.OUT);
1020: param.setOutBinding(pb);
1021: } else {
1022: if (isHeader) {
1023: param.setBinding(ParameterBinding.HEADER);
1024: } else {
1025: ParameterBinding pb = getBinding(operationName,
1026: partName, false, paramMode);
1027: param.setBinding(pb);
1028: }
1029: }
1030: if (param.getInBinding().isBody()) {
1031: if (!param.isOUT()) {
1032: WSDLPart p = getPart(new QName(targetNamespace,
1033: operationName), partName, Mode.IN);
1034: if (p == null)
1035: reqRpcParams.put(reqRpcParams.size() + 10000,
1036: param);
1037: else
1038: reqRpcParams.put(p.getIndex(), param);
1039: }
1040:
1041: if (!param.isIN()) {
1042: if (isOneway) {
1043: throw new RuntimeModelerException(
1044: "runtime.modeler.oneway.operation.no.out.parameters",
1045: portClass.getCanonicalName(),
1046: methodName);
1047: }
1048: WSDLPart p = getPart(new QName(targetNamespace,
1049: operationName), partName, Mode.OUT);
1050: if (p == null)
1051: resRpcParams.put(resRpcParams.size() + 10000,
1052: param);
1053: else
1054: resRpcParams.put(p.getIndex(), param);
1055: }
1056: } else {
1057: javaMethod.addParameter(param);
1058: }
1059: }
1060: for (ParameterImpl p : reqRpcParams.values())
1061: requestWrapper.addWrapperChild(p);
1062: for (ParameterImpl p : resRpcParams.values())
1063: responseWrapper.addWrapperChild(p);
1064: processExceptions(javaMethod, method);
1065: }
1066:
1067: /**
1068: * models the exceptions thrown by <code>method</code> and adds them to the <code>javaMethod</code>
1069: * runtime model object
1070: * @param javaMethod the runtime model object to add the exception model objects to
1071: * @param method the <code>method</code> from which to find the exceptions to model
1072: */
1073: protected void processExceptions(JavaMethodImpl javaMethod,
1074: Method method) {
1075: Action actionAnn = method.getAnnotation(Action.class);
1076: FaultAction[] faultActions = {};
1077: if (actionAnn != null)
1078: faultActions = actionAnn.fault();
1079: for (Class<?> exception : method.getExceptionTypes()) {
1080: if (REMOTE_EXCEPTION_CLASS.isAssignableFrom(exception))
1081: continue;
1082: Class exceptionBean;
1083: Annotation[] anns;
1084: WebFault webFault = getPrivClassAnnotation(exception,
1085: WebFault.class);
1086: Method faultInfoMethod = getWSDLExceptionFaultInfo(exception);
1087: ExceptionType exceptionType = ExceptionType.WSDLException;
1088: String namespace = targetNamespace;
1089: String name = exception.getSimpleName();
1090: String beanPackage = packageName + PD_JAXWS_PACKAGE_PD;
1091: if (packageName.length() == 0)
1092: beanPackage = JAXWS_PACKAGE_PD;
1093: String className = beanPackage + name + BEAN;
1094: if (webFault != null) {
1095: if (webFault.faultBean().length() > 0)
1096: className = webFault.faultBean();
1097: if (webFault.name().length() > 0)
1098: name = webFault.name();
1099: if (webFault.targetNamespace().length() > 0)
1100: namespace = webFault.targetNamespace();
1101: }
1102: if (faultInfoMethod == null) {
1103: exceptionBean = getClass(
1104: className,
1105: ModelerMessages
1106: .localizableRUNTIME_MODELER_WRAPPER_NOT_FOUND(className));
1107: exceptionType = ExceptionType.UserDefined;
1108: anns = exceptionBean.getAnnotations();
1109: } else {
1110: exceptionBean = faultInfoMethod.getReturnType();
1111: anns = faultInfoMethod.getAnnotations();
1112: }
1113: QName faultName = new QName(namespace, name);
1114: TypeReference typeRef = new TypeReference(faultName,
1115: exceptionBean, anns);
1116: CheckedExceptionImpl checkedException = new CheckedExceptionImpl(
1117: javaMethod, exception, typeRef, exceptionType);
1118: checkedException.setMessageName(exception.getSimpleName());
1119: for (FaultAction fa : faultActions) {
1120: if (fa.className().equals(exception)
1121: && !fa.value().equals("")) {
1122: checkedException.setFaultAction(fa.value());
1123: break;
1124: }
1125: }
1126: javaMethod.addException(checkedException);
1127: }
1128: }
1129:
1130: /**
1131: * returns the method that corresponds to "getFaultInfo". Returns null if this is not an
1132: * exception generated from a WSDL
1133: * @param exception the class to search for the "getFaultInfo" method
1134: * @return the method named "getFaultInfo" if this is an exception generated from WSDL or an
1135: * exception that contains the <code>WebFault</code> annotation. Otherwise it returns null
1136: */
1137: protected Method getWSDLExceptionFaultInfo(Class exception) {
1138: if (!exception.isAnnotationPresent(WebFault.class))
1139: return null;
1140: try {
1141: return exception.getMethod("getFaultInfo");
1142: } catch (NoSuchMethodException e) {
1143: return null;
1144: }
1145: }
1146:
1147: /**
1148: * models a document/literal bare method
1149: * @param javaMethod the runtime model <code>JavaMethod</code> instance being created
1150: * @param methodName the runtime model <code>JavaMethod</code> instance being created
1151: * @param webMethod the runtime model <code>JavaMethod</code> instance being created
1152: * @param operationName the runtime model <code>JavaMethod</code> instance being created
1153: * @param method the runtime model <code>JavaMethod</code> instance being created
1154: * @param webService the runtime model <code>JavaMethod</code> instance being created
1155: */
1156: protected void processDocBareMethod(JavaMethodImpl javaMethod,
1157: String methodName, WebMethod webMethod,
1158: String operationName, Method method, WebService webService) {
1159:
1160: String resultName = operationName + RESPONSE;
1161: String resultTNS = targetNamespace;
1162: String resultPartName = null;
1163: boolean isResultHeader = false;
1164: WebResult webResult = method.getAnnotation(WebResult.class);
1165: if (webResult != null) {
1166: if (webResult.name().length() > 0)
1167: resultName = webResult.name();
1168: if (webResult.targetNamespace().length() > 0)
1169: resultTNS = webResult.targetNamespace();
1170: resultPartName = webResult.partName();
1171: isResultHeader = webResult.header();
1172: }
1173:
1174: Class returnType = method.getReturnType();
1175:
1176: if (javaMethod.isAsync()) {
1177: returnType = getAsyncReturnType(method, returnType);
1178: }
1179:
1180: if ((returnType != null)
1181: && (!returnType.getName().equals("void"))) {
1182: Annotation[] rann = method.getAnnotations();
1183: if (resultName != null) {
1184: QName responseQName = new QName(resultTNS, resultName);
1185: TypeReference rTypeReference = new TypeReference(
1186: responseQName, returnType, rann);
1187: ParameterImpl returnParameter = new ParameterImpl(
1188: javaMethod, rTypeReference, Mode.OUT, -1);
1189:
1190: if (resultPartName == null
1191: || (resultPartName.length() == 0)) {
1192: resultPartName = resultName;
1193: }
1194: returnParameter.setPartName(resultPartName);
1195: if (isResultHeader) {
1196: returnParameter.setBinding(ParameterBinding.HEADER);
1197: } else {
1198: ParameterBinding rb = getBinding(operationName,
1199: resultPartName, false, Mode.OUT);
1200: returnParameter.setBinding(rb);
1201: }
1202: javaMethod.addParameter(returnParameter);
1203: }
1204: }
1205:
1206: //get WebParam
1207: Class<?>[] parameterTypes = method.getParameterTypes();
1208: Type[] genericParameterTypes = method
1209: .getGenericParameterTypes();
1210: Annotation[][] pannotations = getPrivParameterAnnotations(method);
1211: int pos = 0;
1212: for (Class clazzType : parameterTypes) {
1213: String paramName = operationName; //method.getName();
1214: String partName = null;
1215: String requestNamespace = targetNamespace;
1216: boolean isHeader = false;
1217:
1218: //async
1219: if (javaMethod.isAsync()
1220: && AsyncHandler.class.isAssignableFrom(clazzType)) {
1221: continue;
1222: }
1223:
1224: boolean isHolder = HOLDER_CLASS.isAssignableFrom(clazzType);
1225: //set the actual type argument of Holder in the TypeReference
1226: if (isHolder) {
1227: if (clazzType == Holder.class)
1228: clazzType = Navigator.REFLECTION
1229: .erasure(((ParameterizedType) genericParameterTypes[pos])
1230: .getActualTypeArguments()[0]);
1231: }
1232:
1233: Mode paramMode = isHolder ? Mode.INOUT : Mode.IN;
1234: for (Annotation annotation : pannotations[pos]) {
1235: if (annotation.annotationType() == javax.jws.WebParam.class) {
1236: javax.jws.WebParam webParam = (javax.jws.WebParam) annotation;
1237: if (webParam.name().length() > 0)
1238: paramName = webParam.name();
1239: partName = webParam.partName();
1240: if (!webParam.targetNamespace().equals("")) {
1241: requestNamespace = webParam.targetNamespace();
1242: }
1243: isHeader = webParam.header();
1244: paramMode = webParam.mode();
1245: if (isHolder && paramMode == Mode.IN)
1246: paramMode = Mode.INOUT;
1247: break;
1248: }
1249: }
1250:
1251: QName requestQName = new QName(requestNamespace, paramName);
1252: //doclit/wrapped
1253: TypeReference typeRef = //operationName with upper 1 char
1254: new TypeReference(requestQName, clazzType,
1255: pannotations[pos]);
1256:
1257: ParameterImpl param = new ParameterImpl(javaMethod,
1258: typeRef, paramMode, pos++);
1259: if (partName == null || (partName.length() == 0)) {
1260: partName = paramName;
1261: }
1262: param.setPartName(partName);
1263: if (paramMode == Mode.INOUT) {
1264: ParameterBinding pb = getBinding(operationName,
1265: partName, isHeader, Mode.IN);
1266: param.setInBinding(pb);
1267: pb = getBinding(operationName, partName, isHeader,
1268: Mode.OUT);
1269: param.setOutBinding(pb);
1270: } else {
1271: if (isHeader) {
1272: param.setBinding(ParameterBinding.HEADER);
1273: } else {
1274: ParameterBinding pb = getBinding(operationName,
1275: partName, false, paramMode);
1276: param.setBinding(pb);
1277: }
1278: }
1279: javaMethod.addParameter(param);
1280: }
1281: validateDocBare(javaMethod);
1282: processExceptions(javaMethod, method);
1283: }
1284:
1285: private void validateDocBare(JavaMethodImpl javaMethod) {
1286: int numInBodyBindings = 0;
1287: for (Parameter param : javaMethod.getRequestParameters()) {
1288: if (param.getBinding().equals(ParameterBinding.BODY)
1289: && param.isIN()) {
1290: numInBodyBindings++;
1291: }
1292: if (numInBodyBindings > 1) {
1293: throw new RuntimeModelerException(ModelerMessages
1294: .localizableNOT_A_VALID_BARE_METHOD(portClass
1295: .getName(), javaMethod.getMethod()
1296: .getName()));
1297: }
1298: }
1299: }
1300:
1301: private Class getAsyncReturnType(Method method, Class returnType) {
1302: if (Response.class.isAssignableFrom(returnType)) {
1303: Type ret = method.getGenericReturnType();
1304: return Navigator.REFLECTION
1305: .erasure(((ParameterizedType) ret)
1306: .getActualTypeArguments()[0]);
1307: } else {
1308: Type[] types = method.getGenericParameterTypes();
1309: Class[] params = method.getParameterTypes();
1310: int i = 0;
1311: for (Class cls : params) {
1312: if (AsyncHandler.class.isAssignableFrom(cls)) {
1313: return Navigator.REFLECTION
1314: .erasure(((ParameterizedType) types[i])
1315: .getActualTypeArguments()[0]);
1316: }
1317: i++;
1318: }
1319: }
1320: return returnType;
1321: }
1322:
1323: /**
1324: * utility to capitalize the first letter in a string
1325: * @param name the string to capitalize
1326: * @return the capitalized string
1327: */
1328: public static String capitalize(String name) {
1329: if (name == null || name.length() == 0) {
1330: return name;
1331: }
1332: char chars[] = name.toCharArray();
1333: chars[0] = Character.toUpperCase(chars[0]);
1334: return new String(chars);
1335: }
1336:
1337: /*
1338: * Return service QName
1339: */
1340: /**
1341: * gets the <code>wsdl:serviceName</code> for a given implementation class
1342: * @param implClass the implementation class
1343: * @return the <code>wsdl:serviceName</code> for the <code>implClass</code>
1344: */
1345: public static QName getServiceName(Class<?> implClass) {
1346: if (implClass.isInterface()) {
1347: throw new RuntimeModelerException(
1348: "runtime.modeler.cannot.get.serviceName.from.interface",
1349: implClass.getCanonicalName());
1350: }
1351:
1352: String name = implClass.getSimpleName() + SERVICE;
1353: String packageName = "";
1354: if (implClass.getPackage() != null)
1355: packageName = implClass.getPackage().getName();
1356:
1357: WebService webService = implClass
1358: .getAnnotation(WebService.class);
1359: if (webService == null) {
1360: throw new RuntimeModelerException(
1361: "runtime.modeler.no.webservice.annotation",
1362: implClass.getCanonicalName());
1363: }
1364: if (webService.serviceName().length() > 0) {
1365: name = webService.serviceName();
1366: }
1367: String targetNamespace = getNamespace(packageName);
1368: if (webService.targetNamespace().length() > 0) {
1369: targetNamespace = webService.targetNamespace();
1370: } else if (targetNamespace == null) {
1371: throw new RuntimeModelerException(
1372: "runtime.modeler.no.package", implClass.getName());
1373: }
1374:
1375: return new QName(targetNamespace, name);
1376: }
1377:
1378: /**
1379: * gets the <code>wsdl:portName</code> for a given implementation class
1380: * @param implClass the implementation class
1381: * @param targetNamespace Namespace URI for service name
1382: * @return the <code>wsdl:portName</code> for the <code>implClass</code>
1383: */
1384: public static QName getPortName(Class<?> implClass,
1385: String targetNamespace) {
1386: WebService webService = implClass
1387: .getAnnotation(WebService.class);
1388: if (webService == null) {
1389: throw new RuntimeModelerException(
1390: "runtime.modeler.no.webservice.annotation",
1391: implClass.getCanonicalName());
1392: }
1393: String name;
1394: if (webService.portName().length() > 0) {
1395: name = webService.portName();
1396: } else if (webService.name().length() > 0) {
1397: name = webService.name() + PORT;
1398: } else {
1399: name = implClass.getSimpleName() + PORT;
1400: }
1401:
1402: if (targetNamespace == null) {
1403: if (webService.targetNamespace().length() > 0) {
1404: targetNamespace = webService.targetNamespace();
1405: } else {
1406: String packageName = null;
1407: if (implClass.getPackage() != null) {
1408: packageName = implClass.getPackage().getName();
1409: }
1410: targetNamespace = getNamespace(packageName);
1411: if (targetNamespace == null) {
1412: throw new RuntimeModelerException(
1413: "runtime.modeler.no.package", implClass
1414: .getName());
1415: }
1416: }
1417:
1418: }
1419:
1420: return new QName(targetNamespace, name);
1421: }
1422:
1423: /**
1424: * Gives portType QName from implementatorClass or SEI
1425: * @param implOrSeiClass cant be null
1426: * @return <code>wsdl:portType@name</code>, null if it could not find the annotated class.
1427: */
1428: public static QName getPortTypeName(Class<?> implOrSeiClass) {
1429: assert (implOrSeiClass != null);
1430: Class<?> clazz = implOrSeiClass;
1431: if (!implOrSeiClass.isAnnotationPresent(WebService.class))
1432: throw new RuntimeModelerException(
1433: "runtime.modeler.no.webservice.annotation",
1434: implOrSeiClass.getCanonicalName());
1435:
1436: if (!implOrSeiClass.isInterface()) {
1437: WebService webService = implOrSeiClass
1438: .getAnnotation(WebService.class);
1439: String epi = webService.endpointInterface();
1440: if (epi.length() > 0) {
1441: try {
1442: clazz = Thread.currentThread()
1443: .getContextClassLoader().loadClass(epi);
1444: } catch (ClassNotFoundException e) {
1445: throw new RuntimeModelerException(
1446: "runtime.modeler.class.not.found", epi);
1447: }
1448: if (!clazz
1449: .isAnnotationPresent(javax.jws.WebService.class)) {
1450: throw new RuntimeModelerException(
1451: "runtime.modeler.endpoint.interface.no.webservice",
1452: webService.endpointInterface());
1453: }
1454: }
1455: }
1456:
1457: WebService webService = clazz.getAnnotation(WebService.class);
1458: String name = webService.name();
1459: if (name.length() == 0) {
1460: name = clazz.getSimpleName();
1461: }
1462:
1463: String tns = webService.targetNamespace();
1464: if (tns.length() == 0)
1465: tns = getNamespace(clazz.getPackage().getName());
1466: if (tns == null) {
1467: throw new RuntimeModelerException(
1468: "runtime.modeler.no.package", clazz.getName());
1469: }
1470: return new QName(tns, name);
1471: }
1472:
1473: private ParameterBinding getBinding(String operation, String part,
1474: boolean isHeader, Mode mode) {
1475: if (binding == null) {
1476: if (isHeader)
1477: return ParameterBinding.HEADER;
1478: else
1479: return ParameterBinding.BODY;
1480: }
1481: QName opName = new QName(binding.getBinding().getPortType()
1482: .getName().getNamespaceURI(), operation);
1483: return binding.getBinding().getBinding(opName, part, mode);
1484: }
1485:
1486: private WSDLPart getPart(QName opName, String partName, Mode mode) {
1487: if (binding != null) {
1488: WSDLBoundOperationImpl bo = binding.getBinding()
1489: .get(opName);
1490: if (bo != null)
1491: return bo.getPart(partName, mode);
1492: }
1493: return null;
1494: }
1495: }
|