View Javadoc
1   /*
2    * @(#)JnlpResource.java	1.8 05/11/17
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.ServletContext;
40  import java.io.File;
41  import java.io.IOException;
42  import java.net.URL;
43  import java.net.URLConnection;
44  import java.util.Date;
45  
46  /**
47   * A JnlpResource encapsulate the information about a resource that is
48   * needed to process a JNLP Download Request.
49   * <p/>
50   * The pattern matching arguments are: name, version-id, os, arch, and locale.
51   * <p/>
52   * The outgoing arguments are:
53   * - path to resource in (WAR File)
54   * - product version-id (Version-id to return or null. Typically same as version-id above)
55   * - mime-type for content
56   * - lastModified date of WAR file resource
57   */
58  public class JnlpResource
59  {
60      private static final String JNLP_MIME_TYPE = "application/x-java-jnlp-file";
61  
62      private static final String JAR_MIME_TYPE = "application/x-java-archive";
63  
64      private static final String JAR_MIME_TYPE_NEW = "application/java-archive";
65  
66      // Default extension for the JNLP file
67      private static final String JNLP_EXTENSION = ".jnlp";
68  
69      private static final String JAR_EXTENSION = ".jar";
70  
71      private static String _jnlpExtension = JNLP_EXTENSION;
72  
73      private static String _jarExtension = JAR_EXTENSION;
74  
75      public static void setDefaultExtensions( String jnlpExtension, String jarExtension )
76      {
77          if ( jnlpExtension != null && jnlpExtension.length() > 0 )
78          {
79              if ( !jnlpExtension.startsWith( "." ) )
80              {
81                  jnlpExtension = "." + jnlpExtension;
82              }
83              _jnlpExtension = jnlpExtension;
84          }
85          if ( jarExtension != null && jarExtension.length() > 0 )
86          {
87              if ( !jarExtension.startsWith( "." ) )
88              {
89                  jarExtension = "." + jarExtension;
90              }
91              _jarExtension = jarExtension;
92          }
93      }
94  
95      /* Pattern matching arguments */
96      private String _name;      // Name of resource with path (this is the same as path for non-version based)
97  
98      private String _versionId;    // Version-id for resource, or null if none
99  
100     private String[] _osList;     // List of OSes for which resource should be returned
101 
102     private String[] _archList;   // List of architectures for which the resource should be returned
103 
104     private String[] _localeList; // List of locales for which the resource should be returned
105 
106     /* Information used for reply */
107     private String _path;            // Path to resource in WAR file (unique)
108 
109     private URL _resource;        // URL to resource in WAR file (unique - same as above really)
110 
111     private long _lastModified;    // Last modified in WAR file
112 
113     private String _mimeType;        // Mime-type for resource
114 
115     private String _returnVersionId; // Version Id to return
116 
117     private String _encoding;        // Accept encoding
118 
119     public JnlpResource( ServletContext context, String path )
120     {
121         this( context, null, null, null, null, null, path, null );
122     }
123 
124     public JnlpResource( ServletContext context, String name, String versionId, String[] osList, String[] archList,
125                          String[] localeList, String path, String returnVersionId )
126     {
127         this( context, name, versionId, osList, archList, localeList, path, returnVersionId, null );
128     }
129 
130     public JnlpResource( ServletContext context, String name, String versionId, String[] osList, String[] archList,
131                          String[] localeList, String path, String returnVersionId, String encoding )
132     {
133         // Matching arguments
134         _encoding = encoding;
135         _name = name;
136         _versionId = versionId;
137         _osList = osList;
138         _archList = archList;
139         _localeList = localeList;
140 
141         _returnVersionId = returnVersionId;
142 
143         /* Check for existance and get last modified timestamp */
144         try
145         {
146             String orig_path = path.trim();
147             String search_path = orig_path;
148             _resource = context.getResource( orig_path );
149             _mimeType = getMimeType( context, orig_path );
150             if ( _resource != null )
151             {
152 
153                 boolean found = false;
154                 // pack200 compression
155                 if ( encoding != null && _mimeType != null &&
156                     ( _mimeType.compareTo( JAR_MIME_TYPE ) == 0 || _mimeType.compareTo( JAR_MIME_TYPE_NEW ) == 0 ) &&
157                     encoding.toLowerCase().contains( DownloadResponse.PACK200_GZIP_ENCODING ) )
158                 {
159                     search_path = orig_path + ".pack.gz";
160                     _resource = context.getResource( search_path );
161                     // Get last modified time
162                     if ( _resource != null )
163                     {
164                         _lastModified = getLastModified( context, _resource, search_path );
165                         if ( _lastModified != 0 )
166                         {
167                             _path = search_path;
168                             found = true;
169                         }
170                         else
171                         {
172                             _resource = null;
173                         }
174                     }
175                 }
176 
177                 // gzip compression
178                 if ( !found && encoding != null &&
179                     encoding.toLowerCase().contains( DownloadResponse.GZIP_ENCODING ) )
180                 {
181                     search_path = orig_path + ".gz";
182                     _resource = context.getResource( search_path );
183                     // Get last modified time
184                     if ( _resource != null )
185                     {
186                         _lastModified = getLastModified( context, _resource, search_path );
187                         if ( _lastModified != 0 )
188                         {
189                             _path = search_path;
190                             found = true;
191                         }
192                         else
193                         {
194                             _resource = null;
195                         }
196                     }
197                 }
198 
199                 if ( !found )
200                 {
201                     // no compression
202                     search_path = orig_path;
203                     _resource = context.getResource( search_path );
204                     // Get last modified time
205                     if ( _resource != null )
206                     {
207                         _lastModified = getLastModified( context, _resource, search_path );
208                         if ( _lastModified != 0 )
209                         {
210                             _path = search_path;
211                             found = true;
212                         }
213                         else
214                         {
215                             _resource = null;
216                         }
217                     }
218                 }
219             }
220         }
221         catch ( IOException ioe )
222         {
223             _resource = null;
224         }
225     }
226 
227     long getLastModified( ServletContext context, URL resource, String path )
228     {
229         long lastModified = 0;
230         URLConnection conn;
231         try
232         {
233             // Get last modified time
234             conn = resource.openConnection();
235             lastModified = conn.getLastModified();
236         }
237         catch ( Exception e )
238         {
239             // do nothing
240         }
241 
242         if ( lastModified == 0 )
243         {
244             // Arguably a bug in the JRE will not set the lastModified for file URLs, and
245             // always return 0. This is a workaround for that problem.
246             String filepath = context.getRealPath( path );
247             if ( filepath != null )
248             {
249                 File f = new File( filepath );
250                 if ( f.exists() )
251                 {
252                     lastModified = f.lastModified();
253                 }
254             }
255         }
256         return lastModified;
257     }
258 
259     /* Get resource specific attributes */
260     public String getPath()
261     {
262         return _path;
263     }
264 
265     public URL getResource()
266     {
267         return _resource;
268     }
269 
270     public String getMimeType()
271     {
272         return _mimeType;
273     }
274 
275     public long getLastModified()
276     {
277         return _lastModified;
278     }
279 
280     public boolean exists()
281     {
282         return _resource != null;
283     }
284 
285     public boolean isJnlpFile()
286     {
287         return _path.endsWith( _jnlpExtension );
288     }
289 
290     public boolean isJarFile()
291     {
292         return _path.endsWith( _jarExtension );
293     }
294 
295     /* Get JNLP version specific attributes */
296     public String getName()
297     {
298         return _name;
299     }
300 
301     public String getVersionId()
302     {
303         return _versionId;
304     }
305 
306     public String[] getOSList()
307     {
308         return _osList;
309     }
310 
311     public String[] getArchList()
312     {
313         return _archList;
314     }
315 
316     public String[] getLocaleList()
317     {
318         return _localeList;
319     }
320 
321     public String getReturnVersionId()
322     {
323         return _returnVersionId;
324     }
325 
326     private String getMimeType( ServletContext context, String path )
327     {
328         String mimeType = context.getMimeType( path );
329         if ( mimeType != null )
330         {
331             return mimeType;
332         }
333         if ( path.endsWith( _jnlpExtension ) )
334         {
335             return JNLP_MIME_TYPE;
336         }
337         if ( path.endsWith( _jarExtension ) )
338         {
339             return JAR_MIME_TYPE;
340         }
341         return "application/unknown";
342     }
343 
344     /**
345      * Print info about an entry
346      */
347     public String toString()
348     {
349         return "JnlpResource[WAR Path: " + _path + showEntry( " versionId=", _versionId ) +
350             showEntry( " name=", _name ) + " lastModified=" + new Date( _lastModified ) +
351             showEntry( " osList=", _osList ) + showEntry( " archList=", _archList ) +
352             showEntry( " localeList=", _localeList ) + "]" + showEntry( " returnVersionId=", _returnVersionId ) + "]";
353 
354     }
355 
356     private String showEntry( String msg, String value )
357     {
358         if ( value == null )
359         {
360             return "";
361         }
362         return msg + value;
363     }
364 
365     private String showEntry( String msg, String[] value )
366     {
367         if ( value == null )
368         {
369             return "";
370         }
371         return msg + java.util.Arrays.asList( value ).toString();
372     }
373 }
374 
375 
376 
377