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 */ 017package org.apache.camel.support; 018 019import java.util.LinkedHashSet; 020import java.util.Set; 021 022import org.apache.camel.util.ServiceHelper; 023 024/** 025 * Base class to control lifecycle for a set of child {@link org.apache.camel.Service}s. 026 */ 027public abstract class ChildServiceSupport extends ServiceSupport { 028 private Set<Object> childServices; 029 030 public void start() throws Exception { 031 start(true); 032 } 033 034 public void start(boolean startChildren) throws Exception { 035 if (!started.get()) { 036 if (starting.compareAndSet(false, true)) { 037 boolean childrenStarted = false; 038 Exception ex = null; 039 try { 040 if (childServices != null && startChildren) { 041 ServiceHelper.startServices(childServices); 042 } 043 childrenStarted = true; 044 doStart(); 045 } catch (Exception e) { 046 ex = e; 047 } finally { 048 if (ex != null) { 049 try { 050 stop(childrenStarted); 051 } catch (Exception e) { 052 // Ignore exceptions as we want to show the original exception 053 } 054 throw ex; 055 } else { 056 started.set(true); 057 starting.set(false); 058 stopping.set(false); 059 stopped.set(false); 060 suspending.set(false); 061 suspended.set(false); 062 shutdown.set(false); 063 shuttingdown.set(false); 064 } 065 } 066 } 067 } 068 } 069 070 private void stop(boolean childrenStarted) throws Exception { 071 if (stopping.compareAndSet(false, true)) { 072 try { 073 try { 074 starting.set(false); 075 suspending.set(false); 076 if (childrenStarted) { 077 doStop(); 078 } 079 } finally { 080 started.set(false); 081 suspended.set(false); 082 if (childServices != null) { 083 ServiceHelper.stopServices(childServices); 084 } 085 } 086 } finally { 087 stopped.set(true); 088 stopping.set(false); 089 starting.set(false); 090 started.set(false); 091 suspending.set(false); 092 suspended.set(false); 093 shutdown.set(false); 094 shuttingdown.set(false); 095 } 096 } 097 } 098 099 public void stop() throws Exception { 100 if (!stopped.get()) { 101 stop(true); 102 } 103 } 104 105 public void shutdown() throws Exception { 106 // ensure we are stopped first 107 stop(); 108 109 if (shuttingdown.compareAndSet(false, true)) { 110 try { 111 try { 112 doShutdown(); 113 } finally { 114 if (childServices != null) { 115 ServiceHelper.stopAndShutdownServices(childServices); 116 } 117 } 118 } finally { 119 // shutdown is also stopped so only set shutdown flags 120 shutdown.set(true); 121 shuttingdown.set(false); 122 } 123 } 124 } 125 126 protected void addChildService(Object childService) { 127 synchronized (this) { 128 if (childServices == null) { 129 childServices = new LinkedHashSet<Object>(); 130 } 131 } 132 childServices.add(childService); 133 } 134 135 protected boolean removeChildService(Object childService) { 136 return childServices != null && childServices.remove(childService); 137 } 138 139}