diff --git a/.travis.yml b/.travis.yml
index 6d30f677..9d7df2c3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,8 +1,41 @@
language: java
+
+# use the container build system
+sudo: false
+
jdk:
- - oraclejdk7
- - openjdk6
- - openjdk7
+- oraclejdk7
+#- openjdk6
+#- openjdk7
after_success:
- - mvn -DserviceJobId=$TRAVIS_JOB_ID clean cobertura:cobertura coveralls:cobertura -Dcobertura.report.format=xml
+- mvn -DserviceJobId=$TRAVIS_JOB_ID cobertura:cobertura coveralls:cobertura package
+ -Dcobertura.report.format=xml
+
+env:
+ global:
+ - secure: OPka1kcKQuWnfZHzPe8bUxOHF4fPI69J9h4bPy95Omg/IrFrvGHPuhpNWRvz2GbGTu9hcN8s2POlBoFAKBk2DFJtNLgORJrll1c/N1+OWEBmfnpaxyp5V8JmcxqISJDwPA4MD5Os+ezzMN2/VXsTaImqnHd43nY4+3K8L1o4WD8=
+ - secure: N2eLGAMFSWFHgba6i9AW7agX6sIn/fWeF6ELWceTSwUi8ZN18tQqtUgcOGnlLJZPI5mHrqyAMSynxVh81ITaaSHdqRYLMyXnq2yGEG6UC9Ptw3OPf8DgyuDG9bbvMHsEtatJPy7iA1Ltn5KpZmVOkHy+1+BEoOG2G0TyaHpJJXE=
+
+before_deploy:
+ - "tar cvfz buddycloud-server-java.tgz target/channelserver-jar-with-dependencies.jar README.md postgres manual"
+ - "shasum -a 256 buddycloud-server-java.tgz > file.hashes"
+deploy:
+- provider: bintray
+ file: ".travis/bintray.json"
+ user: "$BINTRAY_USER"
+ key: "$BINTRAY_API_KEY"
+ skip_cleanup: true
+ on:
+ branch: "master"
+- provider: releases
+ skip_cleanup: true
+ api_key: "GITHUB OAUTH TOKEN... to add later"
+ file:
+ - "README.md"
+ - "target"
+ - "manual"
+ - "postgres"
+ on:
+ tags: true
+ branch: "master"
diff --git a/.travis/bintray.json b/.travis/bintray.json
new file mode 100644
index 00000000..06059445
--- /dev/null
+++ b/.travis/bintray.json
@@ -0,0 +1,34 @@
+{
+ "package": {
+ "name": "builds",
+ "repo": "buddycloud-server-java",
+ "subject": "buddycloud",
+ "desc": "master branch commits built by Travis-CI",
+ "website_url": "https://github.com/buddycloud/buddycloud-server-java",
+ "issue_tracker_url": "https://github.com/buddycloud/buddycloud-server-java/issues",
+ "vcs_url": "https://github.com/buddycloud/buddycloud-server-java.git",
+ "github_use_tag_release_notes": true,
+ "github_release_notes_file": "RELEASE.txt",
+ "licenses": ["Apache 2.0"],
+ "public_download_numbers": false,
+ "public_stats": false
+ },
+ "version": {
+ "name": "latest",
+ "desc": "master branch commits built by Travis-CI",
+ "gpgSign": false
+ },
+ "files": [
+ {
+ "includePattern": "buddycloud-server-java.tgz",
+ "uploadPattern": "buddycloud-server-java.tgz",
+ "matrixParams": { "override": 1 }
+ },
+ {
+ "includePattern": "file.hashes",
+ "uploadPattern": "file.hashes",
+ "matrixParams": { "override": 1 }
+ }
+ ],
+ "publish": true
+}
diff --git a/README.md b/README.md
index b81e4ed6..69b98ec2 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ A buddycloud server written in Java, implementing the [buddycloud channels](http
Note this points to the main buddycloud repository for the java server.
-[](https://travis-ci.org/buddycloud/buddycloud-server-java) [](https://coveralls.io/r/buddycloud/buddycloud-server-java)
+[](https://travis-ci.org/buddycloud/buddycloud-server-java) [](https://coveralls.io/r/buddycloud/buddycloud-server-java) [  ](https://bintray.com/buddycloud/buddycloud-server-java/builds/_latestVersion)
# Manual pages
diff --git a/manual/deployment.md b/manual/deployment.md
index e4557407..7668f538 100644
--- a/manual/deployment.md
+++ b/manual/deployment.md
@@ -13,7 +13,7 @@ Configuration to be set as per [configuration page](https://github.com/buddyclou
## Docker
```
-docker run -d buddycloud/channelserver
+docker run -d buddycloud/channel-server
```
Configuration can be provided by mounting a data volume or via a database environment variable. See the [configuration page](https://github.com/buddycloud/buddycloud-server-java/blob/master/manual/configuration.md) for database instructions.
diff --git a/pom.xml b/pom.xml
index 373e7652..c23cb141 100644
--- a/pom.xml
+++ b/pom.xml
@@ -129,7 +129,7 @@
commons-collections
commons-collections
- 3.2.1
+ 3.2.2
nl.jqno.equalsverifier
diff --git a/src/main/java/org/buddycloud/channelserver/channel/ChannelManagerImpl.java b/src/main/java/org/buddycloud/channelserver/channel/ChannelManagerImpl.java
index 945fa76c..f5bc5281 100644
--- a/src/main/java/org/buddycloud/channelserver/channel/ChannelManagerImpl.java
+++ b/src/main/java/org/buddycloud/channelserver/channel/ChannelManagerImpl.java
@@ -113,9 +113,9 @@ public ResultSet getSubscriptionChanges(JID user, Date startDa
}
@Override
- public CloseableIterator getNodeItems(String nodeId, String afterItemId, int count)
+ public CloseableIterator getNodeItems(String nodeId, String afterItemId, int count, boolean parentOnly)
throws NodeStoreException {
- return nodeStore.getNodeItems(nodeId, afterItemId, count);
+ return nodeStore.getNodeItems(nodeId, afterItemId, count, parentOnly);
}
@Override
@@ -125,8 +125,8 @@ public CloseableIterator getNodeItems(String nodeId) throws NodeStoreE
@Override
public ClosableIteratorImpl getNodeItemReplies(String nodeId, String itemId,
- String afterItemId, int limit) throws NodeStoreException {
- return nodeStore.getNodeItemReplies(nodeId, itemId, afterItemId, limit);
+ String afterItemId, boolean after, int limit) throws NodeStoreException {
+ return nodeStore.getNodeItemReplies(nodeId, itemId, afterItemId, after, limit);
}
@Override
@@ -152,8 +152,8 @@ public CloseableIterator getNewNodeItemsForUser(JID user, Date startDa
}
@Override
- public int countNodeItems(String nodeId) throws NodeStoreException {
- return nodeStore.countNodeItems(nodeId);
+ public int countNodeItems(String nodeId, boolean parentOnly) throws NodeStoreException {
+ return nodeStore.countNodeItems(nodeId, parentOnly);
}
public boolean isCachedNode(String nodeId) throws NodeStoreException {
diff --git a/src/main/java/org/buddycloud/channelserver/db/NodeStore.java b/src/main/java/org/buddycloud/channelserver/db/NodeStore.java
index d34422e2..47d9c029 100644
--- a/src/main/java/org/buddycloud/channelserver/db/NodeStore.java
+++ b/src/main/java/org/buddycloud/channelserver/db/NodeStore.java
@@ -234,10 +234,11 @@ ResultSet getUserMembershipsWithConfiguration(J
* @param afterNodeId the itemId after which to retrieve items (exclusive, based on modified
* date).
* @param count the maximum number of records to return.
+ * @param boolean whether to only retrieve parent items (i.e. no comments/replies)
* @return an {@link Iterator} of the node entries.
* @throws NodeStoreException
*/
- CloseableIterator getNodeItems(String nodeId, String afterItemId, int count) throws NodeStoreException;
+ CloseableIterator getNodeItems(String nodeId, String afterItemId, int count, boolean parentOnly) throws NodeStoreException;
/**
* Get node items between two dates
@@ -267,7 +268,7 @@ ResultSet getUserMembershipsWithConfiguration(J
* @return
* @throws NodeStoreException
*/
- ClosableIteratorImpl getNodeItemReplies(String nodeId, String itemId, String afterItemId, int limit) throws NodeStoreException;
+ ClosableIteratorImpl getNodeItemReplies(String nodeId, String itemId, String rsmItemId, boolean after, int limit) throws NodeStoreException;
/**
* Get a count of the number of replies to an item
@@ -339,10 +340,11 @@ CloseableIterator getRecentItems(JID user, Date since, int maxPerNode,
* Retrieves the number of items within a node.
*
* @param nodeId the node id from which to retrieve the item count.
+ * @param parentOnly whether to include post item replies/comments in count
* @return the entries count.
* @throws NodeStoreException
*/
- int countNodeItems(String nodeId) throws NodeStoreException;
+ int countNodeItems(String nodeId, boolean parentOnly) throws NodeStoreException;
/**
* Retrieves a single node item by the node item id.
diff --git a/src/main/java/org/buddycloud/channelserver/db/jdbc/JDBCNodeStore.java b/src/main/java/org/buddycloud/channelserver/db/jdbc/JDBCNodeStore.java
index 1806833d..5b60ca48 100644
--- a/src/main/java/org/buddycloud/channelserver/db/jdbc/JDBCNodeStore.java
+++ b/src/main/java/org/buddycloud/channelserver/db/jdbc/JDBCNodeStore.java
@@ -401,7 +401,29 @@ public ResultSet getAffiliationChanges(JID user, Date startDate
@Override
public ResultSet getUserMemberships(JID jid) throws NodeStoreException {
- return getUserMemberships(jid, false);
+ PreparedStatement stmt = null;
+ try {
+ stmt = conn.prepareStatement(dialect.selectUserMemberships());
+ stmt.setString(1, jid.toBareJID());
+ java.sql.ResultSet rs = stmt.executeQuery();
+
+ ArrayList result = new ArrayList();
+ while (rs.next()) {
+ JID inviter = null;
+ if (null != rs.getString(6)) {
+ inviter = new JID(rs.getString(6));
+ }
+ NodeMembershipImpl membership =
+ new NodeMembershipImpl(rs.getString(1), new JID(rs.getString(2)), new JID(rs.getString(3)),
+ Subscriptions.valueOf(rs.getString(4)), Affiliations.valueOf(rs.getString(5)), inviter, rs.getTimestamp(7));
+ result.add(membership);
+ }
+ return new ResultSetImpl(result);
+ } catch (SQLException e) {
+ throw new NodeStoreException(e);
+ } finally {
+ close(stmt); // Will implicitly close the resultset if required
+ }
}
@Override
@@ -473,7 +495,7 @@ private static String getCollectionStatement(int collectionLength) {
public ResultSet getUserMemberships(JID jid, boolean ephemeral) throws NodeStoreException {
PreparedStatement stmt = null;
try {
- String sql = dialect.selectUserMemberships();
+ String sql = dialect.selectUserMembershipsFilteredByEphemeral();
String replace = "IS NULL OR \"node_config\".\"value\" != 'true'";
if (ephemeral) {
replace = "= 'true'";
@@ -837,7 +859,7 @@ public ResultSet getNodeSubscriptionListeners() throws NodeSto
}
@Override
- public CloseableIterator getNodeItems(String nodeId, String afterItemId, int count) throws NodeStoreException {
+ public CloseableIterator getNodeItems(String nodeId, String afterItemId, int count, boolean parentOnly) throws NodeStoreException {
NodeItem afterItem = null;
PreparedStatement stmt = null;
@@ -847,16 +869,23 @@ public CloseableIterator getNodeItems(String nodeId, String afterItemI
}
String countSQL = "";
-
if (count > -1) {
countSQL = " OFFSET 0 LIMIT " + count;
} else if (count < -1) {
throw new IllegalArgumentException("Invalid value for parameter count: " + count);
}
-
+
+ String parentOnlySubstitution = "";
+ if (parentOnly) {
+ parentOnlySubstitution = " AND \"in_reply_to\" IS NULL ";
+ }
+
+ String query = null;
try {
if (afterItem == null) {
- stmt = conn.prepareStatement(dialect.selectItemsForNode() + countSQL);
+ query = dialect.selectItemsForNode()
+ .replace("%parentOnly%", parentOnlySubstitution) + countSQL;
+ stmt = conn.prepareStatement(query);
stmt.setString(1, nodeId);
java.sql.ResultSet rs = stmt.executeQuery();
@@ -871,7 +900,9 @@ public NodeItem convertRow(java.sql.ResultSet rs) throws SQLException {
}
});
} else {
- stmt = conn.prepareStatement(dialect.selectItemsForNodeBeforeDate() + countSQL);
+ query = dialect.selectItemsForNodeBeforeDate()
+ .replace("%parentOnly%", parentOnlySubstitution) + countSQL;
+ stmt = conn.prepareStatement(query);
stmt.setString(1, nodeId);
stmt.setTimestamp(2, new java.sql.Timestamp(afterItem.getUpdated().getTime()));
stmt.setTimestamp(3, new java.sql.Timestamp(afterItem.getUpdated().getTime()));
@@ -1132,20 +1163,27 @@ public CloseableIterator getRecentItems(JID user, Date since, int maxP
@Override
public CloseableIterator getNodeItems(String nodeId) throws NodeStoreException {
- return getNodeItems(nodeId, null, -1);
+ return getNodeItems(nodeId, null, -1, false);
}
@Override
- public ClosableIteratorImpl getNodeItemReplies(String nodeId, String itemId, String afterItemId, int limit) throws NodeStoreException {
+ public ClosableIteratorImpl getNodeItemReplies(String nodeId, String itemId, String rsmItem, boolean after, int limit) throws NodeStoreException {
PreparedStatement stmt = null;
try {
- Date since = new Date(0);
- if (null != afterItemId) {
- since = getNodeItem(nodeId, afterItemId).getUpdated();
+ Date since = new Date();
+ String afterReplacement = "<";
+ if (after) {
+ since = new Date(0);
+ afterReplacement = ">";
}
-
- String query = dialect.selectItemReplies();
+
+ if (null != rsmItem) {
+ since = getNodeItem(nodeId, rsmItem).getUpdated();
+ }
+ String query = dialect.selectItemReplies()
+ .replace("%beforeAfter%", afterReplacement);
+
if (-1 != limit) {
query += " LIMIT ?";
}
@@ -1290,11 +1328,18 @@ public CloseableIterator getNewNodeItemsForUser(JID user, Date startDa
}
@Override
- public int countNodeItems(String nodeId) throws NodeStoreException {
+ public int countNodeItems(String nodeId, boolean parentOnly) throws NodeStoreException {
PreparedStatement selectStatement = null;
try {
- selectStatement = conn.prepareStatement(dialect.countItemsForNode());
+ String query = dialect.countItemsForNode();
+ String parentOnlySubstitution = "";
+ if (parentOnly) {
+ parentOnlySubstitution = "AND \"in_reply_to\" IS NULL";
+ }
+ selectStatement = conn.prepareStatement(
+ query.replace("%parentOnly%", parentOnlySubstitution)
+ );
selectStatement.setString(1, nodeId);
java.sql.ResultSet rs = selectStatement.executeQuery();
@@ -1515,7 +1560,7 @@ public ArrayList getNodeList() throws NodeStoreException {
@Override
public boolean isCachedNode(String nodeId) throws NodeStoreException {
- return ((this.countNodeItems(nodeId) > 0) && (true == this.isCachedNodeConfig(nodeId)));
+ return ((this.countNodeItems(nodeId, false) > 0) && (true == this.isCachedNodeConfig(nodeId)));
}
@Override
@@ -1886,6 +1931,8 @@ public interface NodeStoreSQLDialect {
String selectUserMemberships();
+ String selectUserMembershipsFilteredByEphemeral();
+
String selectUserMembershipsWithConfiguration();
String selectMembership();
diff --git a/src/main/java/org/buddycloud/channelserver/db/jdbc/dialect/Sql92NodeStoreDialect.java b/src/main/java/org/buddycloud/channelserver/db/jdbc/dialect/Sql92NodeStoreDialect.java
index 145a6756..0d049844 100644
--- a/src/main/java/org/buddycloud/channelserver/db/jdbc/dialect/Sql92NodeStoreDialect.java
+++ b/src/main/java/org/buddycloud/channelserver/db/jdbc/dialect/Sql92NodeStoreDialect.java
@@ -107,14 +107,14 @@ public class Sql92NodeStoreDialect implements NodeStoreSQLDialect {
+ " FROM \"items\" WHERE \"node\" = ? AND \"id\" = ?";
private static final String SELECT_ITEMS_FOR_NODE = "SELECT \"node\", \"id\", \"updated\", \"xml\", \"in_reply_to\", \"created\""
- + " FROM \"items\" WHERE \"node\" = ? ORDER BY \"updated\" DESC, \"id\" ASC";
+ + " FROM \"items\" WHERE \"node\" = ? %parentOnly% ORDER BY \"updated\" DESC, \"id\" ASC";
private static final String SELECT_ITEMS_FOR_NODE_AFTER_DATE = "SELECT \"node\", \"id\", \"updated\", \"xml\", \"in_reply_to\", \"created\""
+ " FROM \"items\" WHERE \"node\" = ? AND ( \"updated\" > ? OR ( \"updated\" = ? AND \"id\" > ? ) )"
+ " ORDER BY \"updated\" ASC, \"id\" DESC";
private static final String SELECT_ITEMS_FOR_NODE_BEFORE_DATE = "SELECT \"node\", \"id\", \"updated\", \"xml\", \"in_reply_to\", \"created\""
- + " FROM \"items\" WHERE \"node\" = ? AND ( \"updated\" < ? OR ( \"updated\" = ? AND \"id\" < ? ) )"
+ + " FROM \"items\" WHERE \"node\" = ? AND ( \"updated\" < ? OR ( \"updated\" = ? AND \"id\" < ? ) ) %parentOnly%"
+ " ORDER BY \"updated\" DESC, \"id\" ASC";
private static final String SELECT_ITEMS_FOR_USER_BETWEEN_DATES = "" + "SELECT \"node\", \"id\", \"updated\", \"xml\", \"in_reply_to\", \"created\""
@@ -130,10 +130,10 @@ public class Sql92NodeStoreDialect implements NodeStoreSQLDialect {
private static final String SELECT_COUNT_RECENT_ITEM_PARTS = "" + "(SELECT COUNT(\"id\") " + "FROM \"items\" " + "WHERE \"node\" = ? "
+ "AND \"updated\" > ? " + "%parentOnly% " + "LIMIT ?)";
- private static final String COUNT_ITEMS_FOR_NODE = "SELECT COUNT(*)" + " FROM \"items\" WHERE \"node\" = ?";
+ private static final String COUNT_ITEMS_FOR_NODE = "SELECT COUNT(*)" + " FROM \"items\" WHERE \"node\" = ? %parentOnly%;";
private static final String SELECT_ITEM_REPLIES = "" + "SELECT \"id\", \"node\", \"xml\", \"updated\", \"in_reply_to\", \"created\" "
- + "FROM \"items\" WHERE \"node\" = ? AND \"in_reply_to\" LIKE ? " + "AND \"updated\" > ? ORDER BY \"updated\" DESC";
+ + "FROM \"items\" WHERE \"node\" = ? AND \"in_reply_to\" LIKE ? " + "AND \"updated\" %beforeAfter% ? ORDER BY \"updated\" DESC";
private static final String SELECT_ITEM_THREAD = "" + "SELECT \"id\", \"node\", \"xml\", \"updated\", \"in_reply_to\", \"created\" "
+ "FROM \"items\" WHERE \"node\" = ? " + "AND (\"in_reply_to\" LIKE ? OR \"id\" = ?) " + "AND \"updated\" > ? ORDER BY \"updated\" DESC";
@@ -238,9 +238,9 @@ public class Sql92NodeStoreDialect implements NodeStoreSQLDialect {
private static final String SELECT_NODE_THREADS = "SELECT \"node\", \"id\", \"updated\", \"xml\", \"in_reply_to\", "
+ "\"thread_id\", \"thread_updated\", \"created\" FROM \"items\"," + "(SELECT MAX(\"updated\") AS \"thread_updated\", \"thread_id\" FROM "
- + "(SELECT \"updated\", " + "(CASE WHEN (\"in_reply_to\" IS NULL) THEN \"id\" ELSE \"in_reply_to\" END) AS \"thread_id\" "
+ + "(SELECT \"updated\", COALESCE(\"in_reply_to\",\"id\") AS \"thread_id\" "
+ "FROM \"items\" WHERE \"node\" = ?) AS \"_items\" " + "GROUP BY \"thread_id\" " + "HAVING MAX(\"updated\") < ? "
- + "ORDER BY \"thread_updated\" DESC LIMIT ?) AS \"threads\" " + "WHERE \"in_reply_to\" = \"thread_id\" OR \"id\" = \"thread_id\" "
+ + "ORDER BY \"thread_updated\" DESC LIMIT ?) AS \"threads\" " + "WHERE COALESCE(\"in_reply_to\", \"id\") = \"thread_id\" "
+ "ORDER BY \"thread_updated\" DESC, \"updated\"";
private static final String COUNT_NODE_THREADS = "SELECT COUNT(DISTINCT \"thread_id\") "
@@ -263,7 +263,7 @@ public class Sql92NodeStoreDialect implements NodeStoreSQLDialect {
+ "ON \"subscriptions\".\"node\" = \"affiliations\".\"node\" AND \"affiliations\".\"user\" = \"subscriptions\".\"user\" " + "WHERE "
+ "(\"subscriptions\".\"user\" = ? AND \"subscriptions\".\"node\" = ?) " + "ORDER BY \"updated\" DESC; ";
- private static final String SELECT_USER_MEMBERSHIPS = "" + "SELECT " + "CASE WHEN \"subscriptions\".\"node\" != '' "
+ private static final String SELECT_USER_MEMBERSHIPS_FILTERED_BY_EPHEMERAL = "" + "SELECT " + "CASE WHEN \"subscriptions\".\"node\" != '' "
+ "THEN \"subscriptions\".\"node\" " + "ELSE \"affiliations\".\"node\" " + "END AS \"node\"," + "CASE WHEN \"subscriptions\".\"user\" != '' "
+ "THEN \"subscriptions\".\"user\" " + "ELSE \"affiliations\".\"user\" " + "END AS \"user\", " + "CASE "
+ "WHEN \"subscriptions\".\"listener\" != '' THEN \"subscriptions\".\"listener\" "
@@ -281,6 +281,22 @@ public class Sql92NodeStoreDialect implements NodeStoreSQLDialect {
+ "AND (\"node_config\".\"value\" %equals%)"
+ "ORDER BY \"updated\" DESC; ";
+ private static final String SELECT_USER_MEMBERSHIPS = "" + "SELECT " + "CASE WHEN \"subscriptions\".\"node\" != '' "
+ + "THEN \"subscriptions\".\"node\" " + "ELSE \"affiliations\".\"node\" " + "END AS \"node\"," + "CASE WHEN \"subscriptions\".\"user\" != '' "
+ + "THEN \"subscriptions\".\"user\" " + "ELSE \"affiliations\".\"user\" " + "END AS \"user\", " + "CASE "
+ + "WHEN \"subscriptions\".\"listener\" != '' THEN \"subscriptions\".\"listener\" "
+ + "WHEN \"subscriptions\".\"user\" != '' THEN \"subscriptions\".\"user\" " + "ELSE \"affiliations\".\"user\" " + "END AS \"listener\", "
+ + "CASE WHEN \"subscriptions\".\"subscription\" != '' " + "THEN \"subscriptions\".\"subscription\" " + "ELSE 'none' "
+ + "END AS \"subscription\", " + "CASE WHEN \"affiliations\".\"affiliation\" != '' " + "THEN \"affiliations\".\"affiliation\" "
+ + "ELSE 'none' " + "END AS \"affiliation\", " + "\"subscriptions\".\"invited_by\" AS \"invited_by\","
+ + "CASE WHEN \"affiliations\".\"updated\" > \"subscriptions\".\"updated\" " + "THEN \"affiliations\".\"updated\" "
+ + "ELSE \"subscriptions\".\"updated\" " + "END AS \"updated\" " + "FROM \"subscriptions\" "
+
+ + "LEFT JOIN \"affiliations\" "
+ + "ON \"subscriptions\".\"node\" = \"affiliations\".\"node\" AND \"affiliations\".\"user\" = \"subscriptions\".\"user\" " + "WHERE "
+ + "(\"subscriptions\".\"user\" = ?) "
+ + "ORDER BY \"updated\" DESC; ";
+
private static final String SELECT_USER_MEMBERSHIPS_WITH_CONFIGURATION = "SELECT " +
"CASE WHEN \"subscriptions\".\"node\" != '' THEN " +
"\"subscriptions\".\"node\" " +
@@ -692,6 +708,11 @@ public String selectMembership() {
return SELECT_NODE_MEMBERSHIP;
}
+ @Override
+ public String selectUserMembershipsFilteredByEphemeral() {
+ return SELECT_USER_MEMBERSHIPS_FILTERED_BY_EPHEMERAL;
+ }
+
@Override
public String selectUserMemberships() {
return SELECT_USER_MEMBERSHIPS;
diff --git a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/PacketProcessorAbstract.java b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/PacketProcessorAbstract.java
index c68f61f4..70549edb 100644
--- a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/PacketProcessorAbstract.java
+++ b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/PacketProcessorAbstract.java
@@ -4,9 +4,9 @@
import java.util.List;
import java.util.concurrent.BlockingQueue;
+import org.apache.commons.lang.StringUtils;
import org.buddycloud.channelserver.channel.ChannelManager;
import org.buddycloud.channelserver.packetprocessor.PacketProcessor;
-import org.buddycloud.channelserver.queue.UnknownFederatedPacketException;
import org.buddycloud.channelserver.utils.XMLConstants;
import org.buddycloud.channelserver.utils.node.item.payload.Buddycloud;
import org.dom4j.Element;
@@ -14,42 +14,39 @@
import org.dom4j.QName;
import org.dom4j.dom.DOMElement;
import org.xmpp.packet.IQ;
+import org.xmpp.packet.IQ.Type;
import org.xmpp.packet.JID;
import org.xmpp.packet.Packet;
import org.xmpp.packet.PacketError;
-import org.xmpp.packet.IQ.Type;
public abstract class PacketProcessorAbstract implements PacketProcessor {
protected BlockingQueue outQueue;
protected ChannelManager channelManager;
protected List elementProcessors = new LinkedList();
-
+
protected Element pubsub;
protected JID actor;
-
- protected void getActor(IQ reqIQ) throws InterruptedException, IllegalActorException {
+
+ protected void validateActor(IQ reqIQ) throws InterruptedException, IllegalActorException {
if (pubsub.elementText(XMLConstants.ACTOR_ELEM) == null) {
return;
}
actor = new JID(pubsub.elementText(XMLConstants.ACTOR_ELEM).trim());
- String domain = actor.getDomain();
-
- String from = reqIQ.getFrom().getDomain();
- int startPosition = from.length() - domain.length();
- if (from.substring(startPosition).equals(domain)) {
+
+ if (StringUtils.endsWithIgnoreCase(reqIQ.getFrom().getDomain(), "." + actor.getDomain())) {
return;
}
throw new IllegalActorException();
}
-
+
@Override
public void process(IQ reqIQ) throws Exception {
pubsub = reqIQ.getChildElement();
try {
- getActor(reqIQ);
+ validateActor(reqIQ);
} catch (IllegalActorException e) {
sendPolicyViolationResponse(reqIQ);
return;
diff --git a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/PubSubElementProcessorAbstract.java b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/PubSubElementProcessorAbstract.java
index b614635e..b61990bc 100644
--- a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/PubSubElementProcessorAbstract.java
+++ b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/PubSubElementProcessorAbstract.java
@@ -38,8 +38,6 @@ public abstract class PubSubElementProcessorAbstract implements PubSubElementPro
protected IQ response;
protected IQ request;
protected JID actor;
- protected String serverDomain;
- protected String topicsDomain;
protected String node = null;
protected Helper configurationHelper;
protected Map nodeConfiguration;
@@ -49,6 +47,7 @@ public abstract class PubSubElementProcessorAbstract implements PubSubElementPro
// RSM details
protected int maxResults = -1;
protected String afterItemId = null;
+ protected String beforeItemId;
protected Element resultSetManagement;
protected String firstItem;
@@ -68,17 +67,6 @@ public void setChannelManager(ChannelManager channelManager) {
this.channelManager = channelManager;
}
- public void setServerDomain(String domain) {
- serverDomain = domain;
- }
-
- protected String getServerDomain() {
- if (null == serverDomain) {
- serverDomain = Configuration.getInstance().getProperty("server.domain");
- }
- return serverDomain;
- }
-
protected Collection getAdminUsers() {
if (null == adminUsers) {
adminUsers = Configuration.getInstance().getAdminUsers();
@@ -86,21 +74,10 @@ protected Collection getAdminUsers() {
return adminUsers;
}
- public void setTopicsDomain(String domain) {
- topicsDomain = domain;
- }
-
public void setNode(String node) {
this.node = node;
}
- protected String getTopicsDomain() {
- if (null == topicsDomain) {
- topicsDomain = Configuration.getInstance().getProperty("server.domain.topics");
- }
- return topicsDomain;
- }
-
public void setConfigurationHelper(Helper helper) {
configurationHelper = helper;
}
@@ -200,7 +177,7 @@ private AccessModels getNodeAccessModel() {
}
protected boolean actorIsRegistered() {
- if (actor.getDomain().equals(getServerDomain())) {
+ if (Configuration.getInstance().isLocalJID(actor)) {
return true;
} else {
setErrorCondition(PacketError.Type.auth, PacketError.Condition.forbidden);
@@ -291,9 +268,13 @@ protected boolean parseRsmElement() throws NodeStoreException {
maxResults = Integer.parseInt(max.getTextTrim());
}
Element after;
+ Element before;
if (null != (after = rsmElement.element("after"))) {
afterItemId = after.getTextTrim();
}
+ if (null != (before = rsmElement.element("before"))) {
+ beforeItemId = before.getTextTrim();
+ }
return true;
};
diff --git a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/AffiliationsGet.java b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/AffiliationsGet.java
index 6207a59b..80279b98 100644
--- a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/AffiliationsGet.java
+++ b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/AffiliationsGet.java
@@ -13,6 +13,8 @@
import org.buddycloud.channelserver.utils.XMLConstants;
import org.buddycloud.channelserver.utils.node.item.payload.Buddycloud;
import org.dom4j.Element;
+import org.dom4j.Namespace;
+import org.dom4j.QName;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.Packet;
@@ -121,7 +123,7 @@ private boolean getUserMemberships(Element affiliations) throws NodeStoreExcepti
String ephemeralValue =
request.getChildElement().element(XMLConstants.AFFILIATIONS_ELEM)
- .attributeValue(XMLConstants.BUDDYCLOUD_XMLNS_PREFIX + XMLConstants.EPHEMERAL);
+ .attributeValue(new QName(XMLConstants.EPHEMERAL, Namespace.get(Buddycloud.NS)));
if ((null != ephemeralValue) && ephemeralValue.equals("true")) {
ephemeral = true;
}
diff --git a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/RepliesGet.java b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/RepliesGet.java
index 00be0e32..3aefb247 100644
--- a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/RepliesGet.java
+++ b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/RepliesGet.java
@@ -87,19 +87,27 @@ private boolean itemExists() throws NodeStoreException {
}
protected void addRsmElement() throws NodeStoreException {
- if (null == firstItemId) {
- return;
- }
+
Element rsm = pubsub.addElement(XMLConstants.SET_ELEM);
rsm.addNamespace("", NS_RSM);
- rsm.addElement("first").setText(firstItemId);
- rsm.addElement("last").setText(lastItemId);
- rsm.addElement("count").setText(String.valueOf(channelManager.getCountNodeItemReplies(node, parentId)));
+ if (null != firstItemId) {
+ rsm.addElement("first").setText(firstItemId);
+ rsm.addElement("last").setText(lastItemId);
+ }
+ rsm.addElement("count").setText(
+ String.valueOf(channelManager.getCountNodeItemReplies(node, parentId)));
}
private void addReplies() throws NodeStoreException {
- CloseableIterator items = channelManager.getNodeItemReplies(node, parentId, afterItemId, maxResults);
+ String rsmItem = afterItemId;
+ boolean after = true;
+ if (null != beforeItemId) {
+ rsmItem = beforeItemId;
+ after = false;
+ }
+
+ CloseableIterator items = channelManager.getNodeItemReplies(node, parentId, rsmItem, after, maxResults);
NodeItem item;
Element entry;
Element itemElement;
diff --git a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/SubscriptionsGet.java b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/SubscriptionsGet.java
index 6b0b9063..c1d3164e 100644
--- a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/SubscriptionsGet.java
+++ b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/SubscriptionsGet.java
@@ -12,6 +12,8 @@
import org.buddycloud.channelserver.utils.XMLConstants;
import org.buddycloud.channelserver.utils.node.item.payload.Buddycloud;
import org.dom4j.Element;
+import org.dom4j.Namespace;
+import org.dom4j.QName;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.Packet;
@@ -19,9 +21,6 @@
public class SubscriptionsGet extends PubSubElementProcessorAbstract {
- private final BlockingQueue outQueue;
- private ChannelManager channelManager;
-
private IQ result;
private String node;
private JID actorJid;
@@ -29,12 +28,8 @@ public class SubscriptionsGet extends PubSubElementProcessorAbstract {
private boolean ephemeral = false;
public SubscriptionsGet(BlockingQueue outQueue, ChannelManager channelManager) {
- this.outQueue = outQueue;
- this.channelManager = channelManager;
- }
-
- public void setChannelManager(ChannelManager dataStore) {
- channelManager = dataStore;
+ setOutQueue(outQueue);
+ setChannelManager(channelManager);
}
@@ -137,7 +132,7 @@ private boolean getUserMemberships(Element subscriptions) throws NodeStoreExcept
String ephemeralValue =
requestIq.getChildElement().element(XMLConstants.SUBSCRIPTIONS_ELEM)
- .attributeValue(XMLConstants.BUDDYCLOUD_XMLNS_PREFIX + XMLConstants.EPHEMERAL);
+ .attributeValue(new QName(XMLConstants.EPHEMERAL, Namespace.get(Buddycloud.NS)));
if ((null != ephemeralValue) && ephemeralValue.equals("true")) {
ephemeral = true;
}
diff --git a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/items/NodeItemsGet.java b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/items/NodeItemsGet.java
index 5919c6c7..5559db21 100644
--- a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/items/NodeItemsGet.java
+++ b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/items/NodeItemsGet.java
@@ -36,18 +36,16 @@ public class NodeItemsGet extends PubSubElementProcessorAbstract {
public static final int MAX_ITEMS_TO_RETURN = 50;
- private final BlockingQueue outQueue;
-
private ChannelManager channelManager;
private String node;
private String firstItem;
private String lastItem;
private SAXReader xmlReader;
private Element entry;
- private IQ requestIq;
private IQ reply;
private Element resultSetManagement;
private Element element;
+ private boolean parentOnly = false;
private Map nodeDetails;
@@ -55,8 +53,10 @@ public class NodeItemsGet extends PubSubElementProcessorAbstract {
private JID actor;
+ private Element items;
+
public NodeItemsGet(BlockingQueue outQueue, ChannelManager channelManager) {
- this.outQueue = outQueue;
+ setOutQueue(outQueue);
setChannelManager(channelManager);
this.acceptedElementName = XMLConstants.ITEMS_ELEM;
@@ -68,31 +68,37 @@ public void setChannelManager(ChannelManager ds) {
@Override
public void process(Element elm, JID actorJID, IQ reqIQ, Element rsm) throws Exception {
- node = elm.attributeValue(XMLConstants.NODE_ATTR);
- requestIq = reqIQ;
+ request = reqIQ;
+
reply = IQ.createResultIQ(reqIQ);
element = elm;
resultSetManagement = rsm;
- if (!Configuration.getInstance().isLocalJID(requestIq.getFrom())) {
+ if (!Configuration.getInstance().isLocalJID(request.getFrom())) {
reply.getElement().addAttribute(XMLConstants.REMOTE_SERVER_DISCOVER_ATTR, Boolean.FALSE.toString());
}
- boolean isCached = channelManager.isCachedNode(node);
-
- this.actor = actorJID;
- if (null == this.actor) {
- this.actor = requestIq.getFrom();
- }
-
- if (!Configuration.getInstance().isLocalNode(node) && !isCached) {
- LOGGER.debug("Node " + node + " is remote and not cached, off to get some data");
-
- makeRemoteRequest();
- return;
- }
-
try {
+
+ if (!isValidStanza()) {
+ outQueue.put(reply);
+ return;
+ }
+
+ boolean isCached = channelManager.isCachedNode(node);
+
+ this.actor = actorJID;
+ if (null == this.actor) {
+ this.actor = request.getFrom();
+ }
+
+ if (!Configuration.getInstance().isLocalNode(node) && !isCached) {
+ LOGGER.debug("Node " + node + " is remote and not cached, off to get some data");
+
+ makeRemoteRequest();
+ return;
+ }
+
if (!checkNodeExists()) {
setErrorCondition(PacketError.Type.cancel, PacketError.Condition.item_not_found);
outQueue.put(reply);
@@ -104,7 +110,7 @@ public void process(Element elm, JID actorJID, IQ reqIQ, Element rsm) throws Exc
return;
}
xmlReader = new SAXReader();
- if (element.element(XMLConstants.ITEM_ELEM) == null) {
+ if (null == items.element(XMLConstants.ITEM_ELEM)) {
getItems();
} else {
if (!getItem()) {
@@ -114,13 +120,22 @@ public void process(Element elm, JID actorJID, IQ reqIQ, Element rsm) throws Exc
} catch (NodeStoreException e) {
LOGGER.error(e);
setErrorCondition(PacketError.Type.wait, PacketError.Condition.internal_server_error);
+ } catch (NullPointerException e) {
+ LOGGER.error(e);
+ setErrorCondition(PacketError.Type.modify, PacketError.Condition.bad_request);
}
outQueue.put(reply);
}
+
+ protected boolean isValidStanza() {
+ Element pubsub = request.getElement().element(XMLConstants.PUBSUB_ELEM);
+ items = pubsub.element(XMLConstants.ITEMS_ELEM);
+ node = items.attributeValue(XMLConstants.NODE_ATTR);
+ return true;
+ }
private boolean getItem() throws Exception {
- NodeItem nodeItem = channelManager.getNodeItem(node, element.element(XMLConstants.ITEM_ELEM).attributeValue(XMLConstants.ID_ATTR));
-
+ NodeItem nodeItem = channelManager.getNodeItem(node, items.element(XMLConstants.ITEM_ELEM).attributeValue(XMLConstants.ID_ATTR));
if (nodeItem == null) {
if (!Configuration.getInstance().isLocalNode(node)) {
makeRemoteRequest();
@@ -139,12 +154,12 @@ private boolean getItem() throws Exception {
@Override
protected void makeRemoteRequest() throws InterruptedException {
- requestIq.setTo(new JID(node.split("/")[2]).getDomain());
- if (null == requestIq.getElement().element(XMLConstants.PUBSUB_ELEM).element(XMLConstants.ACTOR_ELEM)) {
- Element actor = requestIq.getElement().element(XMLConstants.PUBSUB_ELEM).addElement(XMLConstants.ACTOR_ELEM, Buddycloud.NS);
- actor.addText(requestIq.getFrom().toBareJID());
+ request.setTo(new JID(node.split("/")[2]).getDomain());
+ if (null == request.getElement().element(XMLConstants.PUBSUB_ELEM).element(XMLConstants.ACTOR_ELEM)) {
+ Element actor = request.getElement().element(XMLConstants.PUBSUB_ELEM).addElement(XMLConstants.ACTOR_ELEM, Buddycloud.NS);
+ actor.addText(request.getFrom().toBareJID());
}
- outQueue.put(requestIq);
+ outQueue.put(request);
}
@Override
@@ -171,7 +186,12 @@ private void getItems() throws Exception {
int maxItemsToReturn = MAX_ITEMS_TO_RETURN;
String afterItemId = null;
- String maxItems = element.attributeValue(XMLConstants.MAX_ITEMS_ATTR);
+ String parentOnlyAttribute = request.getChildElement().element(XMLConstants.ITEMS_ELEM).attributeValue(XMLConstants.PARENT_ONLY_ATTR);
+ if ((null != parentOnlyAttribute) && ((Boolean.TRUE.toString().equals(parentOnlyAttribute)) || ("1".equals(parentOnlyAttribute)))) {
+ parentOnly = true;
+ }
+
+ String maxItems = items.attributeValue(XMLConstants.MAX_ITEMS_ATTR);
if (maxItems != null) {
maxItemsToReturn = Integer.parseInt(maxItems);
@@ -207,7 +227,7 @@ private void getItems() throws Exception {
items.addAttribute(XMLConstants.NODE_ATTR, node);
entry = null;
- int totalEntriesCount = getNodeItems(items, maxItemsToReturn, afterItemId);
+ int totalEntriesCount = getNodeItems(items, maxItemsToReturn, afterItemId, parentOnly);
if ((false == Configuration.getInstance().isLocalNode(node)) && (0 == rsmEntriesCount)) {
LOGGER.debug("No results in cache for remote node, so " + "we're going federated to get more");
@@ -256,9 +276,9 @@ private AccessModels getNodeAccessModel() {
/**
* Get items nodes
*/
- private int getNodeItems(Element items, int maxItemsToReturn, String afterItemId) throws NodeStoreException {
+ private int getNodeItems(Element items, int maxItemsToReturn, String afterItemId, boolean parentOnly) throws NodeStoreException {
- CloseableIterator itemIt = channelManager.getNodeItems(node, afterItemId, maxItemsToReturn);
+ CloseableIterator itemIt = channelManager.getNodeItems(node, afterItemId, maxItemsToReturn, parentOnly);
rsmEntriesCount = 0;
if (itemIt == null) {
return 0;
@@ -275,7 +295,7 @@ private int getNodeItems(Element items, int maxItemsToReturn, String afterItemId
lastItem = nodeItem.getId();
}
LOGGER.debug("Including RSM there are " + rsmEntriesCount + " items for node " + node);
- return channelManager.countNodeItems(node);
+ return channelManager.countNodeItems(node, parentOnly);
} finally {
itemIt.close();
}
diff --git a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/AffiliationEvent.java b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/AffiliationEvent.java
index 9dcc3f10..682f694f 100644
--- a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/AffiliationEvent.java
+++ b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/AffiliationEvent.java
@@ -12,6 +12,7 @@
import org.buddycloud.channelserver.pubsub.affiliation.Affiliations;
import org.buddycloud.channelserver.pubsub.model.NodeMembership;
import org.buddycloud.channelserver.pubsub.model.NodeSubscription;
+import org.buddycloud.channelserver.pubsub.subscription.Subscriptions;
import org.buddycloud.channelserver.utils.XMLConstants;
import org.buddycloud.channelserver.utils.node.item.payload.Buddycloud;
import org.dom4j.Document;
@@ -199,7 +200,8 @@ private boolean subscriberHasCurrentAffiliation() throws NodeStoreException {
channelManager.getNodeMembership(node,
new JID(requestedAffiliationElement.attributeValue(XMLConstants.JID_ATTR)));
- if (usersCurrentMembership.getAffiliation().equals(Affiliations.none)) {
+ if (usersCurrentMembership.getAffiliation().equals(Affiliations.none)
+ && usersCurrentMembership.getSubscription().equals(Subscriptions.none)) {
setErrorCondition(PacketError.Type.modify, PacketError.Condition.unexpected_request);
return false;
}
diff --git a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/ItemDelete.java b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/ItemDelete.java
index cf29b729..398054e3 100644
--- a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/ItemDelete.java
+++ b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/ItemDelete.java
@@ -17,6 +17,7 @@
import org.buddycloud.channelserver.pubsub.model.impl.GlobalItemIDImpl;
import org.buddycloud.channelserver.pubsub.subscription.Subscriptions;
import org.buddycloud.channelserver.utils.XMLConstants;
+import org.buddycloud.channelserver.utils.node.item.payload.Buddycloud;
import org.dom4j.Element;
import org.dom4j.Namespace;
import org.dom4j.dom.DOMElement;
@@ -82,7 +83,10 @@ public void process(Element elm, JID actor, IQ reqIQ, Element rsm) throws Interr
setErrorCondition(PacketError.Type.modify, PacketError.Condition.bad_request);
} catch (IllegalArgumentException e) {
LOGGER.error(e);
- setErrorCondition(PacketError.Type.modify, PacketError.Condition.bad_request);
+ createExtendedErrorReply(
+ PacketError.Type.modify, PacketError.Condition.bad_request,
+ "global-id-error", Buddycloud.NS_ERROR, e.getMessage()
+ );
}
outQueue.put(response);
}
@@ -91,13 +95,14 @@ private void deleteReplies() throws NodeStoreException {
if (null != nodeItem.getInReplyTo()) {
return;
}
- ClosableIteratorImpl replies = channelManager.getNodeItemReplies(node, itemId.getItemID(), null, -1);
+ ClosableIteratorImpl replies = channelManager.getNodeItemReplies(node, itemId.getItemID(), null, true, -1);
NodeItem reply = null;
while (replies.hasNext()) {
reply = replies.next();
channelManager.deleteNodeItemById(reply.getNodeId(), reply.getId());
- sendNotifications(node, new GlobalItemIDImpl(new JID(this.getServerDomain()), reply.getNodeId(), reply.getId()));
+ sendNotifications(node, new GlobalItemIDImpl(new JID(
+ Configuration.getInstance().getServerDomain()), reply.getNodeId(), reply.getId()));
}
}
@@ -206,7 +211,8 @@ private boolean itemIdProvided() {
if (GlobalItemIDImpl.isGlobalId(id)) {
itemId = GlobalItemIDImpl.fromBuddycloudString(id);
} else {
- itemId = new GlobalItemIDImpl(new JID(this.getServerDomain()), node, id);
+ itemId = new GlobalItemIDImpl(new JID(
+ Configuration.getInstance().getServerDomain()), node, id);
}
return true;
}
diff --git a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/NodeCreate.java b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/NodeCreate.java
index a7e86c5b..11d7667e 100644
--- a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/NodeCreate.java
+++ b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/NodeCreate.java
@@ -42,7 +42,7 @@ public void process(Element elm, JID actorJID, IQ reqIQ, Element rsm) throws Exc
if (null == actorJID) {
actor = request.getFrom();
}
- if (!nodePresent()) {
+ if (!nodePresent() || !isNodeValid()) {
outQueue.put(response);
return;
}
@@ -50,8 +50,7 @@ public void process(Element elm, JID actorJID, IQ reqIQ, Element rsm) throws Exc
makeRemoteRequest();
return;
}
- if ((checkNodeExists()) || (!actorIsRegistered()) || (!nodeHandledByThisServer())) {
-
+ if ((checkNodeExists()) || (!actorIsRegistered())) {
outQueue.put(response);
return;
}
@@ -100,16 +99,11 @@ protected boolean checkNodeExists() throws NodeStoreException {
return true;
}
- private boolean nodeHandledByThisServer() {
+ private boolean isNodeValid() {
if (!node.matches(NODE_REG_EX)) {
setErrorCondition(PacketError.Type.modify, PacketError.Condition.bad_request);
return false;
}
-
- if ((!node.contains("@" + getServerDomain())) && (!node.contains("@" + getTopicsDomain()))) {
- setErrorCondition(PacketError.Type.modify, PacketError.Condition.not_acceptable);
- return false;
- }
return true;
}
}
diff --git a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/NodeDelete.java b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/NodeDelete.java
index 3a9779c4..1cb56d59 100644
--- a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/NodeDelete.java
+++ b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/NodeDelete.java
@@ -57,7 +57,7 @@ public void process(Element elm, JID actorJID, IQ reqIQ, Element rsm) throws Exc
makeRemoteRequest();
return;
}
- if (!checkNodeExists() || !actorIsRegistered() || !nodeHandledByThisServer()
+ if (!checkNodeExists() || !actorIsRegistered()
|| isEphemeralNode() || !actorAllowedToDelete()) {
outQueue.put(response);
return;
@@ -137,14 +137,6 @@ private boolean actorAllowedToDelete() throws NodeStoreException {
return false;
}
- private boolean nodeHandledByThisServer() {
- if (!node.contains("@" + getServerDomain()) && !node.contains("@" + getTopicsDomain())) {
- setErrorCondition(PacketError.Type.modify, PacketError.Condition.not_acceptable);
- return false;
- }
- return true;
- }
-
private boolean nodeValid() {
if (!node.matches(NODE_REG_EX)) {
setErrorCondition(PacketError.Type.modify, PacketError.Condition.bad_request);
diff --git a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/SubscribeSet.java b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/SubscribeSet.java
index abdacc4e..d9dfcffe 100644
--- a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/SubscribeSet.java
+++ b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/SubscribeSet.java
@@ -45,11 +45,10 @@ public class SubscribeSet extends PubSubElementProcessorAbstract {
public static final String INVALID_NODE_FORMAT = "invalid-node-format";
- private final BlockingQueue outQueue;
private final ChannelManager channelManager;
public SubscribeSet(BlockingQueue outQueue, ChannelManager channelManager) {
- this.outQueue = outQueue;
+ this.setOutQueue(outQueue);
this.channelManager = channelManager;
acceptedElementName = XMLConstants.SUBSCRIBE_ELEM;
diff --git a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/search/SearchSet.java b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/search/SearchSet.java
index 22960131..9fb85ffe 100644
--- a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/search/SearchSet.java
+++ b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/search/SearchSet.java
@@ -60,6 +60,7 @@ public void process(IQ request) throws Exception {
try {
runSearch();
} catch (NodeStoreException e) {
+ LOGGER.error(e);
sendErrorResponse(PacketError.Type.wait, PacketError.Condition.internal_server_error);
return;
}
diff --git a/src/test/java/org/buddycloud/channelserver/db/jdbc/JDBCNodeStoreRecentItemsTest.java b/src/test/java/org/buddycloud/channelserver/db/jdbc/JDBCNodeStoreRecentItemsTest.java
index 53606a34..fd3528b6 100644
--- a/src/test/java/org/buddycloud/channelserver/db/jdbc/JDBCNodeStoreRecentItemsTest.java
+++ b/src/test/java/org/buddycloud/channelserver/db/jdbc/JDBCNodeStoreRecentItemsTest.java
@@ -54,6 +54,25 @@ public void testGetRecentItemsNoSubscriptions() throws Exception {
TEST_SERVER1_USER1_JID, new Date(), -1, -1, null, null, false);
assertEquals(false, items.hasNext());
}
+
+ @Test
+ public void testGetRecentItemsFromEphemeralNode() throws Exception {
+
+ Date since = new Date();
+ dbTester.loadData("node_1");
+ store.setNodeConfValue(TEST_SERVER1_NODE1_ID, "buddycloud#ephemeral", "true");
+
+ NodeItem nodeItem1 = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "123", new Date(), "payload");
+ store.addNodeItem(nodeItem1);
+
+ Thread.sleep(20);
+
+ CloseableIterator items = store.getRecentItems(TEST_SERVER1_USER1_JID, since, -1, -1, null, null, false);
+
+ // 2 -> 1 on purpose results are most recent first!
+ assertSameNodeItem(items.next(), nodeItem1);
+ assertEquals(false, items.hasNext());
+ }
@Test
public void testGetRecentItemsCanBePaged() throws Exception {
diff --git a/src/test/java/org/buddycloud/channelserver/db/jdbc/JDBCNodeStoreTest.java b/src/test/java/org/buddycloud/channelserver/db/jdbc/JDBCNodeStoreTest.java
index 3bbc7d6a..8016e5cf 100644
--- a/src/test/java/org/buddycloud/channelserver/db/jdbc/JDBCNodeStoreTest.java
+++ b/src/test/java/org/buddycloud/channelserver/db/jdbc/JDBCNodeStoreTest.java
@@ -119,7 +119,7 @@ public void testGetNodeItemsWithLimits() throws Exception {
dbTester.loadData("node_1");
Iterator result = store.getNodeItems(TEST_SERVER1_NODE1_ID,
- TEST_SERVER1_NODE1_ITEM4_ID, 4);
+ TEST_SERVER1_NODE1_ITEM4_ID, 4, false);
String[] expectedNodeIds = { TEST_SERVER1_NODE1_ITEM3_ID,
TEST_SERVER1_NODE1_ITEM2_ID, TEST_SERVER1_NODE1_ITEM1_ID };
@@ -163,7 +163,7 @@ public void testGetNodeItemsWithPaging() throws Exception {
}
CloseableIterator result = store.getNodeItems(
- TEST_SERVER1_NODE1_ID, "15", 3);
+ TEST_SERVER1_NODE1_ID, "15", 3, false);
assertEquals("Incorrect node item returned", items[14], result.next());
assertEquals("Incorrect node item returned", items[13], result.next());
@@ -176,7 +176,7 @@ public void testGetNodeItemsWithNegativeOneCountReturnsAllItems()
dbTester.loadData("node_1");
Iterator result = store.getNodeItems(TEST_SERVER1_NODE1_ID,
- null, -1);
+ null, -1, false);
String[] expectedNodeIds = { TEST_SERVER1_NODE1_ITEM5_ID,
TEST_SERVER1_NODE1_ITEM4_ID, TEST_SERVER1_NODE1_ITEM3_ID,
@@ -211,7 +211,7 @@ public void testGetNodeItemsWithNegativeOneCountReturnsAllItems()
public void testGetNodeItemsWithInvalidCountThrowsException()
throws Exception {
store.getNodeItems(TEST_SERVER1_NODE1_ID, TEST_SERVER1_NODE1_ITEM1_ID,
- -2);
+ -2, false);
}
@Test
@@ -220,7 +220,7 @@ public void testGetNodeItemsWithUnknownItemReturnsAllItems()
dbTester.loadData("node_1");
Iterator result = store.getNodeItems(TEST_SERVER1_NODE1_ID,
- "randomunknownitemid", 10);
+ "randomunknownitemid", 10, false);
String[] expectedNodeIds = { TEST_SERVER1_NODE1_ITEM5_ID,
TEST_SERVER1_NODE1_ITEM4_ID, TEST_SERVER1_NODE1_ITEM3_ID,
@@ -255,10 +255,20 @@ public void testGetNodeItemsWithUnknownItemReturnsAllItems()
public void testCountNodeItems() throws Exception {
dbTester.loadData("node_1");
- int result = store.countNodeItems(TEST_SERVER1_NODE1_ID);
+ int result = store.countNodeItems(TEST_SERVER1_NODE1_ID, false);
assertEquals("Incorrect item count", 5, result);
}
+
+ @Test
+ public void countNodeItemsWithNoReplies() throws Exception {
+ dbTester.loadData("node_1");
+ dbTester.loadData("node_4");
+
+ int result = store.countNodeItems(TEST_SERVER1_NODE1_ID, true);
+
+ assertEquals("Incorrect item count", 6, result);
+ }
@Test
public void testGetNewNodeItemsForUserBetweenDates() throws Exception {
@@ -325,7 +335,7 @@ public void testGetNewNodeItemsForUserBetweenDatesWhenOutcast()
public void testCountNodeItemsNonExistantNode() throws Exception {
dbTester.loadData("node_1");
- int result = store.countNodeItems("iamanodewhichdoesntexist");
+ int result = store.countNodeItems("iamanodewhichdoesntexist", false);
assertEquals("Incorrect item count", 0, result);
}
@@ -381,7 +391,7 @@ public void canGetItemReplies() throws Exception {
store.addNodeItem(testItem);
ClosableIteratorImpl items = store.getNodeItemReplies(
- TEST_SERVER1_NODE1_ID, "a5", null, -1);
+ TEST_SERVER1_NODE1_ID, "a5", null, true, -1);
int count = 0;
NodeItem item = null;
@@ -411,7 +421,7 @@ public void canGetItemRepliesWithResultSetManagement() throws Exception {
store.addNodeItem(testItem4);
ClosableIteratorImpl items = store.getNodeItemReplies(
- TEST_SERVER1_NODE1_ID, "a5", "a7", 2);
+ TEST_SERVER1_NODE1_ID, "a5", "a7", true, 2);
int count = 0;
ArrayList itemsResult = new ArrayList();
@@ -425,6 +435,41 @@ public void canGetItemRepliesWithResultSetManagement() throws Exception {
assertSameNodeItem(itemsResult.get(1), testItem1);
}
+ @Test
+ public void canGetItemRepliesWithResultSetManagementPagingBackwards() throws Exception {
+
+ dbTester.loadData("node_1");
+ NodeItem testItem1 = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "a6",
+ new Date(), "payload", "a5", new Date());
+ Thread.sleep(100);
+ NodeItem testItem2 = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "a7",
+ new Date(), "payload", "a5", new Date());
+ Thread.sleep(100);
+ NodeItem testItem3 = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "a8",
+ new Date(), "payload", "a5", new Date());
+ Thread.sleep(100);
+ NodeItem testItem4 = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "a9",
+ new Date(), "payload", "/full-node-item-id-ref/a5", new Date());
+ store.addNodeItem(testItem1);
+ store.addNodeItem(testItem2);
+ store.addNodeItem(testItem3);
+ store.addNodeItem(testItem4);
+
+ ClosableIteratorImpl items = store.getNodeItemReplies(
+ TEST_SERVER1_NODE1_ID, "a5", "a8", false, 4);
+
+ int count = 0;
+ ArrayList itemsResult = new ArrayList();
+ while (items.hasNext()) {
+ ++count;
+ itemsResult.add(items.next());
+
+ }
+ assertEquals(2, count);
+ assertSameNodeItem(itemsResult.get(0), testItem1);
+ assertSameNodeItem(itemsResult.get(1), testItem2);
+ }
+
@Test
public void canGetCountOfItemReplies() throws Exception {
dbTester.loadData("node_1");
@@ -642,9 +687,9 @@ public void testGetNodeListReturnsExpectedNodes() throws Exception {
public void testPurgeNodeItemsDeletesNodeItems() throws Exception {
dbTester.loadData("node_1");
- assertTrue(store.countNodeItems(TEST_SERVER1_NODE1_ID) > 0);
+ assertTrue(store.countNodeItems(TEST_SERVER1_NODE1_ID, false) > 0);
store.purgeNodeItems(TEST_SERVER1_NODE1_ID);
- assertEquals(0, store.countNodeItems(TEST_SERVER1_NODE1_ID));
+ assertEquals(0, store.countNodeItems(TEST_SERVER1_NODE1_ID, false));
}
@Test
@@ -652,10 +697,10 @@ public void testPurgeNodeItemsDoesntDeleteItemsUnexpectedly()
throws Exception {
dbTester.loadData("node_1");
- int itemCount = store.countNodeItems(TEST_SERVER1_NODE1_ID);
+ int itemCount = store.countNodeItems(TEST_SERVER1_NODE1_ID, false);
assertTrue(itemCount > 0);
store.purgeNodeItems(TEST_SERVER1_NODE2_ID); // <--- NODE **2**
- assertEquals(itemCount, store.countNodeItems(TEST_SERVER1_NODE1_ID));
+ assertEquals(itemCount, store.countNodeItems(TEST_SERVER1_NODE1_ID, false));
}
@Test
diff --git a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/PubSubSetTest.java b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/PubSubSetTest.java
index 192333ec..9459c183 100644
--- a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/PubSubSetTest.java
+++ b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/PubSubSetTest.java
@@ -6,17 +6,14 @@
import org.buddycloud.channelserver.channel.ChannelManager;
import org.buddycloud.channelserver.packetHandler.iq.IQTestHandler;
-import org.buddycloud.channelserver.packetprocessor.iq.namespace.pubsub.get.AffiliationsGet;
import org.buddycloud.channelserver.utils.XMLConstants;
import org.buddycloud.channelserver.utils.node.item.payload.Buddycloud;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.xmpp.packet.IQ;
-import org.xmpp.packet.JID;
import org.xmpp.packet.Packet;
import org.xmpp.packet.PacketError;
-import org.xmpp.util.XMPPConstants;
public class PubSubSetTest extends IQTestHandler {
@@ -31,15 +28,15 @@ public void setUp() throws Exception {
pubsubSet = new PubSubSet(queue, channelManager);
pubsubSet.purgeElementProcessors();
}
-
+
@Test
public void returnsErrorForIllegalActor() throws Exception {
IQ request = readStanzaAsIq("/iq/pubsub/bad-actor.stanza");
-
+
pubsubSet.process(request);
Assert.assertEquals(1, queue.size());
IQ response = (IQ) queue.poll();
-
+
Assert.assertEquals(IQ.Type.error, response.getType());
PacketError error = response.getError();
@@ -49,24 +46,45 @@ public void returnsErrorForIllegalActor() throws Exception {
Assert.assertNotNull(response.getElement().element("error").element(XMLConstants.POLICY_VIOLATION));
Assert.assertEquals(XMLConstants.INVALID_NODE, error.getApplicationConditionName());
Assert.assertEquals(Buddycloud.NS_ERROR, error.getApplicationConditionNamespaceURI());
-
+
+ }
+
+ @Test
+ public void returnsErrorForSpoofActor() throws Exception {
+ IQ request = readStanzaAsIq("/iq/pubsub/spoof-actor.stanza");
+
+ pubsubSet.process(request);
+ Assert.assertEquals(1, queue.size());
+ IQ response = (IQ) queue.poll();
+
+ Assert.assertEquals(IQ.Type.error, response.getType());
+
+ PacketError error = response.getError();
+ Assert.assertNotNull(error);
+
+ Assert.assertEquals(PacketError.Type.cancel, error.getType());
+ Assert.assertNotNull(response.getElement().element("error")
+ .element(XMLConstants.POLICY_VIOLATION));
+ Assert.assertEquals(XMLConstants.INVALID_NODE, error.getApplicationConditionName());
+ Assert.assertEquals(Buddycloud.NS_ERROR, error.getApplicationConditionNamespaceURI());
+
}
@Test
public void ifPacketCanNotBeProcessedShouldReceiveAFeatureNotImplementedError() throws Exception {
IQ request = readStanzaAsIq("/iq/pubsub/good-actor.stanza");
-
+
pubsubSet.process(request);
Assert.assertEquals(1, queue.size());
IQ response = (IQ) queue.poll();
-
+
Assert.assertEquals(IQ.Type.error, response.getType());
-
+
PacketError error = response.getError();
Assert.assertNotNull(error);
-
+
Assert.assertEquals(PacketError.Type.cancel, error.getType());
Assert.assertEquals(PacketError.Condition.feature_not_implemented, error.getCondition());
}
-
+
}
\ No newline at end of file
diff --git a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/AffiliationsGetTest.java b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/AffiliationsGetTest.java
index 50cb83df..fe08228a 100644
--- a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/AffiliationsGetTest.java
+++ b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/AffiliationsGetTest.java
@@ -11,7 +11,6 @@
import org.buddycloud.channelserver.channel.ChannelManager;
import org.buddycloud.channelserver.packetHandler.iq.IQTestHandler;
import org.buddycloud.channelserver.packetprocessor.iq.namespace.pubsub.JabberPubsub;
-import org.buddycloud.channelserver.packetprocessor.iq.namespace.pubsub.PubSubElementProcessor;
import org.buddycloud.channelserver.pubsub.affiliation.Affiliations;
import org.buddycloud.channelserver.pubsub.model.NodeMembership;
import org.buddycloud.channelserver.pubsub.model.impl.NodeMembershipImpl;
@@ -19,6 +18,8 @@
import org.buddycloud.channelserver.utils.XMLConstants;
import org.buddycloud.channelserver.utils.node.item.payload.Buddycloud;
import org.dom4j.Element;
+import org.dom4j.Namespace;
+import org.dom4j.QName;
import org.dom4j.tree.BaseElement;
import org.junit.Before;
import org.junit.Test;
@@ -427,7 +428,8 @@ public void canRequestAffiliationsForEphemeralOnlyNodes() throws Exception {
request.getElement().element(XMLConstants.PUBSUB_ELEM)
.element(XMLConstants.AFFILIATIONS_ELEM);
affiliations.addNamespace("bc", Buddycloud.NS);
- affiliations.addAttribute("bc:ephemeral", "true");
+ affiliations.addAttribute(new QName(
+ XMLConstants.EPHEMERAL, Namespace.get(Buddycloud.NS)), "true");
try {
affiliationsGet.process(element, jid, request, null);
@@ -460,7 +462,8 @@ public void providingAnIncorrectValueForEphemeralAttributeResultsInNotEphemeralG
request.getElement().element(XMLConstants.PUBSUB_ELEM)
.element(XMLConstants.AFFILIATIONS_ELEM);
affiliations.addNamespace("bc", Buddycloud.NS);
- affiliations.addAttribute("bc:ephemeral", "sure");
+ affiliations.addAttribute(new QName(
+ XMLConstants.EPHEMERAL, Namespace.get(Buddycloud.NS)), "sure");
try {
affiliationsGet.process(element, jid, request, null);
diff --git a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/RecentItemsGetTest.java b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/RecentItemsGetTest.java
index bbb25074..2740c25f 100644
--- a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/RecentItemsGetTest.java
+++ b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/RecentItemsGetTest.java
@@ -375,7 +375,6 @@ public void testPagingAfterItemWithInvalidAfterId() throws Exception {
public void whenRequestingParentOnlyCorrectFlagIsSetOnDatabaseRequest() throws Exception {
Element rsm = new BaseElement(new QName("set", new Namespace("", "http://jabber.org/protocol/rsm")));
-
element.addAttribute("node", "/user/francisco@denmark.lit/posts");
IQ request = this.request.createCopy();
diff --git a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/RepliesGetTest.java b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/RepliesGetTest.java
index 368ae321..c5b22c98 100644
--- a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/RepliesGetTest.java
+++ b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/RepliesGetTest.java
@@ -160,7 +160,7 @@ public void testIfItemDoesNotExistErrorStanzaIsReturned() throws Exception {
@Test
public void testNoRepliesReturnsEmptyStanza() throws Exception {
- Mockito.when(channelManager.getNodeItemReplies(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyInt())).thenReturn(
+ Mockito.when(channelManager.getNodeItemReplies(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.eq(true), Mockito.anyInt())).thenReturn(
new ClosableIteratorImpl(new ArrayList().iterator()));
repliesGet.process(element, jid, request, null);
@@ -178,7 +178,7 @@ public void testOutgoingStanzaFormattedAsExpected() throws Exception {
expectedResults.add(new NodeItemImpl(TEST_NODE, "1", new Date(), "value1"));
expectedResults.add(new NodeItemImpl(TEST_NODE, "2", new Date(), "value2"));
- Mockito.when(channelManager.getNodeItemReplies(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyInt())).thenReturn(
+ Mockito.when(channelManager.getNodeItemReplies(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.eq(true), Mockito.anyInt())).thenReturn(
new ClosableIteratorImpl(expectedResults.iterator()));
repliesGet.process(element, jid, request, null);
@@ -198,7 +198,7 @@ public void testUnparsableItemEntriesAreSimplyIgnored() throws Exception {
expectedResults.add(new NodeItemImpl(TEST_NODE, "1", new Date(), "value1"));
expectedResults.add(new NodeItemImpl(TEST_NODE, "2", new Date(), "value2"));
- Mockito.when(channelManager.getNodeItemReplies(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyInt())).thenReturn(
+ Mockito.when(channelManager.getNodeItemReplies(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.eq(true), Mockito.anyInt())).thenReturn(
new ClosableIteratorImpl(expectedResults.iterator()));
repliesGet.process(element, jid, request, null);
@@ -225,7 +225,7 @@ public void testRsmElementIsAddedCorrectly() throws Exception {
expectedResults.add(new NodeItemImpl(TEST_NODE, "3", new Date(), "value3"));
expectedResults.add(new NodeItemImpl(TEST_NODE, "4", new Date(), "value4"));
- Mockito.when(channelManager.getNodeItemReplies(Mockito.anyString(), Mockito.anyString(), Mockito.eq("1"), Mockito.eq(4))).thenReturn(
+ Mockito.when(channelManager.getNodeItemReplies(Mockito.anyString(), Mockito.anyString(), Mockito.eq("1"), Mockito.eq(true), Mockito.eq(4))).thenReturn(
new ClosableIteratorImpl(expectedResults.iterator()));
repliesGet.process(element, jid, request, null);
@@ -241,4 +241,59 @@ public void testRsmElementIsAddedCorrectly() throws Exception {
Assert.assertEquals("4", rsmResult.elementText("last"));
Assert.assertEquals(String.valueOf(TOTAL_RESULTS), rsmResult.elementText("count"));
}
+
+ @Test
+ public void rsmStillAddedWhenThereAreNoResults() throws Exception {
+
+ Element rsm = request.getChildElement().addElement("set");
+ rsm.addNamespace("", RepliesGet.NS_RSM);
+ rsm.addElement("max").setText("4");
+ rsm.addElement("after").setText("1");
+
+ ArrayList expectedResults = new ArrayList();
+ Mockito.when(channelManager.getNodeItemReplies(Mockito.anyString(), Mockito.anyString(), Mockito.eq("1"), Mockito.eq(true), Mockito.eq(4))).thenReturn(
+ new ClosableIteratorImpl(expectedResults.iterator()));
+
+ Mockito.when(channelManager.getCountNodeItemReplies(Mockito.anyString(), Mockito.anyString())).thenReturn(0);
+
+ repliesGet.process(element, jid, request, null);
+ Packet response = queue.poll();
+
+ Element items = response.getElement().element("pubsub").element("items");
+
+ Assert.assertEquals("/user/channeluser@example.com/posts", items.attributeValue("node"));
+ Assert.assertEquals(0, items.elements("item").size());
+
+ Element rsmResult = response.getElement().element("pubsub").element("set");
+ Assert.assertNull(rsmResult.elementText("first"));
+ Assert.assertNull(rsmResult.elementText("last"));
+ Assert.assertEquals("0", rsmResult.elementText("count"));
+ }
+
+ @Test
+ public void providingBeforeValueInRsmElementInvokesPastItemLookup() throws Exception {
+
+ Element rsm = request.getChildElement().addElement("set");
+ rsm.addNamespace("", RepliesGet.NS_RSM);
+ rsm.addElement("max").setText("4");
+ rsm.addElement("after").setText("1");
+ rsm.addElement("before").setText("2");
+
+ ArrayList expectedResults = new ArrayList();
+ expectedResults.add(new NodeItemImpl(TEST_NODE, "1", new Date(), "value1"));
+ expectedResults.add(new NodeItemImpl(TEST_NODE, "2", new Date(), "value2"));
+ expectedResults.add(new NodeItemImpl(TEST_NODE, "3", new Date(), "value3"));
+ expectedResults.add(new NodeItemImpl(TEST_NODE, "4", new Date(), "value4"));
+
+ Mockito.when(channelManager.getNodeItemReplies(Mockito.anyString(), Mockito.anyString(), Mockito.eq("2"), Mockito.eq(false), Mockito.eq(4))).thenReturn(
+ new ClosableIteratorImpl(expectedResults.iterator()));
+
+ repliesGet.process(element, jid, request, null);
+ Packet response = queue.poll();
+
+ Element items = response.getElement().element("pubsub").element("items");
+
+ Assert.assertEquals(4, items.elements("item").size());
+ }
+
}
diff --git a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/SubscriptionsGetTest.java b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/SubscriptionsGetTest.java
index 2263c4df..6685797c 100644
--- a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/SubscriptionsGetTest.java
+++ b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/SubscriptionsGetTest.java
@@ -17,6 +17,8 @@
import org.buddycloud.channelserver.utils.XMLConstants;
import org.buddycloud.channelserver.utils.node.item.payload.Buddycloud;
import org.dom4j.Element;
+import org.dom4j.Namespace;
+import org.dom4j.QName;
import org.dom4j.tree.BaseElement;
import org.junit.Before;
import org.junit.Test;
@@ -218,7 +220,8 @@ public void canRequestUserSubscriptionsForEphemeralOnlyNodes() throws Exception
request.getElement().element(XMLConstants.PUBSUB_ELEM)
.element(XMLConstants.SUBSCRIPTIONS_ELEM);
subscriptions.addNamespace("bc", Buddycloud.NS);
- subscriptions.addAttribute("bc:ephemeral", "true");
+ subscriptions.addAttribute(new QName(
+ XMLConstants.EPHEMERAL, Namespace.get(Buddycloud.NS)), "true");
try {
subscriptionsGet.process(element, jid, request, null);
@@ -246,7 +249,8 @@ public void providingAnIncorrectValueForEphemeralAttributeResultsInNotEphemeralG
request.getElement().element(XMLConstants.PUBSUB_ELEM)
.element(XMLConstants.SUBSCRIPTIONS_ELEM);
subscriptions.addNamespace("bc", Buddycloud.NS);
- subscriptions.addAttribute("bc:ephemeral", "sure");
+ subscriptions.addAttribute(new QName(
+ XMLConstants.EPHEMERAL, Namespace.get(Buddycloud.NS)), "sure");
try {
subscriptionsGet.process(element, jid, request, null);
diff --git a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/items/NodeItemsGetTest.java b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/items/NodeItemsGetTest.java
index 49c72018..f5bc78b7 100644
--- a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/items/NodeItemsGetTest.java
+++ b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/items/NodeItemsGetTest.java
@@ -29,6 +29,7 @@
import org.buddycloud.channelserver.pubsub.model.impl.NodeItemImpl;
import org.buddycloud.channelserver.pubsub.model.impl.NodeMembershipImpl;
import org.buddycloud.channelserver.pubsub.subscription.Subscriptions;
+import org.buddycloud.channelserver.utils.XMLConstants;
import org.buddycloud.channelserver.utils.node.NodeAclRefuseReason;
import org.buddycloud.channelserver.utils.node.NodeViewAcl;
import org.dom4j.Element;
@@ -51,7 +52,7 @@ public class NodeItemsGetTest extends IQTestHandler {
private Element element;
private BlockingQueue queue = new LinkedBlockingQueue();
- private String node = "/user/pamela@denmark.lit/posts";
+ private String node = "/user/francisco@denmark.lit/posts";
private JID jid = new JID("juliet@shakespeare.lit");
private ChannelManager channelManager;
private NodeViewAcl nodeViewAcl;
@@ -106,10 +107,12 @@ public void testExternalNodeReturnsExpectedStanzaEarly() throws Exception {
Configuration.getInstance().putProperty(
Configuration.CONFIGURATION_LOCAL_DOMAIN_CHECKER, Boolean.FALSE.toString());
- element.addAttribute("node", "/user/user@remote-server.com/posts");
+ IQ request = this.request.createCopy();
+ request.getChildElement().element(XMLConstants.ITEMS_ELEM).attribute(XMLConstants.NODE_ATTR).detach();
+ request.getChildElement().element(XMLConstants.ITEMS_ELEM).addAttribute(XMLConstants.NODE_ATTR, "/user/user@remote-server.com/posts");
itemsGet.process(element, jid, request, null);
- Packet response = queue.poll(100, TimeUnit.MILLISECONDS);
+ Packet response = queue.poll();
Element element = response.getElement();
@@ -122,14 +125,13 @@ public void testExternalNodeReturnsExpectedStanzaEarly() throws Exception {
}
@Test
- public void testNodeWhichDoesntExistReturnsNotFoundStanza()
+ public void nodeWhichDoesntExistReturnsNotFoundStanza()
throws Exception {
Mockito.when(channelManager.nodeExists(node)).thenReturn(false);
- element.addAttribute("node", node);
itemsGet.process(element, jid, request, null);
- Packet response = queue.poll(100, TimeUnit.MILLISECONDS);
+ Packet response = queue.poll();
PacketError error = response.getError();
Assert.assertNotNull(error);
@@ -139,15 +141,14 @@ public void testNodeWhichDoesntExistReturnsNotFoundStanza()
}
@Test
- public void testNodeStoreExceptionReturnsInternalServerErrorStanza()
+ public void nodeStoreExceptionReturnsInternalServerErrorStanza()
throws Exception {
- element.addAttribute("node", node);
Mockito.when(channelManager.nodeExists(node)).thenThrow(
NodeStoreException.class);
itemsGet.process(element, jid, request, null);
- Packet response = queue.poll(100, TimeUnit.MILLISECONDS);
+ Packet response = queue.poll();
PacketError error = response.getError();
Assert.assertNotNull(error);
@@ -160,8 +161,6 @@ public void testNodeStoreExceptionReturnsInternalServerErrorStanza()
public void testSubscriptionIncompatibleWithItemRetrievalReturnsExpectedStanza()
throws Exception {
- element.addAttribute("node", node);
-
Mockito.when(channelManager.nodeExists(node)).thenReturn(true);
Mockito.when(channelManager.getNodeMembership(node, jid)).thenReturn(
new NodeMembershipImpl(node, jid, Subscriptions.none,
@@ -196,8 +195,6 @@ public void testStandardNodeWithNoItemsReturnsNoItems() throws Exception {
AccessModels accessModel = AccessModels.authorize;
- element.addAttribute("node", node);
-
NodeMembershipImpl membership = Mockito.mock(NodeMembershipImpl.class);
Mockito.when(membership.getAffiliation()).thenReturn(
Affiliations.member);
@@ -208,7 +205,7 @@ public void testStandardNodeWithNoItemsReturnsNoItems() throws Exception {
Mockito.when(
channelManager.getNodeItems(Mockito.anyString(),
- Mockito.anyString(), Mockito.anyInt()))
+ Mockito.anyString(), Mockito.anyInt(), Mockito.eq(false)))
.thenReturn(null);
Mockito.when(channelManager.nodeExists(node)).thenReturn(true);
@@ -237,8 +234,6 @@ public void testUnparsableNodeEntryIsIgnoredInItemsResponse()
throws Exception {
AccessModels accessModel = AccessModels.authorize;
- element.addAttribute("node", node);
-
NodeMembershipImpl membership = Mockito.mock(NodeMembershipImpl.class);
Mockito.when(membership.getAffiliation()).thenReturn(
Affiliations.member);
@@ -260,7 +255,7 @@ public void testUnparsableNodeEntryIsIgnoredInItemsResponse()
Mockito.doReturn(itemList)
.when(channelManager)
.getNodeItems(Mockito.anyString(), Mockito.anyString(),
- Mockito.anyInt());
+ Mockito.anyInt(), Mockito.eq(false));
Mockito.when(channelManager.nodeExists(node)).thenReturn(true);
@@ -288,8 +283,6 @@ public void testUnparsableNodeEntryIsIgnoredInItemsResponse()
public void testPostsNodeReturnsItemsAsExpected() throws Exception {
AccessModels accessModel = AccessModels.authorize;
- element.addAttribute("node", node);
-
NodeMembershipImpl membership = Mockito.mock(NodeMembershipImpl.class);
Mockito.when(membership.getAffiliation()).thenReturn(
Affiliations.member);
@@ -310,7 +303,7 @@ public void testPostsNodeReturnsItemsAsExpected() throws Exception {
Mockito.doReturn(itemList)
.when(channelManager)
.getNodeItems(Mockito.anyString(), Mockito.anyString(),
- Mockito.anyInt());
+ Mockito.anyInt(), Mockito.eq(false));
Mockito.when(channelManager.nodeExists(node)).thenReturn(true);
@@ -323,7 +316,7 @@ public void testPostsNodeReturnsItemsAsExpected() throws Exception {
itemsGet.setNodeViewAcl(nodeViewAclMock);
itemsGet.process(element, jid, request, null);
- Packet response = queue.poll(100, TimeUnit.MILLISECONDS);
+ Packet response = queue.poll();
Element element = response.getElement();
Assert.assertEquals(IQ.Type.result.toString(),
@@ -348,8 +341,6 @@ public void testPagingAfterItem() throws Exception {
rsm.addElement("after").setText(
"tag:denmark.lit,/user/" + node + "/posts,item-id");
- element.addAttribute("node", node);
-
Mockito.when(channelManager.nodeExists(anyString())).thenReturn(true);
NodeMembershipImpl membership = Mockito.mock(NodeMembershipImpl.class);
@@ -363,7 +354,7 @@ public void testPagingAfterItem() throws Exception {
itemsGet.process(element, jid, request, rsm);
verify(channelManager).getNodeItems(anyString(), eq("item-id"),
- anyInt());
+ anyInt(), Mockito.eq(false));
}
@Test
@@ -373,14 +364,12 @@ public void pagingAfterItemWithPlainNodeID() throws Exception {
rsm.addElement("after").setText("item-id");
- element.addAttribute("node", node);
-
Mockito.when(channelManager.nodeExists(anyString())).thenReturn(true);
itemsGet.process(element, jid, request, rsm);
verify(channelManager).getNodeItems(anyString(), eq("item-id"),
- anyInt());
+ anyInt(), Mockito.eq(false));
}
@Test
@@ -397,7 +386,7 @@ public void pagingAfterItemWithInvalidNode() throws Exception {
itemsGet.process(element, jid, request, rsm);
- Packet p = queue.poll(100, TimeUnit.MILLISECONDS);
+ Packet p = queue.poll();
assertEquals("Error expected", "error",
p.getElement().attributeValue("type"));
@@ -424,35 +413,176 @@ public void canRetrieveSingleItem() throws Exception {
String id = "12345";
String payload = "entry text";
- element.addAttribute("node", node);
- element.addElement("item").addAttribute("id", id);
-
Mockito.when(channelManager.nodeExists(Mockito.anyString()))
.thenReturn(true);
- NodeItem item = new NodeItemImpl(node, id, new Date(), payload);
+ NodeItem dbItem = new NodeItemImpl(node, id, new Date(), payload);
Mockito.when(
- channelManager.getNodeItem(Mockito.anyString(),
- Mockito.anyString())).thenReturn(item);
+ channelManager.getNodeItem(Mockito.eq(node),
+ Mockito.eq(id))).thenReturn(dbItem);
+ IQ request = this.request.createCopy();
+ Element item = request.getChildElement().element("items").addElement("item");
+ item.addAttribute("id", id);
+ System.out.println(request.toXML());
itemsGet.process(element, jid, request, null);
- Packet response = queue.poll();
+ IQ response = (IQ) queue.poll();
- Element element = response.getElement();
+ Element element = response.getChildElement();
+ Element items = element.element("items");
- Assert.assertEquals(IQ.Type.result.toString(),
- element.attributeValue("type"));
- Assert.assertEquals(node, element.element("pubsub").element("items")
+ Assert.assertEquals(IQ.Type.result,
+ response.getType());
+ Assert.assertEquals(node, items
.attributeValue("node"));
- Assert.assertEquals(1, element.element("pubsub").element("items")
+ Assert.assertEquals(1, items
.nodeCount());
- Assert.assertEquals(node, element.element("pubsub").element("items")
+ Assert.assertEquals(node, items
.attributeValue("node"));
- Assert.assertEquals(id, element.element("pubsub").element("items")
+ Assert.assertEquals(id, items
.element("item").attributeValue("id"));
Assert.assertEquals("entry text",
- element.element("pubsub").element("items").element("item")
+ items.element("item")
.elementText("entry"));
}
+
+ @Test
+ public void settingParentOnlyToTrueRequestsParentOnlyItems() throws Exception {
+
+ AccessModels accessModel = AccessModels.authorize;
+
+ NodeMembershipImpl membership = Mockito.mock(NodeMembershipImpl.class);
+ Mockito.when(membership.getAffiliation()).thenReturn(
+ Affiliations.member);
+ Mockito.when(membership.getSubscription()).thenReturn(
+ Subscriptions.subscribed);
+ Mockito.when(channelManager.getNodeMembership(node, jid)).thenReturn(
+ membership);
+
+ NodeItem item = Mockito.mock(NodeItem.class);
+ Mockito.when(item.getId()).thenReturn("id");
+ Mockito.when(item.getNodeId()).thenReturn(node);
+ Mockito.when(item.getPayload()).thenReturn("entry text");
+ NodeItem[] items = new NodeItem[2];
+ items[0] = item;
+ items[1] = item;
+ CloseableIterator itemList = new ClosableIteratorImpl(
+ Arrays.asList(items).iterator());
+ Mockito.doReturn(itemList)
+ .when(channelManager)
+ .getNodeItems(Mockito.anyString(), Mockito.anyString(),
+ Mockito.anyInt(), Mockito.eq(true));
+
+ Mockito.when(channelManager.nodeExists(node)).thenReturn(true);
+
+ NodeViewAcl nodeViewAclMock = Mockito.mock(NodeViewAcl.class);
+ Mockito.doReturn(true)
+ .when(nodeViewAclMock)
+ .canViewNode(Mockito.anyString(),
+ Mockito.any(NodeMembership.class),
+ Mockito.any(AccessModels.class), Mockito.anyBoolean());
+ itemsGet.setNodeViewAcl(nodeViewAclMock);
+
+ IQ request = this.request.createCopy();
+ request.getChildElement().element("items").addAttribute("parent-only", "true");
+ itemsGet.process(element, jid, request, null);
+ Packet response = queue.poll();
+
+ Assert.assertEquals(2, response.getElement().element("pubsub").element("items")
+ .nodeCount());
+ }
+
+ @Test
+ public void settingParentOnlyToOneRequestsParentOnlyItems() throws Exception {
+
+ AccessModels accessModel = AccessModels.authorize;
+
+ NodeMembershipImpl membership = Mockito.mock(NodeMembershipImpl.class);
+ Mockito.when(membership.getAffiliation()).thenReturn(
+ Affiliations.member);
+ Mockito.when(membership.getSubscription()).thenReturn(
+ Subscriptions.subscribed);
+ Mockito.when(channelManager.getNodeMembership(node, jid)).thenReturn(
+ membership);
+
+ NodeItem item = Mockito.mock(NodeItem.class);
+ Mockito.when(item.getId()).thenReturn("id");
+ Mockito.when(item.getNodeId()).thenReturn(node);
+ Mockito.when(item.getPayload()).thenReturn("entry text");
+ NodeItem[] items = new NodeItem[2];
+ items[0] = item;
+ items[1] = item;
+ CloseableIterator itemList = new ClosableIteratorImpl(
+ Arrays.asList(items).iterator());
+ Mockito.doReturn(itemList)
+ .when(channelManager)
+ .getNodeItems(Mockito.anyString(), Mockito.anyString(),
+ Mockito.anyInt(), Mockito.eq(true));
+
+ Mockito.when(channelManager.nodeExists(node)).thenReturn(true);
+
+ NodeViewAcl nodeViewAclMock = Mockito.mock(NodeViewAcl.class);
+ Mockito.doReturn(true)
+ .when(nodeViewAclMock)
+ .canViewNode(Mockito.anyString(),
+ Mockito.any(NodeMembership.class),
+ Mockito.any(AccessModels.class), Mockito.anyBoolean());
+ itemsGet.setNodeViewAcl(nodeViewAclMock);
+
+ IQ request = this.request.createCopy();
+ request.getChildElement().element("items").addAttribute("parent-only", "1");
+ itemsGet.process(element, jid, request, null);
+ Packet response = queue.poll();
+
+ Assert.assertEquals(2, response.getElement().element("pubsub").element("items")
+ .nodeCount());
+ }
+
+ @Test
+ public void settingIllegalParentOnlyAttributeDoesNotRequestParentOnlyItems() throws Exception {
+
+ AccessModels accessModel = AccessModels.authorize;
+
+ NodeMembershipImpl membership = Mockito.mock(NodeMembershipImpl.class);
+ Mockito.when(membership.getAffiliation()).thenReturn(
+ Affiliations.member);
+ Mockito.when(membership.getSubscription()).thenReturn(
+ Subscriptions.subscribed);
+ Mockito.when(channelManager.getNodeMembership(node, jid)).thenReturn(
+ membership);
+
+ NodeItem item = Mockito.mock(NodeItem.class);
+ Mockito.when(item.getId()).thenReturn("id");
+ Mockito.when(item.getNodeId()).thenReturn(node);
+ Mockito.when(item.getPayload()).thenReturn("entry text");
+ NodeItem[] items = new NodeItem[2];
+ items[0] = item;
+ items[1] = item;
+ CloseableIterator itemList = new ClosableIteratorImpl(
+ Arrays.asList(items).iterator());
+ Mockito.doReturn(itemList)
+ .when(channelManager)
+ .getNodeItems(Mockito.anyString(), Mockito.anyString(),
+ Mockito.anyInt(), Mockito.eq(false));
+
+ Mockito.when(channelManager.nodeExists(node)).thenReturn(true);
+
+ NodeViewAcl nodeViewAclMock = Mockito.mock(NodeViewAcl.class);
+ Mockito.doReturn(true)
+ .when(nodeViewAclMock)
+ .canViewNode(Mockito.anyString(),
+ Mockito.any(NodeMembership.class),
+ Mockito.any(AccessModels.class), Mockito.anyBoolean());
+ itemsGet.setNodeViewAcl(nodeViewAclMock);
+
+ IQ request = this.request.createCopy();
+ request.getChildElement().element("items").addAttribute("parent-only", "invalidvalue");
+ itemsGet.process(element, jid, request, null);
+ Packet response = queue.poll();
+
+ Assert.assertEquals(2, response.getElement().element("pubsub").element("items")
+ .nodeCount());
+ }
}
+
diff --git a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/AffiliationEventTest.java b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/AffiliationEventTest.java
index 2d6483ed..5960af12 100644
--- a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/AffiliationEventTest.java
+++ b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/AffiliationEventTest.java
@@ -64,7 +64,6 @@ public void setUp() throws Exception {
queue = new LinkedBlockingQueue();
event = new AffiliationEvent(queue, channelManager);
request = readStanzaAsIq("/iq/pubsub/affiliation/affiliationChange.stanza");
- event.setServerDomain("shakespeare.lit");
element = new BaseElement("affiliations");
element.addAttribute("node", node);
diff --git a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/ItemDeleteTest.java b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/ItemDeleteTest.java
index bccbaa74..16ddb7b5 100644
--- a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/ItemDeleteTest.java
+++ b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/ItemDeleteTest.java
@@ -52,8 +52,6 @@ public void setUp() throws Exception {
itemDelete = new ItemDelete(queue, channelManager);
request = readStanzaAsIq("/iq/pubsub/item/delete/request.stanza");
- itemDelete.setServerDomain("shakespeare.lit");
-
element = new BaseElement("retract");
element.addAttribute("node", node);
@@ -183,8 +181,9 @@ public void testProvidingEmptyItemIdReturnsError() throws Exception {
}
@Test
- public void testItemWhichDoesntExistReturnsItemNotFoundError()
+ public void itemWhichDoesntExistReturnsItemNotFoundError()
throws Exception {
+
Mockito.when(channelManager.nodeExists(node)).thenReturn(true);
Mockito.when(channelManager.getNodeItem(node, "item-id")).thenReturn(
null);
@@ -192,7 +191,7 @@ public void testItemWhichDoesntExistReturnsItemNotFoundError()
itemDelete.process(element, jid, request, null);
- Packet response = queue.poll(100, TimeUnit.MILLISECONDS);
+ Packet response = queue.poll();
PacketError error = response.getError();
Assert.assertNotNull(error);
@@ -287,12 +286,12 @@ public void testSuccessfulRequestSendsResponseStanza() throws Exception {
itemDelete.process(element, jid, request, null);
Mockito.verify(channelManager).deleteNodeItemById(node, "item-id");
- IQ response = (IQ) queue.poll(100, TimeUnit.MILLISECONDS);
+ IQ response = (IQ) queue.poll();
Assert.assertEquals(IQ.Type.result.toString(), response.getElement()
.attribute("type").getValue());
// Check that no notifications are sent
- Packet notification = queue.poll(100, TimeUnit.MILLISECONDS);
+ Packet notification = queue.poll();
Assert.assertNull(notification);
}
@@ -397,7 +396,7 @@ public void doesNotRequestThreadWhenDealingWithReply() throws Exception {
Mockito.doThrow(Exception.class)
.when(channelManager)
.getNodeItemReplies(Mockito.anyString(), Mockito.anyString(),
- Mockito.anyString(), Mockito.anyInt());
+ Mockito.anyString(), Mockito.anyBoolean(), Mockito.anyInt());
Mockito.doReturn(new ResultSetImpl(subscriptions))
.when(channelManager).getNodeSubscriptionListeners(node);
@@ -432,7 +431,7 @@ public void requestsThreadWhenDeletingParentPost() throws Exception {
Mockito.when(channelManager.getNodeItem(node, "item-id")).thenReturn(
nodeItem);
Mockito.when(channelManager.getNodeItemReplies(Mockito.eq(node), Mockito.eq("item-id"),
- Mockito.anyString(), Mockito.eq(-1))).thenReturn(new ClosableIteratorImpl(replies
+ Mockito.anyString(), Mockito.anyBoolean(), Mockito.eq(-1))).thenReturn(new ClosableIteratorImpl(replies
.iterator()));
Mockito.doReturn(new ResultSetImpl(subscriptions))
@@ -487,4 +486,32 @@ public void requestsThreadWhenDeletingParentPost() throws Exception {
notification.getElement().element("event").element("items")
.element("retract").attributeValue("id"));
}
+
+ @Test
+ public void canDeleteItemUsingAFullItemId() throws Exception {
+
+ NodeItem nodeItem = new NodeItemImpl(node, "item-id", new Date(),
+ payload.replaceAll("romeo@shakespeare.lit",
+ "juliet@shakespeare.lit"), "item-id");
+
+ Mockito.when(channelManager.nodeExists(node)).thenReturn(true);
+ Mockito.when(
+ channelManager.getNodeItem(Mockito.eq("/user/capulet@shakespeare.lit/posts"),
+ Mockito.eq("item-id"))).thenReturn(nodeItem);
+
+ IQ request = toIq(readStanzaAsString("/iq/pubsub/item/delete/request-full-id.stanza"));
+
+ itemDelete.setChannelManager(channelManager);
+
+ itemDelete.process(element, jid, request, null);
+
+ Mockito.verify(channelManager).deleteNodeItemById(node, "item-id");
+ IQ response = (IQ) queue.poll();
+
+ Assert.assertEquals(IQ.Type.result.toString(), response.getElement()
+ .attribute("type").getValue());
+ // Check that no notifications are sent
+ Packet notification = queue.poll();
+ Assert.assertNull(notification);
+ }
}
diff --git a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/NodeConfigureTest.java b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/NodeConfigureTest.java
index 3e41e5e9..4a22c5f0 100644
--- a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/NodeConfigureTest.java
+++ b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/NodeConfigureTest.java
@@ -50,8 +50,6 @@ public void setUp() throws Exception {
jid = new JID("juliet@shakespeare.lit");
request = readStanzaAsIq("/iq/pubsub/channel/configure/request.stanza");
- nodeConfigure.setServerDomain("shakespeare.lit");
-
element = new BaseElement("create");
element.addAttribute("node", "/user/capulet@shakespeare.lit/posts");
}
diff --git a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/NodeCreateTest.java b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/NodeCreateTest.java
index 134b35e8..d26ff442 100644
--- a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/NodeCreateTest.java
+++ b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/NodeCreateTest.java
@@ -46,8 +46,6 @@ public void setUp() throws Exception {
jid = new JID("juliet@shakespeare.lit");
request = readStanzaAsIq("/iq/pubsub/channel/create/request.stanza");
- nodeCreate.setServerDomain("shakespeare.lit");
-
element = new BaseElement("create");
element.addAttribute("node", node);
}
@@ -106,6 +104,11 @@ public void testRequestingAlreadyExistingNodeReturnsErrorStanza()
public void testUnauthenticatedUserCanNotCreateNode() throws Exception {
JID jid = new JID("juliet@anon.shakespeare.lit");
+ Configuration.getInstance().remove(
+ Configuration.CONFIGURATION_LOCAL_DOMAIN_CHECKER);
+ Configuration.getInstance().putProperty(
+ Configuration.CONFIGURATION_SERVER_DOMAIN, "shakespeare.lit");
+
nodeCreate.process(element, jid, request, null);
Packet response = queue.poll(100, TimeUnit.MILLISECONDS);
@@ -139,26 +142,24 @@ public void testInvalidlyFormattedNodeReturnsError() throws Exception {
}
@Test
- public void testNewNodeMustBeOnADomainSupportedByCurrentServer()
- throws Exception {
+ public void testNodeFromUnknownDomain() throws Exception {
element.addAttribute("node", "/user/capulet@shakespearelit/posts");
- nodeCreate.setTopicsDomain("topics.shakespeare.lit");
-
+ Configuration.getInstance().putProperty(
+ Configuration.CONFIGURATION_LOCAL_DOMAIN_CHECKER, Boolean.FALSE.toString());
+
nodeCreate.process(element, jid, request, null);
Packet response = queue.poll(100, TimeUnit.MILLISECONDS);
- PacketError error = response.getError();
- Assert.assertNotNull(error);
- Assert.assertEquals(PacketError.Type.modify, error.getType());
- Assert.assertEquals(PacketError.Condition.not_acceptable, error.getCondition());
+ Assert.assertNull(response.getError());
+ Assert.assertNotNull(response.getElement().element("pubsub").element("actor"));
/**
* Add this check back in once Tinder supports xmlns on standard
* conditions Assert.assertEquals(JabberPubsub.NS_XMPP_STANZAS,
* error.getApplicationConditionNamespaceURI());
*/
}
-
+
@Test
public void testchannelManagerFailureReturnsInternalServerErrorResponse()
throws Exception {
@@ -270,4 +271,5 @@ public void testFailingNodeConfigurationReturnsErrorStanza()
* error.getApplicationConditionNamespaceURI());
*/
}
+
}
diff --git a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/NodeDeleteTest.java b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/NodeDeleteTest.java
index 717795db..46c1bd47 100644
--- a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/NodeDeleteTest.java
+++ b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/NodeDeleteTest.java
@@ -49,7 +49,6 @@ public void setUp() throws Exception {
this.queue = new LinkedBlockingQueue();
this.nodeDelete = new NodeDelete(queue, channelManager);
- this.nodeDelete.setServerDomain("shakespeare.lit");
this.element = new BaseElement("delete");
Configuration.getInstance().putProperty(Configuration.CONFIGURATION_LOCAL_DOMAIN_CHECKER,
Boolean.TRUE.toString());
@@ -139,8 +138,13 @@ public void testNotRegisteredActor() throws Exception {
String node = deleteEl.attributeValue("node");
Mockito.when(channelManager.nodeExists(node)).thenReturn(true);
- nodeDelete.setServerDomain("fake.domain");
+
+ Configuration.getInstance().remove(
+ Configuration.CONFIGURATION_LOCAL_DOMAIN_CHECKER);
+ Configuration.getInstance().putProperty(
+ Configuration.CONFIGURATION_SERVER_DOMAIN, "shakespeare.lit");
+ JID jid = new JID("juliet@anon.shakespeare.lit");
nodeDelete.process(deleteEl, jid, request, null);
Packet response = queue.poll();
@@ -214,13 +218,14 @@ public void testNodeFromUnknownDomain() throws Exception {
String node = deleteEl.attributeValue("node");
Mockito.when(channelManager.nodeExists(node)).thenReturn(true);
+ Configuration.getInstance().putProperty(
+ Configuration.CONFIGURATION_LOCAL_DOMAIN_CHECKER, Boolean.FALSE.toString());
+
nodeDelete.process(deleteEl, jid, request, null);
Packet response = queue.poll();
- PacketError error = response.getError();
- Assert.assertNotNull(error);
- Assert.assertEquals(PacketError.Type.modify, error.getType());
- Assert.assertEquals(PacketError.Condition.not_acceptable, error.getCondition());
+ Assert.assertNull(response.getError());
+ Assert.assertNotNull(response.getElement().element("pubsub").element("actor"));
}
@Test
diff --git a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/PublishTest.java b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/PublishTest.java
index 3943b22f..ef619c66 100644
--- a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/PublishTest.java
+++ b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/PublishTest.java
@@ -59,7 +59,6 @@ public void setUp() throws Exception {
jid = new JID("juliet@shakespeare.lit/balcony");
request = readStanzaAsIq("/iq/pubsub/publish/request.stanza");
- publish.setServerDomain("shakespeare.lit");
publish.setChannelManager(channelManager);
publish.setEntryValidator(validateEntry);
diff --git a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/SubscribeSetTest.java b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/SubscribeSetTest.java
index d8402ad0..9a1ef808 100644
--- a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/SubscribeSetTest.java
+++ b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/SubscribeSetTest.java
@@ -55,7 +55,6 @@ public void setUp() throws Exception {
queue = new LinkedBlockingQueue();
subscribe = new SubscribeSet(queue, channelManager);
request = readStanzaAsIq("/iq/pubsub/subscribe/request.stanza");
- subscribe.setServerDomain("shakespeare.lit");
element = new BaseElement("subscribe");
element.addAttribute("node", node);
diff --git a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/SubscriptionEventTest.java b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/SubscriptionEventTest.java
index 5127af38..730d5a8c 100644
--- a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/SubscriptionEventTest.java
+++ b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/SubscriptionEventTest.java
@@ -57,7 +57,6 @@ public void setUp() throws Exception {
queue = new LinkedBlockingQueue();
event = new SubscriptionEvent(queue, dataStore);
request = readStanzaAsIq("/iq/pubsub/subscribe/authorizationPendingGrantReply.stanza");
- event.setServerDomain("shakespeare.lit");
element = new BaseElement("subscriptions");
element.addAttribute("node", node);
diff --git a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/UnsubscribeSetTest.java b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/UnsubscribeSetTest.java
index 96d7fa6f..8c897eba 100644
--- a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/UnsubscribeSetTest.java
+++ b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/UnsubscribeSetTest.java
@@ -55,7 +55,6 @@ public void setUp() throws Exception {
queue = new LinkedBlockingQueue();
unsubscribe = new UnsubscribeSet(queue, channelManager);
request = readStanzaAsIq("/iq/pubsub/unsubscribe/request.stanza");
- unsubscribe.setServerDomain("shakespeare.lit");
element = new BaseElement("unsubscribe");
element.addAttribute("node", node);
diff --git a/src/test/resources/org/buddycloud/channelserver/testing/jdbc/scripts/node_1.sql b/src/test/resources/org/buddycloud/channelserver/testing/jdbc/scripts/node_1.sql
index e6236f0a..dc6fec36 100644
--- a/src/test/resources/org/buddycloud/channelserver/testing/jdbc/scripts/node_1.sql
+++ b/src/test/resources/org/buddycloud/channelserver/testing/jdbc/scripts/node_1.sql
@@ -111,4 +111,4 @@ INSERT INTO "items" ("node", "id", "updated", "xml") VALUES ('users/node1@server
note
');
-
\ No newline at end of file
+
diff --git a/src/test/resources/org/buddycloud/channelserver/testing/jdbc/scripts/node_4.sql b/src/test/resources/org/buddycloud/channelserver/testing/jdbc/scripts/node_4.sql
new file mode 100644
index 00000000..bd32dcb2
--- /dev/null
+++ b/src/test/resources/org/buddycloud/channelserver/testing/jdbc/scripts/node_4.sql
@@ -0,0 +1,56 @@
+INSERT INTO "items" ("node", "id", "updated", "xml", "in_reply_to") VALUES ('users/node1@server1/posts', 'a6', TIMESTAMP '2010-01-08 11:45:12', '
+ 2010-01-08T11:45:12Z
+
+ user2@server1
+ user2@server1
+
+ Test 5
+
+ London, England
+ London
+ England
+
+
+ post
+
+ note
+
+ ', 'a1');
+
+INSERT INTO "items" ("node", "id", "updated", "xml", "in_reply_to") VALUES ('users/node1@server1/posts', 'a7', TIMESTAMP '2010-01-06 22:32:12', '
+ 2010-01-06T22:32:12Z
+
+ user1@server1
+ user1@server1
+
+ Test 2
+
+ Paris, France
+ Paris
+ France
+
+
+ post
+
+ note
+
+ ', 'a1');
+
+INSERT INTO "items" ("node", "id", "updated", "xml", "in_reply_to") VALUES ('users/node1@server1/posts', 'a8', TIMESTAMP '2010-01-06 22:32:12', '
+ 2010-01-06T22:32:12Z
+
+ user1@server1
+ user1@server1
+
+ Test 2
+
+ Paris, France
+ Paris
+ France
+
+
+ post
+
+ note
+
+ ', NULL);
diff --git a/src/test/resources/stanzas/iq/pubsub/item/delete/request-full-id.stanza b/src/test/resources/stanzas/iq/pubsub/item/delete/request-full-id.stanza
new file mode 100644
index 00000000..f9a9fb7f
--- /dev/null
+++ b/src/test/resources/stanzas/iq/pubsub/item/delete/request-full-id.stanza
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/stanzas/iq/pubsub/spoof-actor.stanza b/src/test/resources/stanzas/iq/pubsub/spoof-actor.stanza
new file mode 100644
index 00000000..dfd63397
--- /dev/null
+++ b/src/test/resources/stanzas/iq/pubsub/spoof-actor.stanza
@@ -0,0 +1,9 @@
+
+
+
+ francisco@denmark.lit
+
+