View Javadoc

1   package org.apache.turbine.services.xmlrpc.util;
2   
3   /*
4    * Copyright 2001-2005 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License")
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  import java.io.BufferedReader;
20  import java.io.File;
21  import java.io.FileInputStream;
22  import java.io.FileWriter;
23  import java.io.IOException;
24  import java.io.InputStreamReader;
25  import java.io.StringWriter;
26  
27  import javax.mail.internet.MimeUtility;
28  
29  import org.apache.commons.lang.StringUtils;
30  
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  
34  import org.apache.turbine.Turbine;
35  
36  import org.apache.turbine.services.servlet.TurbineServlet;
37  
38  /***
39   * A Handler for use with the XML-RPC service that will deal
40   * with clients sending file to the server (Turbine application)
41   * and clients getting files from the server (Turbine application).
42   *
43   * 1) In the first case where the client sends a file to the server,
44   * the client has encoded the file contents and passes those
45   * encoded file contents on to the server:
46   *
47   * Client --------> encoded file contents -------------> Server
48   *
49   * The server must then decode the file contents and write the
50   * decoded file contents to disk.
51   *
52   * 2) In the second case where the client gets a file from the
53   * the server, the server has encoded the file contents and
54   * passes those encoded file contents on to the client:
55   *
56   * Client <-------  encoded file contents <------------- Server
57   *
58   * The client must then decode the file contents and write the
59   * decoded file contents to disk.
60   *
61   * @author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
62   * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
63   * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
64   * @version $Id: FileHandler.java 264148 2005-08-29 14:21:04Z henning $
65   * @deprecated This is not scope of the Service itself but of an
66   *             application which uses the service. This class shouldn't
67   *             be part of Turbine but of an addon application.
68   */
69  public class FileHandler
70  {
71      /*** Logging */
72      private static Log log = LogFactory.getLog(FileHandler.class);
73  
74      /***
75       * Default Constructor
76       */
77      public FileHandler()
78      {
79      }
80  
81      /***
82       * The client has indicated that it would like
83       * to send a file to the server and have it
84       * stored in a certain location on the server.
85       *
86       * So a client Turbine application might use the
87       * following bit of code to send a file to a server
88       * Turbine application:
89       *
90       * TurbineXmlRpc.executeRpc("file.send", params)
91       *
92       * Where:
93       *
94       * params.get(0) = contents of the file as a string.
95       * params.get(1) = the name the file should have when it lands.
96       * params.get(2) = property describing where the file should land.
97       *
98       * @param fileContents The contents of the file to store. It
99       *    is assumed that any xml content is properly encoded!
100      *
101      * @param fileName Name to give the file created to store
102      *    the contents.
103      *
104      * @param targetLocationProperty storage location of this file
105      *    is controlled by this property that is specified in
106      *    the TR.props file or an included properties file.
107      */
108     public boolean send(String fileContents,
109                         String targetLocationProperty,
110                         String fileName)
111     {
112         /*
113          * Simply take the file contents that have been sent
114          * by the client and write them to disk in the
115          * specified location: targetLocationProperty specifies
116          * the directory in which to place the fileContents
117          * with the name fileName.
118          */
119         return writeFileContents(fileContents, targetLocationProperty,
120                 fileName);
121     }
122 
123     /***
124      * The client has indicated that it would like
125      * to get a file from the server.
126      *
127      * So a client Turbine application might use the
128      * following bit of code to get a file from a server
129      * Turbine application:
130      *
131      * TurbineXmlRpc.executeRpc("file.get", params)
132      *
133      * Where:
134      *
135      * params.get(0) = the name the file should have when it lands.
136      * params.get(1) = property describing where the file should land.
137      *
138      * @param fileName Name to give the file created to store
139      *    the contents.
140      *
141      * @param targetLocationProperty storage location of this file
142      *    is controlled by this property that is specified in
143      *    the TR.props file or an included properties file.
144      *
145      * @return the file contents encoded with base64.
146      */
147     public String get(String targetLocationProperty,
148                       String fileName)
149     {
150         /*
151          * Place the contents of the file with the name
152          * fileName in the directory specified by
153          * targetLocationProperty.
154          */
155         return readFileContents(targetLocationProperty, fileName);
156     }
157 
158     /***
159      * Return the content of file encoded for transfer
160      *
161      * @param targetLocationProperty path to file to encode.
162      * @param fileName file to encode
163      * @return String encoded contents of the requested file.
164      */
165     public static String readFileContents(String targetLocationProperty,
166                                           String fileName)
167     {
168         String location =
169           Turbine.getConfiguration().getString(targetLocationProperty);
170 
171         if (StringUtils.isEmpty(location))
172         {
173           log.error("Could not load Property for location "
174               + targetLocationProperty);
175           return null;
176         }
177 
178         File tmpF = new File(".");
179 
180         StringBuffer sb = new StringBuffer();
181         sb.append(location);
182         sb.append(File.separator);
183         sb.append(fileName);
184 
185         String file = TurbineServlet.getRealPath(sb.toString());
186 
187         StringWriter sw = null;
188         BufferedReader reader = null;
189         try
190         {
191             /*
192              * This little routine was borrowed from the
193              * velocity ContentResource class.
194              */
195 
196             sw = new StringWriter();
197 
198             reader = new BufferedReader(
199                     new InputStreamReader(
200                             new FileInputStream(file)));
201 
202             char buf[] = new char[1024];
203             int len = 0;
204 
205             while ((len = reader.read(buf, 0, 1024)) != -1)
206             {
207                 sw.write(buf, 0, len);
208             }
209 
210             return MimeUtility.encodeText(sw.toString(), "UTF-8", "B");
211         }
212         catch (IOException ioe)
213         {
214             log.error("[FileHandler] Unable to encode the contents " +
215                     "of the request file.", ioe);
216 
217             return null;
218         }
219         finally
220         {
221             try
222             {
223                 if (sw != null)
224                 {
225                     sw.close();
226                 }
227                 if (reader != null)
228                 {
229                     reader.close();
230                 }
231             }
232             catch (Exception e)
233             {
234             }
235         }
236     }
237 
238     public static boolean writeFileContents(String fileContents,
239                                             String targetLocationProperty,
240                                             String fileName)
241     {
242         String location =
243           Turbine.getConfiguration().getString(targetLocationProperty);
244 
245         if (StringUtils.isEmpty(location))
246         {
247           log.error("Could not load Property for location "
248               + targetLocationProperty);
249           return false;
250         }
251 
252         /*
253          * The target location is always within the webapp to
254          * make the application fully portable. So use the TurbineServlet
255          * service to map the target location in the webapp space.
256          */
257 
258         File targetLocation = new File(
259             TurbineServlet.getRealPath(location));
260 
261         if (!targetLocation.exists())
262         {
263             /*
264              * If the target location doesn't exist then
265              * attempt to create the target location and any
266              * necessary parent directories as well.
267              */
268             if (!targetLocation.mkdirs())
269             {
270                 log.error("[FileHandler] Could not create target location: " +
271                         targetLocation + ". Cannot transfer file from client.");
272 
273                 return false;
274             }
275             else
276             {
277                 log.info("[FileHandler] Creating target location:" +
278                         targetLocation +
279                         " in order to complete file transfer from client.");
280             }
281         }
282 
283         FileWriter fileWriter = null;
284         try
285         {
286             /*
287              * Try to create the target file and write it out
288              * to the target location.
289              */
290             fileWriter = new FileWriter(
291                     targetLocation + "/" + fileName);
292 
293             /*
294              * It is assumed that the file has been encoded
295              * and therefore must be decoded before the
296              * contents of the file are stored to disk.
297              */
298             fileWriter.write(MimeUtility.decodeText(fileContents));
299 
300             return true;
301         }
302         catch (IOException ioe)
303         {
304             log.error("[FileHandler] Could not write the decoded file " +
305                     "contents to disk for the following reason.", ioe);
306 
307             return false;
308         }
309         finally
310         {
311             try
312             {
313                 if (fileWriter != null)
314                 {
315                     fileWriter.close();
316                 }
317             }
318             catch (Exception e)
319             {
320             }
321         }
322     }
323 
324     /***
325      * Method to allow a client to remove a file from
326      * the server
327      *
328      * @param sourceLocationProperty
329      * @param sourceFileName
330      */
331     public static void remove(String sourceLocationProperty,
332                               String sourceFileName)
333     {
334         String location =
335           Turbine.getConfiguration().getString(sourceLocationProperty);
336 
337         if (StringUtils.isEmpty(location))
338         {
339           log.error("Could not load Property for location "
340               + sourceLocationProperty);
341           return;
342         }
343 
344         /*
345          * The target location is always within the webapp to
346          * make the application fully portable. So use the TurbineServlet
347          * service to map the target location in the webapp space.
348          */
349         File sourceFile =
350             new File(TurbineServlet.getRealPath(sourceLocationProperty
351                          + "/" + sourceFileName));
352 
353         if (sourceFile.exists())
354         {
355             sourceFile.delete();
356         }
357     }
358 }