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.ServiceStatus; 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: 751221 $ 033 */ 034 public abstract class ServiceSupport implements Service { 035 private static int threadCounter; 036 private final AtomicBoolean started = new AtomicBoolean(false); 037 private final AtomicBoolean starting = new AtomicBoolean(false); 038 private final AtomicBoolean stopping = new AtomicBoolean(false); 039 private final AtomicBoolean stopped = new AtomicBoolean(false); 040 private Collection childServices; 041 private String version; 042 043 public void start() throws Exception { 044 if (started.compareAndSet(false, true)) { 045 starting.set(true); 046 try { 047 if (childServices != null) { 048 ServiceHelper.startServices(childServices); 049 } 050 doStart(); 051 } finally { 052 notStarting(); 053 } 054 } 055 } 056 057 public void stop() throws Exception { 058 if (started.get() && stopping.compareAndSet(false, true)) { 059 try { 060 doStop(); 061 } finally { 062 if (childServices != null) { 063 ServiceHelper.stopServices(childServices); 064 } 065 stopped.set(true); 066 started.set(false); 067 stopping.set(false); 068 } 069 } 070 } 071 072 /** 073 * Returns the current status 074 */ 075 public ServiceStatus getStatus() { 076 // lets check these in oldest first as these flags can be changing in a concurrent world 077 if (isStarting()) { 078 return ServiceStatus.Starting; 079 } 080 if (isStarted()) { 081 return ServiceStatus.Started; 082 } 083 if (isStopping()) { 084 return ServiceStatus.Stopping; 085 } 086 if (isStopped()) { 087 return ServiceStatus.Stopped; 088 } 089 return ServiceStatus.Created; 090 } 091 092 /** 093 * @return true if this service has been started 094 */ 095 public boolean isStarted() { 096 return started.get(); 097 } 098 099 /** 100 * @return true if this service is 101 */ 102 public boolean isStarting() { 103 return starting.get(); 104 } 105 106 /** 107 * @return true if this service is in the process of closing 108 */ 109 public boolean isStopping() { 110 return stopping.get(); 111 } 112 113 /** 114 * Helper methods so the service knows if it should keep running. 115 * Returns false if the service is being stopped or is stopped. 116 * 117 * @return true if the service should continue to run. 118 */ 119 protected boolean isRunAllowed() { 120 return !(stopping.get() || stopped.get()); 121 } 122 123 /** 124 * @return true if this service is closed 125 */ 126 public boolean isStopped() { 127 return stopped.get(); 128 } 129 130 protected abstract void doStart() throws Exception; 131 132 protected abstract void doStop() throws Exception; 133 134 135 protected void notStarting() { 136 starting.set(false); 137 } 138 139 /** 140 * Creates a new thread name with the given prefix 141 */ 142 protected String getThreadName(String prefix) { 143 return prefix + " thread:" + nextThreadCounter(); 144 } 145 146 protected static synchronized int nextThreadCounter() { 147 return ++threadCounter; 148 } 149 150 protected void addChildService(Object childService) { 151 if (childServices == null) { 152 childServices = new ArrayList(); 153 } 154 childServices.add(childService); 155 } 156 157 protected boolean removeChildService(Object childService) { 158 if (childServices != null) { 159 return childServices.remove(childService); 160 } else { 161 return false; 162 } 163 } 164 165 /** 166 * Returns the version of this service 167 */ 168 public synchronized String getVersion() { 169 if (ObjectHelper.isNotEmpty(version)) { 170 return version; 171 } 172 173 Package aPackage = getClass().getPackage(); 174 if (aPackage != null) { 175 version = aPackage.getImplementationVersion(); 176 if (version == null) { 177 version = aPackage.getSpecificationVersion(); 178 if (version == null) { 179 version = ""; 180 } 181 } 182 } else { 183 version = ""; 184 } 185 return version; 186 } 187 }