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