Clover Coverage Report - Pebble 2.5-SNAPSHOT
Coverage timestamp: Sat Jun 12 2010 09:39:29 EST
../../../../../img/srcFileCovDistChart5.png 38% of files have more coverage
155   386   34   9,69
22   247   0,22   8
16     2,12  
2    
This report was generated with an evaluation server license. Purchase Clover or configure your license.
 
  FileStaticPageDAO       Line # 21 129 0% 30 105 36% 0.3597561
  FileStaticPageDAO.StaticPageDateConverter       Line # 333 26 0% 4 4 86,2% 0.86206895
 
  (18)
 
1    package net.sourceforge.pebble.dao.file;
2   
3    import net.sourceforge.pebble.dao.PersistenceException;
4    import net.sourceforge.pebble.dao.StaticPageDAO;
5    import net.sourceforge.pebble.domain.Blog;
6    import net.sourceforge.pebble.domain.StaticPage;
7    import net.sourceforge.pebble.util.SecurityUtils;
8    import org.apache.commons.logging.Log;
9    import org.apache.commons.logging.LogFactory;
10   
11    import javax.xml.bind.JAXBContext;
12    import javax.xml.bind.JAXBElement;
13    import javax.xml.bind.Marshaller;
14    import javax.xml.bind.Unmarshaller;
15    import java.io.*;
16    import java.text.SimpleDateFormat;
17    import java.text.DateFormat;
18    import java.text.ParseException;
19    import java.util.*;
20   
 
