001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */package org.apache.cxf.jaxws.support;
019:
020: import java.lang.annotation.Annotation;
021: import java.lang.reflect.Method;
022: import java.util.concurrent.Future;
023:
024: import javax.jws.Oneway;
025: import javax.jws.WebMethod;
026: import javax.jws.WebParam;
027: import javax.jws.WebParam.Mode;
028: import javax.jws.WebResult;
029: import javax.jws.WebService;
030: import javax.jws.soap.SOAPBinding;
031: import javax.jws.soap.SOAPBinding.ParameterStyle;
032: import javax.jws.soap.SOAPBinding.Style;
033: import javax.xml.namespace.QName;
034: import javax.xml.ws.Holder;
035: import javax.xml.ws.RequestWrapper;
036: import javax.xml.ws.Response;
037: import javax.xml.ws.ResponseWrapper;
038: import javax.xml.ws.WebFault;
039:
040: import org.apache.cxf.common.classloader.ClassLoaderUtils;
041: import org.apache.cxf.common.util.PackageUtils;
042: import org.apache.cxf.interceptor.Fault;
043: import org.apache.cxf.service.factory.AbstractServiceConfiguration;
044: import org.apache.cxf.service.factory.ReflectionServiceFactoryBean;
045: import org.apache.cxf.service.factory.ServiceConstructionException;
046: import org.apache.cxf.service.model.InterfaceInfo;
047: import org.apache.cxf.service.model.MessageInfo;
048: import org.apache.cxf.service.model.OperationInfo;
049: import org.apache.cxf.tools.util.AnnotationUtil;
050:
051: public class JaxWsServiceConfiguration extends
052: AbstractServiceConfiguration {
053:
054: private JaxWsImplementorInfo implInfo;
055:
056: public JaxWsServiceConfiguration() {
057:
058: }
059:
060: @Override
061: public void setServiceFactory(
062: ReflectionServiceFactoryBean serviceFactory) {
063: super .setServiceFactory(serviceFactory);
064: implInfo = ((JaxWsServiceFactoryBean) serviceFactory)
065: .getJaxWsImplementorInfo();
066: }
067:
068: @Override
069: public String getServiceName() {
070: QName service = implInfo.getServiceName();
071: if (service == null) {
072: return null;
073: } else {
074: return service.getLocalPart();
075: }
076: }
077:
078: @Override
079: public String getServiceNamespace() {
080: QName service = implInfo.getServiceName();
081: if (service == null) {
082: return null;
083: } else {
084: return service.getNamespaceURI();
085: }
086: }
087:
088: @Override
089: public QName getEndpointName() {
090: return implInfo.getEndpointName();
091: }
092:
093: @Override
094: public QName getInterfaceName() {
095: return implInfo.getInterfaceName();
096: }
097:
098: @Override
099: public String getWsdlURL() {
100: String wsdlLocation = implInfo.getWsdlLocation();
101: if (wsdlLocation != null && wsdlLocation.length() > 0) {
102: return wsdlLocation;
103: }
104: return null;
105: }
106:
107: @Override
108: public QName getOperationName(InterfaceInfo intf, Method method) {
109: method = getDeclaredMethod(method);
110:
111: WebMethod wm = method.getAnnotation(WebMethod.class);
112: if (wm != null) {
113: String name = wm.operationName();
114: if (name.length() == 0) {
115: name = method.getName();
116: }
117:
118: return new QName(intf.getName().getNamespaceURI(), name);
119: } else {
120: return new QName(intf.getName().getNamespaceURI(), method
121: .getName());
122: }
123: }
124:
125: @Override
126: public Boolean isOperation(Method method) {
127: Method origMethod = method;
128: method = getDeclaredMethod(method);
129: if (method == null
130: || method.getReturnType().equals(Future.class)
131: || method.getReturnType().equals(Response.class)) {
132: return false;
133: }
134:
135: if (method != null) {
136: WebMethod wm = method.getAnnotation(WebMethod.class);
137: if (wm != null) {
138: if (wm.exclude()) {
139: return Boolean.FALSE;
140: } else {
141: return Boolean.TRUE;
142: }
143: } else {
144: if (method.getDeclaringClass().isInterface()) {
145: return hasWebServiceAnnotation(method)
146: || hasWebServiceAnnotation(origMethod);
147: }
148: return hasWebServiceAnnotation(method);
149: }
150: }
151: return Boolean.FALSE;
152: }
153:
154: private boolean hasWebServiceAnnotation(Method method) {
155: return method.getDeclaringClass().getAnnotation(
156: WebService.class) != null;
157: }
158:
159: Method getDeclaredMethod(Method method) {
160: Class<?> endpointClass = implInfo.getEndpointClass();
161:
162: if (!method.getDeclaringClass().equals(endpointClass)) {
163: try {
164: method = endpointClass.getMethod(method.getName(),
165: (Class[]) method.getParameterTypes());
166: } catch (SecurityException e) {
167: throw new ServiceConstructionException(e);
168: } catch (NoSuchMethodException e) {
169: return null;
170: }
171: }
172: return method;
173: }
174:
175: @Override
176: public QName getInPartName(OperationInfo op, Method method,
177: int paramNumber) {
178: if (paramNumber < 0) {
179: return null;
180: }
181:
182: return getPartName(op, method, paramNumber, op.getInput(),
183: "arg", true);
184: }
185:
186: @Override
187: public QName getInParameterName(OperationInfo op, Method method,
188: int paramNumber) {
189: if (paramNumber < 0) {
190: return null;
191: }
192:
193: return getParameterName(op, method, paramNumber, op.getInput()
194: .size(), "arg", true);
195: }
196:
197: private QName getPartName(OperationInfo op, Method method,
198: int paramNumber, MessageInfo mi, String prefix, boolean isIn) {
199: int partIndex = getPartIndex(method, paramNumber, isIn);
200: method = getDeclaredMethod(method);
201: WebParam param = getWebParam(method, paramNumber);
202: String tns = mi.getName().getNamespaceURI();
203: String local = null;
204: if (param != null) {
205: if (Boolean.TRUE.equals(isRPC(method))
206: || isDocumentBare(method)) {
207: local = param.partName();
208: }
209: if (local == null || local.length() == 0) {
210: local = param.name();
211: }
212: }
213:
214: if (local == null || local.length() == 0) {
215: if (Boolean.TRUE.equals(isRPC(method))
216: || !Boolean.FALSE.equals(isWrapped(method))) {
217: local = getDefaultLocalName(op, method, paramNumber,
218: partIndex, prefix);
219: } else {
220: local = getOperationName(op.getInterface(), method)
221: .getLocalPart();
222: }
223: }
224:
225: return new QName(tns, local);
226: }
227:
228: private int getPartIndex(Method method, int paraNumber, boolean isIn) {
229: int ret = 0;
230: if (isIn && isInParam(method, paraNumber)) {
231: for (int i = 0; i < paraNumber; i++) {
232: if (isInParam(method, i)) {
233: ret++;
234: }
235: }
236: }
237: if (!isIn && isOutParam(method, paraNumber)) {
238: if (!method.getReturnType().equals(Void.class)) {
239: ret++;
240: }
241: for (int i = 0; i < paraNumber; i++) {
242: if (isOutParam(method, i)) {
243: ret++;
244: }
245: }
246: }
247: return ret;
248: }
249:
250: private QName getParameterName(OperationInfo op, Method method,
251: int paramNumber, int curSize, String prefix, boolean input) {
252: int partIndex = getPartIndex(method, paramNumber, input);
253: method = getDeclaredMethod(method);
254: WebParam param = getWebParam(method, paramNumber);
255: String tns = null;
256: String local = null;
257: if (param != null) {
258: tns = param.targetNamespace();
259: local = param.name();
260: }
261:
262: if (tns == null || tns.length() == 0) {
263: QName wrappername = null;
264: if (input) {
265: wrappername = getRequestWrapperName(op, method);
266: } else {
267: wrappername = getResponseWrapperName(op, method);
268: }
269: if (wrappername != null) {
270: tns = wrappername.getNamespaceURI();
271: }
272: }
273: if (tns == null || tns.length() == 0) {
274: tns = op.getName().getNamespaceURI();
275: }
276:
277: if (local == null || local.length() == 0) {
278: if (Boolean.TRUE.equals(isRPC(method))
279: || !Boolean.FALSE.equals(isWrapped(method))) {
280: local = getDefaultLocalName(op, method, paramNumber,
281: partIndex, prefix);
282: } else {
283: local = getOperationName(op.getInterface(), method)
284: .getLocalPart();
285: if (!input) {
286: local += "Response";
287: }
288: }
289: }
290:
291: return new QName(tns, local);
292: }
293:
294: private String getDefaultLocalName(OperationInfo op, Method method,
295: int paramNumber, int partIndex, String prefix) {
296: String paramName = null;
297: if (paramNumber != -1) {
298: paramName = prefix + partIndex;
299: } else {
300: paramName = prefix;
301: }
302: return paramName;
303: }
304:
305: private WebParam getWebParam(Method method, int parameter) {
306: Annotation[][] annotations = method.getParameterAnnotations();
307: if (parameter >= annotations.length) {
308: return null;
309: } else {
310: for (int i = 0; i < annotations[parameter].length; i++) {
311: Annotation annotation = annotations[parameter][i];
312: // With the ibm jdk, the condition:
313: // if (annotation.annotationType().equals(WebParam.class)) {
314: // SOMETIMES returns false even when the annotation type
315: // is a WebParam. Doing an instanceof check or using the
316: // == operator seems to give the desired result.
317: if (annotation instanceof WebParam) {
318: return (WebParam) annotation;
319: }
320: }
321: return null;
322: }
323: }
324:
325: @Override
326: public QName getOutParameterName(OperationInfo op, Method method,
327: int paramNumber) {
328: method = getDeclaredMethod(method);
329:
330: if (paramNumber >= 0) {
331: return getParameterName(op, method, paramNumber, op
332: .getOutput().size(), "return", false);
333: } else {
334: WebResult webResult = getWebResult(method);
335:
336: String tns = null;
337: String local = null;
338: if (webResult != null) {
339: tns = webResult.targetNamespace();
340: local = webResult.name();
341: }
342: if (tns == null || tns.length() == 0) {
343: QName wrappername = getResponseWrapperName(op, method);
344: if (wrappername != null) {
345: tns = wrappername.getNamespaceURI();
346: }
347: }
348:
349: if (tns == null || tns.length() == 0) {
350: tns = op.getName().getNamespaceURI();
351: }
352:
353: if (local == null || local.length() == 0) {
354: if (Boolean.TRUE.equals(isRPC(method))
355: || !Boolean.FALSE.equals(isWrapped(method))) {
356: local = getDefaultLocalName(op, method,
357: paramNumber, op.getOutput().size(),
358: "return");
359: } else {
360: local = getOperationName(op.getInterface(), method)
361: .getLocalPart()
362: + "Response";
363: }
364: }
365:
366: return new QName(tns, local);
367: }
368: }
369:
370: @Override
371: public QName getOutPartName(OperationInfo op, Method method,
372: int paramNumber) {
373: method = getDeclaredMethod(method);
374:
375: if (paramNumber >= 0) {
376: return getPartName(op, method, paramNumber, op.getOutput(),
377: "return", false);
378: } else {
379: WebResult webResult = getWebResult(method);
380: String tns = op.getOutput().getName().getNamespaceURI();
381: String local = null;
382: if (webResult != null) {
383: if (Boolean.TRUE.equals(isRPC(method))
384: || isDocumentBare(method)) {
385: local = webResult.partName();
386: }
387: if (local == null || local.length() == 0) {
388: local = webResult.name();
389: }
390: }
391:
392: if (local == null || local.length() == 0) {
393: if (Boolean.TRUE.equals(isRPC(method))
394: || !Boolean.FALSE.equals(isWrapped(method))) {
395: local = "return";
396: } else {
397: local = getOperationName(op.getInterface(), method)
398: .getLocalPart()
399: + "Response";
400: }
401: }
402:
403: return new QName(tns, local);
404: }
405: }
406:
407: @Override
408: public Boolean isInParam(Method method, int j) {
409: if (j < 0) {
410: return Boolean.FALSE;
411: }
412:
413: method = getDeclaredMethod(method);
414:
415: WebParam webParam = getWebParam(method, j);
416:
417: return webParam == null
418: || (webParam.mode().equals(Mode.IN) || webParam.mode()
419: .equals(Mode.INOUT));
420: }
421:
422: private WebResult getWebResult(Method method) {
423: return method.getAnnotation(WebResult.class);
424: }
425:
426: @Override
427: public Boolean isOutParam(Method method, int j) {
428: method = getDeclaredMethod(method);
429: if (j == -1) {
430: return !method.getReturnType().equals(void.class);
431: }
432:
433: WebParam webParam = getWebParam(method, j);
434:
435: if (webParam != null
436: && (webParam.mode().equals(Mode.OUT) || webParam.mode()
437: .equals(Mode.INOUT))) {
438: return Boolean.TRUE;
439: }
440:
441: return method.getParameterTypes()[j] == Holder.class;
442: }
443:
444: @Override
445: public QName getRequestWrapperName(OperationInfo op, Method method) {
446: Method m = getDeclaredMethod(method);
447: RequestWrapper rw = m.getAnnotation(RequestWrapper.class);
448: if (rw == null) {
449: return null;
450: }
451: String nm = rw.targetNamespace();
452: String lp = rw.localName();
453: if (nm.length() > 0 && lp.length() > 0) {
454: return new QName(nm, lp);
455: }
456: return null;
457: }
458:
459: @Override
460: public QName getResponseWrapperName(OperationInfo op, Method method) {
461: Method m = getDeclaredMethod(method);
462: ResponseWrapper rw = m.getAnnotation(ResponseWrapper.class);
463: if (rw == null) {
464: return null;
465: }
466: String nm = rw.targetNamespace();
467: String lp = rw.localName();
468: if (nm.length() > 0 && lp.length() > 0) {
469: return new QName(nm, lp);
470: }
471: return null;
472: }
473:
474: @Override
475: public Class getResponseWrapper(Method selected) {
476: Method m = getDeclaredMethod(selected);
477:
478: ResponseWrapper rw = m.getAnnotation(ResponseWrapper.class);
479: String clsName = "";
480: if (rw == null) {
481: clsName = getPackageName(selected) + ".jaxws."
482: + AnnotationUtil.capitalize(selected.getName())
483: + "Response";
484: } else {
485: clsName = rw.className();
486: }
487:
488: if (clsName.length() > 0) {
489: try {
490: return ClassLoaderUtils.loadClass(clsName, implInfo
491: .getEndpointClass());
492: } catch (ClassNotFoundException e) {
493: //do nothing, we will mock a schema for wrapper bean later on
494: }
495: }
496:
497: return null;
498: }
499:
500: @Override
501: public String getResponseWrapperClassName(Method selected) {
502: Method m = getDeclaredMethod(selected);
503:
504: ResponseWrapper rw = m.getAnnotation(ResponseWrapper.class);
505: String clsName = "";
506: if (rw != null) {
507: clsName = rw.className();
508: }
509: if (clsName.length() > 0) {
510: return clsName;
511: }
512: return null;
513: }
514:
515: public String getRequestWrapperClassName(Method selected) {
516: Method m = getDeclaredMethod(selected);
517:
518: RequestWrapper rw = m.getAnnotation(RequestWrapper.class);
519: String clsName = "";
520: if (rw != null) {
521: clsName = rw.className();
522: }
523: if (clsName.length() > 0) {
524: return clsName;
525: }
526: return null;
527: }
528:
529: @Override
530: public Class getRequestWrapper(Method selected) {
531: Method m = getDeclaredMethod(selected);
532:
533: RequestWrapper rw = m.getAnnotation(RequestWrapper.class);
534: String clsName = "";
535: if (rw == null) {
536: clsName = getPackageName(selected) + ".jaxws."
537: + AnnotationUtil.capitalize(selected.getName());
538: } else {
539: clsName = rw.className();
540: }
541:
542: if (clsName.length() > 0) {
543: try {
544: return ClassLoaderUtils.loadClass(clsName, implInfo
545: .getEndpointClass());
546: } catch (ClassNotFoundException e) {
547: //do nothing, we will mock a schema for wrapper bean later on
548: }
549: }
550:
551: return null;
552: }
553:
554: private static String getPackageName(Method method) {
555: return PackageUtils.getPackageName(method.getDeclaringClass());
556: }
557:
558: @Override
559: public QName getFaultName(InterfaceInfo service, OperationInfo o,
560: Class<?> exClass, Class<?> beanClass) {
561: WebFault fault = exClass.getAnnotation(WebFault.class);
562: if (fault != null) {
563: String name = fault.name();
564: if (name.length() == 0) {
565: name = exClass.getSimpleName();
566: }
567: String ns = fault.targetNamespace();
568: if (ns.length() == 0) {
569: ns = service.getName().getNamespaceURI();
570: }
571:
572: return new QName(ns, name);
573: }
574: return null;
575: }
576:
577: @Override
578: public Boolean isWrapped(Method m) {
579: // see if someone overrode the default value
580: if (getServiceFactory().getWrapped() != null) {
581: return getServiceFactory().getWrapped();
582: }
583: m = getDeclaredMethod(m);
584:
585: SOAPBinding ann = m.getAnnotation(SOAPBinding.class);
586: if (ann != null) {
587: if (ann.style().equals(Style.RPC)) {
588: throw new Fault(
589: new RuntimeException(
590: "Method ["
591: + m.getName()
592: + "] processing error: "
593: + "SOAPBinding can not on method with RPC style"));
594: }
595: return !(ann.parameterStyle().equals(ParameterStyle.BARE));
596: }
597:
598: return isWrapped();
599: }
600:
601: @Override
602: public Boolean isWrapped() {
603: SOAPBinding ann = implInfo.getEndpointClass().getAnnotation(
604: SOAPBinding.class);
605: if (ann != null) {
606: return !(ann.parameterStyle().equals(ParameterStyle.BARE) || ann
607: .style().equals(Style.RPC));
608: }
609: return null;
610: }
611:
612: @Override
613: public Boolean isHeader(Method method, int j) {
614: method = getDeclaredMethod(method);
615: if (j >= 0) {
616: WebParam webParam = getWebParam(method, j);
617: return webParam != null && webParam.header();
618: } else {
619: WebResult webResult = getWebResult(method);
620: return webResult != null && webResult.header();
621: }
622: }
623:
624: @Override
625: public String getStyle() {
626: SOAPBinding ann = implInfo.getEndpointClass().getAnnotation(
627: SOAPBinding.class);
628: if (ann != null) {
629: return ann.style().toString().toLowerCase();
630: }
631: return "document";
632: }
633:
634: private boolean isDocumentBare(Method method) {
635: SOAPBinding ann = method.getAnnotation(SOAPBinding.class);
636: if (ann != null) {
637: return ann.style().equals(SOAPBinding.Style.DOCUMENT)
638: && ann.parameterStyle().equals(
639: SOAPBinding.ParameterStyle.BARE);
640: }
641: ann = implInfo.getEndpointClass().getAnnotation(
642: SOAPBinding.class);
643: if (ann != null) {
644: return ann.style().equals(SOAPBinding.Style.DOCUMENT)
645: && ann.parameterStyle().equals(
646: SOAPBinding.ParameterStyle.BARE);
647: }
648: return false;
649: }
650:
651: @Override
652: public Boolean isRPC(Method method) {
653: SOAPBinding ann = implInfo.getEndpointClass().getAnnotation(
654: SOAPBinding.class);
655: if (ann != null) {
656: return ann.style().equals(SOAPBinding.Style.RPC);
657: }
658: return Boolean.FALSE;
659: }
660:
661: @Override
662: public Boolean hasOutMessage(Method method) {
663: method = getDeclaredMethod(method);
664: return !method.isAnnotationPresent(Oneway.class);
665: }
666:
667: @Override
668: public String getAction(OperationInfo op, Method method) {
669: method = getDeclaredMethod(method);
670: WebMethod wm = method.getAnnotation(WebMethod.class);
671: if (wm != null) {
672: return wm.action();
673: } else {
674: return "";
675: }
676: }
677:
678: }
|