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.camel.impl;
018    
019    import java.util.ArrayList;
020    import java.util.Collection;
021    import java.util.concurrent.atomic.AtomicBoolean;
022    
023    import org.apache.camel.Service;
024    import org.apache.camel.ServiceStatus;
025    import org.apache.camel.util.ObjectHelper;
026    import org.apache.camel.util.ServiceHelper;
027    
028    /**
029     * A useful base class which ensures that a service is only initialized once and
030     * provides some helper methods for enquiring of its status
031     *
032     * @version $Revision: 751221 $
033     */
034    public abstract class ServiceSupport implements Service {
035        private static int threadCounter;
036        private final AtomicBoolean started = new AtomicBoolean(false);
037        private final AtomicBoolean starting = new AtomicBoolean(false);
038        private final AtomicBoolean stopping = new AtomicBoolean(false);
039        private final AtomicBoolean stopped = new AtomicBoolean(false);
040        private Collection childServices;
041        private String version;
042    
043        public void start() throws Exception {
044            if (started.compareAndSet(false, true)) {
045                starting.set(true);
046                try {
047                    if (childServices != null) {
048                        ServiceHelper.startServices(childServices);
049                    }
050                    doStart();
051                } finally {
052                    notStarting();
053                }
054            }
055        }
056    
057        public void stop() throws Exception {
058            if (started.get() && stopping.compareAndSet(false, true)) {
059                try {
060                    doStop();
061                } finally {
062                    if (childServices != null) {
063                        ServiceHelper.stopServices(childServices);
064                    }
065                    stopped.set(true);
066                    started.set(false);
067                    stopping.set(false);
068                }
069            }
070        }
071    
072        /**
073         * Returns the current status
074         */
075        public ServiceStatus getStatus() {
076            // lets check these in oldest first as these flags can be changing in a concurrent world
077            if (isStarting()) {
078                return ServiceStatus.Starting;
079            }
080            if (isStarted()) {
081                return ServiceStatus.Started;
082            }
083            if (isStopping()) {
084                return ServiceStatus.Stopping;
085            }
086            if (isStopped()) {
087                return ServiceStatus.Stopped;
088            }
089            return ServiceStatus.Created;
090        }
091        
092        /**
093         * @return true if this service has been started
094         */
095        public boolean isStarted() {
096            return started.get();
097        }
098    
099        /**
100         * @return true if this service is
101         */
102        public boolean isStarting() {
103            return starting.get();
104        }
105    
106        /**
107         * @return true if this service is in the process of closing
108         */
109        public boolean isStopping() {
110            return stopping.get();
111        }
112    
113        /**
114         * Helper methods so the service knows if it should keep running.
115         * Returns false if the service is being stopped or is stopped.
116         *
117         * @return true if the service should continue to run.
118         */
119        protected boolean isRunAllowed() {
120            return !(stopping.get() || stopped.get());
121        }
122    
123        /**
124         * @return true if this service is closed
125         */
126        public boolean isStopped() {
127            return stopped.get();
128        }
129    
130        protected abstract void doStart() throws Exception;
131    
132        protected abstract void doStop() throws Exception;
133    
134    
135        protected void notStarting() {
136            starting.set(false);
137        }
138    
139        /**
140         * Creates a new thread name with the given prefix
141         */
142        protected String getThreadName(String prefix) {
143            return prefix + " thread:" + nextThreadCounter();
144        }
145    
146        protected static synchronized int nextThreadCounter() {
147            return ++threadCounter;
148        }
149    
150        protected void addChildService(Object childService) {
151            if (childServices == null) {
152                childServices = new ArrayList();
153            }
154            childServices.add(childService);
155        }
156    
157        protected boolean removeChildService(Object childService) {
158            if (childServices != null) {
159                return childServices.remove(childService);
160            } else {
161                return false;
162            }
163        }
164    
165        /**
166         * Returns the version of this service
167         */
168        public synchronized String getVersion() {
169            if (ObjectHelper.isNotEmpty(version)) {
170                return version;
171            }
172            
173            Package aPackage = getClass().getPackage();
174            if (aPackage != null) {
175                version = aPackage.getImplementationVersion();
176                if (version == null) {
177                    version = aPackage.getSpecificationVersion();
178                    if (version == null) {
179                        version = "";
180                    }
181                }
182            } else {
183                version = "";
184            }
185            return version;
186        }
187    }