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.interceptor;
019:
020: import java.net.URI;
021: import java.net.URISyntaxException;
022: import java.util.ArrayList;
023: import java.util.Collection;
024: import java.util.Iterator;
025: import java.util.List;
026: import java.util.ResourceBundle;
027: import java.util.logging.Logger;
028:
029: import javax.xml.namespace.QName;
030: import javax.xml.stream.XMLStreamConstants;
031: import javax.xml.stream.XMLStreamReader;
032:
033: import org.apache.cxf.common.i18n.BundleUtils;
034: import org.apache.cxf.databinding.DataReader;
035: import org.apache.cxf.endpoint.Endpoint;
036: import org.apache.cxf.message.Exchange;
037: import org.apache.cxf.message.Message;
038: import org.apache.cxf.message.MessageContentsList;
039: import org.apache.cxf.phase.Phase;
040: import org.apache.cxf.service.Service;
041: import org.apache.cxf.service.model.BindingMessageInfo;
042: import org.apache.cxf.service.model.BindingOperationInfo;
043: import org.apache.cxf.service.model.EndpointInfo;
044: import org.apache.cxf.service.model.MessageInfo;
045: import org.apache.cxf.service.model.MessagePartInfo;
046: import org.apache.cxf.service.model.OperationInfo;
047: import org.apache.cxf.service.model.ServiceInfo;
048: import org.apache.cxf.staxutils.DepthXMLStreamReader;
049: import org.apache.cxf.staxutils.StaxUtils;
050: import org.apache.ws.commons.schema.XmlSchemaElement;
051:
052: public class DocLiteralInInterceptor extends
053: AbstractInDatabindingInterceptor {
054: private static final Logger LOG = Logger
055: .getLogger(DocLiteralInInterceptor.class.getName());
056: private static final ResourceBundle BUNDLE = BundleUtils
057: .getBundle(DocLiteralInInterceptor.class);
058:
059: public DocLiteralInInterceptor() {
060: super (Phase.UNMARSHAL);
061: addAfter(URIMappingInterceptor.class.getName());
062: addBefore(WrappedInInterceptor.class.getName());
063: }
064:
065: public void handleMessage(Message message) {
066: if (isGET(message) && message.getContent(List.class) != null) {
067: LOG
068: .info("DocLiteralInInterceptor skipped in HTTP GET method");
069: return;
070: }
071:
072: DepthXMLStreamReader xmlReader = getXMLStreamReader(message);
073: DataReader<XMLStreamReader> dr = getDataReader(message);
074: MessageContentsList parameters = new MessageContentsList();
075:
076: Exchange exchange = message.getExchange();
077: BindingOperationInfo bop = exchange
078: .get(BindingOperationInfo.class);
079:
080: boolean client = isRequestor(message);
081:
082: //if body is empty and we have BindingOperationInfo, we do not need to match
083: //operation anymore, just return
084: if (!StaxUtils.toNextElement(xmlReader) && bop != null) {
085: // body may be empty for partial response to decoupled request
086: return;
087: }
088:
089: //bop might be a unwrpped, wrap it back so that we can get correct info
090: if (bop != null && bop.isUnwrapped()) {
091: bop = bop.getWrappedOperation();
092: }
093:
094: if (bop == null) {
095: QName startQName = xmlReader.getName();
096: bop = getBindingOperationInfo(exchange, startQName, client);
097: }
098:
099: if (bop != null && bop.isUnwrappedCapable()) {
100: ServiceInfo si = bop.getBinding().getService();
101: // Wrapped case
102: MessageInfo msgInfo = setMessage(message, bop, client, si);
103:
104: // Determine if there is a wrapper class
105: if (msgInfo.getMessageParts().get(0).getTypeClass() != null) {
106: Object wrappedObject = dr.read(msgInfo
107: .getMessageParts().get(0), xmlReader);
108: parameters.put(msgInfo.getMessageParts().get(0),
109: wrappedObject);
110: } else {
111: // Unwrap each part individually if we don't have a wrapper
112:
113: bop = bop.getUnwrappedOperation();
114:
115: msgInfo = setMessage(message, bop, client, si);
116: List<MessagePartInfo> messageParts = msgInfo
117: .getMessageParts();
118: Iterator<MessagePartInfo> itr = messageParts.iterator();
119:
120: // advance just past the wrapped element so we don't get
121: // stuck
122: if (xmlReader.getEventType() == XMLStreamConstants.START_ELEMENT) {
123: StaxUtils.nextEvent(xmlReader);
124: }
125:
126: // loop through each child element
127: getPara(xmlReader, dr, parameters, itr, message);
128: }
129:
130: } else {
131: //Bare style
132: BindingMessageInfo msgInfo = null;
133:
134: if (bop != null) { //for xml binding or client side
135: getMessageInfo(message, bop);
136: if (client) {
137: msgInfo = bop.getOutput();
138: } else {
139: msgInfo = bop.getInput();
140: }
141: }
142:
143: Collection<OperationInfo> operations = null;
144: operations = new ArrayList<OperationInfo>();
145: Endpoint ep = exchange.get(Endpoint.class);
146: ServiceInfo si = ep.getEndpointInfo().getService();
147: operations.addAll(si.getInterface().getOperations());
148:
149: if (!StaxUtils.toNextElement(xmlReader)) {
150: // empty input
151:
152: // TO DO : check duplicate operation with no input
153: for (OperationInfo op : operations) {
154: MessageInfo bmsg = op.getInput();
155: if (bmsg.getMessageParts().size() == 0) {
156: BindingOperationInfo boi = ep.getEndpointInfo()
157: .getBinding().getOperation(op);
158: exchange.put(BindingOperationInfo.class, boi);
159: exchange.put(OperationInfo.class, op);
160: exchange.setOneWay(op.isOneWay());
161: }
162: }
163: return;
164: }
165:
166: int paramNum = 0;
167:
168: do {
169: QName elName = xmlReader.getName();
170: Object o = null;
171:
172: MessagePartInfo p;
173: if (!client && msgInfo != null
174: && msgInfo.getMessageParts() != null
175: && msgInfo.getMessageParts().size() == 0) {
176: //no input messagePartInfo
177: return;
178: }
179: if (msgInfo != null
180: && msgInfo.getMessageParts() != null
181: && msgInfo.getMessageParts().size() > 0) {
182: assert msgInfo.getMessageParts().size() > paramNum;
183: p = msgInfo.getMessageParts().get(paramNum);
184: } else {
185: p = findMessagePart(exchange, operations, elName,
186: client, paramNum);
187: }
188:
189: if (p == null) {
190: throw new Fault(
191: new org.apache.cxf.common.i18n.Message(
192: "NO_PART_FOUND", BUNDLE, elName),
193: Fault.FAULT_CODE_CLIENT);
194: }
195:
196: o = dr.read(p, xmlReader);
197: parameters.put(p, o);
198:
199: paramNum++;
200: } while (StaxUtils.toNextElement(xmlReader));
201:
202: }
203:
204: if (parameters.size() > 0) {
205: message.setContent(List.class, parameters);
206: }
207: }
208:
209: private void getPara(DepthXMLStreamReader xmlReader,
210: DataReader<XMLStreamReader> dr,
211: MessageContentsList parameters,
212: Iterator<MessagePartInfo> itr, Message message) {
213:
214: boolean hasNext = true;
215: while (itr.hasNext()) {
216: MessagePartInfo part = itr.next();
217: if (hasNext) {
218: hasNext = StaxUtils.toNextElement(xmlReader);
219: }
220: Object obj = null;
221: if (hasNext) {
222: QName rname = xmlReader.getName();
223: while (part != null
224: && !rname.equals(part.getConcreteName())) {
225: String bindingType = message.getExchange().get(
226: Service.class).getDataBinding().getClass()
227: .getName();
228: if (part.getXmlSchema() instanceof XmlSchemaElement) {
229: if (bindingType.endsWith("AegisDatabinding")) {
230: parameters.add(dr.read(part, xmlReader));
231: } else {
232: //should check minOccurs=0
233: parameters.put(part, null);
234: }
235: }
236:
237: if (itr.hasNext()) {
238: part = itr.next();
239: } else {
240: part = null;
241: }
242: }
243: if (part == null) {
244: return;
245: }
246: if (rname.equals(part.getConcreteName())) {
247: obj = dr.read(part, xmlReader);
248: }
249: }
250: parameters.put(part, obj);
251: }
252: }
253:
254: private MessageInfo setMessage(Message message,
255: BindingOperationInfo operation, boolean requestor,
256: ServiceInfo si) {
257: MessageInfo msgInfo = getMessageInfo(message, operation,
258: requestor);
259: message.put(MessageInfo.class, msgInfo);
260:
261: Exchange ex = message.getExchange();
262: ex.put(BindingOperationInfo.class, operation);
263: ex.put(OperationInfo.class, operation.getOperationInfo());
264: ex.setOneWay(operation.getOperationInfo().isOneWay());
265:
266: //Set standard MessageContext properties required by JAX_WS, but not specific to JAX_WS.
267: message.put(Message.WSDL_OPERATION, operation.getName());
268:
269: QName serviceQName = si.getName();
270: message.put(Message.WSDL_SERVICE, serviceQName);
271:
272: QName interfaceQName = si.getInterface().getName();
273: message.put(Message.WSDL_INTERFACE, interfaceQName);
274:
275: EndpointInfo endpointInfo = ex.get(Endpoint.class)
276: .getEndpointInfo();
277: QName portQName = endpointInfo.getName();
278: message.put(Message.WSDL_PORT, portQName);
279:
280: URI wsdlDescription = endpointInfo
281: .getProperty("URI", URI.class);
282: if (wsdlDescription == null) {
283: String address = endpointInfo.getAddress();
284: try {
285: wsdlDescription = new URI(address + "?wsdl");
286: } catch (URISyntaxException e) {
287: //do nothing
288: }
289: endpointInfo.setProperty("URI", wsdlDescription);
290: }
291: message.put(Message.WSDL_DESCRIPTION, wsdlDescription);
292:
293: return msgInfo;
294: }
295:
296: }
|