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.slf4j.Logger;
025    import org.slf4j.LoggerFactory;
026    
027    /**
028     * A helper class for working with services together with a useful base class
029     * for service implementations.
030     * 
031     * 
032     */
033    public abstract class ServiceSupport implements Service {
034        private static final Logger LOG = LoggerFactory.getLogger(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                stopped.set(false);
053                try {
054                    doStart();
055                    success = true;
056                } finally {
057                    started.set(success);
058                }
059                for(ServiceListener l:this.serviceListeners) {
060                    l.started(this);
061                }
062            }
063        }
064    
065        public void stop() throws Exception {
066            if (stopped.compareAndSet(false, true)) {
067                stopping.set(true);
068                ServiceStopper stopper = new ServiceStopper();
069                try {
070                    doStop(stopper);
071                } catch (Exception e) {
072                    stopper.onException(this, e);
073                }
074                stopped.set(true);
075                started.set(false);
076                stopping.set(false);
077                for(ServiceListener l:this.serviceListeners) {
078                    l.stopped(this);
079                }
080                stopper.throwFirstException();
081            }
082        }
083    
084        /**
085         * @return true if this service has been started
086         */
087        public boolean isStarted() {
088            return started.get();
089        }
090    
091        /**
092         * @return true if this service is in the process of closing
093         */
094        public boolean isStopping() {
095            return stopping.get();
096        }
097    
098        /**
099         * @return true if this service is closed
100         */
101        public boolean isStopped() {
102            return stopped.get();
103        }
104        
105        public void addServiceListener(ServiceListener l) {
106            this.serviceListeners.add(l);
107        }
108        
109        public void removeServiceListener(ServiceListener l) {
110            this.serviceListeners.remove(l);
111        }
112    
113        protected abstract void doStop(ServiceStopper stopper) throws Exception;
114    
115        protected abstract void doStart() throws Exception;
116    }