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