You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@roller.apache.org by ag...@apache.org on 2007/07/10 23:26:01 UTC

svn commit: r555084 - in /roller/trunk/apps/weblogger: src/java/org/apache/roller/weblogger/business/plugins/ src/java/org/apache/roller/weblogger/business/plugins/comment/ src/java/org/apache/roller/weblogger/business/startup/ src/java/org/apache/roll...

Author: agilliland
Date: Tue Jul 10 14:25:59 2007
New Revision: 555084

URL: http://svn.apache.org/viewvc?view=rev&rev=555084
Log:
introducing comment plugins to provide greater control and flexibility over how weblog comments are handled.  A number of things changed in this commit ...

1. Added new column 'plugins' to roller_comment table, varchar(255).

2. Added new attribute 'plugins' to WeblogEntryComment pojo, including mapping elements in jpa and hibernate mapping files.

3. Added new interface WeblogEntryCommentPlugin in business.plugins.comment package.  Interface has 1 method, render(comment) which returns a string of the transformed content.

5. Added 2 new comment plugins, AutoformatPlugin and HTMLSubsetPlugin, to replace old functionality.

6. Added 2 new methods to PluginManager and PluginManagerImpl. applyCommentPlugins(comment) which returns a string, and getCommentPlugins() which returns the list of plugins.

7. Added new property 'comments.plugins.classnames' in roller.properties which lists the configured comment plugin classes.

8. Added new runtime property 'users.comments.plugins' which is a comma separated list of the plugins which are enabled.

9. Modified CommentServlet to basically call comment.setPlugins(runtimeConfig.getProp('users.comments.plugins')). This basically applies whatever comment plugins are configured to the specific comment as it gets saved.

10. Modified Comment pojo wrapper so that the call to getContent() actually applies plugins and other transformations before returning output.

11. Unit test for AutoformatPlugin.

12. Add to the current upgrade process to set 'users.comments.plugins' global property and each individual comment.plugins property if existing autoformat or htmlsubset functionality was enabled.

13. Cleanup current comment macros and move logic out of macro and into pojo wrapper.

TODO: the last remaining item regarding this work is to polish up the global settings page and remove the old comment properties and provide a nicer UI for enabling/disabling comment plugins.

Added:
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/comment/
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/comment/AutoformatPlugin.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/comment/HTMLSubsetPlugin.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/comment/WeblogEntryCommentPlugin.java
    roller/trunk/apps/weblogger/test/java/org/apache/roller/weblogger/business/plugins/
    roller/trunk/apps/weblogger/test/java/org/apache/roller/weblogger/business/plugins/CommentPluginsTest.java
    roller/trunk/apps/weblogger/test/java/org/apache/roller/weblogger/business/plugins/PluginsTestSuite.java
    roller/trunk/apps/weblogger/test/java/org/apache/roller/weblogger/ui/UITestSuite.java
Modified:
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/PluginManager.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/PluginManagerImpl.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/startup/DatabaseInstaller.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/config/roller.properties
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/config/runtimeConfigDefs.xml
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/pojos/WeblogEntryComment.hbm.xml
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/pojos/WeblogEntryComment.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/pojos/WeblogEntryComment.orm.xml
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/pojos/wrapper/WeblogEntryCommentWrapper.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/ui/rendering/model/UtilitiesModel.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/ui/rendering/servlets/CommentServlet.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/util/Utilities.java
    roller/trunk/apps/weblogger/src/sql/310-to-400-migration.vm
    roller/trunk/apps/weblogger/src/sql/createdb.vm
    roller/trunk/apps/weblogger/test/java/org/apache/roller/weblogger/ui/rendering/util/CommentValidatorTest.java
    roller/trunk/apps/weblogger/web/WEB-INF/classes/ApplicationResources.properties
    roller/trunk/apps/weblogger/web/WEB-INF/velocity/weblog.vm

Modified: roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/PluginManager.java
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/PluginManager.java?view=diff&rev=555084&r1=555083&r2=555084
==============================================================================
--- roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/PluginManager.java (original)
+++ roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/PluginManager.java Tue Jul 10 14:25:59 2007
@@ -18,9 +18,12 @@
 
 package org.apache.roller.weblogger.business.plugins;
 
+import java.util.List;
 import java.util.Map;
+import org.apache.roller.weblogger.business.plugins.comment.WeblogEntryCommentPlugin;
 import org.apache.roller.weblogger.pojos.WeblogEntry;
 import org.apache.roller.weblogger.pojos.Weblog;
+import org.apache.roller.weblogger.pojos.WeblogEntryComment;
 
 
 /**
@@ -54,6 +57,26 @@
      * @return        the transformed text
      */
     public String applyWeblogEntryPlugins(Map pagePlugins,WeblogEntry entry, String str);
+    
+    
+    /**
+     * Get the list of WeblogEntryCommentPlugin classes configured.
+     *
+     * This lists the set of plugins which are available to the system, not the
+     * set of plugins which are enabled.
+     *
+     * Should return an empty list if no plugins are configured.
+     */
+    public List<WeblogEntryCommentPlugin> getCommentPlugins();
+    
+    
+    /**
+     * Apply comment plugins.
+     *
+     * @param comment The comment to apply plugins for.
+     * @return String The transformed comment text.
+     */
+    public String applyCommentPlugins(WeblogEntryComment comment);
     
     
     /**

Modified: roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/PluginManagerImpl.java
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/PluginManagerImpl.java?view=diff&rev=555084&r1=555083&r2=555084
==============================================================================
--- roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/PluginManagerImpl.java (original)
+++ roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/PluginManagerImpl.java Tue Jul 10 14:25:59 2007
@@ -18,7 +18,7 @@
 
 package org.apache.roller.weblogger.business.plugins;
 
-import org.apache.roller.weblogger.business.plugins.PluginManager;
+import java.util.ArrayList;
 import org.apache.roller.weblogger.business.plugins.entry.WeblogEntryPlugin;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
@@ -30,6 +30,8 @@
 import org.apache.roller.weblogger.pojos.WeblogEntry;
 import org.apache.roller.weblogger.pojos.Weblog;
 import org.apache.commons.lang.StringUtils;
+import org.apache.roller.weblogger.business.plugins.comment.WeblogEntryCommentPlugin;
+import org.apache.roller.weblogger.pojos.WeblogEntryComment;
 
 
 /**
@@ -42,12 +44,19 @@
     // Plugin classes keyed by plugin name
     static Map mPagePlugins = new LinkedHashMap();
     
+    // Comment plugins
+    private List<WeblogEntryCommentPlugin> commentPlugins = new ArrayList();
+    
     
     /**
      * Creates a new instance of PluginManagerImpl
      */
     public PluginManagerImpl() {
+        // load weblog entry plugins
         loadPagePluginClasses();
+        
+        // load weblog entry comment plugins
+        loadCommentPlugins();
     }
     
     
