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.cxfse;
018
019 import java.lang.reflect.Field;
020 import java.lang.reflect.Method;
021 import java.util.HashMap;
022 import java.util.List;
023 import java.util.Map;
024 import java.util.concurrent.CopyOnWriteArrayList;
025
026 import javax.annotation.PostConstruct;
027 import javax.annotation.PreDestroy;
028 import javax.jbi.component.ComponentContext;
029 import javax.jbi.management.DeploymentException;
030 import javax.jbi.messaging.DeliveryChannel;
031 import javax.jbi.messaging.ExchangeStatus;
032 import javax.jbi.messaging.MessageExchange;
033 import javax.wsdl.WSDLException;
034 import javax.wsdl.factory.WSDLFactory;
035 import javax.xml.namespace.QName;
036 import javax.xml.ws.WebServiceRef;
037
038 import org.apache.cxf.Bus;
039 import org.apache.cxf.interceptor.Fault;
040 import org.apache.cxf.interceptor.Interceptor;
041 import org.apache.cxf.interceptor.InterceptorProvider;
042 import org.apache.cxf.jaxws.EndpointImpl;
043 import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
044 import org.apache.cxf.jaxws.ServiceImpl;
045 import org.apache.cxf.jaxws.support.JaxWsImplementorInfo;
046 import org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean;
047 import org.apache.cxf.service.model.EndpointInfo;
048 import org.apache.cxf.transport.ConduitInitiatorManager;
049 import org.apache.cxf.transport.jbi.JBIDestination;
050 import org.apache.cxf.transport.jbi.JBIDispatcherUtil;
051 import org.apache.cxf.transport.jbi.JBITransportFactory;
052 import org.apache.cxf.wsdl11.ServiceWSDLBuilder;
053 import org.apache.servicemix.common.endpoints.ProviderEndpoint;
054 import org.apache.servicemix.cxfse.interceptors.AttachmentInInterceptor;
055 import org.apache.servicemix.cxfse.interceptors.AttachmentOutInterceptor;
056 import org.apache.servicemix.cxfse.support.ReflectionUtils;
057 import org.apache.servicemix.id.IdGenerator;
058 import org.springframework.util.ReflectionUtils.FieldCallback;
059
060 /**
061 *
062 * @author gnodet
063 * @org.apache.xbean.XBean element="endpoint"
064 */
065 public class CxfSeEndpoint extends ProviderEndpoint implements
066 InterceptorProvider {
067
068 private static final IdGenerator ID_GENERATOR = new IdGenerator();
069
070 private Object pojo;
071
072 private EndpointImpl endpoint;
073
074 private String address;
075
076 private List<Interceptor> in = new CopyOnWriteArrayList<Interceptor>();
077
078 private List<Interceptor> out = new CopyOnWriteArrayList<Interceptor>();
079
080 private List<Interceptor> outFault = new CopyOnWriteArrayList<Interceptor>();
081
082 private List<Interceptor> inFault = new CopyOnWriteArrayList<Interceptor>();
083
084 private Map properties;
085
086 private boolean mtomEnabled;
087
088 private boolean schemaValidationEnabled;
089
090 private boolean useJBIWrapper = true;
091
092
093 /**
094 * @return the pojo
095 */
096 public Object getPojo() {
097 return pojo;
098 }
099
100 /**
101 * @param pojo
102 * the pojo to set
103 */
104 public void setPojo(Object pojo) {
105 this.pojo = pojo;
106 }
107
108 public List<Interceptor> getOutFaultInterceptors() {
109 return outFault;
110 }
111
112 public List<Interceptor> getInFaultInterceptors() {
113 return inFault;
114 }
115
116 public List<Interceptor> getInInterceptors() {
117 return in;
118 }
119
120 public List<Interceptor> getOutInterceptors() {
121 return out;
122 }
123
124 public void setInInterceptors(List<Interceptor> interceptors) {
125 in = interceptors;
126 }
127
128 public void setInFaultInterceptors(List<Interceptor> interceptors) {
129 inFault = interceptors;
130 }
131
132 public void setOutInterceptors(List<Interceptor> interceptors) {
133 out = interceptors;
134 }
135
136 public void setOutFaultInterceptors(List<Interceptor> interceptors) {
137 outFault = interceptors;
138 }
139
140 public Map getProperties() {
141 return properties;
142 }
143
144 public void setProperties(Map properties) {
145 this.properties = properties;
146 }
147
148
149 /*
150 * (non-Javadoc)
151 *
152 * @see org.apache.servicemix.common.Endpoint#validate()
153 */
154 @Override
155 public void validate() throws DeploymentException {
156 if (getPojo() == null) {
157 throw new DeploymentException("pojo must be set");
158 }
159 JaxWsServiceFactoryBean serviceFactory = new JaxWsServiceFactoryBean();
160 serviceFactory.setPopulateFromClass(true);
161 endpoint = new EndpointImpl(getBus(), getPojo(),
162 new JaxWsServerFactoryBean(serviceFactory));
163 if (isUseJBIWrapper()) {
164 endpoint.setBindingUri(org.apache.cxf.binding.jbi.JBIConstants.NS_JBI_BINDING);
165 }
166 endpoint.setInInterceptors(getInInterceptors());
167 endpoint.setInFaultInterceptors(getInFaultInterceptors());
168 endpoint.setOutInterceptors(getOutInterceptors());
169 endpoint.setOutFaultInterceptors(getOutFaultInterceptors());
170 if (isMtomEnabled()) {
171 endpoint.getInInterceptors().add(new AttachmentInInterceptor());
172 endpoint.getOutInterceptors().add(new AttachmentOutInterceptor());
173 }
174 if (isSchemaValidationEnabled()) {
175 if (endpoint.getProperties() == null) {
176 endpoint.setProperties(new HashMap<String, Object>());
177 }
178 endpoint.getProperties().put(org.apache.cxf.message.Message.SCHEMA_VALIDATION_ENABLED, true);
179 }
180 JaxWsImplementorInfo implInfo = new JaxWsImplementorInfo(getPojo()
181 .getClass());
182 setService(implInfo.getServiceName());
183 setInterfaceName(implInfo.getInterfaceName());
184 setEndpoint(implInfo.getEndpointName().getLocalPart());
185 super.validate();
186 }
187
188 /*
189 * (non-Javadoc)
190 *
191 * @see org.apache.servicemix.common.endpoints.ProviderEndpoint#process(javax.jbi.messaging.MessageExchange)
192 */
193 @Override
194 public void process(MessageExchange exchange) throws Exception {
195
196 QName opeName = exchange.getOperation();
197 EndpointInfo ei = endpoint.getServer().getEndpoint().getEndpointInfo();
198 if (opeName == null) {
199 // if interface only have one operation, may not specify the opeName in MessageExchange
200 if (ei.getBinding().getOperations().size() == 1) {
201 opeName = ei.getBinding().getOperations().iterator().next().getName();
202 exchange.setOperation(opeName);
203 } else {
204 throw new Fault(
205 new Exception("Operation not bound on this MessageExchange"));
206
207 }
208 }
209
210 JBITransportFactory jbiTransportFactory = (JBITransportFactory) getBus()
211 .getExtension(ConduitInitiatorManager.class)
212 .getConduitInitiator(CxfSeComponent.JBI_TRANSPORT_ID);
213
214 QName serviceName = exchange.getService();
215 if (serviceName == null) {
216 serviceName = getService();
217 exchange.setService(serviceName);
218 }
219 QName interfaceName = exchange.getInterfaceName();
220 if (interfaceName == null) {
221 interfaceName = getInterfaceName();
222 exchange.setInterfaceName(interfaceName);
223 }
224 JBIDestination jbiDestination = jbiTransportFactory
225 .getDestination(serviceName.toString()
226 + interfaceName.toString());
227 DeliveryChannel dc = getContext().getDeliveryChannel();
228 jbiTransportFactory.setDeliveryChannel(dc);
229
230 jbiDestination.setDeliveryChannel(dc);
231 if (exchange.getStatus() == ExchangeStatus.ACTIVE) {
232 jbiDestination.getJBIDispatcherUtil().dispatch(exchange);
233 }
234
235 }
236
237 /*
238 * (non-Javadoc)
239 *
240 * @see org.apache.servicemix.common.endpoints.ProviderEndpoint#start()
241 */
242 @Override
243 public void start() throws Exception {
244 super.start();
245 address = "jbi://" + ID_GENERATOR.generateSanitizedId();
246 try {
247 endpoint.publish(address);
248 } catch (Exception e) {
249 e.printStackTrace();
250 }
251
252 setService(endpoint.getServer().getEndpoint().getService().getName());
253 setEndpoint(endpoint.getServer().getEndpoint().getEndpointInfo()
254 .getName().getLocalPart());
255 try {
256 definition = new ServiceWSDLBuilder(getBus(), endpoint.getServer()
257 .getEndpoint().getService().getServiceInfos().iterator()
258 .next()).build();
259 description = WSDLFactory.newInstance().newWSDLWriter().getDocument(definition);
260 } catch (WSDLException e) {
261 throw new DeploymentException(e);
262 }
263 ReflectionUtils.doWithFields(getPojo().getClass(), new FieldCallback() {
264 public void doWith(Field field) throws IllegalArgumentException,
265 IllegalAccessException {
266 if (field.getAnnotation(WebServiceRef.class) != null) {
267 ServiceImpl s = new ServiceImpl(getBus(), null, null, field
268 .getType());
269 s.addPort(new QName("port"),
270 JBITransportFactory.TRANSPORT_ID, "jbi://"
271 + ID_GENERATOR.generateSanitizedId());
272 Object o = s.getPort(new QName("port"), field.getType());
273 field.setAccessible(true);
274 field.set(getPojo(), o);
275 }
276 }
277 });
278 ReflectionUtils.callLifecycleMethod(getPojo(), PostConstruct.class);
279 injectPojo();
280 }
281
282
283 /*
284 * (non-Javadoc)
285 *
286 * @see org.apache.servicemix.common.endpoints.ProviderEndpoint#stop()
287 */
288 @Override
289 public void stop() throws Exception {
290 endpoint.stop();
291 ReflectionUtils.callLifecycleMethod(getPojo(), PreDestroy.class);
292 JBIDispatcherUtil.clean();
293 JBITransportFactory jbiTransportFactory = (JBITransportFactory) getBus()
294 .getExtension(ConduitInitiatorManager.class)
295 .getConduitInitiator(CxfSeComponent.JBI_TRANSPORT_ID);
296 jbiTransportFactory.removeDestination(getService().toString()
297 + getInterfaceName().toString());
298 super.stop();
299 }
300
301 protected Bus getBus() {
302 return ((CxfSeComponent) getServiceUnit().getComponent()).getBus();
303 }
304
305
306 @PostConstruct
307 protected void injectPojo() {
308 try {
309 ComponentContext context = getContext();
310 Method mth = pojo.getClass().getMethod("setContext", new Class[] {ComponentContext.class });
311 if (mth != null) {
312 mth.invoke(pojo, new Object[] {context});
313 }
314 } catch (Exception e) {
315 logger.debug("Unable to inject ComponentContext: " + e.getMessage());
316 }
317
318 }
319
320 public void setMtomEnabled(boolean mtomEnabled) {
321 this.mtomEnabled = mtomEnabled;
322 }
323
324 public boolean isMtomEnabled() {
325 return mtomEnabled;
326 }
327
328 public boolean isSchemaValidationEnabled() {
329 return schemaValidationEnabled;
330 }
331
332 public void setSchemaValidationEnabled(boolean schemaValidationEnabled) {
333 this.schemaValidationEnabled = schemaValidationEnabled;
334 }
335
336 public void setUseJBIWrapper(boolean useJBIWrapper) {
337 this.useJBIWrapper = useJBIWrapper;
338 }
339
340 public boolean isUseJBIWrapper() {
341 return useJBIWrapper;
342 }
343 }