001: /**
002: * Copyright (c) 2003-2007, David A. Czarnecki
003: * All rights reserved.
004: *
005: * Redistribution and use in source and binary forms, with or without
006: * modification, are permitted provided that the following conditions are met:
007: *
008: * Redistributions of source code must retain the above copyright notice, this list of conditions and the
009: * following disclaimer.
010: * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
011: * following disclaimer in the documentation and/or other materials provided with the distribution.
012: * Neither the name of "David A. Czarnecki" and "blojsom" nor the names of its contributors may be used to
013: * endorse or promote products derived from this software without specific prior written permission.
014: * Products derived from this software may not be called "blojsom", nor may "blojsom" appear in their name,
015: * without prior written permission of David A. Czarnecki.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
018: * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
019: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
020: * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
021: * EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
022: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
025: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
026: * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
027: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
028: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
029: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
030: */package org.blojsom.plugin.admin;
031:
032: import org.apache.commons.logging.Log;
033: import org.apache.commons.logging.LogFactory;
034: import org.blojsom.blog.Blog;
035: import org.blojsom.blog.Entry;
036: import org.blojsom.fetcher.Fetcher;
037: import org.blojsom.fetcher.FetcherException;
038: import org.blojsom.plugin.PluginException;
039: import org.blojsom.util.BlojsomConstants;
040: import org.blojsom.util.BlojsomUtils;
041:
042: import javax.servlet.http.HttpServletRequest;
043: import javax.servlet.http.HttpServletResponse;
044: import java.io.File;
045: import java.util.*;
046:
047: /**
048: * EditBlogFlavorsPlugin
049: *
050: * @author David Czarnecki
051: * @version $Id: EditBlogFlavorsPlugin.java,v 1.7 2007/01/17 02:35:05 czarneckid Exp $
052: * @since blojsom 3.0
053: */
054: public class EditBlogFlavorsPlugin extends BaseAdminPlugin {
055:
056: private Log _logger = LogFactory
057: .getLog(EditBlogFlavorsPlugin.class);
058:
059: private static final String PROTECTED_FLAVORS_IP = "protected-flavors";
060: private static final String DEFAULT_PROTECTED_FLAVORS = "admin";
061:
062: // Pages
063: private static final String EDIT_BLOG_FLAVORS_PAGE = "/org/blojsom/plugin/admin/templates/admin-edit-blog-flavors";
064: private static final String EDIT_BLOG_FLAVOR_PAGE = "/org/blojsom/plugin/admin/templates/admin-edit-blog-flavor";
065:
066: // Constants
067: private static final String DEFAULT_MIME_TYPE = "text/html";
068: private static final String DEFAULT_CHARACTER_SET = BlojsomConstants.UTF8;
069: private static final String BLOJSOM_PLUGIN_EDIT_BLOG_FLAVORS_EXISTING = "BLOJSOM_PLUGIN_EDIT_BLOG_FLAVORS_EXISTING";
070: private static final String BLOJSOM_PLUGIN_EDIT_BLOG_FLAVORS_TEMPLATE_FILES = "BLOJSOM_PLUGIN_EDIT_BLOG_FLAVORS_TEMPLATE_FILES";
071: private static final String BLOJSOM_PLUGIN_EDIT_BLOG_FLAVORS_FLAVORS = "BLOJSOM_PLUGIN_EDIT_BLOG_FLAVORS_FLAVORS";
072:
073: private static final String FLAVOR_NAME_EDIT = "FLAVOR_NAME_EDIT";
074: private static final String FLAVOR_TYPE_EDIT = "FLAVOR_TYPE_EDIT";
075: private static final String FLAVOR_CHARACTER_SET_EDIT = "FLAVOR_CHARACTER_SET_EDIT";
076: private static final String FLAVOR_TEMPLATE_EDIT = "FLAVOR_TEMPLATE_EDIT";
077:
078: // Localization constants
079: private static final String FAILED_EDIT_FLAVOR_PERMISSION_KEY = "failed.edit.flavor.permission.text";
080: private static final String NO_FLAVOR_SPECIFIED_KEY = "no.flavor.specified.text";
081: private static final String NO_BLOG_TEMPLATE_SPECIFIED_KEY = "no.blog.template.specified.text";
082: private static final String SUCCESSFULLY_ADDED_FLAVOR_KEY = "successfully.added.flavor.text";
083: private static final String FAILED_UPDATE_FLAVOR_KEY = "failed.update.flavor.text";
084: private static final String FAILED_DELETE_DEFAULT_FLAVOR_KEY = "failed.delete.default.flavor.text";
085: private static final String FAILED_DELETE_PROTECTED_FLAVOR_KEY = "failed.delete.protected.flavor.text";
086: private static final String SUCCESSFULLY_DELETED_FLAVOR_KEY = "successfully.deleted.flavor.text";
087:
088: // Actions
089: private static final String ADD_BLOG_FLAVOR_ACTION = "add-blog-flavor";
090: private static final String MODIFY_BLOG_FLAVOR_ACTION = "modify-blog-flavor";
091: private static final String DELETE_BLOG_FLAVOR_ACTION = "delete-blog-flavor";
092: private static final String EDIT_BLOG_FLAVOR_ACTION = "edit-blog-flavor";
093:
094: // Form elements
095: private static final String FLAVOR_NAME = "flavor-name";
096: private static final String FLAVOR_MIME_TYPE = "flavor-mime-type";
097: private static final String FLAVOR_CHARACTER_SET = "flavor-character-set";
098: private static final String BLOG_TEMPLATE = "blog-template";
099:
100: // Permissions
101: private static final String EDIT_BLOG_FLAVORS_PERMISSION = "edit_blog_flavors_permission";
102:
103: private Fetcher _fetcher;
104: private Properties _blojsomProperties;
105: private String _templatesDirectory;
106: private String _blogsDirectory;
107:
108: /**
109: * Default constructor.
110: */
111: public EditBlogFlavorsPlugin() {
112: }
113:
114: /**
115: * Set the {@link Fetcher}
116: *
117: * @param fetcher {@link Fetcher}
118: */
119: public void setFetcher(Fetcher fetcher) {
120: _fetcher = fetcher;
121: }
122:
123: /**
124: * Set the default blojsom properties
125: *
126: * @param blojsomProperties Default blojsom properties
127: */
128: public void setBlojsomProperties(Properties blojsomProperties) {
129: _blojsomProperties = blojsomProperties;
130: }
131:
132: /**
133: * Initialize this plugin. This method only called when the plugin is instantiated.
134: *
135: * @throws PluginException If there is an error initializing the plugin
136: */
137: public void init() throws PluginException {
138: super .init();
139:
140: _templatesDirectory = _blojsomProperties.getProperty(
141: BlojsomConstants.TEMPLATES_DIRECTORY_IP,
142: BlojsomConstants.DEFAULT_TEMPLATES_DIRECTORY);
143: _blogsDirectory = _blojsomProperties.getProperty(
144: BlojsomConstants.BLOGS_DIRECTORY_IP,
145: BlojsomConstants.DEFAULT_BLOGS_DIRECTORY);
146: }
147:
148: /**
149: * Add flavor information to the context
150: *
151: * @param blog {@link Blog}
152: * @param context Context
153: */
154: protected void addFlavorInformationToContext(Blog blog, Map context) {
155: // Put the available templates in the context for the edit flavors template
156: File templatesDirectory = new File(_servletConfig
157: .getServletContext().getRealPath("/")
158: + BlojsomConstants.DEFAULT_CONFIGURATION_BASE_DIRECTORY
159: + _blogsDirectory
160: + blog.getBlogId()
161: + _templatesDirectory);
162: _logger.debug("Looking for templates in directory: "
163: + templatesDirectory.toString());
164:
165: List templateFiles = new ArrayList();
166: BlojsomUtils.listFilesInSubdirectories(templatesDirectory,
167: templatesDirectory.getAbsolutePath(), templateFiles);
168: File[] templates = (File[]) templateFiles
169: .toArray(new File[templateFiles.size()]);
170: Arrays.sort(templates);
171:
172: // Put the available flavors in the context for the edit flavors template
173: context.put(BLOJSOM_PLUGIN_EDIT_BLOG_FLAVORS_FLAVORS,
174: new TreeMap(blog.getTemplates()));
175: context.put(BLOJSOM_PLUGIN_EDIT_BLOG_FLAVORS_TEMPLATE_FILES,
176: templates);
177: context.put(BLOJSOM_PLUGIN_EDIT_BLOG_FLAVORS_EXISTING,
178: new TreeMap(blog.getTemplates()));
179: }
180:
181: /**
182: * Process the blog entries
183: *
184: * @param httpServletRequest Request
185: * @param httpServletResponse Response
186: * @param blog {@link Blog} instance
187: * @param context Context
188: * @param entries Blog entries retrieved for the particular request
189: * @return Modified set of blog entries
190: * @throws PluginException If there is an error processing the blog entries
191: */
192: public Entry[] process(HttpServletRequest httpServletRequest,
193: HttpServletResponse httpServletResponse, Blog blog,
194: Map context, Entry[] entries) throws PluginException {
195: if (!authenticateUser(httpServletRequest, httpServletResponse,
196: context, blog)) {
197: httpServletRequest.setAttribute(
198: BlojsomConstants.PAGE_PARAM, ADMIN_LOGIN_PAGE);
199:
200: return entries;
201: }
202:
203: String username = getUsernameFromSession(httpServletRequest,
204: blog);
205: if (!checkPermission(blog, null, username,
206: EDIT_BLOG_FLAVORS_PERMISSION)) {
207: httpServletRequest.setAttribute(
208: BlojsomConstants.PAGE_PARAM,
209: ADMIN_ADMINISTRATION_PAGE);
210: addOperationResultMessage(context, getAdminResource(
211: FAILED_EDIT_FLAVOR_PERMISSION_KEY,
212: FAILED_EDIT_FLAVOR_PERMISSION_KEY, blog
213: .getBlogAdministrationLocale()));
214:
215: return entries;
216: }
217:
218: String protectedFlavors = blog
219: .getProperty(PROTECTED_FLAVORS_IP);
220: if (BlojsomUtils.checkNullOrBlank(protectedFlavors)) {
221: protectedFlavors = DEFAULT_PROTECTED_FLAVORS;
222: }
223:
224: if (protectedFlavors.indexOf(DEFAULT_PROTECTED_FLAVORS) == -1) {
225: protectedFlavors = protectedFlavors + " "
226: + DEFAULT_PROTECTED_FLAVORS;
227: }
228:
229: addFlavorInformationToContext(blog, context);
230:
231: String action = BlojsomUtils.getRequestValue(ACTION_PARAM,
232: httpServletRequest);
233: if (BlojsomUtils.checkNullOrBlank(action)) {
234: _logger.debug("User did not request edit action");
235:
236: httpServletRequest.setAttribute(
237: BlojsomConstants.PAGE_PARAM,
238: ADMIN_ADMINISTRATION_PAGE);
239: } else if (PAGE_ACTION.equals(action)) {
240: _logger.debug("User requested add blog flavor page");
241:
242: httpServletRequest
243: .setAttribute(BlojsomConstants.PAGE_PARAM,
244: EDIT_BLOG_FLAVORS_PAGE);
245: } else if (ADD_BLOG_FLAVOR_ACTION.equals(action)
246: || MODIFY_BLOG_FLAVOR_ACTION.equals(action)) {
247: _logger.debug("User requested add blog flavor action");
248:
249: String flavorName = BlojsomUtils.getRequestValue(
250: FLAVOR_NAME, httpServletRequest);
251: if (BlojsomUtils.checkNullOrBlank(flavorName)) {
252: _logger.debug("No flavor name specified");
253: addOperationResultMessage(context, getAdminResource(
254: NO_FLAVOR_SPECIFIED_KEY,
255: NO_FLAVOR_SPECIFIED_KEY, blog
256: .getBlogAdministrationLocale()));
257: httpServletRequest.setAttribute(
258: BlojsomConstants.PAGE_PARAM,
259: EDIT_BLOG_FLAVORS_PAGE);
260:
261: return entries;
262: }
263:
264: String blogTemplate = BlojsomUtils.getRequestValue(
265: BLOG_TEMPLATE, httpServletRequest);
266: if (BlojsomUtils.checkNullOrBlank(blogTemplate)) {
267: _logger.debug("No blog template specified");
268: addOperationResultMessage(context, getAdminResource(
269: NO_BLOG_TEMPLATE_SPECIFIED_KEY,
270: NO_BLOG_TEMPLATE_SPECIFIED_KEY, blog
271: .getBlogAdministrationLocale()));
272: httpServletRequest.setAttribute(
273: BlojsomConstants.PAGE_PARAM,
274: EDIT_BLOG_FLAVORS_PAGE);
275:
276: return entries;
277: }
278:
279: String flavorMimeType = BlojsomUtils.getRequestValue(
280: FLAVOR_MIME_TYPE, httpServletRequest);
281: if (BlojsomUtils.checkNullOrBlank(flavorMimeType)) {
282: flavorMimeType = DEFAULT_MIME_TYPE;
283: _logger
284: .debug("Flavor MIME type not specified. Using default: "
285: + flavorMimeType);
286: }
287:
288: String flavorCharacterSet = BlojsomUtils.getRequestValue(
289: FLAVOR_CHARACTER_SET, httpServletRequest);
290: if (BlojsomUtils.checkNullOrBlank(flavorCharacterSet)) {
291: flavorCharacterSet = DEFAULT_CHARACTER_SET;
292: _logger
293: .debug("Flavor character set not specified. Using default: "
294: + flavorCharacterSet);
295: }
296:
297: Map templateMap = new HashMap(blog.getTemplates());
298: templateMap
299: .put(flavorName, blogTemplate + ", "
300: + flavorMimeType + ";charset="
301: + flavorCharacterSet);
302: blog.setTemplates(templateMap);
303:
304: _logger.debug("Successfully added flavor: " + flavorName
305: + " using template: " + blogTemplate
306: + " with content type: " + flavorMimeType + ";"
307: + flavorCharacterSet);
308:
309: try {
310: _fetcher.saveBlog(blog);
311: addOperationResultMessage(context, formatAdminResource(
312: SUCCESSFULLY_ADDED_FLAVOR_KEY,
313: SUCCESSFULLY_ADDED_FLAVOR_KEY, blog
314: .getBlogAdministrationLocale(),
315: new Object[] { flavorName, blogTemplate,
316: flavorMimeType, flavorCharacterSet }));
317: _logger
318: .debug("Successfully wrote flavor configuration file for blog: "
319: + blog.getBlogId());
320:
321: addFlavorInformationToContext(blog, context);
322: } catch (FetcherException e) {
323: addOperationResultMessage(context, getAdminResource(
324: FAILED_UPDATE_FLAVOR_KEY,
325: FAILED_UPDATE_FLAVOR_KEY, blog
326: .getBlogAdministrationLocale()));
327: _logger.error(e);
328: }
329:
330: httpServletRequest
331: .setAttribute(BlojsomConstants.PAGE_PARAM,
332: EDIT_BLOG_FLAVORS_PAGE);
333: } else if (DELETE_BLOG_FLAVOR_ACTION.equals(action)) {
334: _logger.debug("User requested delete blog flavor action");
335:
336: String flavorName = BlojsomUtils.getRequestValue(
337: FLAVOR_NAME, httpServletRequest);
338: if (BlojsomUtils.checkNullOrBlank(flavorName)) {
339: _logger.debug("No flavor name specified");
340: addOperationResultMessage(context, getAdminResource(
341: NO_FLAVOR_SPECIFIED_KEY,
342: NO_FLAVOR_SPECIFIED_KEY, blog
343: .getBlogAdministrationLocale()));
344: httpServletRequest.setAttribute(
345: BlojsomConstants.PAGE_PARAM,
346: EDIT_BLOG_FLAVORS_PAGE);
347:
348: return entries;
349: }
350:
351: if (flavorName
352: .equalsIgnoreCase(blog.getBlogDefaultFlavor())) {
353: _logger.debug("Cannot delete the default flavor");
354: addOperationResultMessage(context, getAdminResource(
355: FAILED_DELETE_DEFAULT_FLAVOR_KEY,
356: FAILED_DELETE_DEFAULT_FLAVOR_KEY, blog
357: .getBlogAdministrationLocale()));
358: httpServletRequest.setAttribute(
359: BlojsomConstants.PAGE_PARAM,
360: EDIT_BLOG_FLAVORS_PAGE);
361:
362: return entries;
363: }
364:
365: if (protectedFlavors.indexOf(flavorName) != -1) {
366: _logger.debug("Cannot delete protected flavor: "
367: + flavorName);
368: addOperationResultMessage(context, formatAdminResource(
369: FAILED_DELETE_PROTECTED_FLAVOR_KEY,
370: FAILED_DELETE_PROTECTED_FLAVOR_KEY, blog
371: .getBlogAdministrationLocale(),
372: new Object[] { flavorName }));
373: httpServletRequest.setAttribute(
374: BlojsomConstants.PAGE_PARAM,
375: EDIT_BLOG_FLAVORS_PAGE);
376:
377: return entries;
378: }
379:
380: // Delete the flavor from the maps
381: Map templateMap = new HashMap(blog.getTemplates());
382: templateMap.remove(flavorName);
383: blog.setTemplates(templateMap);
384:
385: Map pluginsMap = new HashMap(blog.getPlugins());
386: pluginsMap.remove(flavorName);
387: blog.setPlugins(pluginsMap);
388:
389: // Write out the flavor configuration file
390: try {
391: _fetcher.saveBlog(blog);
392: _logger
393: .debug("Successfully wrote flavor configuration file for blog: "
394: + blog.getBlogId());
395: addOperationResultMessage(context, formatAdminResource(
396: SUCCESSFULLY_DELETED_FLAVOR_KEY,
397: SUCCESSFULLY_DELETED_FLAVOR_KEY, blog
398: .getBlogAdministrationLocale(),
399: new Object[] { flavorName }));
400:
401: addFlavorInformationToContext(blog, context);
402: } catch (FetcherException e) {
403: addOperationResultMessage(context, getAdminResource(
404: FAILED_UPDATE_FLAVOR_KEY,
405: FAILED_UPDATE_FLAVOR_KEY, blog
406: .getBlogAdministrationLocale()));
407: _logger.error(e);
408: }
409:
410: httpServletRequest
411: .setAttribute(BlojsomConstants.PAGE_PARAM,
412: EDIT_BLOG_FLAVORS_PAGE);
413: } else if (EDIT_BLOG_FLAVOR_ACTION.equals(action)) {
414: String flavor = BlojsomUtils.getRequestValue(FLAVOR_NAME,
415: httpServletRequest);
416:
417: context.put(FLAVOR_NAME_EDIT, flavor);
418:
419: Map templates = blog.getTemplates();
420: String templateAndType = (String) templates.get(flavor);
421: String[] templateType = BlojsomUtils
422: .parseCommaList(templateAndType);
423: String[] typeAndCharacterSet;
424: if (templateType.length == 2) {
425: typeAndCharacterSet = BlojsomUtils.parseDelimitedList(
426: templateType[1], ";", true);
427: } else {
428: typeAndCharacterSet = new String[] { "text/html" };
429: }
430:
431: context.put(FLAVOR_TYPE_EDIT, typeAndCharacterSet[0]);
432: if (typeAndCharacterSet.length == 2) {
433: context.put(FLAVOR_CHARACTER_SET_EDIT,
434: typeAndCharacterSet[1]
435: .substring(typeAndCharacterSet[1]
436: .indexOf("=") + 1));
437: } else {
438: context.put(FLAVOR_CHARACTER_SET_EDIT,
439: BlojsomUtils.UTF8);
440: }
441: context.put(FLAVOR_TEMPLATE_EDIT, templateType[0]);
442:
443: httpServletRequest.setAttribute(
444: BlojsomConstants.PAGE_PARAM, EDIT_BLOG_FLAVOR_PAGE);
445: }
446:
447: return entries;
448: }
449: }
|