KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > riotfamily > common > web > file > DefaultFileStore


1 /* ***** BEGIN LICENSE BLOCK *****
2  * Version: MPL 1.1
3  * The contents of this file are subject to the Mozilla Public License Version
4  * 1.1 (the "License"); you may not use this file except in compliance with
5  * the License. You may obtain a copy of the License at
6  * http://www.mozilla.org/MPL/
7  *
8  * Software distributed under the License is distributed on an "AS IS" basis,
9  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
10  * for the specific language governing rights and limitations under the
11  * License.
12  *
13  * The Original Code is Riot.
14  *
15  * The Initial Developer of the Original Code is
16  * Neteye GmbH.
17  * Portions created by the Initial Developer are Copyright (C) 2006
18  * the Initial Developer. All Rights Reserved.
19  *
20  * Contributor(s):
21  * Felix Gnass [fgnass at neteye dot de]
22  *
23  * ***** END LICENSE BLOCK ***** */

24 package org.riotfamily.common.web.file;
25
26 import java.io.File JavaDoc;
27 import java.io.IOException JavaDoc;
28
29 import javax.servlet.ServletContext JavaDoc;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.springframework.beans.factory.InitializingBean;
34 import org.springframework.util.Assert;
35 import org.springframework.util.FileCopyUtils;
36 import org.springframework.util.StringUtils;
37 import org.springframework.web.context.ServletContextAware;
38
39 /**
40  * Default FileStore implementation.
41  *
42  * @author Felix Gnass [fgnass at neteye dot de]
43  */

