View Javadoc

1   package org.apache.tomcat.maven.common.run;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.plugin.logging.Log;
23  
24  import java.lang.reflect.InvocationTargetException;
25  import java.lang.reflect.Method;
26  import java.util.HashSet;
27  import java.util.Iterator;
28  import java.util.Set;
29  
30  /**
31   * Registry which collects all embedded Tomcat Servers so that they will be shutdown
32   * through a shutdown hook when the JVM terminates or you can ask the registry to
33   * shutdown all started servers.
34   *
35   * @author Mark Michaelis
36   * @since 1.1
37   */
38  public final class EmbeddedRegistry
39  {
40      private static EmbeddedRegistry instance;
41  
42      private Set<Object> containers = new HashSet<Object>( 1 );
43  
44      /**
45       * Don't instantiate - use the instance through {@link #getInstance()}.
46       */
47      private EmbeddedRegistry()
48      {
49          // no op
50      }
51  
52      /**
53       * Retrieve the lazily initialized instance of the registry.
54       *
55       * @return singleton instance of the registry
56       */
57      public static EmbeddedRegistry getInstance()
58      {
59          if ( instance == null )
60          {
61              instance = new EmbeddedRegistry();
62              Runtime.getRuntime().addShutdownHook( new Thread()
63              {
64                  @Override
65                  public void run()
66                  {
67                      try
68                      {
69                          getInstance().shutdownAll( null );
70                      }
71                      catch ( Exception e )
72                      {
73                          // ignore, the exception should already have been reported
74                      }
75                  }
76              } );
77          }
78          return instance;
79      }
80  
81      /**
82       * Adds the given container to the registry which automatically registers it for the shutdown
83       * hook.
84       *
85       * @param container the container to register
86       * @return true if it got added; false if not
87       */
88      public synchronized boolean register( final Object container )
89      {
90          return containers.add( container );
91      }
92  
93      /**
94       * Shuts down all registered embedded tomcats. All tomcats which successfully shut down will be
95       * removed from the registry.
96       *
97       * @param log the log to write possible shutdown exceptions to
98       * @throws Exception the first exception which occurred will be rethrown
99       */
100     public synchronized void shutdownAll( final Log log )
101         throws Exception
102     {
103         Exception firstException = null;
104         for ( Iterator<Object> iterator = containers.iterator(); iterator.hasNext(); )
105         {
106             Object embedded = iterator.next();
107             try
108             {
109                 Method method = embedded.getClass().getMethod( "stop", null );
110                 method.invoke( embedded, null );
111                 iterator.remove();
112             }
113             catch ( NoSuchMethodException e )
114             {
115                 if ( firstException == null )
116                 {
117                     firstException = e;
118                     error( log, e, "no stop method in class " + embedded.getClass().getName() );
119                 }
120                 else
121                 {
122                     error( log, e, "Error while shutting down embedded Tomcat." );
123                 }
124             }
125             catch ( IllegalAccessException e )
126             {
127                 if ( firstException == null )
128                 {
129                     firstException = e;
130                     error( log, e, "IllegalAccessException for stop method in class " + embedded.getClass().getName() );
131                 }
132                 else
133                 {
134                     error( log, e, "Error while shutting down embedded Tomcat." );
135                 }
136             }
137             catch ( InvocationTargetException e )
138             {
139 
140                 if ( firstException == null )
141                 {
142                     firstException = e;
143                     error( log, e, "IllegalAccessException for stop method in class " + embedded.getClass().getName() );
144                 }
145                 else
146                 {
147                     error( log, e, "Error while shutting down embedded Tomcat." );
148                 }
149             }
150         }
151         if ( firstException != null )
152         {
153             throw firstException;
154         }
155     }
156 
157     /**
158      * Reports the exception. If a log is given (typically when called from within a Mojo) the
159      * message will be printed to the log. Otherwise it will be printed to StdErr.
160      *
161      * @param log     the log to write the message to; null to write to stderr
162      * @param e       exception which shall be reported
163      * @param message message which shall be reported
164      */
165     private void error( final Log log, final Exception e, final String message )
166     {
167         if ( log == null )
168         {
169             System.err.println( "ERROR: " + message );
170             e.printStackTrace();
171         }
172         else
173         {
174             log.error( message, e );
175         }
176     }
177 
178 }