@@ -98,6 +107,39 @@
     
     
     /**
+     * @inheritDoc
+     */
+    public List<WeblogEntryCommentPlugin> getCommentPlugins() {
+        return commentPlugins;
+    }
+    
+    
+    /**
+     * @inheritDoc
+     */
+    public String applyCommentPlugins(WeblogEntryComment comment) {
+        
+        if(comment == null) {
+            throw new IllegalArgumentException("comment cannot be null");
+        }
+        
+        String content = comment.getContent();
+        
+        if (commentPlugins.size() > 0) {
+            for( WeblogEntryCommentPlugin plugin : commentPlugins ) {
+                if(comment.getPlugins() != null &&
+                        comment.getPlugins().indexOf(plugin.getName()) != -1) {
+                    log.debug("Invoking comment plugin "+plugin.getName());
+                    content = plugin.render(comment, content);
+                }
+            }
+        }
+        
+        return content;
+    }
+    
+    
+    /**
      * Initialize PagePlugins declared in roller.properties.
      * By using the full class name we also allow for the implementation of
      * "external" Plugins (maybe even packaged seperately). These classes are
@@ -130,6 +172,44 @@
                 }
             }
         }
+    }
+    
+    
+    /**
+     * Initialize all comment plugins defined in weblogger config.
+     */
+    private void loadCommentPlugins() {
+        
+        log.debug("Initializing comment plugins");
+        
+        String pluginStr = WebloggerConfig.getProperty("comment.formatter.classnames");
+        if (pluginStr != null) {
+            String[] plugins = StringUtils.stripAll(StringUtils.split(pluginStr, ","));
+            for (int i=0; i < plugins.length; i++) {
+                log.debug("trying " + plugins[i]);
+                
+                try {
+                    Class pluginClass = Class.forName(plugins[i]);
+                    WeblogEntryCommentPlugin plugin = 
+                            (WeblogEntryCommentPlugin) pluginClass.newInstance();
+                    
+                    // make sure and maintain ordering
+                    commentPlugins.add(i, plugin);
+                    
+                    log.debug("Configured comment plugin: "+plugins[i]);
+                    
+                } catch (ClassCastException e) {
+                    log.error("ClassCastException for " + plugins[i]);
+                } catch (ClassNotFoundException e) {
+                    log.error("ClassNotFoundException for " + plugins[i]);
+                } catch (InstantiationException e) {
+                    log.error("InstantiationException for " + plugins[i]);
+                } catch (IllegalAccessException e) {
+                    log.error("IllegalAccessException for " + plugins[i]);
+                }
+            }
+        }
+        
     }
     
     

Added: roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/comment/AutoformatPlugin.java
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/comment/AutoformatPlugin.java?view=auto&rev=555084
==============================================================================
--- roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/comment/AutoformatPlugin.java (added)
+++ roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/comment/AutoformatPlugin.java Tue Jul 10 14:25:59 2007
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.weblogger.business.plugins.comment;
+
+import java.io.BufferedReader;
+import java.io.StringReader;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.weblogger.pojos.WeblogEntryComment;
+
+
+/**
+ * Comment plugin which turns plain text paragraph formatting into html
+ * paragraph formatting using <p> and <br/> tags.
+ */
+public class AutoformatPlugin implements WeblogEntryCommentPlugin {
+    
+    private static final Log log = LogFactory.getLog(AutoformatPlugin.class);
+    
+    
+    public AutoformatPlugin() {
+        // no-op
+    }
+    
+    
+    public String getName() {
+        return "AutoFormat";
+    }
+    
+    
+    public String getDescription() {
+        return "Converts plain text style paragraphs into html paragraphs.";
+    }
+    
+    
+    public String render(final WeblogEntryComment comment, String text) {
+        
+        log.debug("starting value:\n"+text);
+        
+        /* 
+         * setup a buffered reader and iterate through each line
+         * inserting html as needed
+         *
+         * NOTE: we consider a paragraph to be 2 endlines with no text between them
+         */
+        StringBuffer buf = new StringBuffer();
+        try {
+            BufferedReader br = new BufferedReader(new StringReader(text));
+            
+            String line = null;
+            boolean insidePara = false;
+            while((line = br.readLine()) != null) {
+                
+                if(!insidePara && line.trim().length() > 0) {
+                    // start of a new paragraph
+                    buf.append("\n<p>");
+                    buf.append(line);
+                    insidePara = true;
+                } else if(insidePara && line.trim().length() > 0) {
+                    // another line in an existing paragraph
+                    buf.append("<br/>\n");
+                    buf.append(line);
+                } else if(insidePara && line.trim().length() < 1) {
+                    // end of a paragraph
+                    buf.append("</p>\n\n");
+                    insidePara = false;
+                }
+            }
+            
+            // if the text ends without an empty line then we need to
+            // terminate the last paragraph now
+            if(insidePara)
+                buf.append("</p>\n\n");
+            
+        } catch(Exception e) {
+            log.warn("trouble rendering text.", e);
+        }
+        
+        log.debug("ending value:\n"+buf.toString());
+        
+        return buf.toString();
+    }
+    
+}

