Home » apache-tomcat-6.0.26-src » org.apache » catalina » session » [javadoc | source]

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    * 
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    * 
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   
   18   
   19   package org.apache.catalina.session;
   20   
   21   
   22   import java.io.BufferedInputStream;
   23   import java.io.BufferedOutputStream;
   24   import java.io.File;
   25   import java.io.FileInputStream;
   26   import java.io.FileNotFoundException;
   27   import java.io.FileOutputStream;
   28   import java.io.IOException;
   29   import java.io.ObjectInputStream;
   30   import java.io.ObjectOutputStream;
   31   import java.util.ArrayList;
   32   
   33   import javax.servlet.ServletContext;
   34   
   35   import org.apache.catalina.Container;
   36   import org.apache.catalina.Context;
   37   import org.apache.catalina.Globals;
   38   import org.apache.catalina.Loader;
   39   import org.apache.catalina.Session;
   40   import org.apache.catalina.Store;
   41   import org.apache.catalina.util.CustomObjectInputStream;
   42   
   43   
   44   /**
   45    * Concrete implementation of the <b>Store</b> interface that utilizes
   46    * a file per saved Session in a configured directory.  Sessions that are
   47    * saved are still subject to being expired based on inactivity.
   48    *
   49    * @author Craig R. McClanahan
   50    * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (Tue, 24 Oct 2006) $
   51    */
   52   
   53   public final class FileStore
   54       extends StoreBase implements Store {
   55   
   56   
   57       // ----------------------------------------------------- Constants
   58   
   59   
   60       /**
   61        * The extension to use for serialized session filenames.
   62        */
   63       private static final String FILE_EXT = ".session";
   64   
   65   
   66       // ----------------------------------------------------- Instance Variables
   67   
   68   
   69       /**
   70        * The pathname of the directory in which Sessions are stored.
   71        * This may be an absolute pathname, or a relative path that is
   72        * resolved against the temporary work directory for this application.
   73        */
   74       private String directory = ".";
   75   
   76   
   77       /**
   78        * A File representing the directory in which Sessions are stored.
   79        */
   80       private File directoryFile = null;
   81   
   82   
   83       /**
   84        * The descriptive information about this implementation.
   85        */
   86       private static final String info = "FileStore/1.0";
   87   
   88       /**
   89        * Name to register for this Store, used for logging.
   90        */
   91       private static final String storeName = "fileStore";
   92   
   93       /**
   94        * Name to register for the background thread.
   95        */
   96       private static final String threadName = "FileStore";
   97   
   98   
   99       // ------------------------------------------------------------- Properties
  100   
  101   
  102       /**
  103        * Return the directory path for this Store.
  104        */
  105       public String getDirectory() {
  106   
  107           return (directory);
  108   
  109       }
  110   
  111   
  112       /**
  113        * Set the directory path for this Store.
  114        *
  115        * @param path The new directory path
  116        */
  117       public void setDirectory(String path) {
  118   
  119           String oldDirectory = this.directory;
  120           this.directory = path;
  121           this.directoryFile = null;
  122           support.firePropertyChange("directory", oldDirectory,
  123                                      this.directory);
  124   
  125       }
  126   
  127   
  128       /**
  129        * Return descriptive information about this Store implementation and
  130        * the corresponding version number, in the format
  131        * <code>&lt;description&gt;/&lt;version&gt;</code>.
  132        */
  133       public String getInfo() {
  134   
  135           return (info);
  136   
  137       }
  138   
  139       /**
  140        * Return the thread name for this Store.
  141        */
  142       public String getThreadName() {
  143           return(threadName);
  144       }
  145   
  146       /**
  147        * Return the name for this Store, used for logging.
  148        */
  149       public String getStoreName() {
  150           return(storeName);
  151       }
  152   
  153   
  154       /**
  155        * Return the number of Sessions present in this Store.
  156        *
  157        * @exception IOException if an input/output error occurs
  158        */
  159       public int getSize() throws IOException {
  160   
  161           // Acquire the list of files in our storage directory
  162           File file = directory();
  163           if (file == null) {
  164               return (0);
  165           }
  166           String files[] = file.list();
  167   
  168           // Figure out which files are sessions
  169           int keycount = 0;
  170           for (int i = 0; i < files.length; i++) {
  171               if (files[i].endsWith(FILE_EXT)) {
  172                   keycount++;
  173               }
  174           }
  175           return (keycount);
  176   
  177       }
  178   
  179   
  180       // --------------------------------------------------------- Public Methods
  181   
  182   
  183       /**
  184        * Remove all of the Sessions in this Store.
  185        *
  186        * @exception IOException if an input/output error occurs
  187        */
  188       public void clear()
  189           throws IOException {
  190   
  191           String[] keys = keys();
  192           for (int i = 0; i < keys.length; i++) {
  193               remove(keys[i]);
  194           }
  195   
  196       }
  197   
  198   
  199       /**
  200        * Return an array containing the session identifiers of all Sessions
  201        * currently saved in this Store.  If there are no such Sessions, a
  202        * zero-length array is returned.
  203        *
  204        * @exception IOException if an input/output error occurred
  205        */
  206       public String[] keys() throws IOException {
  207   
  208           // Acquire the list of files in our storage directory
  209           File file = directory();
  210           if (file == null) {
  211               return (new String[0]);
  212           }
  213   
  214           String files[] = file.list();
  215           
  216           // Bugzilla 32130
  217           if((files == null) || (files.length < 1)) {
  218               return (new String[0]);
  219           }
  220   
  221           // Build and return the list of session identifiers
  222           ArrayList list = new ArrayList();
  223           int n = FILE_EXT.length();
  224           for (int i = 0; i < files.length; i++) {
  225               if (files[i].endsWith(FILE_EXT)) {
  226                   list.add(files[i].substring(0, files[i].length() - n));
  227               }
  228           }
  229           return ((String[]) list.toArray(new String[list.size()]));
  230   
  231       }
  232   
  233   
  234       /**
  235        * Load and return the Session associated with the specified session
  236        * identifier from this Store, without removing it.  If there is no
  237        * such stored Session, return <code>null</code>.
  238        *
  239        * @param id Session identifier of the session to load
  240        *
  241        * @exception ClassNotFoundException if a deserialization error occurs
  242        * @exception IOException if an input/output error occurs
  243        */
  244       public Session load(String id)
  245           throws ClassNotFoundException, IOException {
  246   
  247           // Open an input stream to the specified pathname, if any
  248           File file = file(id);
  249           if (file == null) {
  250               return (null);
  251           }
  252   
  253           if (! file.exists()) {
  254               return (null);
  255           }
  256           if (manager.getContainer().getLogger().isDebugEnabled()) {
  257               manager.getContainer().getLogger().debug(sm.getString(getStoreName()+".loading",
  258                                id, file.getAbsolutePath()));
  259           }
  260   
  261           FileInputStream fis = null;
  262           ObjectInputStream ois = null;
  263           Loader loader = null;
  264           ClassLoader classLoader = null;
  265           try {
  266               fis = new FileInputStream(file.getAbsolutePath());
  267               BufferedInputStream bis = new BufferedInputStream(fis);
  268               Container container = manager.getContainer();
  269               if (container != null)
  270                   loader = container.getLoader();
  271               if (loader != null)
  272                   classLoader = loader.getClassLoader();
  273               if (classLoader != null)
  274                   ois = new CustomObjectInputStream(bis, classLoader);
  275               else
  276                   ois = new ObjectInputStream(bis);
  277           } catch (FileNotFoundException e) {
  278               if (manager.getContainer().getLogger().isDebugEnabled())
  279                   manager.getContainer().getLogger().debug("No persisted data file found");
  280               return (null);
  281           } catch (IOException e) {
  282               if (ois != null) {
  283                   try {
  284                       ois.close();
  285                   } catch (IOException f) {
  286                       ;
  287                   }
  288                   ois = null;
  289               }
  290               throw e;
  291           }
  292   
  293           try {
  294               StandardSession session =
  295                   (StandardSession) manager.createEmptySession();
  296               session.readObjectData(ois);
  297               session.setManager(manager);
  298               return (session);
  299           } finally {
  300               // Close the input stream
  301               if (ois != null) {
  302                   try {
  303                       ois.close();
  304                   } catch (IOException f) {
  305                       ;
  306                   }
  307               }
  308           }
  309       }
  310   
  311   
  312       /**
  313        * Remove the Session with the specified session identifier from
  314        * this Store, if present.  If no such Session is present, this method
  315        * takes no action.
  316        *
  317        * @param id Session identifier of the Session to be removed
  318        *
  319        * @exception IOException if an input/output error occurs
  320        */
  321       public void remove(String id) throws IOException {
  322   
  323           File file = file(id);
  324           if (file == null) {
  325               return;
  326           }
  327           if (manager.getContainer().getLogger().isDebugEnabled()) {
  328               manager.getContainer().getLogger().debug(sm.getString(getStoreName()+".removing",
  329                                id, file.getAbsolutePath()));
  330           }
  331           file.delete();
  332   
  333       }
  334   
  335   
  336       /**
  337        * Save the specified Session into this Store.  Any previously saved
  338        * information for the associated session identifier is replaced.
  339        *
  340        * @param session Session to be saved
  341        *
  342        * @exception IOException if an input/output error occurs
  343        */
  344       public void save(Session session) throws IOException {
  345   
  346           // Open an output stream to the specified pathname, if any
  347           File file = file(session.getIdInternal());
  348           if (file == null) {
  349               return;
  350           }
  351           if (manager.getContainer().getLogger().isDebugEnabled()) {
  352               manager.getContainer().getLogger().debug(sm.getString(getStoreName()+".saving",
  353                                session.getIdInternal(), file.getAbsolutePath()));
  354           }
  355           FileOutputStream fos = null;
  356           ObjectOutputStream oos = null;
  357           try {
  358               fos = new FileOutputStream(file.getAbsolutePath());
  359               oos = new ObjectOutputStream(new BufferedOutputStream(fos));
  360           } catch (IOException e) {
  361               if (oos != null) {
  362                   try {
  363                       oos.close();
  364                   } catch (IOException f) {
  365                       ;
  366                   }
  367               }
  368               throw e;
  369           }
  370   
  371           try {
  372               ((StandardSession)session).writeObjectData(oos);
  373           } finally {
  374               oos.close();
  375           }
  376   
  377       }
  378   
  379   
  380       // -------------------------------------------------------- Private Methods
  381   
  382   
  383       /**
  384        * Return a File object representing the pathname to our
  385        * session persistence directory, if any.  The directory will be
  386        * created if it does not already exist.
  387        */
  388       private File directory() {
  389   
  390           if (this.directory == null) {
  391               return (null);
  392           }
  393           if (this.directoryFile != null) {
  394               // NOTE:  Race condition is harmless, so do not synchronize
  395               return (this.directoryFile);
  396           }
  397           File file = new File(this.directory);
  398           if (!file.isAbsolute()) {
  399               Container container = manager.getContainer();
  400               if (container instanceof Context) {
  401                   ServletContext servletContext =
  402                       ((Context) container).getServletContext();
  403                   File work = (File)
  404                       servletContext.getAttribute(Globals.WORK_DIR_ATTR);
  405                   file = new File(work, this.directory);
  406               } else {
  407                   throw new IllegalArgumentException
  408                       ("Parent Container is not a Context");
  409               }
  410           }
  411           if (!file.exists() || !file.isDirectory()) {
  412               file.delete();
  413               file.mkdirs();
  414           }
  415           this.directoryFile = file;
  416           return (file);
  417   
  418       }
  419   
  420   
  421       /**
  422        * Return a File object representing the pathname to our
  423        * session persistence file, if any.
  424        *
  425        * @param id The ID of the Session to be retrieved. This is
  426        *    used in the file naming.
  427        */
  428       private File file(String id) {
  429   
  430           if (this.directory == null) {
  431               return (null);
  432           }
  433           String filename = id + FILE_EXT;
  434           File file = new File(directory(), filename);
  435           return (file);
  436   
  437       }
  438   
  439   
  440   }

Home » apache-tomcat-6.0.26-src » org.apache » catalina » session » [javadoc | source]