KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jcorporate > expresso > services > dbobj > MediaDBObject


1 /* ====================================================================
2  * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
3  *
4  * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  *
18  * 3. The end-user documentation included with the redistribution,
19  * if any, must include the following acknowledgment:
20  * "This product includes software developed by Jcorporate Ltd.
21  * (http://www.jcorporate.com/)."
22  * Alternately, this acknowledgment may appear in the software itself,
23  * if and wherever such third-party acknowledgments normally appear.
24  *
25  * 4. "Jcorporate" and product names such as "Expresso" must
26  * not be used to endorse or promote products derived from this
27  * software without prior written permission. For written permission,
28  * please contact info@jcorporate.com.
29  *
30  * 5. Products derived from this software may not be called "Expresso",
31  * or other Jcorporate product names; nor may "Expresso" or other
32  * Jcorporate product names appear in their name, without prior
33  * written permission of Jcorporate Ltd.
34  *
35  * 6. No product derived from this software may compete in the same
36  * market space, i.e. framework, without prior written permission
37  * of Jcorporate Ltd. For written permission, please contact
38  * partners@jcorporate.com.
39  *
40  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
41  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
42  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
43  * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
44  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
46  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
47  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
48  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
49  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
50  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * ====================================================================
53  *
54  * This software consists of voluntary contributions made by many
55  * individuals on behalf of the Jcorporate Ltd. Contributions back
56  * to the project(s) are encouraged when you make modifications.
57  * Please send them to support@jcorporate.com. For more information
58  * on Jcorporate Ltd. and its products, please see
59  * <http://www.jcorporate.com/>.
60  *
61  * Portions of this software are based upon other open source
62  * products and are subject to their respective licenses.
63  */

64
65 package com.jcorporate.expresso.services.dbobj;
66
67 import com.jcorporate.expresso.core.dataobjects.DataField;
68 import com.jcorporate.expresso.core.dataobjects.jdbc.LobField;
69 import com.jcorporate.expresso.core.db.DBConnection;
70 import com.jcorporate.expresso.core.db.DBException;
71 import com.jcorporate.expresso.core.dbobj.RequestContext;
72 import com.jcorporate.expresso.core.dbobj.SecuredDBObject;
73 import com.jcorporate.expresso.core.misc.ConfigJdbc;
74 import com.jcorporate.expresso.core.misc.ConfigManager;
75 import com.jcorporate.expresso.core.misc.ConfigurationException;
76 import org.apache.log4j.Logger;
77
78 import java.io.File JavaDoc;
79 import java.io.FileInputStream JavaDoc;
80 import java.io.FileNotFoundException JavaDoc;
81 import java.io.IOException JavaDoc;
82 import java.io.InputStream JavaDoc;
83 import java.sql.SQLException JavaDoc;
84
85 /**
86  * A MediaDBObject is a DBObject intended to be used for storage of media objects
87  * directly in the database. It facilitates generic storage by automatically
88  * creating filename and MimeType fields that map to the MimeTypes table for
89  * easy downloading. This allows for the ability to store more than one media
90  * type in the same table while still allowing the Application to appropriately
91  * deal with each MimeType.
92  * <p/>
93  * <p/>
94  * This data object conveniently stores and retrieves Binary Large OBjects (BLOBS) or
95  * Character Large OBjects (CLOBS).
96  * <p/>
97  * <p/>
98  * Performance note: Each blob field access requires one more round trip to the
99  * database since BLOBs cannot be effectively stored in memory. Thus the lazy
100  * loading.
101  * </p>
102  * <p>Typical Usage:<code><pre>
103  * myMediaDBObject = new myMediaDBObject();
104  * File f = new File("/temp/output.tmp");
105  * FileOutputStream fos = new FileOutputStream(f);
106  * myMediaDBObject.setField("id", 2)
107  * InputStream is = myMediaDBObject.retrieveBlob("picture");
108  * // Copy the input stream to the file output stream
109  * myMediaDBObject.release();
110  * </pre></code></p>
111  *
112  * @author Michael Rimov, Peter Pilgrim
113  * @version $Revision: 1.9 $ on $Date: 2004/11/17 20:48:18 $
114  * @since Expresso 5.1
115  */

