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 * Is the given service suspended 349 * 350 * @return <tt>true</tt> if already suspended, otherwise <tt>false</tt> 351 */ 352 public static boolean isSuspended(Object value) { 353 if (value instanceof StatefulService) { 354 StatefulService service = (StatefulService) value; 355 if (service.isSuspended() || service.isSuspending()) { 356 return true; 357 } 358 } 359 return false; 360 } 361 362 /** 363 * Gather all child services by navigating the service to recursively gather all child services. 364 * 365 * @param service the service 366 * @return the services, including the parent service, and all its children 367 */ 368 public static Set<Service> getChildServices(Service service) { 369 Set<Service> answer = new LinkedHashSet<Service>(); 370 doGetChildServices(answer, service); 371 return answer; 372 } 373 374 private static void doGetChildServices(Set<Service> services, Service service) { 375 services.add(service); 376 if (service instanceof Navigate) { 377 Navigate<?> nav = (Navigate<?>) service; 378 if (nav.hasNext()) { 379 List<?> children = nav.next(); 380 for (Object child : children) { 381 if (child instanceof Service) { 382 doGetChildServices(services, (Service) child); 383 } 384 } 385 } 386 } 387 } 388 389 }