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.util;
018
019 import java.util.Arrays;
020 import java.util.Collection;
021 import java.util.LinkedHashSet;
022 import java.util.List;
023 import java.util.Set;
024
025 import org.apache.camel.Navigate;
026 import org.apache.camel.Service;
027 import org.apache.camel.ShutdownableService;
028 import org.apache.camel.StatefulService;
029 import org.apache.camel.SuspendableService;
030 import org.slf4j.Logger;
031 import org.slf4j.LoggerFactory;
032
033 /**
034 * A collection of helper methods for working with {@link Service} objects
035 *
036 * @version
037 */
038 public final class ServiceHelper {
039 private static final transient Logger LOG = LoggerFactory.getLogger(ServiceHelper.class);
040
041 /**
042 * Utility classes should not have a public constructor.
043 */
044 private ServiceHelper() {
045 }
046
047 /**
048 * Starts all of the given services
049 */
050 public static void startService(Object value) throws Exception {
051 if (value instanceof Service) {
052 startService((Service)value);
053 } else if (value instanceof Collection) {
054 startServices((Collection<?>)value);
055 }
056 }
057
058 /**
059 * Starts all of the given services
060 */
061 public static void startService(Service service) throws Exception {
062 service.start();
063 }
064
065 /**
066 * Starts all of the given services
067 */
068 public static void startServices(Object... services) throws Exception {
069 if (services == null) {
070 return;
071 }
072 for (Object value : services) {
073 startService(value);
074 }
075 }
076
077 /**
078 * Starts all of the given services
079 */
080 public static void startServices(Collection<?> services) throws Exception {
081 if (services == null) {
082 return;
083 }
084 for (Object value : services) {
085 startService(value);
086 }
087 }
088
089 /**
090 * Stops all of the given services, throwing the first exception caught
091 */
092 public static void stopServices(Object... services) throws Exception {
093 if (services == null) {
094 return;
095 }
096 List<Object> list = Arrays.asList(services);
097 stopServices(list);
098 }
099
100 /**
101 * Stops all of the given services, throwing the first exception caught
102 */
103 public static void stopService(Object value) throws Exception {
104 if (isStopped(value)) {
105 // only stop service if not already stopped
106 LOG.trace("Service already stopped: {}", value);
107 return;
108 }
109 if (value instanceof Service) {
110 Service service = (Service)value;
111 LOG.trace("Stopping service {}", value);
112 service.stop();
113 } else if (value instanceof Collection) {
114 stopServices((Collection<?>)value);
115 }
116 }
117
118 /**
119 * Stops all of the given services, throwing the first exception caught
120 */
121 public static void stopServices(Collection<?> services) throws Exception {
122 if (services == null) {
123 return;
124 }
125 Exception firstException = null;
126 for (Object value : services) {
127 try {
128 stopService(value);
129 } catch (Exception e) {
130 if (LOG.isDebugEnabled()) {
131 LOG.debug("Caught exception stopping service: " + value, e);
132 }
133 if (firstException == null) {
134 firstException = e;
135 }
136 }
137 }
138 if (firstException != null) {
139 throw firstException;
140 }
141 }
142
143 /**
144 * Stops and shutdowns all of the given services, throwing the first exception caught
145 */
146 public static void stopAndShutdownServices(Object... services) throws Exception {
147 if (services == null) {
148 return;
149 }
150 List<Object> list = Arrays.asList(services);
151 stopAndShutdownServices(list);
152 }
153
154 /**
155 * Stops and shutdowns all of the given services, throwing the first exception caught
156 */
157 public static void stopAndShutdownService(Object value) throws Exception {
158 stopService(value);
159
160 // then try to shutdown
161 if (value instanceof ShutdownableService) {
162 ShutdownableService service = (ShutdownableService)value;
163 LOG.trace("Shutting down service {}", value);
164 service.shutdown();
165 }
166 }
167
168 /**
169 * Stops and shutdowns all of the given services, throwing the first exception caught
170 */
171 public static void stopAndShutdownServices(Collection<?> services) throws Exception {
172 if (services == null) {
173 return;
174 }
175 Exception firstException = null;
176
177 for (Object value : services) {
178
179 // must stop it first
180 stopService(value);
181
182 // then try to shutdown
183 if (value instanceof ShutdownableService) {
184 ShutdownableService service = (ShutdownableService)value;
185 try {
186 LOG.trace("Shutting down service: {}", service);
187 service.shutdown();
188 } catch (Exception e) {
189 if (LOG.isDebugEnabled()) {
190 LOG.debug("Caught exception shutting down service: " + service, e);
191 }
192 if (firstException == null) {
193 firstException = e;
194 }
195 }
196 }
197 }
198 if (firstException != null) {
199 throw firstException;
200 }
201 }
202
203 public static void resumeServices(Collection<?> services) throws Exception {
204 if (services == null) {
205 return;
206 }
207 Exception firstException = null;
208 for (Object value : services) {
209 if (value instanceof Service) {
210 Service service = (Service)value;
211 try {
212 resumeService(service);
213 } catch (Exception e) {
214 if (LOG.isDebugEnabled()) {
215 LOG.debug("Caught exception resuming service: " + service, e);
216 }
217 if (firstException == null) {
218 firstException = e;
219 }
220 }
221 }
222 }
223 if (firstException != null) {
224 throw firstException;
225 }
226 }
227
228 /**
229 * Resumes the given service.
230 * <p/>
231 * If the service is a {@link org.apache.camel.SuspendableService} then the <tt>resume</tt>
232 * operation is <b>only</b> invoked if the service is suspended.
233 * <p/>
234 * If the service is a {@link org.apache.camel.support.ServiceSupport} then the <tt>start</tt>
235 * operation is <b>only</b> invoked if the service is startable.
236 * <p/>
237 * Otherwise the service is started.
238 *
239 * @param service the service
240 * @return <tt>true</tt> if either <tt>resume</tt> or <tt>start</tt> was invoked,
241 * <tt>false</tt> if the service is already in the desired state.
242 * @throws Exception is thrown if error occurred
243 */
244 public static boolean resumeService(Service service) throws Exception {
245 if (service instanceof SuspendableService) {
246 SuspendableService ss = (SuspendableService) service;
247 if (ss.isSuspended()) {
248 LOG.debug("Resuming service {}", service);
249 ss.resume();
250 return true;
251 } else {
252 return false;
253 }
254 } else {
255 startService(service);
256 return true;
257 }
258 }
259
260 public static void suspendServices(Collection<?> services) throws Exception {
261 if (services == null) {
262 return;
263 }
264 Exception firstException = null;
265 for (Object value : services) {
266 if (value instanceof Service) {
267 Service service = (Service)value;
268 try {
269 suspendService(service);
270 } catch (Exception e) {
271 if (LOG.isDebugEnabled()) {
272 LOG.debug("Caught exception suspending service: " + service, e);
273 }
274 if (firstException == null) {
275 firstException = e;
276 }
277 }
278 }
279 }
280 if (firstException != null) {
281 throw firstException;
282 }
283 }
284
285 /**
286 * Suspends the given service.
287 * <p/>
288 * If the service is a {@link org.apache.camel.SuspendableService} then the <tt>suspend</tt>
289 * operation is <b>only</b> invoked if the service is <b>not</b> suspended.
290 * <p/>
291 * If the service is a {@link org.apache.camel.support.ServiceSupport} then the <tt>stop</tt>
292 * operation is <b>only</b> invoked if the service is stoppable.
293 * <p/>
294 * Otherwise the service is stopped.
295 *
296 * @param service the service
297 * @return <tt>true</tt> if either <tt>suspend</tt> or <tt>stop</tt> was invoked,
298 * <tt>false</tt> if the service is already in the desired state.
299 * @throws Exception is thrown if error occurred
300 */
301 public static boolean suspendService(Service service) throws Exception {
302 if (service instanceof SuspendableService) {
303 SuspendableService ss = (SuspendableService) service;
304 if (!ss.isSuspended()) {
305 LOG.trace("Suspending service {}", service);
306 ss.suspend();
307 return true;
308 } else {
309 return false;
310 }
311 } else {
312 stopService(service);
313 return true;
314 }
315 }
316
317 /**
318 * Is the given service stopping or stopped?
319 *
320 * @return <tt>true</tt> if already stopped, otherwise <tt>false</tt>
321 */
322 public static boolean isStopped(Object value) {
323 if (value instanceof StatefulService) {
324 StatefulService service = (StatefulService) value;
325 if (service.isStopping() || service.isStopped()) {
326 return true;
327 }
328 }
329 return false;
330 }
331
332 /**
333 * Is the given service starting or started?
334 *
335 * @return <tt>true</tt> if already started, otherwise <tt>false</tt>
336 */
337 public static boolean isStarted(Object value) {
338 if (value instanceof StatefulService) {
339 StatefulService service = (StatefulService) value;
340 if (service.isStarting() || service.isStarted()) {
341 return true;
342 }
343 }
344 return false;
345 }
346
347 /**
348 * Gather all child services by navigating the service to recursively gather all child services.
349 *
350 * @param service the service
351 * @return the services, including the parent service, and all its children
352 */
353 public static Set<Service> getChildServices(Service service) {
354 Set<Service> answer = new LinkedHashSet<Service>();
355 doGetChildServices(answer, service);
356 return answer;
357 }
358
359 private static void doGetChildServices(Set<Service> services, Service service) {
360 services.add(service);
361 if (service instanceof Navigate) {
362 Navigate<?> nav = (Navigate<?>) service;
363 if (nav.hasNext()) {
364 List<?> children = nav.next();
365 for (Object child : children) {
366 if (child instanceof Service) {
367 doGetChildServices(services, (Service) child);
368 }
369 }
370 }
371 }
372 }
373
374 }