Merge "Add Mycilla code to odlguice"
[odlguice.git] / inject / inject / src / main / java / org / opendaylight / infrautils / inject / AbstractLifecycle.java
1 /*
2  * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.infrautils.inject;
9
10 import java.util.concurrent.atomic.AtomicReference;
11 import javax.annotation.PostConstruct;
12 import javax.annotation.PreDestroy;
13 import org.slf4j.Logger;
14 import org.slf4j.LoggerFactory;
15
16 /**
17  * Support class for {@link Lifecycle}. Provides a convenient base
18  * implementation including correct thread safety, exception handling and check
19  * for accidental unnecessary re-start & stop. Subclasses must implement
20  * {@link #start()} & {@link #stop()}.
21  *
22  * @author Michael Vorburger (with guidance re. AtomicReference from Tom Pantelis)
23  */
24 public abstract class AbstractLifecycle implements Lifecycle {
25     private static final Logger LOG = LoggerFactory.getLogger(AbstractLifecycle.class);
26
27     private enum State {
28         STARTED, STOPPED
29     }
30
31     private final AtomicReference<State> state = new AtomicReference<>(State.STOPPED);
32
33     protected abstract void start() throws Exception;
34
35     protected abstract void stop() throws Exception;
36
37     /**
38      * Please implement {@link #start()} instead of overriding this (here intentionally final) method.
39      */
40     @Override
41     @PostConstruct // NOTE: @PostConstruct is *NOT* inherited from interface, so must be here
42     @SuppressWarnings("checkstyle:IllegalCatch")
43     public final void init() throws ModuleSetupRuntimeException {
44         if (state.compareAndSet(State.STOPPED, State.STARTED)) {
45             try {
46                 start();
47             } catch (Exception e) {
48                 throw new ModuleSetupRuntimeException(e);
49             }
50         } else {
51             LOG.warn("Lifecycled object already started; ignoring start()");
52         }
53     }
54
55     /**
56      * Please implement {@link #stop()} instead of overriding this (here intentionally final) method.
57      */
58     @Override
59     @PreDestroy // NOTE: @PostConstruct is *NOT* inherited from interface, so must be here
60     @SuppressWarnings("checkstyle:IllegalCatch")
61     public final void destroy() throws ModuleSetupRuntimeException {
62         if (state.compareAndSet(State.STARTED, State.STOPPED)) {
63             try {
64                 stop();
65             } catch (Exception e) {
66                 throw new ModuleSetupRuntimeException(e);
67             }
68         } else {
69             LOG.warn("Lifecycled object already stopped; ignoring stop()");
70         }
71     }
72
73     @Override
74     public boolean isRunning() {
75         return state.get() == State.STARTED;
76     }
77
78     protected void checkIsRunning() {
79         if (!isRunning()) {
80             throw new IllegalStateException("Lifecycled object is already stopped: " + this.toString());
81         }
82     }
83
84 }