001 /*
002 * This file is part of the Echo Point Project. This project is a
003 * collection of Components that have extended the Echo Web Application
004 * Framework Version 3.
005 *
006 * Version: MPL 1.1
007 *
008 * The contents of this file are subject to the Mozilla Public License Version
009 * 1.1 (the "License"); you may not use this file except in compliance with
010 * the License. You may obtain a copy of the License at
011 * http://www.mozilla.org/MPL/
012 *
013 * Software distributed under the License is distributed on an "AS IS" basis,
014 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
015 * for the specific language governing rights and limitations under the
016 * License.
017 */
018 package echopoint.tucana.event;
019
020 import org.apache.commons.io.IOUtils;
021
022 import java.io.BufferedInputStream;
023 import java.io.BufferedOutputStream;
024 import java.io.File;
025 import java.io.FileInputStream;
026 import java.io.FileOutputStream;
027
028 /**
029 * A default implementation of an {@link UploadCallback} that saves the
030 * uploaded file(s) to a specified directory.
031 *
032 * <p><b>Note:</b> Development of this component was sponsored by <a
033 * href='http://tcnbroadcasting.com/index.jsp' target='_top'>TCN
034 * Broadcasting</a>. We are grateful for their support and sponsorship.</p>
035 *
036 * @author Rakesh 2008-11-9
037 * @version $Id: DefaultUploadCallback.java 106 2009-02-03 16:00:33Z sptrakesh $
038 */
039 public class DefaultUploadCallback extends UploadCallbackAdapter
040 {
041 private static final long serialVersionUID = 1l;
042
043 /** The file separator character to use. */
044 protected static final String FILE_SEPARATOR =
045 System.getProperty( "file.separator" );
046
047 /** The system default temporary directory. */
048 protected static final String TEMP_DIR =
049 System.getProperty( "java.io.tmpdir" );
050
051 /** The directory to which uploaded files are to be saved. */
052 private File directory;
053
054 /** Default constructor to allow sub-classing. */
055 protected DefaultUploadCallback() {}
056
057 /**
058 * Create a new callback handler that saves files to the specified directory.
059 *
060 * @param directory The directory to which files are to be saved.
061 * @throws IllegalArgumentException If the file specified is not a directory.
062 */
063 public DefaultUploadCallback( final File directory ) throws IllegalArgumentException
064 {
065 setDirectory( directory );
066 }
067
068 /**
069 * Over-ridden to save the contents of the uploaded file to {@link #directory}.
070 * Client-code should ideally wrap this method in a try-catch clause to
071 * handle file copying errors and update the UI as appropriate.
072 *
073 * {@inheritDoc}
074 * @throws RuntimeException If errors are encountered while copying the
075 * uploaded file to the specified directory.
076 */
077 @Override
078 public void uploadSucceeded( final UploadFinishEvent event )
079 {
080 final File temp = getTempFile();
081 final File file = getFileName( event.getFileName() );
082
083 try
084 {
085 event.getFileItem().write( temp );
086
087 if ( ! temp.renameTo( file ) )
088 {
089 BufferedOutputStream bos =
090 new BufferedOutputStream( new FileOutputStream( file ) );
091 BufferedInputStream bis =
092 new BufferedInputStream( new FileInputStream( temp ) );
093 IOUtils.copy( bis, bos );
094 bis.close();
095 bos.close();
096 temp.delete();
097 logger.log( level, "Rename of temp file to " + file.getAbsolutePath() +
098 " failed. Recopied from source." );
099 }
100
101 event.getFileItem().delete();
102
103 logger.log( level, "Copied upload file contents to: " +
104 file.getAbsolutePath() );
105 }
106 catch ( Exception e )
107 {
108 throw new RuntimeException( "Error copying uploaded file!", e );
109 }
110
111 super.uploadSucceeded( event );
112 }
113
114 /**
115 * Return a file object that represents the uploaded file that is to be
116 * saved.
117 *
118 * @param name The file name of the uploaded file.
119 * @return The new file object that represents the file to be saved.
120 */
121 protected File getFileName( final String name )
122 {
123 return new File( directory.getAbsolutePath() + FILE_SEPARATOR + name );
124 }
125
126 /**
127 * Return a temporary file to which the contents of the uploaded file will
128 * be initially written. This file will then be moved to the proper
129 * destination file. This ensures atomic creation of the new file.
130 *
131 * @return The temporary file to create.
132 */
133 protected File getTempFile()
134 {
135 return new File( directory.getAbsolutePath() + FILE_SEPARATOR +
136 "echopoint.tempfile." + System.currentTimeMillis() + ".tmp" );
137 }
138
139 /**
140 * Accessor for property 'directory'.
141 *
142 * @return Value for property 'directory'.
143 */
144 public File getDirectory()
145 {
146 return directory;
147 }
148
149 /**
150 * Mutator for property 'directory'.
151 *
152 * @param directory Value to set for property 'directory'.
153 * @throws IllegalArgumentException If the file specified is not a directory.
154 */
155 public void setDirectory( final File directory ) throws IllegalArgumentException
156 {
157 if ( ! directory.isDirectory() )
158 {
159 throw new IllegalArgumentException( "File specified must be a directory!" );
160 }
161
162 this.directory = directory;
163 }
164 }