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