Permalink
Browse files

Merge branch 'master' of git://github.com/simong/open-experiments

* 'master' of git://github.com/simong/open-experiments:
  Fixed parsing of replies in search result processors.
  Added from filter to chat messages.
  Made small adjustments so comments and discussions now use the new routing system.
  • Loading branch information...
2 parents 1bfb3f9 + cf48d02 commit 4a15b6034cafcb532405c022974d81da9ec6d787 nicolaas committed Sep 16, 2009
Showing with 331 additions and 86 deletions.
  1. +6 −0 .../bundles/discussion/src/main/java/org/sakaiproject/kernel/api/discussion/DiscussionConstants.java
  2. +20 −4 ...el/bundles/discussion/src/main/java/org/sakaiproject/kernel/api/discussion/DiscussionManager.java
  3. +15 −0 ...rnel/bundles/discussion/src/main/java/org/sakaiproject/kernel/api/discussion/DiscussionTypes.java
  4. +25 −32 ...ests/osgikernel/bundles/discussion/src/main/java/org/sakaiproject/kernel/api/discussion/Post.java
  5. +44 −3 ...el/bundles/discussion/src/main/java/org/sakaiproject/kernel/discussion/DiscussionManagerImpl.java
  6. +44 −0 ...gikernel/bundles/discussion/src/main/java/org/sakaiproject/kernel/discussion/DiscussionRoute.java
  7. +102 −0 ...ikernel/bundles/discussion/src/main/java/org/sakaiproject/kernel/discussion/DiscussionRouter.java
  8. +0 −7 ...gikernel/bundles/discussion/src/main/resources/SLING-INF/content/var/discussion/initialposts.json
  9. +1 −1 ...iscussion/src/main/resources/SLING-INF/content/var/search/discussions/initialdiscussionposts.json
  10. +1 −1 ...rnel/bundles/discussion/src/main/resources/SLING-INF/content/var/search/discussions/threaded.json
  11. +5 −1 ...ikernel/bundles/messaging/src/main/java/org/sakaiproject/kernel/api/message/MessageConstants.java
  12. +25 −5 ...undles/messaging/src/main/java/org/sakaiproject/kernel/message/MessageSearchPropertyProvider.java
  13. +7 −3 ...bundles/messaging/src/main/java/org/sakaiproject/kernel/message/MessageSearchResultProcessor.java
  14. +3 −1 ...ikernel/bundles/messaging/src/main/java/org/sakaiproject/kernel/message/MessagingServiceImpl.java
  15. +1 −1 ...sts/osgikernel/bundles/messaging/src/main/resources/SLING-INF/content/_user/message/chat/all.json
  16. +1 −1 .../osgikernel/bundles/messaging/src/main/resources/SLING-INF/content/_user/message/chat/unread.json
  17. +29 −24 ...osgikernel/bundles/personal/src/main/java/org/sakaiproject/kernel/api/personal/PersonalUtils.java
  18. +1 −1 slingtests/osgikernel/bundles/search/src/main/java/org/sakaiproject/kernel/search/SearchServlet.java
  19. +1 −1 slingtests/osgikernel/bundles/site/src/main/java/org/sakaiproject/kernel/site/SiteServiceImpl.java
