KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > blojsom > plugin > admin > FileUploadPlugin


1 /**
2  * Copyright (c) 2003-2006, David A. Czarnecki
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * Redistributions of source code must retain the above copyright notice, this list of conditions and the
9  * following disclaimer.
10  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
11  * following disclaimer in the documentation and/or other materials provided with the distribution.
12  * Neither the name of "David A. Czarnecki" and "blojsom" nor the names of its contributors may be used to
13  * endorse or promote products derived from this software without specific prior written permission.
14  * Products derived from this software may not be called "blojsom", nor may "blojsom" appear in their name,
15  * without prior written permission of David A. Czarnecki.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
18  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
19  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
21  * EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */

31 package org.blojsom.plugin.admin;
32
33 import org.apache.commons.fileupload.FileItem;
34 import org.apache.commons.fileupload.FileUploadException;
35 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
36 import org.apache.commons.fileupload.servlet.ServletFileUpload;
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39 import org.blojsom.blog.Blog;
40 import org.blojsom.blog.Entry;
41 import org.blojsom.plugin.PluginException;
42 import org.blojsom.util.BlojsomConstants;
43 import org.blojsom.util.BlojsomUtils;
44
45 import javax.servlet.http.HttpServletRequest JavaDoc;
46 import javax.servlet.http.HttpServletResponse JavaDoc;
47 import java.io.File JavaDoc;
48 import java.util.*;
49
50 /**
51  * FileUploadPlugin
52  *
53  * @author David Czarnecki
54  * @version $Id: FileUploadPlugin.java,v 1.2 2006/04/20 15:40:44 czarneckid Exp $
55  * @since blojsom 3.0
56  */

