diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/subscriptions/follow.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/subscriptions/follow.get.desc.xml
new file mode 100644
index 0000000000..321348a2a8
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/subscriptions/follow.get.desc.xml
@@ -0,0 +1,8 @@
+
+ Follow
+ Follow a user
+ /api/subscriptions/{userid}/follow/{otheruserid}
+
+ user
+ required
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/subscriptions/followers.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/subscriptions/followers.get.desc.xml
new file mode 100644
index 0000000000..ac57645be0
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/subscriptions/followers.get.desc.xml
@@ -0,0 +1,8 @@
+
+ Followers
+ Returns followers
+ /api/subscriptions/{userid}/followers
+
+ user
+ required
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/subscriptions/followerscount.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/subscriptions/followerscount.get.desc.xml
new file mode 100644
index 0000000000..ff9ca0deca
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/subscriptions/followerscount.get.desc.xml
@@ -0,0 +1,8 @@
+
+ Followers Count
+ Returns the size of followers list
+ /api/subscriptions/{userid}/followers/count
+
+ user
+ required
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/subscriptions/following.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/subscriptions/following.get.desc.xml
new file mode 100644
index 0000000000..d2c6ade0c2
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/subscriptions/following.get.desc.xml
@@ -0,0 +1,8 @@
+
+ Following
+ Returns the following list
+ /api/subscriptions/{userid}/following
+
+ user
+ required
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/subscriptions/followingcount.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/subscriptions/followingcount.get.desc.xml
new file mode 100644
index 0000000000..ac1f94d48f
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/subscriptions/followingcount.get.desc.xml
@@ -0,0 +1,8 @@
+
+ Following Count
+ Returns size of the following list
+ /api/subscriptions/{userid}/following/count
+
+ user
+ required
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/subscriptions/unfollow.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/subscriptions/unfollow.get.desc.xml
new file mode 100644
index 0000000000..8d1da74dd6
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/subscriptions/unfollow.get.desc.xml
@@ -0,0 +1,8 @@
+
+ Follow
+ Follow a user
+ /api/subscriptions/{userid}/unfollow/{otheruserid}
+
+ user
+ required
+
\ No newline at end of file
diff --git a/config/alfresco/web-scripts-application-context.xml b/config/alfresco/web-scripts-application-context.xml
index c59654d1cf..a3111c12b3 100644
--- a/config/alfresco/web-scripts-application-context.xml
+++ b/config/alfresco/web-scripts-application-context.xml
@@ -595,7 +595,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/java/org/alfresco/repo/web/scripts/subscriptions/AbstractSubscriptionServiceWebScript.java b/source/java/org/alfresco/repo/web/scripts/subscriptions/AbstractSubscriptionServiceWebScript.java
new file mode 100644
index 0000000000..6ac6acf066
--- /dev/null
+++ b/source/java/org/alfresco/repo/web/scripts/subscriptions/AbstractSubscriptionServiceWebScript.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2005-2011 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+package org.alfresco.repo.web.scripts.subscriptions;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Date;
+import java.util.List;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.query.PagingRequest;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.security.NoSuchPersonException;
+import org.alfresco.service.cmr.security.PersonService;
+import org.alfresco.service.cmr.subscriptions.PrivateSubscriptionListException;
+import org.alfresco.service.cmr.subscriptions.SubscriptionService;
+import org.alfresco.util.ISO8601DateFormat;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.springframework.extensions.webscripts.AbstractWebScript;
+import org.springframework.extensions.webscripts.WebScriptException;
+import org.springframework.extensions.webscripts.WebScriptRequest;
+import org.springframework.extensions.webscripts.WebScriptResponse;
+
+public abstract class AbstractSubscriptionServiceWebScript extends AbstractWebScript
+{
+ protected SubscriptionService subscriptionService;
+ protected NodeService nodeService;
+ protected PersonService personService;
+
+ public void setSubscriptionService(SubscriptionService subscriptionService)
+ {
+ this.subscriptionService = subscriptionService;
+ }
+
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+ public void setPersonService(PersonService personService)
+ {
+ this.personService = personService;
+ }
+
+ public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException
+ {
+ try
+ {
+ String userId = req.getServiceMatch().getTemplateVars().get("userid");
+ JSONObject obj = executeImpl(userId, req, res);
+
+ if (obj == null)
+ {
+ res.setStatus(204);
+ } else
+ {
+ Writer writer = res.getWriter();
+ obj.write(writer);
+ writer.flush();
+ }
+ } catch (NoSuchPersonException nspe)
+ {
+ throw new WebScriptException(400, "Unknown user '" + nspe.getUserName() + "'!", nspe);
+ } catch (PrivateSubscriptionListException psle)
+ {
+ throw new WebScriptException(403, "Subscription list is private!", psle);
+ } catch (JSONException je)
+ {
+ throw new WebScriptException(500, "Unable to serialize JSON!", je);
+ }
+ }
+
+ public abstract JSONObject executeImpl(String userId, WebScriptRequest req, WebScriptResponse res)
+ throws IOException, JSONException;
+
+ protected int parseNumber(String name, String number, int def)
+ {
+
+ if (number != null && number.length() > 0)
+ {
+ try
+ {
+ return Integer.parseInt(number);
+
+ } catch (NumberFormatException e)
+ {
+ throw new WebScriptException(400, name + " is not a number!", e);
+ }
+ } else
+ {
+ return def;
+ }
+ }
+
+ protected PagingRequest createPagingRequest(WebScriptRequest req)
+ {
+ int skipCount = parseNumber("skipCount", req.getParameter("skipCount"), 0);
+ int maxItems = parseNumber("maxItems", req.getParameter("maxItems"), -1);
+
+ PagingRequest result = new PagingRequest(skipCount, maxItems, null);
+ result.setRequestTotalCountMax(Integer.MAX_VALUE);
+
+ return result;
+ }
+
+ protected JSONObject getUserDetails(String username) throws JSONException
+ {
+ NodeRef node = personService.getPerson(username);
+
+ JSONObject result = new JSONObject();
+ result.put("userName", username);
+ result.put("firstName", nodeService.getProperty(node, ContentModel.PROP_FIRSTNAME));
+ result.put("lastName", nodeService.getProperty(node, ContentModel.PROP_LASTNAME));
+
+ String status = (String) nodeService.getProperty(node, ContentModel.PROP_USER_STATUS);
+ if (status != null)
+ {
+ result.put("userStatus", status);
+ }
+
+ Date statusTime = (Date) nodeService.getProperty(node, ContentModel.PROP_USER_STATUS_TIME);
+ if (statusTime != null)
+ {
+ JSONObject statusTimeJson = new JSONObject();
+ statusTimeJson.put("iso8601", ISO8601DateFormat.format(statusTime));
+ result.put("userStatusTime", statusTimeJson);
+ }
+
+ return result;
+ }
+
+ protected JSONArray getUserArray(List usernames) throws JSONException
+ {
+ JSONArray result = new JSONArray();
+
+ if (usernames != null)
+ {
+ for (String username : usernames)
+ {
+ result.put(getUserDetails(username));
+ }
+ }
+
+ return result;
+ }
+}
diff --git a/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowGet.java b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowGet.java
new file mode 100644
index 0000000000..e6342e9603
--- /dev/null
+++ b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowGet.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2005-2011 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+package org.alfresco.repo.web.scripts.subscriptions;
+
+import java.io.IOException;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.springframework.extensions.webscripts.WebScriptRequest;
+import org.springframework.extensions.webscripts.WebScriptResponse;
+
+public class SubscriptionServiceFollowGet extends AbstractSubscriptionServiceWebScript
+{
+ public JSONObject executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException,
+ JSONException
+ {
+ String otherUser = req.getServiceMatch().getTemplateVars().get("otheruserid");
+
+ subscriptionService.follow(userId, otherUser);
+
+ return null;
+ }
+}
diff --git a/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowersCountGet.java b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowersCountGet.java
new file mode 100644
index 0000000000..4b53e6a50e
--- /dev/null
+++ b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowersCountGet.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2005-2011 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+package org.alfresco.repo.web.scripts.subscriptions;
+
+import java.io.IOException;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.springframework.extensions.webscripts.WebScriptRequest;
+import org.springframework.extensions.webscripts.WebScriptResponse;
+
+public class SubscriptionServiceFollowersCountGet extends AbstractSubscriptionServiceWebScript
+{
+ public JSONObject executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException,
+ JSONException
+ {
+ int count = subscriptionService.getFollowersCount(userId);
+
+ JSONObject obj = new JSONObject();
+ obj.put("count", count);
+
+ return obj;
+ }
+}
diff --git a/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowersGet.java b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowersGet.java
new file mode 100644
index 0000000000..758790ae6f
--- /dev/null
+++ b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowersGet.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2005-2011 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+package org.alfresco.repo.web.scripts.subscriptions;
+
+import java.io.IOException;
+
+import org.alfresco.service.cmr.subscriptions.PagingFollowingResults;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.springframework.extensions.webscripts.WebScriptRequest;
+import org.springframework.extensions.webscripts.WebScriptResponse;
+
+public class SubscriptionServiceFollowersGet extends AbstractSubscriptionServiceWebScript
+{
+ public JSONObject executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException,
+ JSONException
+ {
+ PagingFollowingResults result = subscriptionService.getFollowers(userId, createPagingRequest(req));
+
+ JSONObject obj = new JSONObject();
+ obj.put("people", getUserArray(result.getPage()));
+ obj.put("hasMoreItems", result.hasMoreItems());
+ if (result.getTotalResultCount() != null)
+ {
+ obj.put("totalCount", result.getTotalResultCount().getFirst());
+ }
+
+ return obj;
+ }
+}
diff --git a/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowingCountGet.java b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowingCountGet.java
new file mode 100644
index 0000000000..ad766e5de3
--- /dev/null
+++ b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowingCountGet.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2005-2011 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+package org.alfresco.repo.web.scripts.subscriptions;
+
+import java.io.IOException;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.springframework.extensions.webscripts.WebScriptRequest;
+import org.springframework.extensions.webscripts.WebScriptResponse;
+
+public class SubscriptionServiceFollowingCountGet extends AbstractSubscriptionServiceWebScript
+{
+ public JSONObject executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException,
+ JSONException
+ {
+ int count = subscriptionService.getFollowingCount(userId);
+
+ JSONObject obj = new JSONObject();
+ obj.put("count", count);
+
+ return obj;
+ }
+}
diff --git a/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowingGet.java b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowingGet.java
new file mode 100644
index 0000000000..e88beecfdd
--- /dev/null
+++ b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceFollowingGet.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2005-2011 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+package org.alfresco.repo.web.scripts.subscriptions;
+
+import java.io.IOException;
+
+import org.alfresco.service.cmr.subscriptions.PagingFollowingResults;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.springframework.extensions.webscripts.WebScriptRequest;
+import org.springframework.extensions.webscripts.WebScriptResponse;
+
+public class SubscriptionServiceFollowingGet extends AbstractSubscriptionServiceWebScript
+{
+ public JSONObject executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException,
+ JSONException
+ {
+ PagingFollowingResults result = subscriptionService.getFollowing(userId, createPagingRequest(req));
+
+ JSONObject obj = new JSONObject();
+ obj.put("people", getUserArray(result.getPage()));
+ obj.put("hasMoreItems", result.hasMoreItems());
+ if (result.getTotalResultCount() != null)
+ {
+ obj.put("totalCount", result.getTotalResultCount().getFirst());
+ }
+
+ return obj;
+ }
+}
diff --git a/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceUnfollowGet.java b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceUnfollowGet.java
new file mode 100644
index 0000000000..780fefe993
--- /dev/null
+++ b/source/java/org/alfresco/repo/web/scripts/subscriptions/SubscriptionServiceUnfollowGet.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2005-2011 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+package org.alfresco.repo.web.scripts.subscriptions;
+
+import java.io.IOException;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.springframework.extensions.webscripts.WebScriptRequest;
+import org.springframework.extensions.webscripts.WebScriptResponse;
+
+public class SubscriptionServiceUnfollowGet extends AbstractSubscriptionServiceWebScript
+{
+ public JSONObject executeImpl(String userId, WebScriptRequest req, WebScriptResponse res) throws IOException,
+ JSONException
+ {
+ String otherUser = req.getServiceMatch().getTemplateVars().get("otheruserid");
+
+ subscriptionService.unfollow(userId, otherUser);
+
+ return null;
+ }
+}