@@ -40,6 +40,10 @@
* Holds the value of people who editted this message.
*/
public static final String PROP_EDITEDBY = "sakai:editedby";
+ /**
+ * Holds the profile info for the editters.
+ */
+ public static final String PROP_EDITEDBYPROFILES = "sakai:editedbyprofiles";
/**
* Holds the ID of the message we want to reply on.
@@ -57,4 +61,6 @@
*/
public static final String PROP_NOTIFICATION = "sakai:notification";
+ public static final String PROP_NOTIFY_ADDRESS = "sakai:notificationaddress";
+
}
@@ -25,12 +25,28 @@
public interface DiscussionManager {
/**
* Goes trough the repository to look for a message with an id and a marker.
- * @param messageId The ID of the message to look for.
- * @param marker The marker it should have.
+ *
+ * @param messageId
+ * The ID of the message to look for.
+ * @param marker
+ * The marker it should have.
* @param session
- * @param path An optional path where you want to look in.
+ * @param path
+ * An optional path where you want to look in.
* @return
* @throws MessagingException
*/
- public Node findMessage(String messageId, String marker, Session session, String path) throws MessagingException;
+ public Node findMessage(String messageId, String marker, Session session, String path)
+ throws MessagingException;
+
+ /**
+ * Looks in the entire repository to find a sakai/settings file of a certain type and
+ * marker.
+ *
+ * @param marker
+ * @param session
+ * @param type
+ * @return
+ */
+ public Node findSettings(String marker, Session session, String type);
}
@@ -0,0 +1,15 @@
+package org.sakaiproject.kernel.api.discussion;
+
+public enum DiscussionTypes {
+ discussion, comment;
+
+ public static boolean hasValue(String s) {
+ DiscussionTypes[] types = values();
+ for (DiscussionTypes t : types) {
+ if (t.name().equalsIgnoreCase(s)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
@@ -91,9 +91,11 @@ public void setPostId(String postId) {
*/
public boolean checkEdit() {
try {
- AccessControlManager acm = AccessControlUtil.getAccessControlManager(node.getSession());
+ AccessControlManager acm = AccessControlUtil.getAccessControlManager(node
+ .getSession());
Privilege write = acm.privilegeFromName(ACLUtils.WRITE_GRANTED.substring(2));
- Privilege modProps = acm.privilegeFromName(ACLUtils.MODIFY_PROPERTIES_GRANTED.substring(2));
+ Privilege modProps = acm.privilegeFromName(ACLUtils.MODIFY_PROPERTIES_GRANTED
+ .substring(2));
Privilege[] privileges = { write, modProps };
if (acm.hasPrivileges(node.getPath(), privileges)) {
return true;
@@ -118,12 +120,15 @@ public boolean checkEdit() {
*/
public boolean checkDelete() {
try {
- AccessControlManager acm = AccessControlUtil.getAccessControlManager(node.getSession());
+ AccessControlManager acm = AccessControlUtil.getAccessControlManager(node
+ .getSession());
Privilege write = acm.privilegeFromName(ACLUtils.WRITE_GRANTED.substring(2));
- Privilege modProps = acm.privilegeFromName(ACLUtils.MODIFY_PROPERTIES_GRANTED.substring(2));
- Privilege deleteNode = acm.privilegeFromName(ACLUtils.REMOVE_NODE_GRANTED.substring(2));
- Privilege deleteChildNode = acm.privilegeFromName(ACLUtils.REMOVE_CHILD_NODES_GRANTED
+ Privilege modProps = acm.privilegeFromName(ACLUtils.MODIFY_PROPERTIES_GRANTED
+ .substring(2));
+ Privilege deleteNode = acm.privilegeFromName(ACLUtils.REMOVE_NODE_GRANTED
.substring(2));
+ Privilege deleteChildNode = acm
+ .privilegeFromName(ACLUtils.REMOVE_CHILD_NODES_GRANTED.substring(2));
Privilege[] privileges = { write, modProps, deleteNode, deleteChildNode };
if (acm.hasPrivileges(node.getPath(), privileges)) {
return true;
@@ -141,9 +146,8 @@ public boolean checkDelete() {
return false;
}
- public void outputPostAsJSON(JSONWriter writer) throws JSONException, RepositoryException {
- LOG.info("Outputting post with ID: " + getPostId());
-
+ public void outputPostAsJSON(JSONWriter writer) throws JSONException,
+ RepositoryException {
boolean canEdit = checkEdit();
boolean canDelete = checkDelete();
@@ -172,31 +176,18 @@ public void outputPostAsJSON(JSONWriter writer) throws JSONException, Repository
writer.key("canDelete");
writer.value(canDelete);
- // List of all the people who have edited this post.
+ // Show profile of editters.
if (node.hasProperty(DiscussionConstants.PROP_EDITEDBY)) {
- Property editedByProperty = getNode().getProperty(DiscussionConstants.PROP_EDITEDBY);
- Value[] editedBy;
- try {
- editedBy = editedByProperty.getValues();
- } catch (Exception e) {
- editedBy = new Value[1];
- editedBy[0] = editedByProperty.getValue();
- }
- writer.key("editters");
+ String edittedBy[] = StringUtils.split(getNode().getProperty(
+ DiscussionConstants.PROP_EDITEDBY).getString(), ',');
+
+ writer.key(DiscussionConstants.PROP_EDITEDBYPROFILES);
writer.array();
- for (int i = 0; i < editedBy.length; i++) {
- String[] s = StringUtils.split(editedBy[i].getString(), '|');
+ for (int i = 0; i < edittedBy.length; i++) {
writer.object();
-
- writer.key("profile");
- String profilePath = PersonalUtils.getProfilePath(getNode().getProperty(
- MessageConstants.PROP_SAKAI_FROM).getString());
- Node profileNode = JcrUtils.getFirstExistingNode(getNode().getSession(), profilePath);
- ExtendedJSONWriter.writeNodeToWriter(writer, profileNode);
- writer.key("date");
- writer.value(s[1]);
-
+ PersonalUtils.writeUserInfo(getNode().getSession(), edittedBy[i], writer,
+ "editter");
writer.endObject();
}
writer.endArray();
@@ -205,7 +196,8 @@ public void outputPostAsJSON(JSONWriter writer) throws JSONException, Repository
writer.key("profile");
String profilePath = PersonalUtils.getProfilePath(getNode().getProperty(
MessageConstants.PROP_SAKAI_FROM).getString());
- Node profileNode = JcrUtils.getFirstExistingNode(getNode().getSession(), profilePath);
+ Node profileNode = JcrUtils.getFirstExistingNode(getNode().getSession(),
+ profilePath);
ExtendedJSONWriter.writeNodeToWriter(writer, profileNode);
writer.endObject();
@@ -219,7 +211,8 @@ public void outputPostAsJSON(JSONWriter writer) throws JSONException, Repository
}
}
- public void outputChildrenAsJSON(JSONWriter writer) throws JSONException, RepositoryException {
+ public void outputChildrenAsJSON(JSONWriter writer) throws JSONException,
+ RepositoryException {
LOG.info("this post {} has {} children", getPostId(), getChildren().size());
for (Post p : children) {
p.outputPostAsJSON(writer);
@@ -19,6 +19,7 @@
import org.sakaiproject.kernel.api.discussion.DiscussionManager;
import org.sakaiproject.kernel.api.message.MessagingException;
+import org.sakaiproject.kernel.util.PathUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -53,12 +54,20 @@
public Node findMessage(String messageId, String marker, Session session, String path)
throws MessagingException {
- if (path == null) { path = "/"; }
+ if (path == null) {
+ path = "/";
+ }
if (!path.startsWith("/")) {
- throw new MessagingException(500, "Path should be an absolute path starting with a '/'");
+ throw new MessagingException(500,
+ "Path should be an absolute path starting with a '/'");
+ }
+ if (path.endsWith("/")) {
+ path = path.substring(0, path.length());
}
- String queryString = "/" + path + "/*[@sling:resourceType=\"sakai/message\" and @sakai:type='discussion' and @sakai:id='"
+ String queryString = "/"
+ + path
+ + "//*[@sling:resourceType=\"sakai/message\" and @sakai:type='discussion' and @sakai:id='"
+ messageId + "' and @sakai:marker='" + marker + "']";
LOG.info("Trying to find message with query: {}", queryString);
try {
@@ -80,6 +89,38 @@ public Node findMessage(String messageId, String marker, Session session, String
LOG.warn("No message with ID '{}' and marker '{}' found.", messageId, marker);
return null;
+ }
+ /**
+ *
+ * {@inheritDoc}
+ * @see org.sakaiproject.kernel.api.discussion.DiscussionManager#findSettings(java.lang.String, javax.jcr.Session, java.lang.String)
+ */
+ public Node findSettings(String marker, Session session, String type) {
+ if (type == null || type == "") {
+ type = "discussion";
+ }
+ String queryString = "//*[@sling:resourceType=\"sakai/settings\" and @sakai:type='"
+ + type + "' and @sakai:marker='" + marker + "']";
+ LOG.info("Trying to find settings with query: {}", queryString);
+ try {
+ QueryManager queryManager = session.getWorkspace().getQueryManager();
+ Query query = queryManager.createQuery(queryString, Query.XPATH);
+ QueryResult result = query.execute();
+ NodeIterator nodeIterator = result.getNodes();
+
+ while (nodeIterator.hasNext()) {
+ Node n = nodeIterator.nextNode();
+ return n;
+ }
+
+ } catch (RepositoryException e) {
+ LOG.warn("Unable to check for settings of type '{}' and marker '{}'", type, marker);
+ e.printStackTrace();
+ }
+
+ LOG.warn("No settings with type '{}' and marker '{}' found.", type, marker);
+
+ return null;
}
}
@@ -0,0 +1,44 @@
+package org.sakaiproject.kernel.discussion;
+
+import org.sakaiproject.kernel.api.message.MessageRoute;
+import org.sakaiproject.kernel.util.StringUtils;
+
+public class DiscussionRoute implements MessageRoute {
+
+ private static final String INTERNAL = "internal";
+ private String transport;
+ private String rcpt;
+
+ // TODO Just use MessageRouteImpl ?
+ /**
+ * @param r
+ */
+ public DiscussionRoute(String r) {
+ String[] routing = StringUtils.split(r, ':', 2);
+ if (routing == null || routing.length == 0) {
+ transport = null;
+ rcpt = null;
+ } else if (routing.length == 1) {
+ transport = INTERNAL;
+ rcpt = routing[0];
+ } else {
+ transport = routing[0];
+ rcpt = routing[1];
+ }
+ }
+
+ /**
+ * @return the transport
+ */
+ public String getTransport() {
+ return transport;
+ }
+
+ /**
+ * @return the rcpt
+ */
+ public String getRcpt() {
+ return rcpt;
+ }
+
+}
@@ -0,0 +1,102 @@
+package org.sakaiproject.kernel.discussion;
+
+import org.sakaiproject.kernel.api.discussion.DiscussionConstants;
+import org.sakaiproject.kernel.api.discussion.DiscussionManager;
+import org.sakaiproject.kernel.api.discussion.DiscussionTypes;
+import org.sakaiproject.kernel.api.message.MessageConstants;
+import org.sakaiproject.kernel.api.message.MessageRoute;
+import org.sakaiproject.kernel.api.message.MessageRouter;
+import org.sakaiproject.kernel.api.message.MessageRoutes;
+import org.sakaiproject.kernel.message.listener.MessageRouteImpl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.RepositoryException;
+import javax.jcr.ValueFormatException;
+
+/**
+ *
+ * @scr.component inherit="true" label="DiscussionRouter" immediate="true"
+ * @scr.service interface="org.sakaiproject.kernel.api.message.MessageRouter"
+ * @scr.property name="service.description"
+ * value="Manages Routing for the discussion posts."
+ * @scr.property name="service.vendor" value="The Sakai Foundation"
+ * @scr.reference name="DiscussionManager"
+ * interface="org.sakaiproject.kernel.api.discussion.DiscussionManager"
+ */
+public class DiscussionRouter implements MessageRouter {
+
+ private DiscussionManager discussionManager;
+
+ protected void bindDiscussionManager(DiscussionManager discussionManager) {
+ this.discussionManager = discussionManager;
+ }
+
+ protected void unbindDiscussionManager(DiscussionManager discussionManager) {
+ this.discussionManager = null;
+ }
+
+ public int getPriority() {
+ return 0;
+ }
+
+ public void route(Node n, MessageRoutes routing) {
+ List<MessageRoute> toRemove = new ArrayList<MessageRoute>();
+ List<MessageRoute> toAdd = new ArrayList<MessageRoute>();
+
+ // Check if this message is a discussion message.
+ try {
+ if (n.hasProperty(MessageConstants.PROP_SAKAI_TYPE)
+ && n.hasProperty(DiscussionConstants.PROP_MARKER)
+ && DiscussionTypes.hasValue(n.getProperty(MessageConstants.PROP_SAKAI_TYPE)
+ .getString())) {
+
+ // This is a discussion message, find the settings file for it.
+ String marker = n.getProperty(DiscussionConstants.PROP_MARKER).getString();
+ String type = n.getProperty(MessageConstants.PROP_SAKAI_TYPE).getString();
+
+ Node settings = discussionManager.findSettings(marker, n.getSession(), type);
+ if (settings != null
+ && settings.hasProperty(DiscussionConstants.PROP_NOTIFICATION)) {
+ boolean sendMail = settings.getProperty(DiscussionConstants.PROP_NOTIFICATION)
+ .getBoolean();
+ if (sendMail && settings.hasProperty(DiscussionConstants.PROP_NOTIFY_ADDRESS)) {
+ String address = settings
+ .getProperty(DiscussionConstants.PROP_NOTIFY_ADDRESS).getString();
+ toAdd.add(new DiscussionRoute("internal:" + address));
+
+ }
+ }
+
+ }
+ } catch (ValueFormatException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (PathNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (RepositoryException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ for (MessageRoute route : routing) {
+ if (DiscussionTypes.hasValue(route.getTransport())) {
+ toAdd.add(new DiscussionRoute("internal:" + route.getRcpt()));
+ toRemove.add(route);
+ }
+ }
+ // Add the new routes
+ for (MessageRoute route : toAdd) {
+ routing.add(route);
+ }
+ // Remove the discussion route (if there is any).
+ for (MessageRoute route : toRemove) {
+ routing.remove(route);
+ }
+ }
+
+}
Oops, something went wrong.

0 comments on commit 4a15b60

Please sign in to comment.