View Javadoc

1   /* 
2    * Copyright (c) 2007, Fraunhofer-Gesellschaft
3    * All rights reserved.
4    * 
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions are
7    * met:
8    * 
9    * (1) Redistributions of source code must retain the above copyright
10   *     notice, this list of conditions and the disclaimer at the end.
11   *     Redistributions in binary form must reproduce the above copyright
12   *     notice, this list of conditions and the following disclaimer in
13   *     the documentation and/or other materials provided with the
14   *     distribution.
15   * 
16   * (2) Neither the name of Fraunhofer nor the names of its
17   *     contributors may be used to endorse or promote products derived
18   *     from this software without specific prior written permission.
19   * 
20   * DISCLAIMER
21   * 
22   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26   * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33   *  
34   */
35  package org.ogf.graap.wsag.wsrf.bootstrap;
36  
37  import java.beans.Introspector;
38  import java.net.InetAddress;
39  import java.sql.Driver;
40  import java.sql.DriverManager;
41  import java.util.Enumeration;
42  
43  import javax.servlet.ServletContext;
44  import javax.servlet.ServletContextEvent;
45  import javax.servlet.ServletContextListener;
46  
47  import org.apache.axis2.context.ConfigurationContext;
48  import org.apache.log4j.Logger;
49  import org.apache.xml.resolver.tools.CatalogResolver;
50  import org.hsqldb.DatabaseManager;
51  import org.ogf.graap.wsag.server.persistence.EmfRegistry;
52  
53  /**
54   * @author owaeld
55   * 
56   */
57  public class WSAG4JContextListener implements ServletContextListener
58  {
59  
60      /**
61       * 
62       */
63      private static final int DB_WAITING_TIME = 2500;
64  
65      /**
66       * 
67       */
68      private static final int MAX_DB_SHUTDOWN_RETRIES = 25;
69  
70      private static final Logger LOG = Logger.getLogger( WSAG4JContextListener.class );
71  
72      /**
73       * {@inheritDoc}
74       * 
75       * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)
76       */
77      public void contextDestroyed( ServletContextEvent eContext )
78      {
79  
80          BootstrapIsolationLayer isolationLayer =
81              (BootstrapIsolationLayer) eContext.getServletContext().getAttribute( "isolationLayer" );
82          LOG.info( "shutdown WSAG4J service" );
83  
84          try
85          {
86              isolationLayer.shutdown();
87              isolationLayer = null;
88          }
89          catch ( Exception e )
90          {
91              String message = "WSAG4J shutdown process failed. Error: " + e.getMessage();
92              LOG.error( message );
93          }
94  
95          BootstrapRegistry.finalizeBootstrapRegistry();
96  
97          //
98          // in case there is a WSAG4J version without hsqldb, remove this block
99          //
100         //
101         // hard shutdown of the HSQL Timer on undeploy/stop of the webapp
102         //
103         Thread runner = DatabaseManager.getTimer().getThread();
104         DatabaseManager.getTimer().shutdown();
105 
106         //
107         // wait for HSQLDB to finish outstanding work.
108         //
109         // HSQLDB has a default write delay of 60 seconds for scripts.
110         // Therefore we wait a bit more than a minute at max for HSQLDB
111         // shutdown.
112         //
113         int maxWaitingTime = MAX_DB_SHUTDOWN_RETRIES;
114 
115         while ( runner.isAlive() )
116         {
117             if ( maxWaitingTime == 0 )
118             {
119                 break;
120             }
121 
122             maxWaitingTime--;
123 
124             try
125             {
126                 LOG.debug( "wait for HSQLDB to finish outstanding work..." );
127                 synchronized ( this )
128                 {
129                     wait( DB_WAITING_TIME );
130                 }
131             }
132             catch ( InterruptedException e )
133             {
134                 break;
135             }
136         }
137 
138         //
139         // check if HSQLDB terminated normally
140         //
141         if ( runner.isAlive() )
142         {
143             LOG.warn( "HSQLDB failed to terminate normally. Send interupt." );
144             runner.interrupt();
145         }
146         else
147         {
148             LOG.info( "HSQLDB shutdown complete." );
149         }
150         //
151         // end of hsqldb specific block
152         //
153 
154         LOG.debug( "cleanup database drivers..." );
155         Introspector.flushCaches();
156         for ( Enumeration<Driver> e = DriverManager.getDrivers(); e.hasMoreElements(); )
157         {
158             Driver driver = e.nextElement();
159             if ( driver.getClass().getClassLoader() == getClass().getClassLoader() )
160             {
161                 try
162                 {
163                     LOG.debug( "deregister: " + driver.getClass().getName() );
164                     DriverManager.deregisterDriver( driver );
165                 }
166                 catch ( Exception ex )
167                 {
168                     LOG.warn( "failed to deregister driver.", ex );
169                 }
170             }
171         }
172 
173         LOG.info( "shutdown of WSAG4J service completed" );
174     }
175 
176     /**
177      * {@inheritDoc}
178      * 
179      * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)
180      */
181     public void contextInitialized( ServletContextEvent contextEvent )
182     {
183         synchronized ( WSAG4JContextListener.class )
184         {
185 
186             //
187             // use the CatalogResolver as default for XmlBeans
188             // this is required for template validation
189             //
190             System.setProperty( "xmlbean.entityResolver", CatalogResolver.class.getName() );
191 
192             try
193             {
194                 //
195                 // get the real path for bootstraping configuration files, etc.
196                 //
197                 ServletContext context = contextEvent.getServletContext();
198                 String path = context.getRealPath( "/" );
199                 String defaultGatewayURI = getDefaultGatewayURI( context );
200                 String datapath = path + "/WEB-INF/wsag4j-data";
201 
202                 if ( !System.getProperties().containsKey( EmfRegistry.WSAG4J_DATAPATH ) )
203                 {
204                     System.getProperties().setProperty( EmfRegistry.WSAG4J_DATAPATH, datapath );
205                 }
206 
207                 //
208                 // create and initialize the isolation layer
209                 //
210                 BootstrapIsolationLayer isolationLayer =
211                     new BootstrapIsolationLayer( path, defaultGatewayURI );
212                 isolationLayer.initialize();
213 
214                 contextEvent.getServletContext().setAttribute( "isolationLayer", isolationLayer );
215             }
216             catch ( Exception e )
217             {
218                 String message = "WSAG4J initialization process failed. Error: " + e.getMessage();
219                 LOG.error( message );
220             }
221 
222         }
223     }
224 
225     /**
226      * Returns the gateway URI for the web application.
227      * 
228      * @param context
229      *            the servlet context of the web application
230      * 
231      * @return the default gateway URI (application URL)
232      * 
233      * @throws Exception
234      *             failed to resolve the application URL
235      */
236     protected String getDefaultGatewayURI( ServletContext context ) throws Exception
237     {
238         String contextPath = context.getResource( "/" ).getPath();
239         contextPath = contextPath.substring( 0, contextPath.lastIndexOf( "/" ) );
240         contextPath = contextPath.substring( contextPath.lastIndexOf( "/" ) + 1 );
241 
242         try
243         {
244             String host = InetAddress.getLocalHost().getHostAddress();
245             ConfigurationContext axisContext =
246                 (ConfigurationContext) context.getAttribute( Bootstrap.CONFIGURATION_CONTEXT );
247 
248             // Try to resolve the running port via the Axis2 configuration.
249             // We use 8080 as default port.
250             // String port = (String)axisContext.getProperty(ListingAgent.RUNNING_PORT);
251             String port = (String) axisContext.getProperty( "RUNNING_PORT" );
252             port = ( port == null ) ? "8080" : port;
253 
254             String generatedGatewayURL = "http://" + host + ":" + port + "/" + contextPath;
255 
256             return generatedGatewayURL;
257         }
258         catch ( Exception e )
259         {
260             LOG.trace( "Could not generate gateway url. Use default." );
261             String generatedGatewayURL = "http://localhost:8080/" + contextPath;
262             return generatedGatewayURL;
263         }
264     }
265 
266 }