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.Method;
020 import java.util.List;
021
022 import javax.jbi.component.ComponentContext;
023 import javax.jbi.messaging.DeliveryChannel;
024 import javax.naming.InitialContext;
025 import javax.xml.namespace.QName;
026
027 import org.apache.cxf.Bus;
028 import org.apache.cxf.BusFactory;
029 import org.apache.cxf.bus.spring.SpringBusFactory;
030 import org.apache.cxf.frontend.ClientProxy;
031 import org.apache.cxf.interceptor.Interceptor;
032 import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
033 import org.apache.cxf.transport.ConduitInitiatorManager;
034 import org.apache.cxf.transport.jbi.JBITransportFactory;
035 import org.apache.servicemix.cxfse.interceptors.AttachmentInInterceptor;
036 import org.apache.servicemix.cxfse.interceptors.AttachmentOutInterceptor;
037 import org.apache.servicemix.id.IdGenerator;
038 import org.apache.servicemix.jbi.api.ClientFactory;
039 import org.apache.servicemix.jbi.api.Container;
040 import org.apache.servicemix.jbi.api.ServiceMixClient;
041
042 import org.springframework.beans.factory.DisposableBean;
043 import org.springframework.beans.factory.FactoryBean;
044 import org.springframework.beans.factory.InitializingBean;
045
046 /**
047 *
048 * @author ffang
049 * @org.apache.xbean.XBean element="proxy" description="A CXF proxy"
050 *
051 */
052 public class CxfSeProxyFactoryBean implements FactoryBean, InitializingBean,
053 DisposableBean {
054
055 private static final String[] CXF_CONFIG = new String[] {
056 "META-INF/cxf/cxf.xml",
057 "META-INF/cxf/cxf-extension-soap.xml",
058 "META-INF/cxf/transport/jbi/cxf-transport-jbi.xml",
059 "META-INF/cxf/binding/jbi/cxf-binding-jbi.xml"
060 };
061
062 private String name = ClientFactory.DEFAULT_JNDI_NAME;
063
064 private Container container;
065
066 private ClientFactory factory;
067
068 private ComponentContext context;
069
070 private Class type;
071
072 private Object proxy;
073
074 private QName service;
075
076 private QName interfaceName;
077
078 private String endpoint;
079
080 private boolean propagateSecuritySubject;
081
082 private ServiceMixClient client;
083
084 private boolean useJBIWrapper = true;
085
086 private boolean useSOAPEnvelope = true;
087
088 private boolean mtomEnabled;
089
090 private Object componentRegistry;
091
092 public Object getObject() throws Exception {
093 if (proxy == null) {
094 proxy = createProxy();
095 }
096 return proxy;
097 }
098
099 private Object createProxy() throws Exception {
100 JaxWsProxyFactoryBean cf = new JaxWsProxyFactoryBean();
101 cf.setServiceName(getService());
102 if (getEndpoint() != null) {
103 cf.setEndpointName(new QName(getService().getNamespaceURI(), getEndpoint()));
104 }
105 cf.setServiceClass(type);
106 cf.setAddress("jbi://" + new IdGenerator().generateSanitizedId());
107 if (isUseJBIWrapper()) {
108 cf.setBindingId(org.apache.cxf.binding.jbi.JBIConstants.NS_JBI_BINDING);
109 }
110 ComponentContext internalContext = getInternalContext();
111
112 Bus bus = new SpringBusFactory().createBus(CXF_CONFIG);;
113 JBITransportFactory jbiTransportFactory = (JBITransportFactory) bus
114 .getExtension(ConduitInitiatorManager.class)
115 .getConduitInitiator(JBITransportFactory.TRANSPORT_ID);
116 if (internalContext != null) {
117 DeliveryChannel dc = internalContext.getDeliveryChannel();
118 if (dc != null) {
119 jbiTransportFactory.setDeliveryChannel(dc);
120 }
121 }
122 cf.setBus(bus);
123 Object proxy = cf.create();
124 if (!isUseJBIWrapper() && !isUseSOAPEnvelope()) {
125 removeInterceptor(ClientProxy.getClient(proxy).getEndpoint().getBinding().getInInterceptors(),
126 "ReadHeadersInterceptor");
127 removeInterceptor(ClientProxy.getClient(proxy).getEndpoint().getBinding().getInFaultInterceptors(),
128 "ReadHeadersInterceptor");
129 removeInterceptor(ClientProxy.getClient(proxy).getEndpoint().getBinding().getOutInterceptors(),
130 "SoapOutInterceptor");
131 removeInterceptor(ClientProxy.getClient(proxy).getEndpoint().getBinding().getOutFaultInterceptors(),
132 "SoapOutInterceptor");
133 removeInterceptor(ClientProxy.getClient(proxy).getEndpoint().getBinding().getOutInterceptors(),
134 "StaxOutInterceptor");
135 }
136 if (isMtomEnabled()) {
137 ClientProxy.getClient(proxy).getEndpoint()
138 .getBinding().getInInterceptors().add(new AttachmentInInterceptor());
139 ClientProxy.getClient(proxy).getEndpoint()
140 .getBinding().getOutInterceptors().add(new AttachmentOutInterceptor());
141 }
142 return proxy;
143 }
144
145 private void removeInterceptor(List<Interceptor> interceptors, String whichInterceptor) {
146 for (Interceptor interceptor : interceptors) {
147 if (interceptor.getClass().getName().endsWith(whichInterceptor)) {
148 interceptors.remove(interceptor);
149 }
150 }
151 }
152
153 public Class getObjectType() {
154 return type;
155 }
156
157 public boolean isSingleton() {
158 return true;
159 }
160
161 protected ComponentContext getInternalContext() throws Exception {
162 if (CxfSeComponent.getComponentRegistry() != null) {
163 //in osgi container, use ComponentRegistry from CxfSeComponent
164 Object componentRegistry = CxfSeComponent.getComponentRegistry();
165 //use reflection to avoid nmr project dependency
166 Method mth = componentRegistry.getClass().getMethod("createComponentContext");
167 if (mth != null) {
168 context = (ComponentContext) mth.invoke(componentRegistry);
169 }
170 } else if (getComponentRegistry() != null) {
171 //in osgi container, use ComponentRegistry from Proxy directly,
172 //this won't depend on the CxfSeComponent Bundle start first
173 Object componentRegistry = getComponentRegistry();
174 //use reflection to avoid nmr project dependency
175 Method mth = componentRegistry.getClass().getMethod("createComponentContext");
176 if (mth != null) {
177 context = (ComponentContext) mth.invoke(componentRegistry);
178 }
179 }
180
181 if (context == null) {
182 if (factory == null) {
183 if (container != null) {
184 factory = container.getClientFactory();
185 } else {
186 factory = (ClientFactory) new InitialContext().lookup(name);
187 }
188 }
189 client = factory.createClient();
190 context = client.getContext();
191 }
192 return context;
193 }
194
195 public Class getType() {
196 return type;
197 }
198
199 public void setType(Class type) {
200 this.type = type;
201 }
202
203 public String getEndpoint() {
204 return endpoint;
205 }
206
207 public void setEndpoint(String endpointName) {
208 this.endpoint = endpointName;
209 }
210
211 public QName getInterfaceName() {
212 return interfaceName;
213 }
214
215 public void setInterfaceName(QName interfaceName) {
216 this.interfaceName = interfaceName;
217 }
218
219 public QName getService() {
220 return service;
221 }
222
223 public void setService(QName service) {
224 this.service = service;
225 }
226
227 /**
228 * @return the context
229 */
230 public ComponentContext getContext() {
231 return context;
232 }
233
234 /**
235 * @param context
236 * the context to set
237 */
238 public void setContext(ComponentContext context) {
239 this.context = context;
240 }
241
242 /**
243 * @return the container
244 */
245 public Container getContainer() {
246 return container;
247 }
248
249 /**
250 * @param container
251 * the container to set
252 */
253 public void setContainer(Container container) {
254 this.container = container;
255 }
256
257 /**
258 * @return the factory
259 */
260 public ClientFactory getFactory() {
261 return factory;
262 }
263
264 /**
265 * @param factory
266 * the factory to set
267 */
268 public void setFactory(ClientFactory factory) {
269 this.factory = factory;
270 }
271
272 /**
273 * @return the name
274 */
275 public String getName() {
276 return name;
277 }
278
279 /**
280 * @param name
281 * the name to set
282 */
283 public void setName(String name) {
284 this.name = name;
285 }
286
287 /**
288 * @return the propagateSecuritySubject
289 */
290 public boolean isPropagateSecuritySubject() {
291 return propagateSecuritySubject;
292 }
293
294 /**
295 * @param propagateSecuritySubject
296 * the propagateSecuritySubject to set
297 */
298 public void setPropagateSecuritySubject(boolean propagateSecuritySubject) {
299 this.propagateSecuritySubject = propagateSecuritySubject;
300 }
301
302 public void afterPropertiesSet() throws Exception {
303 if (type == null) {
304 throw new IllegalArgumentException("type must be set");
305 }
306 }
307
308 public void destroy() throws Exception {
309 if (client != null) {
310 client.close();
311 client = null;
312 }
313 }
314
315 /**
316 * Specifies if the endpoint expects messages that are encased in the
317 * JBI wrapper used for SOAP messages. Ignore the value of useSOAPEnvelope
318 * if useJBIWrapper is true
319 *
320 * @org.apache.xbean.Property description="Specifies if the endpoint expects to receive the JBI wrapper in the message received from the NMR. The default is <code>true</code>.
321 * Ignore the value of useSOAPEnvelope if useJBIWrapper is true"
322 * */
323 public void setUseJBIWrapper(boolean useJBIWrapper) {
324 this.useJBIWrapper = useJBIWrapper;
325 }
326
327 public boolean isUseJBIWrapper() {
328 return useJBIWrapper;
329 }
330
331 /**
332 * Specifies if the endpoint expects soap messages when useJBIWrapper is false,
333 * if useJBIWrapper is true then ignore useSOAPEnvelope
334 *
335 * @org.apache.xbean.Property description="Specifies if the endpoint expects soap messages when useJBIWrapper is false,
336 * if useJBIWrapper is true then ignore useSOAPEnvelope. The default is <code>true</code>.
337 * */
338 public void setUseSOAPEnvelope(boolean useSOAPEnvelope) {
339 this.useSOAPEnvelope = useSOAPEnvelope;
340 }
341
342 public boolean isUseSOAPEnvelope() {
343 return useSOAPEnvelope;
344 }
345
346 public void setMtomEnabled(boolean mtomEnabled) {
347 this.mtomEnabled = mtomEnabled;
348 }
349
350 public boolean isMtomEnabled() {
351 return mtomEnabled;
352 }
353
354 public void setComponentRegistry(Object componentRegistry) {
355 this.componentRegistry = componentRegistry;
356 }
357
358 public Object getComponentRegistry() {
359 return componentRegistry;
360 }
361
362 }