Added: roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/comment/HTMLSubsetPlugin.java
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/comment/HTMLSubsetPlugin.java?view=auto&rev=555084
==============================================================================
--- roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/comment/HTMLSubsetPlugin.java (added)
+++ roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/comment/HTMLSubsetPlugin.java Tue Jul 10 14:25:59 2007
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.weblogger.business.plugins.comment;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.weblogger.pojos.WeblogEntryComment;
+import org.apache.roller.weblogger.util.Utilities;
+
+
+/**
+ * Transforms the given String into a subset of HTML.
+ */
+public class HTMLSubsetPlugin implements WeblogEntryCommentPlugin {
+    
+    private static final Log log = LogFactory.getLog(AutoformatPlugin.class);
+    
+    
+    public HTMLSubsetPlugin() {
+        // no-op
+    }
+    
+    
+    public String getName() {
+        return "HTMLSubset";
+    }
+    
+    
+    public String getDescription() {
+        return "Transforms the given comment body into a subset of HTML";
+    }
+    
+    
+    public String render(final WeblogEntryComment comment, String text) {
+        
+        log.debug("starting value:\n"+text);
+        
+        // just use old utilities method
+        String output = Utilities.transformToHTMLSubset(text);
+        
+        log.debug("ending value:\n"+output);
+        
+        return output;
+    }
+    
+}

Added: roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/comment/WeblogEntryCommentPlugin.java
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/comment/WeblogEntryCommentPlugin.java?view=auto&rev=555084
==============================================================================
--- roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/comment/WeblogEntryCommentPlugin.java (added)
+++ roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/plugins/comment/WeblogEntryCommentPlugin.java Tue Jul 10 14:25:59 2007
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.weblogger.business.plugins.comment;
+
+import org.apache.roller.weblogger.pojos.WeblogEntryComment;
+
+
+/**
+ * Interface for weblog entry comment plugins.
+ *
+ * Weblog entry comment plugins are used to make transformations to comment text.
+ */
+public interface WeblogEntryCommentPlugin {
+    
+    /**
+     * Returns the display name of this Plugin.
+     */
+    public String getName();
+    
+    
+    /**
+     * Briefly describes the function of the Plugin.  May contain HTML.
+     */
+    public String getDescription();
+    
+    
+    /**
+     * Apply plugin to the specified text.
+     *
+     * @param entry       Entry being rendered.
+     * @param str         String to which plugin should be applied.
+     * @return            Results of applying plugin to string.
+     */
+    public String render(final WeblogEntryComment comment, String str);
+    
+}

Modified: roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/startup/DatabaseInstaller.java
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/startup/DatabaseInstaller.java?view=diff&rev=555084&r1=555083&r2=555084
==============================================================================
--- roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/startup/DatabaseInstaller.java (original)
+++ roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/startup/DatabaseInstaller.java Tue Jul 10 14:25:59 2007
@@ -915,6 +915,115 @@
             throw new StartupException("Problem upgrading database to version 400", e);
         }
         
+        
+        // upgrade comments to use new plugin mechanism
+        try {
+            successMessage("Upgrading existing comments to use new comment plugins");
+            
+            // we are just going to set the 'plugins' value for comments to
+            // include 'AutoFormat' if it was configured previously
+            
+            // look in db and see if comment autoformatting is enabled
+            boolean autoformatEnabled = false;
+            String autoformat = null;
+            PreparedStatement selectIsAutoformtEnabled = con.prepareStatement(
+                "select value from roller_properties where name = 'users.comments.autoformat'");
+            ResultSet rs = selectIsAutoformtEnabled.executeQuery();
+            if (rs.next()) {
+                autoformat = rs.getString(1);
+                if(autoformat != null && "true".equals(autoformat)) {
+                    autoformatEnabled = true;
+                }
+            }
+            
+            // look in db and see if comment html escaping is enabled
+            boolean htmlsubsetEnabled = false;
+            String escapehtml = null;
+            PreparedStatement selectIsEscapehtmlEnabled = con.prepareStatement(
+                "select value from roller_properties where name = 'users.comments.escapehtml'");
+            ResultSet rs1 = selectIsEscapehtmlEnabled.executeQuery();
+            if (rs1.next()) {
+                escapehtml = rs1.getString(1);
+                // NOTE: we enforce an html subset only when html escaping is OFF
+                if(escapehtml != null && !"true".equals(escapehtml)) {
+                    htmlsubsetEnabled = true;
+                }
+            }
+            
+            // now update existing comments with necessary plugins
+            if(htmlsubsetEnabled && autoformatEnabled) {
+                
+                // set new global config property for enabled coment plugins
+                PreparedStatement addCommentPluginsProp = con.prepareStatement(
+                        "insert into roller_properties(name,value) values(?,?)");
+                addCommentPluginsProp.clearParameters();
+                addCommentPluginsProp.setString( 1, "users.comments.plugins");
+                addCommentPluginsProp.setString( 2, "HTMLSubset, AutoFormat");
+                addCommentPluginsProp.executeUpdate();
+                
+                // update existing comments
+                PreparedStatement updateComments = con.prepareStatement(
+                        "update roller_comment set plugins = ?");
+                updateComments.clearParameters();
+                updateComments.setString( 1, "HTMLSubset, AutoFormat");
+                updateComments.executeUpdate();
+                
+            } else if(autoformatEnabled) {
+                
+                // set new global config property for enabled coment plugins
+                PreparedStatement addCommentPluginsProp = con.prepareStatement(
+                        "insert into roller_properties(name,value) values(?,?)");
+                addCommentPluginsProp.clearParameters();
+                addCommentPluginsProp.setString( 1, "users.comments.plugins");
+                addCommentPluginsProp.setString( 2, "AutoFormat");
+                addCommentPluginsProp.executeUpdate();
+                
+                // update existing comments
+                PreparedStatement updateComments = con.prepareStatement(
+                        "update roller_comment set plugins = ?");
+                updateComments.clearParameters();
+                updateComments.setString( 1, "AutoFormat");
+                updateComments.executeUpdate();
+                
+            } else if(htmlsubsetEnabled) {
+                
+                // set new global config property for enabled coment plugins
+                PreparedStatement addCommentPluginsProp = con.prepareStatement(
+                        "insert into roller_properties(name,value) values(?,?)");
+                addCommentPluginsProp.clearParameters();
+                addCommentPluginsProp.setString( 1, "users.comments.plugins");
+                addCommentPluginsProp.setString( 2, "HTMLSubset");
+                addCommentPluginsProp.executeUpdate();
+                
+                // update existing comments
+                PreparedStatement updateComments = con.prepareStatement(
+                        "update roller_comment set plugins = ?");
+                updateComments.clearParameters();
+                updateComments.setString( 1, "HTMLSubset");
+                updateComments.executeUpdate();
+                
+            } else {
+                
+                // set new global config property for enabled coment plugins
+                PreparedStatement addCommentPluginsProp = con.prepareStatement(
+                        "insert into roller_properties(name,value) values(?,?)");
+                addCommentPluginsProp.clearParameters();
+                addCommentPluginsProp.setString( 1, "users.comments.plugins");
+                addCommentPluginsProp.setString( 2, "");
+                addCommentPluginsProp.executeUpdate();
+                
+                // no need to update existing comments because plugins aren't enabled
+            }
+            
+            if (!con.getAutoCommit()) con.commit();
+           
+            successMessage("Comments successfully updated to use new comment plugins.");
+            
+        } catch (Exception e) {
+            errorMessage("Problem upgrading database to version 400", e);
+            throw new StartupException("Problem upgrading database to version 400", e);
+        }
+        
         // finally, upgrade db version string to 400
         updateDatabaseVersion(con, 400);
     }