116 public class MediaDBObject extends SecuredDBObject {
117
118     /**
119      * The LOBField object for streaming data into and out of the Database
120      */

121     private LobField lf = null;
122
123     /**
124      * The Log4j Logger
125      */

126     private static final Logger log = Logger.getLogger(MediaDBObject.class);
127
128     /**
129      * Suffix for the filename field.
130      * <p>Each blob field has several additional supporting fields. The supporting
131      * fields have the name of the original BLOB field plus a suffix that is appended
132      * to the BLOB field name to get the supporting field</p>
133      */

134     public static final String JavaDoc FLD_FILE_SUFFIX = "_fileName";
135
136     /**
137      * Suffix for the mime number field. This field contains a pointer into the
138      * MimeTypes table.
139      * <p>Each blob field has several additional supporting fields. The supporting
140      * fields have the name of the original BLOB field plus a suffix that is appended
141      * to the BLOB field name to get the supporting field</p>
142      */

143     public static final String JavaDoc FLD_MIME_SUFFIX = "_mimeType";
144
145     /**
146      * Suffix for the file size field. This field contains the size of the blob
147      * that was saved to the database.
148      * <p>Each blob field has several additional supporting fields. The supporting
149      * fields have the name of the original BLOB field plus a suffix that is appended
150      * to the BLOB field name to get the supporting field</p>
151      */

152     public static final String JavaDoc FLD_SIZE_SUFFIX = "_fileSize";
153
154
155     /**
156      * Default Constructor.
157      *
158      * @throws DBException upon initialization error
159      */

160     public MediaDBObject() throws DBException {
161         super();
162     }
163
164
165     /**
166      * Constructor that sets the connection on create
167      *
168      * @param newConnection The dbConnection object to associate with this
169      * object
170      */

171     public MediaDBObject(DBConnection newConnection)
172             throws DBException {
173         super(newConnection);
174     } /* SecuredDBObject(DBConnection) */
175
176     /**
177      * <p/>
178      * Constructor that sets a connection as the object is created - typically
179      * this is used when a particular DBConnection is required for the purposes of
180      * maintaining a database transaction. If a specific connection is not used,
181      * there is no way to use commit() and rollback() in the event of failure, as a
182      * different DBConnection might be used for each phase of the transaction.
183      * Critial sections should therefore explicity request a DBConnection from the
184      * connection pool and pass it to each of the DB objects in that section.
185      * </p>
186      * <p>This constructor is neceesary to work with otherDBMap and transaction
187      * capabilities</p>
188      *
189      * @param newConnection The DBConnection to utilize
190      * @param setupTablesContext The data context that contains the setup (and
191      * security) tables for this object
192      */

193     public MediaDBObject(DBConnection newConnection, String JavaDoc setupTablesContext)
194             throws DBException {
195         super(newConnection, setupTablesContext);
196     } /* DBObject(DBConnection) */
197
198     /**
199      * Constructor: Specify a DB connection AND user
200      *
201      * @param newUid User ID attempting to use this object.
202      * If this is SecuredDBObject.SYSTEM_ACCOUNT, then
203      * full permissions are granted. Note that you cannot log in
204      * as SecuredDBObject.SYSTEM_ACCOUNT,
205      * t can only be used from within a method.
206      * @throws DBException If the object cannot be created
207      */

208     public MediaDBObject(int newUid)
209             throws DBException {
210         super(newUid);
211     }
212
213     /**
214      * For using DBObjects within Controllers. Initializes based upon the current
215      * user and the requested db. [Of course this can be modified later]
216      *
217      * @param request - The controller request handed to you by the framework.
218      * @throws DBException upon construction error
219      */

220     public MediaDBObject(RequestContext request)
221             throws DBException {
222         super(request);
223     }
224
225     /**
226      * Convenience method to get the LOB attachment filename
227      *
228      * @throws DBException if a database error occurs
229      * @parameter fieldName the field name of the attachment
230      */

231     public String JavaDoc getBlobFilename(String JavaDoc fieldName) throws DBException {
232         return getField(fieldName + FLD_FILE_SUFFIX);
233     }
234
235     /**
236      * Convenience method to get the LOB attachment mime content type
237      *
238      * @throws DBException if a database error occurs
239      * @parameter fieldName the field name of the attachment
240      */

241     public String JavaDoc getBlobMimeType(String JavaDoc fieldName) throws DBException {
242         return getField(fieldName + FLD_MIME_SUFFIX);
243     }
244
245     /**
246      * Convenience method to get the LOB attachment content length
247      *
248      * @throws DBException if a database error occurs
249      * @parameter fieldName the field name of the attachment
250      */

251     public String JavaDoc getBlobFileSize(String JavaDoc fieldName) throws DBException {
252         return getField(fieldName + FLD_SIZE_SUFFIX);
253     }
254
255     /**
256      * Convenience method to get the LOB attachment content length as
257      * an integer
258      *
259      * @throws DBException if a database error occurs
260      * @parameter fieldName the field name of the attachment
261      */

262     public int getBlobFileSizeInt(String JavaDoc fieldName) throws DBException {
263         return getFieldInt(fieldName + FLD_SIZE_SUFFIX);
264     }
265
266     /**
267      * Adds a BLOB field definition to this DBObject.
268      * <p>Using this method creates several supporting fields.
269      * <ul>
270      * <li>BlobFieldName + '_mimeType': An integer value that points to the mime type
271      * in the MimeTypes table. When the BLOB is retrieved, the content stream
272      * mime type can be set allowing for the web browser to properly interpret the
273      * incoming stream.</li>
274      * <li>BlobFieldName + '_fileName': A file name for the BLOB field. While this is
275      * optional, it allows the WebBrowser to assign a default file name when it
276      * saves the BLOB locally </li>
277      * <li>BlobFieldName + '_fileSize': This field gets set when a file is uploaded
278      * into the database table. It allows for the browser to determine what percentage
279      * of the BLOB is transferred to the browser</li>
280      * </ul>
281      * </p>
282      *
283      * @param fieldName The name of the field to create.
284      * @param fieldDescription The 'friendly name' of the field to create
285      * @throws DBException upon creation error.
286      */

287     protected void addBlobField(String JavaDoc fieldName, String JavaDoc fieldDescription) throws DBException {
288         this.addField(fieldName, "blob", 0, true, fieldDescription);
289         this.addField(fieldName + FLD_MIME_SUFFIX, "int", 0, true, fieldDescription + " Mime Type");
290         this.addField(fieldName + FLD_FILE_SUFFIX, "varchar", 128, true, fieldDescription + " File Name");
291         this.setLookupObject(fieldName + FLD_MIME_SUFFIX,
292                 com.jcorporate.expresso.services.dbobj.MimeTypes.class.getName());
293
294         this.addField(fieldName + FLD_SIZE_SUFFIX, "long", 0, true,
295                 fieldDescription + " File Size");
296
297         this.setReadOnly(fieldName + FLD_FILE_SUFFIX);
298         this.setReadOnly(fieldName + FLD_MIME_SUFFIX);
299         this.setReadOnly(fieldName + FLD_SIZE_SUFFIX);
300     }
301
302     /**
303      * This method is for saving a BLOB field that has been processed by the
304      * DefaultAutoElement object. We have all the information we need because
305      * the file to save, mime types, etc, have all been saved as attributes of
306      * the fieldName specified. Do not call this method if you have not either
307      * set the appropriate attributes yourself or have called
308      * DefaultAutoElement.parseSingleInput().
309      * <p/>
310      * This method also deletes the uploaded temp file upon completion. Create the
311      * File object and call one of the other saveBlob objects yourself if you do
312      * not want this behavior.
313      * </p>
314      *
315      * @param fieldName The field Name to save
316      * @throws DBException If unable to save the file to the database
317      * @throws IllegalStateException if unable to retrieve the appropriate attributes.
318      * @throws IllegalArgumentException if fieldName doesn't exist or is null.
319      * @see com.jcorporate.expresso.services.controller.ui.DefaultAutoElement#parseSingleInput
320      */

321     public void saveBlob(String JavaDoc fieldName) throws DBException {
322         if (fieldName == null) {
323             throw new IllegalArgumentException JavaDoc("Argument fieldName must not be null");
324         }
325
326         DataField myField = this.getDataField(fieldName);
327         if (myField == null) {
328             throw new IllegalArgumentException JavaDoc("Field " + fieldName + " is not defined");
329         }
330
331         String JavaDoc origFileName = (String JavaDoc) myField.getAttribute("origFileName");
332         String JavaDoc localFileName = (String JavaDoc) myField.getAttribute("fileName");
333
334         if (origFileName == null || localFileName == null) {
335             log.error("Unable to retrieve attributes: origFileName = " +
336                     origFileName + " localFileName = " + localFileName);
337
338             throw new IllegalStateException JavaDoc("Unable to DataObject attribtues");
339         }
340
341         File JavaDoc f = new File JavaDoc(localFileName);
342         if (f == null) {
343             log.error("File: " + localFileName + " doesn't appear to exist.");
344             throw new IllegalStateException JavaDoc("Unable to retrieve uploaded file!");
345         }
346
347         int fileSize = (int) f.length();
348         InputStream JavaDoc is;
349         try {
350             is = new FileInputStream JavaDoc(f);
351         } catch (FileNotFoundException JavaDoc ex) {
352             log.error("File: " + localFileName + " doesn't appear to exist.", ex);
353             throw new IllegalStateException JavaDoc("Unable to retrieve uploaded file!");
354         }
355
356         this.saveBlob(fieldName, is, origFileName, fileSize);
357
358         try {
359             is.close();
360             f.delete();
361         } catch (IOException JavaDoc ex) {
362             log.error("Error closing and deleting file " + localFileName, ex);
363         }
364     }
365
366
367     /**
368      * Saves a BLOB field to the database
369      *
370      * @param fieldName the field Name to save
371      * @param value A binary stream to become the value of the new strea,
372      * @param fileName The name of the 'file' to store
373      * @param fileSize The size of the file to save.
374      */

375     public void saveBlob(String JavaDoc fieldName, java.io.InputStream JavaDoc value,
376                          String JavaDoc fileName, int fileSize) throws DBException {
377         if (lf == null) {
378             lf = new LobField();
379         }
380
381         lf.setCriteria(this);
382         try {
383             lf.saveBlob(fieldName, value, fileSize);
384
385         } finally {
386             lf.close();
387         }
388
389         this.setField(fieldName + "_fileName", fileName);
390
391         this.setField(fieldName + "_mimeType",
392                 MimeTypes.getMimeType(fileName,
393                         this.getDataContext()).getField(MimeTypes.FLD_MIMENUMBER));
394         this.setField(fieldName + "_fileSize", fileSize);
395         this.update();
396     }
397
398     /**
399      * Saves a file to the blob field,
400      *
401      * @param fieldName the field name to save to the database
402      * @param value A java.io.InputStream to save into the database
403      * @param fileSize the size of the stream that is getting saved to the database
404      * @throws DBException upon communication error
405      */

406     public void saveBlob(String JavaDoc fieldName, java.io.InputStream JavaDoc value, int fileSize) throws DBException {
407         if (lf == null) {
408             lf = new LobField();
409         }
410
411         lf.setCriteria(this);
412         lf.saveBlob(fieldName, value, fileSize);
413         try {
414             lf.saveBlob(fieldName, value, fileSize);
415         } finally {
416             lf.close();
417         }
418         this.setField(fieldName + "_fileName", "unknown");
419         this.setField(fieldName + "_mimeType", "application/x-unknown");
420         this.setField(fieldName + "_fileSize", fileSize);
421         this.update();
422     }
423
424     /**
425      * Retrieves a BLOB from the database. This functiona allocates a DBConnection
426      * object and all the corresponding input streams. You must process the BLOB
427      * before doing anything else to this particular DBObject, and then call
428      * the release() function to release the DBConnection and close the appropriate
429      * InputStreams.
430      *
431      * @param fieldName The name of the field to retrieve
432      * @return java.io.InputStream the contents of the BLOB field. [May be null]
433      * @throws DBException upon retrieval error
434      */

435     public java.io.InputStream JavaDoc retrieveBlob(String JavaDoc fieldName) throws DBException {
436         if (lf == null) {
437             lf = new LobField();
438         }
439
440         lf.setCriteria(this);
441
442         try {
443             ConfigJdbc jdbcConfig = ConfigManager.getContext(this.getDataContext()).getJdbc();
444             boolean nativeBlob = jdbcConfig.isNativeBlob();
445             if (!nativeBlob) {
446                 return lf.getBlobStream(fieldName);
447             } else {
448                 try {
449                     java.sql.Blob JavaDoc blob = lf.getBlob(fieldName);
450                     if (blob == null) {
451                         throw new DBException("Error getting BLOB object from field " + fieldName);
452                     }
453                     return blob.getBinaryStream();
454                 } catch (SQLException JavaDoc ex) {
455                     throw new DBException("Error getting binary stream from Blob object", ex);
456                 }
457             }
458         } catch (ConfigurationException ex) {
459             throw new DBException("Unable to get 'nativeBlob' setting.", ex);
460         }
461     }
462
463     /**
464      * Release the associated data with the blob fields. Very important that this
465      * is called once you've retrieved/set the BLOB fields.
466      */

467     public void release() {
468         if (lf != null) {
469             lf.close();
470         }
471     }
472
473
474 }
475
Popular Tags