View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 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  
19  package org.eclipse.jetty.util.thread;
20  
21  import java.util.Arrays;
22  import java.util.List;
23  import java.util.concurrent.CopyOnWriteArrayList;
24  
25  import org.eclipse.jetty.util.component.LifeCycle;
26  import org.eclipse.jetty.util.log.Log;
27  import org.eclipse.jetty.util.log.Logger;
28  
29  
30  /* ------------------------------------------------------------ */
31  /**
32   * ShutdownThread is a shutdown hook thread implemented as 
33   * singleton that maintains a list of lifecycle instances
34   * that are registered with it and provides ability to stop
35   * these lifecycles upon shutdown of the Java Virtual Machine 
36   */
37  public class ShutdownThread extends Thread
38  {
39      private static final Logger LOG = Log.getLogger(ShutdownThread.class);
40      private static final ShutdownThread _thread = new ShutdownThread();
41  
42      private boolean _hooked;
43      private final List<LifeCycle> _lifeCycles = new CopyOnWriteArrayList<LifeCycle>();
44  
45      /* ------------------------------------------------------------ */
46      /**
47       * Default constructor for the singleton
48       * 
49       * Registers the instance as shutdown hook with the Java Runtime
50       */
51      private ShutdownThread()
52      {
53      }
54      
55      /* ------------------------------------------------------------ */
56      private synchronized void hook()
57      {
58          try
59          {
60              if (!_hooked)
61                  Runtime.getRuntime().addShutdownHook(this);
62              _hooked=true;
63          }
64          catch(Exception e)
65          {
66              LOG.ignore(e);
67              LOG.info("shutdown already commenced");
68          }
69      }
70      
71      /* ------------------------------------------------------------ */
72      private synchronized void unhook()
73      {
74          try
75          {
76              _hooked=false;
77              Runtime.getRuntime().removeShutdownHook(this);
78          }
79          catch(Exception e)
80          {
81              LOG.ignore(e);
82              LOG.info("shutdown already commenced");
83          }
84      }
85      
86      /* ------------------------------------------------------------ */
87      /**
88       * Returns the instance of the singleton
89       * 
90       * @return the singleton instance of the {@link ShutdownThread}
91       */
92      public static ShutdownThread getInstance()
93      {
94          return _thread;
95      }
96  
97      /* ------------------------------------------------------------ */
98      public static synchronized void register(LifeCycle... lifeCycles)
99      {
100         _thread._lifeCycles.addAll(Arrays.asList(lifeCycles));
101         if (_thread._lifeCycles.size()>0)
102             _thread.hook();
103     }
104 
105     /* ------------------------------------------------------------ */
106     public static synchronized void register(int index, LifeCycle... lifeCycles)
107     {
108         _thread._lifeCycles.addAll(index,Arrays.asList(lifeCycles));
109         if (_thread._lifeCycles.size()>0)
110             _thread.hook();
111     }
112     
113     /* ------------------------------------------------------------ */
114     public static synchronized void deregister(LifeCycle lifeCycle)
115     {
116         _thread._lifeCycles.remove(lifeCycle);
117         if (_thread._lifeCycles.size()==0)
118             _thread.unhook();
119     }
120 
121     /* ------------------------------------------------------------ */
122     @Override
123     public void run()
124     {
125         for (LifeCycle lifeCycle : _thread._lifeCycles)
126         {
127             try
128             {
129                 if (lifeCycle.isStarted())
130                 {
131                     lifeCycle.stop();
132                     LOG.debug("Stopped {}",lifeCycle);
133                 }
134             }
135             catch (Exception ex)
136             {
137                 LOG.debug(ex);
138             }
139         }
140     }
141 }