Coverage Report - net.sourceforge.pebble.domain.AbstractBlog
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractBlog
63%
58/91
50%
5/10
1.184
 
 1  
 /*
 2  
  * Copyright (c) 2003-2011, 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  
 
 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  4
   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  2740
   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  2740
     super(null);
 88  2740
     this.root = root;
 89  
 // see javadoc comment about why init cannot be called here.
 90  
 //    init();
 91  2740
   }
 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  
    */
 98  
   protected void init() {
 99  2740
     loadProperties();
 100  2740
   }
 101  
 
 102  
   /**
 103  
    * Loads the properties for this blog, from the blog.properties file
 104  
    * in the root directory.
 105  
    */
 106  
   protected void loadProperties() {
 107  
     try {
 108  2740
       this.properties = new Properties(getDefaultProperties());
 109  
 
 110  2740
       File blogPropertiesFile = new File(getRoot(), BLOG_PROPERTIES_FILE);
 111  2740
       if (!blogPropertiesFile.exists()) {
 112  2740
         return;
 113  
       }
 114  
 
 115  0
       FileInputStream fin = new FileInputStream(blogPropertiesFile);
 116  0
       properties.load(fin);
 117  0
       fin.close();
 118  0
     } catch (IOException ioe) {
 119  0
       log.error("A blog.properties file at " + getRoot() + " cannot be loaded", ioe);
 120  0
     }
 121  0
   }
 122  
 
 123  
   public boolean isConfigured() {
 124  0
     File blogPropertiesFile = new File(getRoot(), BLOG_PROPERTIES_FILE);
 125  0
     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  
    */
 147  
   public String getRoot() {
 148  73444
     return root;
 149  
   }
 150  
 
 151  
   /**
 152  
    * Sets the filesystem root for this blog.
 153  
    *
 154  
    * @param root    a String representing the absolute path
 155  
    */
 156  
   protected void setRoot(String root) {
 157  0
     this.root = root;
 158  0
   }
 159  
 
 160  
   /**
 161  
    * Gets the properties associated with this blog.
 162  
    *
 163  
    * @return  a java.util.Properties object
 164  
    */
 165  
   public Properties getProperties() {
 166  4
     return (Properties)properties.clone();
 167  
   }
 168  
 
 169  
   /**
 170  
    * Gets a named property for this blog.
 171  
    *
 172  
    * @param key     the property name/key
 173  
    * @return        the property value
 174  
    */
 175  
   public String getProperty(String key) {
 176  29992
     return properties.getProperty(key);
 177  
   }
 178  
 
 179  
   /**
 180  
    * Sets a named property for this blog.
 181  
    *
 182  
    * @param key     the property name/key
 183  
    * @param value   the property value
 184  
    */
 185  
   public void setProperty(String key, String value) {
 186  2876
     if (key != null) {
 187  2876
       if (value != null) {
 188  2876
         properties.setProperty(key, value);
 189  
       } else {
 190  0
         removeProperty(key);
 191  
       }
 192  
     }
 193  2876
   }
 194  
 
 195  
   /**
 196  
    * Removes a named property for this blog.
 197  
    *
 198  
    * @param key     the property name/key
 199  
    */
 200  
   public void removeProperty(String key) {
 201  20
     properties.remove(key);
 202  20
   }
 203  
 
 204  
   /**
 205  
    * Stores the properties associated with this blog.
 206  
    *
 207  
    * @throws BlogServiceException    if the properties can't be stored
 208  
    */
 209  
   public void storeProperties() throws BlogServiceException {
 210  
     try {
 211  0
       FileOutputStream fout = new FileOutputStream(new File(getRoot(), BLOG_PROPERTIES_FILE));
 212  0
       properties.store(fout, "Properties for " + getName());
 213  0
       fout.flush();
 214  0
       fout.close();
 215  0
     } catch (IOException ioe) {
 216  0
       log.error(ioe);
 217  0
     }
 218  0
   }
 219  
 
 220  
   /**
 221  
    * Gets the name of this blog.
 222  
    *
 223  
    * @return    the name
 224  
    */
 225  
   public String getName() {
 226  44
     return properties.getProperty(NAME_KEY);
 227  
   }
 228  
 
 229  
   /**
 230  
    * Gets the author of this blog.
 231  
    *
 232  
    * @return    the author
 233  
    */
 234  
   public String getAuthor() {
 235  12
     return properties.getProperty(AUTHOR_KEY);
 236  
   }
 237  
 
 238  
   /**
 239  
    * Gets the description of this blog.
 240  
    *
 241  
    * @return    the description
 242  
    */
 243  
   public String getDescription() {
 244  12
     return properties.getProperty(DESCRIPTION_KEY);
 245  
   }
 246  
 
 247  
   /**
 248  
    * Gets the image for this blog.
 249  
    *
 250  
    * @return    a URL pointing to an image
 251  
    */
 252  
   public String getImage() {
 253  16
     return properties.getProperty(IMAGE_KEY);
 254  
   }
 255  
 
 256  
   /**
 257  
    * Gets the URL where this blog is deployed.
 258  
    *
 259  
    * @return  a URL as a String
 260  
    */
 261  
   public abstract String getUrl();
 262  
 
 263  
   /**
 264  
    * Gets the relative URL where this blog is deployed.
 265  
    *
 266  
    * @return  a URL as a String
 267  
    */
 268  
   public abstract String getRelativeUrl();
 269  
 
 270  
   /**
 271  
    * Gets the domain name where this blog is deployed.
 272  
    *
 273  
    * @return  a domain name as a String
 274  
    */
 275  
   public String getDomainName() {
 276  24
     return PebbleContext.getInstance().getConfiguration().getDomainName();
 277  
   }
 278  
 
 279  
   /**
 280  
    * Gets the protocol where this blog is deployed.
 281  
    *
 282  
    * @return  a protocol as a String
 283  
    */
 284  
   public String getProtocol() {
 285  4
     String url = PebbleContext.getInstance().getConfiguration().getUrl();
 286  4
     return url.substring(0, url.indexOf("://")+3);
 287  
   }
 288  
 
 289  
   /**
 290  
    * Gets the context where Pebble is deployed.
 291  
    *
 292  
    * @return    the webapp context
 293  
    */
 294  
   public String getContext() {
 295  12
     String url = PebbleContext.getInstance().getConfiguration().getUrl();
 296  12
     int index = url.indexOf("/", url.indexOf("://")+3);
 297  12
     if (index == -1) {
 298  0
       return "/";
 299  
     } else {
 300  12
       return url.substring(index);
 301  
     }
 302  
   }
 303  
 
 304  
   /**
 305  
    * Gets the ID of the time zone for the blog.
 306  
    *
 307  
    * @return    a String (Europe/London by default)
 308  
    */
 309  
   public String getTimeZoneId() {
 310  307404
     return properties.getProperty(TIMEZONE_KEY);
 311  
   }
 312  
 
 313  
   /**
 314  
    * Gets the TimeZone instance representing the timezone for the blog.
 315  
    *
 316  
    * @return    a TimeZone instance
 317  
    */
 318  
   public TimeZone getTimeZone() {
 319  307272
     return TimeZone.getTimeZone(getTimeZoneId());
 320  
   }
 321  
 
 322  
   /**
 323  
    * Gets a Calendar instance representing the current moment in time,
 324  
    * with the timezone and locale set to be the same as that specified
 325  
    * for this blog.
 326  
    *
 327  
    * @return    a Calendar instance
 328  
    */
 329  
   public Calendar getCalendar() {
 330  299868
     return Calendar.getInstance(getTimeZone(), getLocale());
 331  
   }
 332  
 
 333  
   /**
 334  
    * Gets the number of recent blog entries that are displayed on the home page.
 335  
    *
 336  
    * @return  an int (3 by default)
 337  
    */
 338  
   public int getRecentBlogEntriesOnHomePage() {
 339  52
     return Integer.parseInt(properties.getProperty(RECENT_BLOG_ENTRIES_ON_HOME_PAGE_KEY));
 340  
   }
 341  
 
 342  
   /**
 343  
    * Gets the number of recent comments that are displayed on the home page.
 344  
    *
 345  
    * @return  an int (0 by default)
 346  
    */
 347  
   public int getRecentResponsesOnHomePage() {
 348  4
     return Integer.parseInt(properties.getProperty(RECENT_RESPONSES_ON_HOME_PAGE_KEY));
 349  
   }
 350  
 
 351  
   /**
 352  
    * Gets the character encoding in use by this blog.
 353  
    *
 354  
    * @return  the character encoding as an IANA registered character set code
 355  
    */
 356  
   public String getCharacterEncoding() {
 357  36
     return properties.getProperty(CHARACTER_ENCODING_KEY);
 358  
   }
 359  
 
 360  
   /**
 361  
    * Gets string instance representing the language for the blog.
 362  
    *
 363  
    * @return    a two-letter ISO language code (en by default)
 364  
    */
 365  
   public String getLanguage() {
 366  302984
     return properties.getProperty(LANGUAGE_KEY);
 367  
   }
 368  
 
 369  
   /**
 370  
    * Gets string instance representing the country for the blog.
 371  
    *
 372  
    * @return    a two-letter ISO country code (GB by default)
 373  
    */
 374  
   public String getCountry() {
 375  302976
     return properties.getProperty(COUNTRY_KEY);
 376  
   }
 377  
 
 378  
   /**
 379  
    * Gets the Locale instance for the blog.
 380  
    *
 381  
    * @return  a Locale instance based upon the language and country.
 382  
    */
 383  
   public Locale getLocale() {
 384  302972
     return new Locale(getLanguage(), getCountry());
 385  
   }
 386  
 
 387  
   /**
 388  
    * Gets the theme being used.
 389  
    *
 390  
    * @return  a theme name as a String
 391  
    */
 392  
   public String getTheme() {
 393  0
     return properties.getProperty(THEME_KEY);
 394  
   }
 395  
 
 396  
   /**
 397  
    * Gets the location where the blog images are stored.
 398  
    *
 399  
    * @return    an absolute, local path on the filing system
 400  
    */
 401  
   public String getImagesDirectory() {
 402  2732
     return getRoot() + File.separator + "images";
 403  
   }
 404  
 
 405  
   /**
 406  
    * Gets the location where the blog search indexes are stored.
 407  
    *
 408  
    * @return    an absolute, local path on the filing system
 409  
    */
 410  
   public String getIndexesDirectory() {
 411  35944
     return getRoot() + File.separator + "indexes";
 412  
   }
 413  
 
 414  
   /**
 415  
    * Gets the location where the blog search indexes are stored.
 416  
    *
 417  
    * @return    an absolute, local path on the filing system
 418  
    */
 419  
   public String getSearchIndexDirectory() {
 420  688
     return getIndexesDirectory() + File.separator + "search";
 421  
   }
 422  
 
 423  
   /**
 424  
    * Gets the location where the blog logs are stored.
 425  
    *
 426  
    * @return    an absolute, local path on the filing system
 427  
    */
 428  
   public String getLogsDirectory() {
 429  4152
     return getRoot() + File.separator + "logs";
 430  
   }
 431  
 
 432  
   /**
 433  
    * Gets the most recent blog entries, the number
 434  
    * of which is specified.
 435  
    *
 436  
    * @param   numberOfEntries   the number of entries to get
 437  
    * @return  a List containing the most recent blog entries
 438  
    */
 439  
   public abstract List<BlogEntry> getRecentBlogEntries(int numberOfEntries);
 440  
 
 441  
   /**
 442  
    * Gets the most recent blog entries, the number of which is taken from
 443  
    * the recentBlogEntriesOnHomePage property.
 444  
    *
 445  
    * @return  a List containing the most recent blog entries
 446  
    */
 447  
   public List<BlogEntry> getRecentBlogEntries() {
 448  12
     return getRecentBlogEntries(getRecentBlogEntriesOnHomePage());
 449  
   }
 450  
 
 451  
   /**
 452  
    * Setter method for the recentBlogEntries property - this is here so that
 453  
    * the property complies with the JavaBeans standard.
 454  
    * 
 455  
    * @param entries
 456  
    */
 457  
   public void setRecentBlogEntries(List<BlogEntry> entries) {
 458  
     // do nothing
 459  0
   }
 460  
 
 461  
   /**
 462  
    * Gets the date that this blog was last updated.
 463  
    *
 464  
    * @return  a Date instance representing the time of the most recent entry
 465  
    */
 466  
   public abstract Date getLastModified();
 467  
 
 468  
   /**
 469  
    * Gets a string representation of this object.
 470  
    *
 471  
    * @return  a String
 472  
    */
 473  
   public String toString() {
 474  0
     return getName();
 475  
   }
 476  
 
 477  
   public synchronized void info(String text) {
 478  108
     Message message = new Message(MessageType.INFO, text);
 479  108
     messages.add(0, message);
 480  108
     log.info(message.getText());
 481  108
     truncateMessages();
 482  108
   }
 483  
 
 484  
   public synchronized void warn(String text) {
 485  0
     Message message = new Message(MessageType.WARN, text);
 486  0
     messages.add(0, message);
 487  0
     log.warn(message.getText());
 488  0
     truncateMessages();
 489  0
   }
 490  
 
 491  
   public synchronized void error(String text) {
 492  4
     Message message = new Message(MessageType.ERROR, text);
 493  4
     messages.add(0, message);
 494  4
     log.error(message.getText());
 495  4
     truncateMessages();
 496  4
   }
 497  
 
 498  
   private void truncateMessages() {
 499  112
     if (messages.size() > MAXIMUM_MESSAGES) {
 500  0
       messages = messages.subList(0, MAXIMUM_MESSAGES);
 501  
     }
 502  112
   }
 503  
 
 504  
   public synchronized void clearMessages() {
 505  0
     messages.clear();
 506  0
   }
 507  
 
 508  
   public List<Message> getMessages() {
 509  8
     return new ArrayList<Message>(messages);
 510  
   }
 511  
 
 512  
   public int getNumberOfMessages() {
 513  0
     return messages.size();
 514  
   }
 515  
 
 516  
   /**
 517  
    * Logs this request for blog.
 518  
    *
 519  
    * @param request   the HttpServletRequest instance for this request
 520  
    */
 521  
   public abstract void log(HttpServletRequest request, int status);
 522  
 
 523  
 }