KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > emb > MediaBean


1 /*
2  * JBoss, the OpenSource J2EE webOS
3  *
4  * Distributable under LGPL license.
5  * See terms of license at gnu.org.
6  */

7
8 package javax.emb;
9
10 import java.io.File;
11 import java.io.FileInputStream;
12 import java.io.FileNotFoundException;
13 import java.io.FileOutputStream;
14 import java.io.IOException;
15 import java.io.InputStream;
16 import java.io.OutputStream;
17 import java.io.RandomAccessFile;
18
19 /**
20  * This class implements the Media interface and models media objects that are
21  * transient, immutable, and local. In order to avoid excessive memory use, a
22  * temporary file may be used to store and access the media content while an
23  * instance is alive.
24  *
25  * @version <tt>$Revision: 1.11 $</tt>
26  * @author <a HREF="mailto:ricardoarguello@users.sourceforge.net">Ricardo
27  * Argüello</a>
28  */

29 public class MediaBean implements Media
30 {
31    /** Media name. */
32    private String name;
33
34    /** Media MIME type. */
35    private String mimeType;
36
37    /** Temporary file. */
38    private transient File tempFile;
39
40    /**
41     * This constructor initializes a new instance with content copied from the
42     * given content stream, and the given mime type and name. The given name is
43     * a file name that should be associated with the object. If the given
44     * mimeType is <code>null</code>, one is chosen automatically by
45     * analyzing the given file extension, or <code>Media.MIME_TYPE_UNKNOWN</code>
46     * is assigned in case none can be derived.
47     *
48     * <p>This constructor is suitable for media content regardless of its
49     * size. Please note that the given input stream is closed once the content
50     * is read completely. Also note that a temporary file is used internally to
51     * maintain the content. The implementation tries to delete this file once
52     * the instance is garbage collected, and again once the process dies in
53     * case the former attempt fails.
54     *
55     * @param contentStream media content stream.
56     * @param mimeType media mime type.
57     * @param name media name.
58     * @throws javax.emb.ContentAccessException if something goes wrong during
59     * content transfer.
60     * @throws java.lang.NullPointerException if the given content stream or
61     * name is <code>null</code>.
62     */

63    public MediaBean(InputStream contentStream, String mimeType, String name)
64       throws MediaException
65    {
66       if (contentStream == null || name == null)
67       {
68          throw new NullPointerException();
69       }
70
71       this.name = name;
72
73       if (mimeType != null)
74       {
75          this.mimeType = mimeType;
76       }
77       else
78       {
79          try
80          {
81             // Lookup a mime type given the file extension
82
MediaFormatRegistry.SINGLETON.lookup(getFileExtension(name));
83          }
84          catch (FormatNotFoundException e)
85          {
86             this.mimeType = Media.MIME_TYPE_UNKNOWN;
87          }
88       }
89
90       String tempFilePrefix = getFileName(name);
91       String tempFileSuffix = getFileExtension(name);
92
93       try
94       {
95          // Create the temporary file
96
tempFile = File.createTempFile(tempFilePrefix, tempFileSuffix);
97          tempFile.deleteOnExit();
98
99          // Copy the contents of the content stream to the temporary file
100
OutputStream tempFileStream = new FileOutputStream(tempFile);
101
102          try
103          {
104             int DEFAULT_BUFFER_SIZE = 65536;
105             byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
106             int bytesRead;
107
108             // Copy contentStream to tempFileStream
109
while ((bytesRead = contentStream.read(buffer)) != -1)
110             {
111                tempFileStream.write(buffer, 0, bytesRead);
112             }
113          }
114          catch (IOException e)
115          {
116             // Throwed by OutputStream.write(byte[], int, int);
117
throw new ContentAccessException(e.getMessage());
118          }
119          finally
120          {
121             try
122             {
123                tempFileStream.close();
124             }
125             catch (IOException ignore)
126             {
127             }
128          }
129       }
130       catch (IOException e)
131       {
132          // Throwed by File.createTempFile(String, String);
133
throw new ContentAccessException(e.getMessage());
134       }
135       finally
136       {
137          try
138          {
139             contentStream.close();
140          }
141          catch (IOException ignore)
142          {
143          }
144       }
145    }
146
147    /**
148     * This constructor wraps a new instance around the given media file. The
149     * name property of the receiver is initialized to the name of the given
150     * file (without path information). If the given mimeType is null, one is
151     * chosen automatically by analyzing the file extension, or <code>Media.MIME_TYPE_UNKNOWN</code>
152     * is assigned in case none can be derived.
153     *
154     * This constructor is useful to invoke a media related service on an
155     * existing media file without copying the content of the latter. Please
156     * note that the file is not deleted once an instance referencing it is
157     * garbage collected.
158     *
159     * @param mediaFile a file.
160     * @param mimeType the optional MIME type of the content.
161     * @throws javax.emb.ContentAccessException if something goes wrong during
162     * content transfer, or if the given file is not present or cannot
163     * be accessed.
164     * @throws java.lang.NullPointerException if the given media file is null.
165     */

166    public MediaBean(File mediaFile, String mimeType) throws MediaException
167    {
168       if (mediaFile == null)
169       {
170          throw new NullPointerException();
171       }
172
173       if (!mediaFile.exists())
174       {
175          throw new ContentAccessException("The given file is not present or cannot be accessed.");
176       }
177
178       this.tempFile = mediaFile;
179       this.name = mediaFile.getName();
180
181       if (mimeType != null)
182       {
183          this.mimeType = mimeType;
184       }
185       else
186       {
187          try
188          {
189             // Lookup a mime type given the file extension
190
MediaFormatRegistry.SINGLETON.lookup(getFileExtension(name));
191          }
192          catch (FormatNotFoundException e)
193          {
194             this.mimeType = Media.MIME_TYPE_UNKNOWN;
195          }
196       }
197    }
198
199    /**
200     * @see javax.emb.Media#getContent()
201     */

202    public byte[] getContent() throws MediaException
203    {
204       long size = getSize();
205
206       if (size > Integer.MAX_VALUE)
207       {
208          throw new ContentTooLargeException("Content exceeds maximum Java array size.");
209       }
210
211       return getContent(0, (int) size);
212    }
213
214    /**
215     * @see javax.emb.Media#getFormat()
216     */

217    public MediaFormat getFormat() throws MediaException
218    {
219       String fileExtension = getFileExtension(name);
220       return MediaFormatRegistry.SINGLETON.lookup(fileExtension);
221    }
222
223    /**
224     * @see javax.emb.Media#getHeader()
225     */

226    public MediaHeader getHeader() throws MediaException
227    {
228       return getFormat().extractHeader(getContentStream());
229    }
230
231    /**
232     * @see javax.emb.Media#getMimeType()
233     */

234    public String getMimeType() throws MediaException
235    {
236       return mimeType;
237    }
238
239    /**
240     * @see javax.emb.Media#getName()
241     */

242    public String getName() throws MediaException
243    {
244       return name;
245    }
246
247    /**
248     * @see javax.emb.Media#getProxy()
249     */

250    public Media getProxy() throws MediaException
251    {
252       return getFormat().extractProxy(getContentStream());
253    }
254
255    /**
256     * @see javax.emb.Media#getSize()
257     */

258    public long getSize() throws MediaException
259    {
260       return tempFile.length();
261    }
262
263    /**
264     * @see javax.emb.Media#readContent(long, byte[])
265     */

266    public int readContent(long position, byte[] buffer) throws MediaException
267    {
268       return this.readContent(position, buffer, 0, buffer.length);
269    }
270
271    /**
272     * @see javax.emb.Media#readContent(long, byte[], int, int)
273     */

274    public int readContent(long position, byte[] buffer, int offset, int length)
275       throws MediaException
276    {
277       if (position < 0 || position > getSize())
278       {
279          throw new IndexOutOfBoundsException();
280       }
281
282       if (position < 0)
283       {
284          throw new NegativeArraySizeException();
285       }
286
287       if (buffer == null)
288       {
289          throw new NullPointerException();
290       }
291
292       // TODO: Calculate offset
293

294       int bytesRead = 0;
295
296       try
297       {
298          InputStream contentStream = new FileInputStream(tempFile);
299          long contentPosition = contentStream.skip(position);
300          bytesRead = contentStream.read(buffer, offset, length);
301       }
302       catch (IOException e)
303       {
304          throw new ContentAccessException(e.getMessage());
305       }
306
307       return bytesRead;
308    }
309
310    private byte[] getContent(long position, int length) throws MediaException
311    {
312       if (position < 0 || position > getSize())
313       {
314          throw new IndexOutOfBoundsException();
315       }
316
317       int contentLength;
318
319       if ((getSize() - position) < (long) length)
320       {
321          contentLength = (int) (getSize() - position);
322       }
323       else
324       {
325          contentLength = length;
326       }
327
328       RandomAccessFile randomAccessFile = null;
329
330       try
331       {
332          randomAccessFile = new RandomAccessFile(tempFile, "r");
333
334          byte[] content = new byte[contentLength];
335
336          randomAccessFile.seek(position);
337          randomAccessFile.read(content);
338
339          return content;
340       }
341       catch (FileNotFoundException e)
342       {
343          throw new ContentAccessException(e.getMessage());
344       }
345       catch (IOException e)
346       {
347          throw new ContentAccessException(e.getMessage());
348       }
349       finally
350       {
351          if (randomAccessFile != null)
352          {
353             try
354             {
355                randomAccessFile.close();
356             }
357             catch (IOException ignore)
358             {
359             }
360          }
361       }
362    }
363
364    /**
365     * Returns an input stream on the receiver's content that can be utilized to
366     * read said content in a stream I/O fashion.
367     *
368     * <p>This method can be used instead of the generic block access to
369     * content as defined in the <code>Media</code> interface to reduce memory
370     * fragmentation in order to reduce garbage collection.
371     *
372     * @return content stream.
373     * @throws javax.emb.ContentAccessException if the content cannot be
374     * accessed.
375     */

376    private InputStream getContentStream() throws MediaException
377    {
378       try
379       {
380          return new FileInputStream(tempFile);
381       }
382       catch (FileNotFoundException e)
383       {
384          throw new ContentAccessException(e.getMessage());
385       }
386    }
387
388    private static String getFileName(String name)
389    {
390       int lastDotPosition = name.lastIndexOf('.');
391
392       if (lastDotPosition == -1)
393       {
394          return name;
395       }
396       else
397       {
398          return name.substring(0, lastDotPosition);
399       }
400    }
401
402    private static String getFileExtension(String name)
403    {
404       int lastDotPosition = name.lastIndexOf('.');
405
406       if (lastDotPosition == -1)
407       {
408          return null;
409       }
410       else
411       {
412          return name.substring(lastDotPosition + 1);
413       }
414    }
415 }
Popular Tags