1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  package org.abstracthorizon.danube.freemarker;
14  
15  import org.abstracthorizon.danube.connection.Connection;
16  import org.abstracthorizon.danube.connection.ConnectionException;
17  import org.abstracthorizon.danube.mvc.ModelAndView;
18  import org.abstracthorizon.danube.mvc.View;
19  import org.abstracthorizon.danube.support.RuntimeIOException;
20  import org.abstracthorizon.danube.support.URLUtils;
21  
22  import java.io.File;
23  import java.io.FileReader;
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.io.InputStreamReader;
27  import java.io.Reader;
28  import java.io.Writer;
29  import java.net.URL;
30  import java.net.URLConnection;
31  
32  import org.slf4j.Logger;
33  import org.slf4j.LoggerFactory;
34  
35  import freemarker.cache.TemplateLoader;
36  import freemarker.template.Configuration;
37  import freemarker.template.DefaultObjectWrapper;
38  import freemarker.template.Template;
39  import freemarker.template.TemplateException;
40  import freemarker.template.TemplateExceptionHandler;
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  public class FreeMarkerViewAdapter implements View {
51  
52      
53      protected Logger logger = LoggerFactory.getLogger(getClass());
54  
55      
56      public static final String DEFAULT_SUFFIX = ".page";
57  
58      
59      protected File templatesPath;
60  
61      
62      protected URL templatesURL;
63  
64      
65      protected String suffix = DEFAULT_SUFFIX;
66  
67      
68      protected Configuration configuration;
69  
70      
71  
72  
73      public FreeMarkerViewAdapter() {
74      }
75  
76      
77  
78  
79  
80      public void init() throws RuntimeIOException {
81  
82          configuration = new Configuration();
83          configuration.setTemplateLoader(createTemplateLoader());
84          DefaultObjectWrapper defaultObjectWrapper = new DefaultObjectWrapper();
85          configuration.setObjectWrapper(defaultObjectWrapper);
86          configuration.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
87      }
88  
89      protected TemplateLoader createTemplateLoader() throws RuntimeIOException {
90          return new LocalTemplateLoader();
91      }
92  
93      
94  
95  
96  
97  
98  
99      public void render(Connection connection, ModelAndView modelAndView) throws ConnectionException {
100 
101         try {
102             Template template = configuration.getTemplate(makeTemplateName(modelAndView.getView()));
103             Writer writer = (Writer)connection.adapt(Writer.class);
104 
105             template.process(modelAndView.getModel(), writer);
106         } catch (TemplateException templateException) {
107             throw new ConnectionException(templateException);
108         } catch (IOException e) {
109             throw new RuntimeIOException(e);
110         }
111 
112         
113     }
114 
115     
116 
117 
118 
119     public File getTemplatesPath() {
120         return templatesPath;
121     }
122 
123     
124 
125 
126 
127     public void setTemplatesPath(File templatesPath) {
128         this.templatesPath = templatesPath;
129         if (configuration != null) {
130             configuration.setTemplateLoader(createTemplateLoader());
131         }
132     }
133 
134     
135 
136 
137 
138     public URL getTemplatesURL() {
139         return templatesURL;
140     }
141 
142     
143 
144 
145 
146     public void setTemplatesURL(URL templatesURL) {
147         this.templatesURL = templatesURL;
148         if (templatesURL.getProtocol().equals("file")) {
149             templatesPath = new File(templatesURL.getFile());
150         }
151     }
152 
153     
154 
155 
156 
157 
158     protected String makeTemplateName(String view) {
159         if (suffix == null) {
160             return view;
161         } else {
162             return view + suffix;
163         }
164     }
165 
166     
167 
168 
169 
170     public String getSuffix() {
171         return suffix;
172     }
173 
174     
175 
176 
177 
178     public void setSuffix(String suffix) {
179         if (suffix.startsWith(".")) {
180             this.suffix = suffix;
181         } else {
182             this.suffix = "." + suffix;
183         }
184     }
185 
186     
187 
188 
189 
190     public class LocalTemplateLoader implements TemplateLoader {
191 
192         
193         public LocalTemplateLoader() {
194         }
195 
196         
197 
198 
199 
200 
201         public void closeTemplateSource(Object tmp) throws IOException {
202         }
203 
204         
205 
206 
207 
208 
209 
210 
211         public Object findTemplateSource(String path) throws IOException {
212             if (templatesPath != null) {
213                 File file = new File(templatesPath, path);
214                 if (file.exists()) {
215                     return file;
216                 }
217             }
218             if (templatesURL != null) {
219                 URL newURL = URLUtils.addPath(templatesURL, path);
220                 try {
221                     InputStream peek = newURL.openStream();
222                     peek.read();
223                     peek.close();
224                     return newURL;
225                 } catch (IOException ignore) {
226                 }
227             }
228 
229             return null;
230         }
231 
232         
233 
234 
235 
236 
237 
238 
239         public long getLastModified(Object tmp) {
240             if (tmp instanceof File) {
241                 return ((File)tmp).lastModified();
242             } else if (tmp instanceof URL) {
243                 try {
244                     URLConnection connection = ((URL)tmp).openConnection();
245                     return connection.getLastModified();
246                 } catch (IOException ignore) {
247                 }
248             }
249 
250             return -1;
251         }
252 
253         
254 
255 
256 
257 
258 
259         public Reader getReader(Object tmp, String encoding) throws IOException {
260             if (tmp instanceof File) {
261                 File file = (File)tmp;
262                 return new FileReader(file);
263             } else if (tmp instanceof URL) {
264                 URL url = (URL)tmp;
265                 return new InputStreamReader(url.openStream());
266             } else {
267                 return null;
268             }
269         }
270 
271     }
272 }