File Source: blog.java
/*
P/P * Method: net.sourceforge.pebble.domain.Blog__static_init
*
* Postconditions:
* init'ed(log)
*/
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.domain;
33
34 import java.io.File;
35 import java.lang.reflect.Constructor;
36 import java.util.ArrayList;
37 import java.util.Arrays;
38 import java.util.Calendar;
39 import java.util.Collection;
40 import java.util.Collections;
41 import java.util.Date;
42 import java.util.Iterator;
43 import java.util.LinkedList;
44 import java.util.List;
45 import java.util.Properties;
46 import java.util.StringTokenizer;
47
/*
P/P * Method: void net.sourceforge.pebble.domain.Blog(String)
*
* Postconditions:
* init'ed(this.blog)
* init'ed(this.id)
* init'ed(this.messages)
* init'ed(this.root)
* new LinkedList(AbstractBlog#1) num objects == 1
*/
48 import javax.servlet.http.HttpServletRequest;
49
50 import net.sourceforge.pebble.Configuration;
51 import net.sourceforge.pebble.Constants;
52 import net.sourceforge.pebble.PebbleContext;
53 import net.sourceforge.pebble.PluginProperties;
54 import net.sourceforge.pebble.aggregator.NewsFeedCache;
55 import net.sourceforge.pebble.aggregator.NewsFeedEntry;
56 import net.sourceforge.pebble.api.confirmation.CommentConfirmationStrategy;
57 import net.sourceforge.pebble.api.confirmation.TrackBackConfirmationStrategy;
58 import net.sourceforge.pebble.api.decorator.ContentDecorator;
59 import net.sourceforge.pebble.api.event.EventDispatcher;
60 import net.sourceforge.pebble.api.event.blog.BlogEvent;
61 import net.sourceforge.pebble.api.event.blog.BlogListener;
62 import net.sourceforge.pebble.api.event.blogentry.BlogEntryListener;
63 import net.sourceforge.pebble.api.event.comment.CommentListener;
64 import net.sourceforge.pebble.api.event.trackback.TrackBackListener;
65 import net.sourceforge.pebble.api.permalink.PermalinkProvider;
66 import net.sourceforge.pebble.confirmation.DefaultConfirmationStrategy;
67 import net.sourceforge.pebble.dao.CategoryDAO;
68 import net.sourceforge.pebble.dao.DAOFactory;
69 import net.sourceforge.pebble.dao.PersistenceException;
70 import net.sourceforge.pebble.decorator.ContentDecoratorChain;
71 import net.sourceforge.pebble.decorator.HideUnapprovedResponsesDecorator;
72 import net.sourceforge.pebble.event.AuditListener;
73 import net.sourceforge.pebble.event.DefaultEventDispatcher;
74 import net.sourceforge.pebble.event.EventListenerList;
75 import net.sourceforge.pebble.event.blogentry.EmailSubscriptionListener;
76 import net.sourceforge.pebble.index.AuthorIndex;
77 import net.sourceforge.pebble.index.AuthorIndexListener;
78 import net.sourceforge.pebble.index.BlogEntryIndex;
79 import net.sourceforge.pebble.index.BlogEntryIndexListener;
80 import net.sourceforge.pebble.index.CategoryIndex;
81 import net.sourceforge.pebble.index.CategoryIndexListener;
82 import net.sourceforge.pebble.index.EmailSubscriptionList;
83 import net.sourceforge.pebble.index.ResponseIndex;
84 import net.sourceforge.pebble.index.ResponseIndexListener;
85 import net.sourceforge.pebble.index.SearchIndex;
86 import net.sourceforge.pebble.index.SearchIndexListener;
87 import net.sourceforge.pebble.index.StaticPageIndex;
88 import net.sourceforge.pebble.index.TagIndex;
89 import net.sourceforge.pebble.index.TagIndexListener;
90 import net.sourceforge.pebble.logging.AbstractLogger;
91 import net.sourceforge.pebble.logging.CombinedLogFormatLogger;
92 import net.sourceforge.pebble.permalink.DefaultPermalinkProvider;
93 import net.sourceforge.pebble.util.StringUtils;
94
95 import org.apache.commons.logging.Log;
96 import org.apache.commons.logging.LogFactory;
97
98 /**
99 * Represents a blog.
100 *
101 * @author Simon Brown
102 */
103 public class Blog extends AbstractBlog {
104
105 private static final Log log = LogFactory.getLog(Blog.class);
106
107 public static final String ABOUT_KEY = "about";
108 public static final String EMAIL_KEY = "email";
109 public static final String BLOG_OWNERS_KEY = "blogOwners";
110 public static final String BLOG_PUBLISHERS_KEY = "blogPublishers";
111 public static final String BLOG_CONTRIBUTORS_KEY = "blogContributors";
112 public static final String BLOG_READERS_KEY = "blogReaders";
113 public static final String PRIVATE_KEY = "private";
114 public static final String LUCENE_ANALYZER_KEY = "luceneAnalyzer";
115 public static final String CONTENT_DECORATORS_KEY = "decorators";
116 public static final String BLOG_LISTENERS_KEY = "blogListeners";
117 public static final String BLOG_ENTRY_LISTENERS_KEY = "blogEntryListeners";
118 public static final String COMMENT_LISTENERS_KEY = "commentListeners";
119 public static final String TRACKBACK_LISTENERS_KEY = "trackBackListeners";
120 public static final String EVENT_DISPATCHER_KEY = "eventDispatcher";
121 public static final String LOGGER_KEY = "logger";
122 public static final String PERMALINK_PROVIDER_KEY = "permalinkProviderName";
123 public static final String COMMENT_CONFIRMATION_STRATEGY_KEY = "commentConfirmationStrategy";
124 public static final String TRACKBACK_CONFIRMATION_STRATEGY_KEY = "trackBackConfirmationStrategy";
125 public static final String RICH_TEXT_EDITOR_FOR_COMMENTS_ENABLED_KEY = "richTextEditorForCommentsEnabled";
126 public static final String HOME_PAGE_KEY = "homePage";
127
128 /** the ID of this blog */
129 private String id = "default";
130
131 /** the collection of Year instance that this root blog is managing */
132 private List<Year> years;
133
134 /** the root category associated with this blog */
135 private Category rootCategory;
136
137 /** the referer filter associated with this blog */
138 private RefererFilterManager refererFilterManager;
139
140 /** the editable theme belonging to this blog */
141 private Theme editableTheme;
142
143 /** the permalink provider in use */
144 private PermalinkProvider permalinkProvider;
145
146 /** the log used to log referers, requests, etc */
147 private AbstractLogger logger;
148
149 /** the decorator chain associated with this blog */
150 private ContentDecoratorChain decoratorChain;
151
152 private CommentConfirmationStrategy commentConfirmationStrategy;
153 private TrackBackConfirmationStrategy trackBackConfirmationStrategy;
154
155 /** the event dispatcher */
156 private EventDispatcher eventDispatcher;
157
158 /** the event listener list */
159 private EventListenerList eventListenerList;
160
161 /** the plugin properties */
162 private PluginProperties pluginProperties;
163
164 private SearchIndex searchIndex;
165 private BlogEntryIndex blogEntryIndex;
166 private ResponseIndex responseIndex;
167 private TagIndex tagIndex;
168 private CategoryIndex categoryIndex;
169 private AuthorIndex authorIndex;
170 private StaticPageIndex staticPageIndex;
171
172 private EmailSubscriptionList emailSubscriptionList;
173
174 /**
175 * Creates a new Blog instance, based at the specified location.
176 *
177 * @param root an absolute path pointing to the root directory of the blog
178 */
179 public Blog(String root) {
180 super(root);
181
182 // probably Blog should be made a final class if init is called from here -
183 // see javadoc comment on AbstractBlog.init() for reasons
184 init();
185 }
186
187 /**
188 * Initialize this blog - prepare it for use.
189 * Note: As this blog instance is passed to the various participants while
190 * it is being initialized, this method is dependent on the correct order
191 * of calls: Keep in mind that 'this' is only partly initialized until the
192 * end of this method...
193 */
194
/*
P/P * Method: void init()
*
* Preconditions:
* init'ed(this.root)
* (soft) net/sourceforge/pebble/dao/DAOFactory.configuredFactory != null
* (soft) net/sourceforge/pebble/dao/DAOFactory.configuredFactory.categoryDAO != null
* (soft) net/sourceforge/pebble/dao/DAOFactory.configuredFactory.refererFilterDAO != null
* (soft) net/sourceforge/pebble/dao/file/FileRefererFilterDAO.log != null
* (soft) net/sourceforge/pebble/domain/AbstractBlog.log != null
* (soft) this.messages != null
* (soft) init'ed(this.rootCategory)
*
* Presumptions:
* java.lang.Class:forName(...)@199 != null
* java.lang.Class:forName(...)@232 != null
* java.lang.Class:forName(...)@241 != null
*
* Postconditions:
* this.authorIndex == &new AuthorIndex(init#11)
* this.blogEntryIndex == &new BlogEntryIndex(init#7)
* this.categoryIndex == &new CategoryIndex(init#10)
* this.commentConfirmationStrategy != null
* this.decoratorChain == &new ContentDecoratorChain(init#13)
* this.emailSubscriptionList == &new EmailSubscriptionList(init#18)
* this.eventDispatcher != null
* init'ed(this.eventDispatcher.eventListenerList)
* this.eventListenerList == &new EventListenerList(initEventDispatcher#1)
* init'ed(this.logger)
* ...
*/
195 protected void init() {
196 super.init();
197
198 try {
199 Class c = Class.forName(getPermalinkProviderName());
200 setPermalinkProvider((PermalinkProvider)c.newInstance());
201 } catch (Exception e) {
202 error("Could not load permalink provider \"" + getPermalinkProviderName() + "\"");
203 e.printStackTrace();
204 setPermalinkProvider(new DefaultPermalinkProvider());
205 }
206
207 // load categories
208 try {
209 DAOFactory factory = DAOFactory.getConfiguredFactory();
210 CategoryDAO dao = factory.getCategoryDAO();
211 rootCategory = dao.getCategories(this);
212 } catch (PersistenceException pe) {
213 pe.printStackTrace();
214 }
215
216 refererFilterManager = new RefererFilterManager(this);
217 pluginProperties = new PluginProperties(this);
218 years = new ArrayList();
219
220 // create the various indexes for this blog
221 searchIndex = new SearchIndex(this);
222 blogEntryIndex = new BlogEntryIndex(this);
223 responseIndex = new ResponseIndex(this);
224 tagIndex = new TagIndex(this);
225 categoryIndex = new CategoryIndex(this);
226 authorIndex = new AuthorIndex(this);
227 staticPageIndex = new StaticPageIndex(this);
228
229 decoratorChain = new ContentDecoratorChain(this);
230
231 try {
232 Class c = Class.forName(getCommentConfirmationStrategyName());
233 commentConfirmationStrategy = (CommentConfirmationStrategy)c.newInstance();
234 } catch (Exception e) {
+ 235 error("Could not load comment confirmation strategy \"" + getCommentConfirmationStrategyName() + "\"");
236 e.printStackTrace();
237 commentConfirmationStrategy = new DefaultConfirmationStrategy();
238 }
239
240 try {
241 Class c = Class.forName(getTrackBackConfirmationStrategyName());
242 trackBackConfirmationStrategy = (TrackBackConfirmationStrategy)c.newInstance();
243 } catch (Exception e) {
+ 244 error("Could not load TrackBack confirmation strategy \"" + getTrackBackConfirmationStrategyName() + "\"");
245 e.printStackTrace();
246 trackBackConfirmationStrategy = new DefaultConfirmationStrategy();
247 }
248
249 emailSubscriptionList = new EmailSubscriptionList(this);
250
251 initLogger();
252 initEventDispatcher();
253 initBlogListeners();
254 initBlogEntryListeners();
255 initCommentListeners();
256 initTrackBackListeners();
257 initDecorators();
258 }
259
260 /**
261 * Initialises the logger for this blog.
262 */
/*
P/P * Method: void initLogger()
*
* Preconditions:
* this.properties != null
* (soft) net/sourceforge/pebble/domain/AbstractBlog.log != null
* (soft) this.messages != null
*
* Presumptions:
* java.lang.Class:forName(...)@267 != null
* java.lang.Class:getConstructor(...)@268 != null
* org.apache.commons.logging.LogFactory:getLog(...)@105 != null
*
* Postconditions:
* init'ed(this.logger)
* init'ed(this.messages)
* new CombinedLogFormatLogger(initLogger#4) num objects <= 1
*/
263 private void initLogger() {
264 log.debug("Initializing logger");
265
266 try {
267 Class c = Class.forName(getLoggerName());
268 Constructor cons = c.getConstructor(new Class[] {Blog.class});
269 this.logger = (AbstractLogger)cons.newInstance(new Object[] {this});
270 } catch (Exception e) {
271 error("Could not start logger \"" + getLoggerName() + "\"");
272 e.printStackTrace();
273 this.logger = new CombinedLogFormatLogger(this);
274 }
275 }
276
277 /**
278 * Initialises the event dispatcher for this blog.
279 */
/*
P/P * Method: void initEventDispatcher()
*
* Preconditions:
* (soft) this.properties != null
*
* Presumptions:
* java.lang.Class:forName(...)@285 != null
* org.apache.commons.logging.LogFactory:getLog(...)@105 != null
*
* Postconditions:
* this.eventDispatcher != null
* init'ed(this.eventDispatcher.eventListenerList)
* this.eventListenerList == &new EventListenerList(initEventDispatcher#1)
* new ArrayList(EventListenerList#1) num objects == 1
* new ArrayList(EventListenerList#2) num objects == 1
* new ArrayList(EventListenerList#3) num objects == 1
* new ArrayList(EventListenerList#4) num objects == 1
* new EventListenerList(initEventDispatcher#1) num objects == 1
* new DefaultEventDispatcher(initEventDispatcher#2) num objects <= 1
* init'ed(new DefaultEventDispatcher(initEventDispatcher#2).eventListenerList)
* ...
*/
280 private void initEventDispatcher() {
281 log.debug("Initializing event dispatcher");
282 eventListenerList = new EventListenerList();
283
284 try {
285 Class c = Class.forName(getEventDispatcherName());
286 this.eventDispatcher = (EventDispatcher)c.newInstance();
287 } catch (Exception e) {
288 e.printStackTrace();
289 this.eventDispatcher = new DefaultEventDispatcher();
290 }
291
292 eventDispatcher.setEventListenerList(eventListenerList);
293 }
294
295 /**
296 * Initialises any blog listeners configured for this blog.
297 */
/*
P/P * Method: void initBlogListeners()
*
* Preconditions:
* this.properties != null
* (soft) net/sourceforge/pebble/domain/AbstractBlog.log != null
* (soft) this.messages != null
* (soft) this.eventListenerList != null
* (soft) this.eventListenerList.blogListeners != null
*
* Presumptions:
* java.lang.Class:forName(...)@303 != null
* java.util.Iterator:next(...)@301 != null
* org.apache.commons.logging.LogFactory:getLog(...)@105 != null
*
* Postconditions:
* init'ed(this.messages)
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@301: {1}, {0}
*/
298 private void initBlogListeners() {
299 log.debug("Registering blog listeners");
300
301 for (String className : getBlogListeners()) {
302 try {
303 Class c = Class.forName(className.trim());
304 BlogListener listener = (BlogListener) c.newInstance();
305 eventListenerList.addBlogListener(listener);
306 } catch (Exception e) {
+ 307 error("Could not start blog listener \"" + className + "\" - check the class name is correct on the <a href=\"viewPlugins.secureaction#blogListeners\">plugins page</a>.");
308 log.error("Blog listener " + className + " could not be registered", e);
309 }
310 }
311 }
312
313 /**
314 * Initialises any blog entry listeners configured for this blog.
315 */
/*
P/P * Method: void initBlogEntryListeners()
*
* Preconditions:
* this.eventListenerList != null
* this.eventListenerList.blogEntryListeners != null
* this.properties != null
* (soft) net/sourceforge/pebble/domain/AbstractBlog.log != null
* (soft) this.messages != null
*
* Presumptions:
* java.lang.Class:forName(...)@321 != null
* java.lang.Throwable:getMessage(...)@344 != null
* java.util.Iterator:next(...)@319 != null
* org.apache.commons.logging.LogFactory:getLog(...)@105 != null
*
* Postconditions:
* init'ed(this.messages)
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@319: {1}, {0}
*/
316 private void initBlogEntryListeners() {
317 log.debug("Registering blog entry listeners");
318
319 for (String className : getBlogEntryListeners()) {
320 try {
321 Class c = Class.forName(className.trim());
322 BlogEntryListener listener = (BlogEntryListener) c.newInstance();
323 eventListenerList.addBlogEntryListener(listener);
324 } catch (Exception e) {
+ 325 error("Could not start blog entry listener \"" + className + "\" - check the class name is correct on the <a href=\"viewPlugins.secureaction#blogEntryListeners\">plugins page</a>.");
326 log.error("Blog entry listener " + className + " could not be registered", e);
327 }
328 }
329
330 // these are required to keep the various indexes up to date
331 eventListenerList.addBlogEntryListener(new BlogEntryIndexListener());
332 eventListenerList.addBlogEntryListener(new TagIndexListener());
333 eventListenerList.addBlogEntryListener(new CategoryIndexListener());
334 eventListenerList.addBlogEntryListener(new AuthorIndexListener());
335 eventListenerList.addBlogEntryListener(new SearchIndexListener());
336 eventListenerList.addBlogEntryListener(new AuditListener());
337 try {
338 eventListenerList.addBlogEntryListener(new EmailSubscriptionListener());
339 } catch (Throwable t) {
+ 340 final String text = "Error while starting e-mail subscription listener - add mail.jar and activation.jar to the server classpath if you want to enable this listener.";
+ 341 warn(text);
342 if(t instanceof NoClassDefFoundError &&
343 t.getMessage() != null &&
344 t.getMessage().indexOf("javax/mail/Session") > -1) {
345 log.warn(text); // consider exception already handled well...
346 } else {
347 log.warn(text, t);
348 }
349 }
350 }
351
352 /**
353 * Initialises any comment listeners configured for this blog.
354 */
/*
P/P * Method: void initCommentListeners()
*
* Preconditions:
* this.eventListenerList != null
* this.eventListenerList.commentListeners != null
* this.properties != null
* (soft) net/sourceforge/pebble/domain/AbstractBlog.log != null
* (soft) this.messages != null
*
* Presumptions:
* java.lang.Class:forName(...)@360 != null
* java.util.Iterator:next(...)@358 != null
* org.apache.commons.logging.LogFactory:getLog(...)@105 != null
*
* Postconditions:
* init'ed(this.messages)
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@358: {1}, {0}
*/
355 private void initCommentListeners() {
356 log.debug("Registering comment listeners");
357
358 for (String className : getCommentListeners()) {
359 try {
360 Class c = Class.forName(className.trim());
361 CommentListener listener = (CommentListener) c.newInstance();
362 eventListenerList.addCommentListener(listener);
363 } catch (Exception e) {
+ 364 error("Could not start comment listener \"" + className + "\" - check the class name is correct on the <a href=\"viewPlugins.secureaction#commentListeners\">plugins page</a>.");
365 log.error("Comment listener " + className + " could not be registered", e);
366 }
367 }
368
369 eventListenerList.addCommentListener(new ResponseIndexListener());
370 eventListenerList.addCommentListener(new AuditListener());
371 }
372
373 /**
374 * Initialises any TrackBack listeners configured for this blog.
375 */
/*
P/P * Method: void initTrackBackListeners()
*
* Preconditions:
* this.eventListenerList != null
* this.eventListenerList.trackBackListeners != null
* this.properties != null
* (soft) net/sourceforge/pebble/domain/AbstractBlog.log != null
* (soft) this.messages != null
*
* Presumptions:
* java.lang.Class:forName(...)@381 != null
* java.util.Iterator:next(...)@379 != null
* org.apache.commons.logging.LogFactory:getLog(...)@105 != null
*
* Postconditions:
* init'ed(this.messages)
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@379: {1}, {0}
*/
376 private void initTrackBackListeners() {
377 log.debug("Registering TrackBack listeners");
378
379 for (String className : getTrackBackListeners()) {
380 try {
381 Class c = Class.forName(className.trim());
382 TrackBackListener listener = (TrackBackListener) c.newInstance();
383 eventListenerList.addTrackBackListener(listener);
384 } catch (Exception e) {
+ 385 error("Could not start TrackBack listener \"" + className + "\" - check the class name is correct on the <a href=\"viewPlugins.secureaction#trackbackListeners\">plugins page</a>.");
386 log.error("TrackBack listener " + className + " could not be registered", e);
387 }
388 }
389
390 eventListenerList.addTrackBackListener(new ResponseIndexListener());
391 eventListenerList.addTrackBackListener(new AuditListener());
392 }
393
394 /**
395 * Initialises any content decorators configufred for this blog.
396 */
/*
P/P * Method: void initDecorators()
*
* Preconditions:
* this.decoratorChain != null
* this.decoratorChain.decorators != null
* this.properties != null
* (soft) net/sourceforge/pebble/domain/AbstractBlog.log != null
* (soft) this.messages != null
*
* Presumptions:
* java.lang.Class:forName(...)@404 != null
* java.util.Iterator:next(...)@402 != null
* org.apache.commons.logging.LogFactory:getLog(...)@105 != null
*
* Postconditions:
* init'ed(this.messages)
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@402: {1}, {0}
*/
397 private void initDecorators() {
398 log.debug("Registering decorators");
399
400 decoratorChain.add(new HideUnapprovedResponsesDecorator());
401
402 for (String className : getContentDecorators()) {
403 try {
404 Class c = Class.forName(className.trim());
405 ContentDecorator decorator = (ContentDecorator) c.newInstance();
406 decorator.setBlog(this);
407 decoratorChain.add(decorator);
408 } catch (Exception e) {
+ 409 error("Could not start decorator \"" + className + "\" - check the class name is correct on the <a href=\"viewPlugins.secureaction#contentDecorators\">plugins page</a>.");
410 e.printStackTrace();
411 log.error(className + " could not be started", e);
412 }
413 }
414 }
415
416 /**
417 * Gets the default properties for a Blog.
418 *
419 * @return a Properties instance
420 */
/*
P/P * Method: Properties getDefaultProperties()
*
* Postconditions:
* return_value == &new Properties(getDefaultProperties#1)
* new Properties(getDefaultProperties#1) num objects == 1
*/
421 protected Properties getDefaultProperties() {
422 Properties defaultProperties = new Properties();
423 defaultProperties.setProperty(NAME_KEY, "My blog");
424 defaultProperties.setProperty(DESCRIPTION_KEY, "");
425 defaultProperties.setProperty(IMAGE_KEY, "");
426 defaultProperties.setProperty(AUTHOR_KEY, "Blog Owner");
427 defaultProperties.setProperty(EMAIL_KEY, "blog@yourdomain.com");
428 defaultProperties.setProperty(TIMEZONE_KEY, "Europe/London");
429 defaultProperties.setProperty(LANGUAGE_KEY, "en");
430 defaultProperties.setProperty(COUNTRY_KEY, "GB");
431 defaultProperties.setProperty(CHARACTER_ENCODING_KEY, "UTF-8");
432 defaultProperties.setProperty(RECENT_BLOG_ENTRIES_ON_HOME_PAGE_KEY, "3");
433 defaultProperties.setProperty(RECENT_RESPONSES_ON_HOME_PAGE_KEY, "3");
434 defaultProperties.setProperty(THEME_KEY, "default");
435 defaultProperties.setProperty(PRIVATE_KEY, FALSE);
436 defaultProperties.setProperty(LUCENE_ANALYZER_KEY, "org.apache.lucene.analysis.SimpleAnalyzer");
437 defaultProperties.setProperty(CONTENT_DECORATORS_KEY,
438 "net.sourceforge.pebble.decorator.RadeoxDecorator\n" +
439 "net.sourceforge.pebble.decorator.HtmlDecorator\n" +
440 "net.sourceforge.pebble.decorator.EscapeMarkupDecorator\n" +
441 "net.sourceforge.pebble.decorator.RelativeUriDecorator\n" +
442 "net.sourceforge.pebble.decorator.ReadMoreDecorator\n" +
443 "net.sourceforge.pebble.decorator.BlogTagsDecorator");
444 defaultProperties.setProperty(BLOG_ENTRY_LISTENERS_KEY,
445 "net.sourceforge.pebble.event.blogentry.XmlRpcNotificationListener");
446 defaultProperties.setProperty(COMMENT_LISTENERS_KEY,
447 "net.sourceforge.pebble.event.response.IpAddressListener\r\n" +
448 "net.sourceforge.pebble.event.response.LinkSpamListener\r\n" +
449 "net.sourceforge.pebble.event.response.ContentSpamListener\r\n" +
450 "net.sourceforge.pebble.event.response.SpamScoreListener\r\n" +
451 "net.sourceforge.pebble.event.response.MarkApprovedWhenAuthenticatedListener\r\n" +
452 "#net.sourceforge.pebble.event.response.DeleteRejectedListener\r\n" +
453 "#net.sourceforge.pebble.event.comment.EmailAuthorNotificationListener");
454 defaultProperties.setProperty(TRACKBACK_LISTENERS_KEY,
455 "net.sourceforge.pebble.event.response.IpAddressListener\r\n" +
456 "net.sourceforge.pebble.event.response.LinkSpamListener\r\n" +
457 "net.sourceforge.pebble.event.response.ContentSpamListener\r\n" +
458 "net.sourceforge.pebble.event.response.SpamScoreListener\r\n" +
459 "net.sourceforge.pebble.event.response.MarkApprovedWhenAuthenticatedListener\r\n" +
460 "#net.sourceforge.pebble.event.response.DeleteRejectedListener\r\n" +
461 "#net.sourceforge.pebble.event.trackback.EmailAuthorNotificationListener");
462 defaultProperties.setProperty(PERMALINK_PROVIDER_KEY, "net.sourceforge.pebble.permalink.DefaultPermalinkProvider");
463 defaultProperties.setProperty(EVENT_DISPATCHER_KEY, "net.sourceforge.pebble.event.DefaultEventDispatcher");
464 defaultProperties.setProperty(LOGGER_KEY, "net.sourceforge.pebble.logging.CombinedLogFormatLogger");
465 defaultProperties.setProperty(COMMENT_CONFIRMATION_STRATEGY_KEY, "net.sourceforge.pebble.confirmation.DefaultConfirmationStrategy");
466 defaultProperties.setProperty(TRACKBACK_CONFIRMATION_STRATEGY_KEY, "net.sourceforge.pebble.confirmation.DefaultConfirmationStrategy");
467 defaultProperties.setProperty(RICH_TEXT_EDITOR_FOR_COMMENTS_ENABLED_KEY, "true");
468
469 return defaultProperties;
470 }
471
472 /**
473 * Gets the ID of this blog.
474 *
475 * @return the ID as a String
476 */
/*
P/P * Method: String getId()
*
* Preconditions:
* init'ed(this.id)
*
* Postconditions:
* return_value == this.id
* init'ed(return_value)
*/
477 public String getId() {
478 return this.id;
479 }
480
481 /**
482 * Sets the ID of this blog.
483 *
484 * @param id the ID as a String
485 */
/*
P/P * Method: void setId(String)
*
* Postconditions:
* this.id == id
* init'ed(this.id)
*/
486 public void setId(String id) {
487 this.id = id;
488 }
489
490 /**
491 * Gets the URL where this blog is deployed.
492 *
493 * @return a URL as a String
494 */
/*
P/P * Method: String getUrl()
*
* Preconditions:
* (soft) net/sourceforge/pebble/domain/BlogManager.instance != null
* (soft) init'ed(net/sourceforge/pebble/domain/BlogManager.instance.multiBlog)
* (soft) init'ed(this.id)
*
* Presumptions:
* java.lang.String:indexOf(...)@503 <= 232-4
* net.sourceforge.pebble.PebbleContext:getConfiguration(...)@496 != null
* net.sourceforge.pebble.PebbleContext:getInstance(...)@496 != null
*
* Postconditions:
* return_value != null
*
* Test Vectors:
* net/sourceforge/pebble/domain/BlogManager.instance.multiBlog: {0}, {1}
* config.url@496: Addr_Set{null}, Inverse{null}
* config.virtualHostingEnabled@496: {0}, {1}
* java.lang.String:length(...)@499: {1..232-1}, {0}
*/
495 public String getUrl() {
496 Configuration config = PebbleContext.getInstance().getConfiguration();
497 String url = config.getUrl();
498
499 if (url == null || url.length() == 0) {
500 return "";
501 } else if (BlogManager.getInstance().isMultiBlog()) {
502 if (config.isVirtualHostingEnabled()) {
503 return url.substring(0, url.indexOf("://")+3) + getId() + "." + url.substring(url.indexOf("://")+3);
504 } else {
505 return url + getId() + "/";
506 }
507 } else {
508 return url;
509 }
510 }
511
512 /**
513 * Gets the relative URL where this blog is deployed.
514 *
515 * @return a URL as a String
516 */
/*
P/P * Method: String getRelativeUrl()
*
* Preconditions:
* net/sourceforge/pebble/domain/BlogManager.instance != null
* init'ed(net/sourceforge/pebble/domain/BlogManager.instance.multiBlog)
* (soft) init'ed(this.id)
*
* Postconditions:
* return_value != null
*
* Test Vectors:
* net/sourceforge/pebble/domain/BlogManager.instance.multiBlog: {0}, {1}
*/
517 public String getRelativeUrl() {
518 if (BlogManager.getInstance().isMultiBlog()) {
519 return "/" + getId() + "/";
520 } else {
521 return "/";
522 }
523 }
524
525 /**
526 * Gets the about description of this blog.
527 *
528 * @return a String
529 */
/*
P/P * Method: String getAbout()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
530 public String getAbout() {
531 return properties.getProperty(ABOUT_KEY);
532 }
533
534 /**
535 * Gets the home page to be used for this blog.
536 *
537 * @return a String
538 */
/*
P/P * Method: String getHomePage()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
539 public String getHomePage() {
540 return properties.getProperty(HOME_PAGE_KEY);
541 }
542
543 /**
544 * Gets the e-mail address of the blog owner.
545 *
546 * @return the e-mail address
547 */
/*
P/P * Method: String getEmail()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
548 public String getEmail() {
549 return properties.getProperty(EMAIL_KEY);
550 }
551
552 /**
553 * Gets a Collection of e-mail addresses.
554 *
555 * @return a Collection of String instances
556 */
/*
P/P * Method: Collection getEmailAddresses()
*
* Preconditions:
* this.properties != null
*
* Presumptions:
* java.util.Properties:getProperty(...)@549 != null
*
* Postconditions:
* init'ed(return_value)
*/
557 public Collection getEmailAddresses() {
558 return Arrays.asList(getEmail().split(","));
559 }
560
561 /**
562 * Gets the first of multiple e-mail addresses.
563 *
564 * @return the firt e-mail address as a String
565 */
/*
P/P * Method: String getFirstEmailAddress()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*
* Test Vectors:
* java.util.Arrays:asList(...)@558: Addr_Set{null}, Inverse{null}
* java.util.Collection:isEmpty(...)@568: {1}, {0}
*/
566 public String getFirstEmailAddress() {
567 Collection emailAddresses = getEmailAddresses();
568 if (emailAddresses != null && !emailAddresses.isEmpty()) {
569 return (String)emailAddresses.iterator().next();
570 } else {
571 return "";
572 }
573 }
574
575 /**
576 * Gets a comma separated list of the users that are blog owners
577 * for this blog.
578 *
579 * @return a String containng a comma separated list of user names
580 */
/*
P/P * Method: String getBlogOwnersAsString()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
581 public String getBlogOwnersAsString() {
582 return properties.getProperty(BLOG_OWNERS_KEY);
583 }
584
585 /**
586 * Gets a list of the users that are blog owners for this blog.
587 *
588 * @return a String containng a comma separated list of user names
589 */
/*
P/P * Method: List getBlogOwners()
*
* Preconditions:
* this.properties != null
*
* Presumptions:
* java.util.StringTokenizer:nextToken(...)@596 != null
*
* Postconditions:
* return_value == &new LinkedList(getBlogOwners#1)
* new LinkedList(getBlogOwners#1) num objects == 1
*
* Test Vectors:
* java.util.Properties:getProperty(...)@582: Addr_Set{null}, Inverse{null}
* java.util.StringTokenizer:hasMoreTokens(...)@595: {1}, {0}
*/
590 public List<String> getBlogOwners() {
591 String commaSeparatedUsers = getBlogOwnersAsString();
592 List<String> users = new LinkedList<String>();
593 if (commaSeparatedUsers != null) {
594 StringTokenizer tok = new StringTokenizer(commaSeparatedUsers, ",");
595 while (tok.hasMoreTokens()) {
596 users.add(tok.nextToken().trim());
597 }
598 }
599
600 return users;
601 }
602
603 /**
604 * Gets a comma separated list of the users that are blog publishers
605 * for this blog.
606 *
607 * @return a String containng a comma separated list of user names
608 */
/*
P/P * Method: String getBlogPublishersAsString()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
609 public String getBlogPublishersAsString() {
610 return properties.getProperty(BLOG_PUBLISHERS_KEY);
611 }
612
613 /**
614 * Gets a list of the users that are blog publishers for this blog.
615 *
616 * @return a String containng a comma separated list of user names
617 */
/*
P/P * Method: List getBlogPublishers()
*
* Preconditions:
* this.properties != null
*
* Presumptions:
* java.util.StringTokenizer:nextToken(...)@624 != null
*
* Postconditions:
* return_value == &new LinkedList(getBlogPublishers#1)
* new LinkedList(getBlogPublishers#1) num objects == 1
*
* Test Vectors:
* java.util.Properties:getProperty(...)@610: Addr_Set{null}, Inverse{null}
* java.util.StringTokenizer:hasMoreTokens(...)@623: {1}, {0}
*/
618 public List<String> getBlogPublishers() {
619 String commaSeparatedUsers = getBlogPublishersAsString();
620 List<String> users = new LinkedList<String>();
621 if (commaSeparatedUsers != null) {
622 StringTokenizer tok = new StringTokenizer(commaSeparatedUsers, ",");
623 while (tok.hasMoreTokens()) {
624 users.add(tok.nextToken().trim());
625 }
626 }
627
628 return users;
629 }
630
631 /**
632 * Gets a comma separated list of the users that are blog contributors
633 * for this blog.
634 *
635 * @return a String containng a comma separated list of user names
636 */
/*
P/P * Method: String getBlogContributorsAsString()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
637 public String getBlogContributorsAsString() {
638 return properties.getProperty(BLOG_CONTRIBUTORS_KEY);
639 }
640
641 /**
642 * Gets a list of the users that are blog contributors for this blog.
643 *
644 * @return a String containng a comma separated list of user names
645 */
/*
P/P * Method: List getBlogContributors()
*
* Preconditions:
* this.properties != null
*
* Presumptions:
* java.util.StringTokenizer:nextToken(...)@652 != null
*
* Postconditions:
* return_value == &new LinkedList(getBlogContributors#1)
* new LinkedList(getBlogContributors#1) num objects == 1
*
* Test Vectors:
* java.util.Properties:getProperty(...)@638: Addr_Set{null}, Inverse{null}
* java.util.StringTokenizer:hasMoreTokens(...)@651: {1}, {0}
*/
646 public List<String> getBlogContributors() {
647 String commaSeparatedUsers = getBlogContributorsAsString();
648 List<String> users = new LinkedList<String>();
649 if (commaSeparatedUsers != null) {
650 StringTokenizer tok = new StringTokenizer(commaSeparatedUsers, ",");
651 while (tok.hasMoreTokens()) {
652 users.add(tok.nextToken().trim());
653 }
654 }
655
656 return users;
657 }
658
659 /**
660 * Gets a comma separated list of the users that are blog readers
661 * for this blog.
662 *
663 * @return a String containng a comma separated list of user names
664 */
/*
P/P * Method: String getBlogReadersAsString()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
665 public String getBlogReadersAsString() {
666 return properties.getProperty(BLOG_READERS_KEY);
667 }
668
669 /**
670 * Gets a list of the users that are blog readers for this blog.
671 *
672 * @return a String containng a comma separated list of user names
673 */
/*
P/P * Method: List getBlogReaders()
*
* Preconditions:
* this.properties != null
*
* Presumptions:
* java.util.StringTokenizer:nextToken(...)@680 != null
*
* Postconditions:
* return_value == &new LinkedList(getBlogReaders#1)
* new LinkedList(getBlogReaders#1) num objects == 1
*
* Test Vectors:
* java.util.Properties:getProperty(...)@666: Addr_Set{null}, Inverse{null}
* java.util.StringTokenizer:hasMoreTokens(...)@679: {1}, {0}
*/
674 public List<String> getBlogReaders() {
675 String commaSeparatedUsers = getBlogReadersAsString();
676 List<String> users = new LinkedList<String>();
677 if (commaSeparatedUsers != null) {
678 StringTokenizer tok = new StringTokenizer(commaSeparatedUsers, ",");
679 while (tok.hasMoreTokens()) {
680 users.add(tok.nextToken().trim());
681 }
682 }
683
684 return users;
685 }
686
687 /**
688 * Gets the name of the Lucene analyzer to use.
689 *
690 * @return a fully qualified class name
691 */
/*
P/P * Method: String getLuceneAnalyzer()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
692 public String getLuceneAnalyzer() {
693 return properties.getProperty(LUCENE_ANALYZER_KEY);
694 }
695
696 /**
697 * Gets the name of the logger in use.
698 *
699 * @return a fully qualified class name
700 */
/*
P/P * Method: String getLoggerName()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
701 public String getLoggerName() {
702 return properties.getProperty(LOGGER_KEY);
703 }
704
705 /**
706 * Gets a Collection containing the names of users that are blog owners
707 * for this blog.
708 *
709 * @return a Collection containng user names as Strings
710 */
/*
P/P * Method: Collection getUsersInRole(String)
*
* Preconditions:
* init'ed(net/sourceforge/pebble/Constants.BLOG_OWNER_ROLE)
* roleName != null
* (soft) init'ed(net/sourceforge/pebble/Constants.BLOG_CONTRIBUTOR_ROLE)
* (soft) init'ed(net/sourceforge/pebble/Constants.BLOG_PUBLISHER_ROLE)
* (soft) init'ed(net/sourceforge/pebble/Constants.BLOG_READER_ROLE)
* (soft) this.properties != null
*
* Postconditions:
* return_value == One-of{&new LinkedList(getBlogOwners#1), &new LinkedList(getBlogPublishers#1), &new LinkedList(getBlogContributors#1), &new LinkedList(getUsersInRole#1), &new LinkedList(getBlogReaders#1)}
* return_value in Addr_Set{&new LinkedList(getUsersInRole#1),&new LinkedList(getBlogContributors#1),&new LinkedList(getBlogReaders#1),&new LinkedList(getBlogOwners#1),&new LinkedList(getBlogPublishers#1)}
* new LinkedList(getBlogContributors#1) num objects <= 1
* new LinkedList(getBlogOwners#1) num objects <= 1
* new LinkedList(getBlogPublishers#1) num objects <= 1
* new LinkedList(getBlogReaders#1) num objects <= 1
* new LinkedList(getUsersInRole#1) num objects == 1
*
* Test Vectors:
* java.lang.String:equals(...)@714: {0}, {1}
* java.lang.String:equals(...)@716: {0}, {1}
* java.lang.String:equals(...)@718: {0}, {1}
* java.lang.String:equals(...)@720: {0}, {1}
*/
711 public Collection getUsersInRole(String roleName) {
712 List<String> users = new LinkedList<String>();
713
714 if (roleName.equals(Constants.BLOG_OWNER_ROLE)) {
715 users = getBlogOwners();
716 } else if (roleName.equals(Constants.BLOG_PUBLISHER_ROLE)) {
717 users = getBlogPublishers();
718 } else if (roleName.equals(Constants.BLOG_CONTRIBUTOR_ROLE)) {
719 users = getBlogContributors();
720 } else if (roleName.equals(Constants.BLOG_READER_ROLE)) {
721 users = getBlogReaders();
722 }
723
724 return users;
725 }
726
727 /**
728 * Determines whether the specified user is in the specified role.
729 *
730 * @param roleName the name of the role
731 * @param user the name of the user
732 * @return true if the user is a member of the role or the list of users
733 * is empty, false otherwise
734 */
/*
P/P * Method: bool isUserInRole(String, String)
*
* Preconditions:
* init'ed(net/sourceforge/pebble/Constants.BLOG_OWNER_ROLE)
* roleName != null
* (soft) init'ed(net/sourceforge/pebble/Constants.BLOG_CONTRIBUTOR_ROLE)
* (soft) init'ed(net/sourceforge/pebble/Constants.BLOG_PUBLISHER_ROLE)
* (soft) init'ed(net/sourceforge/pebble/Constants.BLOG_READER_ROLE)
* (soft) this.properties != null
*
* Postconditions:
* init'ed(return_value)
*
* Test Vectors:
* java.util.Collection:contains(...)@737: {0}, {1}
* java.util.Collection:isEmpty(...)@737: {1}, {0}
*/
735 public boolean isUserInRole(String roleName, String user) {
736 Collection users = getUsersInRole(roleName);
737 if (users.isEmpty() || users.contains(user)) {
738 return true;
739 }
740
741 return false;
742 }
743
744 /**
745 * Gets the Year instance for the specified year.
746 *
747 * @param year the year as an int (e.g. 2003)
748 * @return a Year instance
749 */
/*
P/P * Method: Year getBlogForYear(int)
*
* Preconditions:
* this.years != null
*
* Presumptions:
* java.util.Iterator:next(...)@754 != null
*
* Postconditions:
* (soft) return_value != null
* init'ed(new ArrayList(Day#1) num objects)
* init'ed(new ArrayList(Day#2) num objects)
* init'ed(new ArrayList(Day#3) num objects)
* init'ed(new Day(Month#2) num objects)
* init'ed(new Day(Month#2).blog)
* init'ed(new Day(Month#2).blogEntries)
* init'ed(new Day(Month#2).date)
* init'ed(new Day(Month#2).day)
* init'ed(new Day(Month#2).month)
* ...
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@753: {1}, {0}
*/
750 public Year getBlogForYear(int year) {
751 Iterator it = years.iterator();
752 Year y;
753 while (it.hasNext()) {
754 y = (Year)it.next();
755 if (y.getYear() == year) {
756 return y;
757 }
758 }
759
760 y = new Year(this, year);
761 years.add(y);
762 Collections.sort(years);
763
764 return y;
765 }
766
767 /**
768 * Gets the Year instance representing this year.
769 *
770 * @return a Year instance for this year
771 */
/*
P/P * Method: Year getBlogForThisYear()
*
* Preconditions:
* this.properties != null
* this.years != null
*
* Presumptions:
* java.util.Calendar:getInstance(...)@329 != null
*
* Postconditions:
* return_value != null
* init'ed(new ArrayList(Day#1) num objects)
* init'ed(new ArrayList(Day#2) num objects)
* init'ed(new ArrayList(Day#3) num objects)
* init'ed(new Day(Month#2) num objects)
* init'ed(new Day(Month#2).blog)
* init'ed(new Day(Month#2).blogEntries)
* init'ed(new Day(Month#2).date)
* init'ed(new Day(Month#2).day)
* init'ed(new Day(Month#2).month)
* ...
*/
772 public Year getBlogForThisYear() {
773 Calendar cal = getCalendar();
774 return getBlogForYear(cal.get(Calendar.YEAR));
775 }
776
777 /**
778 * Gets all Years managed by this root blog.
779 *
780 * @return a Collection of Year instances
781 */
/*
P/P * Method: List getYears()
*
* Preconditions:
* init'ed(this.years)
*
* Postconditions:
* return_value == this.years
* init'ed(return_value)
*/
782 public List getYears() {
783 return years;
784 }
785
786 /**
787 * Gets all Years managed by this root blog, in reverse order.
788 *
789 * @return a Collection of Year instances
790 */
/*
P/P * Method: List getArchives()
*
* Preconditions:
* init'ed(this.blogEntryIndex)
* this.years != null
* (soft) init'ed(this.blogEntryIndex.indexEntries)
* (soft) this.properties != null
*
* Presumptions:
* getBlogForFirstMonth(...).year@793 != null
* java.util.Iterator:next(...)@797 != null
*
* Postconditions:
* return_value == &new LinkedList(getArchives#1)
* new LinkedList(getArchives#1) num objects == 1
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@797: {1}, {0}
*/
791 public List<Year> getArchives() {
792 List<Year> list = new LinkedList<Year>();
+ 793 int firstYear = getBlogForFirstMonth().getYear().getYear();
794 int thisYear = getBlogForThisYear().getYear();
795 // only add years that are in range
+ 796 Calendar cal = getCalendar();
797 for (Year year : years) {
798 if (year.getYear() >= firstYear && year.getYear() <= thisYear) {
799 list.add(year);
800 }
801 }
802 Collections.reverse(list);
803 return list;
804 }
805
806 /**
807 * Gets the Month instance representing the first month that
808 * contains blog entries.
809 *
810 * @return a Month instance
811 */
/*
P/P * Method: Month getBlogForFirstMonth()
*
* Preconditions:
* init'ed(this.blogEntryIndex)
* (soft) init'ed(this.blogEntryIndex.indexEntries)
* (soft) this.properties != null
* (soft) this.years != null
*
* Presumptions:
* java.util.List:size(...)@822 >= -231+1
*
* Postconditions:
* init'ed(return_value)
* init'ed(new ArrayList(Day#1) num objects)
* init'ed(new ArrayList(Day#2) num objects)
* init'ed(new ArrayList(Day#3) num objects)
* init'ed(new Day(Month#2) num objects)
* init'ed(new Day(Month#2).blog)
* init'ed(new Day(Month#2).blogEntries)
* init'ed(new Day(Month#2).date)
* init'ed(new Day(Month#2).day)
* init'ed(new Day(Month#2).month)
* ...
*
* Test Vectors:
* this.blogEntryIndex: Inverse{null}, Addr_Set{null}
* java.util.List:get(...)@822: Inverse{null}, Addr_Set{null}
* java.util.List:isEmpty(...)@818: {0}, {1}
*/
812 public Month getBlogForFirstMonth() {
813 if (getBlogEntryIndex() == null) {
814 return getBlogForThisMonth();
815 }
816
817 List<String> blogEntryIds = getBlogEntryIndex().getBlogEntries();
+ 818 if (blogEntryIds == null || blogEntryIds.isEmpty()) {
819 return getBlogForThisMonth();
820 }
821
822 String firstBlogEntryId = blogEntryIds.get(blogEntryIds.size()-1);
823 if (firstBlogEntryId == null) {
824 return getBlogForThisMonth();
825 }
826
827 long dateInMillis = Long.parseLong(firstBlogEntryId);
828 Date date = new Date(dateInMillis);
+ 829 return getBlogForDay(date).getMonth();
830 }
831
832 /**
833 * Gets a Day intance for the specified Date.
834 *
835 * @param date a java.util.Date instance
836 * @return a Day instance representing the specified Date
837 */
/*
P/P * Method: Day getBlogForDay(Date)
*
* Preconditions:
* this.properties != null
* this.years != null
*
* Presumptions:
* java.util.Calendar:get(...)@843 in 0..11
* java.util.Calendar:get(...)@844 >= 1
* java.util.Calendar:getInstance(...)@329 != null
*
* Postconditions:
* init'ed(return_value)
* init'ed(new ArrayList(Day#1) num objects)
* init'ed(new ArrayList(Day#2) num objects)
* init'ed(new ArrayList(Day#3) num objects)
* init'ed(new Day(Month#2) num objects)
* init'ed(new Day(Month#2).blog)
* init'ed(new Day(Month#2).blogEntries)
* init'ed(new Day(Month#2).date)
* init'ed(new Day(Month#2).day)
* init'ed(new Day(Month#2).month)
* ...
*/
838 public Day getBlogForDay(Date date) {
839 Calendar cal = getCalendar();
840 cal.setTime(date);
841
842 int year = cal.get(Calendar.YEAR);
843 int month = (cal.get(Calendar.MONTH) + 1);
844 int day = cal.get(Calendar.DAY_OF_MONTH);
845
846 return getBlogForDay(year, month, day);
847 }
848
849 /**
850 * Gets the Day instance for today.
851 *
852 * @return a Day instance
853 */
/*
P/P * Method: Day getBlogForToday()
*
* Preconditions:
* this.properties != null
* this.years != null
*
* Presumptions:
* java.util.Calendar:getInstance(...)@329 != null
*
* Postconditions:
* init'ed(return_value)
* init'ed(new ArrayList(Day#1) num objects)
* init'ed(new ArrayList(Day#2) num objects)
* init'ed(new ArrayList(Day#3) num objects)
* init'ed(new Day(Month#2) num objects)
* init'ed(new Day(Month#2).blog)
* init'ed(new Day(Month#2).blogEntries)
* init'ed(new Day(Month#2).date)
* init'ed(new Day(Month#2).day)
* init'ed(new Day(Month#2).month)
* ...
*/
854 public Day getBlogForToday() {
855 return this.getBlogForDay(getCalendar().getTime());
856 }
857
858 /**
859 * Gets a Day intance for the specified year, month and day.
860 *
861 * @param year the year as an int
862 * @param month the month as an int
863 * @param day the day as an int
864 * @return a Day instance representing the specified year, month and day
865 */
/*
P/P * Method: Day getBlogForDay(int, int, int)
*
* Preconditions:
* day >= 1
* month in 1..12
* this.years != null
*
* Presumptions:
* getBlogForMonth(...).dailyBlogs.length@867 >= 1
* getBlogForMonth(...).dailyBlogs@867 != null
* getBlogForMonth(...).lastDayInMonth@867 >= 1
*
* Postconditions:
* init'ed(return_value)
* init'ed(new ArrayList(Day#1) num objects)
* init'ed(new ArrayList(Day#2) num objects)
* init'ed(new ArrayList(Day#3) num objects)
* init'ed(new Day(Month#2) num objects)
* init'ed(new Day(Month#2).blog)
* init'ed(new Day(Month#2).blogEntries)
* init'ed(new Day(Month#2).date)
* init'ed(new Day(Month#2).day)
* init'ed(new Day(Month#2).month)
* ...
*/
866 public Day getBlogForDay(int year, int month, int day) {
+ 867 return getBlogForMonth(year, month).getBlogForDay(day);
868 }
869
870 /**
871 * Gets a Month intance for the specified year and month.
872 *
873 * @param year the year as an int
874 * @param month the month as an int
875 * @return a Month instance representing the specified year and month
876 */
/*
P/P * Method: Month getBlogForMonth(int, int)
*
* Preconditions:
* month in 1..12
* this.years != null
*
* Presumptions:
* getBlogForYear(...).months.length@878 >= 1
* month <= getBlogForYear(...).months.length@878
* getBlogForYear(...).months@878 != null
*
* Postconditions:
* init'ed(return_value)
* init'ed(new ArrayList(Day#1) num objects)
* init'ed(new ArrayList(Day#2) num objects)
* init'ed(new ArrayList(Day#3) num objects)
* init'ed(new Day(Month#2) num objects)
* init'ed(new Day(Month#2).blog)
* init'ed(new Day(Month#2).blogEntries)
* init'ed(new Day(Month#2).date)
* init'ed(new Day(Month#2).day)
* init'ed(new Day(Month#2).month)
* ...
*/
877 public Month getBlogForMonth(int year, int month) {
878 return getBlogForYear(year).getBlogForMonth(month);
879 }
880
881 /**
882 * Gets the Month instance representing this month.
883 *
884 * @return a Month instance for this month
885 */
/*
P/P * Method: Month getBlogForThisMonth()
*
* Preconditions:
* this.properties != null
* this.years != null
*
* Presumptions:
* java.util.Calendar:get(...)@888 in 0..11
* java.util.Calendar:getInstance(...)@329 != null
*
* Postconditions:
* init'ed(return_value)
* init'ed(new ArrayList(Day#1) num objects)
* init'ed(new ArrayList(Day#2) num objects)
* init'ed(new ArrayList(Day#3) num objects)
* init'ed(new Day(Month#2) num objects)
* init'ed(new Day(Month#2).blog)
* init'ed(new Day(Month#2).blogEntries)
* init'ed(new Day(Month#2).date)
* init'ed(new Day(Month#2).day)
* init'ed(new Day(Month#2).month)
* ...
*/
886 public Month getBlogForThisMonth() {
887 Calendar cal = getCalendar();
888 return getBlogForMonth(cal.get(Calendar.YEAR), (cal.get(Calendar.MONTH) + 1));
889 }
890
891 /**
892 * Given a Year, this method returns the Year instance
893 * representing the previous year.
894 *
895 * @param year a Year instance
896 * @return a Year representing the previous year
897 */
/*
P/P * Method: Year getBlogForPreviousYear(Year)
*
* Preconditions:
* this.years != null
* year != null
* year.year >= -231+1
*
* Postconditions:
* return_value != null
* init'ed(new ArrayList(Day#1) num objects)
* init'ed(new ArrayList(Day#2) num objects)
* init'ed(new ArrayList(Day#3) num objects)
* init'ed(new Day(Month#2) num objects)
* init'ed(new Day(Month#2).blog)
* init'ed(new Day(Month#2).blogEntries)
* init'ed(new Day(Month#2).date)
* init'ed(new Day(Month#2).day)
* init'ed(new Day(Month#2).month)
* ...
*/
898 public Year getBlogForPreviousYear(Year year) {
899 return getBlogForYear(year.getYear() - 1);
900 }
901
902 /**
903 * Given a Year, this method returns the Year instance
904 * representing the next year.
905 *
906 * @param year a Year instance
907 * @return a Year representing the next year
908 */
/*
P/P * Method: Year getBlogForNextYear(Year)
*
* Preconditions:
* this.years != null
* year != null
* year.year <= 232-2
*
* Postconditions:
* return_value != null
* init'ed(new ArrayList(Day#1) num objects)
* init'ed(new ArrayList(Day#2) num objects)
* init'ed(new ArrayList(Day#3) num objects)
* init'ed(new Day(Month#2) num objects)
* init'ed(new Day(Month#2).blog)
* init'ed(new Day(Month#2).blogEntries)
* init'ed(new Day(Month#2).date)
* init'ed(new Day(Month#2).day)
* init'ed(new Day(Month#2).month)
* ...
*/
909 public Year getBlogForNextYear(Year year) {
910 return getBlogForYear(year.getYear() + 1);
911 }
912
913 /**
914 * Gets all blog entries for this blog.
915 *
916 * @return a List of BlogEntry objects
917 */
/*
P/P * Method: List getBlogEntries()
*
* Preconditions:
* this.years != null
*
* Presumptions:
* java.util.List:get(...)@923 != null
* java.util.List:size(...)@922 >= -231+1
* months[month].month@924 in 1..12
* org.apache.commons.logging.LogFactory:getLog(...)@105 != null
* y.months.length@923 >= 1
* ...
*
* Postconditions:
* return_value == &new ArrayList(getBlogEntries#1)
* new ArrayList(getBlogEntries#1) num objects == 1
*/
918 public List getBlogEntries() {
919 List blogEntries = new ArrayList();
920 BlogService service = new BlogService();
921
922 for (int year = years.size()-1; year >= 0; year--) {
923 Year y = (Year)years.get(year);
924 Month[] months = y.getMonths();
925 for (int month = 11; month >= 0; month--) {
926 try {
+ 927 blogEntries.addAll(service.getBlogEntries(this, y.getYear(), months[month].getMonth()));
928 } catch (BlogServiceException e) {
929 log.error("Exception encountered", e);
930 }
931 }
932 }
933
934 return blogEntries;
935 }
936
937 /**
938 * Gets all unpublished blog entries for this blog.
939 *
940 * @return a List of BlogEntry objects
941 */
/*
P/P * Method: List getUnpublishedBlogEntries()
*
* Preconditions:
* this.blogEntryIndex != null
* init'ed(this.blogEntryIndex.unpublishedIndexEntries)
*
* Presumptions:
* org.apache.commons.logging.LogFactory:getLog(...)@105 != null
*
* Postconditions:
* return_value == &new ArrayList(getUnpublishedBlogEntries#1)
* new ArrayList(getUnpublishedBlogEntries#1) num objects == 1
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@947: {1}, {0}
*/
942 public List<BlogEntry> getUnpublishedBlogEntries() {
943 List<BlogEntry> blogEntries = new ArrayList<BlogEntry>();
944 BlogService service = new BlogService();
945
946 List<String> blogEntryIds = blogEntryIndex.getUnpublishedBlogEntries();
947 for (String blogEntryId : blogEntryIds) {
948 try {
949 blogEntries.add(service.getBlogEntry(this, blogEntryId));
950 } catch (BlogServiceException e) {
951 log.error("Exception encountered", e);
952 }
953 }
954
955 return blogEntries;
956 }
957
958 /**
959 * Gets the number of blog entries for this blog.
960 *
961 * @return an int
962 */
/*
P/P * Method: int getNumberOfBlogEntries()
*
* Preconditions:
* this.blogEntryIndex != null
* this.blogEntryIndex.indexEntries != null
*
* Postconditions:
* init'ed(return_value)
*/
963 public int getNumberOfBlogEntries() {
964 return blogEntryIndex.getNumberOfBlogEntries();
965 }
966
967 /**
968 * Gets the number of published blog entries for this blog.
969 *
970 * @return an int
971 */
/*
P/P * Method: int getNumberOfPublishedBlogEntries()
*
* Preconditions:
* this.blogEntryIndex != null
* this.blogEntryIndex.publishedIndexEntries != null
*
* Postconditions:
* init'ed(return_value)
*/
972 public int getNumberOfPublishedBlogEntries() {
973 return blogEntryIndex.getNumberOfPublishedBlogEntries();
974 }
975
976 /**
977 * Gets the number of unpublished blog entries for this blog.
978 *
979 * @return an int
980 */
/*
P/P * Method: int getNumberOfUnpublishedBlogEntries()
*
* Preconditions:
* this.blogEntryIndex != null
* this.blogEntryIndex.unpublishedIndexEntries != null
*
* Postconditions:
* init'ed(return_value)
*/
981 public int getNumberOfUnpublishedBlogEntries() {
982 return blogEntryIndex.getNumberOfUnpublishedBlogEntries();
983 }
984
985 /**
986 * Gets the number of static pages for this blog.
987 *
988 * @return an int
989 */
/*
P/P * Method: int getNumberOfStaticPages()
*
* Preconditions:
* this.staticPageIndex != null
* this.staticPageIndex.index != null
*
* Postconditions:
* init'ed(return_value)
*/
990 public int getNumberOfStaticPages() {
991 return staticPageIndex.getNumberOfStaticPages();
992 }
993
994 /**
995 * Gets the most recent blog entries, the number
996 * of which is specified.
997 *
998 * @param numberOfEntries the number of entries to get
999 * @return a List containing the most recent blog entries
1000 */
/*
P/P * Method: List getRecentBlogEntries(int)
*
* Preconditions:
* this.blogEntryIndex != null
* init'ed(this.blogEntryIndex.indexEntries)
*
* Presumptions:
* org.apache.commons.logging.LogFactory:getLog(...)@105 != null
*
* Postconditions:
* return_value == &new ArrayList(getRecentBlogEntries#2)
* new ArrayList(getRecentBlogEntries#2) num objects == 1
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@1005: {1}, {0}
*/
1001 public List getRecentBlogEntries(int numberOfEntries) {
1002 BlogService service = new BlogService();
1003 List<String> blogEntryIds = blogEntryIndex.getBlogEntries();
1004 List blogEntries = new ArrayList();
1005 for (String blogEntryId : blogEntryIds) {
1006 try {
1007 BlogEntry blogEntry = service.getBlogEntry(this, blogEntryId);
1008 blogEntries.add(blogEntry);
1009 } catch (BlogServiceException e) {
1010 log.error("Exception encountered", e);
1011 }
1012
1013 if (blogEntries.size() == numberOfEntries) {
1014 break;
1015 }
1016 }
1017
1018 return blogEntries;
1019 }
1020
1021 /**
1022 * Gets the most recent published blog entries, the number of which
1023 * is taken from the recentBlogEntriesOnHomePage property.
1024 *
1025 * @return a List containing the most recent blog entries
1026 */
/*
P/P * Method: List getRecentPublishedBlogEntries()
*
* Preconditions:
* this.blogEntryIndex != null
* init'ed(this.blogEntryIndex.publishedIndexEntries)
* this.properties != null
*
* Postconditions:
* return_value == &new ArrayList(getRecentPublishedBlogEntries#2*)
* new ArrayList(getRecentPublishedBlogEntries#2*) num objects == 1
*/
1027 public List getRecentPublishedBlogEntries() {
1028 return getRecentPublishedBlogEntries(getRecentBlogEntriesOnHomePage());
1029 }
1030
1031 /**
1032 * Gets the most recent published blog entries, the number of which
1033 * is specified
1034 *
1035 * @param number the number of blog entries to get
1036 * @return a List containing the most recent blog entries
1037 */
/*
P/P * Method: List getRecentPublishedBlogEntries(int)
*
* Preconditions:
* this.blogEntryIndex != null
* init'ed(this.blogEntryIndex.publishedIndexEntries)
*
* Presumptions:
* org.apache.commons.logging.LogFactory:getLog(...)@105 != null
*
* Postconditions:
* return_value == &new ArrayList(getRecentPublishedBlogEntries#2)
* new ArrayList(getRecentPublishedBlogEntries#2) num objects == 1
*
* Test Vectors:
* getBlogEntry(...)@1048: Addr_Set{null}, Inverse{null}
* java.util.Iterator:hasNext(...)@1042: {1}, {0}
*/
1038 public List getRecentPublishedBlogEntries(int number) {
1039 BlogService service = new BlogService();
1040 List<String> blogEntryIds = blogEntryIndex.getPublishedBlogEntries();
1041 List blogEntries = new ArrayList();
1042 for (String blogEntryId : blogEntryIds) {
1043 if (blogEntries.size() == number) {
1044 break;
1045 }
1046
1047 try {
1048 BlogEntry blogEntry = service.getBlogEntry(this, blogEntryId);
1049 if (blogEntry != null) {
1050 blogEntries.add(blogEntry);
1051 }
1052 } catch (BlogServiceException e) {
1053 log.error("Exception encountered", e);
1054 }
1055 }
1056
1057 return blogEntries;
1058 }
1059
1060 /**
1061 * Gets blog entries for a given list of IDs.
1062 *
1063 * @param blogEntryIds the list of blog entry IDs
1064 * @return a List containing the blog entries
1065 */
/*
P/P * Method: List getBlogEntries(List)
*
* Preconditions:
* blogEntryIds != null
*
* Presumptions:
* org.apache.commons.logging.LogFactory:getLog(...)@105 != null
*
* Postconditions:
* return_value == &new LinkedList(getBlogEntries#2)
* new LinkedList(getBlogEntries#2) num objects == 1
*
* Test Vectors:
* getBlogEntry(...)@1071: Addr_Set{null}, Inverse{null}
* java.util.Iterator:hasNext(...)@1069: {1}, {0}
*/
1066 public List<BlogEntry> getBlogEntries(List<String> blogEntryIds) {
1067 BlogService service = new BlogService();
1068 List<BlogEntry> blogEntries = new LinkedList<BlogEntry>();
1069 for (String blogEntryId : blogEntryIds) {
1070 try {
1071 BlogEntry blogEntry = service.getBlogEntry(this, blogEntryId);
1072 if (blogEntry != null) {
1073 blogEntries.add(blogEntry);
1074 }
1075 } catch (BlogServiceException e) {
1076 log.error("Exception encountered", e);
1077 }
1078 }
1079
1080 return blogEntries;
1081 }
1082
1083 /**
1084 * Gets the most recent published blog entries for a given category, the
1085 * number of which is taken from the recentBlogEntriesOnHomePage property.
1086 *
1087 * @param category a category
1088 * @return a List containing the most recent blog entries
1089 */
/*
P/P * Method: List getRecentPublishedBlogEntries(Category)
*
* Preconditions:
* category != null
* init'ed(category.blogEntries)
* this.categoryIndex != null
* (soft) this.properties != null
*
* Presumptions:
* blogEntry.state@1096 != null
* net.sourceforge.pebble.domain.State__static_init.new State(State__static_init#5).name@1096 != null
* org.apache.commons.logging.LogFactory:getLog(...)@105 != null
* this.properties@1096 != null
*
* Postconditions:
* return_value == &new ArrayList(getRecentPublishedBlogEntries#2)
* new ArrayList(getRecentPublishedBlogEntries#2) num objects == 1
*
* Test Vectors:
* getBlogEntry(...)@1096: Addr_Set{null}, Inverse{null}
* java.util.Iterator:hasNext(...)@1094: {1}, {0}
*/
1090 public List getRecentPublishedBlogEntries(Category category) {
1091 BlogService service = new BlogService();
1092 List<String> blogEntryIds = categoryIndex.getRecentBlogEntries(category);
1093 List blogEntries = new ArrayList();
1094 for (String blogEntryId : blogEntryIds) {
1095 try {
1096 BlogEntry blogEntry = service.getBlogEntry(this, blogEntryId);
1097 if (blogEntry != null && blogEntry.isPublished()) {
1098 blogEntries.add(blogEntry);
1099 }
1100 } catch (BlogServiceException e) {
1101 log.error("Exception encountered", e);
1102 }
1103
1104 if (blogEntries.size() == getRecentBlogEntriesOnHomePage()) {
1105 break;
1106 }
1107 }
1108
1109 return blogEntries;
1110 }
1111
1112 /**
1113 * Gets the most recent published blog entries for a given category, the
1114 * number of which is taken from the recentBlogEntriesOnHomePage property.
1115 *
1116 * @param author the author's username
1117 * @return a List containing the most recent blog entries
1118 */
/*
P/P * Method: List getRecentPublishedBlogEntries(String)
*
* Preconditions:
* this.authorIndex != null
* this.authorIndex.authors != null
* (soft) this.properties != null
*
* Presumptions:
* blogEntry.state@1125 != null
* net.sourceforge.pebble.domain.State__static_init.new State(State__static_init#5).name@1125 != null
* org.apache.commons.logging.LogFactory:getLog(...)@105 != null
* this.properties@1125 != null
*
* Postconditions:
* return_value == &new ArrayList(getRecentPublishedBlogEntries#2)
* new ArrayList(getRecentPublishedBlogEntries#2) num objects == 1
*
* Test Vectors:
* getBlogEntry(...)@1125: Addr_Set{null}, Inverse{null}
* java.util.Iterator:hasNext(...)@1123: {1}, {0}
*/
1119 public List getRecentPublishedBlogEntries(String author) {
1120 BlogService service = new BlogService();
1121 List<String> blogEntryIds = authorIndex.getRecentBlogEntries(author);
1122 List blogEntries = new ArrayList();
1123 for (String blogEntryId : blogEntryIds) {
1124 try {
1125 BlogEntry blogEntry = service.getBlogEntry(this, blogEntryId);
1126 if (blogEntry != null && blogEntry.isPublished()) {
1127 blogEntries.add(blogEntry);
1128 }
1129 } catch (BlogServiceException e) {
1130 log.error("Exception encountered", e);
1131 }
1132
1133 if (blogEntries.size() == getRecentBlogEntriesOnHomePage()) {
1134 break;
1135 }
1136 }
1137
1138 return blogEntries;
1139 }
1140
1141 /**
1142 * Gets the most recent published blog entries for a given tag, the
1143 * number of which is taken from the recentBlogEntriesOnHomePage property.
1144 *
1145 * @param tag a tag
1146 * @return a List containing the most recent blog entries
1147 */
/*
P/P * Method: List getRecentPublishedBlogEntries(Tag)
*
* Preconditions:
* tag != null
* init'ed(tag.name)
* this.tagIndex != null
* this.tagIndex.tags != null
* (soft) this.properties != null
* (soft) init'ed(this.tagIndex.blog)
*
* Presumptions:
* blogEntry.state@1154 != null
* net.sourceforge.pebble.domain.State__static_init.new State(State__static_init#5).name@1154 != null
* org.apache.commons.logging.LogFactory:getLog(...)@105 != null
* this.properties@1154 != null
*
* Postconditions:
* return_value == &new ArrayList(getRecentPublishedBlogEntries#2)
* new ArrayList(getRecentPublishedBlogEntries#2) num objects == 1
*
* Test Vectors:
* getBlogEntry(...)@1154: Addr_Set{null}, Inverse{null}
* java.util.Iterator:hasNext(...)@1152: {1}, {0}
*/
1148 public List getRecentPublishedBlogEntries(Tag tag) {
1149 BlogService service = new BlogService();
1150 List<String> blogEntryIds = tagIndex.getRecentBlogEntries(tag);
1151 List blogEntries = new ArrayList();
1152 for (String blogEntryId : blogEntryIds) {
1153 try {
1154 BlogEntry blogEntry = service.getBlogEntry(this, blogEntryId);
1155 if (blogEntry != null && blogEntry.isPublished()) {
1156 blogEntries.add(blogEntry);
1157 }
1158 } catch (BlogServiceException e) {
1159 log.error("Exception encountered", e);
1160 }
1161
1162 if (blogEntries.size() == getRecentBlogEntriesOnHomePage()) {
1163 break;
1164 }
1165 }
1166
1167 return blogEntries;
1168 }
1169
1170 /**
1171 * Gets the most recent responses.
1172 *
1173 * @return a List containing the most recent blog entries
1174 */
/*
P/P * Method: List getRecentApprovedResponses()
*
* Preconditions:
* this.responseIndex != null
* init'ed(this.responseIndex.approvedResponses)
* (soft) net.sourceforge.pebble.domain.State__static_init.new State(State__static_init#5).name != null
* (soft) this.properties != null
*
* Presumptions:
* getBlogEntry(...).state@1181 != null
* java.util.Iterator:next(...)@1179 != null
* org.apache.commons.logging.LogFactory:getLog(...)@105 != null
* response.blogEntry@1181 != null
*
* Postconditions:
* return_value == &new ArrayList(getRecentApprovedResponses#2)
* new ArrayList(getRecentApprovedResponses#2) num objects == 1
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@1179: {1}, {0}
*/
1175 public List<Response> getRecentApprovedResponses() {
1176 BlogService service = new BlogService();
1177 List<String> responseIds = responseIndex.getApprovedResponses();
1178 List<Response> responses = new ArrayList<Response>();
1179 for (String responseId : responseIds) {
1180 try {
1181 Response response = service.getResponse(this, responseId);
1182 if (response != null && response.getBlogEntry().isPublished()) {
1183 responses.add(response);
1184 }
1185 } catch (BlogServiceException e) {
1186 log.error("Exception encountered", e);
1187 }
1188
1189 if (responses.size() == getRecentResponsesOnHomePage()) {
1190 break;
1191 }
1192 }
1193
1194 return responses;
1195 }
1196
1197 /**
1198 * Gets the list of approved responses.
1199 *
1200 * @return a List of response IDs
1201 */
/*
P/P * Method: List getApprovedResponses()
*
* Preconditions:
* this.responseIndex != null
* init'ed(this.responseIndex.approvedResponses)
*
* Postconditions:
* return_value == &new ArrayList(getApprovedResponses#1*)
* new ArrayList(getApprovedResponses#1*) num objects == 1
*/
1202 public List<String> getApprovedResponses() {
1203 return responseIndex.getApprovedResponses();
1204 }
1205
1206 /**
1207 * Gets the list of pending responses.
1208 *
1209 * @return a List of response IDs
1210 */
/*
P/P * Method: List getPendingResponses()
*
* Preconditions:
* this.responseIndex != null
* init'ed(this.responseIndex.pendingResponses)
*
* Postconditions:
* return_value == &new ArrayList(getPendingResponses#1*)
* new ArrayList(getPendingResponses#1*) num objects == 1
*/
1211 public List<String> getPendingResponses() {
1212 return responseIndex.getPendingResponses();
1213 }
1214
1215 /**
1216 * Gets the list of rejected responses.
1217 *
1218 * @return a List of response IDs
1219 */
/*
P/P * Method: List getRejectedResponses()
*
* Preconditions:
* this.responseIndex != null
* init'ed(this.responseIndex.rejectedResponses)
*
* Postconditions:
* return_value == &new ArrayList(getRejectedResponses#1*)
* new ArrayList(getRejectedResponses#1*) num objects == 1
*/
1220 public List<String> getRejectedResponses() {
1221 return responseIndex.getRejectedResponses();
1222 }
1223
1224 /**
1225 * Gets the number of responses.
1226 *
1227 * @return the number of responses
1228 */
/*
P/P * Method: int getNumberOfResponses()
*
* Preconditions:
* this.responseIndex != null
* this.responseIndex.approvedResponses != null
* this.responseIndex.pendingResponses != null
* this.responseIndex.rejectedResponses != null
*
* Presumptions:
* java.util.List:size(...)@202 + java.util.List:size(...)@193 + java.util.List:size(...)@211 in -231..232-1
*
* Postconditions:
* init'ed(return_value)
*/
1229 public int getNumberOfResponses() {
1230 return responseIndex.getNumberOfResponses();
1231 }
1232
1233 /**
1234 * Gets the number of approved responses.
1235 *
1236 * @return the number of approved responses
1237 */
/*
P/P * Method: int getNumberOfApprovedResponses()
*
* Preconditions:
* this.responseIndex != null
* this.responseIndex.approvedResponses != null
*
* Postconditions:
* init'ed(return_value)
*/
1238 public int getNumberOfApprovedResponses() {
1239 return responseIndex.getNumberOfApprovedResponses();
1240 }
1241
1242 /**
1243 * Gets the number of pending responses.
1244 *
1245 * @return the number of pending responses
1246 */
/*
P/P * Method: int getNumberOfPendingResponses()
*
* Preconditions:
* this.responseIndex != null
* this.responseIndex.pendingResponses != null
*
* Postconditions:
* init'ed(return_value)
*/
1247 public int getNumberOfPendingResponses() {
1248 return responseIndex.getNumberOfPendingResponses();
1249 }
1250
1251 /**
1252 * Gets the number of rejected responses.
1253 *
1254 * @return the number of rejected responses
1255 */
/*
P/P * Method: int getNumberOfRejectedResponses()
*
* Preconditions:
* this.responseIndex != null
* this.responseIndex.rejectedResponses != null
*
* Postconditions:
* init'ed(return_value)
*/
1256 public int getNumberOfRejectedResponses() {
1257 return responseIndex.getNumberOfRejectedResponses();
1258 }
1259
1260 /**
1261 * Gets the date that this blog was last updated through the addition
1262 * of a blog entry.
1263 *
1264 * @return a Date instance representing the time of the most recent entry
1265 */
/*
P/P * Method: Date getLastModified()
*
* Preconditions:
* this.blogEntryIndex != null
* init'ed(this.blogEntryIndex.publishedIndexEntries)
*
* Presumptions:
* java.util.List:get(...)@1270 != null
*
* Postconditions:
* init'ed(return_value)
* new Date(getLastModified#1) num objects == 1
*
* Test Vectors:
* java.util.List:size(...)@1269: {-231..0, 2..232-1}, {1}
*/
1266 public Date getLastModified() {
1267 Date date = new Date(0);
1268 List blogEntries = getRecentPublishedBlogEntries(1);
1269 if (blogEntries.size() == 1) {
1270 date = ((BlogEntry)blogEntries.get(0)).getDate();
1271 }
1272
1273 return date;
1274 }
1275
1276 /**
1277 * Gets the date of the most recent response.
1278 *
1279 * @return a Date instance representing the time of the most recent entry
1280 */
/*
P/P * Method: Date getDateOfLastResponse()
*
* Preconditions:
* this.responseIndex != null
* init'ed(this.responseIndex.approvedResponses)
* (soft) net.sourceforge.pebble.domain.State__static_init.new State(State__static_init#5).name != null
* (soft) this.properties != null
*
* Presumptions:
* java.util.List:get(...)@1284 != null
*
* Postconditions:
* init'ed(return_value)
* new Date(getDateOfLastResponse#1) num objects <= 1
*
* Test Vectors:
* java.util.List:size(...)@1283: {-231..0}, {1..232-1}
*/
1281 public Date getDateOfLastResponse() {
1282 List<Response> responses = this.getRecentApprovedResponses();
+ 1283 if (responses != null && responses.size() > 0) {
1284 return responses.get(0).getDate();
1285 } else {
1286 return new Date(0);
1287 }
1288 }
1289
/*
P/P * Method: BlogEntry getPreviousBlogEntry(BlogEntry)
*
* Preconditions:
* blogEntry != null
* init'ed(blogEntry.date)
* init'ed(blogEntry.id)
* init'ed(this.blogEntryIndex)
* (soft) init'ed(this.blogEntryIndex.indexEntries)
* (soft) this.properties != null
* (soft) this.years != null
*
* Presumptions:
* day.day <= day.month.dailyBlogs.length@1294 + 1
* day.month.dailyBlogs.length@1294 >= 1
* day.month.dailyBlogs@1294 != null
* day.month.month@1294 <= 13
* day.month.month@1294 <= day.month.year.months.length@1294 + 1
* ...
*
* Postconditions:
* init'ed(return_value)
*/
1290 public BlogEntry getPreviousBlogEntry(BlogEntry blogEntry) {
+ 1291 Day firstDay = getBlogForFirstMonth().getBlogForFirstDay();
1292 Day day = getBlogForDay(blogEntry.getDate());
1293
+ 1294 String blogEntryId = day.getPreviousBlogEntry(blogEntry.getId());
1295 while (day != firstDay && blogEntryId == null) {
1296 day = day.getPreviousDay();
+ 1297 blogEntryId = day.getLastBlogEntry();
1298 }
1299
1300 if (blogEntryId != null) {
1301 BlogService service = new BlogService();
1302 try {
1303 BlogEntry previousBlogEntry = service.getBlogEntry(this, blogEntryId);
1304 return previousBlogEntry;
1305 } catch (BlogServiceException e) {
1306 // do nothing
1307 }
1308 }
1309
1310 return null;
1311 }
1312
/*
P/P * Method: BlogEntry getNextBlogEntry(BlogEntry)
*
* Preconditions:
* blogEntry != null
* init'ed(blogEntry.date)
* init'ed(blogEntry.id)
* this.properties != null
* this.years != null
*
* Presumptions:
* day.day < day.month.dailyBlogs.length@1317
* day.day - day.month.lastDayInMonth@1317 in -232+1..6_442_450_943
* day.month.dailyBlogs.length@1317 >= 1
* day.month.dailyBlogs@1317 != null
* day.month.month@1317 >= 0
* ...
*
* Postconditions:
* init'ed(return_value)
*/
1313 public BlogEntry getNextBlogEntry(BlogEntry blogEntry) {
1314 Day lastDay = getBlogForToday();
1315 Day day = getBlogForDay(blogEntry.getDate());
1316
+ 1317 String blogEntryId = day.getNextBlogEntry(blogEntry.getId());
1318 while (day != lastDay && blogEntryId == null) {
1319 day = day.getNextDay();
+ 1320 blogEntryId = day.getFirstBlogEntry();
1321 }
1322
1323 if (blogEntryId != null) {
1324 BlogService service = new BlogService();
1325 try {
1326 BlogEntry nextBlogEntry = service.getBlogEntry(this, blogEntryId);
1327 return nextBlogEntry;
1328 } catch (BlogServiceException e) {
1329 // do nothing
1330 }
1331 }
1332
1333 return null;
1334 }
1335
1336 /**
1337 * Gets the categories associated with this blog.
1338 *
1339 * @return a List of Category instances
1340 */
/*
P/P * Method: List getCategories()
*
* Preconditions:
* init'ed(this.rootCategory)
*
* Postconditions:
* return_value == &new ArrayList(getCategories#1*)
* init'ed(new ArrayList(Category#1) num objects)
* init'ed(new ArrayList(Category#2) num objects)
* init'ed(new ArrayList(Category#3) num objects)
* new ArrayList(getCategories#1*) num objects == 1
* init'ed(new Category(getCategory#2) num objects)
* possibly_updated(new Category(getCategory#2).blog)
* init'ed(new Category(getCategory#2).blogEntries)
* possibly_updated(new Category(getCategory#2).id)
* init'ed(new Category(getCategory#2).name)
* ...
*/
1341 public List<Category> getCategories() {
1342 CategoryBuilder builder = new CategoryBuilder(this, rootCategory);
1343 return builder.getCategories();
1344 }
1345
1346 /**
1347 * Gets a specific category.
1348 *
1349 * @return a Category instance
1350 */
/*
P/P * Method: Category getCategory(String)
*
* Preconditions:
* init'ed(this.rootCategory)
*
* Postconditions:
* init'ed(return_value)
* init'ed(new ArrayList(Category#1) num objects)
* init'ed(new ArrayList(Category#2) num objects)
* init'ed(new ArrayList(Category#3) num objects)
* init'ed(new Category(getCategory#2*) num objects)
* possibly_updated(new Category(getCategory#2*).blog)
* init'ed(new Category(getCategory#2*).blogEntries)
* possibly_updated(new Category(getCategory#2*).id)
* init'ed(new Category(getCategory#2*).name)
* possibly_updated(new Category(getCategory#2*).parent)
* ...
*/
1351 public Category getCategory(String id) {
1352 CategoryBuilder builder = new CategoryBuilder(this, rootCategory);
1353 return builder.getCategory(id);
1354 }
1355
1356 /**
1357 * Gets the root category for this blog.
1358 *
1359 * @return a Category instance
1360 */
/*
P/P * Method: Category getRootCategory()
*
* Preconditions:
* init'ed(this.rootCategory)
*
* Postconditions:
* return_value == this.rootCategory
* init'ed(return_value)
*/
1361 public Category getRootCategory() {
1362 return this.rootCategory;
1363 }
1364
1365 /**
1366 * Sets the root category for this blog.
1367 *
1368 * @param category a Category instance
1369 */
/*
P/P * Method: void setRootCategory(Category)
*
* Postconditions:
* this.rootCategory == category
* init'ed(this.rootCategory)
*/
1370 public void setRootCategory(Category category) {
1371 this.rootCategory = category;
1372 }
1373
1374 /**
1375 * Adds a category.
1376 *
1377 * @param category the Category to be added
1378 */
/*
P/P * Method: void addCategory(Category)
*
* Preconditions:
* category != null
* init'ed(this.rootCategory)
* (soft) category.id != null
*
* Postconditions:
* possibly_updated(category.blog)
* possibly_updated(category.parent)
* init'ed(new ArrayList(Category#1) num objects)
* init'ed(new ArrayList(Category#2) num objects)
* init'ed(new ArrayList(Category#3) num objects)
* init'ed(new Category(getCategory#2*) num objects)
* possibly_updated(new Category(getCategory#2*).blog)
* init'ed(new Category(getCategory#2*).blogEntries)
* possibly_updated(new Category(getCategory#2*).id)
* init'ed(new Category(getCategory#2*).name)
* ...
*/
1379 public synchronized void addCategory(Category category) {
1380 if (getCategory(category.getId()) == null) {
1381 CategoryBuilder builder = new CategoryBuilder(this, rootCategory);
+ 1382 builder.addCategory(category);
1383 }
1384 }
1385
1386 /**
1387 * Removes a category.
1388 *
1389 * @param category the Category to be removed
1390 */
/*
P/P * Method: void removeCategory(Category)
*
* Preconditions:
* category != null
* (soft) category.id != null
* (soft) init'ed(this.rootCategory)
*
* Postconditions:
* possibly_updated(category.parent)
* init'ed(new ArrayList(Category#1) num objects)
* init'ed(new ArrayList(Category#2) num objects)
* init'ed(new ArrayList(Category#3) num objects)
* init'ed(new Category(getCategory#2) num objects)
* possibly_updated(new Category(getCategory#2).blog)
* init'ed(new Category(getCategory#2).blogEntries)
* possibly_updated(new Category(getCategory#2).id)
* init'ed(new Category(getCategory#2).name)
* possibly_updated(new Category(getCategory#2).parent)
* ...
*/
1391 public synchronized void removeCategory(Category category) {
1392 if (getCategory(category.getId()) != null) {
1393 CategoryBuilder builder = new CategoryBuilder(this, rootCategory);
+ 1394 builder.removeCategory(category);
1395 }
1396 }
1397
1398 /**
1399 * Gets the list of tags associated with this blog.
1400 */
/*
P/P * Method: List getTags()
*
* Preconditions:
* this.tagIndex != null
* init'ed(this.tagIndex.orderedTags)
*
* Postconditions:
* return_value == &new ArrayList(getTags#1*)
* new ArrayList(getTags#1*) num objects == 1
*/
1401 public List<Tag> getTags() {
1402 return tagIndex.getTags();
1403 }
1404
1405 /**
1406 * Gets the tag with the specified name.
1407 *
1408 * @param name the name as a String
1409 * @return a Tag instance
1410 */
/*
P/P * Method: Tag getTag(String)
*
* Postconditions:
* return_value == &new Tag(getTag#1)
* new Tag(getTag#1) num objects == 1
* return_value.blog == this
* return_value.blog != null
* return_value.name != null
*/
1411 public Tag getTag(String name) {
1412 return new Tag(name, this);
1413 }
1414
1415 /**
1416 * Gets the object managing referer filters.
1417 *
1418 * @return a RefererFilterManager instance
1419 */
/*
P/P * Method: RefererFilterManager getRefererFilterManager()
*
* Preconditions:
* init'ed(this.refererFilterManager)
*
* Postconditions:
* return_value == this.refererFilterManager
* init'ed(return_value)
*/
1420 public RefererFilterManager getRefererFilterManager() {
1421 return this.refererFilterManager;
1422 }
1423
1424 /**
1425 * Gets the search index.
1426 *
1427 * @return a BlogEntryIndex instance
1428 */
/*
P/P * Method: SearchIndex getSearchIndex()
*
* Preconditions:
* init'ed(this.searchIndex)
*
* Postconditions:
* return_value == this.searchIndex
* init'ed(return_value)
*/
1429 public SearchIndex getSearchIndex() {
1430 return this.searchIndex;
1431 }
1432
1433 /**
1434 * Gets the blog entry index.
1435 *
1436 * @return a BlogEntryIndex instance
1437 */
/*
P/P * Method: BlogEntryIndex getBlogEntryIndex()
*
* Preconditions:
* init'ed(this.blogEntryIndex)
*
* Postconditions:
* return_value == this.blogEntryIndex
* init'ed(return_value)
*/
1438 public BlogEntryIndex getBlogEntryIndex() {
1439 return this.blogEntryIndex;
1440 }
1441
1442 /**
1443 * Gets the response index.
1444 *
1445 * @return a ResponseIndex instance
1446 */
/*
P/P * Method: ResponseIndex getResponseIndex()
*
* Preconditions:
* init'ed(this.responseIndex)
*
* Postconditions:
* return_value == this.responseIndex
* init'ed(return_value)
*/
1447 public ResponseIndex getResponseIndex() {
1448 return this.responseIndex;
1449 }
1450
1451 /**
1452 * Gets the tag index.
1453 *
1454 * @return a TagIndex instance
1455 */
/*
P/P * Method: TagIndex getTagIndex()
*
* Preconditions:
* init'ed(this.tagIndex)
*
* Postconditions:
* return_value == this.tagIndex
* init'ed(return_value)
*/
1456 public TagIndex getTagIndex() {
1457 return this.tagIndex;
1458 }
1459
1460 /**
1461 * Gets the category index.
1462 *
1463 * @return a CategoryIndex instance
1464 */
/*
P/P * Method: CategoryIndex getCategoryIndex()
*
* Preconditions:
* init'ed(this.categoryIndex)
*
* Postconditions:
* return_value == this.categoryIndex
* init'ed(return_value)
*/
1465 public CategoryIndex getCategoryIndex() {
1466 return this.categoryIndex;
1467 }
1468
1469 /**
1470 * Gets the author index.
1471 *
1472 * @return a AuthorIndex instance
1473 */
/*
P/P * Method: AuthorIndex getAuthorIndex()
*
* Preconditions:
* init'ed(this.authorIndex)
*
* Postconditions:
* return_value == this.authorIndex
* init'ed(return_value)
*/
1474 public AuthorIndex getAuthorIndex() {
1475 return this.authorIndex;
1476 }
1477
1478 /**
1479 * Gets the story index.
1480 *
1481 * @return a StaticPageIndex instance
1482 */
/*
P/P * Method: StaticPageIndex getStaticPageIndex()
*
* Preconditions:
* init'ed(this.staticPageIndex)
*
* Postconditions:
* return_value == this.staticPageIndex
* init'ed(return_value)
*/
1483 public StaticPageIndex getStaticPageIndex() {
1484 return this.staticPageIndex;
1485 }
1486
1487 /**
1488 * Logs this request for blog.
1489 *
1490 * @param request the HttpServletRequest instance for this request
1491 */
1492 public synchronized void log(HttpServletRequest request, int status) {
/*
P/P * Method: void log(HttpServletRequest, int)
*
* Preconditions:
* request != null
* (soft) this.logger != null
*
* Presumptions:
* javax.servlet.http.HttpServletRequest:getAttribute(...)@1493 != null
*
* Test Vectors:
* java.lang.String:matches(...)@1494: {1}, {0}
*/
1493 String externalUri = (String)request.getAttribute(Constants.EXTERNAL_URI);
1494 if (externalUri.matches("/images/.+")) {
1495 // do nothing, we don't want to log the following types of requests
1496 // - a blog's images
1497 } else {
1498 // log the request
1499 logger.log(request, status);
1500 }
1501 }
1502
1503 /**
1504 * Gets an object representing the editable theme.
1505 *
1506 * @return an EditableTheme instance
1507 */
/*
P/P * Method: Theme getEditableTheme()
*
* Preconditions:
* init'ed(this.editableTheme)
*
* Postconditions:
* return_value == this.editableTheme
* init'ed(return_value)
*/
1508 public Theme getEditableTheme() {
1509 return editableTheme;
1510 }
1511
1512 /**
1513 * Sets an object representing the editable theme.
1514 *
1515 * @param editableTheme an EditableTheme instance
1516 */
/*
P/P * Method: void setEditableTheme(Theme)
*
* Postconditions:
* this.editableTheme == editableTheme
* init'ed(this.editableTheme)
*/
1517 public void setEditableTheme(Theme editableTheme) {
1518 this.editableTheme = editableTheme;
1519 }
1520
1521 /**
1522 * Gets the location where the blog files are stored.
1523 *
1524 * @return an absolute, local path on the filing system
1525 */
/*
P/P * Method: String getFilesDirectory()
*
* Preconditions:
* init'ed(this.root)
*
* Presumptions:
* init'ed(java.io.File.separator)
*
* Postconditions:
* return_value != null
*/
1526 public String getFilesDirectory() {
1527 return getRoot() + File.separator + "files";
1528 }
1529
1530 /**
1531 * Gets the location where the blog theme is stored.
1532 *
1533 * @return an absolute, local path on the filing system
1534 */
/*
P/P * Method: String getThemeDirectory()
*
* Preconditions:
* init'ed(this.root)
*
* Presumptions:
* init'ed(java.io.File.separator)
*
* Postconditions:
* return_value != null
*/
1535 public String getThemeDirectory() {
1536 return getRoot() + File.separator + "theme";
1537 }
1538
1539 /**
1540 * Gets the location where the plugin properties file is stored.
1541 *
1542 * @return an absolute, local path on the filing system
1543 */
/*
P/P * Method: String getPluginPropertiesFile()
*
* Preconditions:
* init'ed(this.root)
*
* Presumptions:
* init'ed(java.io.File.separator)
*
* Postconditions:
* return_value != null
*/
1544 public String getPluginPropertiesFile() {
1545 return getRoot() + File.separator + "plugin.properties";
1546 }
1547
1548 /**
1549 * Determines whether this blog is public.
1550 *
1551 * @return true if public, false otherwise
1552 */
/*
P/P * Method: bool isPublic()
*
* Preconditions:
* this.properties != null
*
* Presumptions:
* java.util.Properties:getProperty(...)@1554 != null
*
* Postconditions:
* init'ed(return_value)
*/
1553 public boolean isPublic() {
1554 return properties.getProperty(PRIVATE_KEY).equalsIgnoreCase(FALSE);
1555 }
1556
1557 /**
1558 * Determines whether this blog is private.
1559 *
1560 * @return true if public, false otherwise
1561 */
/*
P/P * Method: bool isPrivate()
*
* Preconditions:
* this.properties != null
*
* Presumptions:
* java.util.Properties:getProperty(...)@1563 != null
*
* Postconditions:
* init'ed(return_value)
*/
1562 public boolean isPrivate() {
1563 return properties.getProperty(PRIVATE_KEY).equalsIgnoreCase(TRUE);
1564 }
1565
1566 /**
1567 * Called to start (i.e. activate/initialise, restore the theme, etc) this
1568 * blog.
1569 */
/*
P/P * Method: void start()
*
* Preconditions:
* net/sourceforge/pebble/domain/Theme.log != null
* this.editableTheme != null
* this.editableTheme.blog != null
* init'ed(this.editableTheme.name)
* init'ed(this.editableTheme.pathToLiveThemes)
* this.eventDispatcher != null
* this.eventDispatcher.eventListenerList != null
* this.eventDispatcher.eventListenerList.blogListeners != null
* init'ed(this.id)
* this.logger != null
* ...
*
* Presumptions:
* org.apache.commons.logging.LogFactory:getLog(...)@105 != null
*
* Postconditions:
* possibly_updated(this.messages)
* possibly_updated(this.staticPageIndex.index)
* possibly_updated(this.staticPageIndex.lockAttempts)
* new HashMap(reindex#1) num objects <= 1
*
* Test Vectors:
* java.io.File:exists(...)@1575: {1}, {0}
* java.io.File:exists(...)@1581: {1}, {0}
* java.io.File:exists(...)@1586: {1}, {0}
* java.io.File:exists(...)@1591: {1}, {0}
*/
1570 void start() {
1571 log.debug("Starting blog with ID " + getId());
1572
1573 // reindex the blog if the indexes don't exist
1574 File indexes = new File(getIndexesDirectory());
1575 if (!indexes.exists()) {
1576 indexes.mkdir();
1577 reindex();
1578 }
1579
1580 File imagesDirectory = new File(getImagesDirectory());
1581 if (!imagesDirectory.exists()) {
1582 imagesDirectory.mkdir();
1583 }
1584
1585 File filesDirectory = new File(getFilesDirectory());
1586 if (!filesDirectory.exists()) {
1587 filesDirectory.mkdir();
1588 }
1589
1590 File logDirectory = new File(getLogsDirectory());
1591 if (!logDirectory.exists()) {
1592 logDirectory.mkdir();
1593 }
1594
1595 logger.start();
1596 editableTheme.restore();
1597
1598 // call blog listeners
1599 eventDispatcher.fireBlogEvent(new BlogEvent(this, BlogEvent.BLOG_STARTED));
1600 log.info("Started blog with ID " + getId());
1601 }
1602
1603 /**
1604 * Called to shutdown this blog.
1605 */
/*
P/P * Method: void stop()
*
* Preconditions:
* net/sourceforge/pebble/domain/Theme.log != null
* this.editableTheme != null
* this.editableTheme.blog != null
* init'ed(this.editableTheme.name)
* init'ed(this.editableTheme.pathToLiveThemes)
* this.eventDispatcher != null
* this.eventDispatcher.eventListenerList != null
* this.eventDispatcher.eventListenerList.blogListeners != null
* init'ed(this.id)
* this.logger != null
*
* Presumptions:
* org.apache.commons.logging.LogFactory:getLog(...)@105 != null
*/
1606 void stop() {
1607 log.debug("Stopping blog with ID " + getId());
1608
1609 logger.stop();
1610 editableTheme.backup();
1611
1612 // call blog listeners
1613 eventDispatcher.fireBlogEvent(new BlogEvent(this, BlogEvent.BLOG_STOPPED));
1614 log.info("Stopped blog with ID " + getId());
1615 }
1616
1617 /**
1618 * Gets the logger associated with this blog.
1619 *
1620 * @return an AbstractLogger implementation
1621 */
/*
P/P * Method: AbstractLogger getLogger()
*
* Preconditions:
* init'ed(this.logger)
*
* Postconditions:
* return_value == this.logger
* init'ed(return_value)
*/
1622 public AbstractLogger getLogger() {
1623 return this.logger;
1624 }
1625
1626 /**
1627 * Gets the list of plugins.
1628 *
1629 * @return a comma separated list of class names
1630 */
/*
P/P * Method: List getContentDecorators()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* return_value == &new ArrayList(getStringsFromProperty#1)
* new ArrayList(getStringsFromProperty#1) num objects == 1
*/
1631 public List<String> getContentDecorators() {
1632 return getStringsFromProperty(CONTENT_DECORATORS_KEY);
1633 }
1634
1635 /**
1636 * Gets the decorator manager associated with this blog.
1637 *
1638 * @return a BlogEntryDecoratorManager instance
1639 */
/*
P/P * Method: ContentDecoratorChain getContentDecoratorChain()
*
* Preconditions:
* init'ed(this.decoratorChain)
*
* Postconditions:
* return_value == this.decoratorChain
* init'ed(return_value)
*/
1640 public ContentDecoratorChain getContentDecoratorChain() {
1641 return this.decoratorChain;
1642 }
1643
1644 /**
1645 * Gets the list of blog listeners as strings.
1646 *
1647 * @return The list of class names
1648 */
/*
P/P * Method: List getBlogListeners()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* return_value == &new ArrayList(getStringsFromProperty#1)
* new ArrayList(getStringsFromProperty#1) num objects == 1
*/
1649 public List<String> getBlogListeners() {
1650 return getStringsFromProperty(BLOG_LISTENERS_KEY);
1651 }
1652
1653 /**
1654 * Gets the list of blog entry listeners as strings.
1655 *
1656 * @return The list of class names
1657 */
/*
P/P * Method: List getBlogEntryListeners()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* return_value == &new ArrayList(getStringsFromProperty#1)
* new ArrayList(getStringsFromProperty#1) num objects == 1
*/
1658 public List<String> getBlogEntryListeners() {
1659 return getStringsFromProperty(BLOG_ENTRY_LISTENERS_KEY);
1660 }
1661
1662 /**
1663 * Gets the list of comment listeners as strings.
1664 *
1665 * @return The list of class names
1666 */
/*
P/P * Method: List getCommentListeners()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* return_value == &new ArrayList(getStringsFromProperty#1)
* new ArrayList(getStringsFromProperty#1) num objects == 1
*/
1667 public List<String> getCommentListeners() {
1668 return getStringsFromProperty(COMMENT_LISTENERS_KEY);
1669 }
1670
1671 /**
1672 * Gets the list of TrackBack listeners as strings.
1673 *
1674 * @return The list of class names
1675 */
/*
P/P * Method: List getTrackBackListeners()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* return_value == &new ArrayList(getStringsFromProperty#1)
* new ArrayList(getStringsFromProperty#1) num objects == 1
*/
1676 public List<String> getTrackBackListeners() {
1677 return getStringsFromProperty(TRACKBACK_LISTENERS_KEY);
1678 }
1679
1680 /**
1681 * Gets the name the event dispatcher.
1682 *
1683 * @return a String
1684 */
/*
P/P * Method: String getEventDispatcherName()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
1685 public String getEventDispatcherName() {
1686 return getProperty(EVENT_DISPATCHER_KEY);
1687 }
1688
1689 /**
1690 * Gets the event dispatcher in use.
1691 *
1692 * @return an EventDispatcher implementation
1693 */
/*
P/P * Method: EventDispatcher getEventDispatcher()
*
* Preconditions:
* init'ed(this.eventDispatcher)
*
* Postconditions:
* return_value == this.eventDispatcher
* init'ed(return_value)
*/
1694 public EventDispatcher getEventDispatcher() {
1695 return this.eventDispatcher;
1696 }
1697
1698 /**
1699 * Gets the event listsner list.
1700 */
/*
P/P * Method: EventListenerList getEventListenerList()
*
* Preconditions:
* init'ed(this.eventListenerList)
*
* Postconditions:
* return_value == this.eventListenerList
* init'ed(return_value)
*/
1701 public EventListenerList getEventListenerList() {
1702 return this.eventListenerList;
1703 }
1704
/*
P/P * Method: PluginProperties getPluginProperties()
*
* Preconditions:
* init'ed(this.pluginProperties)
*
* Postconditions:
* return_value == this.pluginProperties
* init'ed(return_value)
*/
1705 public PluginProperties getPluginProperties() {
1706 return this.pluginProperties;
1707 }
1708
1709 /**
1710 * Gets the name of the permalink provider.
1711 *
1712 * @return the fully qualified class name of the permalink provider
1713 */
/*
P/P * Method: String getPermalinkProviderName()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
1714 public String getPermalinkProviderName() {
1715 return properties.getProperty(PERMALINK_PROVIDER_KEY);
1716 }
1717
1718 /**
1719 * Gets the permalink provider in use.
1720 *
1721 * @return a PermalinkProvider instance
1722 */
/*
P/P * Method: PermalinkProvider getPermalinkProvider()
*
* Preconditions:
* init'ed(this.permalinkProvider)
*
* Postconditions:
* return_value == this.permalinkProvider
* init'ed(return_value)
*/
1723 public PermalinkProvider getPermalinkProvider() {
1724 return this.permalinkProvider;
1725 }
1726
1727 /**
1728 * Sets the permalink provider in use.
1729 *
1730 * @param provider PermalinkProvider instance
1731 */
/*
P/P * Method: void setPermalinkProvider(PermalinkProvider)
*
* Preconditions:
* provider != null
*
* Postconditions:
* this.permalinkProvider == provider
* this.permalinkProvider != null
*/
1732 public void setPermalinkProvider(PermalinkProvider provider) {
1733 this.permalinkProvider = provider;
1734 this.permalinkProvider.setBlog(this);
1735 }
1736
/*
P/P * Method: void reindex()
*
* Preconditions:
* init'ed(this.id)
*
* Presumptions:
* net/sourceforge/pebble/dao/DAOFactory.configuredFactory.staticPageDAO@1740 != null
* net/sourceforge/pebble/dao/DAOFactory.configuredFactory@1740 != null
* net/sourceforge/pebble/domain/AbstractBlog.log@1740 != null
* net/sourceforge/pebble/domain/BlogManager.instance@1740 != null
* org.apache.commons.logging.LogFactory:getLog(...)@105 != null
* ...
*
* Postconditions:
* init'ed(this.messages)
* possibly_updated(this.staticPageIndex.index)
* possibly_updated(this.staticPageIndex.lockAttempts)
* new HashMap(reindex#1) num objects <= 1
*/
1737 public void reindex() {
1738 log.info("Reindexing blog with ID " + getId());
1739
1740 reindexBlogEntries();
1741 reindexStaticPages();
1742 }
1743
/*
P/P * Method: void reindexBlogEntries()
*
* Preconditions:
* net/sourceforge/pebble/domain/AbstractBlog.log != null
* this.messages != null
* this.authorIndex != null
* this.blogEntryIndex != null
* this.categoryIndex != null
* this.categoryIndex.blog != null
* this.responseIndex != null
* this.searchIndex != null
* this.searchIndex.blog != null
* this.tagIndex != null
* ...
*
* Presumptions:
* java.lang.Object:getClass(...)@1763 != null
* org.apache.commons.logging.LogFactory:getLog(...)@105 != null
*
* Postconditions:
* this.authorIndex.authors == &new HashMap(clear#1)
* this.blogEntryIndex.indexEntries == &new ArrayList(clear#1)
* this.blogEntryIndex.publishedIndexEntries == &new ArrayList(clear#2)
* this.blogEntryIndex.unpublishedIndexEntries == &new ArrayList(clear#3)
* init'ed(this.messages)
* this.responseIndex.approvedResponses == &new ArrayList(clear#1)
* this.responseIndex.pendingResponses == &new ArrayList(clear#2)
* this.responseIndex.rejectedResponses == &new ArrayList(clear#3)
* this.tagIndex.orderedTags == One-of{old this.tagIndex.orderedTags, &new ArrayList(recalculateTagRankings#2)}
* this.tagIndex.tags == &new HashMap(clear#1)
* ...
*/
1744 public void reindexBlogEntries() {
1745 blogEntryIndex.clear();
1746 responseIndex.clear();
1747 tagIndex.clear();
1748 categoryIndex.clear();
1749 authorIndex.clear();
1750 searchIndex.clear();
1751
1752 try {
1753 // to reindex all blog entries, we need to load them via the DAO
1754 Collection<BlogEntry> blogEntries = DAOFactory.getConfiguredFactory().getBlogEntryDAO().loadBlogEntries(this);
1755 blogEntryIndex.index(blogEntries);
1756 responseIndex.index(blogEntries);
1757 tagIndex.index(blogEntries);
1758 categoryIndex.index(blogEntries);
1759 authorIndex.index(blogEntries);
1760 searchIndex.indexBlogEntries(blogEntries);
1761 info("Blog entries reindexed.");
1762 } catch (Exception e) {
1763 error(e.getClass().getName() + " reindexing blog entries - " + StringUtils.transformHTML(e.getMessage()));
1764 log.error("Error reindexing blog entries", e);
1765 }
1766 }
1767
/*
P/P * Method: void reindexStaticPages()
*
* Preconditions:
* net/sourceforge/pebble/domain/AbstractBlog.log != null
* this.messages != null
* (soft) net/sourceforge/pebble/dao/DAOFactory.configuredFactory != null
* (soft) net/sourceforge/pebble/dao/DAOFactory.configuredFactory.staticPageDAO != null
* (soft) net/sourceforge/pebble/domain/BlogManager.instance != null
* (soft) init'ed(net/sourceforge/pebble/domain/BlogManager.instance.multiBlog)
* (soft) this.staticPageIndex.lockAttempts <= 232-2
* (soft) this...properties != null
* (soft) this.searchIndex != null
* (soft) this.searchIndex.blog != null
* ...
*
* Presumptions:
* java.lang.Object:getClass(...)@1776 != null
* org.apache.commons.logging.LogFactory:getLog(...)@105 != null
*
* Postconditions:
* init'ed(this.messages)
* this.staticPageIndex.index == One-of{old this.staticPageIndex.index, &new HashMap(reindex#1)}
* this.staticPageIndex.lockAttempts == One-of{old this.staticPageIndex.lockAttempts, old this.staticPageIndex.lockAttempts + 1, 0}
* init'ed(this.staticPageIndex.lockAttempts)
* new HashMap(reindex#1) num objects <= 1
*/
1768 public void reindexStaticPages() {
1769 try {
1770 // to reindex all static pages, we need to load them via the DAO
1771 Collection<StaticPage> staticPages = DAOFactory.getConfiguredFactory().getStaticPageDAO().loadStaticPages(this);
1772 staticPageIndex.reindex(staticPages);
1773 searchIndex.indexStaticPages(staticPages);
1774 info("Static pages reindexed.");
1775 } catch (Exception e) {
1776 error(e.getClass().getName() + " reindexing static pages - " + StringUtils.transformHTML(e.getMessage()));
1777 log.error("Error reindexing static pages", e);
1778 }
1779 }
1780
1781 /**
1782 * Indicates whether some other object is "equal to" this one.
1783 *
1784 * @param o the reference object with which to compare.
1785 * @return <code>true</code> if this object is the same as the obj
1786 * argument; <code>false</code> otherwise.
1787 * @see #hashCode()
1788 * @see java.util.Hashtable
1789 */
/*
P/P * Method: bool equals(Object)
*
* Preconditions:
* (soft) init'ed(o.id)
* (soft) this.id != null
*
* Postconditions:
* init'ed(return_value)
*
* Test Vectors:
* this == o: {0}, {1}
*/
1790 public boolean equals(Object o) {
1791 if (this == o) {
1792 return true;
1793 }
1794
1795 if (!(o instanceof Blog)) {
1796 return false;
1797 }
1798
1799 Blog blog = (Blog)o;
1800 return getId().equals(blog.getId());
1801 }
1802
1803
/*
P/P * Method: String getCommentConfirmationStrategyName()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
1804 public String getCommentConfirmationStrategyName() {
1805 return getProperty(COMMENT_CONFIRMATION_STRATEGY_KEY);
1806 }
1807
/*
P/P * Method: CommentConfirmationStrategy getCommentConfirmationStrategy()
*
* Preconditions:
* init'ed(this.commentConfirmationStrategy)
*
* Postconditions:
* return_value == this.commentConfirmationStrategy
* init'ed(return_value)
*/
1808 public CommentConfirmationStrategy getCommentConfirmationStrategy() {
1809 return commentConfirmationStrategy;
1810 }
1811
/*
P/P * Method: String getTrackBackConfirmationStrategyName()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
1812 public String getTrackBackConfirmationStrategyName() {
1813 return getProperty(TRACKBACK_CONFIRMATION_STRATEGY_KEY);
1814 }
1815
/*
P/P * Method: TrackBackConfirmationStrategy getTrackBackConfirmationStrategy()
*
* Preconditions:
* init'ed(this.trackBackConfirmationStrategy)
*
* Postconditions:
* return_value == this.trackBackConfirmationStrategy
* init'ed(return_value)
*/
1816 public TrackBackConfirmationStrategy getTrackBackConfirmationStrategy() {
1817 return trackBackConfirmationStrategy;
1818 }
1819
/*
P/P * Method: bool isRichTextEditorForCommentsEnabled()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*
* Test Vectors:
* java.lang.String:equalsIgnoreCase(...)@1822: {0}, {1}
* java.util.Properties:getProperty(...)@175: Addr_Set{null}, Inverse{null}
*/
1820 public boolean isRichTextEditorForCommentsEnabled() {
1821 String s = getProperty(RICH_TEXT_EDITOR_FOR_COMMENTS_ENABLED_KEY);
1822 return s != null && s.equalsIgnoreCase("true");
1823 }
1824
/*
P/P * Method: EmailSubscriptionList getEmailSubscriptionList()
*
* Preconditions:
* init'ed(this.emailSubscriptionList)
*
* Postconditions:
* return_value == this.emailSubscriptionList
* init'ed(return_value)
*/
1825 public EmailSubscriptionList getEmailSubscriptionList() {
1826 return emailSubscriptionList;
1827 }
1828
/*
P/P * Method: List getNewsFeedEntries()
*
* Preconditions:
* init'ed(this.id)
*
* Postconditions:
* return_value != null
* new LinkedList(getNewsFeedEntries#1*) num objects <= 1
*/
1829 public List<NewsFeedEntry> getNewsFeedEntries() {
1830 return NewsFeedCache.getInstance().getNewsFeedEntries(this);
1831 }
1832
/*
P/P * Method: List getRecentNewsFeedEntries()
*
* Preconditions:
* init'ed(this.id)
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
* new LinkedList(getNewsFeedEntries#1*) num objects <= 1
*/
1833 public List<NewsFeedEntry> getRecentNewsFeedEntries() {
1834 List<NewsFeedEntry> entries = getNewsFeedEntries();
1835 if (entries.size() > getRecentBlogEntriesOnHomePage()) {
1836 entries = entries.subList(0, getRecentBlogEntriesOnHomePage());
1837 }
1838 return entries;
1839 }
1840
/*
P/P * Method: List getStringsFromProperty(String)
*
* Preconditions:
* this.properties != null
*
* Presumptions:
* values.length@1845 <= 232-1
* values[i]@1845 != null
*
* Postconditions:
* return_value == &new ArrayList(getStringsFromProperty#1)
* new ArrayList(getStringsFromProperty#1) num objects == 1
*
* Test Vectors:
* java.lang.String:length(...)@1844: {0}, {1..232-1}
* java.lang.String:startsWith(...)@1847: {1}, {0}
* java.util.Properties:getProperty(...)@175: Addr_Set{null}, Inverse{null}
*/
1841 private List<String> getStringsFromProperty(String key) {
1842 List<String> strings = new ArrayList<String>();
1843 String value = getProperty(key);
1844 if (value != null && value.length() > 0) {
1845 String values[] = value.split("\\s+");
1846 for (int i = 0; i < values.length; i++) {
1847 if (!values[i].startsWith("#")) {
1848 strings.add(values[i].trim());
1849 }
1850 }
1851 }
1852 return strings;
1853 }
1854 }
SofCheck Inspector Build Version : 2.22510
| blog.java |
2010-Jun-25 19:40:32 |
| blog.class |
2010-Jul-19 20:23:40 |