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 package org.apache.servicemix.cxfbc;
018
019 import java.io.IOException;
020 import java.util.ArrayList;
021 import java.util.Iterator;
022 import java.util.List;
023 import java.util.Map;
024 import java.util.ResourceBundle;
025 import java.util.Set;
026 import java.util.concurrent.ConcurrentHashMap;
027 import java.util.concurrent.CopyOnWriteArrayList;
028
029 import javax.activation.DataHandler;
030 import javax.jbi.JBIException;
031 import javax.jbi.component.ComponentContext;
032 import javax.jbi.management.DeploymentException;
033 import javax.jbi.messaging.ExchangeStatus;
034 import javax.jbi.messaging.MessageExchange;
035 import javax.jbi.messaging.NormalizedMessage;
036 import javax.jbi.servicedesc.ServiceEndpoint;
037 import javax.transaction.TransactionManager;
038 import javax.wsdl.WSDLException;
039 import javax.wsdl.extensions.soap.SOAPBinding;
040 import javax.xml.namespace.QName;
041 import javax.xml.transform.Source;
042
043 import org.w3c.dom.Element;
044 import org.w3c.dom.Node;
045 import org.w3c.dom.NodeList;
046 import com.ibm.wsdl.extensions.soap.SOAPAddressImpl;
047 import com.ibm.wsdl.extensions.soap.SOAPBindingImpl;
048
049 import org.apache.cxf.Bus;
050 import org.apache.cxf.BusFactory;
051 import org.apache.cxf.attachment.AttachmentImpl;
052 import org.apache.cxf.binding.AbstractBindingFactory;
053 import org.apache.cxf.binding.jbi.JBIFault;
054 import org.apache.cxf.binding.soap.SoapFault;
055 import org.apache.cxf.binding.soap.SoapMessage;
056 import org.apache.cxf.binding.soap.interceptor.MustUnderstandInterceptor;
057 import org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor;
058 import org.apache.cxf.binding.soap.interceptor.SoapActionOutInterceptor;
059 import org.apache.cxf.binding.soap.interceptor.SoapOutInterceptor;
060 import org.apache.cxf.binding.soap.interceptor.SoapPreProtocolOutInterceptor;
061 import org.apache.cxf.bus.spring.SpringBusFactory;
062 import org.apache.cxf.catalog.OASISCatalogManager;
063 import org.apache.cxf.continuations.Continuation;
064 import org.apache.cxf.continuations.ContinuationProvider;
065 import org.apache.cxf.endpoint.Endpoint;
066 import org.apache.cxf.endpoint.EndpointImpl;
067 import org.apache.cxf.endpoint.Server;
068 import org.apache.cxf.endpoint.ServerImpl;
069 import org.apache.cxf.endpoint.ServerRegistry;
070 import org.apache.cxf.feature.AbstractFeature;
071 import org.apache.cxf.helpers.DOMUtils;
072 import org.apache.cxf.interceptor.AttachmentInInterceptor;
073 import org.apache.cxf.interceptor.AttachmentOutInterceptor;
074 import org.apache.cxf.interceptor.Fault;
075 import org.apache.cxf.interceptor.Interceptor;
076 import org.apache.cxf.interceptor.OutgoingChainInterceptor;
077 import org.apache.cxf.interceptor.StaxInInterceptor;
078 import org.apache.cxf.interceptor.StaxOutInterceptor;
079 import org.apache.cxf.message.Attachment;
080 import org.apache.cxf.message.Exchange;
081 import org.apache.cxf.message.Message;
082 import org.apache.cxf.message.MessageContentsList;
083 import org.apache.cxf.phase.AbstractPhaseInterceptor;
084 import org.apache.cxf.phase.Phase;
085 import org.apache.cxf.service.Service;
086 import org.apache.cxf.service.invoker.Invoker;
087 import org.apache.cxf.service.model.BindingFaultInfo;
088 import org.apache.cxf.service.model.BindingOperationInfo;
089 import org.apache.cxf.service.model.EndpointInfo;
090 import org.apache.cxf.service.model.FaultInfo;
091 import org.apache.cxf.service.model.MessagePartInfo;
092 import org.apache.cxf.service.model.ServiceInfo;
093 import org.apache.cxf.transport.ChainInitiationObserver;
094 import org.apache.cxf.transport.Destination;
095 import org.apache.cxf.transport.http_jetty.JettyHTTPDestination;
096 import org.apache.cxf.transport.http_jetty.JettyHTTPServerEngine;
097 import org.apache.cxf.transport.jms.JMSConfiguration;
098 import org.apache.cxf.transport.jms.JMSDestination;
099 import org.apache.cxf.ws.addressing.AddressingProperties;
100 import org.apache.cxf.ws.rm.Servant;
101 import org.apache.cxf.wsdl.WSDLManager;
102 import org.apache.cxf.wsdl11.WSDLServiceFactory;
103 import org.apache.servicemix.common.endpoints.ConsumerEndpoint;
104 import org.apache.servicemix.cxfbc.interceptors.JbiInInterceptor;
105 import org.apache.servicemix.cxfbc.interceptors.JbiInWsdl1Interceptor;
106 import org.apache.servicemix.cxfbc.interceptors.JbiJAASInterceptor;
107 import org.apache.servicemix.cxfbc.interceptors.JbiOperationInterceptor;
108 import org.apache.servicemix.cxfbc.interceptors.JbiOutWsdl1Interceptor;
109 import org.apache.servicemix.cxfbc.interceptors.MtomCheckInterceptor;
110 import org.apache.servicemix.jbi.jaxp.SourceTransformer;
111 import org.apache.servicemix.soap.util.DomUtil;
112 import org.mortbay.jetty.Handler;
113 import org.springframework.core.io.Resource;
114 import org.springframework.transaction.PlatformTransactionManager;
115
116 /**
117 *
118 * @author gnodet
119 * @org.apache.xbean.XBean element="consumer" description="a consumer endpoint
120 * that is capable of using SOAP/HTTP or SOAP/JMS"
121 */
122 public class CxfBcConsumer extends ConsumerEndpoint implements
123 CxfBcEndpointWithInterceptor {
124
125 List<Interceptor> in = new CopyOnWriteArrayList<Interceptor>();
126
127 List<Interceptor> out = new CopyOnWriteArrayList<Interceptor>();
128
129 List<Interceptor> outFault = new CopyOnWriteArrayList<Interceptor>();
130
131 List<Interceptor> inFault = new CopyOnWriteArrayList<Interceptor>();
132
133 private Resource wsdl;
134
135 private Endpoint ep;
136
137 private ChainInitiationObserver chain;
138
139 private Server server;
140
141 private Map<String, Message> messages = new ConcurrentHashMap<String, Message>();
142
143 private boolean synchronous = true;
144
145 private boolean isOneway;
146
147 private String busCfg;
148
149 private BindingFaultInfo faultWanted;
150
151 private Bus bus;
152
153 private boolean mtomEnabled;
154
155 private String locationURI;
156
157 private int timeout = 10;
158
159 private boolean useJBIWrapper = true;
160
161 private boolean useSOAPEnvelope = true;
162
163 private EndpointInfo ei;
164
165 private List<AbstractFeature> features = new CopyOnWriteArrayList<AbstractFeature>();
166
167 private boolean transactionEnabled;
168
169 private boolean isSTFlow;
170
171 private ClassLoader suClassLoader;
172
173 /**
174 * @return the wsdl
175 */
176 public Resource getWsdl() {
177 return wsdl;
178 }
179
180 /**
181 * Specifies the location of the WSDL defining the endpoint's interface.
182 *
183 * @param wsdl
184 * the location of the WSDL contract as a <code>Resource</code>
185 * object
186 * @org.apache.xbean.Property description="the location of the WSDL document
187 * defining the endpoint's interface"
188 */
189 public void setWsdl(Resource wsdl) {
190 this.wsdl = wsdl;
191 }
192
193 /**
194 * Returns the list of interceptors used to process fault messages being
195 * sent to the provider.
196 *
197 * @return a list of <code>Interceptor</code> objects
198 */
199 public List<Interceptor> getOutFaultInterceptors() {
200 return outFault;
201 }
202
203 /**
204 * Returns the list of interceptors used to process fault messages being
205 * recieved by the endpoint.
206 *
207 * @return a list of <code>Interceptor</code> objects
208 */
209 public List<Interceptor> getInFaultInterceptors() {
210 return inFault;
211 }
212
213 /**
214 * Returns the list of interceptors used to process responses being recieved
215 * by the endpoint.
216 *
217 * @return a list of <code>Interceptor</code> objects
218 */
219 public List<Interceptor> getInInterceptors() {
220 return in;
221 }
222
223 /**
224 * Returns the list of interceptors used to process requests being sent to
225 * the provider.
226 *
227 * @return a list of <code>Interceptor</code> objects
228 */
229 public List<Interceptor> getOutInterceptors() {
230 return out;
231 }
232
233 /**
234 * Specifies a list of interceptors used to process responses recieved by
235 * the endpoint.
236 *
237 * @param interceptors
238 * a list of <code>Interceptor</code> objects
239 * @org.apache.xbean.Property description="a list of beans configuring
240 * interceptors that process incoming responses"
241 */
242 public void setInInterceptors(List<Interceptor> interceptors) {
243 in.addAll(interceptors);
244 }
245
246 /**
247 * Specifies a list of interceptors used to process faults recieved by the
248 * endpoint.
249 *
250 * @param interceptors
251 * a list of <code>Interceptor</code> objects
252 * @org.apache.xbean.Property description="a list of beans configuring
253 * interceptors that process incoming faults"
254 */
255 public void setInFaultInterceptors(List<Interceptor> interceptors) {
256 inFault.addAll(interceptors);
257 }
258
259 /**
260 * Specifies a list of interceptors used to process requests sent by the
261 * endpoint.
262 *
263 * @param interceptors
264 * a list of <code>Interceptor</code> objects
265 * @org.apache.xbean.Property description="a list of beans configuring
266 * interceptors that process requests"
267 */
268 public void setOutInterceptors(List<Interceptor> interceptors) {
269 out.addAll(interceptors);
270 }
271
272 /**
273 * Specifies a list of interceptors used to process faults sent by the
274 * endpoint.
275 *
276 * @param interceptors
277 * a list of <code>Interceptor</code> objects
278 * @org.apache.xbean.Property description="a list of beans configuring
279 * interceptors that process fault messages being
280 * returned to the consumer"
281 */
282 public void setOutFaultInterceptors(List<Interceptor> interceptors) {
283 outFault.addAll(interceptors);
284 }
285
286 public void process(MessageExchange exchange) throws Exception {
287
288
289 if (exchange.getStatus() != ExchangeStatus.ACTIVE) {
290 return;
291 }
292
293 Message message = messages.remove(exchange.getExchangeId());
294
295 synchronized (message.getInterceptorChain()) {
296 boolean oneway = message.getExchange().get(
297 BindingOperationInfo.class).getOperationInfo().isOneWay();
298 if (!isSynchronous() && !oneway) {
299 ContinuationProvider continuationProvider = (ContinuationProvider) message
300 .get(ContinuationProvider.class.getName());
301 Continuation continuation = continuationProvider.getContinuation();
302 if (continuation.isPending()) {
303 continuation.resume();
304 isSTFlow = false;
305 } else {
306 isSTFlow = true;
307 }
308 }
309 if (exchange.getStatus() == ExchangeStatus.ACTIVE) {
310 exchange.setStatus(ExchangeStatus.DONE);
311 message.getExchange().get(ComponentContext.class)
312 .getDeliveryChannel().send(exchange);
313 }
314 }
315
316
317 }
318
319 @Override
320 public void start() throws Exception {
321 super.start();
322 try {
323 registerListServiceHandler();
324 applyFeatures();
325 checkJmsTransportTransaction();
326 server.start();
327 } catch (Exception ex) {
328 super.stop();
329 throw ex;
330 }
331 }
332
333 private void checkJmsTransportTransaction() {
334 Destination destination = server.getDestination();
335 if (destination instanceof JMSDestination) {
336 JMSDestination jmsDestination = (JMSDestination)destination;
337 JMSConfiguration jmsConfig = jmsDestination.getJmsConfig();
338 if (jmsConfig.isSessionTransacted()) {
339 TransactionManager tm = (TransactionManager) getContext().getTransactionManager();
340 if (tm == null) {
341 throw new IllegalStateException("No TransactionManager available");
342 } else if (tm instanceof PlatformTransactionManager) {
343 jmsConfig.setSessionTransacted(true);
344 jmsConfig.setTransactionManager((PlatformTransactionManager)tm);
345 setSynchronous(true);
346 transactionEnabled = true;
347 }
348 }
349 }
350
351 }
352
353 private void applyFeatures() {
354 if (getFeatures() != null) {
355 for (AbstractFeature feature : getFeatures()) {
356 feature.initialize(server, getBus());
357 }
358 }
359 }
360
361 private void registerListServiceHandler() {
362 if (server.getDestination() instanceof JettyHTTPDestination) {
363 JettyHTTPDestination jettyDest = (JettyHTTPDestination) server
364 .getDestination();
365 JettyHTTPServerEngine jettyEng = (JettyHTTPServerEngine) jettyDest
366 .getEngine();
367 List<Handler> handlers = jettyEng.getHandlers();
368 if (handlers == null) {
369 handlers = new ArrayList<Handler>();
370 jettyEng.setHandlers(handlers);
371 }
372 handlers.add(new ListServiceHandler(getBus().getExtension(
373 ServerRegistry.class)));
374
375 }
376 }
377
378 @Override
379 public void stop() throws Exception {
380 server.stop();
381 if (ei.getAddress() != null && ei.getAddress().startsWith("https")) {
382 bus.shutdown(false);
383 bus = null;
384 }
385 if (!isComponentBus()) {
386 //if use the endpoint own bus, then shutdown it
387 bus.shutdown(true);
388 bus = null;
389 }
390 super.stop();
391 }
392
393 @Override
394 public void validate() throws DeploymentException {
395 try {
396 suClassLoader = Thread.currentThread().getContextClassLoader();
397 if (definition == null) {
398 retrieveWSDL();
399 }
400 if (service == null) {
401 // looking for the servicename according to targetServiceName
402 // first
403 if (definition.getServices().containsKey(getTargetService())) {
404 service = getTargetService();
405 } else {
406 service = (QName) definition.getServices().keySet()
407 .iterator().next();
408 }
409 }
410 WSDLServiceFactory factory = new WSDLServiceFactory(getBus(),
411 definition, service);
412
413 Service cxfService = factory.create();
414
415 ei = cxfService.getServiceInfos().iterator().next().getEndpoints()
416 .iterator().next();
417 for (ServiceInfo serviceInfo : cxfService.getServiceInfos()) {
418 if (serviceInfo.getName().equals(service)
419 && getEndpoint() != null
420 && serviceInfo.getEndpoint(new QName(serviceInfo
421 .getName().getNamespaceURI(), getEndpoint())) != null) {
422 ei = serviceInfo.getEndpoint(new QName(serviceInfo
423 .getName().getNamespaceURI(), getEndpoint()));
424
425 }
426 }
427
428
429 if (endpoint == null) {
430 endpoint = ei.getName().getLocalPart();
431 }
432
433 if (locationURI != null) {
434 ei.setAddress(locationURI);
435 }
436
437 ei.getBinding().setProperty(
438 AbstractBindingFactory.DATABINDING_DISABLED, Boolean.TRUE);
439
440 cxfService.getInInterceptors().add(new MustUnderstandInterceptor());
441 cxfService.getInInterceptors().add(new AttachmentInInterceptor());
442 cxfService.getInInterceptors().add(new StaxInInterceptor());
443 cxfService.getInInterceptors().add(
444 new ReadHeadersInterceptor(getBus()));
445 cxfService.getInInterceptors().add(new JbiOperationInterceptor());
446 cxfService.getInInterceptors().add(
447 new JbiInWsdl1Interceptor(isUseJBIWrapper(),
448 isUseSOAPEnvelope()));
449 cxfService.getInInterceptors().add(new JbiInInterceptor());
450 cxfService.getInInterceptors().add(
451 new JbiJAASInterceptor(((CxfBcComponent) this
452 .getServiceUnit().getComponent())
453 .getConfiguration().getAuthenticationService()));
454 cxfService.getInInterceptors().add(new JbiInvokerInterceptor());
455
456 cxfService.getInInterceptors().add(new JbiPostInvokerInterceptor());
457
458 cxfService.getInInterceptors().add(new OutgoingChainInterceptor());
459
460 cxfService.getOutInterceptors().add(
461 new JbiOutWsdl1Interceptor(isUseJBIWrapper()));
462
463 cxfService.getOutInterceptors().add(new SoapActionOutInterceptor());
464 cxfService.getOutInterceptors().add(new AttachmentOutInterceptor());
465 cxfService.getOutInterceptors().add(
466 new MtomCheckInterceptor(isMtomEnabled()));
467
468 cxfService.getOutInterceptors().add(new StaxOutInterceptor());
469 cxfService.getOutInterceptors().add(
470 new SoapPreProtocolOutInterceptor());
471 cxfService.getOutInterceptors().add(
472 new SoapOutInterceptor(getBus()));
473 cxfService.getOutFaultInterceptors().add(
474 new SoapOutInterceptor(getBus()));
475
476 ep = new EndpointImpl(getBus(), cxfService, ei);
477 getInInterceptors().addAll(getBus().getInInterceptors());
478 getInFaultInterceptors().addAll(getBus().getInFaultInterceptors());
479 getOutInterceptors().addAll(getBus().getOutInterceptors());
480 getOutFaultInterceptors()
481 .addAll(getBus().getOutFaultInterceptors());
482
483 cxfService.getInInterceptors().addAll(getInInterceptors());
484 cxfService.getInFaultInterceptors()
485 .addAll(getInFaultInterceptors());
486 cxfService.getOutInterceptors().addAll(getOutInterceptors());
487 cxfService.getOutFaultInterceptors().addAll(
488 getOutFaultInterceptors());
489
490 ep.getInInterceptors().addAll(getInInterceptors());
491 ep.getInFaultInterceptors().addAll(getInFaultInterceptors());
492 ep.getOutInterceptors().addAll(getOutInterceptors());
493 ep.getOutFaultInterceptors().addAll(getOutFaultInterceptors());
494
495 ep.getOutInterceptors().add(new SoapActionOutInterceptor());
496 ep.getOutInterceptors().add(new AttachmentOutInterceptor());
497 ep.getOutInterceptors().add(new StaxOutInterceptor());
498 ep.getOutInterceptors().add(new SoapOutInterceptor(getBus()));
499
500 cxfService.getInInterceptors().addAll(getBus().getInInterceptors());
501 cxfService.getInFaultInterceptors().addAll(
502 getBus().getInFaultInterceptors());
503 cxfService.getOutInterceptors().addAll(
504 getBus().getOutInterceptors());
505 cxfService.getOutFaultInterceptors().addAll(
506 getBus().getOutFaultInterceptors());
507
508 chain = new JbiChainInitiationObserver(ep, getBus());
509 server = new ServerImpl(getBus(), ep, null, chain);
510 super.validate();
511 } catch (DeploymentException e) {
512 throw e;
513 } catch (Exception e) {
514 throw new DeploymentException(e);
515 }
516 }
517
518 private void retrieveWSDL() throws JBIException, WSDLException,
519 DeploymentException, IOException {
520 if (wsdl == null) {
521 if (getTargetService() != null && getTargetEndpoint() != null) {
522 ServiceEndpoint serviceEndpoint = getServiceUnit()
523 .getComponent().getComponentContext().getEndpoint(
524 getTargetService(), getTargetEndpoint());
525 if (serviceEndpoint != null) {
526 description = this.getServiceUnit().getComponent()
527 .getComponentContext().getEndpointDescriptor(
528 serviceEndpoint);
529 definition = getBus().getExtension(WSDLManager.class)
530 .getDefinition(
531 (Element) description.getFirstChild());
532 List address = definition.getService(getTargetService())
533 .getPort(getTargetEndpoint())
534 .getExtensibilityElements();
535 if (address == null || address.size() == 0) {
536 SOAPAddressImpl soapAddress = new SOAPAddressImpl();
537 // specify default transport if there is no one in the
538 // internal wsdl
539 soapAddress.setLocationURI("http://localhost");
540 definition.getService(getTargetService()).getPort(
541 getTargetEndpoint()).addExtensibilityElement(
542 soapAddress);
543 }
544 List binding = definition.getService(getTargetService())
545 .getPort(getTargetEndpoint()).getBinding()
546 .getExtensibilityElements();
547 if (binding == null || binding.size() == 0) {
548 // no binding info in the internal wsdl so we need add
549 // default soap11 binding
550 SOAPBinding soapBinding = new SOAPBindingImpl();
551 soapBinding
552 .setTransportURI("http://schemas.xmlsoap.org/soap/http");
553 soapBinding.setStyle("document");
554 definition.getService(getTargetService()).getPort(
555 getTargetEndpoint()).getBinding()
556 .addExtensibilityElement(soapBinding);
557 }
558
559 }
560 } else {
561 throw new DeploymentException("can't get wsdl");
562 }
563
564 } else {
565 description = DomUtil.parse(wsdl.getInputStream());
566 try {
567 //ensure the jax-ws-catalog is loaded
568 OASISCatalogManager.getCatalogManager(getBus()).loadContextCatalogs();
569 // use wsdl manager to parse wsdl or get cached
570 // definition
571 definition = getBus().getExtension(WSDLManager.class)
572 .getDefinition(wsdl.getURL());
573 } catch (WSDLException ex) {
574 // throw new ServiceConstructionException(new
575 // Message("SERVICE_CREATION_MSG", LOG), ex);
576 }
577 }
578 }
579
580 protected Bus getBus() {
581 if (getBusCfg() != null) {
582 if (bus == null) {
583 SpringBusFactory bf = new SpringBusFactory();
584 bus = bf.createBus(getBusCfg());
585 if (locationURI != null && locationURI.startsWith("/")) {
586 //it's in the servlet container
587 //set this bus so that it could be used in CXFManagerServlet
588 BusFactory.setDefaultBus(bus);
589 }
590 }
591 return bus;
592 } else {
593 return ((CxfBcComponent) getServiceUnit().getComponent()).getBus();
594 }
595 }
596
597 private boolean isComponentBus() {
598 return getBus() == ((CxfBcComponent) getServiceUnit().getComponent()).getBus();
599 }
600
601 /**
602 * Specifies the HTTP address to which requests are sent. This value will
603 * overide any value specified in the WSDL.
604 *
605 * @param locationURI
606 * the URI as a string
607 * @org.apache.xbean.Property description="the HTTP address to which
608 * requests are sent. This value will overide any
609 * value specified in the WSDL."
610 */
611 public void setLocationURI(String locationURI) {
612 this.locationURI = locationURI;
613 }
614
615 public String getLocationURI() {
616 return locationURI;
617 }
618
619
620
621 protected class JbiChainInitiationObserver extends ChainInitiationObserver {
622
623 public JbiChainInitiationObserver(Endpoint endpoint, Bus bus) {
624 super(endpoint, bus);
625 }
626
627 protected void setExchangeProperties(Exchange exchange, Message m) {
628 super.setExchangeProperties(exchange, m);
629 exchange.put(ComponentContext.class, CxfBcConsumer.this
630 .getContext());
631 exchange.put(CxfBcConsumer.class, CxfBcConsumer.this);
632 }
633
634 public void onMessage(Message m) {
635 m.put("suClassloader", suClassLoader);
636 ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
637 if (oldCl != suClassLoader) {
638 try {
639 Thread.currentThread().setContextClassLoader(suClassLoader);
640 super.onMessage(m);
641 } finally {
642 Thread.currentThread().setContextClassLoader(oldCl);
643 }
644 } else {
645 super.onMessage(m);
646 }
647 }
648 }
649
650 public class JbiInvokerInterceptor extends
651 AbstractPhaseInterceptor<Message> {
652
653 public JbiInvokerInterceptor() {
654 super(Phase.INVOKE);
655 }
656
657 private Object getInvokee(Message message) {
658 Object invokee = message.getContent(List.class);
659 if (invokee == null) {
660 invokee = message.getContent(Object.class);
661 }
662 return invokee;
663 }
664
665 private void copyJaxwsProperties(Message inMsg, Message outMsg) {
666 outMsg.put(Message.WSDL_OPERATION, inMsg
667 .get(Message.WSDL_OPERATION));
668 outMsg.put(Message.WSDL_SERVICE, inMsg.get(Message.WSDL_SERVICE));
669 outMsg.put(Message.WSDL_INTERFACE, inMsg
670 .get(Message.WSDL_INTERFACE));
671 outMsg.put(Message.WSDL_PORT, inMsg.get(Message.WSDL_PORT));
672 outMsg.put(Message.WSDL_DESCRIPTION, inMsg
673 .get(Message.WSDL_DESCRIPTION));
674 }
675
676 public void handleMessage(final Message message) throws Fault {
677
678 final Exchange cxfExchange = message.getExchange();
679 final Endpoint endpoint = cxfExchange.get(Endpoint.class);
680 final Service service = endpoint.getService();
681 final Invoker invoker = service.getInvoker();
682
683 if (invoker instanceof Servant) {
684 // it's rm request, run the invocation directly in bc, not send
685 // to se.
686
687 Exchange runableEx = message.getExchange();
688
689 Object result = invoker.invoke(runableEx, getInvokee(message));
690 if (!cxfExchange.isOneWay()) {
691 Endpoint end = cxfExchange.get(Endpoint.class);
692
693 Message outMessage = runableEx.getOutMessage();
694 if (outMessage == null) {
695 outMessage = end.getBinding().createMessage();
696 cxfExchange.setOutMessage(outMessage);
697 }
698 copyJaxwsProperties(message, outMessage);
699 if (result != null) {
700 MessageContentsList resList = null;
701 if (result instanceof MessageContentsList) {
702 resList = (MessageContentsList) result;
703 } else if (result instanceof List) {
704 resList = new MessageContentsList((List) result);
705 } else if (result.getClass().isArray()) {
706 resList = new MessageContentsList((Object[]) result);
707 } else {
708 outMessage.setContent(Object.class, result);
709 }
710 if (resList != null) {
711 outMessage.setContent(List.class, resList);
712 }
713 }
714 }
715
716 return;
717 }
718
719 MessageExchange exchange = message
720 .getContent(MessageExchange.class);
721 ComponentContext context = message.getExchange().get(
722 ComponentContext.class);
723 CxfBcConsumer.this.configureExchangeTarget(exchange);
724 CxfBcConsumer.this.isOneway = message.getExchange().get(
725 BindingOperationInfo.class).getOperationInfo().isOneWay();
726 message.getExchange().setOneWay(CxfBcConsumer.this.isOneway);
727
728 try {
729 if (CxfBcConsumer.this.isOneway) {
730 CxfBcConsumer.this.messages.put(exchange.getExchangeId(), message);
731 context.getDeliveryChannel().send(exchange);
732 } else if (CxfBcConsumer.this.isSynchronous()) {
733 CxfBcConsumer.this.messages.put(exchange.getExchangeId(), message);
734 context.getDeliveryChannel().sendSync(exchange,
735 timeout * 1000);
736 process(exchange);
737 } else {
738 synchronized (((ContinuationProvider) message.get(
739 ContinuationProvider.class.getName())).getContinuation()) {
740 ContinuationProvider continuationProvider =
741 (ContinuationProvider) message.get(ContinuationProvider.class.getName());
742 Continuation continuation = continuationProvider.getContinuation();
743 if (!continuation.isPending()) {
744 CxfBcConsumer.this.messages.put(exchange.getExchangeId(), message);
745 context.getDeliveryChannel().send(exchange);
746 if (!isSTFlow) {
747 continuation.suspend(timeout * 1000);
748 }
749 } else {
750 //retry or timeout
751 if (!continuation.isResumed()) {
752 //exchange timeout
753 messages.remove(exchange.getExchangeId());
754 throw new Exception("Exchange timed out: " + exchange.getExchangeId());
755 }
756
757 }
758
759 }
760 }
761 } catch (org.apache.cxf.continuations.SuspendedInvocationException e) {
762 throw e;
763 } catch (Exception e) {
764 throw new Fault(e);
765 }
766 }
767
768 }
769
770 protected class JbiPostInvokerInterceptor extends
771 AbstractPhaseInterceptor<Message> {
772 public JbiPostInvokerInterceptor() {
773 super(Phase.POST_INVOKE);
774 addBefore(OutgoingChainInterceptor.class.getName());
775 }
776
777 public void handleMessage(final Message message) throws Fault {
778 MessageExchange exchange = message
779 .getContent(MessageExchange.class);
780 Exchange ex = message.getExchange();
781 if (exchange.getStatus() == ExchangeStatus.ERROR) {
782 throw new Fault(exchange.getError());
783 }
784 if (!ex.isOneWay()) {
785 if (exchange.getFault() != null) {
786 Fault f = null;
787 if (isUseJBIWrapper()) {
788 f = new JBIFault(
789 new org.apache.cxf.common.i18n.Message(
790 "Fault occured", (ResourceBundle) null));
791 if (exchange.getProperty("faultstring") != null) {
792 f.setMessage((String) exchange
793 .getProperty("faultstring"));
794 }
795 if (exchange.getProperty("faultcode") != null) {
796 f.setFaultCode((QName) exchange
797 .getProperty("faultcode"));
798 }
799 if (exchange.getProperty("hasdetail") == null) {
800 Element details = toElement(exchange.getFault()
801 .getContent());
802 f.setDetail(details);
803 }
804
805 } else {
806 Element details = toElement(exchange.getFault()
807 .getContent());
808
809 if (isUseSOAPEnvelope()) {
810 details = (Element) details.getElementsByTagNameNS(
811 details.getNamespaceURI(), "Body").item(0);
812 assert details != null;
813 details = (Element) details.getElementsByTagNameNS(
814 details.getNamespaceURI(), "Fault").item(0);
815 }
816 assert details != null;
817 if (exchange.getProperty("faultstring") != null) {
818 details = (Element) details.getElementsByTagName(
819 "faultstring").item(0);
820 } else {
821 details = (Element) details.getElementsByTagName(
822 "detail").item(0);
823 }
824
825 assert details != null;
826 f = new SoapFault(
827 new org.apache.cxf.common.i18n.Message(
828 "Fault occured", (ResourceBundle) null),
829 new QName(details.getNamespaceURI(), "detail"));
830 f.setDetail(details);
831 if (exchange.getProperty("faultstring") != null) {
832 f.setMessage((String) exchange
833 .getProperty("faultstring"));
834 }
835
836 }
837 processFaultDetail(f, message);
838 message.put(BindingFaultInfo.class, faultWanted);
839
840 throw f;
841 } else if (exchange.getMessage("out") != null) {
842 Endpoint endpoint = ex.get(Endpoint.class);
843 Message outMessage = ex.getOutMessage();
844 if (outMessage == null) {
845 outMessage = endpoint.getBinding().createMessage();
846 ex.setOutMessage(outMessage);
847 }
848
849 NormalizedMessage norMessage = (NormalizedMessage) exchange
850 .getMessage("out");
851
852 if (outMessage instanceof SoapMessage) {
853 AddressingProperties addressingProperties = WSAUtils
854 .getCXFAddressingPropertiesFromMap((Map<String, String>) norMessage
855 .getProperty(WSAUtils.WSA_HEADERS_OUTBOUND));
856 outMessage.put(WSAUtils.WSA_HEADERS_OUTBOUND,
857 addressingProperties);
858 }
859 List<Attachment> attachmentList = new ArrayList<Attachment>();
860 outMessage.setContent(Source.class, exchange.getMessage(
861 "out").getContent());
862 Set attachmentNames = norMessage.getAttachmentNames();
863
864 Iterator iter = attachmentNames.iterator();
865 while (iter.hasNext()) {
866 String id = (String) iter.next();
867 DataHandler dh = norMessage.getAttachment(id);
868 attachmentList.add(new AttachmentImpl(id, dh));
869 }
870
871 outMessage.setAttachments(attachmentList);
872 }
873 }
874
875 }
876
877 public void handleFault(Message message) {
878 if (transactionEnabled) {
879 //detect if the fault is defined in the wsdl, which means need return to client and
880 //jms transactionManger just commit
881 Exchange ex = message.getExchange();
882 BindingOperationInfo boi = ex.get(BindingOperationInfo.class);
883 for (BindingFaultInfo bfi : boi.getFaults()) {
884 FaultInfo fi = bfi.getFaultInfo();
885 //get fault details
886 MessagePartInfo mpi = fi.getMessageParts().get(0);
887 if (mpi != null) {
888 Fault fault = (Fault) message.getContent(Exception.class);
889 Element detail = fault.getDetail();
890 if (detail != null
891 && detail.getFirstChild().getLocalName().equals(mpi.getName().getLocalPart())) {
892 //it's fault defined in the wsdl, so let it go back to the client
893 return;
894 }
895 }
896 }
897 //this exception is undefined in the wsdl, so tell the transactionManager injected into
898 //jms transport need rollback
899 throw new Error("rollback");
900 }
901 }
902
903
904 // this method is used for ws-policy to set BindingFaultInfo
905 protected void processFaultDetail(Fault fault, Message msg) {
906 if (fault.getDetail() == null) {
907 return;
908 }
909
910 Element exDetail = (Element) DOMUtils.getChild(fault.getDetail(),
911 Node.ELEMENT_NODE);
912 if (exDetail == null) {
913 return;
914 }
915 QName qname = new QName(exDetail.getNamespaceURI(), exDetail
916 .getLocalName());
917
918 faultWanted = null;
919 BindingOperationInfo boi = msg.getExchange().get(
920 BindingOperationInfo.class);
921 if (boi.isUnwrapped()) {
922 boi = boi.getWrappedOperation();
923 }
924 for (BindingFaultInfo bfi : boi.getFaults()) {
925 for (MessagePartInfo mpi : bfi.getFaultInfo().getMessageParts()) {
926 if (qname.equals(mpi.getConcreteName())) {
927 faultWanted = bfi;
928 msg.put(BindingFaultInfo.class, faultWanted);
929 break;
930 }
931 }
932 if (faultWanted != null) {
933 break;
934 }
935 }
936
937 }
938
939 }
940
941 private static Element toElement(Source src) throws Fault {
942 try {
943 SourceTransformer transformer = new SourceTransformer();
944 Element ret = transformer.toDOMElement(src);
945 ret = removeEmptyDefaultTns(ret);
946 return ret;
947 } catch (Exception e) {
948 throw new Fault(e);
949 }
950 }
951
952 private static Element removeEmptyDefaultTns(Element ret) {
953 // to make unquailied fault work
954 if (ret.hasAttribute("xmlns")
955 && ret.getAttribute("xmlns").length() == 0) {
956 ret.removeAttribute("xmlns");
957 }
958 NodeList nodes = ret.getChildNodes();
959 for (int i = 0; i < nodes.getLength(); i++) {
960 if (nodes.item(i) instanceof Element) {
961 Element ele = (Element) nodes.item(i);
962 ele = removeEmptyDefaultTns(ele);
963
964 }
965 }
966 return ret;
967 }
968
969 /**
970 * Specifies the location of the CXF configuraiton file used to configure
971 * the CXF bus. This allows you to access features like JMS runtime behavior
972 * and WS-RM.
973 *
974 * @param busCfg
975 * a string containing the relative path to the configuration
976 * file
977 * @org.apache.xbean.Property description="the location of the CXF
978 * configuration file used to configure the CXF
979 * bus. This allows you to configure features
980 * like WS-RM and JMS runtime behavior."
981 */
982 public void setBusCfg(String busCfg) {
983 this.busCfg = busCfg;
984 }
985
986 public String getBusCfg() {
987 return busCfg;
988 }
989
990 /**
991 * Specifies if the endpoint can support binnary attachments.
992 *
993 * @param mtomEnabled
994 * a boolean
995 * @org.apache.xbean.Property description="Specifies if MTOM / attachment
996 * support is enabled. Default is
997 * <code>false</code>."
998 */
999 public void setMtomEnabled(boolean mtomEnabled) {
1000 this.mtomEnabled = mtomEnabled;
1001 }
1002
1003 public boolean isMtomEnabled() {
1004 return mtomEnabled;
1005 }
1006
1007 /**
1008 * Specifies the interval for which the endpoint will wait for a response,
1009 * This is specified in seconds.
1010 *
1011 * @param timeout
1012 * the number of second to wait for a response
1013 * @org.apache.xbean.Property description="the number of second the endpoint
1014 * will wait for a response. The default is 10 secs."
1015 */
1016 public void setTimeout(int timeout) {
1017 this.timeout = timeout;
1018 }
1019
1020 public int getTimeout() {
1021 return timeout;
1022 }
1023
1024 /**
1025 * Specifies if the endpoint expects messages to use the JBI wrapper for
1026 * SOAP messages.
1027 *
1028 * @param useJBIWrapper
1029 * a boolean
1030 * @org.apache.xbean.Property description="Specifies if the JBI wrapper is
1031 * sent in the body of the message. Default is
1032 * <code>true</code>. Ignore the value of
1033 * useSOAPEnvelope if useJBIWrapper is true"
1034 */
1035 public void setUseJBIWrapper(boolean useJBIWrapper) {
1036 this.useJBIWrapper = useJBIWrapper;
1037 }
1038
1039 public boolean isUseJBIWrapper() {
1040 return useJBIWrapper;
1041 }
1042
1043 /**
1044 * Specifies if the endpoint expects soap messages when useJBIWrapper is
1045 * false, if useJBIWrapper is true then ignore useSOAPEnvelope
1046 *
1047 * @org.apache.xbean.Property description="Specifies if the endpoint expects
1048 * soap messages when useJBIWrapper is false, if
1049 * useJBIWrapper is true then ignore
1050 * useSOAPEnvelope. The default is
1051 * <code>true</code>.
1052 */
1053 public void setUseSOAPEnvelope(boolean useSOAPEnvelope) {
1054 this.useSOAPEnvelope = useSOAPEnvelope;
1055 }
1056
1057 public boolean isUseSOAPEnvelope() {
1058 return useSOAPEnvelope;
1059 }
1060
1061 /**
1062 * Specifies if the endpoint expects send messageExchange by sendSync
1063 *
1064 * @param synchronous
1065 * a boolean
1066 * @org.apache.xbean.Property description="Specifies if the endpoint expects
1067 * send messageExchange by sendSync . Default is
1068 * <code>true</code>."
1069 */
1070 public void setSynchronous(boolean synchronous) {
1071 this.synchronous = synchronous;
1072 }
1073
1074 public boolean isSynchronous() {
1075 return synchronous;
1076 }
1077
1078 public void setFeatures(List<AbstractFeature> features) {
1079 this.features = features;
1080 }
1081
1082 public List<AbstractFeature> getFeatures() {
1083 return features;
1084 }
1085
1086 }