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.interceptors;
019:
020: import java.lang.reflect.Method;
021: import java.util.ArrayList;
022: import java.util.List;
023: import java.util.logging.Logger;
024:
025: import org.apache.cxf.interceptor.Fault;
026: import org.apache.cxf.message.Exchange;
027: import org.apache.cxf.message.Message;
028: import org.apache.cxf.message.MessageContentsList;
029: import org.apache.cxf.phase.AbstractPhaseInterceptor;
030: import org.apache.cxf.phase.Phase;
031: import org.apache.cxf.service.model.BindingMessageInfo;
032: import org.apache.cxf.service.model.BindingOperationInfo;
033: import org.apache.cxf.service.model.MessageInfo;
034: import org.apache.cxf.service.model.MessagePartInfo;
035: import org.apache.cxf.service.model.OperationInfo;
036:
037: public class WrapperClassInInterceptor extends
038: AbstractPhaseInterceptor<Message> {
039:
040: private static final Logger LOG = Logger
041: .getLogger(WrapperClassInInterceptor.class.getName());
042:
043: public WrapperClassInInterceptor() {
044: super (Phase.POST_LOGICAL);
045: }
046:
047: public void handleMessage(Message message) throws Fault {
048: Exchange ex = message.getExchange();
049: BindingOperationInfo boi = ex.get(BindingOperationInfo.class);
050: if (boi == null) {
051: return;
052: }
053:
054: Method method = ex.get(Method.class);
055:
056: if (method != null && method.getName().endsWith("Async")) {
057: Class<?> retType = method.getReturnType();
058: if (retType.getName().equals("java.util.concurrent.Future")
059: || retType.getName()
060: .equals("javax.xml.ws.Response")) {
061: return;
062: }
063: }
064:
065: if (boi != null && boi.isUnwrappedCapable()) {
066: BindingOperationInfo boi2 = boi.getUnwrappedOperation();
067: OperationInfo op = boi2.getOperationInfo();
068: BindingMessageInfo bmi;
069:
070: MessageInfo wrappedMessageInfo = message
071: .get(MessageInfo.class);
072: MessageInfo messageInfo;
073: if (wrappedMessageInfo == boi.getOperationInfo().getInput()) {
074: messageInfo = op.getInput();
075: bmi = boi2.getInput();
076: } else {
077: messageInfo = op.getOutput();
078: bmi = boi2.getOutput();
079: }
080:
081: // Sometimes, an operation can be unwrapped according to WSDLServiceFactory,
082: // but not according to JAX-WS. We should unify these at some point, but
083: // for now check for the wrapper class.
084: MessageContentsList lst = MessageContentsList
085: .getContentsList(message);
086: if (lst == null) {
087: return;
088: }
089: Class<?> wrapperClass = null;
090: Object wrappedObject = null;
091: MessagePartInfo wrapperPart = null;
092: if (wrappedMessageInfo != null) {
093: for (MessagePartInfo part : wrappedMessageInfo
094: .getMessageParts()) {
095: //headers should appear in both, find the part that doesn't
096: if (messageInfo.getMessagePart(part.getName()) == null) {
097: wrapperClass = part.getTypeClass();
098: for (Object o : lst) {
099: if (wrapperClass.isInstance(o)) {
100: wrappedObject = o;
101: wrapperPart = part;
102: break;
103: }
104: }
105: break;
106: }
107: }
108: }
109:
110: if (lst != null) {
111: message.put(MessageInfo.class, messageInfo);
112: message.put(BindingMessageInfo.class, bmi);
113: ex.put(BindingOperationInfo.class, boi2);
114: ex.put(OperationInfo.class, op);
115: }
116: if (isGET(message)) {
117: LOG
118: .info("WrapperClassInInterceptor skipped in HTTP GET method");
119: return;
120: }
121: if (wrapperClass == null || wrappedObject == null) {
122: return;
123: }
124:
125: WrapperHelper helper = wrapperPart.getProperty(
126: "WRAPPER_CLASS", WrapperHelper.class);
127: if (helper == null) {
128: helper = createWrapperHelper(messageInfo,
129: wrappedMessageInfo, wrapperClass);
130: wrapperPart.setProperty("WRAPPER_CLASS", helper);
131: }
132:
133: MessageContentsList newParams;
134: try {
135: newParams = new MessageContentsList(helper
136: .getWrapperParts(wrappedObject));
137:
138: for (MessagePartInfo part : messageInfo
139: .getMessageParts()) {
140: if (wrappedMessageInfo.getMessagePart(part
141: .getName()) != null) {
142: newParams.put(part, lst.get(part));
143: }
144: }
145: } catch (Exception e) {
146: throw new Fault(e);
147: }
148:
149: message.setContent(List.class, newParams);
150: }
151: }
152:
153: private WrapperHelper createWrapperHelper(MessageInfo messageInfo,
154: MessageInfo wrappedMessageInfo, Class<?> wrapperClass) {
155: List<String> partNames = new ArrayList<String>();
156: List<String> elTypeNames = new ArrayList<String>();
157: List<Class<?>> partClasses = new ArrayList<Class<?>>();
158:
159: for (MessagePartInfo p : messageInfo.getMessageParts()) {
160: if (wrappedMessageInfo.getMessagePart(p.getName()) != null) {
161: int idx = p.getIndex();
162: ensureSize(elTypeNames, idx);
163: ensureSize(partClasses, idx);
164: ensureSize(partNames, idx);
165: elTypeNames.set(idx, null);
166: partClasses.set(idx, null);
167: partNames.set(idx, null);
168: } else {
169: String elementType = null;
170: if (p.isElement()) {
171: elementType = p.getElementQName().getLocalPart();
172: } else {
173: if (p.getTypeQName() == null) {
174: // handling anonymous complex type
175: elementType = null;
176: } else {
177: elementType = p.getTypeQName().getLocalPart();
178: }
179: }
180: int idx = p.getIndex();
181: ensureSize(elTypeNames, idx);
182: ensureSize(partClasses, idx);
183: ensureSize(partNames, idx);
184:
185: elTypeNames.set(idx, elementType);
186: partClasses.set(idx, p.getTypeClass());
187: partNames.set(idx, p.getName().getLocalPart());
188: }
189: }
190: return WrapperHelper.createWrapperHelper(wrapperClass,
191: partNames, elTypeNames, partClasses);
192: }
193:
194: private void ensureSize(List<?> lst, int idx) {
195: while (idx >= lst.size()) {
196: lst.add(null);
197: }
198: }
199: }
|