View Javadoc
1   /*
2    * @(#)DownloadResponse.java	1.8 07/03/15
3    * 
4    * Copyright (c) 2006 Sun Microsystems, Inc. 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 are met:
8    *
9    * -Redistribution of source code must retain the above copyright notice, this
10   *  list of conditions and the following disclaimer.
11   *
12   * -Redistribution in binary form must reproduce the above copyright notice,
13   *  this list of conditions and the following disclaimer in the documentation
14   *  and/or other materials provided with the distribution.
15   *
16   * Neither the name of Sun Microsystems, Inc. or the names of contributors may
17   * be used to endorse or promote products derived from this software without
18   * specific prior written permission.
19   *
20   * This software is provided "AS IS," without a warranty of any kind. ALL
21   * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
22   * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
23   * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
24   * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
25   * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
26   * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
27   * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
28   * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
29   * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
30   * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31   *
32   * You acknowledge that this software is not designed, licensed or intended
33   * for use in the design, construction, operation or maintenance of any
34   * nuclear facility.
35   */
36  
37  package jnlp.sample.servlet;
38  
39  import javax.servlet.http.HttpServletResponse;
40  import java.io.BufferedInputStream;
41  import java.io.ByteArrayInputStream;
42  import java.io.File;
43  import java.io.FileInputStream;
44  import java.io.IOException;
45  import java.io.InputStream;
46  import java.io.OutputStream;
47  import java.io.PrintWriter;
48  import java.net.URL;
49  import java.util.Date;
50  import java.util.MissingResourceException;
51  
52  /**
53   * A class used to encapsulate a file response, and
54   * factory methods to create some common types.
55   */
56  abstract public class DownloadResponse
57  {
58      private static final String HEADER_LASTMOD = "Last-Modified";
59  
60      private static final String HEADER_JNLP_VERSION = "x-java-jnlp-version-id";
61  
62      private static final String JNLP_ERROR_MIMETYPE = "application/x-java-jnlp-error";
63  
64      public static final int STS_00_OK = 0;
65  
66      public static final int ERR_10_NO_RESOURCE = 10;
67  
68      public static final int ERR_11_NO_VERSION = 11;
69  
70      public static final int ERR_20_UNSUP_OS = 20;
71  
72      public static final int ERR_21_UNSUP_ARCH = 21;
73  
74      public static final int ERR_22_UNSUP_LOCALE = 22;
75  
76      public static final int ERR_23_UNSUP_JRE = 23;
77  
78      public static final int ERR_99_UNKNOWN = 99;
79  
80      // HTTP Compression RFC 2616 : Standard headers
81      public static final String CONTENT_ENCODING = "content-encoding";
82  
83      // HTTP Compression RFC 2616 : Standard header for HTTP/Pack200 Compression
84      public static final String GZIP_ENCODING = "gzip";
85  
86      public static final String PACK200_GZIP_ENCODING = "pack200-gzip";
87  
88      public DownloadResponse()
89      { /* do nothing */ }
90  
91      public String toString()
92      {
93          return getClass().getName();
94      }
95  
96      /**
97       * Post information to an HttpResponse
98       */
99      abstract void sendRespond( HttpServletResponse response )
100         throws IOException;
101 
102     /**
103      * Factory methods for error responses
104      */
105     static DownloadResponse getNotFoundResponse()
106     {
107         return new NotFoundResponse();
108     }
109 
110     static DownloadResponse getNoContentResponse()
111     {
112         return new NotFoundResponse();
113     }
114 
115     static DownloadResponse getJnlpErrorResponse( int jnlpErrorCode )
116     {
117         return new JnlpErrorResponse( jnlpErrorCode );
118     }
119 
120     /**
121      * Factory method for file download responses
122      */
123 
124     static DownloadResponse getNotModifiedResponse()
125     {
126         return new NotModifiedResponse();
127     }
128 
129     static DownloadResponse getHeadRequestResponse( String mimeType, String versionId, long lastModified,
130                                                     int contentLength )
131     {
132         return new HeadRequestResponse( mimeType, versionId, lastModified, contentLength );
133     }
134 
135     static DownloadResponse getFileDownloadResponse( byte[] content, String mimeType, long timestamp, String versionId )
136     {
137         return new ByteArrayFileDownloadResponse( content, mimeType, versionId, timestamp );
138     }
139 
140     static DownloadResponse getFileDownloadResponse( URL resource, String mimeType, long timestamp, String versionId )
141     {
142         return new ResourceFileDownloadResponse( resource, mimeType, versionId, timestamp );
143     }
144 
145     static DownloadResponse getFileDownloadResponse( File file, String mimeType, long timestamp, String versionId )
146     {
147         return new DiskFileDownloadResponse( file, mimeType, versionId, timestamp );
148     }
149 
150     //
151     // Private classes implementing the various types
152     //
153 
154     static private class NotModifiedResponse
155         extends DownloadResponse
156     {
157         public void sendRespond( HttpServletResponse response )
158             throws IOException
159         {
160             response.sendError( HttpServletResponse.SC_NOT_MODIFIED );
161         }
162     }
163 
164     static private class NotFoundResponse
165         extends DownloadResponse
166     {
167         public void sendRespond( HttpServletResponse response )
168             throws IOException
169         {
170             response.sendError( HttpServletResponse.SC_NOT_FOUND );
171         }
172     }
173 
174     static private class NoContentResponse
175         extends DownloadResponse
176     {
177         public void sendRespond( HttpServletResponse response )
178             throws IOException
179         {
180             response.sendError( HttpServletResponse.SC_NO_CONTENT );
181         }
182     }
183 
184     static private class HeadRequestResponse
185         extends DownloadResponse
186     {
187         private String _mimeType;
188 
189         private String _versionId;
190 
191         private long _lastModified;
192 
193         private int _contentLength;
194 
195         HeadRequestResponse( String mimeType, String versionId, long lastModified, int contentLength )
196         {
197             _mimeType = mimeType;
198             _versionId = versionId;
199             _lastModified = lastModified;
200             _contentLength = contentLength;
201         }
202 
203         /**
204          * Post information to an HttpResponse
205          */
206         public void sendRespond( HttpServletResponse response )
207             throws IOException
208         {
209             // Set header information
210             response.setContentType( _mimeType );
211             response.setContentLength( _contentLength );
212             if ( _versionId != null )
213             {
214                 response.setHeader( HEADER_JNLP_VERSION, _versionId );
215             }
216             if ( _lastModified != 0 )
217             {
218                 response.setDateHeader( HEADER_LASTMOD, _lastModified );
219             }
220             response.sendError( HttpServletResponse.SC_OK );
221         }
222     }
223 
224     static public class JnlpErrorResponse
225         extends DownloadResponse
226     {
227         private String _message;
228 
229         public JnlpErrorResponse( int jnlpErrorCode )
230         {
231             String msg = Integer.toString( jnlpErrorCode );
232             String dsc = "No description";
233             try
234             {
235                 dsc = JnlpDownloadServlet.getResourceBundle().getString( "servlet.jnlp.err." + msg );
236             }
237             catch ( MissingResourceException mre )
238             { /* ignore */}
239             _message = msg + " " + dsc;
240         }
241 
242         public void sendRespond( HttpServletResponse response )
243             throws IOException
244         {
245             response.setContentType( JNLP_ERROR_MIMETYPE );
246             PrintWriter pw = response.getWriter();
247             pw.println( _message );
248         }
249 
250         ;
251 
252         public String toString()
253         {
254             return super.toString() + "[" + _message + "]";
255         }
256     }
257 
258     static private abstract class FileDownloadResponse
259         extends DownloadResponse
260     {
261         private String _mimeType;
262 
263         private String _versionId;
264 
265         private long _lastModified;
266 
267         private String _fileName;
268 
269         FileDownloadResponse( String mimeType, String versionId, long lastModified )
270         {
271             _mimeType = mimeType;
272             _versionId = versionId;
273             _lastModified = lastModified;
274             _fileName = null;
275         }
276 
277         FileDownloadResponse( String mimeType, String versionId, long lastModified, String fileName )
278         {
279             _mimeType = mimeType;
280             _versionId = versionId;
281             _lastModified = lastModified;
282             _fileName = fileName;
283         }
284 
285 
286         /**
287          * Information about response
288          */
289         String getMimeType()
290         {
291             return _mimeType;
292         }
293 
294         String getVersionId()
295         {
296             return _versionId;
297         }
298 
299         long getLastModified()
300         {
301             return _lastModified;
302         }
303 
304         abstract int getContentLength()
305             throws IOException;
306 
307         abstract InputStream getContent()
308             throws IOException;
309 
310         /**
311          * Post information to an HttpResponse
312          */
313         public void sendRespond( HttpServletResponse response )
314             throws IOException
315         {
316             // Set header information
317             response.setContentType( getMimeType() );
318             response.setContentLength( getContentLength() );
319             if ( getVersionId() != null )
320             {
321                 response.setHeader( HEADER_JNLP_VERSION, getVersionId() );
322             }
323             if ( getLastModified() != 0 )
324             {
325                 response.setDateHeader( HEADER_LASTMOD, getLastModified() );
326             }
327             if ( _fileName != null )
328             {
329 
330                 if ( _fileName.endsWith( ".pack.gz" ) )
331                 {
332                     response.setHeader( CONTENT_ENCODING, PACK200_GZIP_ENCODING );
333                 }
334                 else if ( _fileName.endsWith( ".gz" ) )
335                 {
336                     response.setHeader( CONTENT_ENCODING, GZIP_ENCODING );
337                 }
338                 else
339                 {
340                     response.setHeader( CONTENT_ENCODING, null );
341                 }
342             }
343 
344             // Send contents
345             InputStream in = getContent();
346             OutputStream out = response.getOutputStream();
347             try
348             {
349                 byte[] bytes = new byte[32 * 1024];
350                 int read;
351                 while ( ( read = in.read( bytes ) ) != -1 )
352                 {
353                     out.write( bytes, 0, read );
354                 }
355             }
356             finally
357             {
358                 if ( in != null )
359                 {
360                     in.close();
361                 }
362             }
363         }
364 
365         protected String getArgString()
366         {
367             long length = 0;
368             try
369             {
370                 length = getContentLength();
371             }
372             catch ( IOException ioe )
373             { /* ignore */ }
374             return "Mimetype=" + getMimeType() + " VersionId=" + getVersionId() + " Timestamp=" +
375                 new Date( getLastModified() ) + " Length=" + length;
376         }
377     }
378 
379     static private class ByteArrayFileDownloadResponse
380         extends FileDownloadResponse
381     {
382         private byte[] _content;
383 
384         ByteArrayFileDownloadResponse( byte[] content, String mimeType, String versionId, long lastModified )
385         {
386             super( mimeType, versionId, lastModified );
387             _content = content;
388         }
389 
390         int getContentLength()
391         {
392             return _content.length;
393         }
394 
395         InputStream getContent()
396         {
397             return new ByteArrayInputStream( _content );
398         }
399 
400         public String toString()
401         {
402             return super.toString() + "[ " + getArgString() + "]";
403         }
404     }
405 
406     static private class ResourceFileDownloadResponse
407         extends FileDownloadResponse
408     {
409         URL _url;
410 
411         ResourceFileDownloadResponse( URL url, String mimeType, String versionId, long lastModified )
412         {
413             super( mimeType, versionId, lastModified, url.toString() );
414             _url = url;
415         }
416 
417         int getContentLength()
418             throws IOException
419         {
420             return _url.openConnection().getContentLength();
421         }
422 
423         InputStream getContent()
424             throws IOException
425         {
426             return _url.openConnection().getInputStream();
427         }
428 
429         public String toString()
430         {
431             return super.toString() + "[ " + getArgString() + "]";
432         }
433     }
434 
435     static private class DiskFileDownloadResponse
436         extends FileDownloadResponse
437     {
438         private File _file;
439 
440         DiskFileDownloadResponse( File file, String mimeType, String versionId, long lastModified )
441         {
442             super( mimeType, versionId, lastModified, file.getName() );
443             _file = file;
444         }
445 
446         int getContentLength()
447             throws IOException
448         {
449             return (int) _file.length();
450         }
451 
452         InputStream getContent()
453             throws IOException
454         {
455             return new BufferedInputStream( new FileInputStream( _file ) );
456         }
457 
458         public String toString()
459         {
460             return super.toString() + "[ " + getArgString() + "]";
461         }
462     }
463 }
464 
465 
466