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.camel.component.cxf;
018
019
020 import java.util.HashMap;
021 import java.util.Map;
022
023 import org.apache.camel.Processor;
024 import org.apache.camel.impl.DefaultConsumer;
025 import org.apache.commons.logging.Log;
026 import org.apache.commons.logging.LogFactory;
027 import org.apache.cxf.endpoint.Server;
028 import org.apache.cxf.frontend.ServerFactoryBean;
029 import org.apache.cxf.interceptor.Fault;
030 import org.apache.cxf.message.Exchange;
031 import org.apache.cxf.service.invoker.Invoker;
032 import org.apache.cxf.service.model.BindingOperationInfo;
033
034 /**
035 * A Consumer of exchanges for a service in CXF. CxfConsumer acts a CXF
036 * service to receive requests, convert them, and forward them to Camel
037 * route for processing. It is also responsible for converting and sending
038 * back responses to CXF client.
039 *
040 * @version $Revision: 21400 $
041 */
042 public class CxfConsumer extends DefaultConsumer {
043 private static final Log LOG = LogFactory.getLog(CxfConsumer.class);
044 private Server server;
045
046 public CxfConsumer(CxfEndpoint endpoint, Processor processor) throws Exception {
047 super(endpoint, processor);
048
049 // create server
050 ServerFactoryBean svrBean = endpoint.createServerFactoryBean();
051 svrBean.setInvoker(new Invoker() {
052
053 // we receive a CXF request when this method is called
054 public Object invoke(Exchange cxfExchange, Object o) {
055
056 if (LOG.isTraceEnabled()) {
057 LOG.trace("Received CXF Request: " + cxfExchange);
058 }
059
060 // get CXF binding
061 CxfEndpoint endpoint = (CxfEndpoint)getEndpoint();
062 CxfBinding binding = endpoint.getCxfBinding();
063
064 // create a Camel exchange
065 org.apache.camel.Exchange camelExchange = endpoint.createExchange();
066 DataFormat dataFormat = endpoint.getDataFormat();
067
068 BindingOperationInfo boi = cxfExchange.getBindingOperationInfo();
069 // make sure the "boi" is remained as wrapped in PAYLOAD mode
070 if (dataFormat == DataFormat.PAYLOAD && boi.isUnwrapped()) {
071 boi = boi.getWrappedOperation();
072 cxfExchange.put(BindingOperationInfo.class, boi);
073 }
074
075 if (boi != null) {
076 camelExchange.setProperty(BindingOperationInfo.class.getName(), boi);
077 if (LOG.isTraceEnabled()) {
078 LOG.trace("Set exchange property: BindingOperationInfo: " + boi);
079 }
080 }
081
082 // set data format mode in Camel exchange
083 camelExchange.setProperty(CxfConstants.DATA_FORMAT_PROPERTY, dataFormat);
084 if (LOG.isTraceEnabled()) {
085 LOG.trace("Set Exchange property: " + DataFormat.class.getName()
086 + "=" + dataFormat);
087 }
088
089 // bind the CXF request into a Camel exchange
090 binding.populateExchangeFromCxfRequest(cxfExchange, camelExchange);
091
092 // extract the javax.xml.ws header
093 Map<String, Object> context = new HashMap<String, Object>();
094 binding.extractJaxWsContext(cxfExchange, context);
095 // send Camel exchange to the target processor
096 if (LOG.isTraceEnabled()) {
097 LOG.trace("Processing +++ START +++");
098 }
099 try {
100 getProcessor().process(camelExchange);
101 } catch (Exception e) {
102 throw new Fault(e);
103 }
104 if (LOG.isTraceEnabled()) {
105 LOG.trace("Processing +++ END +++");
106 }
107 checkFailure(camelExchange);
108
109 // bind the Camel response into a CXF response
110 if (camelExchange.getPattern().isOutCapable()) {
111 binding.populateCxfResponseFromExchange(camelExchange, cxfExchange);
112 }
113
114 // check failure again as fault could be discovered by converter
115 checkFailure(camelExchange);
116
117 // copy the headers javax.xml.ws header back
118 binding.copyJaxWsContext(cxfExchange, context);
119 // response should have been set in outMessage's content
120 return null;
121 }
122
123 private void checkFailure(org.apache.camel.Exchange camelExchange) throws Fault {
124 if (camelExchange.isFailed()) {
125 // either Fault or Exception
126 Throwable t = (camelExchange.hasOut() && camelExchange.getOut().isFault())
127 ? camelExchange.getOut().getBody(Throwable.class) : camelExchange.getException();
128 // There is no exception and the Fault message is set to the out message
129 if (t != null) {
130 throw (t instanceof Fault) ? (Fault)t : new Fault(t);
131 }
132 }
133
134 }
135
136 });
137 server = svrBean.create();
138 }
139
140 @Override
141 protected void doStart() throws Exception {
142 super.doStart();
143 server.start();
144 }
145
146 @Override
147 protected void doStop() throws Exception {
148 server.stop();
149 super.doStop();
150 }
151
152 public Server getServer() {
153 return server;
154 }
155
156 }