View Javadoc

    1   /*
    2    * $Id: MemoryDatabasePlugIn.java 471754 2006-11-06 14:55:09Z husted $
    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.webapp.example2.memory;
    24
    25
    26  import java.io.BufferedInputStream;
    27  import java.io.BufferedOutputStream;
    28  import java.io.File;
    29  import java.io.FileOutputStream;
    30  import java.io.InputStream;
    31  import java.util.ArrayList;
    32  import javax.servlet.ServletException;
    33  import org.apache.commons.logging.Log;
    34  import org.apache.commons.logging.LogFactory;
    35  import org.apache.struts.action.ActionServlet;
    36  import org.apache.struts.action.PlugIn;
    37  import org.apache.struts.config.ModuleConfig;
    38  import org.apache.struts.util.LabelValueBean;
    39  import org.apache.struts.webapp.example2.Constants;
    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: 471754 $ $Date: 2006-11-06 08:55:09 -0600 (Mon, 06 Nov 2006) $
    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       * Logging output for this plug in instance.
    73       */
    74      private Log log = LogFactory.getLog(this.getClass());
    75
    76
    77      /**
    78       * The {@link ActionServlet} owning this application.
    79       */
    80      private ActionServlet servlet = null;
    81
    82
    83      // ------------------------------------------------------------- Properties
    84
    85
    86      /**
    87       * The web application resource path of our persistent database
    88       * storage file.
    89       */
    90      private String pathname = "/WEB-INF/database.xml";
    91
    92      public String getPathname() {
    93          return (this.pathname);
    94      }
    95
    96      public void setPathname(String pathname) {
    97          this.pathname = pathname;
    98      }
    99
    100
    101     // --------------------------------------------------------- PlugIn Methods
    102
    103
    104     /**
    105      * Gracefully shut down this database, releasing any resources
    106      * that were allocated at initialization.
    107      */
    108     public void destroy() {
    109
    110         log.info("Finalizing memory database plug in");
    111
    112         if (database != null) {
    113             try {
    114                 database.close();
    115             } catch (Exception e) {
    116                 log.error("Closing memory database", e);
    117             }
    118         }
    119
    120     servlet.getServletContext().removeAttribute(Constants.DATABASE_KEY);
    121         database = null;
    122         servlet = null;
    123         database = null;
    124
    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      * @exception 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             if (log.isDebugEnabled()) {
    150                 log.debug(" Loading database from '" + path + "'");
    151             }
    152             database.setPathname(path);
    153             database.open();
    154         } catch (Exception e) {
    155             log.error("Opening memory database", e);
    156             throw new ServletException("Cannot load database from '" +
    157                                        pathname + "'", e);
    158         }
    159
    160         // Make the initialized database available
    161         servlet.getServletContext().setAttribute(Constants.DATABASE_KEY,
    162                                                  database);
    163
    164         // Setup and cache other required data
    165         setupCache(servlet, config);
    166
    167     }
    168
    169
    170     // --------------------------------------------------------- Public Methods
    171
    172
    173     // ------------------------------------------------------ Protected Methods
    174
    175
    176     /**
    177      * <p>Cache commonly required data as servlet context attributes.</p>
    178      *
    179      * @param servlet The <code>ActionServlet</code> instance running
    180      *  this webapp
    181      * @param config The <code>ModuleConfig</code> for this application module
    182      */
    183     protected void setupCache(ActionServlet servlet, ModuleConfig config) {
    184
    185         // Set up list of server types under "serverTypes"
    186         ArrayList serverTypes = new ArrayList();
    187         serverTypes.add(new LabelValueBean("IMAP Protocol", "imap"));
    188         serverTypes.add(new LabelValueBean("POP3 Protocol", "pop3"));
    189         servlet.getServletContext().setAttribute("serverTypes", serverTypes);
    190
    191     }
    192
    193
    194
    195
    196     // -------------------------------------------------------- Private Methods
    197
    198
    199     /**
    200      * Calculate and return an absolute pathname to the XML file to contain
    201      * our persistent storage information.
    202      *
    203      * @exception Exception if an input/output error occurs
    204      */
    205     private String calculatePath() throws Exception {
    206
    207         // Can we access the database via file I/O?
    208         String path = servlet.getServletContext().getRealPath(pathname);
    209         if (path != null) {
    210             return (path);
    211         }
    212
    213         // Does a copy of this file already exist in our temporary directory
    214         File dir = (File)
    215             servlet.getServletContext().getAttribute
    216             ("javax.servlet.context.tempdir");
    217         File file = new File(dir, "struts-example-database.xml");
    218         if (file.exists()) {
    219             return (file.getAbsolutePath());
    220         }
    221
    222         // Copy the static resource to a temporary file and return its path
    223         InputStream is =
    224             servlet.getServletContext().getResourceAsStream(pathname);
    225         BufferedInputStream bis = new BufferedInputStream(is, 1024);
    226         FileOutputStream os =
    227             new FileOutputStream(file);
    228         BufferedOutputStream bos = new BufferedOutputStream(os, 1024);
    229         byte buffer[] = new byte[1024];
    230         while (true) {
    231             int n = bis.read(buffer);
    232             if (n <= 0) {
    233                 break;
    234             }
    235             bos.write(buffer, 0, n);
    236         }
    237         bos.close();
    238         bis.close();
    239         return (file.getAbsolutePath());
    240
    241     }
    242
    243
    244 }