View Javadoc

1   /*
2    * ----------------------------------------------------------------------
3    * Copyright (C) 2009 Enrique Lara (k957@68k.org)
4    *
5    * TinLizard is free software; you can redistribute it and/or
6    * modify it under the terms of the GNU Lesser General Public License
7    * as published by the Free Software Foundation; either version 3.0
8    * of the License, or (at your option) any later version.
9    *
10   * TinLizard is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13   * GNU Lesser General Public License for more details.
14   *
15   * You should have received a copy of the GNU Lesser General Public License
16   * along with TinLizard. If not, see http://www.gnu.org/licenses/.
17   * ----------------------------------------------------------------------
18   */
19  package tinlizard.dao.io;
20  
21  import freemarker.template.Configuration;
22  import freemarker.template.DefaultObjectWrapper;
23  import freemarker.template.Template;
24  
25  import tinlizard.dao.MashDao;
26  
27  import tinlizard.util.Messages;
28  
29  import java.io.File;
30  import java.io.FileNotFoundException;
31  import java.io.FileOutputStream;
32  import java.io.IOException;
33  import java.io.InputStream;
34  import java.io.Writer;
35  import java.util.HashMap;
36  import java.util.Locale;
37  import java.util.Map;
38  
39  import org.apache.commons.lang.StringUtils;
40  import org.apache.log4j.Logger;
41  
42  /***
43   * Freemarker implementation of MashDao.
44   */
45  public final class MashDaoImpl implements MashDao {
46      private static final Logger LOG = Logger.getLogger(MashDaoImpl.class);
47      private static final int BUFFER_SIZE = 128;
48      private String mashFilesDirectory;
49      private File mashDir = new File("/tmp");
50      private File resourcesDir = new File("/tmp");
51      private Configuration cfg = null;
52      private static final int SECONDS_PER_MINUTE = 60;
53      private int delayMinutes = 5;
54  
55      public String getMashFilesDirectory() {
56          return mashFilesDirectory;
57      }
58  
59      public void setMashFilesDirectory(final String mashFilesDirectory) {
60          this.mashFilesDirectory = mashFilesDirectory;
61  
62          mashDir = new File(mashFilesDirectory);
63          resourcesDir = new File(mashDir, "resources");
64  
65          if (!mashDir.isDirectory()) {
66              mashDir.mkdirs();
67          }
68  
69          if (!resourcesDir.isDirectory()) {
70              resourcesDir.mkdir();
71          }
72  
73          try {
74              cfg = new Configuration();
75              cfg.setDirectoryForTemplateLoading(mashDir);
76              cfg.setObjectWrapper(new DefaultObjectWrapper());
77              cfg.setTemplateUpdateDelay(delayMinutes * SECONDS_PER_MINUTE);
78          } catch (Exception e) {
79              throw new RuntimeException(Messages.error_0300(), e);
80          }
81      }
82  
83      public File getResourcesFile(final String path) {
84          if (path.indexOf("..") != -1) {
85              //XXX consider logging warning.
86              return null;
87          }
88  
89          File resFile = new File(resourcesDir, path);
90  
91          if (!resFile.getParentFile().exists()) {
92              return null;
93          }
94  
95          if (!resFile.exists()) {
96              String resourceClassPath = "/mash-files/resources" + path;
97  
98              if (copyFromClasspath(resFile, resourceClassPath)) {
99                  return resFile;
100             }
101         }
102 
103         return null;
104     }
105 
106     private boolean copyFromClasspath(final File resFile, final String resourceClassPath) {
107         InputStream is = getClass().getResourceAsStream(resourceClassPath);
108 
109         if (is == null) {
110             return false;
111         }
112 
113         if (!resFile.getParentFile().isDirectory()) {
114             resFile.getParentFile().mkdirs();
115         }
116 
117         FileOutputStream os = null;
118 
119         try {
120             os = new FileOutputStream(resFile);
121 
122             byte[] buffer = new byte[BUFFER_SIZE];
123             int nRead = -1;
124 
125             while ((nRead = is.read(buffer)) > -1) {
126                 os.write(buffer, 0, nRead);
127             }
128 
129             return true;
130         } catch (FileNotFoundException e) {
131             return false;
132         } catch (IOException e) {
133             return false;
134         } finally {
135             try {
136                 is.close();
137             } catch (IOException e) {
138                 LOG.trace("Ignore, nothing to do.");
139             }
140 
141             if (os != null) {
142                 try {
143                     os.close();
144                 } catch (IOException e) {
145                     LOG.trace("Ignore, nothing to do.");
146                 }
147             }
148         }
149     }
150 
151     public void applyTemplate(final Object it, final String template, final Writer out, final Locale locale, final String username) {
152         try {
153             boolean foundTemplate = false;
154 
155             String resourcePath = null;
156 
157             Class<?> clazz = it.getClass();
158 
159             while (!foundTemplate && !Object.class.equals(clazz)) {
160                 if (LOG.isDebugEnabled()) {
161                     LOG.debug("Class:" + clazz);
162                 }
163 
164                 File classMashDir = getClassMashDir(clazz);
165                 resourcePath = getResourcePath(clazz);
166 
167                 File templateFile = new File(classMashDir, template);
168                 foundTemplate = templateFile.exists();
169 
170                 if (!foundTemplate) {
171                     String resourceClassPath = "/mash-files/" + resourcePath + "/" + template;
172 
173                     if (LOG.isDebugEnabled()) {
174                         LOG.debug("Check:" + resourceClassPath);
175                     }
176 
177                     foundTemplate = copyFromClasspath(templateFile, resourceClassPath);
178                 }
179 
180                 clazz = clazz.getSuperclass();
181             }
182 
183             if (foundTemplate) {
184                 if (LOG.isDebugEnabled()) {
185                     LOG.debug("Found:" + resourcePath + "/" + template);
186                 }
187 
188                 Map<Object, Object> root = new HashMap<Object, Object>();
189                 root.put("it", it);
190 
191                 if (StringUtils.isNotBlank(username)) {
192                     root.put("username", username);
193                 }
194 
195                 Template temp = cfg.getTemplate(resourcePath + "/" + template, locale);
196                 temp.process(root, out);
197             }
198         } catch (Exception e) {
199             LOG.info("Problems Applying template:" + template, e);
200         }
201     }
202 
203     private String getResourcePath(final Class<?extends Object> clazz) {
204         String clazzName = clazz.getName();
205         String clazzDir = clazzName.replaceAll("//.", "/");
206 
207         return clazzDir;
208     }
209 
210     private File getClassMashDir(final Class<?extends Object> clazz) {
211         String clazzName = clazz.getName();
212         String clazzDir = clazzName.replaceAll("//.", "/");
213 
214         return new File(mashDir, clazzDir);
215     }
216 }