Clover Coverage Report - Pebble 2.5-SNAPSHOT
Coverage timestamp: Sat Jun 12 2010 09:39:29 EST
../../../../img/srcFileCovDistChart0.png 48% of files have more coverage
165   387   47   12,69
56   250   0,28   13
13     3,62  
1    
This report was generated with an evaluation server license. Purchase Clover or configure your license.
 
  Utilities       Line # 58 165 0% 47 234 0% 0.0
 
No Tests
 
1    /*
2    * Copyright (c) 2003-2005, Simon Brown
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions are met:
7    *
8    * - Redistributions of source code must retain the above copyright
9    * notice, this list of conditions and the following disclaimer.
10    *
11    * - Redistributions in binary form must reproduce the above copyright
12    * notice, this list of conditions and the following disclaimer in
13    * the documentation and/or other materials provided with the
14    * distribution.
15    *
16    * - Neither the name of Pebble nor the names of its contributors may
17    * be used to endorse or promote products derived from this software
18    * without specific prior written permission.
19    *
20    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21    * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22    * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23    * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24    * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25    * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26    * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27    * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28    * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29    * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30    * POSSIBILITY OF SUCH DAMAGE.
31    */
32    package net.sourceforge.pebble.util;
33   
34    import net.sourceforge.pebble.Configuration;
35    import net.sourceforge.pebble.PebbleContext;
36    import net.sourceforge.pebble.dao.CategoryDAO;
37    import net.sourceforge.pebble.dao.DAOFactory;
38    import net.sourceforge.pebble.dao.file.*;
39    import net.sourceforge.pebble.domain.*;
40    import net.sourceforge.pebble.api.event.comment.CommentEvent;
41    import net.sourceforge.pebble.api.event.trackback.TrackBackEvent;
42    import net.sourceforge.pebble.event.response.IpAddressListener;
43    import org.apache.commons.logging.Log;
44    import org.apache.commons.logging.LogFactory;
45   
46    import java.io.File;
47    import java.io.FileInputStream;
48    import java.io.FilenameFilter;
49    import java.util.*;
50    import java.text.SimpleDateFormat;
51   
52    /**
53    * Utilities for the current blog, such as those useful for moving
54    * between versions of Pebble.
55    *
56    * @author Simon Brown
57    */
 
