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;
018    
019    import org.apache.commons.logging.Log;
020    
021    import javax.jbi.component.ServiceUnitManager;
022    import javax.jbi.management.DeploymentException;
023    import javax.jbi.management.LifeCycleMBean;
024    
025    /**
026     * A simple service unit manager.
027     * This service unit manager uses {@link Deployer} objects
028     * to handle different type of service units.
029     * 
030     * @author Guillaume Nodet
031     * @version $Revision: 695836 $
032     * @since 3.0
033     */
034    public class BaseServiceUnitManager implements ServiceUnitManager {
035    
036        protected final transient Log logger;
037        
038        protected ServiceMixComponent component;
039        
040        protected Deployer[] deployers;
041        
042        protected boolean persistent;
043        
044        public BaseServiceUnitManager(ServiceMixComponent component, Deployer[] deployers) {
045            this(component, deployers, false);
046        }
047    
048        public BaseServiceUnitManager(ServiceMixComponent component, Deployer[] deployers, boolean persistent) {
049            this.component = component;
050            this.logger = component.getLogger();
051            this.deployers = deployers;
052            this.persistent = persistent;
053        }
054        
055        /* (non-Javadoc)
056         * @see javax.jbi.component.ServiceUnitManager#deploy(java.lang.String, java.lang.String)
057         */
058        public synchronized String deploy(String serviceUnitName, String serviceUnitRootPath) throws DeploymentException {
059            try {
060                if (logger.isDebugEnabled()) {
061                    logger.debug("Deploying service unit");
062                }
063                if (serviceUnitName == null || serviceUnitName.length() == 0) {
064                    throw new IllegalArgumentException("serviceUnitName should be non null and non empty");
065                }
066                if (getServiceUnit(serviceUnitName) != null) {
067                    throw failure("deploy", "Service Unit '" + serviceUnitName + "' is already deployed", null);
068                }
069                ServiceUnit su = doDeploy(serviceUnitName, serviceUnitRootPath);
070                if (su == null) {
071                    throw failure("deploy", "Unable to find suitable deployer for Service Unit '" + serviceUnitName + "'", null);
072                }
073                component.getRegistry().registerServiceUnit(su);
074                if (logger.isDebugEnabled()) {
075                    logger.debug("Service unit deployed");
076                }
077                return createSuccessMessage("deploy");
078            } catch (DeploymentException e) {
079                throw e;
080            } catch (Exception e) {
081                throw failure("deploy", "Unable to deploy service unit", e);
082            }
083        }
084        
085        protected ServiceUnit doDeploy(String serviceUnitName, String serviceUnitRootPath) throws Exception {
086            for (int i = 0; i < deployers.length; i++) {
087                if (deployers[i].canDeploy(serviceUnitName, serviceUnitRootPath)) {
088                    return deployers[i].deploy(serviceUnitName, serviceUnitRootPath);
089                }
090            }
091            return null;
092        }
093    
094        /* (non-Javadoc)
095         * @see javax.jbi.component.ServiceUnitManager#init(java.lang.String, java.lang.String)
096         */
097        public synchronized void init(String serviceUnitName, String serviceUnitRootPath) throws DeploymentException {
098            ClassLoader cl = Thread.currentThread().getContextClassLoader();
099            try {
100                if (logger.isDebugEnabled()) {
101                    logger.debug("Initializing service unit");
102                }
103                if (serviceUnitName == null || serviceUnitName.length() == 0) {
104                    throw new IllegalArgumentException("serviceUnitName should be non null and non empty");
105                }
106                ServiceUnit su = getServiceUnit(serviceUnitName);
107                if (su == null) {
108                    if (!persistent) {
109                        su = doDeploy(serviceUnitName, serviceUnitRootPath);
110                        if (su == null) {
111                            throw failure("deploy", "Unable to find suitable deployer for Service Unit '" + serviceUnitName + "'", null);
112                        }
113                        component.getRegistry().registerServiceUnit(su);
114                    } else {
115                        throw failure("init", "Service Unit '" + serviceUnitName + "' is not deployed", null);
116                    }
117                }
118                if (!LifeCycleMBean.SHUTDOWN.equals(su.getCurrentState())) {
119                    throw failure("init", "ServiceUnit should be in a SHUTDOWN state", null);
120                }
121                Thread.currentThread().setContextClassLoader(su.getConfigurationClassLoader());
122                su.init();
123                if (logger.isDebugEnabled()) {
124                    logger.debug("Service unit initialized");
125                }
126            } catch (DeploymentException e) {
127                throw e;
128            } catch (Exception e) {
129                throw failure("init", "Unable to init service unit", e);
130            } finally {
131                Thread.currentThread().setContextClassLoader(cl);
132            }
133        }
134    
135        /* (non-Javadoc)
136         * @see javax.jbi.component.ServiceUnitManager#start(java.lang.String)
137         */
138        public synchronized void start(String serviceUnitName) throws DeploymentException {
139            ClassLoader cl = Thread.currentThread().getContextClassLoader();
140            try {
141                if (logger.isDebugEnabled()) {
142                    logger.debug("Starting service unit");
143                }
144                if (serviceUnitName == null || serviceUnitName.length() == 0) {
145                    throw new IllegalArgumentException("serviceUnitName should be non null and non empty");
146                }
147                ServiceUnit su = (ServiceUnit) getServiceUnit(serviceUnitName);
148                if (su == null) {
149                    throw failure("start", "Service Unit '" + serviceUnitName + "' is not deployed", null);
150                }
151                if (!LifeCycleMBean.STOPPED.equals(su.getCurrentState())) {
152                    throw failure("start", "ServiceUnit should be in a STOPPED state", null);
153                }
154                Thread.currentThread().setContextClassLoader(su.getConfigurationClassLoader());
155                su.start();
156                if (logger.isDebugEnabled()) {
157                    logger.debug("Service unit started");
158                }
159            } catch (DeploymentException e) {
160                throw e;
161            } catch (Exception e) {
162                throw failure("start", "Unable to start service unit", e);
163            } finally {
164                Thread.currentThread().setContextClassLoader(cl);
165            }
166        }
167    
168        /* (non-Javadoc)
169         * @see javax.jbi.component.ServiceUnitManager#stop(java.lang.String)
170         */
171        public synchronized void stop(String serviceUnitName) throws DeploymentException {
172            ClassLoader cl = Thread.currentThread().getContextClassLoader();
173            try {
174                if (logger.isDebugEnabled()) {
175                    logger.debug("Stopping service unit");
176                }
177                if (serviceUnitName == null || serviceUnitName.length() == 0) {
178                    throw new IllegalArgumentException("serviceUnitName should be non null and non empty");
179                }
180                ServiceUnit su = getServiceUnit(serviceUnitName);
181                if (su == null) {
182                    throw failure("stop", "Service Unit '" + serviceUnitName + "' is not deployed", null);
183                }
184                if (!LifeCycleMBean.STARTED.equals(su.getCurrentState())) {
185                    throw failure("stop", "ServiceUnit should be in a STARTED state", null);
186                }
187                Thread.currentThread().setContextClassLoader(su.getConfigurationClassLoader());
188                su.stop();
189                if (logger.isDebugEnabled()) {
190                    logger.debug("Service unit stopped");
191                }
192            } catch (DeploymentException e) {
193                throw e;
194            } catch (Exception e) {
195                throw failure("stop", "Unable to stop service unit", e);
196            } finally {
197                Thread.currentThread().setContextClassLoader(cl);
198            }
199        }
200    
201        /* (non-Javadoc)
202         * @see javax.jbi.component.ServiceUnitManager#shutDown(java.lang.String)
203         */
204        public synchronized void shutDown(String serviceUnitName) throws DeploymentException {
205            ClassLoader cl = Thread.currentThread().getContextClassLoader();
206            try {
207                if (logger.isDebugEnabled()) {
208                    logger.debug("Shutting down service unit");
209                }
210                if (serviceUnitName == null || serviceUnitName.length() == 0) {
211                    throw new IllegalArgumentException("serviceUnitName should be non null and non empty");
212                }
213                ServiceUnit su = getServiceUnit(serviceUnitName);
214                if (su == null) {
215                    throw failure("shutDown", "Service Unit '" + serviceUnitName + "' is not deployed", null);
216                }
217                if (!LifeCycleMBean.STOPPED.equals(su.getCurrentState())) {
218                    throw failure("start", "ServiceUnit should be in a STOPPED state", null);
219                }
220                Thread.currentThread().setContextClassLoader(su.getConfigurationClassLoader());
221                su.shutDown();
222                if (logger.isDebugEnabled()) {
223                    logger.debug("Service unit shut down");
224                }
225            } catch (DeploymentException e) {
226                throw e;
227            } catch (Exception e) {
228                throw failure("shutDown", "Unable to shutdown service unit", e);
229            } finally {
230                Thread.currentThread().setContextClassLoader(cl);
231            }
232        }
233    
234        /* (non-Javadoc)
235         * @see javax.jbi.component.ServiceUnitManager#undeploy(java.lang.String, java.lang.String)
236         */
237        public synchronized String undeploy(String serviceUnitName, String serviceUnitRootPath) throws DeploymentException {
238            ClassLoader cl = Thread.currentThread().getContextClassLoader();
239            try {
240                if (logger.isDebugEnabled()) {
241                    logger.debug("Undeploying service unit");
242                }
243                if (logger.isDebugEnabled()) {
244                    logger.debug("Shutting down service unit");
245                }
246                if (serviceUnitName == null || serviceUnitName.length() == 0) {
247                    throw new IllegalArgumentException("serviceUnitName should be non null and non empty");
248                }
249                ServiceUnit su = getServiceUnit(serviceUnitName);
250                if (su == null) {
251                    throw failure("undeploy", "Service Unit '" + serviceUnitName + "' is not deployed", null);
252                }
253                if (!LifeCycleMBean.SHUTDOWN.equals(su.getCurrentState())) {
254                    throw failure("undeploy", "ServiceUnit should be in a SHUTDOWN state", null);
255                }
256                Thread.currentThread().setContextClassLoader(su.getConfigurationClassLoader());
257                doUndeploy(su);
258                component.getRegistry().unregisterServiceUnit(su);
259                if (logger.isDebugEnabled()) {
260                    logger.debug("Service unit undeployed");
261                }
262                return createSuccessMessage("undeploy");
263            } catch (DeploymentException e) {
264                throw e;
265            } catch (Exception e) {
266                throw failure("undeploy", "Unable to undeploy service unit", e);
267            } finally {
268                Thread.currentThread().setContextClassLoader(cl);
269            }
270        }
271    
272        protected void doUndeploy(ServiceUnit su) throws Exception {
273            for (int i = 0; i < deployers.length; i++) {
274                if (deployers[i].canDeploy(su.getName(), su.getRootPath())) {
275                    deployers[i].undeploy(su);
276                    return;
277                }
278            }
279            throw failure("undeploy", "Unable to find suitable deployer for Service Unit '" + su.getName() + "'", null);
280        }
281        
282        protected DeploymentException failure(String task, String info, Exception e) throws DeploymentException {
283            ManagementSupport.Message msg = new ManagementSupport.Message();
284            msg.setComponent(component.getComponentName());
285            msg.setTask(task);
286            msg.setResult("FAILED");
287            msg.setType("ERROR");
288            msg.setException(e);
289            msg.setMessage(info);
290            return new DeploymentException(ManagementSupport.createComponentMessage(msg));
291        }
292    
293        protected String createSuccessMessage(String task) {
294            ManagementSupport.Message msg = new ManagementSupport.Message();
295            msg.setComponent(component.getComponentName());
296            msg.setTask(task);
297            msg.setResult("SUCCESS");
298            return ManagementSupport.createComponentMessage(msg);
299        }
300        
301        protected ServiceUnit getServiceUnit(String name) {
302            return component.getRegistry().getServiceUnit(name);
303        }
304        
305    }