File Source: blogmanager.java
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 net.sourceforge.pebble.PebbleContext;
35 import net.sourceforge.pebble.util.UpgradeUtilities;
36 import net.sourceforge.pebble.comparator.BlogByLastModifiedDateComparator;
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39
40 import java.io.*;
41 import java.util.*;
42
43 /**
44 * A singleton to manage the active blog.
45 *
46 * @author Simon Brown
47 */
48 public class BlogManager {
49
50 /** the log used by this class */
/*
P/P * Method: net.sourceforge.pebble.domain.BlogManager__static_init
*
* Postconditions:
* instance == &new BlogManager(BlogManager__static_init#1)
* init'ed(log)
* new BlogManager(BlogManager__static_init#1) num objects == 1
* new HashMap(BlogManager#1) num objects == 1
* instance.blogs == &new HashMap(BlogManager#1)
* instance.multiBlog == 0
*/
51 private static Log log = LogFactory.getLog(BlogManager.class);
52
53 /** the singleton instance of this class */
54 private static BlogManager instance = new BlogManager();
55
56 private static final String THEMES_PATH = "themes";
57 private static final String DEFAULT_BLOG = "default";
58
59 /** the blogs that are currently being managed */
60 private Map<String,Blog> blogs = new HashMap<String,Blog>();
61
62 private boolean multiBlog = false;
63
64 /**
65 * Creates a new instance - private constructor for the singleton pattern.
66 */
/*
P/P * Method: void net.sourceforge.pebble.domain.BlogManager()
*
* Postconditions:
* this.blogs == &new HashMap(BlogManager#1)
* this.multiBlog == 0
* new HashMap(BlogManager#1) num objects == 1
*/
67 private BlogManager() {
68 }
69
70 /**
71 * Gets the singleton instance of this class.
72 *
73 * @return the singleton BlogManager instance
74 */
75 public static BlogManager getInstance() {
/*
P/P * Method: BlogManager getInstance()
*
* Preconditions:
* init'ed(instance)
*
* Postconditions:
* return_value == instance
* init'ed(return_value)
*/
76 return instance;
77 }
78
79 /**
80 * Gets the default blog.
81 *
82 * @return the active Blog instance
83 */
84 public Blog getBlog() {
/*
P/P * Method: Blog getBlog()
*
* Preconditions:
* this.blogs != null
*
* Postconditions:
* init'ed(return_value)
*/
85 return getBlog(DEFAULT_BLOG);
86 }
87
88 /**
89 * Gets a named blog. If running in single user mode then this method
90 * returns the currently active blog. If running in multi-user mode,
91 * this method returns the named blog from the overall composite
92 * blog.
93 *
94 * @param id the blog ID
95 * @return a Blog instance
96 */
97 public Blog getBlog(String id) {
/*
P/P * Method: Blog getBlog(String)
*
* Preconditions:
* this.blogs != null
*
* Postconditions:
* init'ed(return_value)
*/
98 return blogs.get(id);
99 }
100
101 /**
102 * Configures this instance to manage the blog(s) in the specified directory.
103 */
104 public void startBlogs() {
/*
P/P * Method: void startBlogs()
*
* Preconditions:
* init'ed(this.multiBlog)
* (soft) log != null
*
* Presumptions:
* Local_7[Local_5]@115 != null
* files.length@115 <= 232-1
*
* Test Vectors:
* this.multiBlog: {0}, {1}
* java.io.File:exists(...)@108: {1}, {0}
* java.io.File:isDirectory(...)@118: {0}, {1}
* java.io.File:listFiles(...)@115: Addr_Set{null}, Inverse{null}
*/
105 File blogsDirectory = getBlogsDirectory();
106 File defaultBlog = new File(blogsDirectory, DEFAULT_BLOG);
107
108 if (!blogsDirectory.exists()) {
109 log.info("Pebble blog directory does not exist - creating");
110 defaultBlog.mkdirs();
111 }
112
113 if (isMultiBlog()) {
114 // find all directories and set them up as blogs
115 File files[] = getBlogsDirectory().listFiles();
116 if (files != null) {
117 for (File file : files) {
118 if (file.isDirectory()) {
119 startBlog(file.getAbsolutePath(), file.getName());
120 }
121 }
122 }
123 } else {
124 // start the default blog only
125 startBlog(defaultBlog.getAbsolutePath(), DEFAULT_BLOG);
126 }
127 }
128
129 public void stopBlogs() {
/*
P/P * Method: void stopBlogs()
*
* Preconditions:
* (soft) net/sourceforge/pebble/domain/Theme.log != null
*
* Presumptions:
* blog.editableTheme.blog@130 != null
* blog.editableTheme@130 != null
* blog.eventDispatcher.eventListenerList.blogListeners@130 != null
* blog.eventDispatcher.eventListenerList@130 != null
* blog.eventDispatcher@130 != null
* ...
*
* Preconditions:
* this.blogs != null
*
* Presumptions:
* java.util.Iterator:next(...)@130 != null
* java.util.Map:values(...)@130 != null
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@130: {1}, {0}
*/
130 for (Blog blog : blogs.values()) {
131 stopBlog(blog);
132 }
133 }
134
135 private void stopBlog(Blog blog) {
/*
P/P * Method: void stopBlog(Blog)
*
* Preconditions:
* blog != null
* blog.editableTheme != null
* blog.editableTheme.blog != null
* init'ed(blog.editableTheme.name)
* init'ed(blog.editableTheme.pathToLiveThemes)
* blog.eventDispatcher != null
* blog.eventDispatcher.eventListenerList != null
* blog.eventDispatcher.eventListenerList.blogListeners != null
* init'ed(blog.id)
* blog.logger != null
* ...
*/
136 blog.stop();
137 }
138
139 public void reloadBlog(Blog blog) {
/*
P/P * Method: void reloadBlog(Blog)
*
* Preconditions:
* blog != null
* blog.editableTheme != null
* blog.editableTheme.blog != null
* init'ed(blog.editableTheme.name)
* init'ed(blog.editableTheme.pathToLiveThemes)
* blog.eventDispatcher != null
* blog.eventDispatcher.eventListenerList != null
* blog.eventDispatcher.eventListenerList.blogListeners != null
* init'ed(blog.id)
* blog.logger != null
* ...
*/
140 stopBlog(blog);
141
142 File f = new File(getBlogsDirectory(), blog.getId());
143 startBlog(f.getAbsolutePath(), blog.getId());
144 }
145
146 /**
147 * Loads a blog that is a part of a larger composite blog.
148 *
149 * @param blogDir the blog.dir for the blog
150 * @param blogId the ID for the blog
151 */
152 private void startBlog(String blogDir, String blogId) {
/*
P/P * Method: void startBlog(String, String)
*
* Preconditions:
* this.blogs != null
* (soft) log != null
* net/sourceforge/pebble/domain/Theme.log != null
*
* Presumptions:
* blog.eventDispatcher != null
* blog.eventDispatcher.eventListenerList != null
* blog.eventDispatcher.eventListenerList.blogListeners != null
* blog.eventDispatcher.eventListenerList.blogListeners@179 != null
* blog.eventDispatcher.eventListenerList@179 != null
* ...
*
* Test Vectors:
* java.io.File:exists(...)@168: {0}, {1}
* java.lang.String:equals(...)@178: {1}, {0}
*/
153 Blog blog = new Blog(blogDir);
154 blog.setId(blogId);
155
156 File pathToLiveThemes = new File(PebbleContext.getInstance().getWebApplicationRoot(), THEMES_PATH);
157 Theme theme = new Theme(blog, "user-" + blogId, pathToLiveThemes.getAbsolutePath());
158 blog.setEditableTheme(theme);
159
160 blog.start();
161 blogs.put(blog.getId(), blog);
162
163 // which version are we at and do we need to upgrade?
164 File versionFile = new File(blogDir, "pebble.version");
165 String blogVersion = null;
166 String currentVersion = PebbleContext.getInstance().getBuildVersion();
167 try {
168 if (versionFile.exists()) {
169 BufferedReader reader = new BufferedReader(new FileReader(versionFile));
170 blogVersion = reader.readLine();
171 reader.close();
172 }
173 } catch (Exception e) {
174 log.error("Exception encountered", e);
175 }
176
177 try {
178 if (blogVersion == null || !blogVersion.equals(currentVersion)) {
179 UpgradeUtilities.upgradeBlog(blog, blogVersion, currentVersion);
180
181 BufferedWriter writer = new BufferedWriter(new FileWriter(versionFile));
182 writer.write(currentVersion);
183 writer.close();
184
185 // now that the upgrade is complete, reload the blog
186 reloadBlog(blog);
187 }
188 } catch (Exception e) {
189 log.error("Exception encountered", e);
190 }
191 }
192
193 public void addBlog(String blogId) {
/*
P/P * Method: void addBlog(String)
*/
194 File file = new File(getBlogsDirectory(), blogId);
195 file.mkdirs();
196 startBlog(file.getAbsolutePath(), blogId);
197 }
198
199 /**
200 * Determines whether this blog manager supports multiple blogs.
201 *
202 * @return true if multiple blogs are supported, false otherwise
203 */
204 public boolean isMultiBlog() {
/*
P/P * Method: bool isMultiBlog()
*
* Preconditions:
* init'ed(this.multiBlog)
*
* Postconditions:
* return_value == this.multiBlog
* init'ed(return_value)
*/
205 return this.multiBlog;
206 }
207
208 public void setMultiBlog(boolean multiBlog) {
/*
P/P * Method: void setMultiBlog(bool)
*
* Postconditions:
* this.multiBlog == multiBlog
* init'ed(this.multiBlog)
*/
209 this.multiBlog = multiBlog;
210 }
211
212 public void addBlog(Blog blog) {
/*
P/P * Method: void addBlog(Blog)
*
* Preconditions:
* blog != null
* this.blogs != null
* init'ed(blog.id)
*/
213 blogs.put(blog.getId(), blog);
214 }
215
216 public void removeAllBlogs() {
/*
P/P * Method: void removeAllBlogs()
*
* Postconditions:
* this.blogs == &new HashMap(removeAllBlogs#1)
* new HashMap(removeAllBlogs#1) num objects == 1
*/
217 blogs = new HashMap<String,Blog>();
218 }
219
220 /**
221 * Gets all blogs that are currently being managed.
222 *
223 * @return a Collection of Blog instances
224 */
225 public Collection<Blog> getBlogs() {
/*
P/P * Method: Collection getBlogs()
*
* Preconditions:
* this.blogs != null
*
* Postconditions:
* return_value == &new ArrayList(getBlogs#1)
* new ArrayList(getBlogs#1) num objects == 1
*/
226 List<Blog> sortedBlogs = new ArrayList<Blog>(blogs.values());
227 Collections.sort(sortedBlogs, new BlogByLastModifiedDateComparator());
228 return sortedBlogs;
229 }
230
231 /**
232 * Gets the number of blogs that are currently being managed.
233 *
234 * @return the number of managed blogs
235 */
236 public int getNumberOfBlogs() {
/*
P/P * Method: int getNumberOfBlogs()
*
* Preconditions:
* this.blogs != null
*
* Postconditions:
* init'ed(return_value)
*/
237 return blogs.size();
238 }
239
240
241 /**
242 * Gets all blogs that are currently being managed and are
243 * to be included in aggregated pages and feeds.
244 *
245 * @return a List of Blog instances
246 */
247 public List<Blog> getPublicBlogs() {
/*
P/P * Method: List getPublicBlogs()
*
* Preconditions:
* this.blogs != null
*
* Presumptions:
* java.util.Iterator:next(...)@249 != null
* java.util.Map:values(...)@249 != null
*
* Postconditions:
* return_value == &new ArrayList(getPublicBlogs#1)
* new ArrayList(getPublicBlogs#1) num objects == 1
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@249: {1}, {0}
*
* Presumptions:
* blog.properties@249 != null
*
* Test Vectors:
* java.lang.String:equalsIgnoreCase(...)@1554: {0}, {1}
*/
248 List<Blog> list = new ArrayList<Blog>();
249 for (Blog blog : blogs.values()) {
250 if (blog.isPublic()) {
251 list.add(blog);
252 }
253 }
254
255 return list;
256 }
257
258 /**
259 * Determines whether there is a blog with the specified ID.
260 *
261 * @param id the blog ID
262 * @return true if a blog with the specified ID exists, false otherwise
263 */
264 public boolean hasBlog(String id) {
/*
P/P * Method: bool hasBlog(String)
*
* Preconditions:
* this.blogs != null
*
* Postconditions:
* init'ed(return_value)
*/
265 return blogs.containsKey(id);
266 }
267
268 public MultiBlog getMultiBlog() {
/*
P/P * Method: MultiBlog getMultiBlog()
*
* Postconditions:
* return_value == &new MultiBlog(getMultiBlog#1)
* new MultiBlog(getMultiBlog#1) num objects == 1
*
* Preconditions:
* (soft) net/sourceforge/pebble/domain/AbstractBlog.log != null
*
* Presumptions:
* net.sourceforge.pebble.PebbleContext:getConfiguration(...)@269 != null
* net.sourceforge.pebble.PebbleContext:getInstance(...)@269 != null
*
* Postconditions:
* new LinkedList(AbstractBlog#1) num objects == 1
* new Properties(loadProperties#1) num objects == 1
* init'ed(return_value.blog)
* return_value.messages == &new LinkedList(AbstractBlog#1)
* return_value.properties == &new Properties(loadProperties#1)
* init'ed(return_value.root)
*/
269 return new MultiBlog(PebbleContext.getInstance().getConfiguration().getDataDirectory());
270 }
271
272 private File getBlogsDirectory() {
/*
P/P * Method: File getBlogsDirectory()
*
* Postconditions:
* return_value == &new File(getBlogsDirectory#1)
* new File(getBlogsDirectory#1) num objects == 1
*
* Presumptions:
* net.sourceforge.pebble.PebbleContext:getConfiguration(...)@273 != null
* net.sourceforge.pebble.PebbleContext:getInstance(...)@273 != null
*/
273 return new File(PebbleContext.getInstance().getConfiguration().getDataDirectory(), "blogs");
274 }
275
276 }
SofCheck Inspector Build Version : 2.22510
| blogmanager.java |
2010-Jun-25 19:40:32 |
| blogmanager.class |
2010-Jul-19 20:23:40 |