File Source: ThemeManagerImpl.java
/*
P/P * Method: org.apache.roller.weblogger.business.themes.ThemeManagerImpl$1__static_init
*/
1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. The ASF licenses this file to You
4 * under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License. For additional information regarding
15 * copyright in this work, please see the NOTICE file in the top level
16 * directory of this distribution.
17 */
18
19 package org.apache.roller.weblogger.business.themes;
20
21 import java.io.File;
22 import java.io.FilenameFilter;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.Date;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Set;
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.apache.roller.weblogger.WebloggerException;
35 import org.apache.roller.weblogger.business.FileManager;
36 import org.apache.roller.weblogger.business.InitializationException;
37 import org.apache.roller.weblogger.business.Weblogger;
38 import org.apache.roller.weblogger.business.UserManager;
39 import org.apache.roller.weblogger.config.WebloggerConfig;
40 import org.apache.roller.weblogger.pojos.Theme;
41 import org.apache.roller.weblogger.pojos.ThemeResource;
42 import org.apache.roller.weblogger.pojos.ThemeTemplate;
43 import org.apache.roller.weblogger.pojos.WeblogTemplate;
44 import org.apache.roller.weblogger.pojos.WeblogTheme;
45 import org.apache.roller.weblogger.pojos.Weblog;
46
47
48 /**
49 * Base implementation of a ThemeManager.
50 *
51 * This particular implementation reads theme data off the filesystem
52 * and assumes that those themes are not changable at runtime.
53 */
54 @com.google.inject.Singleton
55 public class ThemeManagerImpl implements ThemeManager {
56
/*
P/P * Method: org.apache.roller.weblogger.business.themes.ThemeManagerImpl__static_init
*
* Postconditions:
* init'ed(log)
*/
57 private static Log log = LogFactory.getLog(ThemeManagerImpl.class);
58
59 private final Weblogger roller;
60
61 // directory where themes are kept
62 private String themeDir = null;
63
64 // the Map contains ... (theme id, Theme)
65 private Map themes = null;
66
67
68 @com.google.inject.Inject
/*
P/P * Method: void org.apache.roller.weblogger.business.themes.ThemeManagerImpl(Weblogger)
*
* Preconditions:
* org/apache/roller/weblogger/config/WebloggerConfig.config != null
* org/apache/roller/weblogger/config/WebloggerConfig.log != null
*
* Presumptions:
* java.io.File:canRead(...)@85 == 1
* java.io.File:exists(...)@85 == 1
* java.io.File:isDirectory(...)@85 == 1
* java.lang.String:length(...)@75 >= 1
*
* Postconditions:
* java.lang.String:substring(...)._tainted == 0
* this.roller == roller
* init'ed(this.roller)
* this.themeDir != null
* this.themes == null
*
* Test Vectors:
* java.lang.String:endsWith(...)@79: {0}, {1}
*/
69 protected ThemeManagerImpl(Weblogger roller) {
70
71 this.roller = roller;
72
73 // get theme directory from config and verify it
74 this.themeDir = WebloggerConfig.getProperty("themes.dir");
+ 75 if(themeDir == null || themeDir.trim().length() < 1) {
76 throw new RuntimeException("couldn't get themes directory from config");
77 } else {
78 // chop off trailing slash if it exists
79 if(themeDir.endsWith("/")) {
80 themeDir = themeDir.substring(0, themeDir.length()-1);
81 }
82
83 // make sure it exists and is readable
84 File themeDirFile = new File(themeDir);
85 if(!themeDirFile.exists() ||
86 !themeDirFile.isDirectory() ||
87 !themeDirFile.canRead()) {
88 throw new RuntimeException("couldn't access theme dir ["+themeDir+"]");
89 }
90 }
91 }
92
93
94 public void initialize() throws InitializationException {
95
/*
P/P * Method: void initialize()
*
* Preconditions:
* log != null
* init'ed(this.themeDir)
* (soft) org/apache/roller/weblogger/business/themes/SharedThemeFromDir.log != null
*
* Postconditions:
* this.themes == One-of{old this.themes, &new HashMap(loadAllThemesFromDisk#1)}
* new HashMap(loadAllThemesFromDisk#1) num objects <= 1
*
* Test Vectors:
* this.themeDir: Addr_Set{null}, Inverse{null}
*/
96 log.debug("Initializing Theme Manager");
97
98 if(themeDir != null) {
99 // rather than be lazy we are going to load all themes from
100 // the disk preemptively and cache them
101 this.themes = loadAllThemesFromDisk();
102
103 log.info("Loaded "+this.themes.size()+" themes from disk.");
104 }
105 }
106
107
108 /**
109 * @see org.apache.roller.weblogger.model.ThemeManager#getTheme(java.lang.String)
110 */
111 public SharedTheme getTheme(String id)
112 throws ThemeNotFoundException, WebloggerException {
113
114 // try to lookup theme from library
/*
P/P * Method: SharedTheme getTheme(String)
*
* Preconditions:
* this.themes != null
*
* Presumptions:
* java.util.Map:get(...)@115 != null
*
* Postconditions:
* (soft) return_value != null
*/
115 SharedTheme theme = (SharedTheme) this.themes.get(id);
116
117 // no theme? throw exception.
118 if(theme == null) {
119 throw new ThemeNotFoundException("Couldn't find theme ["+id+"]");
120 }
121
122 return theme;
123 }
124
125
126 /**
127 * @see org.apache.roller.weblogger.model.ThemeManager#getTheme(weblog)
128 */
129 public WeblogTheme getTheme(Weblog weblog) throws WebloggerException {
130
/*
P/P * Method: WeblogTheme getTheme(Weblog)
*
* Preconditions:
* (soft) log != null
* (soft) this.roller != null
* (soft) this.themes != null
*
* Postconditions:
* return_value in Addr_Set{null,&new WeblogSharedTheme(getTheme#2),&new WeblogCustomTheme(getTheme#1)}
* new WeblogCustomTheme(getTheme#1) num objects <= 1
* new WeblogSharedTheme(getTheme#2) num objects <= 1
* new WeblogSharedTheme(getTheme#2).theme != null
*
* Test Vectors:
* weblog: Inverse{null}, Addr_Set{null}
* java.lang.String:equals(...)@137: {0}, {1}
* java.util.Map:get(...)@144: Addr_Set{null}, Inverse{null}
* org.apache.roller.weblogger.pojos.Weblog:getEditorTheme(...)@137: Addr_Set{null}, Inverse{null}
*/
131 if(weblog == null)
132 return null;
133
134 WeblogTheme weblogTheme = null;
135
136 // if theme is custom or null then return a WeblogCustomTheme
137 if(weblog.getEditorTheme() == null ||
138 WeblogTheme.CUSTOM.equals(weblog.getEditorTheme())) {
139 weblogTheme = new WeblogCustomTheme(weblog);
140
141 // otherwise we are returning a WeblogSharedTheme
142 } else {
+ 143 ThemeManager themeMgr = roller.getThemeManager();
144 SharedTheme staticTheme =
145 (SharedTheme) this.themes.get(weblog.getEditorTheme());
146 if(staticTheme != null) {
147 weblogTheme = new WeblogSharedTheme(weblog, staticTheme);
148 } else {
149 log.warn("Unable to lookup theme "+weblog.getEditorTheme());
150 }
151 }
152
153 // TODO: if somehow the theme is still null should we provide some
154 // kind of fallback option like a default theme?
155
156 return weblogTheme;
157 }
158
159
160 /**
161 * @see org.apache.roller.weblogger.model.ThemeManager#getEnabledThemesList()
162 *
163 * TODO: reimplement enabled vs. disabled logic once we support it
164 */
165 public List getEnabledThemesList() {
166
/*
P/P * Method: List getEnabledThemesList()
*
* Preconditions:
* this.themes != null
*
* Postconditions:
* return_value == &new ArrayList(getEnabledThemesList#1)
* new ArrayList(getEnabledThemesList#1) num objects == 1
*/
167 List all_themes = new ArrayList(this.themes.values());
168
169 // sort 'em ... default ordering for themes is by name
170 Collections.sort(all_themes);
171
172 return all_themes;
173 }
174
175
176 /**
177 * @see org.apache.roller.weblogger.model.ThemeManager#importTheme(website, theme)
178 */
179 public void importTheme(Weblog website, SharedTheme theme)
180 throws WebloggerException {
181
/*
P/P * Method: void importTheme(Weblog, SharedTheme)
*
* Preconditions:
* log != null
* theme != null
* init'ed(theme.name)
* theme.resources != null
* this.roller != null
* this.roller.userManager != null
* this.roller.userManager.strategy != null
* this.roller.userManager.strategy.threadLocalEntityManager != null
* website != null
* (soft) org/apache/roller/weblogger/business/FileManagerImpl.log != null
* ...
*
* Presumptions:
* java.util.Iterator:next(...)@192 != null
* java.util.Iterator:next(...)@272 != null
* getUserManager(...)@185...strategy != userMgr.roller.userManager.strategy
* org.apache.roller.weblogger.business.themes.SharedTheme:getStylesheet(...)@260 != null
* org.apache.roller.weblogger.business.themes.SharedTheme:getTemplates(...)@190 != null
* ...
*
* Test Vectors:
* java.lang.Object:equals(...)@223: {1}, {0}
* java.lang.String:equals(...)@197: {1}, {0}
* java.util.Iterator:hasNext(...)@191: {0}, {1}
* java.util.Iterator:hasNext(...)@271: {0}, {1}
* java.util.Set:contains(...)@247: {1}, {0}
* org.apache.roller.weblogger.business.themes.SharedTheme:getStylesheet(...)@259: Addr_Set{null}, Inverse{null}
* org.apache.roller.weblogger.pojos.ThemeResource:isDirectory(...)@277: {0}, {1}
* org.apache.roller.weblogger.pojos.ThemeTemplate:getAction(...)@197: Addr_Set{null}, Inverse{null}
*/
182 log.debug("Importing theme ["+theme.getName()+"] to weblog ["+website.getName()+"]");
183
184 try {
185 UserManager userMgr = roller.getUserManager();
186
187 Set importedActionTemplates = new HashSet();
188 ThemeTemplate themeTemplate = null;
189 ThemeTemplate stylesheetTemplate = theme.getStylesheet();
190 Iterator iter = theme.getTemplates().iterator();
191 while ( iter.hasNext() ) {
192 themeTemplate = (ThemeTemplate) iter.next();
193
194 WeblogTemplate template = null;
195
196 // if template is an action, lookup by action
197 if(themeTemplate.getAction() != null &&
198 !themeTemplate.getAction().equals(WeblogTemplate.ACTION_CUSTOM)) {
199 template = userMgr.getPageByAction(website, themeTemplate.getAction());
200 if(template != null) {
201 importedActionTemplates.add(themeTemplate.getAction());
202 }
203
204 // otherwise, lookup by name
205 } else {
206 template = userMgr.getPageByName(website, themeTemplate.getName());
207 }
208
209 // Weblog does not have this template, so create it.
210 boolean newTmpl = false;
211 if (template == null) {
212 template = new WeblogTemplate();
213 template.setWebsite(website);
214 newTmpl = true;
215 }
216
217 // TODO: fix conflict situation
218 // it's possible that someone has defined a theme template which
219 // matches 2 existing templates, 1 by action, the other by name
220
221 // update template attributes
222 // NOTE: we don't want to copy the template data for an existing stylesheet
223 if(newTmpl || !themeTemplate.equals(stylesheetTemplate)) {
224 template.setAction(themeTemplate.getAction());
225 template.setName(themeTemplate.getName());
226 template.setDescription(themeTemplate.getDescription());
227 template.setLink(themeTemplate.getLink());
228 template.setContents(themeTemplate.getContents());
229 template.setHidden(themeTemplate.isHidden());
230 template.setNavbar(themeTemplate.isNavbar());
231 template.setTemplateLanguage(themeTemplate.getTemplateLanguage());
232 // NOTE: decorators are deprecated starting in 4.0
233 template.setDecoratorName(null);
234 template.setLastModified(new Date());
235
236 // save it
237 userMgr.savePage( template );
238 }
239 }
240
241 // now, see if the weblog has left over action templates that
242 // need to be deleted because they aren't in their new theme
243 for(int i=0; i < WeblogTemplate.ACTIONS.length; i++) {
244 String action = WeblogTemplate.ACTIONS[i];
245
246 // if we didn't import this action then see if it should be deleted
247 if(!importedActionTemplates.contains(action)) {
248 WeblogTemplate toDelete = userMgr.getPageByAction(website, action);
249 if(toDelete != null) {
250 log.debug("Removing stale action template "+toDelete.getId());
251 userMgr.removePage(toDelete);
252 }
253 }
254 }
255
256
257 // always update this weblog's theme and customStylesheet, then save
258 website.setEditorTheme(WeblogTheme.CUSTOM);
259 if(theme.getStylesheet() != null) {
260 website.setCustomStylesheetPath(theme.getStylesheet().getLink());
261 }
262 userMgr.saveWebsite(website);
263
264
265 // now lets import all the theme resources
266 FileManager fileMgr = roller.getFileManager();
267
268 List resources = theme.getResources();
269 Iterator iterat = resources.iterator();
270 ThemeResource resource = null;
271 while ( iterat.hasNext() ) {
272 resource = (ThemeResource) iterat.next();
273
274 log.debug("Importing resource to "+resource.getPath());
275
276 try {
277 if(resource.isDirectory()) {
278 fileMgr.createDirectory(website, resource.getPath());
279 } else {
280 // save file without file-type, quota checks, etc.
281 fileMgr.saveFile(website, resource.getPath(), "text/plain",
282 resource.getLength(), resource.getInputStream(), false);
283 }
284 } catch (Exception ex) {
285 log.info(ex);
286 }
287 }
288
289 } catch (Exception e) {
290 log.error("ERROR importing theme", e);
291 throw new WebloggerException( e );
292 }
293 }
294
295
296 /**
297 * This is a convenience method which loads all the theme data from
298 * themes stored on the filesystem in the roller webapp /themes/ directory.
299 */
300 private Map loadAllThemesFromDisk() {
301
/*
P/P * Method: Map loadAllThemesFromDisk()
*
* Preconditions:
* init'ed(this.themeDir)
* (soft) log != null
* (soft) org/apache/roller/weblogger/business/themes/SharedThemeFromDir.log != null
*
* Presumptions:
* init'ed(java.io.File.separator)
* themenames.length@313 <= 232-1
*
* Postconditions:
* return_value == &new HashMap(loadAllThemesFromDisk#1)
* new HashMap(loadAllThemesFromDisk#1) num objects == 1
*
* Test Vectors:
* java.io.File:list(...)@313: Inverse{null}, Addr_Set{null}
*/
302 Map themes = new HashMap();
303
304 // first, get a list of the themes available
305 File themesdir = new File(this.themeDir);
/*
P/P * Method: void org.apache.roller.weblogger.business.themes.ThemeManagerImpl$1(ThemeManagerImpl)
*/
306 FilenameFilter filter = new FilenameFilter() {
307 public boolean accept(File dir, String name) {
/*
P/P * Method: bool accept(File, String)
*
* Preconditions:
* dir != null
*
* Presumptions:
* init'ed(java.io.File.separator)
*
* Postconditions:
* init'ed(return_value)
*/
308 File file =
309 new File(dir.getAbsolutePath() + File.separator + name);
310 return file.isDirectory();
311 }
312 };
313 String[] themenames = themesdir.list(filter);
314
315 if(themenames == null) {
316 log.warn("No themes loaded! Perhaps you specified the wrong "+
317 "location for your themes directory?");
318 }
319
320 // now go through each theme and load it into a Theme object
321 for(int i=0; i < themenames.length; i++) {
322 try {
323 Theme theme = new SharedThemeFromDir(this.themeDir + File.separator + themenames[i]);
+ 324 if(theme != null) {
325 themes.put(theme.getId(), theme);
326 }
327 } catch (Throwable unexpected) {
328 // shouldn't happen, so let's learn why it did
329 log.error("Problem reading theme " + themenames[i], unexpected);
330 }
331 }
332
333 return themes;
334 }
335
336 }
SofCheck Inspector Build Version : 2.18479
| ThemeManagerImpl.java |
2009-Jan-02 14:25:28 |
| ThemeManagerImpl.class |
2009-Sep-04 03:12:31 |
| ThemeManagerImpl$1.class |
2009-Sep-04 03:12:31 |