1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.renderkit.html.util;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.apache.myfaces.shared_tomahawk.config.MyfacesConfig;
24 import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
25 import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
26 import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlResponseWriterImpl;
27 import org.apache.myfaces.shared_tomahawk.util.ClassUtils;
28
29 import javax.faces.FacesException;
30 import javax.faces.context.FacesContext;
31 import javax.faces.context.ResponseWriter;
32 import javax.servlet.ServletContext;
33 import javax.servlet.http.HttpServletRequest;
34 import javax.servlet.http.HttpServletResponse;
35 import java.io.IOException;
36 import java.io.UnsupportedEncodingException;
37 import java.net.URLEncoder;
38 import java.util.Map;
39
40
41
42
43
44 public class NonBufferingAddResource implements AddResource {
45
46 protected static final String PATH_SEPARATOR = "/";
47 protected String _contextPath;
48
49 private static final String RESOURCES_CACHE_KEY = AddResource.class.getName() + ".CACHE_KEY";
50
51 private String resourceVirtualPath;
52
53 protected Log log = LogFactory.getLog(NonBufferingAddResource.class);
54
55
56
57
58
59 public void setContextPath(String contextPath)
60 {
61 if (_contextPath != null)
62 {
63 throw new SecurityException("context path already set");
64 }
65
66 _contextPath = contextPath;
67 }
68
69
70
71
72
73
74
75
76
77
78
79
80 public void addJavaScriptHere(FacesContext context, Class myfacesCustomComponent,
81 String resourceName) throws IOException
82 {
83 addJavaScriptHere(context, new MyFacesResourceHandler(myfacesCustomComponent, resourceName));
84 }
85
86
87
88
89
90
91
92 public void addJavaScriptHere(FacesContext context, String uri) throws IOException
93 {
94 writeJavaScriptReference(context, getResourceUri(context, uri), true, false);
95 }
96
97 protected static void writeJavaScriptReference(FacesContext context, String resourceUri, boolean encoding, boolean defer) throws IOException{
98 ResponseWriter writer = context.getResponseWriter();
99
100 String src = null;
101 if(encoding) {
102 src=context.getExternalContext().encodeResourceURL(resourceUri);
103 }
104 else {
105 src = resourceUri;
106 }
107
108 writeJavaScriptReference(defer, writer, src);
109 }
110
111 protected static void writeJavaScriptReference(HttpServletResponse response, ResponseWriter writer, String resourceUri, boolean encoding, boolean defer) throws IOException {
112 String src = null;
113 if(encoding) {
114 src=response.encodeURL(resourceUri);
115 }
116 else {
117 src = resourceUri;
118 }
119
120 writeJavaScriptReference(defer, writer, src);
121 }
122
123 private static void writeJavaScriptReference(boolean defer, ResponseWriter writer, String src) throws IOException {
124 writer.startElement(org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.SCRIPT_ELEM, null);
125 writer.writeAttribute(org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.SCRIPT_TYPE_ATTR, org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
126
127 if(defer) {
128 writer.writeAttribute(org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.SCRIPT_ELEM_DEFER_ATTR, "true", null);
129 }
130 writer.writeURIAttribute(org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.SRC_ATTR, src, null);
131 writer.endElement(HTML.SCRIPT_ELEM);
132 }
133
134 protected static void writeStyleReference(FacesContext context, String resourceUri) throws IOException {
135 ResponseWriter writer = context.getResponseWriter();
136 writer.startElement(HTML.LINK_ELEM, null);
137 writer.writeAttribute(org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.REL_ATTR, org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.STYLESHEET_VALUE, null);
138 writer.writeAttribute(HTML.HREF_ATTR, context.getExternalContext().encodeResourceURL(resourceUri), null);
139 writer.writeAttribute(HTML.TYPE_ATTR, HTML.STYLE_TYPE_TEXT_CSS, null);
140 writer.endElement(org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.LINK_ELEM);
141 }
142
143 protected static void writeStyleReference(HttpServletResponse response, ResponseWriter writer, String resourceUri) throws IOException {
144 writer.startElement(HTML.LINK_ELEM, null);
145 writer.writeAttribute(org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.REL_ATTR, org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.STYLESHEET_VALUE, null);
146 writer.writeAttribute(HTML.HREF_ATTR, response.encodeURL(resourceUri), null);
147 writer.writeAttribute(HTML.TYPE_ATTR, HTML.STYLE_TYPE_TEXT_CSS, null);
148 writer.endElement(org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.LINK_ELEM);
149 }
150
151 protected static void writeInlineScript(ResponseWriter writer, String inlineScript) throws IOException {
152 writer.startElement(HTML.SCRIPT_ELEM, null);
153 writer.writeAttribute(HTML.SCRIPT_TYPE_ATTR, org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
154 writer.writeText(inlineScript, null);
155 writer.endElement(HTML.SCRIPT_ELEM);
156 }
157
158 protected static void writeInlineStylesheet(ResponseWriter writer, String inlineStyle) throws IOException {
159 writer.startElement(HTML.STYLE_ELEM, null);
160 writer.writeAttribute(HTML.REL_ATTR, HTML.STYLESHEET_VALUE, null);
161 writer.writeAttribute(HTML.TYPE_ATTR, HTML.STYLE_TYPE_TEXT_CSS, null);
162 writer.writeText(inlineStyle, null);
163 writer.endElement(HTML.STYLE_ELEM);
164 }
165
166 public void addJavaScriptHerePlain(FacesContext context, String uri) throws IOException
167 {
168 writeJavaScriptReference(context, getResourceUri(context, uri), false, false);
169 }
170
171
172
173
174
175
176
177
178
179
180 public void addJavaScriptHere(FacesContext context, ResourceHandler resourceHandler)
181 throws IOException
182 {
183 validateResourceHandler(resourceHandler);
184 writeJavaScriptReference(context, getResourceUri(context, resourceHandler), true, false);
185 }
186
187 public void addResourceHere(FacesContext context, ResourceHandler resourceHandler)
188 throws IOException
189 {
190 validateResourceHandler(resourceHandler);
191
192 String path = getResourceUri(context, resourceHandler);
193 ResponseWriter writer = context.getResponseWriter();
194 writer.write(context.getExternalContext().encodeResourceURL(path));
195 }
196
197
198
199
200
201
202
203
204
205 protected void validateResourceHandler(ResourceHandler resourceHandler)
206 {
207 if (resourceHandler == null)
208 {
209 throw new IllegalArgumentException("ResourceHandler is null");
210 }
211 validateResourceLoader(resourceHandler.getResourceLoaderClass());
212 }
213
214
215
216
217
218
219
220 protected void validateResourceLoader(Class resourceloader)
221 {
222 if (!ResourceLoader.class.isAssignableFrom(resourceloader))
223 {
224 throw new FacesException("Class " + resourceloader.getName() + " must implement "
225 + ResourceLoader.class.getName());
226 }
227 }
228
229 public void addJavaScriptAtPosition(FacesContext context, ResourcePosition position, ResourceHandler resourceHandler) {
230 try {
231 writeJavaScriptReference(context,getResourceUri(context,resourceHandler),true,false);
232 } catch (IOException e) {
233 throw new IllegalStateException(e.getMessage());
234 }
235 }
236
237 public void addJavaScriptAtPosition(FacesContext context, ResourcePosition position, Class myfacesCustomComponent, String resourceName) {
238 try {
239 writeJavaScriptReference(context,getResourceUri(context,new MyFacesResourceHandler(
240 myfacesCustomComponent, resourceName)),true,false);
241 } catch (IOException e) {
242 throw new IllegalStateException(e.getMessage());
243 }
244 }
245
246 public void addJavaScriptAtPosition(FacesContext context, ResourcePosition position, Class myfacesCustomComponent, String resourceName, boolean defer) {
247 try {
248 writeJavaScriptReference(context,getResourceUri(context,new MyFacesResourceHandler(
249 myfacesCustomComponent, resourceName)),true,true);
250 } catch (IOException e) {
251 throw new IllegalStateException(e.getMessage());
252 }
253 }
254
255 public void addJavaScriptAtPosition(FacesContext context, ResourcePosition position, String uri) {
256 try {
257 writeJavaScriptReference(context,getResourceUri(context,uri),true,false);
258 } catch (IOException e) {
259 throw new IllegalStateException(e.getMessage());
260 }
261 }
262
263 public void addJavaScriptAtPosition(FacesContext context, ResourcePosition position, String uri, boolean defer) {
264 try {
265 writeJavaScriptReference(context,getResourceUri(context,uri),true,true);
266 } catch (IOException e) {
267 throw new IllegalStateException(e.getMessage());
268 }
269 }
270
271
272
273
274
275
276
277
278
279 public void addJavaScriptToBodyTag(FacesContext context, String javascriptEventName, String addedJavaScript) {
280 throw new UnsupportedOperationException("not supported anymore - use javascript to register your body-event-handler directly");
281 }
282
283 public void addJavaScriptAtPosition(FacesContext context, ResourcePosition position, ResourceHandler resourceHandler, boolean defer) {
284 try {
285 writeJavaScriptReference(context,getResourceUri(context,resourceHandler),true,defer);
286 } catch (IOException e) {
287 throw new IllegalStateException(e.getMessage());
288 }
289 }
290
291 public void addJavaScriptAtPositionPlain(FacesContext context, ResourcePosition position, Class myfacesCustomComponent, String resourceName) {
292 try {
293 writeJavaScriptReference(context,getResourceUri(context,new MyFacesResourceHandler(myfacesCustomComponent, resourceName)),false,false);
294 } catch (IOException e) {
295 throw new IllegalStateException(e.getMessage());
296 }
297 }
298
299 public void addStyleSheet(FacesContext context, ResourcePosition position, Class myfacesCustomComponent, String resourceName) {
300 try {
301 writeStyleReference(context,getResourceUri(context,new MyFacesResourceHandler(myfacesCustomComponent, resourceName)));
302 } catch (IOException e) {
303 throw new IllegalStateException(e.getMessage());
304 }
305 }
306
307 public void addStyleSheet(FacesContext context, ResourcePosition position, String uri) {
308 try {
309 writeStyleReference(context,getResourceUri(context,uri));
310 } catch (IOException e) {
311 throw new IllegalStateException(e.getMessage());
312 }
313 }
314
315 public void addStyleSheet(FacesContext context, ResourcePosition position, ResourceHandler resourceHandler) {
316 try {
317 writeStyleReference(context,getResourceUri(context,resourceHandler));
318 } catch (IOException e) {
319 throw new IllegalStateException(e.getMessage());
320 }
321 }
322
323 public void addInlineStyleAtPosition(FacesContext context, ResourcePosition position, String inlineStyle) {
324 try {
325 writeInlineStylesheet(context.getResponseWriter(), inlineStyle);
326 } catch (IOException e) {
327 throw new IllegalStateException(e.getMessage());
328 }
329 }
330
331 public void addInlineScriptAtPosition(FacesContext context, ResourcePosition position, String inlineScript) {
332 try {
333 writeInlineScript(context.getResponseWriter(), inlineScript);
334 } catch (IOException e) {
335 throw new IllegalStateException(e.getMessage());
336 }
337 }
338
339 public String getResourceUri(FacesContext context, Class myfacesCustomComponent,
340 String resource, boolean withContextPath)
341 {
342 return getResourceUri(context,
343 new MyFacesResourceHandler(myfacesCustomComponent, resource), withContextPath);
344 }
345
346 public String getResourceUri(FacesContext context, Class myfacesCustomComponent, String resource)
347 {
348 return getResourceUri(context, new MyFacesResourceHandler(myfacesCustomComponent, resource));
349 }
350
351
352
353
354
355 public String getResourceUri(FacesContext context, ResourceHandler resourceHandler)
356 {
357 String uri = resourceHandler.getResourceUri(context);
358 if (uri == null)
359 {
360 return getResourceUri(context, resourceHandler.getResourceLoaderClass(), true);
361 }
362 return getResourceUri(context, resourceHandler.getResourceLoaderClass(), true) + uri;
363 }
364
365
366
367
368 public String getResourceUri(FacesContext context, ResourceHandler resourceHandler,
369 boolean withContextPath)
370 {
371 String uri = resourceHandler.getResourceUri(context);
372 if (uri == null)
373 {
374 return getResourceUri(context, resourceHandler.getResourceLoaderClass(),
375 withContextPath);
376 }
377 return getResourceUri(context, resourceHandler.getResourceLoaderClass(), withContextPath)
378 + uri;
379 }
380
381
382
383
384 public String getResourceUri(FacesContext context, String uri)
385 {
386 return getResourceUri(context, uri, true);
387 }
388
389
390
391
392 public String getResourceUri(FacesContext context, String uri, boolean withContextPath)
393 {
394 if (withContextPath)
395 {
396 return context.getApplication().getViewHandler().getResourceURL(context, uri);
397 }
398 return uri;
399 }
400
401
402
403
404
405
406
407
408
409 protected String getResourceUri(FacesContext context, Class resourceLoader,
410 boolean withContextPath)
411 {
412 StringBuffer sb = new StringBuffer(200);
413 sb.append(MyfacesConfig.getCurrentInstance(context.getExternalContext()).getResourceVirtualPath());
414 sb.append(PATH_SEPARATOR);
415 sb.append(resourceLoader.getName());
416 sb.append(PATH_SEPARATOR);
417 sb.append(getCacheKey(context));
418 sb.append(PATH_SEPARATOR);
419 return getResourceUri(context, sb.toString(), withContextPath);
420 }
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457 protected long getCacheKey(FacesContext context)
458 {
459
460 Map applicationMap = context.getExternalContext().getApplicationMap();
461 Long cacheKey = (Long) applicationMap.get(RESOURCES_CACHE_KEY);
462 if (cacheKey == null)
463 {
464 cacheKey = new Long(System.currentTimeMillis() / 100000);
465 applicationMap.put(RESOURCES_CACHE_KEY, cacheKey);
466 }
467 return cacheKey.longValue();
468 }
469
470 public boolean isResourceUri(ServletContext servletContext, HttpServletRequest request)
471 {
472
473 String path;
474 if (_contextPath != null)
475 {
476 path = _contextPath + getResourceVirtualPath(servletContext);
477 }
478 else
479 {
480 path = getResourceVirtualPath(servletContext);
481 }
482
483
484
485
486
487 try
488 {
489 if(request.getRequestURI().startsWith(URLEncoder.encode(path,"UTF-8")))
490 return true;
491 }
492 catch (UnsupportedEncodingException e)
493 {
494 log.error("Unsupported encoding UTF-8 used",e);
495
496 }
497
498 return request.getRequestURI().startsWith(path);
499 }
500
501 private String getResourceVirtualPath(ServletContext servletContext)
502 {
503 if(resourceVirtualPath == null)
504 {
505 resourceVirtualPath = servletContext.getInitParameter(MyfacesConfig.INIT_PARAM_RESOURCE_VIRTUAL_PATH);
506
507 if(resourceVirtualPath == null)
508 {
509 resourceVirtualPath = MyfacesConfig.INIT_PARAM_RESOURCE_VIRTUAL_PATH_DEFAULT;
510 }
511 }
512
513 return resourceVirtualPath;
514 }
515
516 private Class getClass(String className) throws ClassNotFoundException
517 {
518 Class clazz = ClassUtils.classForName(className);
519 validateResourceLoader(clazz);
520 return clazz;
521 }
522
523 public void serveResource(ServletContext context, HttpServletRequest request,
524 HttpServletResponse response) throws IOException
525 {
526 String pathInfo = request.getPathInfo();
527 String uri = request.getContextPath() + request.getServletPath()
528 + (pathInfo == null ? "" : pathInfo);
529 String classNameStartsAfter = getResourceVirtualPath(context) + '/';
530
531 int posStartClassName = uri.indexOf(classNameStartsAfter) + classNameStartsAfter.length();
532 int posEndClassName = uri.indexOf(PATH_SEPARATOR, posStartClassName);
533 String className = uri.substring(posStartClassName, posEndClassName);
534 int posEndCacheKey = uri.indexOf(PATH_SEPARATOR, posEndClassName + 1);
535 String resourceUri = null;
536 if (posEndCacheKey + 1 < uri.length())
537 {
538 resourceUri = uri.substring(posEndCacheKey + 1);
539 }
540 try
541 {
542 Class resourceLoader = getClass(className);
543 validateResourceLoader(resourceLoader);
544 ((ResourceLoader) resourceLoader.newInstance()).serveResource(context, request,
545 response, resourceUri);
546
547
548
549
550
551
552
553
554
555
556 }
557 catch (ResourceLoader.ClosedSocketException e)
558 {
559
560
561 }
562 catch (ClassNotFoundException e)
563 {
564 log.error("Could not find class for name: " + className, e);
565 response.sendError(HttpServletResponse.SC_NOT_FOUND,
566 "Could not find resourceloader class for name: " + className);
567 }
568 catch (InstantiationException e)
569 {
570 log.error("Could not instantiate class for name: " + className, e);
571 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
572 "Could not instantiate resourceloader class for name: " + className);
573 }
574 catch (IllegalAccessException e)
575 {
576 log.error("Could not access class for name: " + className, e);
577 response.sendError(HttpServletResponse.SC_FORBIDDEN,
578 "Could not access resourceloader class for name: " + className);
579 }
580 catch (Throwable e)
581 {
582 log.error("Error while serving resource: " + resourceUri + ", message : " + e.getMessage(), e);
583 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
584 }
585 }
586
587 public void parseResponse(HttpServletRequest request, String bufferedResponse, HttpServletResponse response) throws IOException {
588 throw new UnsupportedOperationException("non-buffering add resource is not buffering.");
589 }
590
591 public void writeMyFacesJavascriptBeforeBodyEnd(HttpServletRequest request, HttpServletResponse response) throws IOException {
592 throw new UnsupportedOperationException("non-buffering add resource is not buffering.");
593 }
594
595 public void writeWithFullHeader(HttpServletRequest request, HttpServletResponse response) throws IOException {
596 throw new UnsupportedOperationException("non-buffering add resource is not buffering.");
597 }
598
599 public void writeResponse(HttpServletRequest request, HttpServletResponse response) throws IOException {
600 throw new UnsupportedOperationException("non-buffering add resource is not buffering.");
601 }
602
603 public boolean requiresBuffer() {
604 return false;
605 }
606
607 public void responseStarted() {
608 }
609
610 public void responseFinished() {
611 }
612
613 public boolean hasHeaderBeginInfos() {
614 return false;
615 }
616 }