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 }