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: 36321 $ 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. Returns 092 * 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 }