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