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                Thread.currentThread().setContextClassLoader(component.getClass().getClassLoader());
075    
076                SpringLoader springLoader = createSpringLoader();
077                springLoader.setKernel(kernel);
078                springLoader.setBaseDir(new File(serviceUnitRootPath));
079                springLoader.setXmlPreprocessors(getXmlPreProcessors(serviceUnitRootPath));
080                springLoader.setBeanFactoryPostProcessors(getBeanFactoryPostProcessors(serviceUnitRootPath));
081                
082                ServiceName configurationName = springLoader.load(getXBeanFile());
083                kernel.startService(configurationName);
084                su.setConfiguration(configurationName);
085                // Use SU classloader
086                Thread.currentThread().setContextClassLoader(su.getConfigurationClassLoader());
087                // Retrieve endpoints
088                List services = getServices(kernel);
089                if (services == null || services.size() == 0) {
090                    throw failure("deploy", "No endpoints found", null);
091                }
092                for (Iterator iter = services.iterator(); iter.hasNext();) {
093                    Endpoint endpoint = (Endpoint) iter.next();
094                    endpoint.setServiceUnit(su);
095                    validate(endpoint);
096                    su.addEndpoint(endpoint);
097                }
098                if (su.getEndpoints().size() == 0) {
099                    throw failure("deploy", "No endpoint found", null);
100                }
101                return su;
102            } catch (Throwable e) {
103                // There is a chance the thread context classloader has been changed by the xbean kernel,
104                // so put back a good one
105                Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
106                kernel.destroy();
107                if (e instanceof DeploymentException) {
108                    throw ((DeploymentException) e);
109                } else {
110                    throw failure("deploy", "Could not deploy xbean service unit", e);
111                }
112            } finally {
113                Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
114            }
115        }
116    
117        /**
118         * A factory method to allow derived classes to create alternative spring loaders
119         */
120        protected SpringLoader createSpringLoader() {
121            return new SpringLoader();
122        }
123    
124        protected List getServices(Kernel kernel) throws DeploymentException {
125            return kernel.getServices(Endpoint.class);
126        }
127        
128        protected List getXmlPreProcessors(String serviceUnitRootPath) {
129            JBIContainer container = null;
130            try {
131                container = ((ComponentContextImpl) component.getComponentContext()).getContainer();
132            } catch (Throwable t) { }
133            FileSystemRepository repository = new FileSystemRepository(new File(serviceUnitRootPath));
134            ClassLoaderXmlPreprocessor classLoaderXmlPreprocessor = new ClassLoaderXmlPreprocessor(repository, container);
135            return Collections.singletonList(classLoaderXmlPreprocessor);
136        }
137        
138        protected List getBeanFactoryPostProcessors(String serviceUnitRootPath) {
139            PropertyPlaceholderConfigurer propertyPlaceholder = new PropertyPlaceholderConfigurer();
140            FileSystemResource propertiesFile = new FileSystemResource(
141                    new File(serviceUnitRootPath) + "/" + getXBeanFile()
142                            + ".properties");
143            if (propertiesFile.getFile().exists()) {                
144                propertyPlaceholder.setLocation(propertiesFile);
145                return Collections.singletonList(propertyPlaceholder);
146            } 
147            return Collections.EMPTY_LIST;
148        }
149        
150    }