001: package org.objectweb.celtix.bus.jaxws;
002:
003: import java.lang.annotation.Annotation;
004: import java.lang.reflect.InvocationTargetException;
005: import java.lang.reflect.Method;
006: import java.util.logging.Level;
007: import java.util.logging.Logger;
008:
009: import javax.jws.Oneway;
010: import javax.jws.WebMethod;
011: import javax.jws.WebParam;
012: import javax.jws.WebResult;
013: import javax.jws.WebService;
014: import javax.jws.soap.SOAPBinding;
015: import javax.jws.soap.SOAPBinding.Style;
016: import javax.xml.bind.JAXBContext;
017: import javax.xml.namespace.QName;
018: import javax.xml.soap.Detail;
019: import javax.xml.soap.SOAPFault;
020: import javax.xml.validation.Schema;
021: import javax.xml.ws.AsyncHandler;
022: import javax.xml.ws.Holder;
023: import javax.xml.ws.RequestWrapper;
024: import javax.xml.ws.ResponseWrapper;
025: import javax.xml.ws.WebFault;
026: import javax.xml.ws.WebServiceException;
027:
028: import org.w3c.dom.Node;
029:
030: import org.objectweb.celtix.bindings.DataReader;
031: import org.objectweb.celtix.bindings.DataWriter;
032: import org.objectweb.celtix.bindings.ServerDataBindingCallback;
033: import org.objectweb.celtix.bus.bindings.soap.SOAPConstants;
034: import org.objectweb.celtix.bus.bindings.xml.XMLFault;
035: import org.objectweb.celtix.bus.jaxws.io.DetailDataWriter;
036: import org.objectweb.celtix.bus.jaxws.io.NodeDataReader;
037: import org.objectweb.celtix.bus.jaxws.io.NodeDataWriter;
038: import org.objectweb.celtix.bus.jaxws.io.SOAPFaultDataReader;
039: import org.objectweb.celtix.bus.jaxws.io.XMLFaultReader;
040: import org.objectweb.celtix.bus.jaxws.io.XMLFaultWriter;
041: import org.objectweb.celtix.common.logging.LogUtils;
042: import org.objectweb.celtix.context.ObjectMessageContext;
043: import org.objectweb.celtix.jaxb.JAXBUtils;
044: import org.objectweb.celtix.jaxb.WrapperHelper;
045:
046: public class JAXBDataBindingCallback implements
047: ServerDataBindingCallback {
048:
049: private static final Logger LOG = LogUtils
050: .getL7dLogger(JAXBDataBindingCallback.class);
051:
052: private SOAPBinding soapBindAnnotation;
053: private WebMethod webMethodAnnotation;
054: private WebResult webResultAnnotation;
055: private Annotation[][] paramAnnotations;
056: private RequestWrapper reqWrapper;
057: private ResponseWrapper respWrapper;
058: private final Method method;
059: private Method syncMethod;
060: private final Mode mode;
061: private WebService webServiceAnnotation;
062: private final JAXBContext context;
063: private final Schema schema;
064: private final EndpointImpl endpoint;
065: private final Object impl;
066:
067: public JAXBDataBindingCallback(Method m, Mode md, JAXBContext ctx) {
068: this (m, md, ctx, null);
069: }
070:
071: public JAXBDataBindingCallback(Method m, Mode md, JAXBContext ctx,
072: Schema s) {
073: this (m, md, ctx, s, null);
074: }
075:
076: public JAXBDataBindingCallback(Method m, Mode md, JAXBContext ctx,
077: Schema s, EndpointImpl ep) {
078: method = m;
079: mode = md;
080: context = ctx;
081: schema = s;
082: endpoint = ep;
083: impl = null;
084: init();
085: }
086:
087: public JAXBDataBindingCallback(Method m, Mode md, JAXBContext ctx,
088: Schema s, Object obj) {
089: method = m;
090: mode = md;
091: context = ctx;
092: schema = s;
093: endpoint = null;
094: impl = obj;
095: init();
096: }
097:
098: public JAXBContext getJAXBContext() {
099: return context;
100: }
101:
102: public Schema getSchema() {
103: return schema;
104: }
105:
106: public Mode getMode() {
107: return mode;
108: }
109:
110: public Class<?>[] getSupportedFormats() {
111: if (mode == Mode.PARTS) {
112: return new Class<?>[] { Node.class, Detail.class,
113: SOAPFault.class };
114: }
115: // TODO Auto-generated method stub
116: return null;
117: }
118:
119: public <T> DataWriter<T> createWriter(Class<T> cls) {
120: if (cls == Node.class) {
121: return new NodeDataWriter<T>(this );
122: } else if (cls == Detail.class) {
123: return new DetailDataWriter<T>(this );
124: } else if (cls == XMLFault.class) {
125: return new XMLFaultWriter<T>(this );
126: }
127: // TODO Auto-generated method stub
128: return null;
129: }
130:
131: public <T> DataReader<T> createReader(Class<T> cls) {
132: if (cls == Node.class) {
133: return new NodeDataReader<T>(this );
134: } else if (cls == SOAPFault.class) {
135: return new SOAPFaultDataReader<T>(this );
136: } else if (cls == XMLFault.class) {
137: return new XMLFaultReader<T>(this );
138: }
139: // TODO Auto-generated method stub
140: return null;
141: }
142:
143: private void init() {
144: if (method != null) {
145: //Get WebService Annotation.
146: webServiceAnnotation = method.getDeclaringClass()
147: .getAnnotation(WebService.class);
148: //Get SOAP Style, Use,
149: soapBindAnnotation = method
150: .getAnnotation(SOAPBinding.class);
151: if (soapBindAnnotation == null) {
152: soapBindAnnotation = method.getDeclaringClass()
153: .getAnnotation(SOAPBinding.class);
154: }
155: //Get Operation,Action Info
156: webMethodAnnotation = method.getAnnotation(WebMethod.class);
157: //Get Parameter Info
158: paramAnnotations = method.getParameterAnnotations();
159: //Get Return Type Info
160: webResultAnnotation = method.getAnnotation(WebResult.class);
161: //Get the RequestWrapper
162: reqWrapper = method.getAnnotation(RequestWrapper.class);
163: //Get the RequestWrapper
164: respWrapper = method.getAnnotation(ResponseWrapper.class);
165:
166: if (JAXBUtils.isAsync(method)) {
167: Class[] paramTypes = method.getParameterTypes();
168: if (paramTypes != null
169: && paramTypes.length > 0
170: && AsyncHandler.class
171: .isAssignableFrom(paramTypes[paramTypes.length - 1])) {
172: Class[] effectiveParamTypes = new Class[paramTypes.length - 1];
173: System.arraycopy(paramTypes, 0,
174: effectiveParamTypes, 0,
175: paramTypes.length - 1);
176: paramTypes = effectiveParamTypes;
177: }
178: String syncMethodName = method.getName().substring(0,
179: method.getName().lastIndexOf("Async"));
180: try {
181: syncMethod = method.getDeclaringClass().getMethod(
182: syncMethodName, paramTypes);
183: webResultAnnotation = syncMethod
184: .getAnnotation(WebResult.class);
185: assert null != webResultAnnotation;
186: } catch (NoSuchMethodException ex) {
187: LOG.severe("Could not find method "
188: + syncMethodName
189: + " in class declaring method "
190: + method.getName());
191: }
192:
193: if (null == webResultAnnotation) {
194: webResultAnnotation = syncMethod
195: .getAnnotation(WebResult.class);
196: }
197: }
198: }
199: }
200:
201: public boolean isOneWay() {
202: if (method != null) {
203: return method.getAnnotation(Oneway.class) != null;
204: }
205: return false;
206: }
207:
208: public SOAPBinding.Style getSOAPStyle() {
209: if (null != soapBindAnnotation) {
210: return soapBindAnnotation.style();
211: }
212: if (endpoint != null) {
213: return endpoint.getStyle();
214: }
215: return Style.DOCUMENT;
216: }
217:
218: public SOAPBinding.Use getSOAPUse() {
219: if (null != soapBindAnnotation) {
220: return soapBindAnnotation.use();
221: }
222: return SOAPBinding.Use.LITERAL;
223: }
224:
225: public SOAPBinding.ParameterStyle getSOAPParameterStyle() {
226: if (null != soapBindAnnotation) {
227: return soapBindAnnotation.parameterStyle();
228: }
229: return SOAPBinding.ParameterStyle.WRAPPED;
230: }
231:
232: public String getTargetNamespace() {
233: if (webServiceAnnotation == null) {
234: return "";
235: }
236: return webServiceAnnotation.targetNamespace();
237: }
238:
239: public String getOperationName() {
240: if (null != webMethodAnnotation
241: && !"".equals(webMethodAnnotation.operationName())) {
242: return webMethodAnnotation.operationName();
243: }
244: if (getMethod() == null) {
245: return "";
246: }
247: return getMethod().getName();
248: }
249:
250: public String getSOAPAction() {
251: if (null != webMethodAnnotation) {
252: return webMethodAnnotation.action();
253: }
254: return "";
255: }
256:
257: public WebResult getWebResult() {
258: return webResultAnnotation;
259: }
260:
261: public QName getWebResultQName() {
262: if (null != webResultAnnotation) {
263: if (getSOAPStyle() == Style.DOCUMENT) {
264: if ("".equals(webResultAnnotation.name())) {
265: return new QName(webResultAnnotation
266: .targetNamespace(), "return");
267: }
268: return new QName(webResultAnnotation.targetNamespace(),
269: webResultAnnotation.name());
270: } else {
271: return new QName("", webResultAnnotation.partName());
272: }
273: }
274: return SOAPConstants.EMPTY_QNAME;
275: }
276:
277: public WebParam getWebParam(int index) {
278: if (null != paramAnnotations && index < paramAnnotations.length) {
279: for (Annotation annotation : paramAnnotations[index]) {
280: if (WebParam.class.equals(annotation.annotationType())) {
281: return (WebParam) annotation;
282: }
283: }
284: }
285: return null;
286: }
287:
288: public QName getRequestWrapperQName() {
289: if (null != reqWrapper) {
290: return new QName(reqWrapper.targetNamespace(), reqWrapper
291: .localName());
292: }
293: return SOAPConstants.EMPTY_QNAME;
294: }
295:
296: public String getRequestWrapperType() {
297: if (null != reqWrapper) {
298: return reqWrapper.className();
299: }
300: return "";
301: }
302:
303: public QName getResponseWrapperQName() {
304: if (null != respWrapper) {
305: return new QName(respWrapper.targetNamespace(), respWrapper
306: .localName());
307: }
308: return SOAPConstants.EMPTY_QNAME;
309: }
310:
311: public String getResponseWrapperType() {
312: if (null != respWrapper) {
313: return respWrapper.className();
314: }
315: return "";
316: }
317:
318: public Method getMethod() {
319: return method;
320: }
321:
322: public Method getSyncMethod() {
323: return syncMethod;
324: }
325:
326: public Class<?> getWebFault(QName faultName) {
327: for (Class<?> clazz : getMethod().getExceptionTypes()) {
328: WebFault wfAnnotation = clazz.getAnnotation(WebFault.class);
329: if (wfAnnotation != null
330: && (wfAnnotation.name().equals(
331: faultName.getLocalPart()) && wfAnnotation
332: .targetNamespace().equals(
333: faultName.getNamespaceURI()))) {
334: return clazz;
335: }
336: }
337: return null;
338: }
339:
340: public int getParamsLength() {
341: return getMethod() != null ? getMethod().getParameterTypes().length
342: : 0;
343: }
344:
345: public Object createWrapperType(ObjectMessageContext objCtx,
346: boolean isOutBound) {
347: String wrapperType = isOutBound ? getResponseWrapperType()
348: : getRequestWrapperType();
349:
350: Object wrapperObj = null;
351: try {
352:
353: ClassLoader loader = Thread.currentThread()
354: .getContextClassLoader();
355: if (loader == null) {
356: loader = getClass().getClassLoader();
357: }
358:
359: if (!"".equals(wrapperType)) {
360: wrapperObj = Class.forName(wrapperType, true, loader)
361: .newInstance();
362: } else {
363: return null;
364: }
365: } catch (Exception ex) {
366: throw new WebServiceException(
367: "Could not create the wrapper element", ex);
368: }
369:
370: if (isOutBound && getWebResult() != null) {
371: setWrappedPart(getWebResultQName().getLocalPart(),
372: wrapperObj, objCtx.getReturn());
373: }
374:
375: //Add the in,inout,out args depend on the inputMode
376: WebParam.Mode ignoreParamMode = isOutBound ? WebParam.Mode.IN
377: : WebParam.Mode.OUT;
378:
379: int noArgs = getMethod().getParameterTypes().length;
380:
381: //Unmarshal parts of mode that should not be ignored and are not part of the SOAP Headers
382: Object[] args = objCtx.getMessageObjects();
383: for (int idx = 0; idx < noArgs; idx++) {
384: WebParam param = getWebParam(idx);
385: if ((param.mode() != ignoreParamMode) && !param.header()) {
386: Object wrappedObj = args[idx];
387: //Unwrap Holder for inout,out parts.
388: if (param.mode() != WebParam.Mode.IN) {
389: wrappedObj = ((Holder) wrappedObj).value;
390: }
391: if (param.name().equals("asyncHandler")
392: && idx == (noArgs - 1)) {
393: break;
394: }
395:
396: setWrappedPart(param.name(), wrapperObj, wrappedObj);
397: }
398: }
399:
400: return wrapperObj;
401: }
402:
403: public void setWrappedPart(String name, Object wrapperType,
404: Object part) {
405: try {
406: WrapperHelper.setWrappedPart(name, wrapperType, part);
407: } catch (Exception ex) {
408: throw new WebServiceException(
409: "Could not set parts into wrapper element", ex);
410: }
411: }
412:
413: public Object getWrappedPart(String name, Object wrapperType,
414: Class<?> part) {
415: Object obj = null;
416: try {
417: assert wrapperType != null;
418: obj = WrapperHelper.getWrappedPart(name, wrapperType, part);
419: assert obj != null;
420: } catch (Exception ex) {
421: throw new WebServiceException(
422: "Could not get part out of wrapper element", ex);
423: }
424: return obj;
425: }
426:
427: public void initObjectContext(ObjectMessageContext octx) {
428: if (method != null) {
429: octx.put(ObjectMessageContext.METHOD_OBJ, method);
430: try {
431: int idx = 0;
432: Object[] methodArgs = new Object[method
433: .getParameterTypes().length];
434: for (Class<?> cls : method.getParameterTypes()) {
435: if (cls.isAssignableFrom(Holder.class)) {
436: methodArgs[idx] = cls.newInstance();
437: }
438: idx++;
439: }
440: octx.setMessageObjects(methodArgs);
441: } catch (Exception ex) {
442: LOG.log(Level.SEVERE, "INIT_OBJ_CONTEXT_FAILED");
443: throw new WebServiceException(ex);
444: }
445: }
446: }
447:
448: public void invoke(ObjectMessageContext octx)
449: throws InvocationTargetException {
450: Object o = impl;
451: try {
452: if (o == null) {
453: o = endpoint.getImplementor();
454: }
455: Object ret = method.invoke(o, octx.getMessageObjects());
456:
457: octx.setReturn(ret);
458: } catch (InvocationTargetException e) {
459: throw e;
460: } catch (Exception e) {
461: throw new InvocationTargetException(e);
462: } finally {
463: if (impl == null) {
464: endpoint.releaseImplementor(o);
465: }
466: }
467: }
468:
469: }
|