57 public class FileUploadPlugin extends BaseAdminPlugin {
58
59     private Log _logger = LogFactory.getLog(FileUploadPlugin.class);
60
61     // Localization constants
62
private static final String JavaDoc FAILED_PERMISSION_KEY = "file.upload.failed.permission.text";
63     private static final String JavaDoc FAILED_RESOURCE_KEY = "file.upload.failed.resource.text";
64     private static final String JavaDoc UNKNOWN_ERROR_KEY = "file.upload.unknown.error.text";
65     private static final String JavaDoc SUCCESSFUL_UPLOAD_KEY = "successful.upload.text";
66     private static final String JavaDoc INVALID_EXTENSION_KEY = "invalid.upload.extension.text";
67     private static final String JavaDoc INVALID_TYPE_KEY = "invalid.upload.type.text";
68     private static final String JavaDoc DELETED_FILES_KEY = "deleted.files.text";
69     private static final String JavaDoc UPLOAD_LIMIT_KEY = "upload.limit.exceeded.text";
70
71     private static final String JavaDoc RESOURCES_DIRECTORY_IP = "resources-directory";
72     private static final String JavaDoc TEMPORARY_DIRECTORY_IP = "temporary-directory";
73     private static final String JavaDoc DEFAULT_TEMPORARY_DIRECTORY = "/tmp";
74     private static final String JavaDoc MAXIMUM_UPLOAD_SIZE_IP = "maximum-upload-size";
75     private static final long DEFAULT_MAXIMUM_UPLOAD_SIZE = 100000;
76     private static final String JavaDoc MAXIMUM_MEMORY_SIZE_IP = "maximum-memory-size";
77     private static final int DEFAULT_MAXIMUM_MEMORY_SIZE = 50000;
78     private static final String JavaDoc ACCEPTED_FILE_TYPES_IP = "accepted-file-types";
79     private static final String JavaDoc[] DEFAULT_ACCEPTED_FILE_TYPES = {"image/jpeg", "image/gif", "image/png"};
80     private static final String JavaDoc INVALID_FILE_EXTENSIONS_IP = "invalid-file-extensions";
81     private static final String JavaDoc[] DEFAULT_INVALID_FILE_EXTENSIONS = {".jsp", ".jspf", ".jspi", ".jspx", ".php", ".cgi"};
82     private static final String JavaDoc UPLOAD_QUOTA_ENABLED_IP = "upload-quota-enabled";
83     private static final String JavaDoc UPLOAD_QUOTA_LIMIT_IP = "upload-quota-limit";
84     private static final long DEFAULT_UPLOAD_QUOTA_LIMIT = 10485760;
85
86     // Pages
87
private static final String JavaDoc FILE_UPLOAD_PAGE = "/org/blojsom/plugin/admin/templates/admin-file-upload";
88
89     // Constants
90
private static final String JavaDoc PLUGIN_ADMIN_FILE_UPLOAD_FILES = "PLUGIN_ADMIN_FILE_UPLOAD_FILES";
91     private static final String JavaDoc ACCEPTED_FILE_TYPES = "ACCEPTED_FILE_TYPES";
92     private static final String JavaDoc INVALID_FILE_EXTENSIONS = "INVALID_FILE_EXTENSIONS";
93
94     // Actions
95
private static final String JavaDoc UPLOAD_FILE_ACTION = "upload-file";
96     private static final String JavaDoc DELETE_UPLOAD_FILES = "delete-upload-files";
97
98     // Form items
99
private static final String JavaDoc FILE_TO_DELETE = "file-to-delete";
100
101     // Permissions
102
private static final String JavaDoc FILE_UPLOAD_PERMISSION = "file_upload_permission";
103
104     private String JavaDoc _temporaryDirectory;
105     private long _maximumUploadSize;
106     private int _maximumMemorySize;
107     private Map _acceptedFileTypes;
108     private String JavaDoc _resourcesDirectory;
109     private String JavaDoc[] _invalidFileExtensions;
110     private boolean _uploadQuotaEnabled;
111     private long _uploadQuotaLimit;
112     private Properties _fileUploadProperties;
113
114     /**
115      * Default constructor.
116      */

117     public FileUploadPlugin() {
118     }
119
120     /**
121      * Set the file upload properties
122      *
123      * @param fileUploadProperties File upload properties
124      */

125     public void setFileUploadProperties(Properties fileUploadProperties) {
126         _fileUploadProperties = fileUploadProperties;
127     }
128
129     /**
130      * Initialize this plugin. This method only called when the plugin is instantiated.
131      *
132      * @throws org.blojsom.plugin.PluginException
133      * If there is an error initializing the plugin
134      */

135     public void init() throws PluginException {
136         super.init();
137
138         _temporaryDirectory = _fileUploadProperties.getProperty(TEMPORARY_DIRECTORY_IP);
139         if (BlojsomUtils.checkNullOrBlank(_temporaryDirectory)) {
140             _temporaryDirectory = DEFAULT_TEMPORARY_DIRECTORY;
141         }
142         _logger.debug("Using temporary directory: " + _temporaryDirectory);
143
144         try {
145             _maximumUploadSize = Long.parseLong(_fileUploadProperties.getProperty(MAXIMUM_UPLOAD_SIZE_IP));
146         } catch (NumberFormatException JavaDoc e) {
147             _maximumUploadSize = DEFAULT_MAXIMUM_UPLOAD_SIZE;
148         }
149         _logger.debug("Using maximum upload size: " + _maximumUploadSize);
150
151         try {
152             _maximumMemorySize = Integer.parseInt(_fileUploadProperties.getProperty(MAXIMUM_MEMORY_SIZE_IP));
153         } catch (NumberFormatException JavaDoc e) {
154             _maximumMemorySize = DEFAULT_MAXIMUM_MEMORY_SIZE;
155         }
156         _logger.debug("Using maximum memory size: " + _maximumMemorySize);
157
158         String JavaDoc acceptedFileTypes = _fileUploadProperties.getProperty(ACCEPTED_FILE_TYPES_IP);
159         String JavaDoc[] parsedListOfTypes;
160         if (BlojsomUtils.checkNullOrBlank(acceptedFileTypes)) {
161             parsedListOfTypes = DEFAULT_ACCEPTED_FILE_TYPES;
162         } else {
163             parsedListOfTypes = BlojsomUtils.parseCommaList(acceptedFileTypes);
164         }
165         _acceptedFileTypes = new HashMap(parsedListOfTypes.length);
166         for (int i = 0; i < parsedListOfTypes.length; i++) {
167             String JavaDoc type = parsedListOfTypes[i];
168             _acceptedFileTypes.put(type, type);
169         }
170         _logger.debug("Using accepted file types: " + BlojsomUtils.arrayOfStringsToString(parsedListOfTypes));
171
172         _resourcesDirectory = _fileUploadProperties.getProperty(RESOURCES_DIRECTORY_IP);
173         if (BlojsomUtils.checkNullOrBlank(_resourcesDirectory)) {
174             _resourcesDirectory = BlojsomConstants.DEFAULT_RESOURCES_DIRECTORY;
175         }
176
177         _resourcesDirectory = BlojsomUtils.checkStartingAndEndingSlash(_resourcesDirectory);
178         _logger.debug("Using resources directory: " + _resourcesDirectory);
179
180         String JavaDoc invalidFileExtensionsProperty = _fileUploadProperties.getProperty(INVALID_FILE_EXTENSIONS_IP);
181         if (BlojsomUtils.checkNullOrBlank(invalidFileExtensionsProperty)) {
182             _invalidFileExtensions = DEFAULT_INVALID_FILE_EXTENSIONS;
183         } else {
184             _invalidFileExtensions = BlojsomUtils.parseCommaList(invalidFileExtensionsProperty);
185         }
186         _logger.debug("Using invalid file extensions: " + invalidFileExtensionsProperty);
187
188         _uploadQuotaEnabled = Boolean.valueOf(_fileUploadProperties.getProperty(UPLOAD_QUOTA_ENABLED_IP)).booleanValue();
189         if (_uploadQuotaEnabled) {
190             String JavaDoc uploadQuotaLimit = _fileUploadProperties.getProperty(UPLOAD_QUOTA_LIMIT_IP);
191             if (BlojsomUtils.checkNullOrBlank(uploadQuotaLimit)) {
192                 _uploadQuotaLimit = DEFAULT_UPLOAD_QUOTA_LIMIT;
193             } else {
194                 try {
195                     _uploadQuotaLimit = Long.parseLong(uploadQuotaLimit);
196                     if (_uploadQuotaLimit <= 0) {
197                         _uploadQuotaLimit = DEFAULT_UPLOAD_QUOTA_LIMIT;
198                     }
199                 } catch (NumberFormatException JavaDoc e) {
200                     _uploadQuotaLimit = DEFAULT_UPLOAD_QUOTA_LIMIT;
201                 }
202             }
203
204             _logger.debug("Upload limit enabled. Quota is : " + _uploadQuotaLimit + " bytes");
205         }
206     }
207
208     /**
209      * Return the size of a directory by getting the size of all its files and all of its directories files
210      *
211      * @param directory Directory whose size should be retrieved
212      * @return Size of files in a directory or -1 if the original argument was not a directory
213      */

214     protected long getDirectorySize(File JavaDoc directory) {
215         if (!directory.isDirectory()) {
216             return -1;
217         }
218
219         long totalSize = 0;
220
221         File JavaDoc[] files = directory.listFiles();
222         for (int i = 0; i < files.length; i++) {
223             File JavaDoc file = files[i];
224
225             if (file.isDirectory()) {
226                 totalSize += getDirectorySize(file);
227             } else {
228                 totalSize += file.length();
229             }
230         }
231
232         return totalSize;
233     }
234
235     /**
236      * Process the blog entries
237      *
238      * @param httpServletRequest Request
239      * @param httpServletResponse Response
240      * @param blog {@link Blog} instance
241      * @param context Context
242      * @param entries Blog entries retrieved for the particular request
243      * @return Modified set of blog entries
244      * @throws PluginException If there is an error processing the blog entries
245      */

246     public Entry[] process(HttpServletRequest JavaDoc httpServletRequest, HttpServletResponse JavaDoc httpServletResponse, Blog blog, Map context, Entry[] entries) throws PluginException {
247         if (!authenticateUser(httpServletRequest, httpServletResponse, context, blog)) {
248             httpServletRequest.setAttribute(BlojsomConstants.PAGE_PARAM, ADMIN_LOGIN_PAGE);
249
250             return entries;
251         }
252
253         String JavaDoc username = getUsernameFromSession(httpServletRequest, blog);
254         if (!checkPermission(blog, null, username, FILE_UPLOAD_PERMISSION)) {
255             httpServletRequest.setAttribute(BlojsomConstants.PAGE_PARAM, ADMIN_ADMINISTRATION_PAGE);
256             addOperationResultMessage(context, getAdminResource(FAILED_PERMISSION_KEY, FAILED_PERMISSION_KEY, blog.getBlogAdministrationLocale()));
257
258             return entries;
259         }
260
261         File JavaDoc resourceDirectory = new File JavaDoc(_servletConfig.getServletContext().getRealPath("/") + _resourcesDirectory + blog.getBlogId() + "/");
262
263         String JavaDoc action = BlojsomUtils.getRequestValue(ACTION_PARAM, httpServletRequest);
264         if (BlojsomUtils.checkNullOrBlank(action)) {
265             _logger.debug("User did not request edit action");
266
267             httpServletRequest.setAttribute(BlojsomConstants.PAGE_PARAM, ADMIN_ADMINISTRATION_PAGE);
268         } else if (PAGE_ACTION.equals(action)) {
269             _logger.debug("User requested file upload page");
270
271             httpServletRequest.setAttribute(BlojsomConstants.PAGE_PARAM, FILE_UPLOAD_PAGE);
272         } else if (UPLOAD_FILE_ACTION.equals(action)) {
273             _logger.debug("User requested file upload action");
274
275             // Create a factory for disk-based file items
276
DiskFileItemFactory factory = new DiskFileItemFactory();
277
278             // Set factory constraints
279
factory.setSizeThreshold(_maximumMemorySize);
280             factory.setRepository(new File JavaDoc(_temporaryDirectory));
281
282             ServletFileUpload upload = new ServletFileUpload(factory);
283
284             // Set overall request size constraint
285
upload.setSizeMax(_maximumUploadSize);
286
287             try {
288                 List items = upload.parseRequest(httpServletRequest);
289                 Iterator itemsIterator = items.iterator();
290                 while (itemsIterator.hasNext()) {
291                     FileItem item = (FileItem) itemsIterator.next();
292
293                     // Check for the file upload form item
294
if (!item.isFormField()) {
295                         String JavaDoc itemNameWithoutPath = BlojsomUtils.getFilenameFromPath(item.getName());
296
297                         _logger.debug("Found file item: " + itemNameWithoutPath + " of type: " + item.getContentType());
298
299                         // Is it one of the accepted file types?
300
String JavaDoc fileType = item.getContentType();
301                         boolean isAcceptedFileType = _acceptedFileTypes.containsKey(fileType);
302
303                         String JavaDoc extension = BlojsomUtils.getFileExtension(itemNameWithoutPath);
304                         boolean isAcceptedFileExtension = true;
305                         for (int i = 0; i < _invalidFileExtensions.length; i++) {
306                             String JavaDoc invalidFileExtension = _invalidFileExtensions[i];
307                             if (itemNameWithoutPath.indexOf(invalidFileExtension) != -1) {
308                                 isAcceptedFileExtension = false;
309                                 break;
310                             }
311                         }
312
313                         if (_uploadQuotaEnabled) {
314                             boolean overQuota = true;
315                             long currentLimit = getDirectorySize(resourceDirectory);
316                             if ((currentLimit != -1) && ((currentLimit + item.getSize() < _uploadQuotaLimit))) {
317                                 overQuota = false;
318                             }
319
320                             if (overQuota) {
321                                 _logger.error("Upload quota exceeded trying to upload file: " + itemNameWithoutPath);
322                                 addOperationResultMessage(context, formatAdminResource(UPLOAD_LIMIT_KEY, UPLOAD_LIMIT_KEY, blog.getBlogAdministrationLocale(), new Object JavaDoc[]{itemNameWithoutPath, new Long JavaDoc(_uploadQuotaLimit)}));
323
324                                 break;
325                             }
326                         }
327
328                         // If so, upload the file to the resources directory
329
if (isAcceptedFileType && isAcceptedFileExtension) {
330                             if (!resourceDirectory.exists()) {
331                                 if (!resourceDirectory.mkdirs()) {
332                                     _logger.error("Unable to create resource directory for user: " + resourceDirectory.toString());
333                                     addOperationResultMessage(context, getAdminResource(FAILED_RESOURCE_KEY, FAILED_RESOURCE_KEY, blog.getBlogAdministrationLocale()));
334                                     return entries;
335                                 }
336                             }
337
338                             File JavaDoc resourceFile = new File JavaDoc(resourceDirectory, itemNameWithoutPath);
339                             try {
340                                 item.write(resourceFile);
341                             } catch (Exception JavaDoc e) {
342                                 _logger.error(e);
343                                 addOperationResultMessage(context, formatAdminResource(UNKNOWN_ERROR_KEY, UNKNOWN_ERROR_KEY, blog.getBlogAdministrationLocale(), new Object JavaDoc[]{e.getMessage()}));
344                             }
345
346                             String JavaDoc resourceURL = blog.getBlogBaseURL() + _resourcesDirectory + blog.getBlogId() + "/" + itemNameWithoutPath;
347
348                             _logger.debug("Successfully uploaded resource file: " + resourceFile.toString());
349                             addOperationResultMessage(context, formatAdminResource(SUCCESSFUL_UPLOAD_KEY, SUCCESSFUL_UPLOAD_KEY, blog.getBlogAdministrationLocale(), new Object JavaDoc[]{itemNameWithoutPath, resourceURL, itemNameWithoutPath}));
350                         } else {
351                             if (!isAcceptedFileExtension) {
352                                 _logger.error("Upload file does not have an accepted extension: " + extension);
353                                 addOperationResultMessage(context, formatAdminResource(INVALID_EXTENSION_KEY, INVALID_EXTENSION_KEY, blog.getBlogAdministrationLocale(), new Object JavaDoc[]{extension}));
354                             } else {
355                                 _logger.error("Upload file is not an accepted type: " + itemNameWithoutPath + " of type: " + item.getContentType());
356                                 addOperationResultMessage(context, formatAdminResource(INVALID_TYPE_KEY, INVALID_TYPE_KEY, blog.getBlogAdministrationLocale(), new Object JavaDoc[]{item.getContentType()}));
357                             }
358                         }
359                     }
360                 }
361             } catch (FileUploadException e) {
362                 _logger.error(e);
363                 addOperationResultMessage(context, formatAdminResource(UNKNOWN_ERROR_KEY, UNKNOWN_ERROR_KEY, blog.getBlogAdministrationLocale(), new Object JavaDoc[]{e.getMessage()}));
364             }
365
366             httpServletRequest.setAttribute(BlojsomConstants.PAGE_PARAM, FILE_UPLOAD_PAGE);
367         } else if (DELETE_UPLOAD_FILES.equals(action)) {
368             String JavaDoc[] filesToDelete = httpServletRequest.getParameterValues(FILE_TO_DELETE);
369             int actualFilesDeleted = 0;
370             if (filesToDelete != null && filesToDelete.length > 0) {
371                 File JavaDoc deletedFile;
372                 for (int i = 0; i < filesToDelete.length; i++) {
373                     String JavaDoc fileToDelete = filesToDelete[i];
374                     deletedFile = new File JavaDoc(resourceDirectory, fileToDelete);
375                     if (!deletedFile.delete()) {
376                         _logger.debug("Unable to delete resource file: " + deletedFile.toString());
377                     } else {
378                         actualFilesDeleted += 1;
379                     }
380                 }
381
382                 addOperationResultMessage(context, formatAdminResource(DELETED_FILES_KEY, DELETED_FILES_KEY, blog.getBlogAdministrationLocale(), new Object JavaDoc[]{new Integer JavaDoc(actualFilesDeleted)}));
383             }
384
385             httpServletRequest.setAttribute(BlojsomConstants.PAGE_PARAM, FILE_UPLOAD_PAGE);
386         }
387
388         // Create a list of files in the user's resource directory
389
Map resourceFilesMap = null;
390         if (resourceDirectory.exists()) {
391             File JavaDoc[] resourceFiles = resourceDirectory.listFiles();
392
393             if (resourceFiles != null) {
394                 resourceFilesMap = new HashMap(resourceFiles.length);
395                 for (int i = 0; i < resourceFiles.length; i++) {
396                     File JavaDoc resourceFile = resourceFiles[i];
397                     resourceFilesMap.put(resourceFile.getName(), resourceFile.getName());
398                 }
399             }
400         } else {
401             resourceFilesMap = new HashMap();
402         }
403
404         resourceFilesMap = new TreeMap(resourceFilesMap);
405         context.put(PLUGIN_ADMIN_FILE_UPLOAD_FILES, resourceFilesMap);
406         context.put(ACCEPTED_FILE_TYPES, new TreeMap(_acceptedFileTypes));
407         context.put(INVALID_FILE_EXTENSIONS, new TreeMap(BlojsomUtils.listToMap(BlojsomUtils.arrayToList(_invalidFileExtensions))));
408         
409         return entries;
410     }
411 }
412
Popular Tags