Modified: roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/config/roller.properties
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/config/roller.properties?view=diff&rev=555084&r1=555083&r2=555084
==============================================================================
--- roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/config/roller.properties (original)
+++ roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/config/roller.properties Tue Jul 10 14:25:59 2007
@@ -164,6 +164,10 @@
 comment.validator.excessSize.threshold=1000
 #comment.validator.akismet.key=<get one at wordpress.com>
 
+# pluggable comment formatters
+comment.formatter.classnames=\
+org.apache.roller.weblogger.business.plugins.comment.AutoformatPlugin
+
 # enables site full blacklist check on comment posts (default: true)
 site.blacklist.enable.comments=true
 

Modified: roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/config/runtimeConfigDefs.xml
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/config/runtimeConfigDefs.xml?view=diff&rev=555084&r1=555083&r2=555084
==============================================================================
--- roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/config/runtimeConfigDefs.xml (original)
+++ roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/config/runtimeConfigDefs.xml Tue Jul 10 14:25:59 2007
@@ -154,6 +154,10 @@
          <type>boolean</type>
          <default-value>true</default-value>
       </property-def>
+      <property-def  name="users.comments.plugins"  key="configForm.commentPlugins">
+         <type>string</type>
+         <default-value></default-value>
+      </property-def>
       <property-def  name="users.comments.autoformat"  key="configForm.autoformatComments">
          <type>boolean</type>
          <default-value>true</default-value>

Modified: roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/pojos/WeblogEntryComment.hbm.xml
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/pojos/WeblogEntryComment.hbm.xml?view=diff&rev=555084&r1=555083&r2=555084
==============================================================================
--- roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/pojos/WeblogEntryComment.hbm.xml (original)
+++ roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/pojos/WeblogEntryComment.hbm.xml Tue Jul 10 14:25:59 2007
@@ -127,6 +127,15 @@
             column="useragent"
             unique="false"
         />
+        
+        <property
+            name="plugins"
+            type="java.lang.String"
+            update="true"
+            insert="true"
+            column="plugins"
+            unique="false"
+        />
 
         <!--
             To add non XDoclet property mappings, create a file named

Modified: roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/pojos/WeblogEntryComment.java
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/pojos/WeblogEntryComment.java?view=diff&rev=555084&r1=555083&r2=555084
==============================================================================
--- roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/pojos/WeblogEntryComment.java (original)
+++ roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/pojos/WeblogEntryComment.java Tue Jul 10 14:25:59 2007
@@ -50,6 +50,7 @@
     private String    remoteHost = null;
     private String    referrer = null;
     private String    userAgent = null;
+    private String    plugins = null;
     
     // associations
     private WeblogEntry weblogEntry = null;
@@ -72,11 +73,9 @@
         this.id = id;
     }
     
