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