View Javadoc

1   package com.atlassian.plugin.manager;
2   
3   import java.util.concurrent.atomic.AtomicReference;
4   
5   /**
6    * Simple thread-safe state machine that prevents illegal transitions.
7    * <p>
8    * Could be easily extended to allow custom workflows by interfacing 
9    * out the State type and having this class generified with that.
10   */
11  class StateTracker
12  {
13      enum State
14      {
15          NOT_STARTED
16          {
17              @Override
18              void check(final State newState)
19              {
20                  if (newState != STARTING && newState != SHUTTING_DOWN)
21                  {
22                      illegalState(newState);
23                  }
24              }
25          },
26          STARTING,
27          STARTED
28          {
29              @Override
30              void check(final State newState)
31              {
32                  if (newState != WARM_RESTARTING && newState != SHUTTING_DOWN)
33                  {
34                      illegalState(newState);
35                  }
36              }
37          },
38          WARM_RESTARTING
39          {
40              @Override
41              void check(final State newState)
42              {
43                  if (newState != STARTED)
44                  {
45                      illegalState(newState);
46                  }
47              }
48          },
49          SHUTTING_DOWN,
50          SHUTDOWN
51          {
52              @Override
53              void check(final State newState)
54              {
55                  if (newState != STARTING)
56                  {
57                      illegalState(newState);
58                  }
59              }
60          };
61  
62          void check(final State newState)
63          {
64              if ((ordinal() + 1) != newState.ordinal())
65              {
66                  illegalState(newState);
67              }
68          }
69  
70          void illegalState(final State newState)
71          {
72              throw new IllegalStateException("Cannot go from State: " + this + " to: " + newState);
73          }
74      }
75  
76      private final AtomicReference<State> state = new AtomicReference<State>(State.NOT_STARTED);
77  
78      public State get()
79      {
80          return state.get();
81      }
82  
83      StateTracker setState(final State newState) throws IllegalStateException
84      {
85          for (;;)
86          {
87              final State oldState = get();
88              oldState.check(newState);
89              if (state.compareAndSet(oldState, newState))
90              {
91                  return this;
92              }
93          }
94      }
95  
96      @Override
97      public String toString()
98      {
99          return get().toString();
100     }
101 }