001: package org.objectweb.celtix.bus.context;
002:
003: import java.lang.annotation.Annotation;
004: import java.lang.reflect.Method;
005: import java.util.ArrayList;
006: import java.util.Collection;
007: import java.util.logging.Level;
008: import java.util.logging.Logger;
009: import javax.jws.WebParam;
010: import javax.jws.WebResult;
011: import javax.xml.bind.JAXBContext;
012: import javax.xml.transform.Source;
013: import javax.xml.ws.LogicalMessage;
014: import javax.xml.ws.RequestWrapper;
015: import javax.xml.ws.ResponseWrapper;
016: import javax.xml.ws.handler.MessageContext;
017: import org.objectweb.celtix.common.logging.LogUtils;
018: import org.objectweb.celtix.context.ObjectMessageContext;
019: import org.objectweb.celtix.jaxb.WrapperHelper;
020:
021: public class LogicalMessageImpl implements LogicalMessage {
022:
023: private static final Logger LOG = LogUtils
024: .getL7dLogger(LogicalMessageImpl.class);
025:
026: private final LogicalMessageContextImpl msgContext;
027:
028: public LogicalMessageImpl(LogicalMessageContextImpl lmctx) {
029: msgContext = lmctx;
030: }
031:
032: public Source getPayload() {
033: throw new UnsupportedOperationException("getPayload");
034: }
035:
036: public void setPayload(Source arg0) {
037: throw new UnsupportedOperationException("setPayload");
038: }
039:
040: public Object getPayload(JAXBContext jaxbCtx) {
041:
042: if (msgContext.get(ObjectMessageContext.MESSAGE_PAYLOAD) == null) {
043: buildMessagePayload();
044: }
045:
046: return msgContext.get(ObjectMessageContext.MESSAGE_PAYLOAD);
047: }
048:
049: public void setPayload(Object payload, JAXBContext ctx) {
050: msgContext.put(ObjectMessageContext.MESSAGE_PAYLOAD, payload);
051: writePayloadToContext(payload);
052: }
053:
054: private void buildMessagePayload() {
055:
056: Object payload = null;
057:
058: if (isRequest()) {
059: Object[] args = (Object[]) msgContext
060: .get(ObjectMessageContext.METHOD_PARAMETERS);
061: if (args == null || args.length == 0) {
062:
063: // no arguments expected in message, so leave payload as
064: // null and return
065: assert msgContext
066: .get(ObjectMessageContext.MESSAGE_PAYLOAD) == null;
067: return;
068: }
069: payload = buildPayloadFromRequest(args);
070: } else {
071: payload = buildPayloadFromResponse();
072: }
073: msgContext.put(ObjectMessageContext.MESSAGE_PAYLOAD, payload);
074: }
075:
076: private Object buildPayloadFromResponse() {
077: Method m = (Method) msgContext
078: .get(ObjectMessageContext.METHOD_OBJ);
079: // TODO -- add support for 'out' params
080: //
081: if (!Void.TYPE.equals(m.getReturnType())) {
082: ResponseWrapper ann = m
083: .getAnnotation(ResponseWrapper.class);
084: assert ann != null : "ResponseWrapper is null";
085: WebResult wr = m.getAnnotation(WebResult.class);
086: assert wr != null : "WebResult is null for method " + m;
087:
088: Object returnVal = msgContext
089: .get(ObjectMessageContext.METHOD_RETURN);
090:
091: // if a handler has aborted the processing sequence, the
092: // return type may be null
093: if (returnVal != null) {
094: Object wrapper = createWrapperInstance(ann.className());
095: setWrapperValue(wrapper, wr.name(), returnVal);
096: return wrapper;
097: }
098: }
099: return null;
100: }
101:
102: private Object buildPayloadFromRequest(Object[] args) {
103:
104: RequestWrapper ann = getMethod().getAnnotation(
105: RequestWrapper.class);
106: assert ann != null : "failed to get request wrapper annotation";
107:
108: Object wrapper = createWrapperInstance(ann.className());
109: int argIndex = 0;
110:
111: Collection<WebParam> annotations = getWebParamAnnotations(getMethod());
112:
113: for (WebParam wp : annotations) {
114: setWrapperValue(wrapper, wp.name(), args[argIndex++]);
115: }
116:
117: return wrapper;
118: }
119:
120: private Object createWrapperInstance(String className) {
121: try {
122: Class<?> wrapperClass = Class.forName(className, true,
123: LogicalMessageContextImpl.class.getClassLoader());
124: return wrapperClass.newInstance();
125: } catch (IllegalAccessException ex) {
126: LOG.log(Level.SEVERE, "WRAPPER_MISSING_DEFAULT_CTOR_MSG",
127: ex);
128: } catch (InstantiationException ex) {
129: LOG.log(Level.SEVERE, "WRAPPER_INSTANTIATION_FAILURE_MSG",
130: ex);
131: } catch (ClassNotFoundException ex) {
132: LOG.log(Level.SEVERE, "WRAPPER_LOAD_FAILURE_MSG", ex);
133: }
134: // should never get here, I think
135: assert false : "unable to create wrappper " + className;
136: return null;
137: }
138:
139: private void writeRequestToContext(Object payload) {
140: Method method = getMethod();
141: Object[] args = new Object[method.getParameterTypes().length];
142: Collection<WebParam> annotations = getWebParamAnnotations(method);
143:
144: int i = 0;
145: for (WebParam wp : annotations) {
146: args[i++] = getAttributeFromWrapper(payload, wp.name());
147: }
148:
149: msgContext.put(ObjectMessageContext.METHOD_PARAMETERS, args);
150: }
151:
152: private void writeResponseToContext(Object payload) {
153:
154: WebResult wr = getMethod().getAnnotation(WebResult.class);
155: assert wr != null : "WebResult is null for method "
156: + getMethod();
157:
158: Object retVal = getAttributeFromWrapper(payload, wr.name());
159: msgContext.put(ObjectMessageContext.METHOD_RETURN, retVal);
160: }
161:
162: private void writePayloadToContext(Object payload) {
163:
164: if (isRequestPayload(payload)) {
165: writeRequestToContext(payload);
166: } else {
167: writeResponseToContext(payload);
168: }
169: }
170:
171: private Object getAttributeFromWrapper(Object wrapper, String name) {
172: assert wrapper != null;
173: assert name != null;
174:
175: Object ret = null;
176: try {
177: String getterName = "get"
178: + Character.toUpperCase(name.charAt(0))
179: + name.substring(1);
180: Method getter = wrapper.getClass().getMethod(getterName);
181: ret = getter.invoke(wrapper);
182: } catch (Exception e) {
183: e.printStackTrace();
184: }
185: assert ret != null : "unable to get attribute: " + name
186: + " from " + wrapper;
187: return ret;
188: }
189:
190: private boolean isRequestPayload(Object payload) {
191:
192: Method m = getMethod();
193:
194: RequestWrapper reqWrapper = m
195: .getAnnotation(RequestWrapper.class);
196: ResponseWrapper respWrapper = m
197: .getAnnotation(ResponseWrapper.class);
198:
199: if (reqWrapper != null) {
200: return payload.getClass().getName().equals(
201: reqWrapper.className());
202: } else if (respWrapper != null) {
203: return !payload.getClass().getName().equals(
204: respWrapper.className());
205: }
206: return true;
207: }
208:
209: private boolean isRequest() {
210:
211: Boolean isInputMsg = (Boolean) msgContext
212: .get(ObjectMessageContext.MESSAGE_INPUT);
213: Boolean isOutbound = (Boolean) msgContext
214: .get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
215:
216: assert isOutbound != null : "MessageContext.MESSAGE_OUTBOUND must be set in context";
217: assert isInputMsg != null : "ObjectMessageContext.MESSAGE_INPUT must be set in context "
218: + msgContext;
219:
220: return (isOutbound && !isInputMsg)
221: || (!isOutbound && !isInputMsg);
222: }
223:
224: private void setWrapperValue(Object wrapper, String name,
225: Object value) {
226:
227: try {
228: WrapperHelper.setWrappedPart(name, wrapper, value);
229: } catch (Exception e) {
230: e.printStackTrace();
231: }
232: }
233:
234: private Collection<WebParam> getWebParamAnnotations(Method m) {
235:
236: Collection<WebParam> ret = new ArrayList<WebParam>();
237:
238: for (Annotation[] anns : m.getParameterAnnotations()) {
239: for (Annotation a : anns) {
240: if (a instanceof WebParam) {
241: ret.add((WebParam) a);
242: }
243: }
244: }
245: return ret;
246: }
247:
248: private Method getMethod() {
249: Method m = (Method) msgContext
250: .get(ObjectMessageContext.METHOD_OBJ);
251: assert m != null : "failed to get method from ObjectMessageContext";
252: return m;
253: }
254: }
|