001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.servicemix.cxfbc.interceptors;
019
020 import java.util.ArrayList;
021 import java.util.Collections;
022 import java.util.HashMap;
023 import java.util.List;
024 import java.util.Map;
025
026 import javax.xml.XMLConstants;
027 import javax.xml.namespace.NamespaceContext;
028 import javax.xml.namespace.QName;
029 import javax.xml.stream.Location;
030 import javax.xml.stream.XMLStreamException;
031 import javax.xml.stream.XMLStreamReader;
032
033 import org.apache.cxf.binding.soap.Soap11;
034 import org.apache.cxf.binding.soap.Soap12;
035 import org.apache.cxf.binding.soap.SoapMessage;
036 import org.apache.cxf.binding.soap.model.SoapBindingInfo;
037 import org.apache.cxf.binding.soap.model.SoapHeaderInfo;
038 import org.apache.cxf.endpoint.Endpoint;
039 import org.apache.cxf.helpers.DOMUtils;
040 import org.apache.cxf.interceptor.Fault;
041 import org.apache.cxf.message.Message;
042 import org.apache.cxf.service.model.BindingMessageInfo;
043 import org.apache.cxf.service.model.BindingOperationInfo;
044 import org.apache.cxf.service.model.MessagePartInfo;
045 import org.apache.cxf.staxutils.DepthXMLStreamReader;
046 import org.apache.cxf.staxutils.PartialXMLStreamReader;
047 import org.apache.cxf.staxutils.StaxUtils;
048 import org.apache.servicemix.soap.util.stax.ExtendedXMLStreamReader;
049 import org.apache.servicemix.soap.util.stax.FragmentStreamReader;
050 import org.w3c.dom.Document;
051 import org.w3c.dom.Element;
052 import org.w3c.dom.NamedNodeMap;
053 import org.w3c.dom.Node;
054
055
056 public class StaxJbiWrapper implements XMLStreamReader {
057 public static final int STATE_START_DOC = 0;
058 public static final int STATE_START_ELEMENT_WRAPPER = 1;
059 public static final int STATE_START_ELEMENT_PART = 2;
060 public static final int STATE_RUN_PART = 3;
061 public static final int STATE_END_ELEMENT_PART = 4;
062 public static final int STATE_END_ELEMENT_WRAPPER = 5;
063 public static final int STATE_END_DOC = 6;
064
065 private BindingMessageInfo wsdlMessage;
066 private int state = STATE_START_DOC;
067 private int part = -1;
068 private int reader = -1;
069 private int event = START_DOCUMENT;
070 private List<List<XMLStreamReader>> parts = new ArrayList<List<XMLStreamReader>>();
071 private List<QName> extraPrefixes = new ArrayList<QName>();
072
073 public StaxJbiWrapper(Message message) {
074 setExtraPrefix((SoapMessage) message);
075 BindingOperationInfo wsdlOperation = getOperation(message);
076 wsdlMessage = !isRequestor(message) ? wsdlOperation.getInput() : wsdlOperation.getOutput();
077 XMLStreamReader xmlReader = message.getContent(XMLStreamReader.class);
078 if (isRequestor(message)) {
079 throw new UnsupportedOperationException();
080 }
081 List<SoapHeaderInfo> headers = wsdlMessage
082 .getExtensors(SoapHeaderInfo.class);
083 if (headers != null && headers.size() > 0) {
084 throw new UnsupportedOperationException();
085 }
086 SoapBindingInfo binding = (SoapBindingInfo) message.getExchange()
087 .get(Endpoint.class).getEndpointInfo().getBinding();
088 String style = binding.getStyle(wsdlOperation.getOperationInfo());
089 if (style == null) {
090 style = binding.getStyle();
091 }
092 int nbBodyParts = 0;
093 for (MessagePartInfo part : wsdlMessage.getMessageParts()) {
094 if (nbBodyParts++ > 0) {
095 throw new UnsupportedOperationException();
096 }
097 if ("document".equals(style)) {
098 parts.add(Collections.<XMLStreamReader>singletonList(new FragmentStreamReader(xmlReader)));
099 } else /* rpc-style */ {
100 throw new UnsupportedOperationException();
101 }
102 }
103 }
104
105 private void setExtraPrefix(SoapMessage message) {
106 Document savedEnv = (Document) message.getContent(Node.class);
107 if (savedEnv != null) {
108 NamedNodeMap attrs = savedEnv.getFirstChild().getAttributes();
109 Map<String, String> nsMap = message.getEnvelopeNs();
110 if (nsMap == null) {
111 nsMap = new HashMap<String, String>();
112 }
113 for (int i = 0; i < attrs.getLength(); i++) {
114 Node node = attrs.item(i);
115 if (!node.getNodeValue().equals(Soap11.SOAP_NAMESPACE)
116 && !node.getNodeValue().equals(Soap12.SOAP_NAMESPACE)) {
117 //set extra prefix
118 nsMap.put(node.getLocalName(), node.getNodeValue());
119 if (!node.getNodeValue().equals(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI)
120 && !node.getNodeValue().equals(XMLConstants.W3C_XML_SCHEMA_NS_URI))
121 extraPrefixes.add(new QName(node.getNodeValue(), "", node.getLocalName()));
122 }
123
124 }
125 if (nsMap.size() > 0) {
126 message.put("soap.env.ns.map", nsMap);
127 }
128 }
129 }
130
131
132 public int getEventType() {
133 return event;
134 }
135
136 public int next() throws XMLStreamException {
137 switch (state) {
138 case STATE_START_DOC:
139 state = STATE_START_ELEMENT_WRAPPER;
140 event = START_ELEMENT;
141 break;
142 case STATE_START_ELEMENT_WRAPPER:
143 if (parts.size() > 0) {
144 state = STATE_START_ELEMENT_PART;
145 event = START_ELEMENT;
146 part = 0;
147 reader = 0;
148 } else {
149 state = STATE_END_ELEMENT_WRAPPER;
150 event = END_ELEMENT;
151 }
152 break;
153 case STATE_START_ELEMENT_PART:
154 if (reader >= parts.get(part).size()) {
155 state = STATE_END_ELEMENT_PART;
156 event = END_ELEMENT;
157 } else {
158 state = STATE_RUN_PART;
159 event = parts.get(part).get(reader).next();
160 if (event == START_DOCUMENT) {
161 event = parts.get(part).get(reader).next();
162 }
163 }
164 break;
165 case STATE_RUN_PART:
166 event = parts.get(part).get(reader).next();
167 if (event == END_DOCUMENT) {
168 if (++reader >= parts.get(part).size()) {
169 state = STATE_END_ELEMENT_PART;
170 event = END_ELEMENT;
171 } else {
172 event = parts.get(part).get(reader).next();
173 if (event == START_DOCUMENT) {
174 event = parts.get(part).get(reader).next();
175 }
176 }
177 }
178 break;
179 case STATE_END_ELEMENT_PART:
180 if (++part >= parts.size()) {
181 state = STATE_END_ELEMENT_WRAPPER;
182 event = END_ELEMENT;
183 } else {
184 state = STATE_START_ELEMENT_PART;
185 event = START_ELEMENT;
186 reader = 0;
187 }
188 break;
189 case STATE_END_ELEMENT_WRAPPER:
190 case STATE_END_DOC:
191 state = STATE_END_DOC;
192 event = END_DOCUMENT;
193 break;
194 }
195 return event;
196 }
197
198 public QName getName() {
199 switch (state) {
200 case STATE_START_ELEMENT_WRAPPER:
201 case STATE_END_ELEMENT_WRAPPER:
202 return CxfJbiConstants.WSDL11_WRAPPER_MESSAGE;
203 case STATE_START_ELEMENT_PART:
204 case STATE_END_ELEMENT_PART:
205 return CxfJbiConstants.WSDL11_WRAPPER_PART;
206 case STATE_RUN_PART:
207 return parts.get(part).get(reader).getName();
208 default:
209 throw new IllegalStateException();
210 }
211 }
212
213 public String getLocalName() {
214 switch (state) {
215 case STATE_START_ELEMENT_WRAPPER:
216 case STATE_END_ELEMENT_WRAPPER:
217 return CxfJbiConstants.WSDL11_WRAPPER_MESSAGE_LOCALNAME;
218 case STATE_START_ELEMENT_PART:
219 case STATE_END_ELEMENT_PART:
220 return CxfJbiConstants.WSDL11_WRAPPER_PART_LOCALNAME;
221 case STATE_RUN_PART:
222 return parts.get(part).get(reader).getLocalName();
223 default:
224 throw new IllegalStateException();
225 }
226 }
227
228 public String getNamespaceURI() {
229 switch (state) {
230 case STATE_START_ELEMENT_WRAPPER:
231 case STATE_END_ELEMENT_WRAPPER:
232 case STATE_START_ELEMENT_PART:
233 case STATE_END_ELEMENT_PART:
234 return CxfJbiConstants.WSDL11_WRAPPER_NAMESPACE;
235 case STATE_RUN_PART:
236 return parts.get(part).get(reader).getNamespaceURI();
237 default:
238 throw new IllegalStateException();
239 }
240 }
241
242 public String getPrefix() {
243 switch (state) {
244 case STATE_START_ELEMENT_WRAPPER:
245 case STATE_END_ELEMENT_WRAPPER:
246 case STATE_START_ELEMENT_PART:
247 case STATE_END_ELEMENT_PART:
248 return CxfJbiConstants.WSDL11_WRAPPER_PREFIX;
249 case STATE_RUN_PART:
250 String prefix = parts.get(part).get(reader).getPrefix();
251 String namespaceURI;
252 if (prefix != null && prefix.length() == 0
253 && ((namespaceURI = parts.get(part).get(reader).getNamespaceURI()) != null && namespaceURI.length() > 0)) {
254 return CxfJbiConstants.WSDL11_WRAPPER_PART_LOCALNAME;
255 } else {
256 return prefix;
257 }
258 default:
259 throw new IllegalStateException();
260 }
261 }
262
263 public boolean hasName() {
264 return state == STATE_RUN_PART ? parts.get(part).get(reader).isStartElement() : (event == START_ELEMENT || event == END_ELEMENT);
265 }
266
267 public Object getProperty(String s) throws IllegalArgumentException {
268 return null; //To change body of implemented methods use File | Settings | File Templates.
269 }
270
271 public void require(int i, String s, String s1) throws XMLStreamException {
272 //To change body of implemented methods use File | Settings | File Templates.
273 }
274
275 public String getElementText() throws XMLStreamException {
276 return null; //To change body of implemented methods use File | Settings | File Templates.
277 }
278
279 public int nextTag() throws XMLStreamException {
280 while (hasNext()) {
281 int e = next();
282 if (e == START_ELEMENT || e == END_ELEMENT)
283 return e;
284 }
285 return event;
286 }
287
288 public boolean hasNext() throws XMLStreamException {
289 return event != END_DOCUMENT;
290 }
291
292 public void close() throws XMLStreamException {
293 //To change body of implemented methods use File | Settings | File Templates.
294 }
295
296 public String getNamespaceURI(String s) {
297 return null; //To change body of implemented methods use File | Settings | File Templates.
298 }
299
300 public boolean isStartElement() {
301 return state == STATE_RUN_PART ? parts.get(part).get(reader).isStartElement() : event == START_ELEMENT;
302 }
303
304 public boolean isEndElement() {
305 return state == STATE_RUN_PART ? parts.get(part).get(reader).isEndElement() : event == END_ELEMENT;
306 }
307
308 public boolean isCharacters() {
309 return state == STATE_RUN_PART ? parts.get(part).get(reader).isCharacters() : event == CHARACTERS;
310 }
311
312 public boolean isWhiteSpace() {
313 return state == STATE_RUN_PART ? parts.get(part).get(reader).isWhiteSpace() : event == SPACE;
314 }
315
316 public String getAttributeValue(String s, String s1) {
317 throw new UnsupportedOperationException("Not implemented");
318 }
319
320 public int getAttributeCount() {
321 switch (state) {
322 case STATE_START_ELEMENT_WRAPPER:
323 return 7 + extraPrefixes.size();
324 case STATE_START_ELEMENT_PART:
325 return 0;
326 case STATE_RUN_PART:
327 return parts.get(part).get(reader).getAttributeCount();
328 default:
329 throw new IllegalStateException();
330 }
331 }
332
333 public QName getAttributeName(int i) {
334 switch (state) {
335 case STATE_START_ELEMENT_WRAPPER:
336 switch (i) {
337 case 0: return new QName(XMLConstants.XMLNS_ATTRIBUTE_NS_URI,
338 CxfJbiConstants.WSDL11_WRAPPER_PREFIX,
339 XMLConstants.XMLNS_ATTRIBUTE);
340 case 1: return new QName(XMLConstants.XMLNS_ATTRIBUTE_NS_URI,
341 CxfJbiConstants.WSDL11_WRAPPER_MESSAGE_PREFIX,
342 XMLConstants.XMLNS_ATTRIBUTE);
343 case 2: return new QName(CxfJbiConstants.WSDL11_WRAPPER_TYPE);
344 case 3: return new QName(CxfJbiConstants.WSDL11_WRAPPER_NAME);
345 case 4: return new QName(CxfJbiConstants.WSDL11_WRAPPER_VERSION);
346 case 5: return new QName(XMLConstants.XMLNS_ATTRIBUTE_NS_URI,
347 CxfJbiConstants.WSDL11_WRAPPER_XSI_PREFIX,
348 XMLConstants.XMLNS_ATTRIBUTE);
349 case 6: return new QName(XMLConstants.XMLNS_ATTRIBUTE_NS_URI,
350 CxfJbiConstants.WSDL11_WRAPPER_XSD_PREFIX,
351 XMLConstants.XMLNS_ATTRIBUTE);
352 default:{
353 if (i < getAttributeCount()) {
354 return new QName(XMLConstants.XMLNS_ATTRIBUTE_NS_URI,
355 extraPrefixes.get(i - 7).getPrefix(),
356 XMLConstants.XMLNS_ATTRIBUTE);
357 } else {
358 throw new IllegalStateException();
359 }
360 }
361 }
362 case STATE_RUN_PART:
363 return parts.get(part).get(reader).getAttributeName(i);
364 default:
365 throw new IllegalStateException();
366 }
367 }
368
369 public String getAttributeNamespace(int i) {
370 switch (state) {
371 case STATE_START_ELEMENT_WRAPPER:
372 switch (i) {
373 case 0:
374 case 1: return XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
375 case 2:
376 case 3:
377 case 4: return XMLConstants.NULL_NS_URI;
378 case 5: return XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
379 case 6: return XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
380 default: {
381 if (i < getAttributeCount()) {
382 return XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
383 } else {
384 throw new IllegalStateException();
385 }
386 }
387 }
388 case STATE_RUN_PART:
389 return parts.get(part).get(reader).getAttributeNamespace(i);
390 default:
391 throw new IllegalStateException();
392 }
393 }
394
395 public String getAttributeLocalName(int i) {
396 switch (state) {
397 case STATE_START_ELEMENT_WRAPPER:
398 switch (i) {
399 case 0: return CxfJbiConstants.WSDL11_WRAPPER_PREFIX;
400 case 1: return CxfJbiConstants.WSDL11_WRAPPER_MESSAGE_PREFIX;
401 case 2: return CxfJbiConstants.WSDL11_WRAPPER_TYPE;
402 case 3: return CxfJbiConstants.WSDL11_WRAPPER_NAME;
403 case 4: return CxfJbiConstants.WSDL11_WRAPPER_VERSION;
404 case 5: return CxfJbiConstants.WSDL11_WRAPPER_XSI_PREFIX;
405 case 6: return CxfJbiConstants.WSDL11_WRAPPER_XSD_PREFIX;
406 default: {
407 if (i < getAttributeCount()) {
408 return extraPrefixes.get(i -7).getPrefix();
409 } else {
410 throw new IllegalStateException();
411 }
412 }
413 }
414 case STATE_RUN_PART:
415 return parts.get(part).get(reader).getAttributeLocalName(i);
416 default:
417 throw new IllegalStateException();
418 }
419 }
420
421 public String getAttributePrefix(int i) {
422 switch (state) {
423 case STATE_START_ELEMENT_WRAPPER:
424 switch (i) {
425 case 0: return XMLConstants.XMLNS_ATTRIBUTE;
426 case 1: return XMLConstants.XMLNS_ATTRIBUTE;
427 case 2:
428 case 3:
429 case 4: return XMLConstants.DEFAULT_NS_PREFIX;
430 case 5: return XMLConstants.XMLNS_ATTRIBUTE;
431 case 6: return XMLConstants.XMLNS_ATTRIBUTE;
432 default: {
433 if (i < getAttributeCount()) {
434 return XMLConstants.XMLNS_ATTRIBUTE;
435 } else {
436 throw new IllegalStateException();
437 }
438 }
439 }
440 case STATE_RUN_PART:
441 return parts.get(part).get(reader).getAttributePrefix(i);
442 default:
443 throw new IllegalStateException();
444 }
445 }
446
447 public String getAttributeType(int i) {
448 return "CDATA";
449 }
450
451 public String getAttributeValue(int i) {
452 switch (state) {
453 case STATE_START_ELEMENT_WRAPPER:
454 switch (i) {
455 case 0:
456 {
457 return CxfJbiConstants.WSDL11_WRAPPER_NAMESPACE;
458 }
459 case 1:
460 {
461 String typeNamespace = wsdlMessage.getMessageInfo().getName().getNamespaceURI();
462 if (typeNamespace == null || typeNamespace.length() == 0) {
463 throw new IllegalArgumentException("messageType namespace is null or empty");
464 }
465 return typeNamespace;
466 }
467 case 2:
468 {
469 String typeLocalName = wsdlMessage.getMessageInfo().getName().getLocalPart();
470 if (typeLocalName == null || typeLocalName.length() == 0) {
471 throw new IllegalArgumentException("messageType local name is null or empty");
472 }
473 return CxfJbiConstants.WSDL11_WRAPPER_MESSAGE_PREFIX + ":" + typeLocalName;
474 }
475 case 3:
476 return wsdlMessage.getMessageInfo().getName().getLocalPart().toString();
477 case 4:
478 return "1.0";
479 case 5:
480 return XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI;
481 case 6:
482 return XMLConstants.W3C_XML_SCHEMA_NS_URI;
483 default: {
484 if (i < getAttributeCount()) {
485 return extraPrefixes.get(i -7).getNamespaceURI();
486 } else {
487 throw new IllegalStateException();
488 }
489 }
490 }
491 case STATE_RUN_PART:
492 return parts.get(part).get(reader).getAttributeValue(i);
493 default:
494 throw new IllegalStateException();
495 }
496 }
497
498 public boolean isAttributeSpecified(int i) {
499 throw new UnsupportedOperationException("Not implemented");
500 }
501
502 public int getNamespaceCount() {
503 switch (state) {
504 case STATE_START_ELEMENT_WRAPPER:
505 case STATE_END_ELEMENT_WRAPPER:
506 case STATE_START_ELEMENT_PART:
507 case STATE_END_ELEMENT_PART:
508 return 0;
509 case STATE_RUN_PART:
510 return parts.get(part).get(reader).getNamespaceCount();
511 default:
512 throw new IllegalStateException();
513 }
514 }
515
516 public String getNamespacePrefix(int i) {
517 String prefix = parts.get(part).get(reader).getNamespacePrefix(i);
518 if (prefix != null && prefix.length() == 0
519 && parts.get(part).get(reader).getNamespaceURI().length() > 0) {
520 return CxfJbiConstants.WSDL11_WRAPPER_PART_LOCALNAME;
521 } else {
522 return prefix;
523 }
524 }
525
526 public String getNamespaceURI(int i) {
527 return parts.get(part).get(reader).getNamespaceURI(i);
528 }
529
530 public NamespaceContext getNamespaceContext() {
531 if (state == STATE_RUN_PART) {
532 return parts.get(part).get(reader).getNamespaceContext();
533 } else {
534 return new ExtendedXMLStreamReader.SimpleNamespaceContext();
535 }
536 }
537
538 public String getText() {
539 if (state == STATE_RUN_PART) {
540 return parts.get(part).get(reader).getText();
541 } else {
542 throw new IllegalStateException();
543 }
544 }
545
546 public char[] getTextCharacters() {
547 if (state == STATE_RUN_PART) {
548 return parts.get(part).get(reader).getTextCharacters();
549 } else {
550 throw new IllegalStateException();
551 }
552 }
553
554 public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException {
555 if (state == STATE_RUN_PART) {
556 return parts.get(part).get(reader).getTextCharacters(i, chars, i1, i2);
557 } else {
558 throw new IllegalStateException();
559 }
560 }
561
562 public int getTextStart() {
563 if (state == STATE_RUN_PART) {
564 return parts.get(part).get(reader).getTextStart();
565 } else {
566 throw new IllegalStateException();
567 }
568 }
569
570 public int getTextLength() {
571 if (state == STATE_RUN_PART) {
572 return parts.get(part).get(reader).getTextLength();
573 } else {
574 throw new IllegalStateException();
575 }
576 }
577
578 public String getEncoding() {
579 throw new UnsupportedOperationException("Not implemented");
580 }
581
582 public boolean hasText() {
583 if (state == STATE_RUN_PART) {
584 return parts.get(part).get(reader).hasText();
585 } else {
586 return false;
587 }
588 }
589
590 public Location getLocation() {
591 return new Location() {
592 public int getCharacterOffset() {
593 return 0;
594 }
595 public int getColumnNumber() {
596 return 0;
597 }
598 public int getLineNumber() {
599 return 0;
600 }
601 public String getPublicId() {
602 return null;
603 }
604 public String getSystemId() {
605 return null;
606 }
607 };
608 }
609
610 public String getVersion() {
611 throw new UnsupportedOperationException("Not implemented");
612 }
613
614 public boolean isStandalone() {
615 throw new UnsupportedOperationException("Not implemented");
616 }
617
618 public boolean standaloneSet() {
619 throw new UnsupportedOperationException("Not implemented");
620 }
621
622 public String getCharacterEncodingScheme() {
623 throw new UnsupportedOperationException("Not implemented");
624 }
625
626 public String getPITarget() {
627 throw new UnsupportedOperationException("Not implemented");
628 }
629
630 public String getPIData() {
631 throw new UnsupportedOperationException("Not implemented");
632 }
633
634 private BindingOperationInfo getOperation(Message message) {
635 BindingOperationInfo operation = message.getExchange().get(
636 BindingOperationInfo.class);
637 if (operation == null) {
638 throw new Fault(
639 new Exception("Operation not bound on this message"));
640 }
641 return operation;
642 }
643
644 private boolean isRequestor(Message message) {
645 return Boolean.TRUE.equals(message.get(Message.REQUESTOR_ROLE));
646 }
647 }