- avoid clash with el expressions: use just {options[..]} rather than ${options[..]}
- look for either local or cascading option list-attribute
- smaller methods
git-svn-id: https://svn.apache.org/repos/asf/tiles/framework/trunk@1199972 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/tiles-parent/tiles-extras/src/main/java/org/apache/tiles/extras/renderer/OptionsRenderer.java b/tiles-parent/tiles-extras/src/main/java/org/apache/tiles/extras/renderer/OptionsRenderer.java
index cfed4d2..8ae8ccd 100644
--- a/tiles-parent/tiles-extras/src/main/java/org/apache/tiles/extras/renderer/OptionsRenderer.java
+++ b/tiles-parent/tiles-extras/src/main/java/org/apache/tiles/extras/renderer/OptionsRenderer.java
@@ -48,7 +48,7 @@
public final class OptionsRenderer implements TypeDetectingRenderer {
private static final Pattern OPTIONS_PATTERN
- = Pattern.compile(Pattern.quote("${options[") + ".+" + Pattern.quote("]}"));
+ = Pattern.compile(Pattern.quote("{options[") + "(.+)" + Pattern.quote("]}"));
private static final Logger LOG = LoggerFactory.getLogger(OptionsRenderer.class);
@@ -68,38 +68,25 @@
@Override
public void render(final String path, final Request request) throws IOException {
- final Matcher matcher = OPTIONS_PATTERN.matcher((String) path);
+ Matcher matcher = OPTIONS_PATTERN.matcher((String) path);
if (null != matcher && matcher.find()) {
boolean done = false;
- final String match = matcher.group();
+ String match = matcher.group(1);
ListAttribute fallbacks = (ListAttribute) TilesAccess
.getCurrentContainer(request)
.getAttributeContext(request)
- .getLocalAttribute(match);
+ .getAttribute(match);
+
+ if(null == fallbacks){
+ throw new IllegalStateException("A matching list-attribute name=\"" + match + "\" must be defined.");
+ }else if(fallbacks.getValue().isEmpty()){
+ throw new IllegalStateException("list-attribute name=\"" + match + "\" must have minimum one attribute");
+ }
for (Attribute option : (List<Attribute>) fallbacks.getValue()) {
- final String template = path.replaceFirst(Pattern.quote(match), (String)option.getValue());
- if(!Cache.isTemplateMissing(template)){
- try {
- if (null != applicationContext.getResource(template)) { // can throw FileNotFoundException !
- renderer.render(template, request); // can throw FileNotFoundException !
- done = true;
- Cache.setIfAbsentTemplateFound(template, true);
- }
- } catch (FileNotFoundException ex) {
- if(ex.getMessage().contains(template)){
- // expected outcome. continue loop.
- LOG.trace(ex.getMessage());
- }else{
- // comes from an inner templateAttribute.render(..) so throw on
- throw ex;
- }
- } catch(IOException ex){ //xxx ???
- throw ex;
- }
- Cache.setIfAbsentTemplateFound(template, false);
- }
+ String template = path.replaceFirst(Pattern.quote(matcher.group()), (String)option.getValue());
+ done = renderAttempt(template, request);
if(done){ break; }
}
if (!done) {
@@ -110,6 +97,31 @@
}
}
+ private boolean renderAttempt(final String template, final Request request) throws IOException{
+ boolean result = false;
+ if(!Cache.isTemplateMissing(template)){
+ try {
+ if (null != applicationContext.getResource(template)) { // can throw FileNotFoundException !
+ renderer.render(template, request); // can throw FileNotFoundException !
+ result = true;
+ Cache.setIfAbsentTemplateFound(template, true);
+ }
+ } catch (FileNotFoundException ex) {
+ if(ex.getMessage().contains(template)){
+ // expected outcome. continue loop.
+ LOG.trace(ex.getMessage());
+ }else{
+ // comes from an inner templateAttribute.render(..) so throw on
+ throw ex;
+ }
+ } catch(IOException ex){ //xxx ???
+ throw ex;
+ }
+ Cache.setIfAbsentTemplateFound(template, false);
+ }
+ return result;
+ }
+
private static final class Cache{
/** It takes CACHE_LIFE milliseconds for any hot deployments to register.