View Javadoc

1   /*
2    * $Id$
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   * http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  package org.apache.tiles.request.mustache;
23  
24  import java.io.IOException;
25  import java.util.HashMap;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.regex.Matcher;
29  import java.util.regex.Pattern;
30  
31  import com.github.mustachejava.MustacheFactory;
32  import com.github.mustachejava.DefaultMustacheFactory;
33  import com.github.mustachejava.MustacheException;
34  import org.apache.tiles.request.Request;
35  import org.apache.tiles.request.render.CannotRenderException;
36  import org.apache.tiles.request.render.Renderer;
37  
38  /**
39   * The Mustache-specific renderer.
40   *
41   * Can be configured to render paths only according to the acceptPattern.
42   *
43   * @version $Rev: 1215006 $ $Date: 2011-12-16 01:30:41 +0100 (Fri, 16 Dec 2011) $
44   */
45  public class MustacheRenderer implements Renderer {
46  
47      // hack. exposes the tiles Request for MustacheFactory implementations.
48      private static final ThreadLocal<Request> REQUEST_HOLDER = new ThreadLocal<Request>();
49  
50      private final MustacheFactory factory;
51      private Pattern acceptPattern;
52  
53      /** Uses the {@link DefaultMustacheFactory} */
54      public MustacheRenderer(){
55          this.factory = new DefaultMustacheFactory();
56      }
57  
58      public MustacheRenderer(MustacheFactory factory) {
59          this.factory = factory;
60      }
61  
62      @Override
63      public void render(String path, Request request) throws IOException {
64          if (path == null) {
65              throw new CannotRenderException("Cannot dispatch a null path");
66          }
67  
68          try {
69              REQUEST_HOLDER.set(request);
70              factory
71                      .compile(path)
72                      .execute(request.getWriter(), buildScope(request));
73              REQUEST_HOLDER.remove();
74  
75          } catch(MustacheException ex) {
76              throw new IOException("failed to MustacheRenderer.render(" + path + ",request)", ex);
77          }
78      }
79  
80      public static Request getThreadLocalRequest() {
81          return REQUEST_HOLDER.get();
82      }
83  
84      protected Map<String,Object> buildScope(Request request) {
85          Map<String,Object> scope = new HashMap<String,Object>();
86          List<String> availableScopes = request.getAvailableScopes();
87          for (int i = availableScopes.size() -1; i >= 0; --i) {
88              scope.putAll(request.getContext(availableScopes.get(i)));
89          }
90          return scope;
91      }
92  
93      @Override
94      public boolean isRenderable(String path, Request request) {
95          if (path == null) {
96              return false;
97          }
98          if (acceptPattern != null) {
99              final Matcher matcher = acceptPattern.matcher(path);
100             return matcher.matches();
101         }
102         return true;
103     }
104 
105     public final void setAcceptPattern(Pattern acceptPattern) {
106         this.acceptPattern = acceptPattern;
107     }
108 }