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. -[![Build Status](https://travis-ci.org/buddycloud/buddycloud-server-java.png?branch=master)](https://travis-ci.org/buddycloud/buddycloud-server-java) [![Coverage Status](https://img.shields.io/coveralls/buddycloud/buddycloud-server-java.svg)](https://coveralls.io/r/buddycloud/buddycloud-server-java) +[![Build Status](https://travis-ci.org/buddycloud/buddycloud-server-java.png?branch=master)](https://travis-ci.org/buddycloud/buddycloud-server-java) [![Coverage Status](https://img.shields.io/coveralls/buddycloud/buddycloud-server-java.svg)](https://coveralls.io/r/buddycloud/buddycloud-server-java) [ ![Download](https://api.bintray.com/packages/buddycloud/buddycloud-server-java/builds/images/download.svg) ](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 + +