44 public class DefaultFileStore implements FileStore, ServletContextAware,
45         InitializingBean {
46
47     private Log log = LogFactory.getLog(DefaultFileStore.class);
48     
49     private String JavaDoc uriPrefix;
50     
51     private String JavaDoc storagePath;
52     
53     private File JavaDoc baseDir;
54
55     private File JavaDoc storageDir;
56     
57     private int storageDirIndex;
58     
59     private int maxFilesPerDir = 500;
60     
61     private ServletContext JavaDoc servletContext;
62         
63     
64     public void setServletContext(ServletContext JavaDoc servletContext) {
65         this.servletContext = servletContext;
66     }
67
68     /**
69      * Sets the path to the directory where the files are stored. Relative
70      * paths are resolved against the webapp's root directory by calling
71      * {@link ServletContext#getRealPath(String)}.
72      *
73      * @param storagePath Either an absolute or relative path denoting a directory
74      */

75     public void setStoragePath(String JavaDoc storagePath) {
76         this.storagePath = storagePath;
77     }
78
79     /**
80      * Sets a prefix that is added to all URIs returned by the
81      * {@link #store(File, String) store()} method.
82      */

83     public void setUriPrefix(String JavaDoc uriPrefix) {
84         Assert.notNull(uriPrefix, "The uriPrefix must not be null");
85         if (uriPrefix.endsWith("/")) {
86             uriPrefix = uriPrefix.substring(0, uriPrefix.length() - 1);
87         }
88         this.uriPrefix = uriPrefix;
89     }
90     
91     /**
92      * Sets the maximum number of files that may be stored in a directory
93      * before a new storageDir is created. Defaults to 500.
94      */

95     public void setMaxFilesPerDir(int maxFilesPerDir) {
96         this.maxFilesPerDir = maxFilesPerDir;
97     }
98     
99     /**
100      * Creates the baseDir after all properties have been set.
101      */

102     public void afterPropertiesSet() throws IOException JavaDoc {
103         Assert.notNull(uriPrefix, "The uriPrefix must not be null");
104         if (storagePath == null) {
105             storagePath = servletContext.getRealPath(uriPrefix);
106         }
107         else if (!storagePath.startsWith(File.separator)
108                 && storagePath.indexOf(":") != 1) {
109             
110             storagePath = servletContext.getRealPath(storagePath);
111         }
112         
113         baseDir = createDir(new File JavaDoc(storagePath));
114         log.info("Files will be stored in "
115                 + baseDir.getCanonicalPath());
116         
117         getStorageDir();
118     }
119     
120     /**
121      * Creates the given directory and all parent directories (unless they
122      * already exist). If the directory can't be created or is not writable
123      * an error message is logged.
124      */

125     protected File JavaDoc createDir(File JavaDoc dir) {
126         if (!(dir.exists() || dir.mkdirs())) {
127             log.error("Error creating directory: " + dir.getPath());
128         }
129         if (!dir.canWrite()) {
130             log.error("Directory " + dir.getPath()
131                     + " is not writable for user "
132                     + System.getProperty("user.name"));
133         }
134         return dir;
135     }
136     
137     /**
138      * Returns whether the next storage directory should be used.
139      */

140     private boolean storageExceeded() {
141         return storageDir == null || storageDir.list().length >= maxFilesPerDir;
142     }
143
144     /**
145      * Returns the directory where the files should be stored. The default
146      * implementation limits the number of files per directory and creates a
147      * new directory when the number of files exceeds the
148      * {@link #setMaxFilesPerDir(int) maxFilesPerDir} value.
149      */

150     protected File JavaDoc getStorageDir() {
151         if (storageExceeded()) {
152             synchronized (this) {
153                 while (storageExceeded()) {
154                     String JavaDoc name = String.valueOf(storageDirIndex++);
155                     storageDir = createDir(new File JavaDoc(baseDir, name));
156                 }
157             }
158         }
159         return storageDir;
160     }
161     
162     /**
163      * Returns an empty new directory with an unique name within the current
164      * storageDir.
165      */

166     protected File JavaDoc getUniqueDir() {
167         File JavaDoc parent = getStorageDir();
168         for (int i = 0; i < maxFilesPerDir; i++) {
169             File JavaDoc dir = new File JavaDoc(parent, String.valueOf(
170                     System.currentTimeMillis()) + i);
171             
172             if (!dir.exists()) {
173                 dir.mkdir();
174                 return dir;
175             }
176         }
177         //This should never happen ...
178
throw new RuntimeException JavaDoc("Failed to create a unique directory name.");
179     }
180     
181     /**
182      * Moves the given file into the store and returns an URI that can be
183      * used to request the file via HTTP.
184      */

185     public String JavaDoc store(File JavaDoc file, String JavaDoc fileName) throws IOException JavaDoc {
186         if (fileName == null) {
187             fileName = file.getName();
188         }
189         File JavaDoc dest = new File JavaDoc(getUniqueDir(), fileName);
190         if (!file.renameTo(dest)) {
191             FileCopyUtils.copy(file, dest);
192             file.delete();
193         }
194         String JavaDoc path = dest.getPath().substring(baseDir.getPath().length());
195         path = StringUtils.replace(path, File.separator, "/");
196         return uriPrefix + path;
197     }
198     
199     /**
200      * Retrieves a file from the store that was previously added via the
201      * {@link #store(File, String) store()} method.
202      */

203     public File JavaDoc retrieve(String JavaDoc uri) {
204         log.debug("Retrieving file for URI: " + uri);
205         if (!uri.startsWith(uriPrefix)) {
206             return null;
207         }
208         uri = stripQueryString(uri.substring(uriPrefix.length() + 1));
209         uri = StringUtils.replace(uri, "/", File.separator);
210         File JavaDoc file = new File JavaDoc(baseDir, uri);
211         log.debug("File: " + file);
212         return file;
213     }
214     
215     /**
216      * Strips the query string from the given URI. Older FileStore
217      * implementations had the option to append a timestamp parameter to the
218      * URI therefore this method is used to ensure backwards compatibility.
219      */

220     private String JavaDoc stripQueryString(String JavaDoc uri) {
221         int i = uri.indexOf('?');
222         if (i != -1) {
223             uri = uri.substring(0, i);
224         }
225         return uri;
226     }
227
228     /**
229      * Deletes the file denoted by the given URI from the store.
230      */

231     public void delete(String JavaDoc uri) {
232         File JavaDoc file = retrieve(uri);
233         file.delete();
234         File JavaDoc dir = file.getParentFile();
235         if (dir.isDirectory() && dir.list().length == 0 &&
236             !dir.equals(baseDir)) {
237             
238             dir.delete();
239         }
240     }
241     
242 }
243
Popular Tags