View Javadoc

1   /*
2    * Copyright 1999-2002,2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  
18  package org.apache.struts.webapp.example2.memory;
19  
20  
21  import java.io.BufferedInputStream;
22  import java.io.BufferedOutputStream;
23  import java.io.File;
24  import java.io.FileOutputStream;
25  import java.io.InputStream;
26  import java.util.ArrayList;
27  import javax.servlet.ServletException;
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  import org.apache.struts.action.ActionServlet;
31  import org.apache.struts.action.PlugIn;
32  import org.apache.struts.config.ModuleConfig;
33  import org.apache.struts.util.LabelValueBean;
34  import org.apache.struts.webapp.example2.Constants;
35  
36  /***
37   * <p><strong>MemoryDatabasePlugIn</strong> initializes and finalizes the
38   * persistent storage of User and Subscription information for the Struts
39   * Demonstration Application, using an in-memory database backed by an
40   * XML file.</p>
41   *
42   * <p><strong>IMPLEMENTATION WARNING</strong> - If this web application is run
43   * from a WAR file, or in another environment where reading and writing of the
44   * web application resource is impossible, the initial contents will be copied
45   * to a file in the web application temporary directory provided by the
46   * container.  This is for demonstration purposes only - you should
47   * <strong>NOT</strong> assume that files written here will survive a restart
48   * of your servlet container.</p>
49   *
50   * @author Craig R. McClanahan
51   * @version $Rev: 421494 $ $Date: 2006-07-12 20:55:17 -0700 (Wed, 12 Jul 2006) $
52   */
53  
54  public final class MemoryDatabasePlugIn implements PlugIn {
55  
56  
57      // ----------------------------------------------------- Instance Variables
58  
59  
60      /***
61       * The {@link MemoryUserDatabase} object we construct and make available.
62       */
63      private MemoryUserDatabase database = null;
64  
65  
66      /***
67       * Logging output for this plug in instance.
68       */
69      private Log log = LogFactory.getLog(this.getClass());
70  
71  
72      /***
73       * The {@link ActionServlet} owning this application.
74       */
75      private ActionServlet servlet = null;
76  
77  
78      // ------------------------------------------------------------- Properties
79  
80  
81      /***
82       * The web application resource path of our persistent database
83       * storage file.
84       */
85      private String pathname = "/WEB-INF/database.xml";
86  
87      public String getPathname() {
88          return (this.pathname);
89      }
90  
91      public void setPathname(String pathname) {
92          this.pathname = pathname;
93      }
94  
95  
96      // --------------------------------------------------------- PlugIn Methods
97  
98  
99      /***
100      * Gracefully shut down this database, releasing any resources
101      * that were allocated at initialization.
102      */
103     public void destroy() {
104 
105         log.info("Finalizing memory database plug in");
106 
107         if (database != null) {
108             try {
109                 database.close();
110             } catch (Exception e) {
111                 log.error("Closing memory database", e);
112             }
113         }
114 
115 	servlet.getServletContext().removeAttribute(Constants.DATABASE_KEY);
116         database = null;
117         servlet = null;
118         database = null;
119 
120     }
121 
122 
123     /***
124      * Initialize and load our initial database from persistent storage.
125      *
126      * @param servlet The ActionServlet for this web application
127      * @param config The ApplicationConfig for our owning module
128      *
129      * @exception ServletException if we cannot configure ourselves correctly
130      */
131     public void init(ActionServlet servlet, ModuleConfig config)
132         throws ServletException {
133 
134         log.info("Initializing memory database plug in from '" +
135                  pathname + "'");
136 
137         // Remember our associated configuration and servlet
138         this.servlet = servlet;
139 
140         // Construct a new database and make it available
141         database = new MemoryUserDatabase();
142         try {
143             String path = calculatePath();
144             if (log.isDebugEnabled()) {
145                 log.debug(" Loading database from '" + path + "'");
146             }
147             database.setPathname(path);
148             database.open();
149         } catch (Exception e) {
150             log.error("Opening memory database", e);
151             throw new ServletException("Cannot load database from '" +
152                                        pathname + "'", e);
153         }
154 
155         // Make the initialized database available
156         servlet.getServletContext().setAttribute(Constants.DATABASE_KEY,
157                                                  database);
158 
159         // Setup and cache other required data
160         setupCache(servlet, config);
161 
162     }
163 
164 
165     // --------------------------------------------------------- Public Methods
166 
167 
168     // ------------------------------------------------------ Protected Methods
169 
170 
171     /***
172      * <p>Cache commonly required data as servlet context attributes.</p>
173      *
174      * @param servlet The <code>ActionServlet</code> instance running
175      *  this webapp
176      * @param config The <code>ModuleConfig</code> for this application module
177      */
178     protected void setupCache(ActionServlet servlet, ModuleConfig config) {
179 
180         // Set up list of server types under "serverTypes"
181         ArrayList serverTypes = new ArrayList();
182         serverTypes.add(new LabelValueBean("IMAP Protocol", "imap"));
183         serverTypes.add(new LabelValueBean("POP3 Protocol", "pop3"));
184         servlet.getServletContext().setAttribute("serverTypes", serverTypes);
185 
186     }
187 
188 
189 
190 
191     // -------------------------------------------------------- Private Methods
192 
193 
194     /***
195      * Calculate and return an absolute pathname to the XML file to contain
196      * our persistent storage information.
197      *
198      * @exception Exception if an input/output error occurs
199      */
200     private String calculatePath() throws Exception {
201 
202         // Can we access the database via file I/O?
203         String path = servlet.getServletContext().getRealPath(pathname);
204         if (path != null) {
205             return (path);
206         }
207 
208         // Does a copy of this file already exist in our temporary directory
209         File dir = (File)
210             servlet.getServletContext().getAttribute
211             ("javax.servlet.context.tempdir");
212         File file = new File(dir, "struts-example-database.xml");
213         if (file.exists()) {
214             return (file.getAbsolutePath());
215         }
216 
217         // Copy the static resource to a temporary file and return its path
218         InputStream is =
219             servlet.getServletContext().getResourceAsStream(pathname);
220         BufferedInputStream bis = new BufferedInputStream(is, 1024);
221         FileOutputStream os =
222             new FileOutputStream(file);
223         BufferedOutputStream bos = new BufferedOutputStream(os, 1024);
224         byte buffer[] = new byte[1024];
225         while (true) {
226             int n = bis.read(buffer);
227             if (n <= 0) {
228                 break;
229             }
230             bos.write(buffer, 0, n);
231         }
232         bos.close();
233         bis.close();
234         return (file.getAbsolutePath());
235 
236     }
237 
238 
239 }