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.List;
022    import java.util.Map;
023    import java.util.concurrent.CopyOnWriteArrayList;
024    
025    import javax.annotation.PostConstruct;
026    import javax.annotation.PreDestroy;
027    import javax.jbi.component.ComponentContext;
028    import javax.jbi.management.DeploymentException;
029    import javax.jbi.messaging.DeliveryChannel;
030    import javax.jbi.messaging.ExchangeStatus;
031    import javax.jbi.messaging.MessageExchange;
032    import javax.wsdl.WSDLException;
033    import javax.xml.namespace.QName;
034    import javax.xml.ws.WebServiceRef;
035    
036    import org.apache.cxf.Bus;
037    import org.apache.cxf.interceptor.Interceptor;
038    import org.apache.cxf.interceptor.InterceptorProvider;
039    import org.apache.cxf.jaxws.EndpointImpl;
040    import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
041    import org.apache.cxf.jaxws.ServiceImpl;
042    import org.apache.cxf.jaxws.support.JaxWsImplementorInfo;
043    import org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean;
044    import org.apache.cxf.transport.ConduitInitiatorManager;
045    import org.apache.cxf.transport.jbi.JBIDestination;
046    import org.apache.cxf.transport.jbi.JBIDispatcherUtil;
047    import org.apache.cxf.transport.jbi.JBITransportFactory;
048    import org.apache.cxf.wsdl11.ServiceWSDLBuilder;
049    import org.apache.servicemix.common.endpoints.ProviderEndpoint;
050    import org.apache.servicemix.cxfse.support.ReflectionUtils;
051    import org.apache.servicemix.id.IdGenerator;
052    import org.springframework.util.ReflectionUtils.FieldCallback;
053    
054    /**
055     * 
056     * @author gnodet
057     * @org.apache.xbean.XBean element="endpoint"
058     */
059    public class CxfSeEndpoint extends ProviderEndpoint implements
060            InterceptorProvider {
061    
062        private static final IdGenerator ID_GENERATOR = new IdGenerator();
063    
064        private Object pojo;
065    
066        private EndpointImpl endpoint;
067    
068        private String address;
069    
070        private List<Interceptor> in = new CopyOnWriteArrayList<Interceptor>();
071    
072        private List<Interceptor> out = new CopyOnWriteArrayList<Interceptor>();
073    
074        private List<Interceptor> outFault = new CopyOnWriteArrayList<Interceptor>();
075    
076        private List<Interceptor> inFault = new CopyOnWriteArrayList<Interceptor>();
077    
078        private Map properties;
079    
080        private boolean useJBIWrapper = true;
081    
082        /**
083         * @return the pojo
084         */
085        public Object getPojo() {
086            return pojo;
087        }
088    
089        /**
090         * @param pojo
091         *            the pojo to set
092         */
093        public void setPojo(Object pojo) {
094            this.pojo = pojo;
095        }
096    
097        public List<Interceptor> getOutFaultInterceptors() {
098            return outFault;
099        }
100    
101        public List<Interceptor> getInFaultInterceptors() {
102            return inFault;
103        }
104    
105        public List<Interceptor> getInInterceptors() {
106            return in;
107        }
108    
109        public List<Interceptor> getOutInterceptors() {
110            return out;
111        }
112    
113        public void setInInterceptors(List<Interceptor> interceptors) {
114            in = interceptors;
115        }
116    
117        public void setInFaultInterceptors(List<Interceptor> interceptors) {
118            inFault = interceptors;
119        }
120    
121        public void setOutInterceptors(List<Interceptor> interceptors) {
122            out = interceptors;
123        }
124    
125        public void setOutFaultInterceptors(List<Interceptor> interceptors) {
126            outFault = interceptors;
127        }
128    
129        public Map getProperties() {
130            return properties;
131        }
132    
133        public void setProperties(Map properties) {
134            this.properties = properties;
135        }
136    
137        /*
138         * (non-Javadoc)
139         * 
140         * @see org.apache.servicemix.common.Endpoint#validate()
141         */
142        @Override
143        public void validate() throws DeploymentException {
144            if (getPojo() == null) {
145                throw new DeploymentException("pojo must be set");
146            }
147            JaxWsServiceFactoryBean serviceFactory = new JaxWsServiceFactoryBean();
148            serviceFactory.setPopulateFromClass(true);
149            endpoint = new EndpointImpl(getBus(), getPojo(),
150                    new JaxWsServerFactoryBean(serviceFactory));
151            if (isUseJBIWrapper()) {
152                endpoint
153                        .setBindingUri(org.apache.cxf.binding.jbi.JBIConstants.NS_JBI_BINDING);
154            }
155            endpoint.setInInterceptors(getInInterceptors());
156            endpoint.setInFaultInterceptors(getInFaultInterceptors());
157            endpoint.setOutInterceptors(getOutInterceptors());
158            endpoint.setOutFaultInterceptors(getOutFaultInterceptors());
159            JaxWsImplementorInfo implInfo = new JaxWsImplementorInfo(getPojo()
160                    .getClass());
161            setService(implInfo.getServiceName());
162            setInterfaceName(implInfo.getInterfaceName());
163            setEndpoint(implInfo.getEndpointName().getLocalPart());
164            super.validate();
165        }
166    
167        /*
168         * (non-Javadoc)
169         * 
170         * @see org.apache.servicemix.common.endpoints.ProviderEndpoint#process(javax.jbi.messaging.MessageExchange)
171         */
172        @Override
173        public void process(MessageExchange exchange) throws Exception {
174            JBITransportFactory jbiTransportFactory = (JBITransportFactory) getBus()
175                    .getExtension(ConduitInitiatorManager.class)
176                    .getConduitInitiator(CxfSeComponent.JBI_TRANSPORT_ID);
177            JBIDestination jbiDestination = jbiTransportFactory
178                    .getDestination(exchange.getService().toString()
179                            + exchange.getInterfaceName().toString());
180            DeliveryChannel dc = getContext().getDeliveryChannel();
181    
182            jbiDestination.setDeliveryChannel(dc);
183            if (exchange.getStatus() == ExchangeStatus.ACTIVE) {
184                jbiDestination.getJBIDispatcherUtil().dispatch(exchange);
185            }
186        }
187    
188        /*
189         * (non-Javadoc)
190         * 
191         * @see org.apache.servicemix.common.endpoints.ProviderEndpoint#start()
192         */
193        @Override
194        public void start() throws Exception {
195            super.start();
196            address = "jbi://" + ID_GENERATOR.generateSanitizedId();
197            endpoint.publish(address);
198            setService(endpoint.getServer().getEndpoint().getService().getName());
199            setEndpoint(endpoint.getServer().getEndpoint().getEndpointInfo()
200                    .getName().getLocalPart());
201            try {
202                definition = new ServiceWSDLBuilder(getBus(), endpoint.getServer()
203                        .getEndpoint().getService().getServiceInfos().iterator()
204                        .next()).build();
205            } catch (WSDLException e) {
206                throw new DeploymentException(e);
207            }
208            ReflectionUtils.doWithFields(getPojo().getClass(), new FieldCallback() {
209                public void doWith(Field field) throws IllegalArgumentException,
210                        IllegalAccessException {
211                    if (field.getAnnotation(WebServiceRef.class) != null) {
212                        ServiceImpl s = new ServiceImpl(getBus(), null, null, field
213                                .getType());
214                        s.addPort(new QName("port"),
215                                JBITransportFactory.TRANSPORT_ID, "jbi://"
216                                        + ID_GENERATOR.generateSanitizedId());
217                        Object o = s.getPort(new QName("port"), field.getType());
218                        field.setAccessible(true);
219                        field.set(getPojo(), o);
220                    }
221                }
222            });
223            ReflectionUtils.callLifecycleMethod(getPojo(), PostConstruct.class);
224            injectPojo();
225        }
226    
227        @PostConstruct
228        protected void injectPojo() {
229            try {
230                Method mth = pojo.getClass().getMethod("setContext",
231                        new Class[] {ComponentContext.class});
232                if (mth != null) {
233                    mth.invoke(pojo, new Object[] {getContext()});
234                }
235            } catch (Exception e) {
236                logger
237                        .debug("Unable to inject ComponentContext: "
238                                + e.getMessage());
239            }
240        }
241    
242        /*
243         * (non-Javadoc)
244         * 
245         * @see org.apache.servicemix.common.endpoints.ProviderEndpoint#stop()
246         */
247        @Override
248        public void stop() throws Exception {
249            ReflectionUtils.callLifecycleMethod(getPojo(), PreDestroy.class);
250            JBIDispatcherUtil.clean();
251            getBus().shutdown(true);
252            super.stop();
253        }
254    
255        protected Bus getBus() {
256            return ((CxfSeComponent) getServiceUnit().getComponent()).getBus();
257        }
258    
259        public void setUseJBIWrapper(boolean useJBIWrapper) {
260            this.useJBIWrapper = useJBIWrapper;
261        }
262    
263        public boolean isUseJBIWrapper() {
264            return useJBIWrapper;
265        }
266    
267    }