/* | |
* Copyright 1999-2002,2004 The Apache Software Foundation. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
* | |
* $Id: ApplicationListener.java 372087 2006-01-25 03:38:42Z craigmcc $ | |
*/ | |
import org.apache.commons.logging.Log; | |
import org.apache.commons.logging.LogFactory; | |
import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase; | |
import javax.servlet.ServletContext; | |
import javax.servlet.ServletContextEvent; | |
import javax.servlet.ServletContextListener; | |
import java.io.*; | |
/** | |
* <p><code>ServletContextListener</code> that initializes and finalizes the | |
* persistent storage of User and Subscription information for the Struts | |
* Demonstration Application, using an in-memory database backed by an XML | |
* file.</p> | |
* <p/> | |
* <p><strong>IMPLEMENTATION WARNING</strong> - If this web application is run | |
* from a WAR file, or in another environment where reading and writing of the | |
* web application resource is impossible, the initial contents will be copied | |
* to a file in the web application temporary directory provided by the | |
* container. This is for demonstration purposes only - you should | |
* <strong>NOT</strong> assume that files written here will survive a restart | |
* of your servlet container.</p> | |
* <p/> | |
* <p>This class was borrowed from the Shale Mailreader. Changes were:</p> | |
* <p/> | |
* <ul> | |
* <p/> | |
* <li>Path to database.xml (under classes here). </li> | |
* <p/> | |
* <li>Class to store protocol list (an array here). </li> | |
* <p/> | |
* </ul> | |
* <p/> | |
* DEVELOPMENT NOTE - Another approach would be to instantiate the database via Spring. | |
* </p> | |
*/ | |
public final class DatabaseListener implements ServletContextListener { | |
// ------------------------------------------------------ Manifest Constants | |
/** | |
* <p>Appication scope attribute key under which the in-memory version of | |
* our database is stored.</p> | |
*/ | |
public static final String DATABASE_KEY = "database"; | |
/** | |
* <p>Application scope attribute key under which the valid selection | |
* items for the protocol property is stored.</p> | |
*/ | |
public static final String PROTOCOLS_KEY = "protocols"; | |
// ------------------------------------------------------ Instance Variables | |
/** | |
* <p>The <code>ServletContext</code> for this web application.</p> | |
*/ | |
private ServletContext context = null; | |
/** | |
* The {@link MemoryUserDatabase} object we construct and make available. | |
*/ | |
private MemoryUserDatabase database = null; | |
/** | |
* <p>Logging output for this plug in instance.</p> | |
*/ | |
private Log log = LogFactory.getLog(this.getClass()); | |
// ------------------------------------------------------------- Properties | |
/** | |
* <p>The web application resource path of our persistent database storage | |
* file.</p> | |
*/ | |
private String pathname = "/WEB-INF/classes/database.xml"; | |
/** | |
* <p>Return the application resource path to the database.</p> | |
* | |
* @return application resource path path to the database | |
*/ | |
public String getPathname() { | |
return (this.pathname); | |
} | |
/** | |
* <p>Set the application resource path to the database.</p> | |
* | |
* @param pathname to the database | |
*/ | |
public void setPathname(String pathname) { | |
this.pathname = pathname; | |
} | |
// ------------------------------------------ ServletContextListener Methods | |
/** | |
* <p>Gracefully shut down this database, releasing any resources that | |
* were allocated at initialization.</p> | |
* | |
* @param event ServletContextEvent to process | |
*/ | |
public void contextDestroyed(ServletContextEvent event) { | |
log.info("Finalizing memory database plug in"); | |
if (database != null) { | |
try { | |
database.close(); | |
} catch (Exception e) { | |
log.error("Closing memory database", e); | |
} | |
} | |
context.removeAttribute(DATABASE_KEY); | |
context.removeAttribute(PROTOCOLS_KEY); | |
database = null; | |
context = null; | |
} | |
/** | |
* <p>Initialize and load our initial database from persistent | |
* storage.</p> | |
* | |
* @param event The context initialization event | |
*/ | |
public void contextInitialized(ServletContextEvent event) { | |
log.info("Initializing memory database plug in from '" + | |
pathname + "'"); | |
// Remember our associated ServletContext | |
this.context = event.getServletContext(); | |
// Construct a new database and make it available | |
database = new MemoryUserDatabase(); | |
try { | |
String path = calculatePath(); | |
if (log.isDebugEnabled()) { | |
log.debug(" Loading database from '" + path + "'"); | |
} | |
database.setPathname(path); | |
database.open(); | |
} catch (Exception e) { | |
log.error("Opening memory database", e); | |
throw new IllegalStateException("Cannot load database from '" + | |
pathname + "': " + e); | |
} | |
context.setAttribute(DATABASE_KEY, database); | |
} | |
// -------------------------------------------------------- Private Methods | |
/** | |
* <p>Calculate and return an absolute pathname to the XML file to contain | |
* our persistent storage information.</p> | |
* | |
* @return Absolute path to XML file. | |
* @throws Exception if an input/output error occurs | |
*/ | |
private String calculatePath() throws Exception { | |
// Can we access the database via file I/O? | |
String path = context.getRealPath(pathname); | |
if (path != null) { | |
return (path); | |
} | |
// Does a copy of this file already exist in our temporary directory | |
File dir = (File) | |
context.getAttribute("javax.servlet.context.tempdir"); | |
File file = new File(dir, "struts-example-database.xml"); | |
if (file.exists()) { | |
return (file.getAbsolutePath()); | |
} | |
// Copy the static resource to a temporary file and return its path | |
InputStream is = | |
context.getResourceAsStream(pathname); | |
BufferedInputStream bis = new BufferedInputStream(is, 1024); | |
FileOutputStream os = | |
new FileOutputStream(file); | |
BufferedOutputStream bos = new BufferedOutputStream(os, 1024); | |
byte buffer[] = new byte[1024]; | |
while (true) { | |
int n = bis.read(buffer); | |
if (n <= 0) { | |
break; | |
} | |
bos.write(buffer, 0, n); | |
} | |
bos.close(); | |
bis.close(); | |
return (file.getAbsolutePath()); | |
} | |
} |