21    public class FileStaticPageDAO implements StaticPageDAO {
22   
23    /**
24    * the log used by this class
25    */
26    private static Log log = LogFactory.getLog(FileStaticPageDAO.class);
27   
28    private static final String STATIC_PAGES_DIRECTORY_NAME = "pages";
29    private static final String STATIC_PAGE_FILE_EXTENSION = ".xml";
30    private static final String STATIC_PAGE_LOCK_EXTENSION = ".lock";
31   
32    private JAXBContext jaxbContext;
33   
 
34  2456 toggle public FileStaticPageDAO() {
35  2456 try {
36  2456 jaxbContext = JAXBContext.newInstance(getClass().getPackage().getName());
37    } catch (Exception e) {
38  0 e.printStackTrace();
39    }
40    }
41   
42    /** the date/time format used when persisting dates */
43    static final String OLD_PERSISTENT_DATETIME_FORMAT = "dd MMM yyyy HH:mm:ss z";
44    static final String NEW_PERSISTENT_DATETIME_FORMAT = "dd MMM yyyy HH:mm:ss:S Z";
45    static final String REGEX_FOR_YEAR = "\\d\\d\\d\\d";
46   
47    /**
48    * Loads the static pages for a given blog.
49    *
50    * @param blog the owning Blog instance
51    * @return a Collection of StaticPage instances
52    * @throws net.sourceforge.pebble.dao.PersistenceException
53    * if static pages cannot be loaded
54    */
 
55  18 toggle public Collection<StaticPage> loadStaticPages(Blog blog) throws PersistenceException {
56  18 List<StaticPage> list = new ArrayList<StaticPage>();
57  18 File root = new File(blog.getRoot(), STATIC_PAGES_DIRECTORY_NAME);
58  18 File files[] = root.listFiles(new FilenameFilter() {
 
59  0 toggle public boolean accept(File dir, String name) {
60  0 return new File(dir, name).isDirectory() && name.matches("\\d+");
61    }
62    });
63   
64  18 if (files != null) {
65  0 for (File file : files) {
66  0 StaticPage staticPage = loadStaticPage(blog, file.getName());
67  0 if (staticPage != null) {
68  0 list.add(staticPage);
69    }
70    }
71    }
72   
73  18 return list;
74    }
75   
76    /**
77    * Loads a specific static page.
78    *
79    * @param blog the owning Blog
80    * @param pageId the page ID
81    * @return a StaticPage instance
82    * @throws net.sourceforge.pebble.dao.PersistenceException
83    * if the static page cannot be loaded
84    */
 
85  2 toggle public StaticPage loadStaticPage(Blog blog, String pageId) throws PersistenceException {
86  2 File path = new File(getPath(blog, pageId));
87  2 File file = new File(path, pageId + STATIC_PAGE_FILE_EXTENSION);
88  2 return loadStaticPage(blog, file);
89    }
90   
91    /**
92    * Loads a static page from the specified file.
93    *
94    * @param blog the Blog to which the static page belongs
95    * @param source the File pointing to the source
96    * @return a StaticPage instance
97    * @throws net.sourceforge.pebble.dao.PersistenceException
98    * if the static page can't be loaded
99    */
 
100  2 toggle private StaticPage loadStaticPage(Blog blog, File source) throws PersistenceException {
101  2 if (source.exists()) {
102  2 log.debug("Loading static page from " + source.getAbsolutePath());
103  2 StaticPage staticPage = new StaticPage(blog);
104   
105  2 try {
106  2 Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
107  2 JAXBElement<StaticPageType> controller = (JAXBElement)unmarshaller.unmarshal(source);
108  2 StaticPageType spt = controller.getValue();
109   
110  2 staticPage.setTitle(spt.getTitle());
111  2 staticPage.setSubtitle(spt.getSubtitle());
112  2 staticPage.setBody(spt.getBody());
113  2 staticPage.setTags(spt.getTags());
114  2 staticPage.setAuthor(spt.getAuthor());
115  2 staticPage.setOriginalPermalink(spt.getOriginalPermalink());
116  2 staticPage.setName(spt.getStaticName());
117  2 StaticPageDateConverter converter = new StaticPageDateConverter(staticPage);
118  2 staticPage.setDate(converter.parse(spt.getDate()));
119  2 staticPage.setTemplate(spt.getTemplate());
120   
121    } catch (Exception e) {
122  0 log.error(e.getMessage(), e);
123  0 e.printStackTrace();
124  0 throw new PersistenceException(e.getMessage());
125    }
126   
127    // and is the page locked?
128  2 staticPage.setLockedBy(getUsernameHoldingLock(staticPage));
129   
130  2 return staticPage;
131    } else {
132  0 return null;
133    }
134    }
135   
136    /**
137    * Stores the specified static page.
138    *
139    * @param staticPage the static page to store
140    * @throws net.sourceforge.pebble.dao.PersistenceException
141    * if something goes wrong storing the static page
142    */
 
143  0 toggle public void storeStaticPage(StaticPage staticPage) throws PersistenceException {
144  0 File outputDir = new File(getPath(staticPage.getBlog(), staticPage.getId()));
145  0 if (!outputDir.exists()) {
146  0 outputDir.mkdirs();
147    }
148   
149  0 File outputFile = new File(outputDir, staticPage.getId() + STATIC_PAGE_FILE_EXTENSION);
150  0 storeStaticPage(staticPage, outputFile);
151    }
152   
153    /**
154    * Stores a static page to the specified file.
155    *
156    * @param staticPage the StaticPage that is being stored
157    * @param destination the File pointing to the destination
158    * @throws PersistenceException if something goes wrong storing the static page
159    */
 
160  0 toggle private void storeStaticPage(StaticPage staticPage, File destination) throws PersistenceException {
161  0 try {
162  0 Marshaller marshaller = jaxbContext.createMarshaller();
163  0 StaticPageType type = new StaticPageType();
164   
165  0 type.setTitle(staticPage.getTitle());
166  0 type.setSubtitle(staticPage.getSubtitle());
167  0 type.setBody(staticPage.getBody());
168  0 type.setTags(staticPage.getTags());
169  0 type.setAuthor(staticPage.getAuthor());
170  0 type.setStaticName(staticPage.getName());
171  0 type.setOriginalPermalink(staticPage.getOriginalPermalink());
172  0 type.setState(ContentState.PUBLISHED);
173  0 type.setTitle(staticPage.getTitle());
174  0 type.setTemplate(staticPage.getTemplate());
175   
176  0 StaticPageDateConverter converter = new StaticPageDateConverter(staticPage);
177  0 type.setDate(converter.format(staticPage.getDate()));
178   
179    // now take a backup of the correct file
180  0 if (destination.exists() && destination.length() > 0) {
181  0 removeStaticPage(staticPage); // this archives the current version
182    }
183   
184  0 log.debug("Saving to " + destination.getAbsolutePath());
185  0 ObjectFactory objectFactory = new ObjectFactory();
186  0 JAXBElement jaxbElement = objectFactory.createStaticPage(type);
187   
188  0 marshaller.setProperty("jaxb.formatted.output", true);
189  0 marshaller.setProperty("jaxb.encoding", staticPage.getBlog().getCharacterEncoding());
190  0 FileWriter writer = new FileWriter(destination);
191  0 marshaller.marshal(jaxbElement, writer);
192  0 writer.flush();
193  0 writer.close();
194    } catch (Exception e) {
195  0 log.error(e.getMessage(), e);
196  0 e.printStackTrace();
197  0 throw new PersistenceException(e.getMessage());
198    }
199    }
200   
201    /**
202    * Removes the specified static page.
203    *
204    * @param staticPage the static page to remove
205    * @throws net.sourceforge.pebble.dao.PersistenceException
206    * if something goes wrong removing the page
207    */
 
208  0 toggle public void removeStaticPage(StaticPage staticPage) throws PersistenceException {
209  0 File path = new File(getPath(staticPage.getBlog(), staticPage.getId()));
210  0 File file = new File(path, staticPage.getId() + STATIC_PAGE_FILE_EXTENSION);
211  0 log.debug("Removing " + staticPage.getGuid());
212   
213    // for archive purposes, the current version of the file will be saved with
214    // the timestamp as the extension
215  0 SimpleDateFormat archiveFileExtension = new SimpleDateFormat("yyyyMMdd-HHmmss");
216  0 archiveFileExtension.setTimeZone(staticPage.getBlog().getTimeZone());
217  0 Date date = new Date();
218  0 if (file.exists()) {
219  0 date = new Date(file.lastModified());
220    }
221  0 File backupFile = new File(
222    file.getParentFile(),
223    file.getName() + "." + archiveFileExtension.format(date));
224   
225  0 if (backupFile.exists()) {
226  0 backupFile.delete();
227    }
228   
229  0 log.debug("Archiving current version to " + backupFile.getAbsolutePath());
230  0 boolean success = file.renameTo(backupFile);
231   
232  0 if (!success) {
233  0 throw new PersistenceException("Deletion of " + staticPage.getGuid() + " failed");
234    }
235    }
236   
237    /**
238    * Given a blog and static page ID, this method determines the path where
239    * that static page is stored.
240    *
241    * @param blog the owning Blog
242    * @param staticPageId the ID of the static page
243    * @return a String of the form blogroot/yyyy/MM/dd
244    */
 
245  2 toggle private String getPath(Blog blog, String staticPageId) {
246  2 StringBuffer buf = new StringBuffer();
247  2 buf.append(blog.getRoot());
248  2 buf.append(File.separator);
249  2 buf.append("pages");
250  2 buf.append(File.separator);
251  2 buf.append(staticPageId);
252   
253  2 return buf.toString();
254    }
255   
256    /**
257    * Locks the specified static page.
258    *
259    * @param staticPage the static page to lock
260    * @return true if the page could be locked, false otherwise
261    */
 
262  0 toggle public boolean lock(StaticPage staticPage) {
263  0 File lockFile = getLockFile(staticPage);
264  0 try {
265  0 boolean success = lockFile.createNewFile();
266  0 if (success) {
267  0 FileWriter writer = new FileWriter(lockFile);
268  0 writer.write(SecurityUtils.getUsername());
269  0 writer.flush();
270  0 writer.close();
271  0 return true;
272    } else {
273  0 String lockedBy = getUsernameHoldingLock(staticPage);
274  0 return (lockedBy != null && lockedBy.equals(SecurityUtils.getUsername()));
275    }
276    } catch (IOException e) {
277  0 log.warn("Exceptoin while attempting to lock static page " + staticPage.getGuid(), e);
278    }
279   
280  0 return false;
281    }
282   
283    /**
284    * Unlocks the specified static page.
285    *
286    * @param staticPage the static page to unlock
287    * @return true if the page could be unlocked, false otherwise
288    */
 
289  0 toggle public boolean unlock(StaticPage staticPage) {
290  0 File lockFile = getLockFile(staticPage);
291  0 if (lockFile.exists()) {
292  0 return lockFile.delete();
293    } else {
294  0 return true;
295    }
296    }
297   
298    /**
299    * Given a static page, this method determines the path where
300    * that static page is stored.
301    *
302    * @param staticPage a StaticPage instance
303    * @return a File instance, representing a lock
304    */
 
305  2 toggle private File getLockFile(StaticPage staticPage) {
306  2 StringBuffer buf = new StringBuffer();
307  2 buf.append(staticPage.getBlog().getRoot());
308  2 buf.append(File.separator);
309  2 buf.append(STATIC_PAGES_DIRECTORY_NAME);
310  2 buf.append(File.separator);
311  2 buf.append(staticPage.getId());
312  2 buf.append(STATIC_PAGE_LOCK_EXTENSION);
313   
314  2 return new File(buf.toString());
315    }
316   
 
317  2 toggle private String getUsernameHoldingLock(StaticPage staticPage) {
318  2 String username = null;
319  2 try {
320  2 File lockFile = getLockFile(staticPage);
321  2 if (lockFile.exists()) {
322  0 BufferedReader reader = new BufferedReader(new FileReader(lockFile));
323  0 username = reader.readLine();
324  0 reader.close();
325    }
326    } catch (IOException ioe) {
327  0 log.warn("Error reading lock file", ioe);
328    }
329   
330  2 return username;
331    }
332   
 
333    class StaticPageDateConverter {
334   
335    private SimpleDateFormat dateTimeFormats[];
336   
 
337  2 toggle StaticPageDateConverter(StaticPage staticPage) {
338    // create all date/time formats, for backwards compatibility
339  2 SimpleDateFormat format;
340  2 dateTimeFormats = new SimpleDateFormat[6];
341   
342  2 format = new SimpleDateFormat(FileBlogEntryDAO.NEW_PERSISTENT_DATETIME_FORMAT, Locale.ENGLISH);
343  2 format.setTimeZone(staticPage.getBlog().getTimeZone());
344  2 dateTimeFormats[0] = format;
345   
346  2 format = new SimpleDateFormat(FileBlogEntryDAO.NEW_PERSISTENT_DATETIME_FORMAT, staticPage.getBlog().getLocale());
347  2 format.setTimeZone(staticPage.getBlog().getTimeZone());
348  2 dateTimeFormats[1] = format;
349   
350  2 format = new SimpleDateFormat(FileBlogEntryDAO.NEW_PERSISTENT_DATETIME_FORMAT);
351  2 format.setTimeZone(staticPage.getBlog().getTimeZone());
352  2 dateTimeFormats[2] = format;
353   
354  2 format = new SimpleDateFormat(FileBlogEntryDAO.OLD_PERSISTENT_DATETIME_FORMAT, Locale.ENGLISH);
355  2 format.setTimeZone(staticPage.getBlog().getTimeZone());
356  2 dateTimeFormats[3] = format;
357   
358  2 format = new SimpleDateFormat(FileBlogEntryDAO.OLD_PERSISTENT_DATETIME_FORMAT, staticPage.getBlog().getLocale());
359  2 format.setTimeZone(staticPage.getBlog().getTimeZone());
360  2 dateTimeFormats[4] = format;
361   
362  2 format = new SimpleDateFormat(FileBlogEntryDAO.OLD_PERSISTENT_DATETIME_FORMAT);
363  2 format.setTimeZone(staticPage.getBlog().getTimeZone());
364  2 dateTimeFormats[5] = format;
365    }
366   
 
367  2 toggle Date parse(String s) {
368  2 for (DateFormat dateTimeFormat : dateTimeFormats) {
369  2 try {
370  2 return dateTimeFormat.parse(s);
371    } catch (ParseException pe) {
372    // do nothing, just try the next one
373    }
374    }
375   
376  0 log.error("Could not parse date of " + s);
377  0 return null;
378    }
379   
 
380  0 toggle String format(Date date) {
381  0 return dateTimeFormats[0].format(date);
382    }
383   
384    }
385   
386    }