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