1
2
3
4
5 package org.rcfaces.core.internal.webapp;
6
7 import java.io.IOException;
8 import java.security.MessageDigest;
9 import java.text.DateFormat;
10 import java.text.ParseException;
11 import java.text.SimpleDateFormat;
12 import java.util.Date;
13 import java.util.HashSet;
14 import java.util.Locale;
15 import java.util.Map;
16 import java.util.Set;
17
18 import javax.faces.context.FacesContext;
19 import javax.servlet.ServletConfig;
20 import javax.servlet.ServletException;
21 import javax.servlet.http.HttpServlet;
22 import javax.servlet.http.HttpServletRequest;
23 import javax.servlet.http.HttpServletResponse;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27 import org.rcfaces.core.internal.Constants;
28 import org.rcfaces.core.internal.lang.StringAppender;
29 import org.rcfaces.core.internal.util.Base64;
30 import org.rcfaces.core.internal.util.MessageDigestSelector;
31
32
33
34
35
36
37 public class ExtendedHttpServlet extends HttpServlet {
38 private static final long serialVersionUID = -8822434295699331135L;
39
40 private static final Log LOG = LogFactory.getLog(ExtendedHttpServlet.class);
41
42 public static final String HTTP_CONTENT_ENCODING = "Content-Encoding";
43
44 public static final String HTTP_ACCEPT_ENCODING = "Accept-Encoding";
45
46 public static final String HTTP_LAST_MODIFIED = "Last-Modified";
47
48 public static final String HTTP_ETAG = "ETag";
49
50 public static final String HTTP_HASH = "Content-MD5";
51
52 public static final String HTTP_EXPIRES = "Expires";
53
54 public static final String HTTP_CACHE_CONTROL = "Cache-Control";
55
56 public static final String HTTP_IF_MODIFIED_SINCE = "If-Modified-Since";
57
58 public static final String HTTP_IF_NONE_MATCH = "If-None-Match";
59
60 public static final String HTTP_IF_NOT_HASH = "If-Not-Hash";
61
62 public static final String HTTP_VARY = "Vary";
63
64 public static final String HTTP_PRAGMA = "Pragma";
65
66 public static final String ACCEPT_ENCODING = "Accept-Encoding";
67
68 public static final String USER_AGENT = "User-Agent";
69
70 public static final String GZIP_CONTENT_ENCODING = "gzip";
71
72 public static final String HEAD_HTTP_METHOD = "HEAD";
73
74 public static final DateFormat HTTP_DATE_FORMATS[] = {
75 new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US),
76 new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US),
77 new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US) };
78
79 public static final String CSS_MIME_TYPE = "text/css";
80
81 public static final String HTML_MIME_TYPE = "text/html";
82
83 public static final String JAVASCRIPT_MIME_TYPE = "text/javascript";
84
85 public static final String TEXT_PLAIN_MIME_TYPE = "text/plain";
86
87 private static Set useGZIPExtensions = new HashSet();
88 static {
89 useGZIPExtensions.add(CSS_MIME_TYPE);
90 useGZIPExtensions.add(HTML_MIME_TYPE);
91 useGZIPExtensions.add(JAVASCRIPT_MIME_TYPE);
92 useGZIPExtensions.add(TEXT_PLAIN_MIME_TYPE);
93 }
94
95 public static final boolean isMimeTypeSupportGZip(String mimeType) {
96 if (mimeType == null || mimeType.length() < 1) {
97 return false;
98 }
99
100 int idx = mimeType.indexOf(";");
101 if (idx >= 0) {
102 mimeType = mimeType.substring(0, idx);
103 }
104
105 mimeType = mimeType.trim().toLowerCase();
106
107 return useGZIPExtensions.contains(mimeType);
108 }
109
110 public static final boolean hasGzipSupport(HttpServletRequest request) {
111 return hasGzipSupport(request.getHeader(HTTP_ACCEPT_ENCODING));
112 }
113
114 public static boolean hasGzipSupport(FacesContext facesContext) {
115 Map requestMap = facesContext.getExternalContext()
116 .getRequestHeaderMap();
117 String contentEncoding = (String) requestMap.get(HTTP_ACCEPT_ENCODING);
118
119 return hasGzipSupport(contentEncoding);
120 }
121
122 private static final boolean hasGzipSupport(String encoding) {
123 if (encoding == null) {
124 return false;
125 }
126
127 if (encoding.toLowerCase().indexOf(GZIP_CONTENT_ENCODING) >= 0) {
128 if (LOG.isDebugEnabled()) {
129 LOG.debug("Detected GZIP content encoding. (encoding="
130 + encoding + ")");
131 }
132
133 return true;
134 }
135
136 if (LOG.isDebugEnabled()) {
137 LOG.debug("GZIP content encoding not accepted ! (encoding="
138 + encoding + ")");
139 }
140
141 return false;
142 }
143
144 public static final String computeETag(byte[] buffer) {
145 MessageDigest messageDigest = MessageDigestSelector
146 .getInstance(Constants.ETAG_DIGEST_ALGORITHMS);
147
148 byte digest[] = messageDigest.digest(buffer);
149
150 StringAppender sb = new StringAppender(digest.length * 2 + 16);
151 sb.append("\"rcfaces:");
152 for (int i = 0; i < digest.length; i++) {
153 int v = digest[i] & 0xff;
154 if (v < 16) {
155 sb.append('0');
156 }
157 sb.append(Integer.toHexString(v));
158 }
159
160 sb.append(':');
161 sb.append(Integer.toHexString(buffer.length));
162
163 sb.append('\"');
164 return sb.toString();
165 }
166
167 public static final String computeHash(byte[] buffer) {
168 MessageDigest messageDigest = MessageDigestSelector
169 .getInstance(Constants.HASH_DIGEST_ALGORITHMS);
170
171
172 byte digest[] = messageDigest.digest(buffer);
173
174 return Base64.encodeBytes(digest, Base64.DONT_BREAK_LINES);
175
176 }
177
178 public static final Date parseHttpDate(String date) throws ParseException {
179
180 ParseException ex = null;
181 for (int i = 0; i < HTTP_DATE_FORMATS.length; i++) {
182 try {
183 Date d = HTTP_DATE_FORMATS[i].parse(date);
184
185 if (LOG.isDebugEnabled()) {
186 LOG.debug("ParseHttpDate returns '" + d + "' for string '"
187 + date + "'.");
188 }
189
190 return d;
191
192 } catch (ParseException e) {
193 ex = e;
194 }
195 }
196
197 if (ex == null) {
198 if (LOG.isDebugEnabled()) {
199 LOG.debug("ParseHttpDate has not recognized date '" + date
200 + "'.");
201 }
202
203 return null;
204 }
205
206 LOG.error("ParseHttpDate has not recognized date '" + date + "'.", ex);
207
208 throw ex;
209 }
210
211 protected final String getParameter(String name) {
212 return getParameter(getServletConfig(), name);
213 }
214
215 public static final String getParameter(ServletConfig config, String name) {
216 String initParameter = config.getInitParameter(name);
217 if (initParameter != null) {
218 return initParameter;
219 }
220
221 initParameter = config.getServletContext().getInitParameter(name);
222 return initParameter;
223 }
224
225 public static final void setNoCache(HttpServletResponse response) {
226
227 response.setHeader(HTTP_PRAGMA, "no-cache");
228
229
230 response.setHeader(HTTP_CACHE_CONTROL,
231 "no-cache, no-store, must-revalidate");
232
233
234 response.addHeader(HTTP_CACHE_CONTROL, "post-check=0, pre-check=0");
235
236 response.setDateHeader(HTTP_EXPIRES, 0);
237 response.setDateHeader(HTTP_LAST_MODIFIED, System.currentTimeMillis());
238 }
239
240 public static void setVaryAcceptEncoding(HttpServletResponse response) {
241 response.setHeader(HTTP_VARY, ACCEPT_ENCODING);
242
243 if (LOG.isDebugEnabled()) {
244 LOG.debug("Set Vary accept encoding.");
245 }
246 }
247
248 public static void setVaryUserAgent(HttpServletResponse response) {
249 response.setHeader(HTTP_VARY, USER_AGENT);
250
251 if (LOG.isDebugEnabled()) {
252 LOG.debug("Set Vary user agent.");
253 }
254 }
255
256 public static void setGzipContentEncoding(HttpServletResponse response,
257 boolean declareVaryAcceptEncoding) {
258 response.setHeader(HTTP_CONTENT_ENCODING, GZIP_CONTENT_ENCODING);
259 if (declareVaryAcceptEncoding) {
260 response.setHeader(HTTP_VARY, ACCEPT_ENCODING);
261 }
262
263 if (LOG.isDebugEnabled()) {
264 LOG.debug("Set GZIP content encoding.");
265 }
266 }
267
268 protected void service(HttpServletRequest req, HttpServletResponse resp)
269 throws ServletException, IOException {
270 try {
271 if (LOG.isTraceEnabled()) {
272 LOG.trace("Process http request requestURI='"
273 + req.getRequestURI() + "'.");
274 }
275
276 super.service(req, resp);
277
278 if (LOG.isTraceEnabled()) {
279 LOG.trace("Http request processed requestURI='"
280 + req.getRequestURI() + "'. (response contentType="
281 + resp.getContentType() + ")");
282 }
283
284 } catch (RuntimeException ex) {
285 LOG.error("Exception request=" + req.getRequestURI(), ex);
286
287 } catch (Error ex) {
288 LOG.error("Error request=" + req.getRequestURI(), ex);
289 }
290 }
291
292 }