[jboss-svn-commits] JBL Code SVN: r5320 - in labs/shotoku/trunk: shotoku-base/src/java/org/jboss/shotoku shotoku-base/src/java/org/jboss/shotoku/tools shotoku-feeds/src/java/org/jboss/shotoku/feeds shotoku-feeds/src/java/org/jboss/shotoku/feeds/comments shotoku-feeds/src/java/org/jboss/shotoku/feeds/data shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special shotoku-feeds/src/java/org/jboss/shotoku/feeds/service shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag shotoku-feeds/src/java/org/jboss/shotoku/feeds/tools shotoku-tags/src/etc/META-INF shotoku-tags/src/java/org/jboss/shotoku/tags/service

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Thu Jul 27 15:54:47 EDT 2006


Author: adamw
Date: 2006-07-27 15:54:34 -0400 (Thu, 27 Jul 2006)
New Revision: 5320

Added:
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/CommentsService.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special/
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special/CommentFeed.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special/ConcreteCommentFeed.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special/ConcreteTagFeed.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special/Rss2CommentFeed.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special/Rss2TagFeed.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special/SpecialFeed.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special/TagFeed.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/service/CommentsServiceImpl.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/service/CommentsServiceLocal.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/CommentFeedTagHandler.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tools/FeedDefAttributes.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tools/NodesFeedsProperties.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tools/VelocityContextAttributes.java
Removed:
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/ConcreteTagFeed.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/Rss2TagFeed.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/SpecialFeed.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/TagFeed.java
Modified:
   labs/shotoku/trunk/shotoku-base/src/java/org/jboss/shotoku/NodeList.java
   labs/shotoku/trunk/shotoku-base/src/java/org/jboss/shotoku/tools/Tools.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/FeedFactory.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/FeedsDescriptor.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/FeedsService.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/comments/CommentsServlet.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/service/FeedsServiceImpl.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/AggregatedFeedTagHandler.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/FeedTagHandler.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/FeedTagHandlerManager.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/RemoteFeedTagHandler.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/ShotokuFeedTagHandler.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/TagFeedTagHandler.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tools/FeedsConstants.java
   labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tools/FeedsTools.java
   labs/shotoku/trunk/shotoku-tags/src/etc/META-INF/persistence.xml
   labs/shotoku/trunk/shotoku-tags/src/java/org/jboss/shotoku/tags/service/TagServiceImpl.java
Log:
http://jira.jboss.org/jira/browse/JBSHOTOKU-38

Modified: labs/shotoku/trunk/shotoku-base/src/java/org/jboss/shotoku/NodeList.java
===================================================================
--- labs/shotoku/trunk/shotoku-base/src/java/org/jboss/shotoku/NodeList.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-base/src/java/org/jboss/shotoku/NodeList.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -96,8 +96,17 @@
 			nodeList = nodeList.subList(0, limit);
 		}
 	}
-	
-	/*
+
+    /**
+     * Gets the i-th element of the list.
+     * @param i Index of the element to get.
+     * @return Node at the given index.
+     */
+    public Node get(int i) {
+        return nodeList.get(i);
+    }
+
+    /*
 	 * Implementation of the Collection interface methods.
 	 */
 
