1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.myfaces.commons.resourcehandler.resource;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.net.JarURLConnection;
24 import java.net.URL;
25 import java.net.URLConnection;
26 import java.text.ParseException;
27 import java.text.SimpleDateFormat;
28 import java.util.Date;
29 import java.util.Locale;
30 import java.util.TimeZone;
31
32 public class ResourceLoaderUtils
33 {
34 // TODO: In tomcat and jetty it is implemented a Flyweight pattern when converting
35 // date headers. For now it is better keep this stuff simple.
36 private static final String HTTP_RESPONSE_DATE_HEADER =
37 "EEE, dd MMM yyyy HH:mm:ss zzz";
38
39 private static final String[] HTTP_REQUEST_DATE_HEADER = {
40 "EEE, dd MMM yyyy HH:mm:ss zzz", "EEEEEE, dd-MMM-yy HH:mm:ss zzz",
41 "EEE MMMM d HH:mm:ss yyyy" };
42
43 private static TimeZone __GMT = TimeZone.getTimeZone("GMT");
44
45 public static String formatDateHeader(long value)
46 {
47 SimpleDateFormat format = new SimpleDateFormat(
48 HTTP_RESPONSE_DATE_HEADER,
49 Locale.US);
50 format.setTimeZone(__GMT);
51 return format.format(new Date(value));
52 }
53
54 public static Long parseDateHeader(String value)
55 {
56 Date date = null;
57 for (int i = 0; (date == null) && (i < HTTP_REQUEST_DATE_HEADER.length); i++)
58 {
59 try
60 {
61 SimpleDateFormat format = new SimpleDateFormat(
62 HTTP_REQUEST_DATE_HEADER[i], Locale.US);
63 format.setTimeZone(__GMT);
64 date = format.parse(value);
65 }
66 catch (ParseException e)
67 {
68 ;
69 }
70 }
71 if (date == null)
72 {
73 return null;
74 }
75 return new Long(date.getTime());
76 }
77
78 //Taken from trinidad URLUtils
79 public static long getResourceLastModified(URL url) throws IOException
80 {
81 if ("file".equals(url.getProtocol()))
82 {
83 String externalForm = url.toExternalForm();
84 // Remove the "file:"
85 File file = new File(externalForm.substring(5));
86
87 return file.lastModified();
88 }
89 else
90 {
91 return getResourceLastModified(url.openConnection());
92 }
93 }
94
95 //Taken from trinidad URLUtils
96 public static long getResourceLastModified(URLConnection connection) throws IOException
97 {
98 long modified;
99 if (connection instanceof JarURLConnection)
100 {
101 // The following hack is required to work-around a JDK bug.
102 // getLastModified() on a JAR entry URL delegates to the actual JAR file
103 // rather than the JAR entry.
104 // This opens internally, and does not close, an input stream to the JAR
105 // file.
106 // In turn, you cannot close it by yourself, because it's internal.
107 // The work-around is to get the modification date of the JAR file
108 // manually,
109 // and then close that connection again.
110
111 URL jarFileUrl = ((JarURLConnection) connection).getJarFileURL();
112 URLConnection jarFileConnection = jarFileUrl.openConnection();
113
114 try
115 {
116 modified = jarFileConnection.getLastModified();
117 }
118 finally
119 {
120 try
121 {
122 jarFileConnection.getInputStream().close();
123 }
124 catch (Exception exception)
125 {
126 // Ignored
127 }
128 }
129 }
130 else
131 {
132 modified = connection.getLastModified();
133 }
134
135 return modified;
136 }
137 }