1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.view.facelets.compiler;
20
21 import org.apache.myfaces.shared.util.ArrayUtils;
22 import org.apache.myfaces.shared.util.StringUtils;
23 import org.apache.myfaces.shared.util.WebConfigParamUtils;
24 import org.apache.myfaces.view.facelets.tag.AbstractTagLibrary;
25 import org.apache.myfaces.view.facelets.tag.TagLibrary;
26 import org.apache.myfaces.view.facelets.tag.composite.CompositeComponentResourceTagHandler;
27 import org.apache.myfaces.view.facelets.tag.composite.CompositeResouceWrapper;
28 import org.apache.myfaces.view.facelets.util.ParameterCheck;
29 import org.apache.myfaces.view.facelets.util.ReflectionUtil;
30
31 import javax.faces.FacesException;
32 import javax.faces.application.Resource;
33 import javax.faces.application.ResourceHandler;
34 import javax.faces.application.ViewHandler;
35 import javax.faces.context.ExternalContext;
36 import javax.faces.context.FacesContext;
37 import javax.faces.view.facelets.ComponentConfig;
38 import javax.faces.view.facelets.FaceletHandler;
39 import javax.faces.view.facelets.Tag;
40 import javax.faces.view.facelets.TagConfig;
41 import javax.faces.view.facelets.TagHandler;
42 import java.lang.reflect.Method;
43 import java.net.URL;
44 import java.util.logging.Logger;
45 import java.util.regex.Pattern;
46 import org.apache.myfaces.config.element.facelets.FaceletBehaviorTag;
47 import org.apache.myfaces.config.element.facelets.FaceletComponentTag;
48 import org.apache.myfaces.config.element.facelets.FaceletConverterTag;
49 import org.apache.myfaces.config.element.facelets.FaceletFunction;
50 import org.apache.myfaces.config.element.facelets.FaceletHandlerTag;
51 import org.apache.myfaces.config.element.facelets.FaceletSourceTag;
52 import org.apache.myfaces.config.element.facelets.FaceletTag;
53 import org.apache.myfaces.config.element.facelets.FaceletTagLibrary;
54 import org.apache.myfaces.config.element.facelets.FaceletValidatorTag;
55
56
57
58
59
60
61
62
63 public final class TagLibraryConfig
64 {
65
66
67
68
69 protected final static Logger log = Logger.getLogger(TagLibraryConfig.class.getName());
70
71 private static class TagLibraryImpl extends AbstractTagLibrary
72 {
73 private String _compositeLibraryName;
74
75 private final ResourceHandler _resourceHandler;
76 private Pattern _acceptPatterns;
77 private String _extension;
78 private String[] _defaultSuffixesArray;
79
80 public TagLibraryImpl(FacesContext facesContext, String namespace)
81 {
82 super(namespace);
83 _compositeLibraryName = null;
84 _resourceHandler = facesContext.getApplication().getResourceHandler();
85 ExternalContext externalContext = facesContext.getExternalContext();
86
87 _acceptPatterns = loadAcceptPattern(externalContext);
88
89 _extension = loadFaceletExtension(externalContext);
90
91 String defaultSuffixes = WebConfigParamUtils.getStringInitParameter(externalContext,
92 ViewHandler.DEFAULT_SUFFIX_PARAM_NAME, ViewHandler.DEFAULT_SUFFIX );
93
94 _defaultSuffixesArray = StringUtils.splitShortString(defaultSuffixes, ' ');
95
96 boolean faceletsExtensionFound = false;
97 for (String ext : _defaultSuffixesArray)
98 {
99 if (_extension.equals(ext))
100 {
101 faceletsExtensionFound = true;
102 break;
103 }
104 }
105 if (!faceletsExtensionFound)
106 {
107 _defaultSuffixesArray = (String[]) ArrayUtils.concat(_defaultSuffixesArray, new String[]{_extension});
108 }
109 }
110
111
112
113
114
115
116
117
118
119 private Pattern loadAcceptPattern(ExternalContext context)
120 {
121 assert context != null;
122
123 String mappings = context.getInitParameter(ViewHandler.FACELETS_VIEW_MAPPINGS_PARAM_NAME);
124 if (mappings == null)
125 {
126 return null;
127 }
128
129
130 mappings = mappings.trim();
131 if (mappings.length() == 0)
132 {
133 return null;
134 }
135
136 return Pattern.compile(toRegex(mappings));
137 }
138
139 private String loadFaceletExtension(ExternalContext context)
140 {
141 assert context != null;
142
143 String suffix = context.getInitParameter(ViewHandler.FACELETS_SUFFIX_PARAM_NAME);
144 if (suffix == null)
145 {
146 suffix = ViewHandler.DEFAULT_FACELETS_SUFFIX;
147 }
148 else
149 {
150 suffix = suffix.trim();
151 if (suffix.length() == 0)
152 {
153 suffix = ViewHandler.DEFAULT_FACELETS_SUFFIX;
154 }
155 }
156
157 return suffix;
158 }
159
160
161
162
163
164
165
166
167
168 private String toRegex(String mappings)
169 {
170 assert mappings != null;
171
172
173 mappings = mappings.replaceAll("\\s", "");
174
175
176 mappings = mappings.replaceAll("\\.", "\\\\.");
177
178
179 mappings = mappings.replaceAll("\\*", ".*");
180
181
182 mappings = mappings.replaceAll(";", "|");
183
184 return mappings;
185 }
186
187 public boolean handles(String resourceName)
188 {
189 if (resourceName == null)
190 {
191 return false;
192 }
193
194 if (resourceName.endsWith(_extension))
195 {
196
197 return true;
198 }
199
200
201 return _acceptPatterns != null && _acceptPatterns.matcher(resourceName).matches();
202 }
203
204 @Override
205 public boolean containsTagHandler(String ns, String localName)
206 {
207 boolean result = super.containsTagHandler(ns, localName);
208
209 if (!result && _compositeLibraryName != null && containsNamespace(ns))
210 {
211 for (String defaultSuffix : _defaultSuffixesArray)
212 {
213 String resourceName = localName + defaultSuffix;
214 if (handles(resourceName))
215 {
216 Resource compositeComponentResource = _resourceHandler.createResource(
217 resourceName, _compositeLibraryName);
218
219 if (compositeComponentResource != null)
220 {
221 URL url = compositeComponentResource.getURL();
222 return (url != null);
223 }
224 }
225 }
226 }
227 return result;
228 }
229
230 @Override
231 public TagHandler createTagHandler(String ns, String localName,
232 TagConfig tag) throws FacesException
233 {
234 TagHandler tagHandler = super.createTagHandler(ns, localName, tag);
235
236 if (tagHandler == null && _compositeLibraryName != null && containsNamespace(ns))
237 {
238 for (String defaultSuffix : _defaultSuffixesArray)
239 {
240 String resourceName = localName + defaultSuffix;
241 if (handles(resourceName))
242 {
243
244
245
246
247
248
249
250
251 Resource compositeComponentResource = new CompositeResouceWrapper(
252 _resourceHandler.createResource(resourceName, _compositeLibraryName));
253
254 if (compositeComponentResource != null)
255 {
256 ComponentConfig componentConfig = new ComponentConfigWrapper(tag,
257 "javax.faces.NamingContainer", null);
258
259 return new CompositeComponentResourceTagHandler(
260 componentConfig, compositeComponentResource);
261 }
262 }
263 }
264 }
265 return tagHandler;
266 }
267
268 public void setCompositeLibrary(String compositeLibraryName)
269 {
270 _compositeLibraryName = compositeLibraryName;
271 }
272
273 public void putConverter(String name, String id)
274 {
275 ParameterCheck.notNull("name", name);
276 ParameterCheck.notNull("id", id);
277 this.addConverter(name, id);
278 }
279
280 public void putConverter(String name, String id, Class<? extends TagHandler> handlerClass)
281 {
282 ParameterCheck.notNull("name", name);
283 ParameterCheck.notNull("id", id);
284 ParameterCheck.notNull("handlerClass", handlerClass);
285 this.addConverter(name, id, handlerClass);
286 }
287
288 public void putValidator(String name, String id)
289 {
290 ParameterCheck.notNull("name", name);
291 ParameterCheck.notNull("id", id);
292 this.addValidator(name, id);
293 }
294
295 public void putValidator(String name, String id, Class<? extends TagHandler> handlerClass)
296 {
297 ParameterCheck.notNull("name", name);
298 ParameterCheck.notNull("id", id);
299 ParameterCheck.notNull("handlerClass", handlerClass);
300 this.addValidator(name, id, handlerClass);
301 }
302
303 public void putTagHandler(String name, Class<? extends TagHandler> type)
304 {
305 ParameterCheck.notNull("name", name);
306 ParameterCheck.notNull("type", type);
307 this.addTagHandler(name, type);
308 }
309
310 public void putComponentFromResourceId(String name, String resourceId)
311 {
312 ParameterCheck.notNull("name", name);
313 ParameterCheck.notNull("resourceId", resourceId);
314 this.addComponentFromResourceId(name, resourceId);
315 }
316
317 public void putComponent(String name, String componentType, String rendererType)
318 {
319 ParameterCheck.notNull("name", name);
320 ParameterCheck.notNull("componentType", componentType);
321 this.addComponent(name, componentType, rendererType);
322 }
323
324 public void putComponent(String name, String componentType, String rendererType,
325 Class<? extends TagHandler> handlerClass)
326 {
327 ParameterCheck.notNull("name", name);
328 ParameterCheck.notNull("componentType", componentType);
329 ParameterCheck.notNull("handlerClass", handlerClass);
330 this.addComponent(name, componentType, rendererType, handlerClass);
331 }
332
333 public void putUserTag(String name, URL source)
334 {
335 ParameterCheck.notNull("name", name);
336 ParameterCheck.notNull("source", source);
337 this.addUserTag(name, source);
338 }
339
340 public void putFunction(String name, Method method)
341 {
342 ParameterCheck.notNull("name", name);
343 ParameterCheck.notNull("method", method);
344 this.addFunction(name, method);
345 }
346
347 public void putBehavior(String name, String id)
348 {
349 ParameterCheck.notNull("name", name);
350 ParameterCheck.notNull("id", id);
351 this.addBehavior(name, id);
352 }
353
354 public void putBehavior(String name, String id, Class<? extends TagHandler> handlerClass)
355 {
356 ParameterCheck.notNull("name", name);
357 ParameterCheck.notNull("id", id);
358 ParameterCheck.notNull("handlerClass", handlerClass);
359 this.addBehavior(name, id, handlerClass);
360 }
361 }
362
363 private static class ComponentConfigWrapper implements ComponentConfig
364 {
365
366 protected final TagConfig parent;
367
368 protected final String componentType;
369
370 protected final String rendererType;
371
372 public ComponentConfigWrapper(TagConfig parent, String componentType,
373 String rendererType)
374 {
375 this.parent = parent;
376 this.componentType = componentType;
377 this.rendererType = rendererType;
378 }
379
380 public String getComponentType()
381 {
382 return this.componentType;
383 }
384
385 public String getRendererType()
386 {
387 return this.rendererType;
388 }
389
390 public FaceletHandler getNextHandler()
391 {
392 return this.parent.getNextHandler();
393 }
394
395 public Tag getTag()
396 {
397 return this.parent.getTag();
398 }
399
400 public String getTagId()
401 {
402 return this.parent.getTagId();
403 }
404 }
405
406 public TagLibraryConfig()
407 {
408 super();
409 }
410
411 public static TagLibrary create(FacesContext facesContext, FaceletTagLibrary faceletTagLibrary)
412 {
413 if (isNotEmpty(faceletTagLibrary.getLibraryClass()))
414 {
415 TagLibrary t = null;
416 Class<?> type;
417 try
418 {
419 type = createClass(TagLibrary.class, faceletTagLibrary.getLibraryClass());
420 t = (TagLibrary) type.newInstance();
421 }
422 catch (Exception ex)
423 {
424 throw new FacesException("Cannot instantiate TagLibrary", ex);
425 }
426
427 return t;
428 }
429
430 TagLibraryImpl impl = new TagLibraryImpl(facesContext, faceletTagLibrary.getNamespace());
431
432 impl.setCompositeLibrary(faceletTagLibrary.getCompositeLibraryName());
433
434 for (FaceletFunction ff : faceletTagLibrary.getFunctions())
435 {
436 try
437 {
438 Class<?> functionClass = createClass(Object.class, ff.getFunctionClass());
439 impl.putFunction(ff.getFunctionName(), createMethod(functionClass, ff.getFunctionSignature()));
440 }
441 catch (Exception ex)
442 {
443 throw new FacesException("Cannot instantiate Function Class", ex);
444 }
445 }
446
447 for (FaceletTag ft : faceletTagLibrary.getTags())
448 {
449 try
450 {
451 if (ft.isHandlerTag())
452 {
453 FaceletHandlerTag tag = (FaceletHandlerTag) ft.getTagDefinition();
454 if (tag.getHandlerClass() != null)
455 {
456 Class<? extends TagHandler> handlerClass =
457 createClass(TagHandler.class, tag.getHandlerClass());
458 impl.putTagHandler(ft.getName(), handlerClass);
459 }
460 }
461 else if (ft.isComponentTag())
462 {
463 FaceletComponentTag tag = (FaceletComponentTag) ft.getTagDefinition();
464 if (tag.getHandlerClass() != null)
465 {
466 Class<? extends TagHandler> handlerClass =
467 createClass(TagHandler.class, tag.getHandlerClass());
468 impl.putComponent(ft.getName(), tag.getComponentType(), tag.getRendererType(), handlerClass);
469 }
470 else if (tag.getResourceId() != null)
471 {
472 impl.putComponentFromResourceId(ft.getName(), tag.getResourceId());
473 }
474 else
475 {
476 impl.putComponent(ft.getName(), tag.getComponentType(), tag.getRendererType());
477 }
478 }
479 else if (ft.isSourceTag())
480 {
481 FaceletSourceTag tag = (FaceletSourceTag) ft.getTagDefinition();
482 impl.putUserTag(ft.getName(), new URL(tag.getSource()));
483 }
484 else if (ft.isConverterTag())
485 {
486 FaceletConverterTag tag = (FaceletConverterTag) ft.getTagDefinition();
487 if (tag.getHandlerClass() != null)
488 {
489 Class<? extends TagHandler> handlerClass =
490 createClass(TagHandler.class, tag.getHandlerClass());
491 impl.putConverter(ft.getName(), tag.getConverterId(), handlerClass);
492 }
493 else
494 {
495 impl.putConverter(ft.getName(), tag.getConverterId());
496 }
497 }
498 else if (ft.isValidatorTag())
499 {
500 FaceletValidatorTag tag = (FaceletValidatorTag) ft.getTagDefinition();
501 if (tag.getHandlerClass() != null)
502 {
503 Class<? extends TagHandler> handlerClass =
504 createClass(TagHandler.class, tag.getHandlerClass());
505 impl.putValidator(ft.getName(), tag.getValidatorId(), handlerClass);
506 }
507 else
508 {
509 impl.putValidator(ft.getName(), tag.getValidatorId());
510 }
511 }
512 else if (ft.isBehaviorTag())
513 {
514 FaceletBehaviorTag tag = (FaceletBehaviorTag) ft.getTagDefinition();
515 if (tag.getHandlerClass() != null)
516 {
517 Class<? extends TagHandler> handlerClass =
518 createClass(TagHandler.class, tag.getHandlerClass());
519 impl.putBehavior(ft.getName(), tag.getBehaviorId(), handlerClass);
520 }
521 else
522 {
523 impl.putBehavior(ft.getName(), tag.getBehaviorId());
524 }
525 }
526 }
527 catch (Exception ex)
528 {
529 throw new FacesException("Cannot instantiate Tag "+ft.getName()+" from namespace "+
530 faceletTagLibrary.getNamespace(), ex);
531 }
532 }
533 return impl;
534 }
535
536 @SuppressWarnings("unchecked")
537 private static <T> Class<? extends T> createClass(Class<T> type, String name) throws Exception
538 {
539 Class<? extends T> factory = (Class<? extends T>)ReflectionUtil.forName(name);
540 if (!type.isAssignableFrom(factory))
541 {
542 throw new Exception(name + " must be an instance of " + type.getName());
543 }
544 return factory;
545 }
546
547 private static Method createMethod(Class<?> type, String s) throws Exception
548 {
549 int pos = s.indexOf(' ');
550 if (pos == -1)
551 {
552 throw new Exception("Must Provide Return Type: " + s);
553 }
554 else
555 {
556 int pos2 = s.indexOf('(', pos + 1);
557 if (pos2 == -1)
558 {
559 throw new Exception("Must provide a method name, followed by '(': " + s);
560 }
561 else
562 {
563 String mn = s.substring(pos + 1, pos2).trim();
564 pos = s.indexOf(')', pos2 + 1);
565 if (pos == -1)
566 {
567 throw new Exception("Must close parentheses, ')' missing: " + s);
568 }
569 else
570 {
571 String[] ps = s.substring(pos2 + 1, pos).trim().split(",");
572 Class<?>[] pc;
573 if (ps.length == 1 && "".equals(ps[0]))
574 {
575 pc = new Class[0];
576 }
577 else
578 {
579 pc = new Class[ps.length];
580 for (int i = 0; i < pc.length; i++)
581 {
582 pc[i] = ReflectionUtil.forName(ps[i].trim());
583 }
584 }
585 try
586 {
587 return type.getMethod(mn, pc);
588 }
589 catch (NoSuchMethodException e)
590 {
591 throw new Exception("No Function Found on type: " + type.getName() + " with signature: "
592 + s);
593 }
594
595 }
596
597 }
598 }
599 }
600
601 private static boolean isNotEmpty(String value)
602 {
603 return value != null && value.length() > 0;
604 }
605
606 }