+    
     /**
-     * Weblog entry assocaited with comment
-     * @roller.wrapPojoMethod type="pojo"
-     * @ejb:persistent-field
-     * @hibernate.many-to-one column="entryid" cascade="none" not-null="true"
+     * Weblog entry associated with comment.
      */
     public WeblogEntry getWeblogEntry() {
         return weblogEntry;
@@ -84,17 +83,14 @@
     
     /**
      * Weblog entry assocaited with comment
-     * @ejb:persistent-field
      */
     public void setWeblogEntry(WeblogEntry entry) {
         weblogEntry = entry;
     }
     
+    
     /**
      * Name of person who wrote comment.
-     * @roller.wrapPojoMethod type="simple"
-     * @ejb:persistent-field
-     * @hibernate.property column="name" non-null="true" unique="false"
      */
     public String getName() {
         return this.name;
@@ -102,17 +98,14 @@
     
     /**
      * Name of person who wrote comment.
-     * @ejb:persistent-field
      */
     public void setName(String name) {
         this.name = name;
     }
     
+    
     /**
      * Email of person who wrote comment.
-     * @roller.wrapPojoMethod type="simple"
-     * @ejb:persistent-field
-     * @hibernate.property column="email" non-null="true" unique="false"
      */
     public String getEmail() {
         return this.email;
@@ -120,17 +113,14 @@
     
     /**
      * Email of person who wrote comment.
-     * @ejb:persistent-field
      */
     public void setEmail(String email) {
         this.email = email;
     }
     
+    
     /**
      * URL of person who wrote comment.
-     * @roller.wrapPojoMethod type="simple"
-     * @ejb:persistent-field
-     * @hibernate.property column="url" non-null="true" unique="false"
      */
     public String getUrl() {
         return this.url;
@@ -138,17 +128,14 @@
     
     /**
      * URL of person who wrote comment.
-     * @ejb:persistent-field
      */
     public void setUrl(String url) {
         this.url = url;
     }
     
+    
     /**
      * Content of comment.
-     * @roller.wrapPojoMethod type="simple"
-     * @ejb:persistent-field
-     * @hibernate.property column="content" non-null="true" unique="false"
      */
     public String getContent() {
         return this.content;
@@ -156,36 +143,29 @@
     
     /**
      * Content of comment.
-     * @ejb:persistent-field
      */
     public void setContent(String content) {
         this.content = content;
     }
     
+    
     /**
      * Time that comment was posted.
-     * @roller.wrapPojoMethod type="simple"
-     * @ejb:persistent-field
-     * @hibernate.property column="posttime" non-null="true" unique="false"
      */
-    public java.sql.Timestamp getPostTime() {
+    public Timestamp getPostTime() {
         return this.postTime;
     }
     
     /**
      * Time that comment was posted.
-     * @ejb:persistent-field
      */
-    public void setPostTime(java.sql.Timestamp postTime) {
+    public void setPostTime(Timestamp postTime) {
         this.postTime = postTime;
     }
     
+    
     /**
      * Status of the comment, i.e. APPROVED, SPAM, PENDING, etc.
-     *
-     * @roller.wrapPojoMethod type="simple"
-     * @ejb:persistent-field
-     * @hibernate.property column="status" non-null="true" unique="false"
      */
     public String getStatus() {
         return status;
@@ -198,12 +178,10 @@
         this.status = status;
     }
     
+    
     /**
      * True if person who wrote comment wishes to be notified of new comments
      * on the same weblog entry.
-     * @roller.wrapPojoMethod type="simple"
-     * @ejb:persistent-field
-     * @hibernate.property column="notify" non-null="false" unique="false"
      */
     public Boolean getNotify() {
         return this.notify;
@@ -212,17 +190,14 @@
     /**
      * True if person who wrote comment wishes to be notified of new comments
      * on the same weblog entry.
-     * @ejb:persistent-field
      */
     public void setNotify(Boolean notify) {
         this.notify = notify;
     }
     
+    
     /**
      * Host name or IP of person who wrote comment.
-     * @roller.wrapPojoMethod type="simple"
-     * @ejb:persistent-field
-     * @hibernate.property column="remotehost" non-null="true" unique="false"
      */
     public String getRemoteHost() {
         return this.remoteHost;
@@ -230,17 +205,14 @@
     
     /**
      * Host name or IP of person who wrote comment.
-     * @ejb:persistent-field
      */
     public void setRemoteHost(String remoteHost) {
         this.remoteHost = remoteHost;
     }
     
+    
     /**
      * HTTP referrer from comment post request
-     * @roller.wrapPojoMethod type="simple"
-     * @ejb:persistent-field
-     * @hibernate.property column="referrer" non-null="true" unique="false"
      */
     public String getReferrer() {
         return referrer;
@@ -248,17 +220,14 @@
     
     /**
      * HTTP referrer from comment post request
-     * @ejb:persistent-field
      */
     public void setReferrer(String referrer) {
         this.referrer = referrer;
     }
     
+    
     /**
      * HTTP user-agent from comment post request
-     * @roller.wrapPojoMethod type="simple"
-     * @ejb:persistent-field
-     * @hibernate.property column="useragent" non-null="true" unique="false"
      */
     public String getUserAgent() {
         return userAgent;
@@ -266,43 +235,53 @@
     
     /**
      * HTTP user-agent from comment post request
-     * @ejb:persistent-field
      */
     public void setUserAgent(String userAgent) {
         this.userAgent = userAgent;
     }
     
+    
+    /**
+     * Comma separated list of comment plugins to apply.
+     */
+    public String getPlugins() {
+        return plugins;
+    }
+    
+    /**
+     * Comma separated list of comment plugins to apply.
+     */
+    public void setPlugins(String plugins) {
+        this.plugins = plugins;
+    }
+    
+    
     /**
      * Indicates that weblog owner considers this comment to be spam.
-     *
-     * @roller.wrapPojoMethod type="simple"
      */
     public Boolean getSpam() {
         return new Boolean(SPAM.equals(this.status));
     }
     
+    
     /**
      * True if comment has is pending moderator approval.
-     *
-     * @roller.wrapPojoMethod type="simple"
      */
     public Boolean getPending() {
         return new Boolean(PENDING.equals(this.status));
     }
     
+    
     /**
      * Indicates that comment has been approved for display on weblog.
-     *
-     * @roller.wrapPojoMethod type="simple"
      */
     public Boolean getApproved() {
         return new Boolean(APPROVED.equals(this.status));
     }
     
+    
     /**
      * Timestamp to be used to formulate comment permlink.
-     *
-     * @roller.wrapPojoMethod type="simple"
      */
     public String getTimestamp() {
         if (postTime != null) {

Modified: roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/pojos/WeblogEntryComment.orm.xml
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/pojos/WeblogEntryComment.orm.xml?view=diff&rev=555084&r1=555083&r2=555084
==============================================================================
--- roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/pojos/WeblogEntryComment.orm.xml (original)
+++ roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/pojos/WeblogEntryComment.orm.xml Tue Jul 10 14:25:59 2007
@@ -96,6 +96,9 @@
             <basic name="userAgent">
                 <column name="useragent" insertable="true" updatable="true" unique="false"/>
             </basic>
+            <basic name="plugins">
+                <column name="plugins" insertable="true" updatable="true" unique="false"/>
+            </basic>
             <many-to-one name="weblogEntry" target-entity="org.apache.roller.weblogger.pojos.WeblogEntry">
                 <join-column name="entryid" insertable="true" updatable="true" nullable="false"/>
             </many-to-one>

Modified: roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/pojos/wrapper/WeblogEntryCommentWrapper.java
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/pojos/wrapper/WeblogEntryCommentWrapper.java?view=diff&rev=555084&r1=555083&r2=555084
==============================================================================
--- roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/pojos/wrapper/WeblogEntryCommentWrapper.java (original)
+++ roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/pojos/wrapper/WeblogEntryCommentWrapper.java Tue Jul 10 14:25:59 2007
@@ -18,9 +18,13 @@
 
 package org.apache.roller.weblogger.pojos.wrapper;
 
+import java.sql.Timestamp;
 import org.apache.commons.lang.StringEscapeUtils;
 import org.apache.roller.weblogger.business.URLStrategy;
+import org.apache.roller.weblogger.business.WebloggerFactory;
+import org.apache.roller.weblogger.business.plugins.PluginManager;
 import org.apache.roller.weblogger.pojos.WeblogEntryComment;
+import org.apache.roller.weblogger.util.Utilities;
 
 
 /**
@@ -61,27 +65,67 @@
     }
     
     
+    /**
+     * Get the name of the comment writer.
+     *
+     * Value is always html escaped.
+     */
     public String getName() {
         return StringEscapeUtils.escapeHtml(this.pojo.getName());
     }
     
     
+    /**
+     * Get the email address of the comment writer, if specified.
+     *
+     * Value is always html escaped.
+     */
     public String getEmail() {
         return StringEscapeUtils.escapeHtml(this.pojo.getEmail());
     }
     
     
+    /**
+     * Get the url of the comment writer, if specified.
+     *
+     * Value is always html escaped.
+     */
     public String getUrl() {
         return StringEscapeUtils.escapeHtml(this.pojo.getUrl());
     }
     
     
+    /**
+     * Get the comment contents.
+     *
+     * Any configured comment plugins are applied first, then the value is 
+     * always html escaped.
+     */
     public String getContent() {
-        return StringEscapeUtils.escapeHtml(this.pojo.getContent());
+        
+        String content = this.pojo.getContent();
+        
+        // encode email
+        content = Utilities.encodeEmail(content);
+        
+        // escape html
+        content = StringEscapeUtils.escapeHtml(content);
+        
+        // apply plugins for transformation
+        PluginManager pmgr = WebloggerFactory.getWeblogger().getPagePluginManager();
+        content = pmgr.applyCommentPlugins(this.pojo);
+        
+        // always add rel=nofollow for links
+        content = Utilities.addNofollow(content);
+        
+        return content;
     }
     
     
-    public java.sql.Timestamp getPostTime() {
+    /**
+     * Get the time the comment was posted.
+     */
+    public Timestamp getPostTime() {
         return this.pojo.getPostTime();
     }
     
@@ -101,6 +145,11 @@
     }
     
     
+    /**
+     * Get the http referrer of the comment poster, used for trackbacks.
+     *
+     * Value is always html escaped.
+     */
     public String getReferrer() {
         return StringEscapeUtils.escapeHtml(this.pojo.getReferrer());
     }

Modified: roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/ui/rendering/model/UtilitiesModel.java
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/ui/rendering/model/UtilitiesModel.java?view=diff&rev=555084&r1=555083&r2=555084
==============================================================================
--- roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/ui/rendering/model/UtilitiesModel.java (original)
+++ roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/ui/rendering/model/UtilitiesModel.java Tue Jul 10 14:25:59 2007
@@ -355,27 +355,7 @@
      * Code (stolen from Pebble) to add rel="nofollow" string to all links in HTML.
      */
     public String addNofollow(String html) {
-        if (html == null || html.length() == 0) {
-            return html;
-        }
-        Matcher m = mLinkPattern.matcher(html);
-        StringBuffer buf = new StringBuffer();
-        while (m.find()) {
-            int start = m.start();
-            int end = m.end();
-            String link = html.substring(start, end);
-            buf.append(html.substring(0, start));
-            if (link.indexOf("rel=\"nofollow\"") == -1) {
-                buf.append(
-                        link.substring(0, link.length() - 1) + " rel=\"nofollow\">");
-            } else {
-                buf.append(link);
-            }
-            html = html.substring(end, html.length());
-            m = mLinkPattern.matcher(html);
-        }
-        buf.append(html);
-        return buf.toString();
+        return Utilities.addNofollow(html);
     }
     
     /**

Modified: roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/ui/rendering/servlets/CommentServlet.java
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/ui/rendering/servlets/CommentServlet.java?view=diff&rev=555084&r1=555083&r2=555084
==============================================================================
--- roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/ui/rendering/servlets/CommentServlet.java (original)
+++ roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/ui/rendering/servlets/CommentServlet.java Tue Jul 10 14:25:59 2007
@@ -20,6 +20,7 @@
 
 import java.io.IOException;
 import java.sql.Timestamp;
+import java.util.Iterator;
 import javax.servlet.RequestDispatcher;
 import javax.servlet.ServletConfig;
 import javax.servlet.ServletException;
@@ -48,7 +49,9 @@
 import org.apache.roller.weblogger.util.MailUtil;
 import org.apache.roller.weblogger.util.I18nMessages;
 import org.apache.roller.weblogger.util.RollerMessages;
+import org.apache.roller.weblogger.util.RollerMessages.RollerMessage;
 import org.apache.roller.weblogger.util.URLUtilities;
+import org.apache.roller.weblogger.util.Utilities;
 import org.apache.roller.weblogger.util.cache.CacheManager;
 
 
@@ -82,20 +85,22 @@
         
         log.info("Initializing CommentServlet");
         
-        commentValidationManager = new CommentValidationManager();
-        
         // lookup the authenticator we are going to use and instantiate it
         try {
             String name = WebloggerConfig.getProperty("comment.authenticator.classname");
-            
             Class clazz = Class.forName(name);
             this.authenticator = (CommentAuthenticator) clazz.newInstance();
-            
         } catch(Exception e) {
             log.error(e);
             this.authenticator = new DefaultCommentAuthenticator();
         }
         
+        // instantiate a comment validation manager for comment spam checking
+        commentValidationManager = new CommentValidationManager();
+        
+        // instantiate a comment format manager for comment formatting
+        String fmtrs = WebloggerConfig.getProperty("comment.formatter.classnames");
+        String[] formatters = Utilities.stringToStringArray(fmtrs, ",");
         
         // are we doing throttling?
         if(WebloggerConfig.getBooleanProperty("comment.throttle.enabled")) {
@@ -232,6 +237,9 @@
         comment.setRemoteHost(request.getRemoteHost());
         comment.setPostTime(new Timestamp(System.currentTimeMillis()));
         
+        // set whatever comment plugins are configured
+        comment.setPlugins(WebloggerRuntimeConfig.getProperty("users.comments.plugins"));
+        
         WeblogEntryCommentForm cf = new WeblogEntryCommentForm();
         cf.setData(comment);
         if (preview) {
@@ -272,11 +280,36 @@
             } else if (validationScore == 100) {
                 // else they're approved
                 comment.setStatus(WeblogEntryComment.APPROVED);
+                message = messageUtils.getString("commentServlet.commentAccepted");
             } else {
                 // Invalid comments are marked as spam
+                log.debug("Comment marked as spam");
                 comment.setStatus(WeblogEntryComment.SPAM);
                 error = messageUtils.getString("commentServlet.commentMarkedAsSpam");
-                log.debug("Comment marked as spam");
+                
+                // add specific error messages if they exist
+                if(messages.getErrorCount() > 0) {
+                    Iterator errors = messages.getErrors();
+                    RollerMessage errorKey = null;
+                    
+                    StringBuffer buf = new StringBuffer();
+                    buf.append("<ul>");
+                    while(errors.hasNext()) {
+                        errorKey = (RollerMessage)errors.next();
+                        
+                        buf.append("<li>");
+                        if(errorKey.getArgs() != null) {
+                            buf.append(messageUtils.getString(errorKey.getKey(), errorKey.getArgs()));
+                        } else {
+                            buf.append(messageUtils.getString(errorKey.getKey()));
+                        }
+                        buf.append("</li>");
+                    }
+                    buf.append("</ul>");
+                    
+                    error += buf.toString();
+                }
+                
             }
             
             try {               

Modified: roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/util/Utilities.java
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/util/Utilities.java?view=diff&rev=555084&r1=555083&r2=555084
==============================================================================
--- roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/util/Utilities.java (original)
+++ roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/util/Utilities.java Tue Jul 10 14:25:59 2007
@@ -203,7 +203,36 @@
         String ret = StringUtils.replace(s, "\n", "<br />");
         return ret;
     }
-        
+    
+    
+    /**
+     * Code (stolen from Pebble) to add rel="nofollow" string to all links in HTML.
+     */
+    public static String addNofollow(String html) {
+        if (html == null || html.length() == 0) {
+            return html;
+        }
+        Matcher m = mLinkPattern.matcher(html);
+        StringBuffer buf = new StringBuffer();
+        while (m.find()) {
+            int start = m.start();
+            int end = m.end();
+            String link = html.substring(start, end);
+            buf.append(html.substring(0, start));
+            if (link.indexOf("rel=\"nofollow\"") == -1) {
+                buf.append(
+                        link.substring(0, link.length() - 1) + " rel=\"nofollow\">");
+            } else {
+                buf.append(link);
+            }
+            html = html.substring(end, html.length());
+            m = mLinkPattern.matcher(html);
+        }
+        buf.append(html);
+        return buf.toString();
+    }
+    
+    
     //------------------------------------------------------------------------
     /**
      * Replaces occurences of non-alphanumeric characters with an underscore.

Modified: roller/trunk/apps/weblogger/src/sql/310-to-400-migration.vm
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/sql/310-to-400-migration.vm?view=diff&rev=555084&r1=555083&r2=555084
==============================================================================
--- roller/trunk/apps/weblogger/src/sql/310-to-400-migration.vm (original)
+++ roller/trunk/apps/weblogger/src/sql/310-to-400-migration.vm Tue Jul 10 14:25:59 2007
@@ -57,6 +57,9 @@
 #addColumnNull("roller_comment" "referrer" "varchar(255)")
 #addColumnNull("roller_comment" "useragent" "varchar(255)")
 
+-- add new field to support comment plugins
+#addColumnNull("roller_comment" "plugins" "varchar(255)")
+
 -- add new status field to comment table to simplify queries
 #addColumnNotNull("roller_comment" "status" "varchar(20)" "'APPROVED'")
 

Modified: roller/trunk/apps/weblogger/src/sql/createdb.vm
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/sql/createdb.vm?view=diff&rev=555084&r1=555083&r2=555084
==============================================================================
--- roller/trunk/apps/weblogger/src/sql/createdb.vm (original)
+++ roller/trunk/apps/weblogger/src/sql/createdb.vm Tue Jul 10 14:25:59 2007
@@ -266,14 +266,12 @@
     url        varchar(255),
     content    $db.TEXT_SQL_TYPE,
     posttime   $db.TIMESTAMP_SQL_TYPE   not null,
-    spam       $db.BOOLEAN_SQL_TYPE_FALSE not null,
     notify     $db.BOOLEAN_SQL_TYPE_FALSE not null,
     remotehost varchar(128),
-    pending    $db.BOOLEAN_SQL_TYPE_TRUE not null,
-    approved   $db.BOOLEAN_SQL_TYPE_FALSE not null,
     referrer   varchar(255),
     useragent  varchar(255),
-    status     varchar(20) not null
+    status     varchar(20) not null,
+    plugins    varchar(255)
 );
 create index co_entryid_idx on roller_comment( entryid );
 create index co_status_idx on roller_comment( status );

Added: roller/trunk/apps/weblogger/test/java/org/apache/roller/weblogger/business/plugins/CommentPluginsTest.java
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/test/java/org/apache/roller/weblogger/business/plugins/CommentPluginsTest.java?view=auto&rev=555084
==============================================================================
--- roller/trunk/apps/weblogger/test/java/org/apache/roller/weblogger/business/plugins/CommentPluginsTest.java (added)
+++ roller/trunk/apps/weblogger/test/java/org/apache/roller/weblogger/business/plugins/CommentPluginsTest.java Tue Jul 10 14:25:59 2007
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.weblogger.business.plugins;
+
+import junit.framework.TestCase;
+import org.apache.roller.weblogger.TestUtils;
+import org.apache.roller.weblogger.business.WebloggerFactory;
+import org.apache.roller.weblogger.pojos.WeblogEntryComment;
+
+
+/**
+ * Test comment plugins.
+ */
+public class CommentPluginsTest extends TestCase {
+
+    private String convertLinesStart = "paragraph1\n\nparagraph2\nline2\nline3\n\nparagraph3";
+    private String convertLinesFormatted = "\n<p>paragraph1</p>\n\n\n<p>paragraph2<br/>\nline2<br/>\nline3</p>\n\n\n<p>paragraph3</p>\n\n";
+    
+    
+    protected void setUp() throws Exception {
+        TestUtils.setupWeblogger();
+    }
+    
+    protected void tearDown() throws Exception {
+        // no-op
+    }
+    
+    
+    public void testAutoFormatPlugin() {
+        
+        PluginManager pmgr = WebloggerFactory.getWeblogger().getPagePluginManager();
+        
+        // setup test comment
+        WeblogEntryComment comment = new WeblogEntryComment();
+        comment.setContent(convertLinesStart); 
+        comment.setPlugins("AutoFormat Plugin");
+        
+        // reformat
+        String output = pmgr.applyCommentPlugins(comment);
+        
+        // make sure it turned out how we planned
+        assertEquals(convertLinesFormatted, output);        
+    }
+    
+}

Added: roller/trunk/apps/weblogger/test/java/org/apache/roller/weblogger/business/plugins/PluginsTestSuite.java
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/test/java/org/apache/roller/weblogger/business/plugins/PluginsTestSuite.java?view=auto&rev=555084
==============================================================================
--- roller/trunk/apps/weblogger/test/java/org/apache/roller/weblogger/business/plugins/PluginsTestSuite.java (added)
+++ roller/trunk/apps/weblogger/test/java/org/apache/roller/weblogger/business/plugins/PluginsTestSuite.java Tue Jul 10 14:25:59 2007
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.weblogger.business.plugins;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.apache.roller.weblogger.business.plugins.CommentPluginsTest;
+
+
+/**
+ * Test Plugins.
+ */
+public class PluginsTestSuite {
+    
+    public static Test suite() {
+
+        TestSuite suite = new TestSuite();
+	
+        // comment plugins
+        suite.addTestSuite(CommentPluginsTest.class);
+
+        return suite;
+    }
+    
+}

Added: roller/trunk/apps/weblogger/test/java/org/apache/roller/weblogger/ui/UITestSuite.java
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/test/java/org/apache/roller/weblogger/ui/UITestSuite.java?view=auto&rev=555084
==============================================================================
--- roller/trunk/apps/weblogger/test/java/org/apache/roller/weblogger/ui/UITestSuite.java (added)
+++ roller/trunk/apps/weblogger/test/java/org/apache/roller/weblogger/ui/UITestSuite.java Tue Jul 10 14:25:59 2007
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.weblogger.ui;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.apache.roller.weblogger.ui.rendering.util.CommentValidatorTest;
+
+
+/**
+ * Test UI.
+ */
+public class UITestSuite {
+    
+    public static Test suite() {
+
+        TestSuite suite = new TestSuite();
+	
+        // comment plugins
+        suite.addTestSuite(CommentValidatorTest.class);
+
+        return suite;
+    }
+    
+}

Modified: roller/trunk/apps/weblogger/test/java/org/apache/roller/weblogger/ui/rendering/util/CommentValidatorTest.java
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/test/java/org/apache/roller/weblogger/ui/rendering/util/CommentValidatorTest.java?view=diff&rev=555084&r1=555083&r2=555084
==============================================================================
--- roller/trunk/apps/weblogger/test/java/org/apache/roller/weblogger/ui/rendering/util/CommentValidatorTest.java (original)
+++ roller/trunk/apps/weblogger/test/java/org/apache/roller/weblogger/ui/rendering/util/CommentValidatorTest.java Tue Jul 10 14:25:59 2007
@@ -43,6 +43,9 @@
     } 
 
     protected void setUp() throws Exception {
+        // setup weblogger
+        TestUtils.setupWeblogger();
+        
         mgr = new CommentValidationManager();
         
         user = TestUtils.setupUser("johndoe");

Modified: roller/trunk/apps/weblogger/web/WEB-INF/classes/ApplicationResources.properties
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/web/WEB-INF/classes/ApplicationResources.properties?view=diff&rev=555084&r1=555083&r2=555084
==============================================================================
--- roller/trunk/apps/weblogger/web/WEB-INF/classes/ApplicationResources.properties (original)
+++ roller/trunk/apps/weblogger/web/WEB-INF/classes/ApplicationResources.properties Tue Jul 10 14:25:59 2007
@@ -326,6 +326,7 @@
 
 # -------------------------------------------------------------- CommentServlet
 
+commentServlet.commentAccepted=Your comment has been accepted.
 commentServlet.commentMarkedAsSpam=Your comment was marked as spam and will not be displayed.
 commentServlet.previewMarkedAsSpam=If you submit this comment, it will be marked as spam and not displayed.
 commentServlet.submittedToModerator=Your comment has been submitted to the moderator for approval.

Modified: roller/trunk/apps/weblogger/web/WEB-INF/velocity/weblog.vm
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/web/WEB-INF/velocity/weblog.vm?view=diff&rev=555084&r1=555083&r2=555084
==============================================================================
--- roller/trunk/apps/weblogger/web/WEB-INF/velocity/weblog.vm (original)
+++ roller/trunk/apps/weblogger/web/WEB-INF/velocity/weblog.vm Tue Jul 10 14:25:59 2007
@@ -179,19 +179,10 @@
     <br/>
     #foreach( $comment in $comments )
         #if($comment.approved || $model.commentForm.preview)
-            #if($config.commentEscapeHtml)
-                #set($content = $comment.content))
-            #else 
-                #set($content = $utils.transformToHTMLSubset($comment.content))
-            #end
-            #if($config.commentAutoFormat)
-                #set($content = $utils.autoformat($content))
-            #end
-            #set($content = $utils.addNofollow($content))
-
             <a name="comment-$comment.timestamp" id="comment-$comment.timestamp"></a>
             <div class="comment#if($velocityCount % 2 == 0) even#else odd#end" id="comment${velocityCount}">
-                ${content}
+
+                $comment.content
 
                 <p class="comment-details">
                 $text.get("macro.weblog.postedby")