View Javadoc

1   package org.apache.turbine.services.upload;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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              // If our temporary directory is in the application
97              // space, try to create it. If this fails, throw
98              // an exception.
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 }