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.activemq.util;
018    
019    import java.util.List;
020    import java.util.concurrent.CopyOnWriteArrayList;
021    import java.util.concurrent.atomic.AtomicBoolean;
022    
023    import org.apache.activemq.Service;
024    import org.apache.commons.logging.Log;
025    import org.apache.commons.logging.LogFactory;
026    
027    /**
028     * A helper class for working with services together with a useful base class
029     * for service implementations.
030     * 
031     * @version $Revision: 1.1 $
032     */
033    public abstract class ServiceSupport implements Service {
034        private static final Log LOG = LogFactory.getLog(ServiceSupport.class);
035    
036        private AtomicBoolean started = new AtomicBoolean(false);
037        private AtomicBoolean stopping = new AtomicBoolean(false);
038        private AtomicBoolean stopped = new AtomicBoolean(false);
039        private List<ServiceListener>serviceListeners = new CopyOnWriteArrayList<ServiceListener>();
040    
041        public static void dispose(Service service) {
042            try {
043                service.stop();
044            } catch (Exception e) {
045                LOG.debug("Could not stop service: " + service + ". Reason: " + e, e);
046            }
047        }
048    
049        public void start() throws Exception {
050            if (started.compareAndSet(false, true)) {
051                boolean success = false;
052                try {
053                    doStart();
054                    success = true;
055                } finally {
056                    started.set(success);
057                }
058                for(ServiceListener l:this.serviceListeners) {
059                    l.started(this);
060                }
061            }
062        }
063    
064        public void stop() throws Exception {
065            if (stopped.compareAndSet(false, true)) {
066                stopping.set(true);
067                ServiceStopper stopper = new ServiceStopper();
068                try {
069                    doStop(stopper);
070                } catch (Exception e) {
071                    stopper.onException(this, e);
072                }
073                stopped.set(true);
074                started.set(false);
075                stopping.set(false);
076                for(ServiceListener l:this.serviceListeners) {
077                    l.stopped(this);
078                }
079                stopper.throwFirstException();
080            }
081        }
082    
083        /**
084         * @return true if this service has been started
085         */
086        public boolean isStarted() {
087            return started.get();
088        }
089    
090        /**
091         * @return true if this service is in the process of closing
092         */
093        public boolean isStopping() {
094            return stopping.get();
095        }
096    
097        /**
098         * @return true if this service is closed
099         */
100        public boolean isStopped() {
101            return stopped.get();
102        }
103        
104        public void addServiceListener(ServiceListener l) {
105            this.serviceListeners.add(l);
106        }
107        
108        public void removeServiceListener(ServiceListener l) {
109            this.serviceListeners.remove(l);
110        }
111    
112        protected abstract void doStop(ServiceStopper stopper) throws Exception;
113    
114        protected abstract void doStart() throws Exception;
115    }