View Javadoc
1   /*
2    * $Id$
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  
23  package org.apache.struts.apps.scriptingmailreader.plugin;
24  
25  
26  import java.io.BufferedInputStream;
27  import java.io.BufferedOutputStream;
28  import java.io.File;
29  import java.io.FileOutputStream;
30  
31  import jakarta.servlet.ServletException;
32  
33  import org.apache.struts.action.ActionServlet;
34  import org.apache.struts.action.PlugIn;
35  import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
36  import org.apache.struts.apps.scriptingmailreader.Constants;
37  import org.apache.struts.config.ModuleConfig;
38  import org.slf4j.Logger;
39  import org.slf4j.LoggerFactory;
40  
41  /**
42   * <p><strong>MemoryDatabasePlugIn</strong> initializes and finalizes the
43   * persistent storage of User and Subscription information for the Struts
44   * Demonstration Application, using an in-memory database backed by an
45   * XML file.</p>
46   *
47   * <p><strong>IMPLEMENTATION WARNING</strong> - If this web application is run
48   * from a WAR file, or in another environment where reading and writing of the
49   * web application resource is impossible, the initial contents will be copied
50   * to a file in the web application temporary directory provided by the
51   * container.  This is for demonstration purposes only - you should
52   * <strong>NOT</strong> assume that files written here will survive a restart
53   * of your servlet container.</p>
54   *
55   * @author Craig R. McClanahan
56   * @version $Rev$ $Date$
57   */
58  
59  public final class MemoryDatabasePlugIn implements PlugIn {
60  
61  
62      // ----------------------------------------------------- Instance Variables
63  
64  
65      /**
66       * The {@link MemoryUserDatabase} object we construct and make available.
67       */
68      private MemoryUserDatabase database = null;
69  
70  
71      /**
72       * The {@code Log} instance for this class.
73       */
74      private final static Logger LOG =
75          LoggerFactory.getLogger(MemoryDatabasePlugIn.class);
76  
77  
78      /**
79       * The {@link ActionServlet} owning this application.
80       */
81      private ActionServlet servlet = null;
82  
83  
84      // ------------------------------------------------------------- Properties
85  
86  
87      /**
88       * The web application resource path of our persistent database
89       * storage file.
90       */
91      private String pathname = "/WEB-INF/database.xml";
92  
93      public String getPathname() {
94          return (this.pathname);
95      }
96  
97      public void setPathname(String pathname) {
98          this.pathname = pathname;
99      }
100 
101 
102     // --------------------------------------------------------- PlugIn Methods
103 
104 
105     /**
106      * Gracefully shut down this database, releasing any resources
107      * that were allocated at initialization.
108      */
109     public void destroy() {
110 
111         LOG.info("Finalizing memory database plug in");
112 
113         if (database != null) {
114             try {
115                 database.close();
116             } catch (Exception e) {
117                 LOG.error("Closing memory database", e);
118             }
119         }
120 
121         servlet.getServletContext().removeAttribute(Constants.DATABASE_KEY);
122         database = null;
123         servlet = null;
124         database = null;
125     }
126 
127 
128     /**
129      * Initialize and load our initial database from persistent storage.
130      *
131      * @param servlet The ActionServlet for this web application
132      * @param config  The ApplicationConfig for our owning module
133      *
134      * @throws ServletException if we cannot configure ourselves correctly
135      */
136     public void init(ActionServlet servlet, ModuleConfig config)
137             throws ServletException {
138 
139         LOG.info("Initializing memory database plug in from '{}'",
140             pathname);
141 
142         // Remember our associated configuration and servlet
143         this.servlet = servlet;
144 
145         // Construct a new database and make it available
146         database = new MemoryUserDatabase();
147         try {
148             String path = calculatePath();
149             LOG.debug(" Loading database from '{}'", path);
150             database.setPathname(path);
151             database.open();
152         } catch (Exception e) {
153             LOG.error("Opening memory database", e);
154             throw new ServletException("Cannot load database from '" +
155                     pathname + "'", e);
156         }
157 
158         // Make the initialized database available
159         servlet.getServletContext().setAttribute(Constants.DATABASE_KEY,
160                 database);
161 
162     }
163 
164 
165     // --------------------------------------------------------- Public Methods
166 
167 
168 
169 
170     // -------------------------------------------------------- Private Methods
171 
172 
173     /**
174      * Calculate and return an absolute pathname to the XML file to contain
175      * our persistent storage information.
176      *
177      * @throws Exception if an input/output error occurs
178      */
179     private String calculatePath() throws Exception {
180 
181         // Can we access the database via file I/O?
182         String path = servlet.getServletContext().getRealPath(pathname);
183         if (path != null) {
184             return (path);
185         }
186 
187         // Does a copy of this file already exist in our temporary directory
188         File dir = (File)
189                 servlet.getServletContext().getAttribute
190                         ("jakarta.servlet.context.tempdir");
191         File file = new File(dir, "struts-example-database.xml");
192         if (file.exists()) {
193             return (file.getAbsolutePath());
194         }
195 
196         // Copy the static resource to a temporary file and return its path
197         try (BufferedInputStream bis = new BufferedInputStream(
198                 servlet.getServletContext().getResourceAsStream(pathname), 1024);
199                 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file), 1024)) {
200 
201             byte buffer[] = new byte[1024];
202             while (true) {
203                 int n = bis.read(buffer);
204                 if (n <= 0) {
205                     break;
206                 }
207                 bos.write(buffer, 0, n);
208             }
209         }
210 
211         return (file.getAbsolutePath());
212 
213     }
214 }