File Source: abstractblog.java
/*
P/P * Method: net.sourceforge.pebble.domain.AbstractBlog__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 org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36
37 import java.io.File;
38 import java.io.FileInputStream;
39 import java.io.FileOutputStream;
40 import java.io.IOException;
41 import java.util.*;
42
43 import net.sourceforge.pebble.PebbleContext;
44
/*
P/P * Method: void net.sourceforge.pebble.domain.AbstractBlog(String)
*
* Postconditions:
* this.blog == null
* this.messages == &new LinkedList(AbstractBlog#1)
* this.root == root
* init'ed(this.root)
* new LinkedList(AbstractBlog#1) num objects == 1
*/
45 import javax.servlet.http.HttpServletRequest;
46
47 public abstract class AbstractBlog extends TimePeriod {
48
49 /** the name of the file containing blog properties */
50 public static final String BLOG_PROPERTIES_FILE = "blog.properties";
51
52 private static final int MAXIMUM_MESSAGES = 20;
53
54 /** the log used by this class */
55 private static Log log = LogFactory.getLog(AbstractBlog.class);
56
57 /** the filesystem root of this blog */
58 private String root;
59
60 protected static final String FALSE = "false";
61 protected static final String TRUE = "true";
62
63 public static final String NAME_KEY = "name";
64 public static final String AUTHOR_KEY = "author";
65 public static final String DESCRIPTION_KEY = "description";
66 public static final String IMAGE_KEY = "image";
67 public static final String TIMEZONE_KEY = "timeZone";
68 public static final String RECENT_BLOG_ENTRIES_ON_HOME_PAGE_KEY = "recentBlogEntriesOnHomePage";
69 public static final String RECENT_RESPONSES_ON_HOME_PAGE_KEY = "recentResponsesOnHomePage";
70 public static final String LANGUAGE_KEY = "language";
71 public static final String COUNTRY_KEY = "country";
72 public static final String CHARACTER_ENCODING_KEY = "characterEncoding";
73 public static final String THEME_KEY = "theme";
74
75 private List<Message> messages = new LinkedList<Message>();
76
77 /** the properties for this blog */
78 protected Properties properties;
79
80 /**
81 * Creates a new Blog instance, based at the specified location.
82 * Note: You must call init() before being able to use this object -
83 *
84 * @param root an absolute path pointing to the root directory of the blog
85 */
86 public AbstractBlog(String root) {
87 super(null);
88 this.root = root;
89 // see javadoc comment about why init cannot be called here.
90 // init();
91 }
92
93 /**
94 * Call this method to initialize this object before using it. As this method
95 * may call some abstract methods, it should be called either last from the
96 * topmost constructor or from the outside just after construction.
97 */
/*
P/P * Method: void init()
*
* Preconditions:
* init'ed(this.root)
* (soft) log != null
*
* Postconditions:
* this.properties == &new Properties(loadProperties#1)
* new Properties(loadProperties#1) num objects == 1
*/
98 protected void init() {
99 loadProperties();
100 }
101
102 /**
103 * Loads the properties for this blog, from the blog.properties file
104 * in the root directory.
105 */
/*
P/P * Method: void loadProperties()
*
* Preconditions:
* init'ed(this.root)
* (soft) log != null
*
* Postconditions:
* this.properties == One-of{&new Properties(loadProperties#1), old this.properties}
* new Properties(loadProperties#1) num objects <= 1
*
* Test Vectors:
* java.io.File:exists(...)@111: {1}, {0}
*/
106 protected void loadProperties() {
107 try {
108 this.properties = new Properties(getDefaultProperties());
109
110 File blogPropertiesFile = new File(getRoot(), BLOG_PROPERTIES_FILE);
111 if (!blogPropertiesFile.exists()) {
112 return;
113 }
114
115 FileInputStream fin = new FileInputStream(blogPropertiesFile);
116 properties.load(fin);
117 fin.close();
118 } catch (IOException ioe) {
119 log.error("A blog.properties file at " + getRoot() + " cannot be loaded", ioe);
120 }
121 }
122
/*
P/P * Method: bool isConfigured()
*
* Preconditions:
* init'ed(this.root)
*
* Postconditions:
* init'ed(return_value)
*/
123 public boolean isConfigured() {
124 File blogPropertiesFile = new File(getRoot(), BLOG_PROPERTIES_FILE);
125 return blogPropertiesFile.exists();
126 }
127
128 /**
129 * Gets the default properties for a blog.
130 *
131 * @return a Properties instance
132 */
133 protected abstract Properties getDefaultProperties();
134
135 /**
136 * Gets the ID of this blog.
137 *
138 * @return the ID as a String
139 */
140 public abstract String getId();
141
142 /**
143 * Gets the filesystem root for this blog.
144 *
145 * @return a String representing an absolute path
146 */
/*
P/P * Method: String getRoot()
*
* Preconditions:
* init'ed(this.root)
*
* Postconditions:
* return_value == this.root
* init'ed(return_value)
*/
147 public String getRoot() {
148 return root;
149 }
150
151 /**
152 * Sets the filesystem root for this blog.
153 *
154 * @param root a String representing the absolute path
155 */
/*
P/P * Method: void setRoot(String)
*
* Postconditions:
* this.root == root
* init'ed(this.root)
*/
156 protected void setRoot(String root) {
157 this.root = root;
158 }
159
160 /**
161 * Gets the properties associated with this blog.
162 *
163 * @return a java.util.Properties object
164 */
/*
P/P * Method: Properties getProperties()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* return_value != null
*/
165 public Properties getProperties() {
166 return (Properties)properties.clone();
167 }
168
169 /**
170 * Gets a named property for this blog.
171 *
172 * @param key the property name/key
173 */
/*
P/P * Method: String getProperty(String)
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
174 public String getProperty(String key) {
175 return properties.getProperty(key);
176 }
177
178 /**
179 * Sets a named property for this blog.
180 *
181 * @param key the property name/key
182 * @param value the property value
183 */
/*
P/P * Method: void setProperty(String, String)
*
* Preconditions:
* (soft) this.properties != null
*
* Test Vectors:
* key: Addr_Set{null}, Inverse{null}
* value: Addr_Set{null}, Inverse{null}
*/
184 public void setProperty(String key, String value) {
185 if (key != null) {
186 if (value != null) {
187 properties.setProperty(key, value);
188 } else {
189 removeProperty(key);
190 }
191 }
192 }
193
194 /**
195 * Removes a named property for this blog.
196 *
197 * @param key the property name/key
198 */
/*
P/P * Method: void removeProperty(String)
*
* Preconditions:
* this.properties != null
*/
199 public void removeProperty(String key) {
200 properties.remove(key);
201 }
202
203 /**
204 * Stores the properties associated with this blog.
205 *
206 * @throws BlogServiceException if the properties can't be stored
207 */
/*
P/P * Method: void storeProperties()
*
* Preconditions:
* (soft) log != null
* (soft) this.properties != null
* (soft) init'ed(this.root)
*/
208 public void storeProperties() throws BlogServiceException {
209 try {
210 FileOutputStream fout = new FileOutputStream(new File(getRoot(), BLOG_PROPERTIES_FILE));
211 properties.store(fout, "Properties for " + getName());
212 fout.flush();
213 fout.close();
214 } catch (IOException ioe) {
215 log.error(ioe);
216 }
217 }
218
219 /**
220 * Gets the name of this blog.
221 *
222 * @return the name
223 */
/*
P/P * Method: String getName()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
224 public String getName() {
225 return properties.getProperty(NAME_KEY);
226 }
227
228 /**
229 * Gets the author of this blog.
230 *
231 * @return the author
232 */
/*
P/P * Method: String getAuthor()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
233 public String getAuthor() {
234 return properties.getProperty(AUTHOR_KEY);
235 }
236
237 /**
238 * Gets the description of this blog.
239 *
240 * @return the description
241 */
/*
P/P * Method: String getDescription()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
242 public String getDescription() {
243 return properties.getProperty(DESCRIPTION_KEY);
244 }
245
246 /**
247 * Gets the image for this blog.
248 *
249 * @return a URL pointing to an image
250 */
/*
P/P * Method: String getImage()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
251 public String getImage() {
252 return properties.getProperty(IMAGE_KEY);
253 }
254
255 /**
256 * Gets the URL where this blog is deployed.
257 *
258 * @return a URL as a String
259 */
260 public abstract String getUrl();
261
262 /**
263 * Gets the relative URL where this blog is deployed.
264 *
265 * @return a URL as a String
266 */
267 public abstract String getRelativeUrl();
268
269 /**
270 * Gets the domain name where this blog is deployed.
271 *
272 * @return a domain name as a String
273 */
/*
P/P * Method: String getDomainName()
*
* Presumptions:
* net.sourceforge.pebble.PebbleContext:getConfiguration(...)@275 != null
* net.sourceforge.pebble.PebbleContext:getInstance(...)@275 != null
*
* Postconditions:
* return_value != null
*/
274 public String getDomainName() {
275 return PebbleContext.getInstance().getConfiguration().getDomainName();
276 }
277
278 /**
279 * Gets the protocol where this blog is deployed.
280 *
281 * @return a protocol as a String
282 */
/*
P/P * Method: String getProtocol()
*
* Presumptions:
* java.lang.String:indexOf(...)@285 <= 232-4
* net.sourceforge.pebble.PebbleContext:getConfiguration(...).url@284 != null
* net.sourceforge.pebble.PebbleContext:getConfiguration(...)@284 != null
* net.sourceforge.pebble.PebbleContext:getInstance(...)@284 != null
*
* Postconditions:
* return_value != null
*/
283 public String getProtocol() {
284 String url = PebbleContext.getInstance().getConfiguration().getUrl();
285 return url.substring(0, url.indexOf("://")+3);
286 }
287
288 /**
289 * Gets the context where Pebble is deployed.
290 *
291 * @return the webapp context
292 */
/*
P/P * Method: String getContext()
*
* Presumptions:
* java.lang.String:indexOf(...)@295 <= 232-4
* net.sourceforge.pebble.PebbleContext:getConfiguration(...).url@294 != null
* net.sourceforge.pebble.PebbleContext:getConfiguration(...)@294 != null
* net.sourceforge.pebble.PebbleContext:getInstance(...)@294 != null
*
* Postconditions:
* return_value != null
*
* Test Vectors:
* java.lang.String:indexOf(...)@295: {-231..-2, 0..232-1}, {-1}
*/
293 public String getContext() {
294 String url = PebbleContext.getInstance().getConfiguration().getUrl();
295 int index = url.indexOf("/", url.indexOf("://")+3);
296 if (index == -1) {
297 return "/";
298 } else {
299 return url.substring(index);
300 }
301 }
302
303 /**
304 * Gets the ID of the time zone for the blog.
305 *
306 * @return a String (Europe/London by default)
307 */
/*
P/P * Method: String getTimeZoneId()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
308 public String getTimeZoneId() {
309 return properties.getProperty(TIMEZONE_KEY);
310 }
311
312 /**
313 * Gets the TimeZone instance representing the timezone for the blog.
314 *
315 * @return a TimeZone instance
316 */
/*
P/P * Method: TimeZone getTimeZone()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
317 public TimeZone getTimeZone() {
318 return TimeZone.getTimeZone(getTimeZoneId());
319 }
320
321 /**
322 * Gets a Calendar instance representing the current moment in time,
323 * with the timezone and locale set to be the same as that specified
324 * for this blog.
325 *
326 * @return a Calendar instance
327 */
/*
P/P * Method: Calendar getCalendar()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
328 public Calendar getCalendar() {
329 return Calendar.getInstance(getTimeZone(), getLocale());
330 }
331
332 /**
333 * Gets the number of recent blog entries that are displayed on the home page.
334 *
335 * @return an int (3 by default)
336 */
/*
P/P * Method: int getRecentBlogEntriesOnHomePage()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
337 public int getRecentBlogEntriesOnHomePage() {
338 return Integer.parseInt(properties.getProperty(RECENT_BLOG_ENTRIES_ON_HOME_PAGE_KEY));
339 }
340
341 /**
342 * Gets the number of recent comments that are displayed on the home page.
343 *
344 * @return an int (0 by default)
345 */
/*
P/P * Method: int getRecentResponsesOnHomePage()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
346 public int getRecentResponsesOnHomePage() {
347 return Integer.parseInt(properties.getProperty(RECENT_RESPONSES_ON_HOME_PAGE_KEY));
348 }
349
350 /**
351 * Gets the character encoding in use by this blog.
352 *
353 * @return the character encoding as an IANA registered character set code
354 */
/*
P/P * Method: String getCharacterEncoding()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
355 public String getCharacterEncoding() {
356 return properties.getProperty(CHARACTER_ENCODING_KEY);
357 }
358
359 /**
360 * Gets string instance representing the language for the blog.
361 *
362 * @return a two-letter ISO language code (en by default)
363 */
/*
P/P * Method: String getLanguage()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
364 public String getLanguage() {
365 return properties.getProperty(LANGUAGE_KEY);
366 }
367
368 /**
369 * Gets string instance representing the country for the blog.
370 *
371 * @return a two-letter ISO country code (GB by default)
372 */
/*
P/P * Method: String getCountry()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
373 public String getCountry() {
374 return properties.getProperty(COUNTRY_KEY);
375 }
376
377 /**
378 * Gets the Locale instance for the blog.
379 *
380 * @return a Locale instance based upon the language and country.
381 */
/*
P/P * Method: Locale getLocale()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* return_value == &new Locale(getLocale#1)
* new Locale(getLocale#1) num objects == 1
*/
382 public Locale getLocale() {
383 return new Locale(getLanguage(), getCountry());
384 }
385
386 /**
387 * Gets the theme being used.
388 *
389 * @return a theme name as a String
390 */
/*
P/P * Method: String getTheme()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
391 public String getTheme() {
392 return properties.getProperty(THEME_KEY);
393 }
394
395 /**
396 * Gets the location where the blog images are stored.
397 *
398 * @return an absolute, local path on the filing system
399 */
/*
P/P * Method: String getImagesDirectory()
*
* Preconditions:
* init'ed(this.root)
*
* Presumptions:
* init'ed(java.io.File.separator)
*
* Postconditions:
* return_value != null
*/
400 public String getImagesDirectory() {
401 return getRoot() + File.separator + "images";
402 }
403
404 /**
405 * Gets the location where the blog search indexes are stored.
406 *
407 * @return an absolute, local path on the filing system
408 */
/*
P/P * Method: String getIndexesDirectory()
*
* Preconditions:
* init'ed(this.root)
*
* Presumptions:
* init'ed(java.io.File.separator)
*
* Postconditions:
* return_value != null
*/
409 public String getIndexesDirectory() {
410 return getRoot() + File.separator + "indexes";
411 }
412
413 /**
414 * Gets the location where the blog search indexes are stored.
415 *
416 * @return an absolute, local path on the filing system
417 */
/*
P/P * Method: String getSearchIndexDirectory()
*
* Preconditions:
* init'ed(this.root)
*
* Presumptions:
* init'ed(java.io.File.separator)
*
* Postconditions:
* return_value != null
*/
418 public String getSearchIndexDirectory() {
419 return getIndexesDirectory() + File.separator + "search";
420 }
421
422 /**
423 * Gets the location where the blog logs are stored.
424 *
425 * @return an absolute, local path on the filing system
426 */
/*
P/P * Method: String getLogsDirectory()
*
* Preconditions:
* init'ed(this.root)
*
* Presumptions:
* init'ed(java.io.File.separator)
*
* Postconditions:
* return_value != null
*/
427 public String getLogsDirectory() {
428 return getRoot() + File.separator + "logs";
429 }
430
431 /**
432 * Gets the most recent blog entries, the number
433 * of which is specified.
434 *
435 * @param numberOfEntries the number of entries to get
436 * @return a List containing the most recent blog entries
437 */
438 public abstract List getRecentBlogEntries(int numberOfEntries);
439
440 /**
441 * Gets the most recent blog entries, the number of which is taken from
442 * the recentBlogEntriesOnHomePage property.
443 *
444 * @return a List containing the most recent blog entries
445 */
/*
P/P * Method: List getRecentBlogEntries()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
* new ArrayList(getRecentBlogEntries#2*) num objects <= 1
* new ArrayList(getRecentBlogEntries#4*) num objects <= 1
*/
446 public List getRecentBlogEntries() {
447 return getRecentBlogEntries(getRecentBlogEntriesOnHomePage());
448 }
449
450 /**
451 * Setter method for the recentBlogEntries property - this is here so that
452 * the property complies with the JavaBeans standard.
453 *
454 * @param entries
455 */
/*
P/P * Method: void setRecentBlogEntries(List)
*/
456 public void setRecentBlogEntries(List entries) {
457 // do nothing
458 }
459
460 /**
461 * Gets the date that this blog was last updated.
462 *
463 * @return a Date instance representing the time of the most recent entry
464 */
465 public abstract Date getLastModified();
466
467 /**
468 * Gets a string representation of this object.
469 *
470 * @return a String
471 */
/*
P/P * Method: String toString()
*
* Preconditions:
* this.properties != null
*
* Postconditions:
* init'ed(return_value)
*/
472 public String toString() {
473 return getName();
474 }
475
/*
P/P * Method: void info(String)
*
* Preconditions:
* log != null
* this.messages != null
*
* Postconditions:
* init'ed(this.messages)
*/
476 public synchronized void info(String text) {
477 Message message = new Message(MessageType.INFO, text);
478 messages.add(0, message);
479 log.info(message.getText());
480 truncateMessages();
481 }
482
/*
P/P * Method: void warn(String)
*
* Preconditions:
* log != null
* this.messages != null
*
* Postconditions:
* init'ed(this.messages)
*/
483 public synchronized void warn(String text) {
484 Message message = new Message(MessageType.WARN, text);
485 messages.add(0, message);
486 log.warn(message.getText());
487 truncateMessages();
488 }
489
/*
P/P * Method: void error(String)
*
* Preconditions:
* log != null
* this.messages != null
*
* Postconditions:
* init'ed(this.messages)
*/
490 public synchronized void error(String text) {
491 Message message = new Message(MessageType.ERROR, text);
492 messages.add(0, message);
493 log.error(message.getText());
494 truncateMessages();
495 }
496
/*
P/P * Method: void truncateMessages()
*
* Preconditions:
* this.messages != null
*
* Postconditions:
* init'ed(this.messages)
*
* Test Vectors:
* java.util.List:size(...)@498: {-231..20}, {21..232-1}
*/
497 private void truncateMessages() {
498 if (messages.size() > MAXIMUM_MESSAGES) {
499 messages = messages.subList(0, MAXIMUM_MESSAGES);
500 }
501 }
502
/*
P/P * Method: void clearMessages()
*
* Preconditions:
* this.messages != null
*/
503 public synchronized void clearMessages() {
504 messages.clear();
505 }
506
/*
P/P * Method: List getMessages()
*
* Preconditions:
* init'ed(this.messages)
*
* Postconditions:
* return_value == &new ArrayList(getMessages#1)
* new ArrayList(getMessages#1) num objects == 1
*/
507 public List<Message> getMessages() {
508 return new ArrayList<Message>(messages);
509 }
510
/*
P/P * Method: int getNumberOfMessages()
*
* Preconditions:
* this.messages != null
*
* Postconditions:
* init'ed(return_value)
*/
511 public int getNumberOfMessages() {
512 return messages.size();
513 }
514
515 /**
516 * Logs this request for blog.
517 *
518 * @param request the HttpServletRequest instance for this request
519 */
520 public abstract void log(HttpServletRequest request, int status);
521
522 }
SofCheck Inspector Build Version : 2.22510
| abstractblog.java |
2010-Jun-25 19:40:32 |
| abstractblog.class |
2010-Jul-19 20:23:40 |