Clover Coverage Report - Pebble 2.5-SNAPSHOT
Coverage timestamp: Sat Jun 12 2010 09:39:29 EST
../../../../img/srcFileCovDistChart4.png 41% of files have more coverage
75   265   29   5,77
22   144   0,39   13
13     2,23  
1    
This report was generated with an evaluation server license. Purchase Clover or configure your license.
 
  StaticPageIndex       Line # 47 75 0% 29 68 38,2% 0.38181818
 
  (16)
 
1    /*
2    * Copyright (c) 2003-2006, 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.index;
33   
34    import net.sourceforge.pebble.domain.Blog;
35    import net.sourceforge.pebble.domain.StaticPage;
36    import org.apache.commons.logging.Log;
37    import org.apache.commons.logging.LogFactory;
38   
39    import java.io.*;
40    import java.util.*;
41   
42    /**
43    * Maintains an index of all static pages
44    *
45    * @author Simon Brown
46    */
 
47    public class StaticPageIndex {
48   
49    private static final Log log = LogFactory.getLog(StaticPageIndex.class);
50   
51    private static final String PAGES_INDEX_DIRECTORY_NAME = "pages";
52    private static final String NAME_TO_ID_INDEX_FILE_NAME = "name.index";
53    private static final String LOCK_FILE_NAME = "pages.lock";
54    private static final int MAXIMUM_LOCK_ATTEMPTS = 3;
55   
56    /** the owning blog */
57    private Blog blog;
58   
59    /** the collection of all static pages */
60    private Map<String,String> index = new HashMap<String,String>();
61    private int lockAttempts = 0;
62   
 
63  1334 toggle public StaticPageIndex(Blog blog) {
64  1334 this.blog = blog;
65   
66    // create the directory structure if it doesn't exist
67  1334 File indexDirectory = new File(blog.getIndexesDirectory(), PAGES_INDEX_DIRECTORY_NAME);
68  1334 if (!indexDirectory.exists()) {
69  1318 indexDirectory.mkdirs();
70    }
71   
72  1334 readIndex();
73    }
74   
75    /**
76    * Indexes one or more blog entries.
77    *
78    * @param staticPages a List of Page instances
79    */
 
80  18 toggle public synchronized void reindex(Collection<StaticPage> staticPages) {
81  18 if (lock()) {
82    // clear the index and add all static pages
83  18 index = new HashMap<String,String>();
84  18 for (StaticPage staticPage : staticPages) {
85  0 index.put(staticPage.getName(), staticPage.getId());
86    }
87   
88    // and finally, write the index
89  18 writeIndex();
90  18 unlock();
91    }
92    }
93   
94    /**
95    * Indexes a single page.
96    *
97    * @param staticPage a Page instance
98    */
 
99  0 toggle public synchronized void index(StaticPage staticPage) {
100  0 if (lock()) {
101  0 readIndex();
102   
103    // remove the old entry for this static page
104  0 Iterator it = index.keySet().iterator();
105  0 while (it.hasNext()) {
106  0 String key = (String)it.next();
107  0 String value = index.get(key);
108  0 if (value.equals(staticPage.getId())) {
109  0 it.remove();
110    }
111    }
112   
113    // and now add the new entry for this page
114  0 index.put(staticPage.getName(), staticPage.getId());
115  0 writeIndex();
116  0 unlock();
117    } else {
118  0 if (lockAttempts <= MAXIMUM_LOCK_ATTEMPTS) {
119  0 try {
120  0 Thread.sleep(1000);
121    } catch (InterruptedException ie) {
122    // ignore
123    }
124  0 index(staticPage);
125    } else {
126  0 blog.error("Could not index static page - try <a href=\"utilities.secureaction?action=buildIndexes\">rebuilding the indexes</a>.");
127    }
128    }
129    }
130   
131    /**
132    * Unindexes a single page.
133    *
134    * @param staticPage a Page instance
135    */
 
136  0 toggle public synchronized void unindex(StaticPage staticPage) {
137  0 if (lock()) {
138  0 readIndex();
139  0 index.remove(staticPage.getName());
140  0 writeIndex();
141  0 unlock();
142    } else {
143  0 if (lockAttempts <= MAXIMUM_LOCK_ATTEMPTS) {
144  0 try {
145  0 Thread.sleep(1000);
146    } catch (InterruptedException ie) {
147    // ignore
148    }
149  0 unindex(staticPage);
150    } else {
151  0 blog.reindexStaticPages();
152    }
153    }
154    }
155   
156    /**
157    * Helper method to load the index.
158    */
 
159  1334 toggle private void readIndex() {
160  1334 log.info("Reading index from disk");
161  1334 File indexFile = getIndexFile();
162  1334 if (indexFile.exists()) {
163  0 try {
164  0 BufferedReader reader = new BufferedReader(new FileReader(indexFile));
165  0 String indexEntry = reader.readLine();
166  0 while (indexEntry != null) {
167  0 String[] parts = indexEntry.split("=");
168  0 index.put(parts[0], parts[1]);
169   
170  0 indexEntry = reader.readLine();
171    }
172   
173  0 reader.close();
174    } catch (Exception e) {
175  0 log.error("Error while reading index", e);
176    }
177    }
178    }
179   
180    /**
181    * Helper method to write out the index to disk.
182    */
 
183  18 toggle private void writeIndex() {
184  18 try {
185  18 File indexFile = getIndexFile();
186  18 BufferedWriter writer = new BufferedWriter(new FileWriter(indexFile));
187   
188  18 for (String name : index.keySet()) {
189  0 writer.write(name + "=" + index.get(name));
190  0 writer.newLine();
191    }
192   
193  18 writer.flush();
194  18 writer.close();
195    } catch (Exception e) {
196  0 log.error("Error while writing index", e);
197    }
198    }
199   
200    /**
201    * Gets the page ID for the specified named page.
202    *
203    * @param name a String
204    * @return a String instance, or null if no page exists
205    * with the specified name
206    */
 
207  0 toggle public String getStaticPage(String name) {
208  0 return index.get(name);
209    }
210   
211    /**
212    * Gets the list of static page IDs.
213    *
214    * @return a List<String>
215    */
 
216  0 toggle public List<String> getStaticPages() {
217  0 return new LinkedList<String>(index.values());
218    }
219   
220    /**
221    * Determines whether a page with the specified permalink exists.
222    *
223    * @param name the name as a String
224    * @return true if the page exists, false otherwise
225    */
 
226  0 toggle public boolean contains(String name) {
227  0 return index.containsKey(name);
228    }
229   
230    /**
231    * Gets the number of static pages.
232    *
233    * @return an int
234    */
 
235  0 toggle public int getNumberOfStaticPages() {
236  0 return index.size();
237    }
238   
 
239  1352 toggle private File getIndexFile() {
240  1352 File indexDirectory = new File(blog.getIndexesDirectory(), PAGES_INDEX_DIRECTORY_NAME);
241  1352 return new File(indexDirectory, NAME_TO_ID_INDEX_FILE_NAME);
242    }
243   
 
244  18 toggle private boolean lock() {
245  18 File lockFile = new File(blog.getIndexesDirectory(), LOCK_FILE_NAME);
246  18 boolean success = false;
247  18 try {
248  18 success = lockFile.createNewFile();
249  18 if (!success) {
250  0 lockAttempts++;
251    }
252    } catch (IOException ioe) {
253  0 log.warn("Error while creating lock file", ioe);
254    }
255   
256  18 return success;
257    }
258   
 
259  18 toggle private void unlock() {
260  18 File lockFile = new File(blog.getIndexesDirectory(), LOCK_FILE_NAME);
261  18 lockFile.delete();
262  18 lockAttempts = 0;
263    }
264   
265    }