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.jbi.framework;
018    
019    import java.beans.PropertyChangeEvent;
020    import java.beans.PropertyChangeListener;
021    import java.io.File;
022    
023    import javax.jbi.component.ServiceUnitManager;
024    import javax.jbi.management.DeploymentException;
025    import javax.management.JMException;
026    import javax.management.MBeanAttributeInfo;
027    import javax.management.MBeanOperationInfo;
028    
029    import org.apache.commons.logging.Log;
030    import org.apache.commons.logging.LogFactory;
031    import org.apache.servicemix.jbi.deployment.Descriptor;
032    import org.apache.servicemix.jbi.deployment.DescriptorFactory;
033    import org.apache.servicemix.jbi.deployment.ServiceUnit;
034    import org.apache.servicemix.jbi.deployment.Services;
035    import org.apache.servicemix.jbi.event.ServiceUnitEvent;
036    import org.apache.servicemix.jbi.event.ServiceUnitListener;
037    import org.apache.servicemix.jbi.management.AttributeInfoHelper;
038    import org.apache.servicemix.jbi.management.MBeanInfoProvider;
039    import org.apache.servicemix.jbi.management.OperationInfoHelper;
040    
041    public class ServiceUnitLifeCycle implements ServiceUnitMBean, MBeanInfoProvider {
042    
043        private static final Log LOG = LogFactory.getLog(ServiceUnitLifeCycle.class);
044    
045        private ServiceUnit serviceUnit;
046    
047        private String currentState = SHUTDOWN;
048        
049        private String serviceAssembly;
050        
051        private Registry registry;
052    
053        private PropertyChangeListener listener;
054        
055        private Services services;
056        
057        private File rootDir;
058        
059        public ServiceUnitLifeCycle(ServiceUnit serviceUnit, 
060                                    String serviceAssembly,
061                                    Registry registry,
062                                    File rootDir) {
063            this.serviceUnit = serviceUnit;
064            this.serviceAssembly = serviceAssembly;
065            this.registry = registry;
066            this.rootDir = rootDir;
067            Descriptor d = DescriptorFactory.buildDescriptor(rootDir);
068            if (d != null) {
069                services = d.getServices();
070            }
071        }
072    
073        /**
074         * Initialize the service unit.
075         * @throws DeploymentException 
076         */
077        public void init() throws DeploymentException {
078            LOG.info("Initializing service unit: " + getName());
079            checkComponentStarted("init");
080            ServiceUnitManager sum = getServiceUnitManager();
081            File path = getServiceUnitRootPath();
082            ClassLoader cl = Thread.currentThread().getContextClassLoader();
083            try {
084                Thread.currentThread().setContextClassLoader(getComponentClassLoader());
085                sum.init(getName(), path.getAbsolutePath());
086            } finally {
087                Thread.currentThread().setContextClassLoader(cl);
088            }
089            currentState = STOPPED;
090        }
091        
092        /**
093         * Start the service unit.
094         * @throws DeploymentException 
095         */
096        public void start() throws DeploymentException {
097            LOG.info("Starting service unit: " + getName());
098            checkComponentStarted("start");
099            ServiceUnitManager sum = getServiceUnitManager();
100            ClassLoader cl = Thread.currentThread().getContextClassLoader();
101            try {
102                Thread.currentThread().setContextClassLoader(getComponentClassLoader());
103                sum.start(getName());
104            } finally {
105                Thread.currentThread().setContextClassLoader(cl);
106            }
107            currentState = STARTED;
108        }
109    
110        /**
111         * Stop the service unit. This suspends current messaging activities.
112         * @throws DeploymentException 
113         */
114        public void stop() throws DeploymentException {
115            LOG.info("Stopping service unit: " + getName());
116            checkComponentStarted("stop");
117            ServiceUnitManager sum = getServiceUnitManager();
118            ClassLoader cl = Thread.currentThread().getContextClassLoader();
119            try {
120                Thread.currentThread().setContextClassLoader(getComponentClassLoader());
121                sum.stop(getName());
122            } finally {
123                Thread.currentThread().setContextClassLoader(cl);
124            }
125            currentState = STOPPED;
126        }
127    
128        /**
129         * Shut down the service unit. 
130         * This releases resources, preparatory to uninstallation.
131         * @throws DeploymentException 
132         */
133        public void shutDown() throws DeploymentException {
134            LOG.info("Shutting down service unit: " + getName());
135            checkComponentStartedOrStopped("shutDown");
136            ServiceUnitManager sum = getServiceUnitManager();
137            ClassLoader cl = Thread.currentThread().getContextClassLoader();
138            try {
139                Thread.currentThread().setContextClassLoader(getComponentClassLoader());
140                sum.shutDown(getName());
141            } finally {
142                Thread.currentThread().setContextClassLoader(cl);
143            }
144            currentState = SHUTDOWN;
145        }
146    
147        /**
148         * @return the currentState as a String
149         */
150        public String getCurrentState() {
151            return currentState;
152        }
153    
154        public boolean isShutDown() {
155            return currentState.equals(SHUTDOWN);
156        }
157    
158        public boolean isStopped() {
159            return currentState.equals(STOPPED);
160        }
161    
162        public boolean isStarted() {
163            return currentState.equals(STARTED);
164        }
165        
166        /**
167         * @return the name of the ServiceAssembly
168         */
169        public String getName() {
170            return serviceUnit.getIdentification().getName();
171        }
172    
173        /**
174         * @return the description of the ServiceAssembly
175         */
176        public String getDescription() {
177            return serviceUnit.getIdentification().getDescription();
178        }
179        
180        public String getComponentName() {
181            return serviceUnit.getTarget().getComponentName();
182        }
183    
184        public String getServiceAssembly() {
185            return serviceAssembly;
186        }
187    
188        public String getDescriptor() {
189            File suDir = getServiceUnitRootPath();
190            return DescriptorFactory.getDescriptorAsText(suDir);
191        }
192        
193        public Services getServices() {
194            return services;
195        }
196    
197        protected void checkComponentStarted(String task) throws DeploymentException {
198            String componentName = getComponentName();
199            String suName = getName();
200            ComponentMBeanImpl lcc = registry.getComponent(componentName);
201            if (lcc == null) {
202                throw ManagementSupport.componentFailure("deploy", componentName, "Target component "
203                                + componentName + " for service unit " + suName + " is not installed");
204            }
205            if (!lcc.isStarted()) {
206                throw ManagementSupport.componentFailure("deploy", componentName, "Target component "
207                                + componentName + " for service unit " + suName + " is not started");
208            }
209            if (lcc.getServiceUnitManager() == null) {
210                throw ManagementSupport.componentFailure("deploy", componentName, "Target component "
211                                + componentName + " for service unit " + suName + " does not accept deployments");
212            }
213        }
214        
215        protected void checkComponentStartedOrStopped(String task) throws DeploymentException {
216            String componentName = getComponentName();
217            String suName = getName();
218            ComponentMBeanImpl lcc = registry.getComponent(componentName);
219            if (lcc == null) {
220                throw ManagementSupport.componentFailure("deploy", componentName, "Target component "
221                                + componentName + " for service unit " + suName + " is not installed");
222            }
223            if (!lcc.isStarted() && !lcc.isStopped()) {
224                throw ManagementSupport.componentFailure("deploy", componentName, "Target component "
225                                + componentName + " for service unit " + suName + " is not started");
226            }
227            if (lcc.getServiceUnitManager() == null) {
228                throw ManagementSupport.componentFailure("deploy", componentName, "Target component "
229                                + componentName + " for service unit " + suName + " does not accept deployments");
230            }
231        }
232        
233        protected File getServiceUnitRootPath() {
234            return rootDir;
235        }
236        
237        protected ServiceUnitManager getServiceUnitManager() {
238            ComponentMBeanImpl lcc = registry.getComponent(getComponentName());
239            return lcc.getServiceUnitManager();
240        }
241    
242        protected ClassLoader getComponentClassLoader() {
243            ComponentMBeanImpl lcc = registry.getComponent(getComponentName());
244            // TODO: should retrieve the real component class loader
245            return lcc.getComponent().getClass().getClassLoader();
246        }
247    
248        public MBeanAttributeInfo[] getAttributeInfos() throws JMException {
249            AttributeInfoHelper helper = new AttributeInfoHelper();
250            helper.addAttribute(getObjectToManage(), "currentState", "current state of the service unit");
251            helper.addAttribute(getObjectToManage(), "name", "name of the service unit");
252            helper.addAttribute(getObjectToManage(), "componentName", "component name of the service unit");
253            helper.addAttribute(getObjectToManage(), "serviceAssembly", "service assembly name of the service unit");
254            helper.addAttribute(getObjectToManage(), "description", "description of the service unit");
255            return helper.getAttributeInfos();
256        }
257    
258        public MBeanOperationInfo[] getOperationInfos() throws JMException {
259            OperationInfoHelper helper = new OperationInfoHelper();
260            helper.addOperation(getObjectToManage(), "getDescriptor", "retrieve the jbi descriptor for this unit");
261            return helper.getOperationInfos();
262        }
263    
264        public Object getObjectToManage() {
265            return this;
266        }
267    
268        public String getType() {
269            return "ServiceUnit";
270        }
271    
272        public String getSubType() {
273            return getComponentName();
274        }
275    
276        public void setPropertyChangeListener(PropertyChangeListener l) {
277            this.listener = l;
278        }
279    
280        protected void firePropertyChanged(String name, Object oldValue, Object newValue) {
281            PropertyChangeListener l = listener;
282            if (l != null) {
283                PropertyChangeEvent event = new PropertyChangeEvent(this, name, oldValue, newValue);
284                l.propertyChange(event);
285            }
286        }
287    
288        public String getKey() {
289            return getComponentName() + "/" + getName();
290        }
291    
292        protected void fireEvent(int type) {
293            ServiceUnitEvent event = new ServiceUnitEvent(this, type);
294            ServiceUnitListener[] listeners = (ServiceUnitListener[]) registry.getContainer().getListeners(ServiceUnitListener.class);
295            for (int i = 0; i < listeners.length; i++) {
296                switch (type) {
297                case ServiceUnitEvent.UNIT_STARTED:
298                    listeners[i].unitStarted(event);
299                    break;
300                case ServiceUnitEvent.UNIT_STOPPED:
301                    listeners[i].unitStopped(event);
302                    break;
303                case ServiceUnitEvent.UNIT_SHUTDOWN:
304                    listeners[i].unitShutDown(event);
305                    break;
306                default:
307                    break;
308                }
309            }
310        }
311    
312    }