Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/RuntimeCollective/content/bean/File.java


1   /* $Header: /home/CVS/rjp/src/com/RuntimeCollective/content/bean/File.java,v 1.27 2003/09/30 15:12:46 joe Exp $
2    * $Revision: 1.27 $
3    * $Date: 2003/09/30 15:12:46 $
4    *
5    * ====================================================================
6    *
7    * Josephine : http://www.runtime-collective.com/josephine/index.html
8    *
9    * Copyright (C) 2003 Runtime Collective
10   * 
11   * This product includes software developed by the
12   * Apache Software Foundation (http://www.apache.org/).
13   *
14   * This library is free software; you can redistribute it and/or
15   * modify it under the terms of the GNU Lesser General Public
16   * License as published by the Free Software Foundation; either
17   * version 2.1 of the License, or (at your option) any later version.
18   *
19   * This library is distributed in the hope that it will be useful,
20   * but WITHOUT ANY WARRANTY; without even the implied warranty of
21   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22   * Lesser General Public License for more details.
23   *
24   * You should have received a copy of the GNU Lesser General Public
25   * License along with this library; if not, write to the Free Software
26   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27   *
28   */
29  
30  package com.RuntimeCollective.content.bean;
31  
32  
33  import com.RuntimeCollective.webapps.bean.User;
34  import com.RuntimeCollective.webapps.RuntimeParameters;
35  import com.RuntimeCollective.webapps.RuntimeDataSource;
36  import com.RuntimeCollective.webapps.RuntimeParameters;
37  import com.RuntimeCollective.webapps.bean.DateBean;
38  import com.RuntimeCollective.webapps.bean.Duplicable;
39  import com.RuntimeCollective.webapps.bean.EntityBean;
40  
41  import org.apache.struts.upload.DiskFile;
42  import org.apache.struts.upload.FormFile;
43  
44  import java.io.BufferedInputStream;
45  import java.io.ByteArrayInputStream;
46  import java.io.FileInputStream;
47  import java.io.FileNotFoundException;
48  import java.io.FileOutputStream;
49  import java.io.InputStream;
50  import java.io.IOException;
51  import java.sql.SQLException;
52  import java.util.Iterator;
53  import java.util.Vector;
54  
55  /**
56   * The File class will hold the content of a file, either directly, or via a
57   * filename reference. In the first case, the content will be saved in the permanence
58   * layer (e.g. database), in the other, only the reference to the file will be kept.
59   * <p> If the latter, then the following runtime parameters must be set:
60   * <ul>
61   * <li><code>contentFilesDataDir</code> -- The directory where the content files will be stored.
62   * <li><code>pageRoot</code> -- The page root of the application
63   * <li><code>contentFilesUrlStub</code> -- The url path, relative to the application page root, where the content files will be available.
64   * </ul>
65   *
66   * @version $Id: File.java,v 1.27 2003/09/30 15:12:46 joe Exp $
67   */
68  public class File extends SimpleContent {
69  
70      // ---Inherited from EntityBean---------------------------
71  
72      /** The name of the database table for this bean type. */
73      public static final String DATABASE_TABLE = "content_file";
74  
75      /** Set the unique id of this File.
76       * @param an int value for the id
77       */
78      public void setId(int id) {
79    // delete the file(s) relating to the old Id
80    if (this.id > -1) {
81        deleteExistingFiles();
82    }
83    super.setId(id);
84      }
85  
86      /** Delete the files saved in the filesystem */
87      protected void deleteExistingFiles() {
88  
89    String dirfilename = RuntimeParameters.get("contentFilesDataDir");
90    java.io.File dirFile = new java.io.File(dirfilename);
91  
92    if ((dirFile == null) || (!dirFile.exists()))
93        RuntimeParameters.logFatal(this, "Cannot find File data dir : "+dirfilename+"\nIs contentFilesDataDir properly set in web.xml ?");
94  
95    else {
96        java.io.File[] files = dirFile.listFiles();
97        java.io.File a_file;
98        for (int i=0; i<files.length; i++) {
99      a_file = files[i];
100     if (a_file.isFile() && a_file.getName().startsWith(getId()+".")) {
101         RuntimeParameters.logInfo(this, "Deleting File file : "+a_file.getName());
102         a_file.delete();
103     }
104       }
105   }
106 
107    }
108 
109     /** Save this File to the database.
110      * @exception SQLException is thrown if the object couldn't be saved properly to the database.
111      */
112     public void save() throws SQLException {
113 
114   String dbalias = RuntimeDataSource.getDefaultAlias();
115 
116   // Save the SimpleContent attributes
117   super.save();
118 
119   // Save the File's basic attributes
120   RuntimeDataSource.save(id, "content_file", new String[] { "mimetype", "file_ending", "original_filename" }, new Object[] { MimeType, FileEnding, OriginalFilename });
121     }
122 
123     /** Delete this File from the database.
124      * This also deletes the suitable file(s) from the contentFilesDataDir directory.
125      * There may be more than one file to delete if we changed the FileEnding.
126      *
127      * @exception SQLException is thrown if the object couldn't be deleted properly from the database.
128      */
129     public void delete() throws SQLException {
130 
131   String[] updates;
132 
133   updates = new String[] { "delete from content_file where id = "+id };
134   RuntimeDataSource.update( updates);
135 
136   // deleting the file(s)
137   deleteExistingFiles();
138 
139   // Delete SimpleContent attributes
140   super.delete();
141     }
142 
143 
144     //---Inherited from Content---------------------
145 
146     /** Get the title
147      * Return the filename and mimetype.
148      *
149      * @return A String which can be used as the title of this object.
150      */
151     public String getTitle() {
152         return (new StringBuffer(30)).append(getId()).append(".").append(getFileEnding()).append(" (").append(getMimeType()).append(")").toString();
153     }
154 
155     /** Get the description
156      * Return the original filename and mimetype.
157      *
158      * @return A String which can be used as the description of this object.
159      */
160     public String getDescription() {
161         return (new StringBuffer(35)).append(getOriginalFilename()).append(" (").append(getMimeType()).append(")").toString();
162     }
163 
164     /** Get the File in a certain format.
165      * For now, only "html" is supported, and it gives the URL of where to find the local file.
166      *
167      * @param A String representing the format in which to display the object.
168      * @return An Object which can be used to display the object in this format.
169      */
170     public Object viewFormat(String format) {
171         if (format.equals("html")) {
172             String filesUrlStub = RuntimeParameters.get("contentFilesUrlStub");
173             if (filesUrlStub != null) {
174                 return (new StringBuffer(70)).append("http://").append(RuntimeParameters.get("pageRoot")).append("/").append(RuntimeParameters.get("contentFilesUrlStub")).append("/").append(getId()).append(".").append(getFileEnding()).append("?").append(Math.random()).toString();
175                 // non-cacheing bit:
176                 // .append("?").append(Math.random())
177             } else {
178                 RuntimeParameters.logError(this, "contentFilesUrlStub not set");
179                 throw new RuntimeException("contentFilesUrlStub not set");
180             }
181             
182         } else {
183             return null;
184         }
185     }
186 
187 
188     //---Specific to File---------------------
189 
190     /** The MimeType */
191     protected String MimeType;
192 
193     /** Set the MimeType
194      * @param The Mime type
195      */
196     public void setMimeType(String mimeType) {
197         MimeType = mimeType;
198     }
199 
200     /** Get the MimeType
201      * @return The Mime type
202      */
203     public String getMimeType() {
204         return MimeType;
205     }
206 
207     /** The OriginalFilename */
208     protected String OriginalFilename;
209 
210     /** Set the OriginalFilename
211      * @param The original file's name
212      */
213     public void setOriginalFilename(String originalFilename) {
214         OriginalFilename = originalFilename;
215     }
216 
217     /** Get the OriginalFilename
218      * @return The original file's name
219      */
220     public String getOriginalFilename() {
221         return OriginalFilename;
222     }
223 
224     /** The FileEnding */
225     protected String FileEnding;
226 
227     /** Set the FileEnding
228      * This will delete old files - if the former FileEnding is not null
229      * (ie if we are not initialising this bean)
230      * @param The end of the file name (eg "gif")
231      */
232     public void setFileEnding(String fileEnding) {
233   if (!fileEnding.equals(FileEnding)) {
234       // get rid of files which use the old FileEnding
235       if (FileEnding != null)
236     deleteExistingFiles();
237 
238       FileEnding = fileEnding;
239   }
240     }
241 
242     /** Get the FileEnding
243      * @return The end of the file name (eg "gif")
244      */
245     public String getFileEnding() {
246   return FileEnding;
247     }
248 
249     /** Construct a new blank File, giving it a new unique ID.
250      * @exception SQLException is thrown if a new ID cannot be created.
251      */
252     public File() throws SQLException {
253   // SimpleContent setup
254   super();
255   setFileEnding("");
256   setOriginalFilename("");
257   setMimeType("");
258     }
259 
260     /** Get a File from the RuntimeDataSource, given an id.
261      * @param id ID of the File.
262      * @exception SQLException is thrown if no such File exists.
263      */
264     public File(int id) throws SQLException {
265 
266   // SimpleContent setup
267   super(id);
268 
269   String dbalias = RuntimeDataSource.getDefaultAlias();
270 
271   Object[] result = RuntimeDataSource.queryRow( "select cf.mimetype, cf.file_ending, cf.original_filename from content_file cf where cf.id = "+id);
272   if (result.length != 3) {
273       throw new SQLException("Cannot load File "+id+": "+result.length+" fields found in content_textcomponent instead of 3.");
274   }
275 
276   if (result[0] != null)
277       setMimeType(result[0].toString());
278   if (result[1] != null)
279       setFileEnding(result[1].toString());
280   if (result[2] != null)
281       setOriginalFilename(result[2].toString());
282     }
283 
284 
285     /** Change the content of the File, from a FormFile
286      * @param A FormFile
287      * @exception RuntimeException is thrown if there is any problem
288      */
289     public void setContent(FormFile formFile) throws RuntimeException {
290         try {
291             String fileName = formFile.getFileName();
292             setMimeType(formFile.getContentType());
293             setOriginalFilename(fileName);
294             
295             RuntimeParameters.logDebug(this, "FormFile stored in : "+((DiskFile) formFile).getFilePath());
296 
297             int lastDot = fileName.lastIndexOf(".");
298             if ((lastDot > -1) && (lastDot < fileName.length() - 2))
299                 setFileEnding(fileName.substring(lastDot + 1));
300             else
301                 setFileEnding("");
302 
303             // do this last as it will use the attributes set above
304             setContent(formFile.getInputStream(), formFile.getFileSize());
305             
306             formFile.destroy();
307             
308         } catch (Exception e) {
309             throw new RuntimeException("Could not get a stream from the specified FormFile to upload : "+e);
310         }
311     }
312 
313 
314     /** Change the content of the File, from a java.io.File
315      * @param A File
316      * @exception RuntimeException is thrown if there is any problem
317      */
318     public void setContent(java.io.File file) throws RuntimeException {
319   try {
320       String fileName = file.getName();
321       int lastDot = fileName.lastIndexOf(".");
322       if ((lastDot > -1) && (lastDot < fileName.length() - 2))
323     setFileEnding(fileName.substring(lastDot + 1));
324       else
325     setFileEnding("");
326 
327       setContent(new FileInputStream(file), (int)file.length());
328 
329   } catch (Exception e) {
330       throw new RuntimeException("Could not get a stream from the specified File to upload : "+e);
331   }
332     }
333 
334 
335     /** Change the content of the File, from a String
336      * Be careful: Strings are 8-bit (no strange characters)
337      * @param A String
338      * @exception RuntimeException is thrown if there is any problem
339      */
340     public void setContent(String string) throws RuntimeException {
341   try {
342       setContent(new ByteArrayInputStream(string.getBytes()), string.length());
343   } catch (RuntimeException e) {
344       throw new RuntimeException("Could not upload the specified String : "+e);
345   }
346     }
347 
348     /**
349      * A method to empty the content of this file.
350      * @exception RuntimeException is thrown if there is any problem
351      */
352     public void emptyContent() throws RuntimeException {
353         try {
354             setContent("");
355             setOriginalFilename("");
356             setMimeType("");
357         } catch (RuntimeException e) {
358             throw new RuntimeException("Could not emptyContent() : "+e);
359         }
360     }
361 
362     /**
363      * Returns whether this file is valid or not, that is, whether it has valid content set.
364      */
365     public boolean isValid() {
366         java.io.File theFile = getFile();
367         if (theFile == null) {
368             return false;
369         } else {
370             return theFile.exists();
371         }
372     }
373 
374 
375     /**
376      * Sometimes, it's just useful to get the raw File itself.  I'm sorry, but it is.
377      * <p>
378      * If there's more than one, just return the first one found. (There shouldn't be.)
379      */
380     public java.io.File getFile() {
381 
382         Vector allFoundFiles = new Vector();
383 
384         String dirfilename = RuntimeParameters.get("contentFilesDataDir");
385         java.io.File dirFile = new java.io.File(dirfilename);
386 
387         if ((dirFile == null) || (!dirFile.exists())) {
388             RuntimeParameters.logError(this, "Cannot find File data dir : "+dirfilename+"\nIs contentFilesDataDir properly set in web.xml ?");
389             return null;
390 
391         } else {
392             java.io.File[] files = dirFile.listFiles();
393             java.io.File a_file;
394 
395             for (int i=0; i<files.length; i++) {
396                 a_file = files[i];
397                 if (a_file.isFile() && a_file.getName().startsWith(getId()+".")) {
398                     RuntimeParameters.logInfo(this, "Found the file : "+a_file.getName());
399                     allFoundFiles.add(a_file);
400                 }
401             }
402         }
403         
404         if (allFoundFiles.size() > 1) {
405             RuntimeParameters.logError(this, "More than one file found for "+getId()+" - just returning the first one.");
406         }
407         
408         if (allFoundFiles.size() == 0) {
409             // No matching files!
410             RuntimeParameters.logDebug(this, "No files found for "+getId()+" - returning null!");
411             return null;
412 
413         } else {
414             // Return the first matching file.
415             // (Hopefully there's just one.)
416             return (java.io.File) allFoundFiles.elementAt(0);
417         }
418     }
419     
420 
421 
422     /** Change the content of the File, from an InputSteam and its size
423      * @param An InputStream
424      * @param An int, the size of the InputStream
425      * @exception RuntimeException is thrown if there is any problem
426      */
427     public void setContent(InputStream inputStream, int length) throws RuntimeException{
428 
429   byte[] content = new byte[length];
430 
431   try {
432       // read the input stream
433       BufferedInputStream bis = new BufferedInputStream(inputStream);
434       bis.read(content, 0, length);
435       bis.close();
436 
437       // create the local file (and parent dir if required)
438       StringBuffer filename = new StringBuffer(40);
439 
440       filename.append(RuntimeParameters.get("contentFilesDataDir"));
441 
442       java.io.File file = new java.io.File(filename.toString());
443       if (!file.exists()) {
444     RuntimeParameters.logInfo(this, "Creating File data dir : "+filename.toString());
445     file.mkdirs();
446       }
447       filename.append(java.io.File.separator).append(getId()).append(".").append(getFileEnding());
448       file = new java.io.File(filename.toString());
449       if (file.exists())
450     file.delete();
451       file.createNewFile();
452 
453       // write the stream's content to the file
454       RuntimeParameters.logInfo(this,"Saving to : "+filename.toString());
455       FileOutputStream os = new FileOutputStream(file);
456       os.write(content);
457       os.flush();
458       os.close();
459 
460   } catch (Exception e) {
461       RuntimeParameters.logError(this, "The content dir is " + RuntimeParameters.get("contentFilesDataDir"));
462       RuntimeParameters.logError(this, "Could not read and save the InputStream's content into a File : ",e);
463       throw new RuntimeException("Could not read and save the InputStream's content into a File : "+e);
464   }
465     }
466 
467 
468     // Duplicable specific
469 
470     /**
471      * The File version of this method actually copies the file on the FileSystem.
472      *
473      * @param duplicate, the "raw" duplicate
474      * @return the "complete" duplicate
475      */
476     public Duplicable customiseDuplicate(Duplicable duplicate) {
477 
478   // use the parent
479   duplicate = super.customiseDuplicate(duplicate);
480 
481   if (duplicate == null) {
482       RuntimeParameters.logDebug(this, " *** File "+getId()+" is passed \"null\" in customiseDuplicate !");
483       return null;
484   }
485 
486   if (!(duplicate instanceof File)) {
487       RuntimeParameters.logDebug(this, " *** File "+getId()+" is passed non-File "+duplicate.getId()+" in customiseDuplicate !");
488       return duplicate;
489   }
490 
491   // we are in the original object, we have the duplicate in hand
492   // what we want to do is tell the duplicate to use a copy of the file of the original:
493   // 1. get the java.io.File of the original
494   // 2. set the content of the duplicate to that java.io.File
495 
496   // 1. get the java.io.File of the original
497   StringBuffer filename = new StringBuffer(40);
498   filename.append(RuntimeParameters.get("contentFilesDataDir"));
499   filename.append(java.io.File.separator).append(getId()).append(".").append(getFileEnding());
500   java.io.File file = new java.io.File(filename.toString());
501 
502   // 2. set the content of the duplicate to that java.io.File
503   if (file.exists()) {
504       try {
505     ((File) duplicate).setContent(file);
506       } catch (RuntimeException e) {
507     RuntimeParameters.logDebug(this, " *** File "+getId()+", in customiseDuplicate("+duplicate.getId()+"), could not setContent of the duplicate : "+e);
508       }
509   }
510 
511   // no need to save anything
512 
513   return duplicate;
514     }
515 }
516 
517 
518 
519