1 package org.apache.turbine.services.upload;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.UnsupportedEncodingException;
24 import java.util.Iterator;
25 import java.util.List;
26
27 import javax.servlet.http.HttpServletRequest;
28
29 import org.apache.commons.configuration.Configuration;
30 import org.apache.commons.fileupload.FileItem;
31 import org.apache.commons.fileupload.FileUploadException;
32 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
33 import org.apache.commons.fileupload.servlet.ServletFileUpload;
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36 import org.apache.turbine.Turbine;
37 import org.apache.turbine.services.InitializationException;
38 import org.apache.turbine.services.TurbineBaseService;
39 import org.apache.turbine.util.TurbineException;
40 import org.apache.turbine.util.parser.ParameterParser;
41
42 /***
43 * <p> This class is an implementation of {@link UploadService}.
44 *
45 * <p> Files will be stored in temporary disk storage on in memory,
46 * depending on request size, and will be available from the {@link
47 * org.apache.turbine.util.parser.ParameterParser} as {@link
48 * org.apache.commons.fileupload.FileItem}s.
49 *
50 * <p>This implementation of {@link UploadService} handles multiple
51 * files per single html widget, sent using multipar/mixed encoding
52 * type, as specified by RFC 1867. Use {@link
53 * org.apache.turbine.util.parser.ParameterParser#getFileItems(String)} to
54 * acquire an array of {@link
55 * org.apache.commons.fileupload.FileItem}s associated with given
56 * html widget.
57 *
58 * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
59 * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
60 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
61 * @version $Id: TurbineUploadService.java 534527 2007-05-02 16:10:59Z tv $
62 */
63 public class TurbineUploadService
64 extends TurbineBaseService
65 implements UploadService
66 {
67 /*** Logging */
68 private static Log log = LogFactory.getLog(TurbineUploadService.class);
69
70 /*** A File Upload object for the actual uploading */
71 protected ServletFileUpload fileUpload = null;
72
73 /*** A File Item Factory object for the actual uploading */
74 protected DiskFileItemFactory itemFactory = null;
75
76 /*** Auto Upload yes? */
77 private boolean automatic;
78
79 /***
80 * Initializes the service.
81 *
82 * This method processes the repository path, to make it relative to the
83 * web application root, if neccessary
84 */
85 public void init()
86 throws InitializationException
87 {
88 Configuration conf = getConfiguration();
89
90 String repoPath = conf.getString(
91 UploadService.REPOSITORY_KEY,
92 UploadService.REPOSITORY_DEFAULT);
93
94 if (!repoPath.startsWith("/"))
95 {
96
97
98
99 String testPath = Turbine.getRealPath(repoPath);
100 File testDir = new File(testPath);
101 if (!testDir.exists())
102 {
103 if (!testDir.mkdirs())
104 {
105 throw new InitializationException(
106 "Could not create target directory!");
107 }
108 }
109 repoPath = testPath;
110 conf.setProperty(UploadService.REPOSITORY_KEY, repoPath);
111 }
112
113 log.debug("Upload Path is now " + repoPath);
114
115 long sizeMax = conf.getLong(
116 UploadService.SIZE_MAX_KEY,
117 UploadService.SIZE_MAX_DEFAULT);
118
119 log.debug("Max Size " + sizeMax);
120
121 int sizeThreshold = conf.getInt(
122 UploadService.SIZE_THRESHOLD_KEY,
123 UploadService.SIZE_THRESHOLD_DEFAULT);
124
125 log.debug("Threshold Size " + sizeThreshold);
126
127 automatic = conf.getBoolean(
128 UploadService.AUTOMATIC_KEY,
129 UploadService.AUTOMATIC_DEFAULT);
130
131 log.debug("Auto Upload " + automatic);
132
133 itemFactory = new DiskFileItemFactory();
134 itemFactory.setSizeThreshold(sizeThreshold);
135 itemFactory.setRepository(new File(repoPath));
136 fileUpload = new ServletFileUpload(itemFactory);
137 fileUpload.setSizeMax(sizeMax);
138
139 setInit(true);
140 }
141
142 /***
143 * <p> Retrieves the value of <code>size.max</code> property of the
144 * {@link org.apache.turbine.services.upload.UploadService}.
145 *
146 * @return The maximum upload size.
147 */
148 public long getSizeMax()
149 {
150 return fileUpload.getSizeMax();
151 }
152
153 /***
154 * <p> Retrieves the value of <code>size.threshold</code> property of
155 * {@link org.apache.turbine.services.upload.UploadService}.
156 *
157 * @return The threshold beyond which files are written directly to disk.
158 */
159 public int getSizeThreshold()
160 {
161 return itemFactory.getSizeThreshold();
162 }
163
164 /***
165 * Retrieves the value of the 'automatic' property of {@link
166 * UploadService}. This reports whether the Parameter parser
167 * should allow "automatic" uploads if it is submitted to
168 * Turbine.
169 *
170 * @return The value of 'automatic' property of {@link
171 * UploadService}.
172 */
173 public boolean getAutomatic()
174 {
175 return automatic;
176 }
177
178 /***
179 * <p> Retrieves the value of the <code>repository</code> property of
180 * {@link org.apache.turbine.services.upload.UploadService}.
181 *
182 * @return The repository.
183 */
184 public String getRepository()
185 {
186 return itemFactory.getRepository().getAbsolutePath();
187 }
188
189 /***
190 * <p> Processes an <a href="http://rf.cx/rfc1867.html">RFC
191 * 1867</a> compliant <code>multipart/form-data</code> stream.
192 *
193 * @param req The servlet request to be parsed.
194 * @param params The ParameterParser instance to insert form
195 * fields into.
196 * @param path The location where the files should be stored.
197 * @exception TurbineException Problems reading/parsing the
198 * request or storing the uploaded file(s).
199 */
200 public void parseRequest(HttpServletRequest req,
201 ParameterParser params,
202 String path)
203 throws TurbineException
204 {
205 String contentType = req.getHeader(CONTENT_TYPE);
206 if (!contentType.startsWith(MULTIPART_FORM_DATA))
207 {
208 throw new TurbineException("the request doesn't contain a " +
209 MULTIPART_FORM_DATA + " stream");
210 }
211 int requestSize = req.getContentLength();
212 if (requestSize == -1)
213 {
214 throw new TurbineException("the request was rejected because " +
215 "it's size is unknown");
216 }
217 if (requestSize > getSizeMax())
218 {
219 throw new TurbineException("the request was rejected because " +
220 "it's size exceeds allowed range");
221 }
222
223 try
224 {
225 List fileList = fileUpload.parseRequest(req);
226
227 if (fileList != null)
228 {
229 for (Iterator it = fileList.iterator(); it.hasNext();)
230 {
231 FileItem fi = (FileItem) it.next();
232 if (fi.isFormField())
233 {
234 log.debug("Found an simple form field: " + fi.getFieldName() +", adding value " + fi.getString());
235
236 String value = null;
237 try
238 {
239 value = fi.getString(params.getCharacterEncoding());
240 }
241 catch (UnsupportedEncodingException e)
242 {
243 log.error(params.getCharacterEncoding()
244 + " encoding is not supported."
245 + "Used the default when reading form data.");
246 value = fi.getString();
247 }
248 params.add(fi.getFieldName(), value);
249 }
250 else
251 {
252 log.debug("Found an uploaded file: " + fi.getFieldName());
253 log.debug("It has " + fi.getSize() + " Bytes and is " + (fi.isInMemory() ? "" : "not ") + "in Memory");
254 log.debug("Adding FileItem as " + fi.getFieldName() + " to the params");
255 params.add(fi.getFieldName(), fi);
256 }
257 }
258 }
259 }
260 catch (FileUploadException e)
261 {
262 throw new TurbineException(e);
263 }
264 }
265 }