1// 2// ======================================================================== 3// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. 4// ------------------------------------------------------------------------ 5// All rights reserved. This program and the accompanying materials 6// are made available under the terms of the Eclipse Public License v1.0 7// and Apache License v2.0 which accompanies this distribution. 8// 9// The Eclipse Public License is available at 10// http://www.eclipse.org/legal/epl-v10.html 11// 12// The Apache License v2.0 is available at 13// http://www.opensource.org/licenses/apache2.0.php 14// 15// You may elect to redistribute this code under either of these licenses. 16// ======================================================================== 17// 18 19package org.eclipse.jetty.util.component; 20 21import java.util.concurrent.CopyOnWriteArrayList; 22 23import org.eclipse.jetty.util.log.Log; 24import org.eclipse.jetty.util.log.Logger; 25 26/** 27 * Basic implementation of the life cycle interface for components. 28 * 29 * 30 */ 31public abstract class AbstractLifeCycle implements LifeCycle 32{ 33 private static final Logger LOG = Log.getLogger(AbstractLifeCycle.class); 34 public static final String STOPPED="STOPPED"; 35 public static final String FAILED="FAILED"; 36 public static final String STARTING="STARTING"; 37 public static final String STARTED="STARTED"; 38 public static final String STOPPING="STOPPING"; 39 public static final String RUNNING="RUNNING"; 40 41 private final Object _lock = new Object(); 42 private final int __FAILED = -1, __STOPPED = 0, __STARTING = 1, __STARTED = 2, __STOPPING = 3; 43 private volatile int _state = __STOPPED; 44 45 protected final CopyOnWriteArrayList<LifeCycle.Listener> _listeners=new CopyOnWriteArrayList<LifeCycle.Listener>(); 46 47 protected void doStart() throws Exception 48 { 49 } 50 51 protected void doStop() throws Exception 52 { 53 } 54 55 public final void start() throws Exception 56 { 57 synchronized (_lock) 58 { 59 try 60 { 61 if (_state == __STARTED || _state == __STARTING) 62 return; 63 setStarting(); 64 doStart(); 65 setStarted(); 66 } 67 catch (Exception e) 68 { 69 setFailed(e); 70 throw e; 71 } 72 catch (Error e) 73 { 74 setFailed(e); 75 throw e; 76 } 77 } 78 } 79 80 public final void stop() throws Exception 81 { 82 synchronized (_lock) 83 { 84 try 85 { 86 if (_state == __STOPPING || _state == __STOPPED) 87 return; 88 setStopping(); 89 doStop(); 90 setStopped(); 91 } 92 catch (Exception e) 93 { 94 setFailed(e); 95 throw e; 96 } 97 catch (Error e) 98 { 99 setFailed(e); 100 throw e; 101 } 102 } 103 } 104 105 public boolean isRunning() 106 { 107 final int state = _state; 108 109 return state == __STARTED || state == __STARTING; 110 } 111 112 public boolean isStarted() 113 { 114 return _state == __STARTED; 115 } 116 117 public boolean isStarting() 118 { 119 return _state == __STARTING; 120 } 121 122 public boolean isStopping() 123 { 124 return _state == __STOPPING; 125 } 126 127 public boolean isStopped() 128 { 129 return _state == __STOPPED; 130 } 131 132 public boolean isFailed() 133 { 134 return _state == __FAILED; 135 } 136 137 public void addLifeCycleListener(LifeCycle.Listener listener) 138 { 139 _listeners.add(listener); 140 } 141 142 public void removeLifeCycleListener(LifeCycle.Listener listener) 143 { 144 _listeners.remove(listener); 145 } 146 147 public String getState() 148 { 149 switch(_state) 150 { 151 case __FAILED: return FAILED; 152 case __STARTING: return STARTING; 153 case __STARTED: return STARTED; 154 case __STOPPING: return STOPPING; 155 case __STOPPED: return STOPPED; 156 } 157 return null; 158 } 159 160 public static String getState(LifeCycle lc) 161 { 162 if (lc.isStarting()) return STARTING; 163 if (lc.isStarted()) return STARTED; 164 if (lc.isStopping()) return STOPPING; 165 if (lc.isStopped()) return STOPPED; 166 return FAILED; 167 } 168 169 private void setStarted() 170 { 171 _state = __STARTED; 172 LOG.debug(STARTED+" {}",this); 173 for (Listener listener : _listeners) 174 listener.lifeCycleStarted(this); 175 } 176 177 private void setStarting() 178 { 179 LOG.debug("starting {}",this); 180 _state = __STARTING; 181 for (Listener listener : _listeners) 182 listener.lifeCycleStarting(this); 183 } 184 185 private void setStopping() 186 { 187 LOG.debug("stopping {}",this); 188 _state = __STOPPING; 189 for (Listener listener : _listeners) 190 listener.lifeCycleStopping(this); 191 } 192 193 private void setStopped() 194 { 195 _state = __STOPPED; 196 LOG.debug("{} {}",STOPPED,this); 197 for (Listener listener : _listeners) 198 listener.lifeCycleStopped(this); 199 } 200 201 private void setFailed(Throwable th) 202 { 203 _state = __FAILED; 204 LOG.warn(FAILED+" " + this+": "+th,th); 205 for (Listener listener : _listeners) 206 listener.lifeCycleFailure(this,th); 207 } 208 209 public static abstract class AbstractLifeCycleListener implements LifeCycle.Listener 210 { 211 public void lifeCycleFailure(LifeCycle event, Throwable cause) {} 212 public void lifeCycleStarted(LifeCycle event) {} 213 public void lifeCycleStarting(LifeCycle event) {} 214 public void lifeCycleStopped(LifeCycle event) {} 215 public void lifeCycleStopping(LifeCycle event) {} 216 } 217} 218