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 java.io.File;
020    import java.util.ArrayList;
021    import java.util.Collection;
022    import java.util.Collections;
023    import java.util.HashMap;
024    import java.util.Iterator;
025    import java.util.List;
026    import java.util.Map;
027    
028    import javax.jbi.management.DeploymentException;
029    
030    import org.apache.servicemix.common.AbstractDeployer;
031    import org.apache.servicemix.common.Endpoint;
032    import org.apache.servicemix.common.EndpointComponentContext;
033    import org.apache.servicemix.common.ServiceMixComponent;
034    import org.apache.servicemix.common.ServiceUnit;
035    import org.apache.xbean.spring.context.FileSystemXmlApplicationContext;
036    import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
037    import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
038    import org.springframework.context.support.AbstractXmlApplicationContext;
039    import org.springframework.core.io.FileSystemResource;
040    
041    public class AbstractXBeanDeployer extends AbstractDeployer {
042    
043        public AbstractXBeanDeployer(ServiceMixComponent component) {
044            super(component);
045        }
046        
047        protected String getXBeanFile() {
048            return "xbean";
049        }
050    
051        /* (non-Javadoc)
052         * @see org.apache.servicemix.common.Deployer#canDeploy(java.lang.String, java.lang.String)
053         */
054        public boolean canDeploy(String serviceUnitName, String serviceUnitRootPath) {
055            File xbean = new File(serviceUnitRootPath, getXBeanFile() + ".xml");
056            if (logger.isDebugEnabled()) {
057                logger.debug("Looking for " + xbean + ": " + xbean.exists());
058            }
059            return xbean.exists();
060        }
061    
062        /* (non-Javadoc)
063         * @see org.apache.servicemix.common.Deployer#deploy(java.lang.String, java.lang.String)
064         */
065        public ServiceUnit deploy(String serviceUnitName, String serviceUnitRootPath) throws DeploymentException {
066            AbstractXmlApplicationContext applicationContext = null;
067            try {
068                // Create service unit
069                XBeanServiceUnit su = new XBeanServiceUnit();
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                File baseDir = new File(serviceUnitRootPath);
078                String location = getXBeanFile();
079                applicationContext = createApplicationContext(serviceUnitRootPath);
080    
081                for (Iterator iter = getBeanFactoryPostProcessors(serviceUnitRootPath).iterator(); iter.hasNext();) {
082                    BeanFactoryPostProcessor processor = (BeanFactoryPostProcessor) iter.next();
083                    applicationContext.addBeanFactoryPostProcessor(processor);
084                }
085    
086                applicationContext.refresh();
087                su.setApplicationContext(applicationContext);
088                // Use SU classloader
089                Thread.currentThread().setContextClassLoader(su.getConfigurationClassLoader());
090                initApplicationContext(applicationContext);
091    
092                // Retrieve endpoints
093                Collection<Endpoint> endpoints = getServices(applicationContext);
094                for (Endpoint endpoint : endpoints) {
095                    endpoint.setServiceUnit(su);
096                    validate(endpoint);
097                    su.addEndpoint(endpoint);
098                }
099                validate(su);
100                return su;
101            } catch (Throwable e) {
102                logger.error(e);
103                if (applicationContext != null) {
104                    try {
105                        applicationContext.destroy();
106                    } catch (Exception ne) {
107                        logger.error(ne);
108                    }
109                }
110                // There is a chance the thread context classloader has been changed by the xbean kernel,
111                // so put back a good one
112                Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
113                if (e instanceof DeploymentException) {
114                    throw ((DeploymentException) e);
115                } else {
116                    throw failure("deploy", "Could not deploy xbean service unit", e);
117                }
118            } finally {
119                Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
120            }
121        }
122    
123        protected void initApplicationContext(AbstractXmlApplicationContext applicationContext) throws Exception {
124        }
125    
126        protected Collection<Endpoint> getServices(AbstractXmlApplicationContext applicationContext) throws Exception {
127            return applicationContext.getBeansOfType(Endpoint.class).values();
128        }
129    
130        protected FileSystemXmlApplicationContext createApplicationContext(String serviceUnitRootPath) {
131            File baseDir = new File(serviceUnitRootPath);
132            String location = getXBeanFile();
133            return new FileSystemXmlApplicationContext(
134                                            new String[] { "/" + baseDir.toURI().resolve(location).getPath() + ".xml" },
135                                            false,
136                                            getXmlPreProcessors(serviceUnitRootPath));
137        }
138    
139        protected List getXmlPreProcessors(String serviceUnitRootPath) {
140            ClassLoaderXmlPreprocessor classLoaderXmlPreprocessor = new ClassLoaderXmlPreprocessor(new File(serviceUnitRootPath), component);
141            return Collections.singletonList(classLoaderXmlPreprocessor);
142        }
143        
144        protected List getBeanFactoryPostProcessors(String serviceUnitRootPath) {
145            List processors = new ArrayList();
146            // Property place holder
147            PropertyPlaceholderConfigurer propertyPlaceholder = new PropertyPlaceholderConfigurer();
148            FileSystemResource propertiesFile = new FileSystemResource(new File(serviceUnitRootPath) + "/" + getXBeanFile() + ".properties");
149            if (propertiesFile.getFile().exists()) {                
150                propertyPlaceholder.setLocation(propertiesFile);
151                processors.add(propertyPlaceholder);
152            }
153            // Parent beans map
154            Map beans = getParentBeansMap();
155            if (beans != null) {
156                processors.add(new ParentBeanFactoryPostProcessor(beans));
157            }
158            return processors;
159        }
160    
161        protected Map getParentBeansMap() {
162            Map beans = new HashMap();
163            beans.put("context", new EndpointComponentContext(component.getComponentContext()));
164            beans.put("component", component);
165            Object smx3 = component.getSmx3Container();
166            if (smx3 != null) {
167                beans.put("container", smx3);
168            }
169            return beans;
170        }
171        
172    }