58    public class Utilities {
59   
60    /** the logger used by this action */
61    private static final Log log = LogFactory.getLog(Utilities.class);
62   
63    /**
64    * Builds the indexes for the given blog.
65    *
66    * @param blog a Blog instance
67    */
 
68  0 toggle public static void buildIndexes(Blog blog) {
69  0 log.info("Reindexing blog");
70  0 blog.reindex();
71    }
72   
73    /**
74    * Builds the blacklist and whitelist of IP addresses from all responses
75    * for the given blog.
76    *
77    * @param blog a Blog instance
78    */
 
79  0 toggle public static void buildIpAddressLists(Blog blog) {
80  0 Iterator blogEntries = blog.getBlogEntries().iterator();
81  0 IpAddressListener ipAddressListener = new IpAddressListener();
82   
83  0 while (blogEntries.hasNext()) {
84  0 BlogEntry blogEntry = (BlogEntry)blogEntries.next();
85  0 log.info("Processing " + blogEntry.getTitle() + " (" + blogEntry.getDate() + ")");
86  0 Iterator comments = blogEntry.getComments().iterator();
87  0 while (comments.hasNext()) {
88  0 Comment comment = (Comment)comments.next();
89  0 if (comment.isApproved()) {
90  0 CommentEvent event = new CommentEvent(comment, CommentEvent.COMMENT_APPROVED);
91  0 ipAddressListener.commentApproved(event);
92  0 } else if (comment.isRejected()) {
93  0 CommentEvent event = new CommentEvent(comment, CommentEvent.COMMENT_REJECTED);
94  0 ipAddressListener.commentRejected(event);
95    }
96    }
97   
98  0 Iterator trackbacks = blogEntry.getTrackBacks().iterator();
99  0 while (trackbacks.hasNext()) {
100  0 TrackBack trackback = (TrackBack)trackbacks.next();
101  0 if (trackback.isApproved()) {
102  0 TrackBackEvent event = new TrackBackEvent(trackback, TrackBackEvent.TRACKBACK_APPROVED);
103  0 ipAddressListener.trackBackApproved(event);
104  0 } else if (trackback.isRejected()) {
105  0 TrackBackEvent event = new TrackBackEvent(trackback, TrackBackEvent.TRACKBACK_REJECTED);
106  0 ipAddressListener.trackBackRejected(event);
107    }
108    }
109    //
110    // try {
111    // blogEntry.store();
112    // } catch (BlogServiceException e) {
113    // log.error("Error storing " + blogEntry.getTitle() + " (" + blogEntry.getDate() + ")");
114    // }
115    }
116    }
117   
118    /**
119    * Fixes HTML escaping of comment and TrackBack content for the given blog.
120    *
121    * @param blog a Blog instance
122    */
 
123  0 toggle public static void fixHtmlInResponses(Blog blog) {
124  0 Iterator blogEntries = blog.getBlogEntries().iterator();
125  0 while (blogEntries.hasNext()) {
126  0 BlogEntry blogEntry = (BlogEntry)blogEntries.next();
127  0 log.info("Processing " + blogEntry.getTitle() + " (" + blogEntry.getDate() + ")");
128  0 Iterator comments = blogEntry.getComments().iterator();
129  0 while (comments.hasNext()) {
130  0 Comment comment = (Comment)comments.next();
131  0 if (comment.getBody() != null) {
132  0 comment.setBody(comment.getBody().replaceAll("&", "&"));
133  0 comment.setBody(comment.getBody().replaceAll("&lt;", "<"));
134  0 comment.setBody(comment.getBody().replaceAll("&gt;", ">"));
135    }
136    }
137  0 Iterator trackbacks = blogEntry.getTrackBacks().iterator();
138  0 while (trackbacks.hasNext()) {
139  0 TrackBack trackback = (TrackBack)trackbacks.next();
140  0 if (trackback.getExcerpt() != null) {
141  0 trackback.setExcerpt(trackback.getExcerpt().replaceAll("&amp;", "&"));
142  0 trackback.setExcerpt(trackback.getExcerpt().replaceAll("&lt;", "<"));
143  0 trackback.setExcerpt(trackback.getExcerpt().replaceAll("&gt;", ">"));
144    }
145    }
146  0 try {
147  0 BlogService service = new BlogService();
148  0 service.putBlogEntry(blogEntry);
149    } catch (BlogServiceException e) {
150  0 log.error("Error storing " + blogEntry.getTitle() + " (" + blogEntry.getDate() + ")");
151    }
152    }
153    }
154   
155    /**
156    * Converts flat categories to hierarchical categories.
157    *
158    * @param blog a Blog instance
159    */
 
160  0 toggle public static void convertCategories(Blog blog) {
161  0 Properties categories = new Properties();
162  0 try {
163  0 FileInputStream in = new FileInputStream(new File(blog.getRoot(), "blog.categories"));
164  0 categories.load(in);
165  0 in.close();
166   
167  0 Iterator it = categories.keySet().iterator();
168  0 while (it.hasNext()) {
169  0 String id = (String)it.next();
170  0 String name = categories.getProperty(id);
171  0 Category category;
172   
173  0 if (!id.startsWith("/")) {
174  0 category = new Category("/" + id, name);
175    } else {
176  0 category = new Category(id, name);
177    }
178   
179  0 blog.addCategory(category);
180  0 DAOFactory factory = DAOFactory.getConfiguredFactory();
181  0 CategoryDAO dao = factory.getCategoryDAO();
182  0 dao.addCategory(category, blog);
183    }
184    } catch (Exception e) {
185  0 log.error(e);
186    }
187    }
188   
189    /**
190    * Moves blog entries from one category to another.
191    *
192    * @param blog a Blog instance
193    */
 
194  0 toggle public static void moveBlogEntriesFromCategory(Blog blog, Category from, Category to) {
195  0 Iterator blogEntries = blog.getBlogEntries().iterator();
196  0 while (blogEntries.hasNext()) {
197  0 BlogEntry blogEntry = (BlogEntry)blogEntries.next();
198  0 log.info("Processing " + blogEntry.getTitle() + " (" + blogEntry.getDate() + ")");
199   
200  0 Collection categories = blogEntry.getCategories();
201  0 if (categories.contains(from)) {
202  0 categories.remove(from);
203  0 categories.add(to);
204  0 blogEntry.setCategories(categories);
205   
206  0 try {
207  0 BlogService service = new BlogService();
208  0 service.putBlogEntry(blogEntry);
209    } catch (BlogServiceException e) {
210  0 log.info("Error storing " + blogEntry.getTitle() + " (" + blogEntry.getDate() + ")");
211    }
212    }
213    }
214    }
215   
216    /**
217    * Resets the theme of a blog to "default".
218    */
 
219  0 toggle public static void resetTheme(Blog blog) {
220  0 log.info("Resetting theme to default");
221  0 try {
222  0 blog.removeProperty(Blog.THEME_KEY);
223  0 blog.storeProperties();
224    } catch (BlogServiceException e) {
225  0 e.printStackTrace();
226    }
227    }
228   
229    /**
230    * Blasts the blog specific theme and overwrites it with the default theme.
231    */
 
232  0 toggle public static void restoreTheme(Blog blog, String themeName) {
233  0 log.info("Restoring theme to " + themeName);
234  0 blog.getEditableTheme().restoreToSpecifiedTheme(themeName);
235    }
236   
237    /**
238    * Resets the plugins back to their defaults.
239    */
 
240  0 toggle public static void resetPlugins(Blog blog) {
241  0 log.info("Resetting plugins to the default configuration");
242  0 try {
243  0 blog.removeProperty(Blog.PERMALINK_PROVIDER_KEY);
244  0 blog.removeProperty(Blog.CONTENT_DECORATORS_KEY);
245  0 blog.removeProperty(Blog.BLOG_LISTENERS_KEY);
246  0 blog.removeProperty(Blog.BLOG_ENTRY_LISTENERS_KEY);
247  0 blog.removeProperty(Blog.COMMENT_LISTENERS_KEY);
248  0 blog.removeProperty(Blog.COMMENT_CONFIRMATION_STRATEGY_KEY);
249  0 blog.removeProperty(Blog.TRACKBACK_LISTENERS_KEY);
250  0 blog.removeProperty(Blog.TRACKBACK_CONFIRMATION_STRATEGY_KEY);
251  0 blog.removeProperty(Blog.LUCENE_ANALYZER_KEY);
252  0 blog.removeProperty(Blog.LOGGER_KEY);
253  0 blog.storeProperties();
254    } catch (BlogServiceException e) {
255  0 e.printStackTrace();
256    }
257    }
258   
259    /**
260    * Moves blog entries from one category to another.
261    *
262    * @param blog a Blog instance
263    */
 
264  0 toggle public static void restructureBlogToGMT(Blog blog) {
265  0 log.info("Restructuring blog entries into GMT directory hierarchy");
266  0 TimeZone gmt = TimeZone.getTimeZone("GMT");
267  0 FileBlogEntryDAO dao = new FileBlogEntryDAO();
268  0 File root = new File(blog.getRoot());
269  0 File years[] = root.listFiles(new FourDigitFilenameFilter());
270  0 for (File year : years) {
271  0 File months[] = year.listFiles(new TwoDigitFilenameFilter());
272  0 for (File month : months) {
273  0 File days[] = month.listFiles(new TwoDigitFilenameFilter());
274  0 for (File day : days) {
275  0 File blogEntryFiles[] = day.listFiles(new BlogEntryFilenameFilter());
276  0 for (File blogEntryFile : blogEntryFiles) {
277  0 String filename = blogEntryFile.getName();
278  0 String id = filename.substring(0, filename.indexOf('.'));
279  0 File oldFile = blogEntryFile;
280  0 File newDirectory = new File(dao.getPath(blog, id, gmt));
281  0 File newFile = new File(newDirectory, filename);
282   
283  0 if (!oldFile.equals(newFile)) {
284  0 log.info("Moving " + id + " to " + newFile.getAbsolutePath() + " from " + oldFile.getAbsolutePath());
285  0 newDirectory.mkdirs();
286  0 oldFile.renameTo(newFile);
287    }
288    }
289    }
290    }
291    }
292    }
293   
294    /**
295    * Restructures how static pages are stored on disk.
296    *
297    * @param blog a Blog instance
298    */
 
299  0 toggle public static void restructureStaticPages(Blog blog) {
300  0 log.info("Restructuring static pages");
301  0 File root = new File(blog.getRoot(), "pages");
302    // Upon first start this directory does not exist yet
303  0 if(!root.isDirectory()) {
304  0 root.mkdir();
305    }
306   
307  0 File files[] = root.listFiles(new FilenameFilter() {
 
308  0 toggle public boolean accept(File dir, String name) {
309  0 return name.matches("(\\d+\\.xml)|(\\d+\\.xml\\.bak)");
310    }
311    });
312   
313  0 for (File file : files) {
314  0 if (file.getName().endsWith(".xml")) {
315  0 File staticPageDirectory = new File(root, file.getName().substring(0, file.getName().indexOf(".xml")));
316  0 if (!staticPageDirectory.exists()) {
317  0 log.info("Creating static page directory at " + staticPageDirectory.getAbsolutePath());
318  0 staticPageDirectory.mkdir();
319    }
320  0 File destination = new File(staticPageDirectory, file.getName());
321  0 log.info("Moving " + file.getAbsolutePath() + " to " + destination.getAbsolutePath());
322  0 file.renameTo(destination);
323    } else {
324  0 File staticPageDirectory = new File(root, file.getName().substring(0, file.getName().indexOf(".xml")));
325  0 if (!staticPageDirectory.exists()) {
326  0 log.info("Creating static page directory at " + staticPageDirectory.getAbsolutePath());
327  0 staticPageDirectory.mkdir();
328    }
329  0 SimpleDateFormat archiveFileExtension = new SimpleDateFormat("yyyyMMdd-HHmmss");
330  0 archiveFileExtension.setTimeZone(blog.getTimeZone());
331  0 File destination = new File(staticPageDirectory, file.getName().substring(0, file.getName().length()-3) + archiveFileExtension.format(new Date(file.lastModified())));
332  0 log.info("Moving " + file.getAbsolutePath() + " to " + destination.getAbsolutePath());
333  0 file.renameTo(destination);
334    }
335    }
336    }
337   
 
338  0 toggle public static void main(String[] args) throws Exception {
339  0 if (args.length != 2) {
340  0 System.out.println("Usage : pebble.util.Utilities %1 %2");
341  0 System.out.println(" %1 : location of Pebble blog");
342  0 System.out.println(" %2 : [ipAddressListener|fixHtmlInResponses|convertCategories]");
343   
344  0 return;
345    }
346   
347  0 DAOFactory.setConfiguredFactory(new FileDAOFactory());
348  0 Blog blog = new Blog(args[0]);
349   
350  0 String action = args[1];
351  0 if (action == null) {
352    // do nothing
353  0 } else if (action.equalsIgnoreCase("ipAddressListener")) {
354  0 buildIpAddressLists(blog);
355  0 } else if (action.equalsIgnoreCase("fixHtmlInResponses")) {
356  0 fixHtmlInResponses(blog);
357  0 } else if (action.equalsIgnoreCase("buildIndexes")) {
358  0 buildIndexes(blog);
359  0 } else if (action.equalsIgnoreCase("convertCategories")) {
360  0 convertCategories(blog);
361    }
362   
363    }
364    /**
365    * this is a very simple way to honor https transfer. As
366    * the frontend depends upon setting a base url in the html/head block, it
367    * should at least contain the https scheme if the current page has been
368    * requested through https.
369    * If there is no https involved, pebbles previous behaviour
370    * (as of version 2.3.1) does not change. This change implies also changing
371    * several frontend jsps WEB-INF/tags/page.tag to use the value calculated
372    * here instead of ${blog.url}. In the context of the patch that introduced
373    * this method, the values have been named ${blogUrl} and ${multiBlogUrl}
374   
375    * @param currentScheme the scheme the current request has been sent through (e.g. request.getScheme())
376    * @param blogUrl the ordinary blog url that might be changed to the secure one.
377    * @return value to be used as base url for the blog named in blogUrl
378    */
 
379  0 toggle public static String calcBaseUrl(String currentScheme, String blogUrl) {
380  0 Configuration configuration = PebbleContext.getInstance().getConfiguration();
381  0 if ("https".equals(currentScheme) && configuration.getSecureUrl().startsWith("https")) {
382  0 return blogUrl.replace(configuration.getUrl(), configuration.getSecureUrl());
383    }
384  0 return blogUrl;
385    }
386   
387    }