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 }