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.util.ServiceHelper;
025
026 /**
027 * A useful base class which ensures that a service is only initialized once and
028 * provides some helper methods for enquiring of its status
029 *
030 * @version $Revision: 659422 $
031 */
032 public abstract class ServiceSupport implements Service {
033 private static int threadCounter;
034 private AtomicBoolean started = new AtomicBoolean(false);
035 private AtomicBoolean starting = new AtomicBoolean(false);
036 private AtomicBoolean stopping = new AtomicBoolean(false);
037 private AtomicBoolean stopped = new AtomicBoolean(false);
038 private Collection childServices;
039
040 public void start() throws Exception {
041 if (started.compareAndSet(false, true)) {
042 starting.set(true);
043 try {
044 if (childServices != null) {
045 ServiceHelper.startServices(childServices);
046 }
047 doStart();
048 } finally {
049 starting.set(false);
050 }
051 }
052 }
053
054 public void stop() throws Exception {
055 if (started.get() && stopping.compareAndSet(false, true)) {
056 try {
057 doStop();
058 } finally {
059 if (childServices != null) {
060 ServiceHelper.stopServices(childServices);
061 }
062 stopped.set(true);
063 started.set(false);
064 stopping.set(false);
065 }
066 }
067 }
068
069 /**
070 * @return true if this service has been started
071 */
072 public boolean isStarted() {
073 return started.get();
074 }
075
076 /**
077 * @return true if this service is
078 */
079 public boolean isStarting() {
080 return starting.get();
081 }
082
083 /**
084 * @return true if this service is in the process of closing
085 */
086 public boolean isStopping() {
087 return stopping.get();
088 }
089
090 /**
091 * Helper methods so the service knows if it should keep running.
092 * Returns false if the service is being stopped or is stopped.
093 *
094 * @return true if the service should continue to run.
095 */
096 protected boolean isRunAllowed() {
097 return !(stopping.get() || stopped.get());
098 }
099
100 /**
101 * @return true if this service is closed
102 */
103 public boolean isStopped() {
104 return stopped.get();
105 }
106
107 protected abstract void doStart() throws Exception;
108
109 protected abstract void doStop() throws Exception;
110
111 /**
112 * Creates a new thread name with the given prefix
113 */
114 protected String getThreadName(String prefix) {
115 return prefix + " thread:" + nextThreadCounter();
116 }
117
118 protected static synchronized int nextThreadCounter() {
119 return ++threadCounter;
120 }
121
122 protected void addChildService(Object childService) {
123 if (childServices == null) {
124 childServices = new ArrayList();
125 }
126 childServices.add(childService);
127 }
128
129 protected boolean removeChildService(Object childService) {
130 if (childServices != null) {
131 return childServices.remove(childService);
132 } else {
133 return false;
134 }
135 }
136 }