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: 452064 $
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            try {
099                if (logger.isDebugEnabled()) {
100                    logger.debug("Initializing service unit");
101                }
102                if (serviceUnitName == null || serviceUnitName.length() == 0) {
103                    throw new IllegalArgumentException("serviceUnitName should be non null and non empty");
104                }
105                if (getServiceUnit(serviceUnitName) == null) {
106                    if (!persistent) {
107                        ServiceUnit su = doDeploy(serviceUnitName, serviceUnitRootPath);
108                        if (su == null) {
109                            throw failure("deploy", "Unable to find suitable deployer for Service Unit '" + serviceUnitName + "'", null);
110                        }
111                        component.getRegistry().registerServiceUnit(su);
112                    } else {
113                        throw failure("init", "Service Unit '" + serviceUnitName + "' is not deployed", null);
114                    }
115                }
116                doInit(serviceUnitName, serviceUnitRootPath);
117                if (logger.isDebugEnabled()) {
118                    logger.debug("Service unit initialized");
119                }
120            } catch (DeploymentException e) {
121                throw e;
122            } catch (Exception e) {
123                throw failure("init", "Unable to init service unit", e);
124            }
125        }
126    
127        protected void doInit(String serviceUnitName, String serviceUnitRootPath) throws Exception {
128        }
129    
130        /* (non-Javadoc)
131         * @see javax.jbi.component.ServiceUnitManager#start(java.lang.String)
132         */
133        public synchronized void start(String serviceUnitName) throws DeploymentException {
134            ClassLoader cl = Thread.currentThread().getContextClassLoader();
135            try {
136                if (logger.isDebugEnabled()) {
137                    logger.debug("Starting service unit");
138                }
139                if (serviceUnitName == null || serviceUnitName.length() == 0) {
140                    throw new IllegalArgumentException("serviceUnitName should be non null and non empty");
141                }
142                ServiceUnit su = (ServiceUnit) getServiceUnit(serviceUnitName);
143                if (su == null) {
144                    throw failure("start", "Service Unit '" + serviceUnitName + "' is not deployed", null);
145                }
146                if (!LifeCycleMBean.STOPPED.equals(su.getCurrentState()) &&
147                    !LifeCycleMBean.SHUTDOWN.equals(su.getCurrentState())) {
148                    throw failure("start", "ServiceUnit should be in a SHUTDOWN or STOPPED state", null);
149                }
150                Thread.currentThread().setContextClassLoader(su.getConfigurationClassLoader());
151                su.start();
152                if (logger.isDebugEnabled()) {
153                    logger.debug("Service unit started");
154                }
155            } catch (DeploymentException e) {
156                throw e;
157            } catch (Exception e) {
158                throw failure("start", "Unable to start service unit", e);
159            } finally {
160                Thread.currentThread().setContextClassLoader(cl);
161            }
162        }
163    
164        /* (non-Javadoc)
165         * @see javax.jbi.component.ServiceUnitManager#stop(java.lang.String)
166         */
167        public synchronized void stop(String serviceUnitName) throws DeploymentException {
168            ClassLoader cl = Thread.currentThread().getContextClassLoader();
169            try {
170                if (logger.isDebugEnabled()) {
171                    logger.debug("Stopping service unit");
172                }
173                if (serviceUnitName == null || serviceUnitName.length() == 0) {
174                    throw new IllegalArgumentException("serviceUnitName should be non null and non empty");
175                }
176                ServiceUnit su = (ServiceUnit) getServiceUnit(serviceUnitName);
177                if (su == null) {
178                    throw failure("stop", "Service Unit '" + serviceUnitName + "' is not deployed", null);
179                }
180                if (!LifeCycleMBean.STARTED.equals(su.getCurrentState())) {
181                    throw failure("stop", "ServiceUnit should be in a SHUTDOWN state", null);
182                }
183                Thread.currentThread().setContextClassLoader(su.getConfigurationClassLoader());
184                su.stop();
185                if (logger.isDebugEnabled()) {
186                    logger.debug("Service unit stopped");
187                }
188            } catch (DeploymentException e) {
189                throw e;
190            } catch (Exception e) {
191                throw failure("stop", "Unable to stop service unit", e);
192            } finally {
193                Thread.currentThread().setContextClassLoader(cl);
194            }
195        }
196    
197        /* (non-Javadoc)
198         * @see javax.jbi.component.ServiceUnitManager#shutDown(java.lang.String)
199         */
200        public synchronized void shutDown(String serviceUnitName) throws DeploymentException {
201            ClassLoader cl = Thread.currentThread().getContextClassLoader();
202            try {
203                if (logger.isDebugEnabled()) {
204                    logger.debug("Shutting down service unit");
205                }
206                if (serviceUnitName == null || serviceUnitName.length() == 0) {
207                    throw new IllegalArgumentException("serviceUnitName should be non null and non empty");
208                }
209                ServiceUnit su = (ServiceUnit) getServiceUnit(serviceUnitName);
210                if (su == null) {
211                    throw failure("shutDown", "Service Unit '" + serviceUnitName + "' is not deployed", null);
212                }
213                Thread.currentThread().setContextClassLoader(su.getConfigurationClassLoader());
214                su.shutDown();
215                if (logger.isDebugEnabled()) {
216                    logger.debug("Service unit shut down");
217                }
218            } catch (DeploymentException e) {
219                throw e;
220            } catch (Exception e) {
221                throw failure("shutDown", "Unable to shutdown service unit", e);
222            } finally {
223                Thread.currentThread().setContextClassLoader(cl);
224            }
225        }
226    
227        /* (non-Javadoc)
228         * @see javax.jbi.component.ServiceUnitManager#undeploy(java.lang.String, java.lang.String)
229         */
230        public synchronized String undeploy(String serviceUnitName, String serviceUnitRootPath) throws DeploymentException {
231            ClassLoader cl = Thread.currentThread().getContextClassLoader();
232            try {
233                if (logger.isDebugEnabled()) {
234                    logger.debug("Undeploying service unit");
235                }
236                if (logger.isDebugEnabled()) {
237                    logger.debug("Shutting down service unit");
238                }
239                if (serviceUnitName == null || serviceUnitName.length() == 0) {
240                    throw new IllegalArgumentException("serviceUnitName should be non null and non empty");
241                }
242                ServiceUnit su = (ServiceUnit) getServiceUnit(serviceUnitName);
243                if (su == null) {
244                    throw failure("undeploy", "Service Unit '" + serviceUnitName + "' is not deployed", null);
245                }
246                if (!LifeCycleMBean.SHUTDOWN.equals(su.getCurrentState())) {
247                    throw failure("undeploy", "ServiceUnit should be in a SHUTDOWN state", null);
248                }
249                Thread.currentThread().setContextClassLoader(su.getConfigurationClassLoader());
250                doUndeploy(su);
251                component.getRegistry().unregisterServiceUnit(su);
252                if (logger.isDebugEnabled()) {
253                    logger.debug("Service unit undeployed");
254                }
255                return createSuccessMessage("undeploy");
256            } catch (DeploymentException e) {
257                throw e;
258            } catch (Exception e) {
259                throw failure("undeploy", "Unable to undeploy service unit", e);
260            } finally {
261                Thread.currentThread().setContextClassLoader(cl);
262            }
263        }
264    
265        protected void doUndeploy(ServiceUnit su) throws Exception {
266            for (int i = 0; i < deployers.length; i++) {
267                if (deployers[i].canDeploy(su.getName(), su.getRootPath())) {
268                    deployers[i].undeploy(su);
269                    return;
270                }
271            }
272            throw failure("undeploy", "Unable to find suitable deployer for Service Unit '" + su.getName() + "'", null);
273        }
274        
275        protected DeploymentException failure(String task, String info, Exception e) throws DeploymentException {
276            ManagementSupport.Message msg = new ManagementSupport.Message();
277            msg.setComponent(component.getComponentName());
278            msg.setTask(task);
279            msg.setResult("FAILED");
280            msg.setType("ERROR");
281            msg.setException(e);
282            msg.setMessage(info);
283            return new DeploymentException(ManagementSupport.createComponentMessage(msg));
284        }
285    
286        protected String createSuccessMessage(String task) {
287            ManagementSupport.Message msg = new ManagementSupport.Message();
288            msg.setComponent(component.getComponentName());
289            msg.setTask(task);
290            msg.setResult("SUCCESS");
291            return ManagementSupport.createComponentMessage(msg);
292        }
293        
294        protected ServiceUnit getServiceUnit(String name) {
295            return component.getRegistry().getServiceUnit(name);
296        }
297        
298    }