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          DELAYED
28          {
29              @Override
30              void check(final State newState)
31              {
32                  if (newState != RESUMING && newState != SHUTTING_DOWN)
33                  {
34                      illegalState(newState);
35                  }
36              }
37          },
38          RESUMING,
39          STARTED
40          {
41              @Override
42              void check(final State newState)
43              {
44                  if (newState != WARM_RESTARTING && newState != SHUTTING_DOWN)
45                  {
46                      illegalState(newState);
47                  }
48              }
49          },
50          WARM_RESTARTING
51          {
52              @Override
53              void check(final State newState)
54              {
55                  if (newState != STARTED)
56                  {
57                      illegalState(newState);
58                  }
59              }
60          },
61          SHUTTING_DOWN,
62          SHUTDOWN
63          {
64              @Override
65              void check(final State newState)
66              {
67                  if (newState != STARTING)
68                  {
69                      illegalState(newState);
70                  }
71              }
72          };
73  
74          void check(final State newState)
75          {
76              if ((ordinal() + 1) != newState.ordinal())
77              {
78                  illegalState(newState);
79              }
80          }
81  
82          void illegalState(final State newState)
83          {
84              throw new IllegalStateException("Cannot go from State: " + this + " to: " + newState);
85          }
86      }
87  
88      private final AtomicReference<State> state = new AtomicReference<State>(State.NOT_STARTED);
89  
90      public State get()
91      {
92          return state.get();
93      }
94  
95      StateTracker setState(final State newState) throws IllegalStateException
96      {
97          for (;;)
98          {
99              final State oldState = get();
100             oldState.check(newState);
101             if (state.compareAndSet(oldState, newState))
102             {
103                 return this;
104             }
105         }
106     }
107 
108     @Override
109     public String toString()
110     {
111         return get().toString();
112     }
113 }