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.Collection;
020 import java.util.concurrent.CopyOnWriteArrayList;
021 import java.util.concurrent.atomic.AtomicBoolean;
022
023 import org.apache.camel.CamelException;
024 import org.apache.camel.Service;
025 import org.apache.camel.util.ObjectHelper;
026 import org.apache.camel.util.ServiceHelper;
027
028 /**
029 * A useful base class which ensures that a service is only initialized once and
030 * provides some helper methods for enquiring of its status
031 *
032 * @version $Revision: 763092 $
033 */
034 public abstract class ServiceSupport implements Service {
035 private static int threadCounter;
036 private AtomicBoolean started = new AtomicBoolean(false);
037 private AtomicBoolean starting = new AtomicBoolean(false);
038 private AtomicBoolean stopping = new AtomicBoolean(false);
039 private AtomicBoolean stopped = new AtomicBoolean(false);
040 private Collection childServices;
041 private String version;
042
043 public void start() throws Exception {
044 if (!started.get()) {
045 if (starting.compareAndSet(false, true)) {
046 boolean childrenStarted = false;
047 Exception ex = null;
048 try {
049 if (childServices != null) {
050 ServiceHelper.startServices(childServices);
051 }
052 childrenStarted = true;
053 doStart();
054 } catch (Exception e) {
055 ex = e;
056 } finally {
057 if (ex != null) {
058 stop(childrenStarted);
059 throw ex;
060 } else {
061 started.set(true);
062 starting.set(false);
063 }
064 }
065 }
066 }
067 }
068
069 private void stop(boolean childrenStarted) throws Exception {
070 if (stopping.compareAndSet(false, true)) {
071 try {
072 try {
073 starting.set(false);
074 if (childrenStarted) {
075 doStop();
076 }
077 } finally {
078 started.set(false);
079 if (childServices != null) {
080 ServiceHelper.stopServices(childServices);
081 }
082 }
083 } finally {
084 stopped.set(true);
085 stopping.set(false);
086 }
087 }
088 }
089
090 public void stop() throws Exception {
091 if (started.get()) {
092 stop(true);
093 }
094 }
095
096 /**
097 * @return true if this service has been started
098 */
099 public boolean isStarted() {
100 return started.get();
101 }
102
103 /**
104 * @return true if this service is
105 */
106 public boolean isStarting() {
107 return starting.get();
108 }
109
110 /**
111 * @return true if this service is in the process of closing
112 */
113 public boolean isStopping() {
114 return stopping.get();
115 }
116
117 /**
118 * @return true if this service is closed
119 */
120 public boolean isStopped() {
121 return stopped.get();
122 }
123
124 /**
125 * Helper methods so the service knows if it should keep running.
126 * Returns false if the service is being stopped or is stopped.
127 *
128 * @return true if the service should continue to run.
129 */
130 protected boolean isRunAllowed() {
131 return !(stopping.get() || stopped.get());
132 }
133
134 protected abstract void doStart() throws Exception;
135
136 protected abstract void doStop() throws Exception;
137
138 /**
139 * Creates a new thread name with the given prefix
140 */
141 protected String getThreadName(String prefix) {
142 return prefix + " thread:" + nextThreadCounter();
143 }
144
145 protected static synchronized int nextThreadCounter() {
146 return ++threadCounter;
147 }
148
149 protected void addChildService(Object childService) {
150 synchronized (this) {
151 if (childServices == null) {
152 childServices = new CopyOnWriteArrayList();
153 }
154 }
155 childServices.add(childService);
156 }
157
158 protected boolean removeChildService(Object childService) {
159 return childServices != null ? childServices.remove(childService) : false;
160 }
161
162 protected synchronized String getVersion() {
163 if (ObjectHelper.isNotNullAndNonEmpty(version)) {
164 return version;
165 }
166
167 Package aPackage = getClass().getPackage();
168 if (aPackage != null) {
169 version = aPackage.getImplementationVersion();
170 if (version == null) {
171 version = aPackage.getSpecificationVersion();
172 }
173 }
174 return version != null ? version : "";
175 }
176 }