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