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.camel;
018    
019    import java.util.ArrayList;
020    import java.util.Collection;
021    import java.util.List;
022    
023    import javax.jbi.management.DeploymentException;
024    
025    import org.apache.camel.Endpoint;
026    import org.apache.camel.component.bean.BeanComponent;
027    import org.apache.camel.spring.SpringCamelContext;
028    import org.apache.servicemix.common.ServiceUnit;
029    import org.apache.servicemix.common.xbean.AbstractXBeanDeployer;
030    import org.apache.xbean.kernel.Kernel;
031    import org.apache.xbean.server.spring.loader.PureSpringLoader;
032    import org.apache.xbean.server.spring.loader.SpringLoader;
033    import org.apache.xbean.spring.context.FileSystemXmlApplicationContext;
034    import org.springframework.context.ApplicationContext;
035    import org.springframework.context.support.AbstractXmlApplicationContext;
036    import org.springframework.context.support.GenericApplicationContext;
037    
038    /**
039     * A deployer of the spring XML file
040     *
041     * @version $Revision: 1.1 $
042     */
043    public class CamelSpringDeployer extends AbstractXBeanDeployer {
044        private final CamelJbiComponent component;
045    
046        private PureSpringLoader springLoader = new PureSpringLoader() {
047            @Override
048            protected AbstractXmlApplicationContext createXmlApplicationContext(String configLocation) {
049                ApplicationContext parentAppContext = createParentApplicationContext(getXmlPreprocessors());
050                return new FileSystemXmlApplicationContext(new String[] {configLocation}, false,
051                                                           parentAppContext, getXmlPreprocessors());
052            }
053        };
054    
055        private List<CamelProviderEndpoint> activatedEndpoints = new ArrayList<CamelProviderEndpoint>();
056    
057        private String serviceUnitName;
058    
059        public CamelSpringDeployer(CamelJbiComponent component) {
060            super(component);
061            this.component = component;
062        }
063    
064        @Override
065        protected String getXBeanFile() {
066            return "camel-context";
067        }
068    
069        public void undeploy(ServiceUnit su) throws DeploymentException {
070            // Remove the jbiComponent form CamelJbiComponent
071            component.removeJbiComponent(su.getName());
072            super.undeploy(su);
073        }
074    
075        /*
076         * (non-Javadoc)
077         *
078         * @see org.apache.servicemix.common.Deployer#deploy(java.lang.String,
079         * java.lang.String)
080         */
081        @Override
082        public ServiceUnit deploy(String suName, String serviceUnitRootPath) throws DeploymentException {
083            // lets register the deployer so that any endpoints activated are added
084            // to this SU
085            component.deployer = this;
086    
087            this.serviceUnitName = suName;
088    
089            // lets install the context class loader
090            ServiceUnit serviceUnit = super.deploy(suName, serviceUnitRootPath);
091            // Thread.currentThread().setContextClassLoader(serviceUnit.getConfigurationClassLoader());
092            return serviceUnit;
093        }
094    
095        public void addService(CamelProviderEndpoint endpoint) {
096            activatedEndpoints.add(endpoint);
097        }
098    
099        @Override
100        protected List getServices(Kernel kernel) {
101            try {
102                List<org.apache.servicemix.common.Endpoint> services =
103                    new ArrayList<org.apache.servicemix.common.Endpoint>(activatedEndpoints);
104                activatedEndpoints.clear();
105    
106                ApplicationContext applicationContext = springLoader.getApplicationContext();
107                SpringCamelContext camelContext = SpringCamelContext.springCamelContext(applicationContext);
108    
109                JbiComponent jbiComponent = camelContext.getComponent("jbi", JbiComponent.class);
110                // now lets iterate through all the endpoints
111                Collection<Endpoint> endpoints = camelContext.getSingletonEndpoints();
112    
113                if (jbiComponent != null) {
114                    // set the SU Name
115                    jbiComponent.setSuName(serviceUnitName);
116                    for (Endpoint endpoint : endpoints) {
117                        if (component.isEndpointExposedOnNmr(endpoint)) {
118                            services.add(jbiComponent.createJbiEndpointFromCamel(endpoint));
119                        }
120                    }
121                    // lets add a control bus endpoint to ensure we have at least
122                    // one endpoint to deploy
123                    BeanComponent beanComponent = camelContext.getComponent("bean", BeanComponent.class);
124                    Endpoint endpoint = beanComponent.createEndpoint(new CamelControlBus(camelContext),
125                                                                     "camel:" + serviceUnitName + "-controlBus");
126                    services.add(jbiComponent.createJbiEndpointFromCamel(endpoint));
127                }
128                return services;
129            } catch (Exception e) {
130                throw new RuntimeException(e);
131            }
132        }
133    
134        @Override
135        protected SpringLoader createSpringLoader() {
136            return springLoader;
137        }
138    
139        /**
140         * Returns the parent application context which can be used to auto-wire any
141         * JBI based components using the jbi prefix
142         */
143        protected ApplicationContext createParentApplicationContext(List xmlProcessors) {
144            GenericApplicationContext answer = new GenericApplicationContext();
145            answer.getBeanFactory().registerSingleton("servicemix-camel", component);
146            answer.getBeanFactory().registerSingleton("jbi", new JbiComponent(component));
147            answer.setClassLoader(Thread.currentThread().getContextClassLoader());
148            answer.start();
149            answer.refresh();
150            return answer;
151        }
152    
153    }