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.common.xbean;
018    
019    import org.apache.servicemix.common.AbstractDeployer;
020    import org.apache.servicemix.common.Endpoint;
021    import org.apache.servicemix.common.ServiceMixComponent;
022    import org.apache.servicemix.common.ServiceUnit;
023    import org.apache.servicemix.jbi.container.JBIContainer;
024    import org.apache.servicemix.jbi.framework.ComponentContextImpl;
025    import org.apache.xbean.kernel.Kernel;
026    import org.apache.xbean.kernel.KernelFactory;
027    import org.apache.xbean.kernel.ServiceName;
028    import org.apache.xbean.server.repository.FileSystemRepository;
029    import org.apache.xbean.server.spring.loader.SpringLoader;
030    import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
031    import org.springframework.core.io.FileSystemResource;
032    
033    import javax.jbi.component.ComponentContext;
034    import javax.jbi.management.DeploymentException;
035    import java.io.File;
036    import java.util.Collections;
037    import java.util.Iterator;
038    import java.util.List;
039    
040    public class AbstractXBeanDeployer extends AbstractDeployer {
041    
042        public AbstractXBeanDeployer(ServiceMixComponent component) {
043            super(component);
044        }
045        
046        protected String getXBeanFile() {
047            return "xbean";
048        }
049    
050        /* (non-Javadoc)
051         * @see org.apache.servicemix.common.Deployer#canDeploy(java.lang.String, java.lang.String)
052         */
053        public boolean canDeploy(String serviceUnitName, String serviceUnitRootPath) {
054            File xbean = new File(serviceUnitRootPath, getXBeanFile() + ".xml");
055            if (logger.isDebugEnabled()) {
056                logger.debug("Looking for " + xbean + ": " + xbean.exists());
057            }
058            return xbean.exists();
059        }
060    
061        /* (non-Javadoc)
062         * @see org.apache.servicemix.common.Deployer#deploy(java.lang.String, java.lang.String)
063         */
064        public ServiceUnit deploy(String serviceUnitName, String serviceUnitRootPath) throws DeploymentException {
065            Kernel kernel = KernelFactory.newInstance().createKernel(component.getComponentName() + "/" + serviceUnitName);
066            try {
067                // Create service unit
068                XBeanServiceUnit su = new XBeanServiceUnit();
069                su.setKernel(kernel);
070                su.setComponent(component);
071                su.setName(serviceUnitName);
072                su.setRootPath(serviceUnitRootPath);
073                // Load configuration
074                ClassLoader classLoader = component.getClass().getClassLoader();
075                Thread.currentThread().setContextClassLoader(classLoader);
076    
077                SpringLoader springLoader = createSpringLoader();
078                springLoader.setKernel(kernel);
079                springLoader.setBaseDir(new File(serviceUnitRootPath));
080                springLoader.setXmlPreprocessors(getXmlPreProcessors(serviceUnitRootPath));
081                springLoader.setBeanFactoryPostProcessors(getBeanFactoryPostProcessors(serviceUnitRootPath));
082                
083                ServiceName configurationName = springLoader.load(getXBeanFile());
084                kernel.startService(configurationName);
085                su.setConfiguration(configurationName);
086                // Use SU classloader
087                Thread.currentThread().setContextClassLoader(su.getConfigurationClassLoader());
088                // Retrieve endpoints
089                List services = getServices(kernel);
090                if (services == null || services.size() == 0) {
091                    throw failure("deploy", "No endpoints found", null);
092                }
093                for (Iterator iter = services.iterator(); iter.hasNext();) {
094                    Endpoint endpoint = (Endpoint) iter.next();
095                    endpoint.setServiceUnit(su);
096                    validate(endpoint);
097                    su.addEndpoint(endpoint);
098                }
099                if (su.getEndpoints().size() == 0) {
100                    throw failure("deploy", "No endpoint found", null);
101                }
102                return su;
103            } catch (Throwable e) {
104                // There is a chance the thread context classloader has been changed by the xbean kernel,
105                // so put back a good one
106                Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
107                kernel.destroy();
108                if (e instanceof DeploymentException) {
109                    throw ((DeploymentException) e);
110                } else {
111                    throw failure("deploy", "Could not deploy xbean service unit", e);
112                }
113            } finally {
114                Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
115            }
116        }
117    
118        /**
119         * A factory method to allow derived classes to create alternative spring loaders
120         */
121        protected SpringLoader createSpringLoader() {
122            return new SpringLoader();
123        }
124    
125        protected List getServices(Kernel kernel) throws DeploymentException {
126            return kernel.getServices(Endpoint.class);
127        }
128        
129        protected List getXmlPreProcessors(String serviceUnitRootPath) {
130            JBIContainer container = null;
131            try {
132                container = ((ComponentContextImpl) component.getComponentContext()).getContainer();
133            } catch (Throwable t) { }
134            FileSystemRepository repository = new FileSystemRepository(new File(serviceUnitRootPath));
135            ClassLoaderXmlPreprocessor classLoaderXmlPreprocessor = new ClassLoaderXmlPreprocessor(repository, container);
136            return Collections.singletonList(classLoaderXmlPreprocessor);
137        }
138        
139        protected List getBeanFactoryPostProcessors(String serviceUnitRootPath) {
140            PropertyPlaceholderConfigurer propertyPlaceholder = new PropertyPlaceholderConfigurer();
141            FileSystemResource propertiesFile = new FileSystemResource(
142                    new File(serviceUnitRootPath) + "/" + getXBeanFile()
143                            + ".properties");
144            if (propertiesFile.getFile().exists()) {                
145                propertyPlaceholder.setLocation(propertiesFile);
146                return Collections.singletonList(propertyPlaceholder);
147            } 
148            return Collections.EMPTY_LIST;
149        }
150        
151    }