View Javadoc

1   package com.atlassian.plugins.rest.module.template;
2   
3   import com.atlassian.templaterenderer.TemplateRenderer;
4   import com.google.common.base.Preconditions;
5   import com.google.common.collect.Maps;
6   import com.sun.jersey.spi.template.TemplateProcessor;
7   import com.sun.jersey.api.core.HttpContext;
8   
9   import java.io.IOException;
10  import java.io.OutputStream;
11  import java.io.OutputStreamWriter;
12  import java.util.Map;
13  
14  import org.osgi.util.tracker.ServiceTracker;
15  import org.apache.log4j.Logger;
16  
17  import javax.ws.rs.core.Context;
18  import javax.servlet.http.HttpServletRequest;
19  import javax.servlet.http.HttpServletResponse;
20  
21  /**
22   * Template processor that uses velocity and locates template within the bundle that uses it.
23   */
24  @SuppressWarnings({"UnusedDeclaration"})
25  public class VelocityTemplateProcessor implements TemplateProcessor
26  {
27      private static final Logger log = Logger.getLogger(VelocityTemplateProcessor.class);
28      private static final String VM = ".vm";
29  
30      private final ServiceTracker templateRendererServiceTracker;
31      private @Context HttpContext httpContext;
32      private @Context HttpServletRequest httpServletRequest;
33      private @Context HttpServletResponse httpServletResponse;
34  
35      VelocityTemplateProcessor(ServiceTracker templateRendererServiceTracker)
36      {
37          this.templateRendererServiceTracker = Preconditions.checkNotNull(templateRendererServiceTracker);
38      }
39  
40      public String resolve(final String path)
41      {
42          return executeOnTemplateRenderer(new TemplateRendererCommand<String>()
43          {
44              public String execute(TemplateRenderer renderer)
45              {
46                  String resolvedPath = path + VM;
47                  if (renderer.resolve(resolvedPath))
48                  {
49                      return resolvedPath;
50                  }
51                  else
52                  {
53                      return null;
54                  }
55              }
56          });
57      }
58  
59      public void writeTo(final String resolvedPath, final Object model, final OutputStream out) throws IOException
60      {
61          try
62          {
63              executeOnTemplateRenderer(new TemplateRendererCommand<Object>()
64              {
65                  public Object execute(TemplateRenderer renderer)
66                  {
67                      final OutputStreamWriter writer = new OutputStreamWriter(out);
68                      final Map<String, Object> context = Maps.newHashMap();
69                      context.put("renderer", new RendererImpl(renderer, writer, httpContext,
70                          httpServletRequest, httpServletResponse));
71                      context.put("it", model);
72                      context.put("httpContext", httpContext);
73                      context.put("request", httpServletRequest);
74                      context.put("response", httpServletResponse);
75                      try
76                      {
77                          renderer.render(resolvedPath, context, writer);
78                      }
79                      catch (IOException ioe)
80                      {
81                          throw new RuntimeException(ioe);
82                      }
83                      return null;
84                  }
85              });
86          }
87          catch (RuntimeException re)
88          {
89              if (re.getCause() instanceof IOException)
90              {
91                  throw (IOException) re.getCause();
92              }
93              else
94              {
95                  throw re;
96              }
97          }
98      }
99  
100     /**
101      * Close the template renderer service tracker.  This should be called when the service is unimported.
102      */
103     public void closeTemplateRendererServiceTracker()
104     {
105         templateRendererServiceTracker.close();
106     }
107 
108     /**
109      * Command so calls to the template renderer don't need to check if the template renderer service is available
110      * first
111      */
112     private interface TemplateRendererCommand<T>
113     {
114         T execute(TemplateRenderer renderer);
115     }
116 
117     private <T> T executeOnTemplateRenderer(TemplateRendererCommand<T> templateRendererCommand)
118     {
119         TemplateRenderer renderer = (TemplateRenderer) templateRendererServiceTracker.getService();
120         if (renderer != null)
121         {
122             return templateRendererCommand.execute(renderer);
123         }
124         else
125         {
126             log.warn("No template renderer service available, not executing command");
127             return null;
128         }
129 
130     }
131 }