001: /*
002: * $Id: MemoryDatabasePlugIn.java 471754 2006-11-06 14:55:09Z husted $
003: *
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021:
022: package org.apache.struts.webapp.example2.memory;
023:
024: import java.io.BufferedInputStream;
025: import java.io.BufferedOutputStream;
026: import java.io.File;
027: import java.io.FileOutputStream;
028: import java.io.InputStream;
029: import java.util.ArrayList;
030: import javax.servlet.ServletException;
031: import org.apache.commons.logging.Log;
032: import org.apache.commons.logging.LogFactory;
033: import org.apache.struts.action.ActionServlet;
034: import org.apache.struts.action.PlugIn;
035: import org.apache.struts.config.ModuleConfig;
036: import org.apache.struts.util.LabelValueBean;
037: import org.apache.struts.webapp.example2.Constants;
038:
039: /**
040: * <p><strong>MemoryDatabasePlugIn</strong> initializes and finalizes the
041: * persistent storage of User and Subscription information for the Struts
042: * Demonstration Application, using an in-memory database backed by an
043: * XML file.</p>
044: *
045: * <p><strong>IMPLEMENTATION WARNING</strong> - If this web application is run
046: * from a WAR file, or in another environment where reading and writing of the
047: * web application resource is impossible, the initial contents will be copied
048: * to a file in the web application temporary directory provided by the
049: * container. This is for demonstration purposes only - you should
050: * <strong>NOT</strong> assume that files written here will survive a restart
051: * of your servlet container.</p>
052: *
053: * @author Craig R. McClanahan
054: * @version $Rev: 471754 $ $Date: 2006-11-06 08:55:09 -0600 (Mon, 06 Nov 2006) $
055: */
056:
057: public final class MemoryDatabasePlugIn implements PlugIn {
058:
059: // ----------------------------------------------------- Instance Variables
060:
061: /**
062: * The {@link MemoryUserDatabase} object we construct and make available.
063: */
064: private MemoryUserDatabase database = null;
065:
066: /**
067: * Logging output for this plug in instance.
068: */
069: private Log log = LogFactory.getLog(this .getClass());
070:
071: /**
072: * The {@link ActionServlet} owning this application.
073: */
074: private ActionServlet servlet = null;
075:
076: // ------------------------------------------------------------- Properties
077:
078: /**
079: * The web application resource path of our persistent database
080: * storage file.
081: */
082: private String pathname = "/WEB-INF/database.xml";
083:
084: public String getPathname() {
085: return (this .pathname);
086: }
087:
088: public void setPathname(String pathname) {
089: this .pathname = pathname;
090: }
091:
092: // --------------------------------------------------------- PlugIn Methods
093:
094: /**
095: * Gracefully shut down this database, releasing any resources
096: * that were allocated at initialization.
097: */
098: public void destroy() {
099:
100: log.info("Finalizing memory database plug in");
101:
102: if (database != null) {
103: try {
104: database.close();
105: } catch (Exception e) {
106: log.error("Closing memory database", e);
107: }
108: }
109:
110: servlet.getServletContext().removeAttribute(
111: Constants.DATABASE_KEY);
112: database = null;
113: servlet = null;
114: database = null;
115:
116: }
117:
118: /**
119: * Initialize and load our initial database from persistent storage.
120: *
121: * @param servlet The ActionServlet for this web application
122: * @param config The ApplicationConfig for our owning module
123: *
124: * @exception ServletException if we cannot configure ourselves correctly
125: */
126: public void init(ActionServlet servlet, ModuleConfig config)
127: throws ServletException {
128:
129: log.info("Initializing memory database plug in from '"
130: + pathname + "'");
131:
132: // Remember our associated configuration and servlet
133: this .servlet = servlet;
134:
135: // Construct a new database and make it available
136: database = new MemoryUserDatabase();
137: try {
138: String path = calculatePath();
139: if (log.isDebugEnabled()) {
140: log.debug(" Loading database from '" + path + "'");
141: }
142: database.setPathname(path);
143: database.open();
144: } catch (Exception e) {
145: log.error("Opening memory database", e);
146: throw new ServletException("Cannot load database from '"
147: + pathname + "'", e);
148: }
149:
150: // Make the initialized database available
151: servlet.getServletContext().setAttribute(
152: Constants.DATABASE_KEY, database);
153:
154: // Setup and cache other required data
155: setupCache(servlet, config);
156:
157: }
158:
159: // --------------------------------------------------------- Public Methods
160:
161: // ------------------------------------------------------ Protected Methods
162:
163: /**
164: * <p>Cache commonly required data as servlet context attributes.</p>
165: *
166: * @param servlet The <code>ActionServlet</code> instance running
167: * this webapp
168: * @param config The <code>ModuleConfig</code> for this application module
169: */
170: protected void setupCache(ActionServlet servlet, ModuleConfig config) {
171:
172: // Set up list of server types under "serverTypes"
173: ArrayList serverTypes = new ArrayList();
174: serverTypes.add(new LabelValueBean("IMAP Protocol", "imap"));
175: serverTypes.add(new LabelValueBean("POP3 Protocol", "pop3"));
176: servlet.getServletContext().setAttribute("serverTypes",
177: serverTypes);
178:
179: }
180:
181: // -------------------------------------------------------- Private Methods
182:
183: /**
184: * Calculate and return an absolute pathname to the XML file to contain
185: * our persistent storage information.
186: *
187: * @exception Exception if an input/output error occurs
188: */
189: private String calculatePath() throws Exception {
190:
191: // Can we access the database via file I/O?
192: String path = servlet.getServletContext().getRealPath(pathname);
193: if (path != null) {
194: return (path);
195: }
196:
197: // Does a copy of this file already exist in our temporary directory
198: File dir = (File) servlet.getServletContext().getAttribute(
199: "javax.servlet.context.tempdir");
200: File file = new File(dir, "struts-example-database.xml");
201: if (file.exists()) {
202: return (file.getAbsolutePath());
203: }
204:
205: // Copy the static resource to a temporary file and return its path
206: InputStream is = servlet.getServletContext()
207: .getResourceAsStream(pathname);
208: BufferedInputStream bis = new BufferedInputStream(is, 1024);
209: FileOutputStream os = new FileOutputStream(file);
210: BufferedOutputStream bos = new BufferedOutputStream(os, 1024);
211: byte buffer[] = new byte[1024];
212: while (true) {
213: int n = bis.read(buffer);
214: if (n <= 0) {
215: break;
216: }
217: bos.write(buffer, 0, n);
218: }
219: bos.close();
220: bis.close();
221: return (file.getAbsolutePath());
222:
223: }
224:
225: }
|