@@ -114,7 +123,8 @@
 	}
 
 	public boolean contains(Object o) {
-		return nodeList.contains(o);
+        //noinspection SuspiciousMethodCalls
+        return nodeList.contains(o);
 	}
 
 	public Object[] toArray() {
@@ -126,7 +136,8 @@
 	}
 
 	public boolean remove(Object o) {
-		return nodeList.remove(o);
+        //noinspection SuspiciousMethodCalls
+        return nodeList.remove(o);
 	}
 
 	public boolean containsAll(Collection<?> c) {

Modified: labs/shotoku/trunk/shotoku-base/src/java/org/jboss/shotoku/tools/Tools.java
===================================================================
--- labs/shotoku/trunk/shotoku-base/src/java/org/jboss/shotoku/tools/Tools.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-base/src/java/org/jboss/shotoku/tools/Tools.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -28,6 +28,8 @@
 import java.util.Random;
 import java.util.Map;
 import java.util.HashMap;
+import java.net.URLEncoder;
+import java.net.URLDecoder;
 
 import org.jboss.shotoku.ContentManager;
 import org.jboss.shotoku.service.ShotokuService;
@@ -289,6 +291,34 @@
     }
 
     /**
+     * Encodes the given string to an URL-friendly format (calls
+     * URLEncoder.encodeURL).
+     * @param s String to encodeURL.
+     * @return Encoded string.
+     */
+    public static String encodeURL(String s) {
+        try {
+            return URLEncoder.encode(s, "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Decodes the given string from aa URL-friendly format (calls
+     * URLDecoder.decodeURL).
+     * @param s String to decodeURL.
+     * @return Decoded string.
+     */
+    public static String decodeURL(String s) {
+        try {
+            return URLDecoder.decode(s, "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
      * Checks if two objects are equal - either both null, or
      * their equals method returns true.
      * @param obj1 First object to compare.

Added: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/CommentsService.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/CommentsService.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/CommentsService.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -0,0 +1,27 @@
+package org.jboss.shotoku.feeds;
+
+import org.jboss.shotoku.feeds.comments.FeedDoesNotExistException;
+import org.jboss.shotoku.feeds.comments.CommentsNotAvialableException;
+import org.jboss.shotoku.feeds.comments.UnauthorizedToCommentException;
+import org.jboss.shotoku.service.AdministratedService;
+import org.jboss.shotoku.Node;
+import org.jboss.shotoku.Directory;
+import org.jboss.shotoku.exceptions.ResourceDoesNotExist;
+
+/**
+ * @author Adam Warski (adamw at aster.pl)
+ */
+public interface CommentsService extends AdministratedService {
+    public void addComment(String feedId, String feedName, String feedElement,
+                           String feedType, String username, String title,
+                           String content, String userIp)
+            throws FeedDoesNotExistException, CommentsNotAvialableException,
+            UnauthorizedToCommentException;
+
+    public String getCommentFeedLink(String feedId, String feedName,
+                                     String feedElement, String feedType,
+                                     String type);
+
+    public Directory getCommentsDirectory(Node commentedNode)
+            throws ResourceDoesNotExist;
+}

Modified: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/FeedFactory.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/FeedFactory.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/FeedFactory.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -22,6 +22,9 @@
 package org.jboss.shotoku.feeds;
 
 import org.jboss.shotoku.feeds.data.*;
+import org.jboss.shotoku.feeds.data.special.Rss2TagFeed;
+import org.jboss.shotoku.feeds.data.special.Rss2CommentFeed;
+import org.jboss.shotoku.feeds.tools.FeedsConstants;
 
 import java.io.File;
 import java.util.HashMap;
@@ -37,7 +40,7 @@
      * Map feed type -> feed class.
      */
     private static Map<String, Class> feedClasses;
-    private static Map<String, Class> specialFeedClasses;
+    private static Map<Integer, Map<String, Class>> specialFeedClasses;
     private static final Random random;
 
     static {
@@ -46,9 +49,20 @@
         feedClasses.put("atom", AtomFeed.class);
         feedClasses.put("rdf", RdfFeed.class);
 
-        specialFeedClasses = new HashMap<String, Class>();
-        specialFeedClasses.put("rss2", Rss2TagFeed.class);
+        specialFeedClasses = new HashMap<Integer, Map<String, Class>>();
 
+        Map<String, Class> tagsSpecialFeedClasses =
+                new HashMap<String, Class>();
+        specialFeedClasses.put(FeedsConstants.TAGS_SPECIAL_FEED,
+                tagsSpecialFeedClasses);
+        tagsSpecialFeedClasses.put("rss2", Rss2TagFeed.class);
+
+        Map<String, Class> commentsSpecialFeedClasses =
+                new HashMap<String, Class>();
+        specialFeedClasses.put(FeedsConstants.COMMENTS_SPECIAL_FEED,
+                commentsSpecialFeedClasses);
+        commentsSpecialFeedClasses.put("rss2", Rss2CommentFeed.class);
+
         random = new Random();
     }
 
@@ -81,11 +95,18 @@
 
     /**
      * Creates a new instance of a special feed implementation of the given type.
+     * @param specialFeedType Type of the special feed.
      * @param type Type of feed to create.
      * @return A new instance of a feed of the given type.
      */
-    public static Class getNewSpecialFeedClass(String type) {
-        return specialFeedClasses.get(type);
+    public static Class getNewSpecialFeedClass(int specialFeedType,
+                                               String type) {
+        Map<String, Class> feedsTypes = specialFeedClasses.get(specialFeedType);
+        if (feedsTypes != null) {
+            return feedsTypes.get(type);
+        } else {
+            return null;
+        }
     }
 
     /**

Modified: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/FeedsDescriptor.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/FeedsDescriptor.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/FeedsDescriptor.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -32,7 +32,7 @@
 import org.apache.log4j.Logger;
 import org.jboss.shotoku.ContentManager;
 import org.jboss.shotoku.feeds.data.NormalFeed;
-import org.jboss.shotoku.feeds.data.SpecialFeed;
+import org.jboss.shotoku.feeds.data.special.SpecialFeed;
 import org.jboss.shotoku.feeds.data.Feed;
 import org.jboss.shotoku.feeds.data.CommentableFeed;
 import org.jboss.shotoku.feeds.variables.VariableResolverManager;

Modified: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/FeedsService.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/FeedsService.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/FeedsService.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -2,28 +2,13 @@
 
 import org.jboss.shotoku.service.AdministratedService;
 import org.jboss.shotoku.feeds.data.Feed;
-import org.jboss.shotoku.feeds.comments.FeedDoesNotExistException;
-import org.jboss.shotoku.feeds.comments.CommentsNotAvialableException;
-import org.jboss.shotoku.feeds.comments.UnauthorizedToCommentException;
+import org.jboss.shotoku.feeds.data.CommentableFeed;
 
 /**
  * @author Adam Warski (adamw at aster.pl)
  */
 public interface FeedsService extends AdministratedService {
     public Feed getFeed(String id, String name, String type);
-
-    public void addComment(String feedId, String feedName, String feedElement,
-                           String feedType, String username, String title,
-                           String content, String userIp)
-            throws FeedDoesNotExistException, CommentsNotAvialableException,
-            UnauthorizedToCommentException;
-
-    /*
-     * SERVICE MANAGEMENT METHODS
-     */
-
-    public void create() throws Exception;
-    public void start() throws Exception;
-    public void stop();
-    public void destroy();
+    public CommentableFeed getCommentableFeed(String id, String name,
+                                              String type);
 }

Modified: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/comments/CommentsServlet.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/comments/CommentsServlet.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/comments/CommentsServlet.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -63,11 +63,16 @@
             String description = Tools.unmarshallText(descriptionNode);
 
             // Adding the comment.
-            FeedsTools.getService().addComment(feedId, feedName, feedType,
+            FeedsTools.getCommentsService().addComment(
+                    feedId, feedName, feedType,
                     feedElement, "adamw", title, description,
                     request.getRemoteHost());
 
             response.setStatus(200);
+
+            System.out.println(FeedsTools.getCommentsService().
+                    getCommentFeedLink(feedId, feedName, feedElement,
+                    feedType, "rss2"));
         } catch (CommentsNotAvialableException e) {
             response.sendError(404, e.getMessage());
         } catch (UnauthorizedToCommentException e) {

Deleted: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/ConcreteTagFeed.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/ConcreteTagFeed.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/ConcreteTagFeed.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -1,51 +0,0 @@
-package org.jboss.shotoku.feeds.data;
-
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import java.io.OutputStream;
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author Adam Warski (adamw at aster.pl)
- */
-public class ConcreteTagFeed implements Feed {
-    private TagFeed tagFeed;
-    private String fullName;
-
-    public ConcreteTagFeed(TagFeed tagFeed, String fullName) {
-        this.tagFeed = tagFeed;
-        this.fullName = fullName;
-    }
-
-    public void write(OutputStream os, HttpServletRequest request)
-            throws IOException {
-        tagFeed.write(os, fullName, request);
-    }
-
-    public void write(HttpServletResponse response, HttpServletRequest request)
-            throws IOException {
-        tagFeed.write(response, fullName, request);
-    }
-
-    public String getName() {
-        return tagFeed.getName();
-    }
-
-    public String getDisplayName() {
-        return tagFeed.getDisplayName();
-    }
-
-    public String getType() {
-        return tagFeed.getType();
-    }
-
-    public void release() {
-        tagFeed.release();
-    }
-
-    public Map<String, Object> getAttributes() {
-        return tagFeed.getAttributes();
-    }
-}

Deleted: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/Rss2TagFeed.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/Rss2TagFeed.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/Rss2TagFeed.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -1,20 +0,0 @@
-package org.jboss.shotoku.feeds.data;
-
-import org.jboss.shotoku.feeds.tools.FeedsConstants;
-import org.apache.velocity.VelocityContext;
-
-import java.util.Map;
-
-/**
- * @author Adam Warski (adamw at aster.pl)
- */
-public class Rss2TagFeed extends TagFeed {
-    public Rss2TagFeed(String name, String type,
-                       Map<String, Object> attributes, VelocityContext vc) {
-        super(name, type, attributes, vc);
-    }
-
-    public String getContentType() {
-        return FeedsConstants.RSS_CONTENT_TYPE;
-    }
-}

Deleted: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/SpecialFeed.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/SpecialFeed.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/SpecialFeed.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -1,10 +0,0 @@
-package org.jboss.shotoku.feeds.data;
-
-/**
- * A special feed interface, which has to be concretized, to get a full feed
- * (basing on a specific request data).
- * @author Adam Warski (adamw at aster.pl)
- */
-public interface SpecialFeed extends Feed {
-    public Feed concretizeFeed(String fullName);
-}

Deleted: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/TagFeed.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/TagFeed.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/TagFeed.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -1,227 +0,0 @@
-package org.jboss.shotoku.feeds.data;
-
-import org.apache.velocity.VelocityContext;
-import org.jboss.shotoku.ContentManager;
-import org.jboss.shotoku.tools.Tools;
-import org.jboss.shotoku.tags.Tag;
-import org.jboss.shotoku.tags.TagService;
-import org.jboss.shotoku.tags.tools.TagTools;
-import org.jboss.shotoku.tags.tools.Constants;
-import org.jboss.shotoku.tags.tools.FeedType;
-import org.jboss.shotoku.tags.exceptions.TagGetException;
-
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import java.io.OutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.util.*;
-import java.net.URLDecoder;
-
-/**
- * @author Adam Warski (adamw at aster.pl)
- */
-public abstract class TagFeed implements SpecialFeed {
-    private String name;
-    private String type;
-    Map<String, Object> attributes;
-    private VelocityContext vcOriginal;
-
-    private int limit;
-    private int nameLength;
-    private ContentManager cm;
-
-    public TagFeed(String name, String type,
-                   Map<String, Object> attributes, VelocityContext vc) {
-        this.name = name;
-        this.type = type;
-        this.attributes = attributes;
-        this.vcOriginal = vc;
-
-        nameLength = name.length();
-        cm = ContentManager.getContentManager(
-                Tools.toString(attributes.get("id")),
-                Tools.toString(attributes.get("prefix")));
-
-        try {
-            limit = Integer.parseInt(Tools.toString(attributes.get("limit")));
-        } catch (NumberFormatException e) {
-            limit = 0;
-        }
-    }
-
-    public Feed concretizeFeed(String fullName) {
-        return new ConcreteTagFeed(this, fullName);
-    }
-
-    public abstract String getContentType();
-
-    public Date getYoungestTagDate(List<Tag> tags) {
-        if (tags.size() == 0) {
-            return new Date();
-        }
-
-        return tags.get(0).getDateCreated();
-    }
-
-    private FeedType getFeedType(String rep) throws IOException {
-        if (FeedType.AUTHOR_ALL.toString().equals(rep)) {
-            return FeedType.AUTHOR_ALL;
-        }
-
-        if (FeedType.RESOURCE.toString().equals(rep)) {
-            return FeedType.RESOURCE;
-        }
-
-        if (FeedType.AUTHOR_UNIQUE.toString().equals(rep)) {
-            return FeedType.AUTHOR_UNIQUE;
-        }
-
-        if (FeedType.AUTHOR_TAG.toString().equals(rep)) {
-            return FeedType.AUTHOR_TAG;
-        }                             
-
-        if (FeedType.TAGS.toString().equals(rep)) {
-            return FeedType.TAGS;
-        }
-
-        throw new IOException("Invalid tag feed request.");
-    }
-
-    public void write(OutputStream os, String fullName,
-                      HttpServletRequest request) throws IOException {
-
-        // Computing the type of the feed to generate.
-        if (fullName.length() < nameLength+1) {
-            throw new IOException("Invalid tag feed request.");
-        }
-
-        String info = fullName.substring(nameLength+1);
-        String[] infoTokens = info.split("[/]", 2);
-        if (infoTokens.length != 2) {
-            throw new IOException("Invalid tag feed request.");
-        }
-
-        VelocityContext vc = new VelocityContext(vcOriginal);
-
-        String infoDataDecoded = infoTokens[1];
-        infoDataDecoded = URLDecoder.decode(infoDataDecoded, "UTF-8");
-        String template = Tools.toString(attributes.get("template"));
-
-        List<Tag> tags;
-        TagService service = TagTools.getService();
-
-        FeedType ft = getFeedType(infoTokens[0]);
-
-        String[] feedCounterData = new String[] { infoDataDecoded };
-        try {
-            switch (ft) {
-                case RESOURCE:
-                    vc.put("resource", infoDataDecoded);
-                    tags = TagTools.getService().getUniqueTags(infoDataDecoded);
-                    break;
-
-                case AUTHOR_UNIQUE:
-                    vc.put("author", infoDataDecoded);
-                    tags = TagTools.getService().getUniqueTagsByAuthor(
-                            infoDataDecoded);
-                    break;
-
-                case AUTHOR_ALL:
-                    vc.put("author", infoDataDecoded);
-                    tags = TagTools.getService().getTagsByAuthor(infoDataDecoded);
-                    break;
-
-                case AUTHOR_TAG:
-                    String[] tagData = infoDataDecoded.split("[+]");
-                    if (tagData.length != 2) {
-                        throw new IOException("Not enough data for a tag-author" +
-                                " feed.");
-                    }
-
-                    vc.put("tagName", tagData[0]);
-                    vc.put("author", tagData[1]);
-                    tags = TagTools.getService().getTags(tagData[0], tagData[1]);
-                    break;
-
-                case TAGS:
-                    String[] tagNames = infoDataDecoded.split("[+]");
-
-                    StringBuffer tagsAsString = new StringBuffer();
-                    for (int i=0; i < tagNames.length; i++) {
-                        tagsAsString.append(tagNames[i]);
-                        if (i < tagNames.length - 1) {
-                            tagsAsString.append(", ");
-                        }
-                    }
-
-                    vc.put("tagsAsString", tagsAsString.toString());
-                    tags = service.getUniqueTags(Arrays.asList(tagNames));
-                    feedCounterData = tagNames;
-                    break;
-
-                default:
-                    throw new IOException("Invalid tag feed request.");
-            }
-        } catch (TagGetException e) {
-            throw new IOException(e.getMessage());
-        }
-
-        for (String feedCounterSingleData : feedCounterData) {
-            service.increaseFeedCounters(ft, feedCounterSingleData,
-                    request.getRemoteAddr());
-        }
-
-        template = template.replace(Constants.TAG_FEED_TYPE_VARIABLE,
-                ft.toString());
-
-        // Computing the date of the youngest tag.
-        vc.put("youngest", getYoungestTagDate(tags));
-        vc.put("tags",
-                limit > 0
-                        ? (tags.size() > limit ? tags.subList(0, limit) : tags)
-                        : tags);
-
-        try {
-            OutputStreamWriter osw = new OutputStreamWriter(os);
-            cm.getVelocityEngine().mergeTemplate(template, vc, osw);
-            osw.flush();
-        } catch (Exception e) {
-            throw new IOException(e.getMessage());
-        }
-    }
-
-    public void write(HttpServletResponse response, String fullName,
-                      HttpServletRequest request) throws IOException {
-        response.setContentType(getContentType());
-        write(response.getOutputStream(), fullName, request);
-    }
-
-    public void write(OutputStream os, HttpServletRequest request) throws IOException {
-        throw new IOException("Can't write a non-concrete tag feed");
-    }
-
-    public void write(HttpServletResponse response, HttpServletRequest request) throws IOException {
-        throw new IOException("Can't write a non-concrete tag feed");
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public String getDisplayName() {
-        return null;
-    }
-
-    public String getType() {
-        return type;
-    }
-
-    public void release() {
-
-    }
-
-    public Map<String, Object> getAttributes() {
-        return attributes;
-    }
-}

Added: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special/CommentFeed.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special/CommentFeed.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special/CommentFeed.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -0,0 +1,173 @@
+package org.jboss.shotoku.feeds.data.special;
+
+import org.apache.velocity.VelocityContext;
+import org.jboss.shotoku.ContentManager;
+import org.jboss.shotoku.Node;
+import org.jboss.shotoku.NodeList;
+import org.jboss.shotoku.Directory;
+import org.jboss.shotoku.search.Search;
+import org.jboss.shotoku.search.DirectoryIncludeParameter;
+import org.jboss.shotoku.search.DateSortParameter;
+import org.jboss.shotoku.search.PropertyValueParameter;
+import org.jboss.shotoku.exceptions.ResourceDoesNotExist;
+import org.jboss.shotoku.feeds.data.Feed;
+import org.jboss.shotoku.feeds.data.CommentableFeed;
+import org.jboss.shotoku.feeds.tools.FeedsTools;
+import org.jboss.shotoku.feeds.tools.NodesFeedsProperties;
+import org.jboss.shotoku.feeds.tools.FeedDefAttributes;
+import org.jboss.shotoku.feeds.tools.VelocityContextAttributes;
+import org.jboss.shotoku.tools.Tools;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Map;
+import java.util.Date;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+
+/**
+ * @author Adam Warski (adamw at aster.pl)
+ */
+public abstract class CommentFeed implements SpecialFeed {
+    private String name;
+    private String type;
+    Map<String, Object> attributes;
+    private VelocityContext vcOriginal;
+
+    private int nameLength;
+    private ContentManager cm;
+
+    public CommentFeed(String name, String type,
+                       Map<String, Object> attributes, VelocityContext vc) {
+        this.name = name;
+        this.type = type;
+        this.attributes = attributes;
+        this.vcOriginal = vc;
+
+        nameLength = name.length();
+        cm = ContentManager.getContentManager(
+                Tools.toString(attributes.get(FeedDefAttributes.CM_ID)),
+                Tools.toString(attributes.get(FeedDefAttributes.CM_PREFIX)));
+    }
+
+    public Feed concretizeFeed(String fullName) {
+        return new ConcreteCommentFeed(this, fullName);
+    }
+
+    public abstract String getContentType();
+
+    private void check(boolean b) throws IOException {
+        if (!b) {
+            throw new IOException("Invalid comment feed request.");
+        }
+    }
+
+    public void write(OutputStream os, String fullName,
+                      HttpServletRequest request) throws IOException {
+        // Getting the feed for which elements feed should be generated
+        // and checking if everything is ok.
+        check(fullName.length() >= nameLength+1);
+
+        String info = fullName.substring(nameLength+1);
+        String[] infoTokens = info.split("[/]");
+        check(infoTokens.length == 4);
+
+        String feedId = Tools.decodeURL(infoTokens[0]);
+        String feedName = Tools.decodeURL(infoTokens[1]);
+        String feedElement = Tools.decodeURL(infoTokens[2]);
+        String feedType = Tools.decodeURL(infoTokens[3]);
+
+        CommentableFeed feed = FeedsTools.getService().getCommentableFeed(
+                feedId, feedName, feedType);
+
+        check(feed != null);
+        //noinspection ConstantConditions
+        check(feed.getCommentsEnabled());
+
+        Node commentedNode = feed.getNodeForFeedElement(feedElement);
+        check(commentedNode != null);
+
+        NodeList comments;
+
+        // Generating the list of nodes that should be included.
+        try {
+            Directory commentDir = FeedsTools.getCommentsService().
+                    getCommentsDirectory(commentedNode);
+
+            Search s = new Search();
+            s.add(new DirectoryIncludeParameter(commentDir));
+
+            if (feed.getCommentsModerated()) {
+                s.add(new PropertyValueParameter(
+                        NodesFeedsProperties.ACCEPTED_COMMENT_NAME,
+                        NodesFeedsProperties.ACCEPTED_COMMENT_VALUE));
+            }
+
+            s.add(new DateSortParameter());
+
+            comments = s.perform(commentDir.getContentManager());
+        } catch (ResourceDoesNotExist e) {
+            comments = new NodeList();
+        }
+
+        VelocityContext vc = new VelocityContext(vcOriginal);
+
+        // Computing the date of the youngest comment.
+        Date youngest;
+        if (comments.size() == 0) {
+            //noinspection ConstantConditions
+            youngest = commentedNode.getCreatedDate();
+        } else {
+            youngest = comments.get(0).getCreatedDate();
+        }
+
+        vc.put("commented", commentedNode);
+        vc.put("youngest", youngest);
+        vc.put(VelocityContextAttributes.NODES_LIST, comments);
+
+        try {
+            OutputStreamWriter osw = new OutputStreamWriter(os);
+            cm.getVelocityEngine().mergeTemplate(
+                    Tools.toString(attributes.get(
+                            FeedDefAttributes.VELOCITY_TEMPLATE)), vc, osw);
+            osw.flush();
+        } catch (Exception e) {
+            throw new IOException(e.getMessage());
+        }
+    }
+
+    public void write(HttpServletResponse response, String fullName,
+                      HttpServletRequest request) throws IOException {
+        response.setContentType(getContentType());
+        write(response.getOutputStream(), fullName, request);
+    }
+
+    public void write(OutputStream os, HttpServletRequest request) throws IOException {
+        throw new IOException("Can't write a non-concrete comment feed");
+    }
+
+    public void write(HttpServletResponse response, HttpServletRequest request) throws IOException {
+        throw new IOException("Can't write a non-concrete comment feed");
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getDisplayName() {
+        return null;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void release() {
+
+    }
+
+    public Map<String, Object> getAttributes() {
+        return attributes;
+    }
+}

Added: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special/ConcreteCommentFeed.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special/ConcreteCommentFeed.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special/ConcreteCommentFeed.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -0,0 +1,52 @@
+package org.jboss.shotoku.feeds.data.special;
+
+import org.jboss.shotoku.feeds.data.Feed;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.OutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * @author Adam Warski (adamw at aster.pl)
+ */
+public class ConcreteCommentFeed implements Feed {
+    private CommentFeed commentFeed;
+    private String fullName;
+
+    public ConcreteCommentFeed(CommentFeed commentFeed, String fullName) {
+        this.commentFeed = commentFeed;
+        this.fullName = fullName;
+    }
+
+    public void write(OutputStream os, HttpServletRequest request)
+            throws IOException {
+        commentFeed.write(os, fullName, request);
+    }
+
+    public void write(HttpServletResponse response, HttpServletRequest request)
+            throws IOException {
+        commentFeed.write(response, fullName, request);
+    }
+
+    public String getName() {
+        return commentFeed.getName();
+    }
+
+    public String getDisplayName() {
+        return commentFeed.getDisplayName();
+    }
+
+    public String getType() {
+        return commentFeed.getType();
+    }
+
+    public void release() {
+        commentFeed.release();
+    }
+
+    public Map<String, Object> getAttributes() {
+        return commentFeed.getAttributes();
+    }
+}

Copied: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special/ConcreteTagFeed.java (from rev 5297, labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/ConcreteTagFeed.java)
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/ConcreteTagFeed.java	2006-07-26 18:59:27 UTC (rev 5297)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special/ConcreteTagFeed.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -0,0 +1,53 @@
+package org.jboss.shotoku.feeds.data.special;
+
+import org.jboss.shotoku.feeds.data.special.TagFeed;
+import org.jboss.shotoku.feeds.data.Feed;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import java.io.OutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * @author Adam Warski (adamw at aster.pl)
+ */
+public class ConcreteTagFeed implements Feed {
+    private TagFeed tagFeed;
+    private String fullName;
+
+    public ConcreteTagFeed(TagFeed tagFeed, String fullName) {
+        this.tagFeed = tagFeed;
+        this.fullName = fullName;
+    }
+
+    public void write(OutputStream os, HttpServletRequest request)
+            throws IOException {
+        tagFeed.write(os, fullName, request);
+    }
+
+    public void write(HttpServletResponse response, HttpServletRequest request)
+            throws IOException {
+        tagFeed.write(response, fullName, request);
+    }
+
+    public String getName() {
+        return tagFeed.getName();
+    }
+
+    public String getDisplayName() {
+        return tagFeed.getDisplayName();
+    }
+
+    public String getType() {
+        return tagFeed.getType();
+    }
+
+    public void release() {
+        tagFeed.release();
+    }
+
+    public Map<String, Object> getAttributes() {
+        return tagFeed.getAttributes();
+    }
+}

Added: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special/Rss2CommentFeed.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special/Rss2CommentFeed.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special/Rss2CommentFeed.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -0,0 +1,20 @@
+package org.jboss.shotoku.feeds.data.special;
+
+import org.apache.velocity.VelocityContext;
+import org.jboss.shotoku.feeds.tools.FeedsConstants;
+
+import java.util.Map;
+
+/**
+ * @author Adam Warski (adamw at aster.pl)
+ */
+public class Rss2CommentFeed extends CommentFeed {
+    public Rss2CommentFeed(String name, String type,
+                           Map<String, Object> attributes, VelocityContext vc) {
+        super(name, type, attributes, vc);
+    }
+
+    public String getContentType() {
+        return FeedsConstants.RSS_CONTENT_TYPE;
+    }
+}

Copied: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special/Rss2TagFeed.java (from rev 5297, labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/Rss2TagFeed.java)
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/Rss2TagFeed.java	2006-07-26 18:59:27 UTC (rev 5297)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special/Rss2TagFeed.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -0,0 +1,21 @@
+package org.jboss.shotoku.feeds.data.special;
+
+import org.jboss.shotoku.feeds.tools.FeedsConstants;
+import org.jboss.shotoku.feeds.data.special.TagFeed;
+import org.apache.velocity.VelocityContext;
+
+import java.util.Map;
+
+/**
+ * @author Adam Warski (adamw at aster.pl)
+ */
+public class Rss2TagFeed extends TagFeed {
+    public Rss2TagFeed(String name, String type,
+                       Map<String, Object> attributes, VelocityContext vc) {
+        super(name, type, attributes, vc);
+    }
+
+    public String getContentType() {
+        return FeedsConstants.RSS_CONTENT_TYPE;
+    }
+}

Copied: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special/SpecialFeed.java (from rev 5297, labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/SpecialFeed.java)
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/SpecialFeed.java	2006-07-26 18:59:27 UTC (rev 5297)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special/SpecialFeed.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -0,0 +1,12 @@
+package org.jboss.shotoku.feeds.data.special;
+
+import org.jboss.shotoku.feeds.data.Feed;
+
+/**
+ * A special feed interface, which has to be concretized, to get a full feed
+ * (basing on a specific request data).
+ * @author Adam Warski (adamw at aster.pl)
+ */
+public interface SpecialFeed extends Feed {
+    public Feed concretizeFeed(String fullName);
+}

Copied: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special/TagFeed.java (from rev 5297, labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/TagFeed.java)
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/TagFeed.java	2006-07-26 18:59:27 UTC (rev 5297)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/data/special/TagFeed.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -0,0 +1,228 @@
+package org.jboss.shotoku.feeds.data.special;
+
+import org.apache.velocity.VelocityContext;
+import org.jboss.shotoku.ContentManager;
+import org.jboss.shotoku.feeds.data.Feed;
+import org.jboss.shotoku.tools.Tools;
+import org.jboss.shotoku.tags.Tag;
+import org.jboss.shotoku.tags.TagService;
+import org.jboss.shotoku.tags.tools.TagTools;
+import org.jboss.shotoku.tags.tools.Constants;
+import org.jboss.shotoku.tags.tools.FeedType;
+import org.jboss.shotoku.tags.exceptions.TagGetException;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import java.io.OutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.util.*;
+import java.net.URLDecoder;
+
+/**
+ * @author Adam Warski (adamw at aster.pl)
+ */
+public abstract class TagFeed implements SpecialFeed {
+    private String name;
+    private String type;
+    Map<String, Object> attributes;
+    private VelocityContext vcOriginal;
+
+    private int limit;
+    private int nameLength;
+    private ContentManager cm;
+
+    public TagFeed(String name, String type,
+                   Map<String, Object> attributes, VelocityContext vc) {
+        this.name = name;
+        this.type = type;
+        this.attributes = attributes;
+        this.vcOriginal = vc;
+
+        nameLength = name.length();
+        cm = ContentManager.getContentManager(
+                Tools.toString(attributes.get("id")),
+                Tools.toString(attributes.get("prefix")));
+
+        try {
+            limit = Integer.parseInt(Tools.toString(attributes.get("limit")));
+        } catch (NumberFormatException e) {
+            limit = 0;
+        }
+    }
+
+    public Feed concretizeFeed(String fullName) {
+        return new ConcreteTagFeed(this, fullName);
+    }
+
+    public abstract String getContentType();
+
+    public Date getYoungestTagDate(List<Tag> tags) {
+        if (tags.size() == 0) {
+            return new Date();
+        }
+
+        return tags.get(0).getDateCreated();
+    }
+
+    private FeedType getFeedType(String rep) throws IOException {
+        if (FeedType.AUTHOR_ALL.toString().equals(rep)) {
+            return FeedType.AUTHOR_ALL;
+        }
+
+        if (FeedType.RESOURCE.toString().equals(rep)) {
+            return FeedType.RESOURCE;
+        }
+
+        if (FeedType.AUTHOR_UNIQUE.toString().equals(rep)) {
+            return FeedType.AUTHOR_UNIQUE;
+        }
+
+        if (FeedType.AUTHOR_TAG.toString().equals(rep)) {
+            return FeedType.AUTHOR_TAG;
+        }                             
+
+        if (FeedType.TAGS.toString().equals(rep)) {
+            return FeedType.TAGS;
+        }
+
+        throw new IOException("Invalid tag feed request.");
+    }
+
+    public void write(OutputStream os, String fullName,
+                      HttpServletRequest request) throws IOException {
+
+        // Computing the type of the feed to generate.
+        if (fullName.length() < nameLength+1) {
+            throw new IOException("Invalid tag feed request.");
+        }
+
+        String info = fullName.substring(nameLength+1);
+        String[] infoTokens = info.split("[/]", 2);
+        if (infoTokens.length != 2) {
+            throw new IOException("Invalid tag feed request.");
+        }
+
+        VelocityContext vc = new VelocityContext(vcOriginal);
+
+        String infoDataDecoded = infoTokens[1];
+        infoDataDecoded = URLDecoder.decode(infoDataDecoded, "UTF-8");
+        String template = Tools.toString(attributes.get("template"));
+
+        List<Tag> tags;
+        TagService service = TagTools.getService();
+
+        FeedType ft = getFeedType(infoTokens[0]);
+
+        String[] feedCounterData = new String[] { infoDataDecoded };
+        try {
+            switch (ft) {
+                case RESOURCE:
+                    vc.put("resource", infoDataDecoded);
+                    tags = TagTools.getService().getUniqueTags(infoDataDecoded);
+                    break;
+
+                case AUTHOR_UNIQUE:
+                    vc.put("author", infoDataDecoded);
+                    tags = TagTools.getService().getUniqueTagsByAuthor(
+                            infoDataDecoded);
+                    break;
+
+                case AUTHOR_ALL:
+                    vc.put("author", infoDataDecoded);
+                    tags = TagTools.getService().getTagsByAuthor(infoDataDecoded);
+                    break;
+
+                case AUTHOR_TAG:
+                    String[] tagData = infoDataDecoded.split("[+]");
+                    if (tagData.length != 2) {
+                        throw new IOException("Not enough data for a tag-author" +
+                                " feed.");
+                    }
+
+                    vc.put("tagName", tagData[0]);
+                    vc.put("author", tagData[1]);
+                    tags = TagTools.getService().getTags(tagData[0], tagData[1]);
+                    break;
+
+                case TAGS:
+                    String[] tagNames = infoDataDecoded.split("[+]");
+
+                    StringBuffer tagsAsString = new StringBuffer();
+                    for (int i=0; i < tagNames.length; i++) {
+                        tagsAsString.append(tagNames[i]);
+                        if (i < tagNames.length - 1) {
+                            tagsAsString.append(", ");
+                        }
+                    }
+
+                    vc.put("tagsAsString", tagsAsString.toString());
+                    tags = service.getUniqueTags(Arrays.asList(tagNames));
+                    feedCounterData = tagNames;
+                    break;
+
+                default:
+                    throw new IOException("Invalid tag feed request.");
+            }
+        } catch (TagGetException e) {
+            throw new IOException(e.getMessage());
+        }
+
+        for (String feedCounterSingleData : feedCounterData) {
+            service.increaseFeedCounters(ft, feedCounterSingleData,
+                    request.getRemoteAddr());
+        }
+
+        template = template.replace(Constants.TAG_FEED_TYPE_VARIABLE,
+                ft.toString());
+
+        // Computing the date of the youngest tag.
+        vc.put("youngest", getYoungestTagDate(tags));
+        vc.put("tags",
+                limit > 0
+                        ? (tags.size() > limit ? tags.subList(0, limit) : tags)
+                        : tags);
+
+        try {
+            OutputStreamWriter osw = new OutputStreamWriter(os);
+            cm.getVelocityEngine().mergeTemplate(template, vc, osw);
+            osw.flush();
+        } catch (Exception e) {
+            throw new IOException(e.getMessage());
+        }
+    }
+
+    public void write(HttpServletResponse response, String fullName,
+                      HttpServletRequest request) throws IOException {
+        response.setContentType(getContentType());
+        write(response.getOutputStream(), fullName, request);
+    }
+
+    public void write(OutputStream os, HttpServletRequest request) throws IOException {
+        throw new IOException("Can't write a non-concrete tag feed");
+    }
+
+    public void write(HttpServletResponse response, HttpServletRequest request) throws IOException {
+        throw new IOException("Can't write a non-concrete tag feed");
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getDisplayName() {
+        return null;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void release() {
+
+    }
+
+    public Map<String, Object> getAttributes() {
+        return attributes;
+    }
+}

Added: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/service/CommentsServiceImpl.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/service/CommentsServiceImpl.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/service/CommentsServiceImpl.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -0,0 +1,320 @@
+package org.jboss.shotoku.feeds.service;
+
+import org.jboss.annotation.ejb.Service;
+import org.jboss.annotation.ejb.Management;
+import org.jboss.annotation.ejb.Depends;
+import org.jboss.shotoku.feeds.tools.FeedsConstants;
+import org.jboss.shotoku.feeds.tools.FeedsTools;
+import org.jboss.shotoku.feeds.tools.NodesFeedsProperties;
+import org.jboss.shotoku.feeds.CommentsService;
+import org.jboss.shotoku.feeds.comments.FeedDoesNotExistException;
+import org.jboss.shotoku.feeds.comments.CommentsNotAvialableException;
+import org.jboss.shotoku.feeds.comments.UnauthorizedToCommentException;
+import org.jboss.shotoku.feeds.comments.CommentEntity;
+import org.jboss.shotoku.feeds.data.CommentableFeed;
+import org.jboss.shotoku.user.tools.UserConstants;
+import org.jboss.shotoku.user.UserNotFoundException;
+import org.jboss.shotoku.tools.Constants;
+import org.jboss.shotoku.tools.Tools;
+import org.jboss.shotoku.service.AdministratedServiceImpl;
+import org.jboss.shotoku.service.AdministratedService;
+import org.jboss.shotoku.tags.tools.UserTools;
+import org.jboss.shotoku.Node;
+import org.jboss.shotoku.Directory;
+import org.jboss.shotoku.ContentManager;
+import org.jboss.shotoku.exceptions.NameFormatException;
+import org.jboss.shotoku.exceptions.ResourceAlreadyExists;
+import org.jboss.shotoku.exceptions.ResourceDoesNotExist;
+import org.apache.log4j.Logger;
+
+import javax.ejb.Local;
+import javax.persistence.PersistenceUnit;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityManager;
+import javax.transaction.UserTransaction;
+import javax.naming.InitialContext;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * @author Adam Warski (adamw at aster.pl)
+ */
+ at Service(objectName = FeedsConstants.COMMENTS_SERVICE_NAME)
+ at Local(CommentsServiceLocal.class)
+ at Management(CommentsService.class)
+ at Depends({UserConstants.USER_SERVICE_NAME, Constants.SHOTOKU_SERVICE_NAME,
+        FeedsConstants.FEEDS_SERVICE_NAME})
+public class CommentsServiceImpl extends AdministratedServiceImpl
+        implements CommentsService, CommentsServiceLocal {
+    private static final Logger log = Logger.getLogger(AdministratedService.class);
+
+    /*
+     * CommentsService implementation.
+     */
+
+    @SuppressWarnings({"UNUSED_SYMBOL"})
+    @PersistenceUnit
+    private EntityManagerFactory emf;
+
+    public void addComment(String feedId, String feedName, String feedType,
+                           String feedElement, String username,
+                           String title, String content, String userIp)
+            throws FeedDoesNotExistException, CommentsNotAvialableException,
+            UnauthorizedToCommentException {
+        System.out.println("ADD COMMENT:");
+        System.out.println("feedId = " + feedId);
+        System.out.println("feedName = " + feedName);
+        System.out.println("feedType = " + feedType);
+        System.out.println("feedElement = " + feedElement);
+        System.out.println("username = " + username);
+        System.out.println("title = " + title);
+        System.out.println("content = " + content);
+
+        // Getting the feed and checking if it exists.
+        CommentableFeed feed = FeedsTools.getService().getCommentableFeed(
+                feedId, feedName, feedType);
+
+        if (feed == null) {
+            throw new FeedDoesNotExistException();
+        }
+
+        // Checking if comments are enabled for this feed.
+        if (!feed.getCommentsEnabled()) {
+            throw new CommentsNotAvialableException();
+        }
+
+        // Checking if there is a user logged in and if it is a valid user.
+        try {
+            UserTools.getService().getUser(username);
+        } catch (UserNotFoundException e) {
+            throw new UnauthorizedToCommentException(e);
+        }
+
+        // Checking if the commented item exists in the content manager.
+        Node commentedElement = feed.getNodeForFeedElement(feedElement);
+
+        if (commentedElement == null) {
+            throw new FeedDoesNotExistException("Invalid feed element.");
+        }
+
+        // Saving the comment for later addition to Shotoku.
+        EntityManager em = emf.createEntityManager();
+        try {
+            em.persist(new CommentEntity(feedId, feedName, feedType,
+                    feedElement, username, title, content));
+        } finally {
+            em.close();
+        }
+    }
+
+    public String getCommentFeedLink(String feedId, String feedName,
+                                     String feedElement, String feedType,
+                                     String type) {
+        return "/feeds/comment/" +
+                Tools.encodeURL(feedId) + "/" +
+                Tools.encodeURL(feedName) + "/" +
+                Tools.encodeURL(feedElement) + "/" +
+                Tools.encodeURL(feedType) + "/" + type;
+    }
+
+    private String getCommentsDirectoryName(Node commentedNode) {
+        return commentedNode.getName() + "_comments";
+    }
+
+    public Directory getCommentsDirectory(Node commentedNode)
+            throws ResourceDoesNotExist {
+        return commentedNode.getParent().getDirectory(
+                getCommentsDirectoryName(commentedNode));
+    }
+
+    /*
+     * Update method.
+     */
+
+    /**
+     * Creates a node in the given directory, in which a comment can
+     * be placed. Effectively, crates a new "fresh" node, which
+     * doesn't yet exist.
+     * @param commentDir Directory in which the node shold be created.
+     * @param number Number from which will be appended to the end of
+     * the node name. If a node with this name already exists, the next
+     * number will be tried, and so on.
+     * @return A "fresh" node.
+     */
+    private Node createCommentNode(Directory commentDir, int number)
+            throws NameFormatException {
+        try {
+            return commentDir.newNode("c" + System.currentTimeMillis()
+                    + "_" + number);
+        } catch (ResourceAlreadyExists e) {
+            return createCommentNode(commentDir, number + 1);
+        }
+    }
+
+    private Node createCommentNode(Directory commentDir)
+            throws NameFormatException {
+        return createCommentNode(commentDir, 0);
+    }
+
+    private void removeCommentEntity(EntityManager em, CommentEntity ce)
+            throws Throwable {
+        UserTransaction tran = null;
+        try {
+            InitialContext jndiCntx = new InitialContext();
+            tran = (UserTransaction) jndiCntx.lookup("UserTransaction");
+
+            tran.begin();
+            em.joinTransaction();
+            em.remove(ce);
+            tran.commit();
+        } catch (Throwable t) {
+            if (tran != null) {
+                tran.rollback();
+            }
+
+            throw t;
+        }
+    }
+
+    public void update() {
+        // Adding any (possible) comments.
+        EntityManager updateThreadEm = emf.createEntityManager();
+
+        try {
+            //noinspection unchecked
+            List<CommentEntity> result = updateThreadEm.createQuery(
+                    "FROM CommentEntity").getResultList();
+
+            List<CommentEntity> failedComments = new ArrayList<CommentEntity>();
+            for (CommentEntity ce : result) {
+                try {
+                    CommentableFeed feed = FeedsTools.getService().
+                            getCommentableFeed(ce.getFeedId(),
+                                    ce.getFeedName(), ce.getFeedType());
+
+                    // Checking if the feed exists.
+                    if (feed == null || !feed.getCommentsEnabled()) {
+                        failedComments.add(ce);
+                        continue;
+                    }
+
+                    Node commentedElement = feed.getNodeForFeedElement(
+                            ce.getFeedElement());
+
+                    // Checking if the commented element exists.
+                    if (commentedElement == null) {
+                        failedComments.add(ce);
+                        continue;
+                    }
+
+                    // Adding the comment.
+
+                    // Getting/ creating the comment directory.
+                    Directory commentDir;
+                    try {
+                        commentDir = getCommentsDirectory(commentedElement);
+                    } catch (ResourceDoesNotExist e) {
+                        try {
+                            commentDir = commentedElement.getParent().
+                                    newDirectory(getCommentsDirectoryName(
+                                            commentedElement));
+                        } catch (ResourceAlreadyExists e1) {
+                            log.warn("A node which does exist and doesn't.", e1);
+                            failedComments.add(ce);
+                            continue;
+                        }
+                    }
+
+                    // Creating the comment node.
+                    Node commentNode = createCommentNode(commentDir);
+                    commentNode.setContent(ce.getContent());
+                    commentNode.setProperty("title", ce.getTitle());
+                    commentNode.setProperty("author", ce.getUsername());
+                    if (feed.getCommentsModerated()) {
+                        commentNode.setProperty(
+                                NodesFeedsProperties.ACCEPTED_COMMENT_NAME,
+                                NodesFeedsProperties.NOTACCEPTED_COMMENT_VALUE);
+                    } else {
+                        // If the feed is not moderated, the entry gets
+                        // automatically accepted.
+                        commentNode.setProperty(
+                                NodesFeedsProperties.ACCEPTED_COMMENT_NAME,
+                                NodesFeedsProperties.ACCEPTED_COMMENT_VALUE);
+                    }
+
+                    // Saving.
+                    commentNode.getContentManager().save("Adding a comment",
+                            commentNode, commentDir);
+                } catch (Throwable t) {
+                    log.warn("Exception when trying to add a comment.", t);
+                    failedComments.add(ce);
+                }
+
+                try {
+                    removeCommentEntity(updateThreadEm, ce);
+                } catch (Throwable t) {
+                    log.warn("Exception when trying to remove a comment entity.", t);
+                }
+            }
+
+            // Logging information about comments, which addition failed.
+            for (CommentEntity ce : failedComments) {
+                log.warn("Failed to add comment: " +
+                        ce.getFeedId() + " :: " + ce.getFeedName() + " :: " +
+                        ce.getFeedType() + " :: " + ce.getFeedElement() + " :: " +
+                        ce.getTitle() + " :: " + ce.getContent() + " :: " +
+                        ce.getUsername());
+
+                try {
+                    removeCommentEntity(updateThreadEm, ce);
+                } catch (Throwable t) {
+                    log.warn("Exception when trying to remove a comment entity.", t);
+                }
+            }
+        } finally {
+            updateThreadEm.close();
+        }
+    }
+
+    /*
+     * Service management.
+     */
+    public void create() throws Exception {
+        super.create();
+
+        setTimerInterval(ContentManager.getProperty(
+                FeedsConstants.PROPERTY_INTERVAL, 10000));
+
+        super.afterCreate();
+    }
+
+    public void start() throws Exception {
+        super.start();
+        startUpdateThread();
+        super.afterStart();
+    }
+
+    public void destroy() {
+
+    }
+
+    /*
+     * Administrated service implementation.
+     */
+
+    public String getServiceId() {
+        return "ShotokuCommentsService";
+    }
+
+    public String getServiceName() {
+        return "Comments service";
+    }
+
+    public String getServiceDescription() {
+        return "Shotoku comments service.";
+    }
+
+    public AdministratedService getServiceInstance() {
+        return FeedsTools.getCommentsService();
+    }
+}

Added: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/service/CommentsServiceLocal.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/service/CommentsServiceLocal.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/service/CommentsServiceLocal.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -0,0 +1,7 @@
+package org.jboss.shotoku.feeds.service;
+
+/**
+ * @author Adam Warski (adamw at aster.pl)
+ */
+public interface CommentsServiceLocal {
+}

Modified: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/service/FeedsServiceImpl.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/service/FeedsServiceImpl.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/service/FeedsServiceImpl.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -6,10 +6,6 @@
 import org.jboss.shotoku.feeds.FeedsService;
 import org.jboss.shotoku.feeds.FeedsDescriptor;
 import org.jboss.shotoku.feeds.FeedsConfigurationWatcher;
-import org.jboss.shotoku.feeds.comments.FeedDoesNotExistException;
-import org.jboss.shotoku.feeds.comments.CommentsNotAvialableException;
-import org.jboss.shotoku.feeds.comments.UnauthorizedToCommentException;
-import org.jboss.shotoku.feeds.comments.CommentEntity;
 import org.jboss.shotoku.feeds.data.Feed;
 import org.jboss.shotoku.feeds.data.CommentableFeed;
 import org.jboss.shotoku.feeds.tools.FeedsConstants;
@@ -17,38 +13,21 @@
 import org.jboss.shotoku.service.AdministratedServiceImpl;
 import org.jboss.shotoku.service.AdministratedService;
 import org.jboss.shotoku.ContentManager;
-import org.jboss.shotoku.Node;
-import org.jboss.shotoku.Directory;
-import org.jboss.shotoku.exceptions.ResourceAlreadyExists;
-import org.jboss.shotoku.exceptions.NameFormatException;
-import org.jboss.shotoku.exceptions.ResourceDoesNotExist;
-import org.jboss.shotoku.user.UserNotFoundException;
-import org.jboss.shotoku.user.tools.UserConstants;
-import org.jboss.shotoku.tags.tools.UserTools;
 import org.jboss.shotoku.tools.Constants;
 import org.jboss.shotoku.aop.CacheItem;
-import org.apache.log4j.Logger;
 
 import javax.ejb.Local;
-import javax.persistence.EntityManager;
-import javax.persistence.EntityManagerFactory;
-import javax.persistence.PersistenceUnit;
-import javax.naming.InitialContext;
-import javax.transaction.UserTransaction;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.List;
-import java.util.ArrayList;
-
 /**
  * @author Adam Warski (adamw at aster.pl)
  */
 @Service(objectName = FeedsConstants.FEEDS_SERVICE_NAME)
 @Local(FeedsServiceLocal.class)
 @Management(FeedsService.class)
- at Depends({UserConstants.USER_SERVICE_NAME,Constants.SHOTOKU_SERVICE_NAME})
+ at Depends(Constants.SHOTOKU_SERVICE_NAME)
 public class FeedsServiceImpl extends AdministratedServiceImpl
         implements FeedsService, FeedsServiceLocal {
-    private static final Logger log = Logger.getLogger(AdministratedService.class);
+    //private static final Logger log = Logger.getLogger(AdministratedService.class);
 
     /*
      * FeedsService implementation.
@@ -61,10 +40,6 @@
     private ConcurrentHashMap<String, FeedsDescriptor> fds;
     public static final Object synchronizer = new Object();
 
-    @SuppressWarnings({"UNUSED_SYMBOL"})
-    @PersistenceUnit
-    private EntityManagerFactory emf;
-
     private FeedsDescriptor getFeedsDescriptor(String id) {
         if (!fds.contains(id)) {
             synchronized(synchronizer) {
@@ -81,202 +56,21 @@
         return getFeedsDescriptor(id).getFeed(name, type);
     }
 
-    public void addComment(String feedId, String feedName, String feedType,
-                           String feedElement, String username,
-                           String title, String content, String userIp)
-            throws FeedDoesNotExistException, CommentsNotAvialableException,
-            UnauthorizedToCommentException {
-        System.out.println("ADD COMMENT:");
-        System.out.println("feedId = " + feedId);
-        System.out.println("feedName = " + feedName);
-        System.out.println("feedType = " + feedType);
-        System.out.println("feedElement = " + feedElement);
-        System.out.println("username = " + username);
-        System.out.println("title = " + title);
-        System.out.println("content = " + content);
-
-        // Getting the feed and checking if it exists.
-        CommentableFeed feed = getFeedsDescriptor(feedId).getCommentableFeed(
-                feedName, feedType);
-
-        if (feed == null) {
-            throw new FeedDoesNotExistException();
-        }
-
-        // Checking if comments are enabled for this feed.
-        if (!feed.getCommentsEnabled()) {
-            throw new CommentsNotAvialableException();
-        }
-
-        // Checking if there is a user logged in and if it is a valid user.
-        try {
-            UserTools.getService().getUser(username);
-        } catch (UserNotFoundException e) {
-            throw new UnauthorizedToCommentException(e);
-        }
-
-        // Checking if the commented item exists in the content manager.
-        Node commentedElement = feed.getNodeForFeedElement(feedElement);
-
-        if (commentedElement == null) {
-            throw new FeedDoesNotExistException("Invalid feed element.");
-        }
-
-        // Saving the comment for later addition to Shotoku.
-        EntityManager em = emf.createEntityManager();
-        try {
-            em.persist(new CommentEntity(feedId, feedName, feedType,
-                    feedElement, username, title, content));
-        } finally {
-            em.close();
-        }
+    public CommentableFeed getCommentableFeed(String id, String name,
+                                              String type) {
+        return getFeedsDescriptor(id).getCommentableFeed(name, type);
     }
 
     /*
      * Update method.
      */
 
-    /**
-     * Creates a node in the given directory, in which a comment can
-     * be placed. Effectively, crates a new "fresh" node, which
-     * doesn't yet exist.
-     * @param commentDir Directory in which the node shold be created.
-     * @param number Number from which will be appended to the end of
-     * the node name. If a node with this name already exists, the next
-     * number will be tried, and so on.
-     * @return A "fresh" node.
-     */
-    private Node createCommentNode(Directory commentDir, int number)
-            throws NameFormatException {
-        try {
-            return commentDir.newNode("c" + System.currentTimeMillis()
-                    + "_" + number);
-        } catch (ResourceAlreadyExists e) {
-            return createCommentNode(commentDir, number + 1);
-        }
-    }
-
-    private Node createCommentNode(Directory commentDir)
-            throws NameFormatException {
-        return createCommentNode(commentDir, 0);
-    }
-
-    private void removeCommentEntity(EntityManager em, CommentEntity ce)
-            throws Throwable {
-        UserTransaction tran = null;
-        try {
-            InitialContext jndiCntx = new InitialContext();
-            tran = (UserTransaction) jndiCntx.lookup("UserTransaction");
-
-            tran.begin();
-            em.joinTransaction();
-            em.remove(ce);
-            tran.commit();
-        } catch (Throwable t) {
-            if (tran != null) {
-                tran.rollback();
-            }
-
-            throw t;
-        }
-    }
-
     public void update() {
-        // Adding any (possible) comments.
-        EntityManager updateThreadEm = emf.createEntityManager();
-
-        try {
-            //noinspection unchecked
-            List<CommentEntity> result = updateThreadEm.createQuery(
-                    "FROM CommentEntity").getResultList();
-
-            List<CommentEntity> failedComments = new ArrayList<CommentEntity>();
-            for (CommentEntity ce : result) {
-                try {
-                    CommentableFeed feed = getFeedsDescriptor(ce.getFeedId()).
-                            getCommentableFeed(ce.getFeedName(), ce.getFeedType());
-
-                    // Checking if the feed exists.
-                    if (feed == null || !feed.getCommentsEnabled()) {
-                        failedComments.add(ce);
-                        continue;
-                    }
-
-                    Node commentedElement = feed.getNodeForFeedElement(
-                            ce.getFeedElement());
-
-                    // Checking if the commented element exists.
-                    if (commentedElement == null) {
-                        failedComments.add(ce);
-                        continue;
-                    }
-
-                    // Adding the comment.
-                    Directory root = commentedElement.getParent();
-                    String commentDirName = commentedElement.getName() +
-                            "_comments";
-
-                    // Getting/ creating the comment directory.
-                    Directory commentDir;
-                    try {
-                        commentDir = root.getDirectory(commentDirName);
-                    } catch (ResourceDoesNotExist e) {
-                        try {
-                            commentDir = root.newDirectory(commentDirName);
-                        } catch (ResourceAlreadyExists e1) {
-                            log.warn("A node which does exist and doesn't.", e1);
-                            failedComments.add(ce);
-                            continue;
-                        }
-                    }
-
-                    // Creating the comment node.
-                    Node commentNode = createCommentNode(commentDir);
-                    commentNode.setContent(ce.getContent());
-                    commentNode.setProperty("title", ce.getTitle());
-                    commentNode.setProperty("author", ce.getUsername());
-                    if (feed.getCommentsModerated()) {
-                        commentNode.setProperty("accepted", "0");
-                    }
-
-                    // Saving.
-                    commentNode.getContentManager().save("Adding a comment",
-                            commentNode, commentDir);
-                } catch (Throwable t) {
-                    log.warn("Exception when trying to add a comment.", t);
-                    failedComments.add(ce);
-                }
-
-                try {
-                    removeCommentEntity(updateThreadEm, ce);
-                } catch (Throwable t) {
-                    log.warn("Exception when trying to remove a comment entity.", t);
-                }
-            }
-
-            // Logging information about comments, which addition failed.
-            for (CommentEntity ce : failedComments) {
-                log.warn("Failed to add comment: " +
-                        ce.getFeedId() + " :: " + ce.getFeedName() + " :: " +
-                        ce.getFeedType() + " :: " + ce.getFeedElement() + " :: " +
-                        ce.getTitle() + " :: " + ce.getContent() + " :: " +
-                        ce.getUsername());
-
-                try {
-                    removeCommentEntity(updateThreadEm, ce);
-                } catch (Throwable t) {
-                    log.warn("Exception when trying to remove a comment entity.", t);
-                }
-            }
-
-            // Updating descriptors.
-            for (String id : fds.keySet()) {
-                FeedsDescriptor fd = fds.get(id);
-                fds.put(id, new FeedsDescriptor(id, conf));
-                fd.release();
-            }
-        } finally {
-            updateThreadEm.close();
+        // Updating descriptors.
+        for (String id : fds.keySet()) {
+            FeedsDescriptor fd = fds.get(id);
+            fds.put(id, new FeedsDescriptor(id, conf));
+            fd.release();
         }
     }
 

Modified: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/AggregatedFeedTagHandler.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/AggregatedFeedTagHandler.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/AggregatedFeedTagHandler.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -5,7 +5,7 @@
 import org.jboss.shotoku.feeds.data.NormalFeed;
 import org.jboss.shotoku.feeds.FeedFactory;
 import org.jboss.shotoku.feeds.FeedsDescriptor;
-import org.jboss.shotoku.feeds.tools.FeedsConstants;
+import org.jboss.shotoku.feeds.tools.FeedDefAttributes;
 import org.jboss.shotoku.feeds.variables.Substitution;
 import org.jboss.shotoku.tools.Tools;
 import org.apache.log4j.Logger;
@@ -80,7 +80,7 @@
         }
 
         NormalFeed feed = FeedFactory.getNewNormalFeed(feedName,
-                Tools.toString(attributes.get(FeedsConstants.DISP_NAME_ATTR)),
+                Tools.toString(attributes.get(FeedDefAttributes.DISP_NAME)),
                 feedType, attributes);
 
         try {

Added: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/CommentFeedTagHandler.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/CommentFeedTagHandler.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/CommentFeedTagHandler.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -0,0 +1,54 @@
+package org.jboss.shotoku.feeds.tag;
+
+import org.w3c.dom.Node;
+import org.jboss.shotoku.feeds.variables.Substitution;
+import org.jboss.shotoku.feeds.FeedsDescriptor;
+import org.jboss.shotoku.feeds.FeedFactory;
+import org.jboss.shotoku.feeds.data.special.SpecialFeed;
+import org.jboss.shotoku.feeds.tools.FeedsTools;
+import org.jboss.shotoku.feeds.tools.FeedsConstants;
+import org.apache.velocity.VelocityContext;
+
+import java.util.Map;
+
+/**
+ * @author Adam Warski (adamw at aster.pl)
+ */
+public class CommentFeedTagHandler extends FeedTagHandler {
+    public CommentFeedTagHandler(String feedName, String group,
+                                 Node definition, Substitution s) {
+        super(feedName, group, definition, s);
+    }
+
+    public boolean generate(FeedsDescriptor fd) {
+        if (!generateAttributes(fd)) {
+            return false;
+        }
+
+        // Reading all attributes and making the substitution on them.
+        Map<String, Object> attributes = getAttributes();
+
+        // Creating a velocity context with parts that won't change in all
+        // generated feeds.
+        VelocityContext vc = new VelocityContext(attributes);
+        FeedsTools.prepareVelocityContext(attributes, vc);
+
+        String feedName = getFeedName();
+        String feedType = getFeedType();
+
+        Class feedClass = FeedFactory.getNewSpecialFeedClass(
+                FeedsConstants.COMMENTS_SPECIAL_FEED, feedType);
+
+        try {
+            fd.addSpecialFeed(feedName, feedType,
+                    (SpecialFeed) feedClass.getConstructor(
+                            String.class, String.class, Map.class,
+                            VelocityContext.class).newInstance(
+                            feedName, feedType, attributes, vc));
+        } catch (Exception e) {
+            return false;
+        }
+
+        return true;
+    }
+}

Modified: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/FeedTagHandler.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/FeedTagHandler.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/FeedTagHandler.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -5,6 +5,7 @@
 import org.jboss.shotoku.feeds.FeedsDescriptor;
 import org.jboss.shotoku.feeds.tools.FeedsConstants;
 import org.jboss.shotoku.feeds.tools.FeedsTools;
+import org.jboss.shotoku.feeds.tools.FeedDefAttributes;
 import org.jboss.shotoku.tools.Tools;
 import org.apache.log4j.Logger;
 
@@ -71,7 +72,7 @@
      * have been met.
      */
     public boolean generateAttributes(FeedsDescriptor fd) {
-        Object extendsObj = attributes.get(FeedsConstants.EXTENDS_ATTR);
+        Object extendsObj = attributes.get(FeedDefAttributes.EXTENDS);
         if (extendsObj == null) {
             return true;
         }
@@ -116,7 +117,7 @@
      */
     protected String generateFeedLink(FeedsDescriptor fd, boolean full, String feedName,
                                       String feedType) {
-        return (full ? getAttributes().get(FeedsConstants.BASE_ADDR_ATTR) : "")
+        return (full ? getAttributes().get(FeedDefAttributes.BASE_ADDR) : "")
                 + "/feeds/" + feedName + "/" + feedType;
     }
 }

Modified: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/FeedTagHandlerManager.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/FeedTagHandlerManager.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/FeedTagHandlerManager.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -2,6 +2,7 @@
 
 import org.jboss.shotoku.tools.Tools;
 import org.jboss.shotoku.feeds.tools.FeedsConstants;
+import org.jboss.shotoku.feeds.tools.FeedDefAttributes;
 import org.jboss.shotoku.feeds.FeedsDescriptor;
 import org.jboss.shotoku.feeds.variables.VariableResolverManager;
 import org.jboss.shotoku.feeds.variables.Substitution;
@@ -45,6 +46,7 @@
         addHandler(FeedsConstants.REM_FEED_TAG, RemoteFeedTagHandler.class);
         addHandler(FeedsConstants.SHO_FEED_TAG, ShotokuFeedTagHandler.class);
         addHandler(FeedsConstants.TAG_FEED_TAG, TagFeedTagHandler.class);
+        addHandler(FeedsConstants.COMMENT_FEED_TAG, CommentFeedTagHandler.class);
         addHandler(FeedsConstants.ATTRS_TAG, AttributesTagHandler.class);
     }
 
@@ -94,7 +96,7 @@
 
         // Reading the feed name attribute.
         String feedNameAttr = Tools.getAttributeValue(definition,
-                FeedsConstants.NAME_ATTR);
+                FeedDefAttributes.NAME);
 
         if (feedNameAttr == null) {
             log.warn("Found a feed definition without a name. Ingoring.");

Modified: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/RemoteFeedTagHandler.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/RemoteFeedTagHandler.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/RemoteFeedTagHandler.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -4,7 +4,7 @@
 import org.jboss.shotoku.feeds.variables.Substitution;
 import org.jboss.shotoku.feeds.data.NormalFeed;
 import org.jboss.shotoku.feeds.FeedFactory;
-import org.jboss.shotoku.feeds.tools.FeedsConstants;
+import org.jboss.shotoku.feeds.tools.FeedDefAttributes;
 import org.jboss.shotoku.feeds.FeedsDescriptor;
 import org.jboss.shotoku.tools.Tools;
 import org.apache.log4j.Logger;
@@ -31,7 +31,7 @@
 
         String address = Tools.toString(getAttributes().get("address"));
         String displayName = Tools.toString(getAttributes().get(
-                FeedsConstants.DISP_NAME_ATTR));
+                FeedDefAttributes.DISP_NAME));
 
         try {
             NormalFeed feed = FeedFactory.getNewNormalFeed(feedName,

Modified: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/ShotokuFeedTagHandler.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/ShotokuFeedTagHandler.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/ShotokuFeedTagHandler.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -10,7 +10,8 @@
 import org.jboss.shotoku.feeds.data.CommentableFeed;
 import org.jboss.shotoku.feeds.FeedFactory;
 import org.jboss.shotoku.feeds.FeedsDescriptor;
-import org.jboss.shotoku.feeds.tools.FeedsConstants;
+import org.jboss.shotoku.feeds.tools.VelocityContextAttributes;
+import org.jboss.shotoku.feeds.tools.FeedDefAttributes;
 import org.jboss.shotoku.feeds.variables.Substitution;
 import org.apache.velocity.VelocityContext;
 import org.apache.log4j.Logger;
@@ -101,7 +102,8 @@
                 // resulting parameter.
                 SearchParameter childParam = generateSearchParameter(child);
 
-                param.getClass().getMethod("add", SearchParameter.class).invoke(param, childParam);
+                param.getClass().getMethod("add",
+                        SearchParameter.class).invoke(param, childParam);
             }
         }
 
@@ -116,13 +118,14 @@
         // Reading all attributes and making the substitution on them.
         Map<String, Object> attributes = getAttributes();
 
-        String template = Tools.toString(attributes.get("template"));
+        String template = Tools.toString(attributes.get(
+                FeedDefAttributes.VELOCITY_TEMPLATE));
         String displayName = Tools.toString(attributes.get(
-                FeedsConstants.DISP_NAME_ATTR));
+                FeedDefAttributes.DISP_NAME));
 
         ContentManager cm = ContentManager.getContentManager(
-                Tools.toString(attributes.get("id")),
-                Tools.toString(attributes.get("prefix")));
+                Tools.toString(FeedDefAttributes.CM_ID),
+                Tools.toString(FeedDefAttributes.CM_PREFIX));
 
         VelocityContext vc = new VelocityContext(attributes);
         FeedsTools.prepareVelocityContext(attributes, vc);
@@ -141,14 +144,16 @@
 
                     org.jboss.shotoku.NodeList list = cm.search(search);
 
-                    String searchNameAttr = Tools.getAttributeValue(searchNode, "name");
+                    String searchNameAttr = Tools.getAttributeValue(searchNode,
+                            "name");
                     if (searchNameAttr == null) {
-                        searchNameAttr = "nodes";
+                        searchNameAttr = VelocityContextAttributes.NODES_LIST;
                     }
 
                     vc.put(searchNameAttr, list);
 
-                    if ("nodes".equals(searchNameAttr)) {
+                    if (VelocityContextAttributes.NODES_LIST.equals(
+                            searchNameAttr)) {
                         nodesNodeList = list;
                     }
 
@@ -174,7 +179,8 @@
         NormalFeed newFeed = FeedFactory.getNewNormalFeed(feedName,
                 displayName, feedType, attributes);
         try {
-            vc.put("link", generateFeedLink(fd, true, feedName, feedType));
+            vc.put(VelocityContextAttributes.LINK,
+                    generateFeedLink(fd, true, feedName, feedType));
 
             // Now that we have type and site, we can render the
             // template.

Modified: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/TagFeedTagHandler.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/TagFeedTagHandler.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tag/TagFeedTagHandler.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -3,8 +3,9 @@
 import org.apache.velocity.VelocityContext;
 import org.jboss.shotoku.feeds.FeedsDescriptor;
 import org.jboss.shotoku.feeds.FeedFactory;
-import org.jboss.shotoku.feeds.data.SpecialFeed;
+import org.jboss.shotoku.feeds.data.special.SpecialFeed;
 import org.jboss.shotoku.feeds.tools.FeedsTools;
+import org.jboss.shotoku.feeds.tools.FeedsConstants;
 import org.jboss.shotoku.feeds.variables.Substitution;
 import org.w3c.dom.Node;
 
@@ -36,7 +37,8 @@
         String feedName = getFeedName();
         String feedType = getFeedType();
 
-        Class feedClass = FeedFactory.getNewSpecialFeedClass(feedType);
+        Class feedClass = FeedFactory.getNewSpecialFeedClass(
+                FeedsConstants.TAGS_SPECIAL_FEED, feedType);
 
         try {
             fd.addSpecialFeed(feedName, feedType,

Added: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tools/FeedDefAttributes.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tools/FeedDefAttributes.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tools/FeedDefAttributes.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -0,0 +1,51 @@
+package org.jboss.shotoku.feeds.tools;
+
+/**
+ * Names of meaningful xml-node attributes in definitions
+ * of feeds.
+ * @author Adam Warski (adamw at aster.pl)
+ */
+public class FeedDefAttributes {
+    /**
+     * Feed name.
+     */
+    public static final String NAME         = "name";
+
+    /**
+     * Feed display name.
+     */
+    public static final String DISP_NAME    = "displayName";
+
+    /**
+     * Content manager id.
+     */
+    public static final String CM_ID        = "id";
+
+    /**
+     * Content manager prefix.
+     */
+    public static final String CM_PREFIX    = "prefix";
+
+    /**
+     * Velocity template to use.
+     */
+    public static final String VELOCITY_TEMPLATE    = "template";
+
+    /**
+     * Base address, which will be prepended to links to feeds.
+     */
+    public static final String BASE_ADDR       = "baseServerAddress";
+
+    /**
+     * Attribute set, which causes a set of attributes to be added
+     * to a feed definition.
+     */
+    public static final String EXTENDS      = "extends";
+
+    /**
+     * Xml node attribute prefix denoting an attribute for which
+     * an instance of the "attribute-value" class should be loaded
+     * and placed in the velocity context.
+     */
+    public static final String CLASS_ATTR_PREFIX = "class-";
+}

Modified: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tools/FeedsConstants.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tools/FeedsConstants.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tools/FeedsConstants.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -7,6 +7,7 @@
  */
 public class FeedsConstants {
     public static final String FEEDS_SERVICE_NAME = "shotoku:service=feeds";
+    public static final String COMMENTS_SERVICE_NAME = "shotoku:service=comments";
 
     /**
      * Node with names ending with this string are parsed and
@@ -15,12 +16,19 @@
     public final static String NODE_ENDING = "-feeds.xml";
 
     /*
+     * Special feed types.
+     */
+    public static final int TAGS_SPECIAL_FEED = 0;
+    public static final int COMMENTS_SPECIAL_FEED = 1;
+
+    /*
      * Tag names.
      */
     public final static String REM_FEED_TAG = "remote-feed";
     public final static String AGG_FEED_TAG = "aggregated-feed";
     public final static String SHO_FEED_TAG = "shotoku-feed";
     public final static String TAG_FEED_TAG = "tag-feed";
+    public final static String COMMENT_FEED_TAG = "comment-feed";
     public final static String ATTRS_TAG    = "attributes";
 
     /*
@@ -72,19 +80,4 @@
      * Variable, for which feed type will be substituted.
      */
     public final static String TYPE_VARIABLE = "${type}";
-
-    /*
-     * Xml node attributes denoting a feed name and display name.
-     */
-    public static final String NAME_ATTR    = "name";
-    public static final String DISP_NAME_ATTR   = "displayName";
-    public static final String BASE_ADDR_ATTR   = "baseServerAddress";
-    public static final String EXTENDS_ATTR = "extends";
-
-    /**
-     * Xml node attribute prefix denoting an attribute for which
-     * an instance of the "attribute-value" class should be loaded
-     * and placed in the velocity context.
-     */
-    public static final String CLASS_ATTR_PREFIX = "class-";
 }

Modified: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tools/FeedsTools.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tools/FeedsTools.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tools/FeedsTools.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -4,7 +4,9 @@
 import org.apache.log4j.Logger;
 import org.jboss.shotoku.feeds.FeedsDescriptor;
 import org.jboss.shotoku.feeds.FeedsService;
+import org.jboss.shotoku.feeds.CommentsService;
 import org.jboss.shotoku.feeds.service.FeedsServiceImpl;
+import org.jboss.shotoku.feeds.service.CommentsServiceImpl;
 import org.jboss.shotoku.ContentManager;
 import org.jboss.shotoku.tools.Tools;
 import org.jboss.mx.util.MBeanProxyExt;
@@ -36,10 +38,10 @@
             Map<String, Object> initial,
             Map<String, String> attributes) {
         for (String key : attributes.keySet()) {
-            if (key.startsWith(FeedsConstants.CLASS_ATTR_PREFIX)) {
+            if (key.startsWith(FeedDefAttributes.CLASS_ATTR_PREFIX)) {
                 try {
                     initial.put(
-                            key.substring(FeedsConstants.CLASS_ATTR_PREFIX.length()),
+                            key.substring(FeedDefAttributes.CLASS_ATTR_PREFIX.length()),
                             Class.forName(attributes.get(key)).newInstance());
                 } catch (Exception e) {
                     log.error("Exception while loading a class to the " +
@@ -115,4 +117,32 @@
             throw new RuntimeException(e);
         }
     }
+
+    private static CommentsService commentsInstance;
+
+    /**
+     * @return An instance of the comments service.
+     */
+    public static CommentsService getCommentsService() {
+        try {
+            if (commentsInstance == null) {
+                if (ContentManager.isEmbedded()) {
+                    // Embedded mode - simply creating a new service instance.
+                    commentsInstance = new CommentsServiceImpl();
+                    commentsInstance.create();
+                    commentsInstance.start();
+                } else {
+                    // Application server mode - creating a proxy to a mbean.
+                    commentsInstance = (CommentsService) MBeanProxyExt.create(
+                            CommentsService.class,
+                            FeedsConstants.COMMENTS_SERVICE_NAME,
+                            MBeanServerLocator.locate());
+                }
+            }
+
+            return commentsInstance;
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
 }

Added: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tools/NodesFeedsProperties.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tools/NodesFeedsProperties.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tools/NodesFeedsProperties.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -0,0 +1,29 @@
+package org.jboss.shotoku.feeds.tools;
+
+/**
+ * Names and values of properties which are set/ read by feeds on
+ * Shotoku nodes (from which feeds are generated).
+ * @author Adam Warski (adamw at aster.pl)
+ */
+public class NodesFeedsProperties {
+    /*
+     * Name and value of a property, which should be set on a comment
+     * node, to indicate that this comment has been accepted and can
+     * be shown in the feed.
+     */
+    public static final String ACCEPTED_COMMENT_NAME   = "accepted";
+    public static final String ACCEPTED_COMMENT_VALUE  = "1";
+    public static final String NOTACCEPTED_COMMENT_VALUE  = "0";
+
+    /**
+     * Name of a property, which should be set on a feed node
+     * to the title of the feed entry.
+     */
+    public static final String TITLE    = "title";
+
+    /**
+     * Name of a property, which should be set on a feed node
+     * to the author of the feed entry.
+     */
+    public static final String AUTHOR   = "author";
+}

Added: labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tools/VelocityContextAttributes.java
===================================================================
--- labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tools/VelocityContextAttributes.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-feeds/src/java/org/jboss/shotoku/feeds/tools/VelocityContextAttributes.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -0,0 +1,18 @@
+package org.jboss.shotoku.feeds.tools;
+
+/**
+ * Names of velocity context attributes which are used in
+ * templates.
+ * @author Adam Warski (adamw at aster.pl)
+ */
+public class VelocityContextAttributes {
+    /**
+     * Primary list of nodes.
+     */
+    public static final String NODES_LIST   = "nodes";
+
+    /**
+     * Link to a feed.
+     */
+    public static final String LINK         = "link";
+}

Modified: labs/shotoku/trunk/shotoku-tags/src/etc/META-INF/persistence.xml
===================================================================
--- labs/shotoku/trunk/shotoku-tags/src/etc/META-INF/persistence.xml	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-tags/src/etc/META-INF/persistence.xml	2006-07-27 19:54:34 UTC (rev 5320)
@@ -7,15 +7,4 @@
             <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
         </properties>
     </persistence-unit>
-
-    <!--<persistence-unit name="tags-noauto">
-        <jta-data-source>java:/LabsDS</jta-data-source>
-        <properties>
-            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
-        </properties>
-
-        <properties>
-            <property name="jboss.entity.manager.factory.jndi.name" value="java:/TagsEMF"/>
-        </properties>
-    </persistence-unit>-->
 </persistence>

Modified: labs/shotoku/trunk/shotoku-tags/src/java/org/jboss/shotoku/tags/service/TagServiceImpl.java
===================================================================
--- labs/shotoku/trunk/shotoku-tags/src/java/org/jboss/shotoku/tags/service/TagServiceImpl.java	2006-07-27 17:33:05 UTC (rev 5319)
+++ labs/shotoku/trunk/shotoku-tags/src/java/org/jboss/shotoku/tags/service/TagServiceImpl.java	2006-07-27 19:54:34 UTC (rev 5320)
@@ -22,8 +22,6 @@
 package org.jboss.shotoku.tags.service;
 
 import java.util.*;
-import java.net.URLEncoder;
-import java.io.UnsupportedEncodingException;
 
 import javax.ejb.Local;
 import javax.persistence.*;
@@ -36,6 +34,7 @@
 import org.jboss.annotation.ejb.Service;
 import org.jboss.annotation.ejb.Depends;
 import org.jboss.shotoku.tools.Constants;
+import org.jboss.shotoku.tools.Tools;
 import org.jboss.shotoku.service.AdministratedServiceImpl;
 import org.jboss.shotoku.service.AdministratedService;
 import org.jboss.shotoku.tags.*;
@@ -546,12 +545,8 @@
     }
 
     public String getFeedLink(FeedType feedType, String data, String type) {
-        try {
-            return "/feeds/tag/" + feedType.toString() + "/"
-                    + URLEncoder.encode(data, "UTF-8") + "/" + type;
-        } catch (UnsupportedEncodingException e) {
-            return "";
-        }
+        return "/feeds/tag/" + feedType.toString() + "/"
+                    + Tools.encodeURL(data) + "/" + type;
     }
 
     public String getFeedLink(FeedType feedType, List<String> dataList,
@@ -565,12 +560,8 @@
             }
         }
 
-        try {
-            return "/feeds/tag/" + feedType.toString() + "/"
-                    + URLEncoder.encode(sb.toString(), "UTF-8") + "/" + type;
-        } catch (UnsupportedEncodingException e) {
-            return "";
-        }
+        return "/feeds/tag/" + feedType.toString() + "/"
+                    + Tools.encodeURL(sb.toString()) + "/" + type;
     }
 
     public List<String> getAllTagsNames() throws TagGetException {




More information about the jboss-svn-commits mailing list