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