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