View Javadoc

    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  package org.apache.commons.vfs.impl;
    18
    19  import org.apache.commons.logging.Log;
    20  import org.apache.commons.logging.LogFactory;
    21  import org.apache.commons.vfs.FileObject;
    22  import org.apache.commons.vfs.FileSelector;
    23  import org.apache.commons.vfs.FileSystemException;
    24  import org.apache.commons.vfs.Selectors;
    25  import org.apache.commons.vfs.VfsLog;
    26  import org.apache.commons.vfs.provider.AbstractVfsComponent;
    27  import org.apache.commons.vfs.provider.FileReplicator;
    28  import org.apache.commons.vfs.provider.TemporaryFileStore;
    29  import org.apache.commons.vfs.provider.UriParser;
    30  import org.apache.commons.vfs.util.Messages;
    31
    32  import java.io.File;
    33  import java.util.ArrayList;
    34  import java.util.Random;
    35
    36  /***
    37   * A simple file replicator and temporary file store.
    38   *
    39   * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
    40   * @version $Revision: 480428 $ $Date: 2006-11-29 07:15:24 +0100 (Mi, 29 Nov 2006) $
    41   */
    42  public class DefaultFileReplicator
    43      extends AbstractVfsComponent
    44      implements FileReplicator, TemporaryFileStore
    45  {
    46      private final static Log log = LogFactory.getLog(DefaultFileReplicator.class);
    47
    48      private final ArrayList copies = new ArrayList();
    49      private File tempDir;
    50      private long filecount;
    51      private boolean tempDirMessageLogged;
    52
    53      private char[] TMP_RESERVED_CHARS = new char[]
    54          {
    55              '?', '/', '//', ' ', '&', '"', '\'', '*', '#', ';', ':', '<', '>', '|'
    56          };
    57
    58      /***
    59       * constructor to set the location of the temporary directory
    60       *
    61       * @param tempDir
    62       */
    63      public DefaultFileReplicator(final File tempDir)
    64      {
    65          this.tempDir = tempDir;
    66      }
    67
    68      public DefaultFileReplicator()
    69      {
    70      }
    71
    72      /***
    73       * Initialises this component.
    74       */
    75      public void init() throws FileSystemException
    76      {
    77          if (tempDir == null)
    78          {
    79              String baseTmpDir = System.getProperty("java.io.tmpdir");
    80
    81              tempDir = new File(baseTmpDir, "vfs_cache").getAbsoluteFile();
    82          }
    83
    84          filecount = new Random().nextInt() & 0xffff;
    85
    86          if (!tempDirMessageLogged)
    87          {
    88              final String message = Messages.getString("vfs.impl/temp-dir.info", tempDir);
    89              VfsLog.info(getLogger(), log, message);
    90
    91              tempDirMessageLogged = true;
    92          }
    93      }
    94
    95      /***
    96       * Closes the replicator, deleting all temporary files.
    97       */
    98      public void close()
    99      {
    100         // Delete the temporary files
    101         synchronized (copies)
    102         {
    103             while (copies.size() > 0)
    104             {
    105                 final File file = (File) removeFile();
    106                 deleteFile(file);
    107             }
    108         }
    109
    110         // Clean up the temp directory, if it is empty
    111         if (tempDir != null && tempDir.exists() && tempDir.list().length == 0)
    112         {
    113             tempDir.delete();
    114             tempDir = null;
    115         }
    116     }
    117
    118     /***
    119      * physically deletes the file from the filesystem
    120      */
    121     protected void deleteFile(File file)
    122     {
    123         try
    124         {
    125             final FileObject fileObject = getContext().toFileObject(file);
    126             fileObject.delete(Selectors.SELECT_ALL);
    127         }
    128         catch (final FileSystemException e)
    129         {
    130             final String message = Messages.getString("vfs.impl/delete-temp.warn", file.getName());
    131             VfsLog.warn(getLogger(), log, message, e);
    132         }
    133     }
    134
    135     /***
    136      * removes a file from the copies list. Will be used for cleanup. <br/>
    137      * Notice: The system awaits that the returning object can be cast to a java.io.File
    138      */
    139     protected Object removeFile()
    140     {
    141         synchronized (copies)
    142         {
    143             return copies.remove(0);
    144         }
    145     }
    146
    147     /***
    148      * removes a instance from the list of copies
    149      */
    150     protected void removeFile(Object file)
    151     {
    152         synchronized (copies)
    153         {
    154             copies.remove(file);
    155         }
    156     }
    157
    158     /***
    159      * Allocates a new temporary file.
    160      */
    161     public File allocateFile(final String baseName) throws FileSystemException
    162     {
    163         // Create a unique-ish file name
    164         final String basename = createFilename(baseName);
    165         synchronized (this)
    166         {
    167             filecount++;
    168         }
    169
    170         final File file = createAndAddFile(tempDir, basename);
    171
    172         return file;
    173     }
    174
    175     protected File createAndAddFile(final File parent, final String basename) throws FileSystemException
    176     {
    177         final File file = createFile(tempDir, basename);
    178
    179         // Keep track to delete later
    180         addFile(file);
    181
    182         return file;
    183     }
    184
    185     protected void addFile(Object file)
    186     {
    187         synchronized (copies)
    188         {
    189             copies.add(file);
    190         }
    191     }
    192
    193     protected long getFilecount()
    194     {
    195         return filecount;
    196     }
    197
    198     /***
    199      * create the temporary file name
    200      */
    201     protected String createFilename(final String baseName)
    202     {
    203         // BUG29007
    204         // return baseName + "_" + getFilecount() + ".tmp";
    205
    206         // imario@apache.org: BUG34976 get rid of maybe reserved and dangerous characters
    207         // e.g. to allow replication of http://hostname.org/fileservlet?file=abc.txt
    208         String safeBasename = UriParser.encode(baseName, TMP_RESERVED_CHARS).replace('%', '_');
    209         return "tmp_" + getFilecount() + "_" + safeBasename;
    210     }
    211
    212     /***
    213      * create the temporary file
    214      */
    215     protected File createFile(final File parent, final String name) throws FileSystemException
    216     {
    217         return new File(parent, UriParser.decode(name));
    218     }
    219
    220     /***
    221      * Creates a local copy of the file, and all its descendents.
    222      */
    223     public File replicateFile(final FileObject srcFile,
    224                               final FileSelector selector)
    225         throws FileSystemException
    226     {
    227         final String basename = srcFile.getName().getBaseName();
    228         final File file = allocateFile(basename);
    229
    230         // Copy from the source file
    231         final FileObject destFile = getContext().toFileObject(file);
    232         destFile.copyFrom(srcFile, selector);
    233
    234         return file;
    235     }
    236 }