Skip to content

Commit 26b73f2

Browse files
committed
fixes #133: Add support to query for PMs in MUC archives
In MUCs, Private Messages (PMs) can be exchanged between two participants. When a participant retrieves its MUC messages, the PMs that they were involved in should also be returned. The pre-existing implementation stores PMs as regular one-to-one messages. By doing this, the context of them being exchanged in a MUC is lost. This commit additionally stores the PMs in context of a MUC (an additional database column is created for this). To be able to query for PMs, it is needed to provide, aside of the archive that's being queried, the person for which messages are queried. Note that this is specific to queries of MUC archives, as for Personal archives, these values are equal (the person owning the archive is the one querying it).
1 parent ba88819 commit 26b73f2

27 files changed

+625
-212
lines changed

changelog.html

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ <h1>
4848
<ul>
4949
<li>[<a href='https://issues.igniterealtime.org/browse/OF-2157'>OF-2157</a>] - SequenceManager generated IDs are unreliable whilst clustering.</li>
5050
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/19'>Issue #19</a>] - Monitoring / Archive plugin fails to reconstruct archived stanza</li>
51+
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/133'>Issue #133</a>] - Allow PMs to be returned when querying MUC archives</li>
5152
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/137'>Issue #137</a>] - MUC messages duplicated as one-on-one messages</li>
5253
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/138'>Issue #138</a>] - Stanzas not always stored for one-to-one messages whilst clustered</li>
5354
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/139'>Issue #139</a>] - Reduce code complexity</li>

plugin.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<minServerVersion>4.4.0</minServerVersion>
1111
<minJavaVersion>1.8</minJavaVersion>
1212
<databaseKey>monitoring</databaseKey>
13-
<databaseVersion>6</databaseVersion>
13+
<databaseVersion>7</databaseVersion>
1414

1515
<adminconsole>
1616
<tab id="tab-server">

src/database/monitoring_db2.sql

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
INSERT INTO ofVersion (name, version) VALUES ('monitoring', 6);
2+
INSERT INTO ofVersion (name, version) VALUES ('monitoring', 7);
33

44
CREATE TABLE ofConversation (
55
conversationID INTEGER NOT NULL,
@@ -34,17 +34,19 @@ CREATE TABLE ofMessageArchive (
3434
toJIDResource VARCHAR(255) NULL,
3535
sentDate BIGINT NOT NULL,
3636
stanza LONG VARCHAR NULL,
37-
body LONG VARCHAR
37+
body LONG VARCHAR NULL,
38+
isPMforJID VARCHAR(1024) NULL
3839
);
3940
CREATE INDEX ofMessageArchive_con_idx ON ofMessageArchive (conversationID);
4041
CREATE INDEX ofMessageArchive_fromjid_idx ON ofMessageArchive (fromJID);
4142
CREATE INDEX ofMessageArchive_tojid_idx ON ofMessageArchive (toJID);
4243
CREATE INDEX ofMessageArchive_sent_idx ON ofMessageArchive (sentDate);
44+
CREATE INDEX ofMessageArchive_pm_idx ON ofMessageArchive (isPMforJID);
4345

4446
CREATE TABLE ofRRDs (
4547
id VARCHAR(100) NOT NULL,
46-
updatedDate BIGINT NOT NULL,
47-
bytes BLOB,
48+
updatedDate BIGINT NOT NULL,
49+
bytes BLOB NULL,
4850
CONSTRAINT ofRRDs_pk PRIMARY KEY (id)
4951
);
5052

src/database/monitoring_hsqldb.sql

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
INSERT INTO ofVersion (name, version) VALUES ('monitoring', 6);
2+
INSERT INTO ofVersion (name, version) VALUES ('monitoring', 7);
33

44
CREATE TABLE ofConversation (
55
conversationID BIGINT NOT NULL,
@@ -34,17 +34,19 @@ CREATE TABLE ofMessageArchive (
3434
toJIDResource VARCHAR(255) NULL,
3535
sentDate BIGINT NOT NULL,
3636
stanza LONGVARCHAR NULL,
37-
body LONGVARCHAR
37+
body LONGVARCHAR NULL,
38+
isPMforJID VARCHAR(1024) NULL
3839
);
3940
CREATE INDEX ofMessageArchive_con_idx ON ofMessageArchive (conversationID);
4041
CREATE INDEX ofMessageArchive_fromjid_idx ON ofMessageArchive (fromJID);
4142
CREATE INDEX ofMessageArchive_tojid_idx ON ofMessageArchive (toJID);
4243
CREATE INDEX ofMessageArchive_sent_idx ON ofMessageArchive (sentDate);
44+
CREATE INDEX ofMessageArchive_pm_idx ON ofMessageArchive (isPMforJID);
4345

4446
CREATE TABLE ofRRDs (
4547
id VARCHAR(100) NOT NULL,
4648
updatedDate BIGINT NOT NULL,
47-
bytes BLOB NULL,
49+
bytes BLOB NULL,
4850
CONSTRAINT ofRRDs_pk PRIMARY KEY (id)
4951
);
5052

src/database/monitoring_mysql.sql

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
INSERT INTO ofVersion (name, version) VALUES ('monitoring', 6);
2+
INSERT INTO ofVersion (name, version) VALUES ('monitoring', 7);
33

44
CREATE TABLE ofConversation (
55
conversationID BIGINT NOT NULL,
@@ -34,11 +34,13 @@ CREATE TABLE ofMessageArchive (
3434
toJIDResource VARCHAR(100) NULL,
3535
sentDate BIGINT NOT NULL,
3636
stanza TEXT NULL,
37-
body TEXT,
37+
body TEXT NULL,
38+
isPMforJID VARCHAR(255) NOT NULL,
3839
INDEX ofMessageArchive_con_idx (conversationID),
3940
INDEX ofMessageArchive_fromjid_idx (fromJID),
4041
INDEX ofMessageArchive_tojid_idx (toJID),
41-
INDEX ofMessageArchive_sent_idx (sentDate)
42+
INDEX ofMessageArchive_sent_idx (sentDate),
43+
INDEX ofMessageArchive_pm_idx (isPMforJID)
4244
);
4345

4446
CREATE TABLE ofRRDs (

src/database/monitoring_oracle.sql

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
INSERT INTO ofVersion (name, version) VALUES ('monitoring', 6);
2+
INSERT INTO ofVersion (name, version) VALUES ('monitoring', 7);
33

44
CREATE TABLE ofConversation (
55
conversationID INTEGER NOT NULL,
@@ -34,12 +34,14 @@ CREATE TABLE ofMessageArchive (
3434
toJIDResource VARCHAR2(255) NULL,
3535
sentDate INTEGER NOT NULL,
3636
stanza CLOB NULL,
37-
body CLOB
37+
body CLOB NULL,
38+
isPMforJID VARCHAR2(1024) NULL
3839
);
3940
CREATE INDEX ofMessageArchive_con_idx ON ofMessageArchive (conversationID);
4041
CREATE INDEX ofMessageArchive_fromjid_idx ON ofMessageArchive (fromJID);
4142
CREATE INDEX ofMessageArchive_tojid_idx ON ofMessageArchive (toJID);
4243
CREATE INDEX ofMessageArchive_sent_idx ON ofMessageArchive (sentDate);
44+
CREATE INDEX ofMessageArchive_pm_idx ON ofMessageArchive (isPMforJID);
4345

4446
CREATE TABLE ofRRDs (
4547
id VARCHAR2(100) NOT NULL,

src/database/monitoring_postgresql.sql

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
INSERT INTO ofVersion (name, version) VALUES ('monitoring', 6);
2+
INSERT INTO ofVersion (name, version) VALUES ('monitoring', 7);
33

44
CREATE TABLE ofConversation (
55
conversationID INTEGER NOT NULL,
@@ -34,12 +34,14 @@ CREATE TABLE ofMessageArchive (
3434
toJIDResource VARCHAR(1024) NULL,
3535
sentDate BIGINT NOT NULL,
3636
stanza TEXT NULL,
37-
body TEXT
37+
body TEXT NULL,
38+
isPMforJID VARCHAR(1024) NULL
3839
);
3940
CREATE INDEX ofMessageArchive_con_idx ON ofMessageArchive (conversationID);
4041
CREATE INDEX ofMessageArchive_fromjid_idx ON ofMessageArchive (fromJID);
4142
CREATE INDEX ofMessageArchive_tojid_idx ON ofMessageArchive (toJID);
4243
CREATE INDEX ofMessageArchive_sent_idx ON ofMessageArchive (sentDate);
44+
CREATE INDEX ofMessageArchive_pm_idx ON ofMessageArchive (isPMforJID);
4345

4446
CREATE TABLE ofRRDs (
4547
id VARCHAR(100) NOT NULL,

src/database/monitoring_sqlserver.sql

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
INSERT INTO ofVersion (name, version) VALUES ('monitoring', 6);
2+
INSERT INTO ofVersion (name, version) VALUES ('monitoring', 7);
33

44
CREATE TABLE ofConversation (
55
conversationID BIGINT NOT NULL,
@@ -34,12 +34,14 @@ CREATE TABLE ofMessageArchive (
3434
toJIDResource NVARCHAR(1024) NULL,
3535
sentDate BIGINT NOT NULL,
3636
stanza NVARCHAR(MAX) NULL,
37-
body NVARCHAR(MAX)
37+
body NVARCHAR(MAX) NULL,
38+
isPMforJID NVARCHAR(1024) NULL
3839
);
3940
CREATE INDEX ofMessageArchive_con_idx ON ofMessageArchive (conversationID);
4041
CREATE INDEX ofMessageArchive_fromjid_idx ON ofMessageArchive (fromJID);
4142
CREATE INDEX ofMessageArchive_tojid_idx ON ofMessageArchive (toJID);
4243
CREATE INDEX ofMessageArchive_sent_idx ON ofMessageArchive (sentDate);
44+
CREATE INDEX ofMessageArchive_pm_idx ON ofMessageArchive (isPMforJID);
4345

4446
CREATE TABLE ofRRDs (
4547
id NVARCHAR(100) NOT NULL,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
ALTER TABLE ofMessageArchive ADD COLUMN isPMforJID VARCHAR(1024) NULL;
2+
CREATE INDEX ofMessageArchive_pm_idx ON ofMessageArchive (isPMforJID);
3+
4+
-- Update database version
5+
UPDATE ofVersion SET version = 7 WHERE name = 'monitoring';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
ALTER TABLE ofMessageArchive ADD COLUMN isPMforJID VARCHAR(1024) NULL;
2+
CREATE INDEX ofMessageArchive_pm_idx ON ofMessageArchive (isPMforJID);
3+
4+
-- Update database version
5+
UPDATE ofVersion SET version = 7 WHERE name = 'monitoring';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
ALTER TABLE ofMessageArchive ADD COLUMN isPMforJID VARCHAR(255) NULL;
2+
ALTER TABLE ofMessageArchive ADD INDEX ofMessageArchive_pm_idx (isPMforJID);
3+
4+
-- Update database version
5+
UPDATE ofVersion SET version = 7 WHERE name = 'monitoring';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
ALTER TABLE ofMessageArchive ADD isPMforJID VARCHAR2(1024) NULL;
2+
CREATE INDEX ofMessageArchive_pm_idx ON ofMessageArchive (isPMforJID);
3+
4+
-- Update database version
5+
UPDATE ofVersion SET version = 7 WHERE name = 'monitoring';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
ALTER TABLE ofMessageArchive ADD COLUMN isPMforJID VARCHAR(1024) NULL;
2+
CREATE INDEX ofMessageArchive_pm_idx ON ofMessageArchive (isPMforJID);
3+
4+
-- Update database version
5+
UPDATE ofVersion SET version = 7 WHERE name = 'monitoring';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
ALTER TABLE ofMessageArchive ADD isPMforJID NVARCHAR(1024) NULL;
2+
CREATE INDEX ofMessageArchive_pm_idx ON ofMessageArchive (isPMforJID);
3+
4+
-- Update database version
5+
UPDATE ofVersion SET version = 7 WHERE name = 'monitoring';

src/java/com/reucon/openfire/plugin/archive/PersistenceManager.java

+9-8
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,17 @@ public interface PersistenceManager
2929
/**
3030
* Searches for messages.
3131
*
32-
* @param startDate earliest start date of the message to find or <code>null</code> for any.
33-
* @param endDate latest end date of the message to find or <code>null</code> for any.
34-
* @param owner bare jid of the owner of the message to find or <code>null</code> for any.
35-
* @param with jid of the communication partner or <code>null</code> for any. This is either
36-
* the jid of another XMPP user or the jid of a group chat.
37-
* @param query A query string, typically representing keywords or a partial text, or <code>null</code>.
38-
* @param useStableID true if MAM2 or another protocol is used that depends on XEP-0359.
32+
* @param startDate earliest start date of the message to find or <code>null</code> for any.
33+
* @param endDate latest end date of the message to find or <code>null</code> for any.
34+
* @param archiveOwner bare jid of the owner of the archive in which to find messages or <code>null</code> for any.
35+
* @param messageOwner bare jid of the owner of the message to find or <code>null</code> for any.
36+
* @param with jid of the communication partner or <code>null</code> for any. This is either
37+
* the jid of another XMPP user or the jid of a group chat.
38+
* @param query A query string, typically representing keywords or a partial text, or <code>null</code>.
39+
* @param useStableID true if MAM2 or another protocol is used that depends on XEP-0359.
3940
* @return the messages that matched search criteria (possibly empty, never null).
4041
*/
41-
Collection<ArchivedMessage> findMessages( Date startDate, Date endDate, JID owner, JID with, String query, XmppResultSet xmppResultSet, boolean useStableID) throws NotFoundException;
42+
Collection<ArchivedMessage> findMessages( Date startDate, Date endDate, JID archiveOwner, JID messageOwner, JID with, String query, XmppResultSet xmppResultSet, boolean useStableID) throws NotFoundException;
4243

4344
/**
4445
* Returns the conversation with the given owner, with and start time including participants and messages.

src/java/com/reucon/openfire/plugin/archive/impl/JdbcPersistenceManager.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import com.reucon.openfire.plugin.archive.model.ArchivedMessage.Direction;
66
import com.reucon.openfire.plugin.archive.model.Conversation;
77
import com.reucon.openfire.plugin.archive.model.Participant;
8-
import com.reucon.openfire.plugin.archive.util.StanzaIDUtil;
98
import com.reucon.openfire.plugin.archive.xep0059.XmppResultSet;
109
import org.dom4j.*;
1110
import org.jivesoftware.database.DbConnectionManager;
@@ -15,7 +14,6 @@
1514
import org.slf4j.Logger;
1615
import org.slf4j.LoggerFactory;
1716
import org.xmpp.packet.JID;
18-
import org.xmpp.packet.Message;
1917

2018
import java.sql.Connection;
2119
import java.sql.PreparedStatement;
@@ -24,7 +22,7 @@
2422
import java.util.*;
2523

2624
/**
27-
* Manages database persistence.
25+
* Manages database interactions to work with 'personal archives' for messages.
2826
*/
2927
public class JdbcPersistenceManager implements PersistenceManager {
3028
private static final Logger Log = LoggerFactory.getLogger( JdbcPersistenceManager.class );
@@ -277,8 +275,10 @@ private int bindConversationParameters(Date startDate, Date endDate, JID owner,
277275
}
278276

279277
@Override
280-
public Collection<ArchivedMessage> findMessages(Date startDate, Date endDate, JID owner, JID with, String query, XmppResultSet xmppResultSet, boolean useStableID) {
281-
278+
public Collection<ArchivedMessage> findMessages(Date startDate, Date endDate, JID owner, JID messageOwner, JID with, String query, XmppResultSet xmppResultSet, boolean useStableID) {
279+
if ( !owner.equals(messageOwner)) {
280+
throw new IllegalArgumentException("A personal archive can't be queried for messages of a different owner than the archive. Supplied archive owner: " + owner + ", supplied message owner: " + messageOwner);
281+
}
282282
Log.debug( "Finding messages of owner '{}' with start date '{}', end date '{}' with '{}' and resultset '{}', useStableId '{}'.", owner, startDate, endDate, with, xmppResultSet, useStableID );
283283

284284
if (startDate == null) {

src/java/com/reucon/openfire/plugin/archive/impl/MucMamPersistenceManager.java

+14-14
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,12 @@ public Collection<Conversation> findConversations(Date startDate, Date endDate,
4545
}
4646

4747
@Override
48-
public Collection<ArchivedMessage> findMessages(Date startDate, Date endDate, JID owner, JID with, String query, XmppResultSet xmppResultSet, boolean useStableID ) throws NotFoundException
48+
public Collection<ArchivedMessage> findMessages(Date startDate, Date endDate, JID archiveOwner, JID messageOwner, JID with, String query, XmppResultSet xmppResultSet, boolean useStableID ) throws NotFoundException
4949
{
50-
Log.debug( "Finding messages of owner '{}' with start date '{}', end date '{}' with '{}', query: '{}' and resultset '{}', useStableId '{}'.", owner, startDate, endDate, with, query, xmppResultSet, useStableID );
50+
Log.debug( "Finding messages in archive '{}' for user '{}' with start date '{}', end date '{}' with '{}', query: '{}' and resultset '{}', useStableId '{}'.", archiveOwner, messageOwner, startDate, endDate, with, query, xmppResultSet, useStableID );
5151
final MultiUserChatManager manager = XMPPServer.getInstance().getMultiUserChatManager();
52-
final MultiUserChatService service = manager.getMultiUserChatService(owner);
53-
final MUCRoom room = service.getChatRoom(owner.getNode());
52+
final MultiUserChatService service = manager.getMultiUserChatService(archiveOwner);
53+
final MUCRoom room = service.getChatRoom(archiveOwner.getNode());
5454

5555
if (!room.isLogEnabled()) {
5656
Log.debug( "Request for message archive of room '{}' that currently has message logging disabled. Returning an empty list.", room.getJID() );
@@ -84,16 +84,16 @@ public Collection<ArchivedMessage> findMessages(Date startDate, Date endDate, JI
8484
}
8585
} else {
8686
if (JiveGlobals.getBooleanProperty("conversation.database.use-openfire-tables", false ) ) {
87-
final PaginatedMucMessageDatabaseQuery paginatedMucMessageDatabaseQuery = new PaginatedMucMessageDatabaseQuery(startDate, endDate, room, with);
88-
Log.debug("Request for message archive of room '{}' resulted in the following query data: {}", room.getJID(), paginatedMucMessageDatabaseQuery);
89-
totalCount = paginatedMucMessageDatabaseQuery.getTotalCount();
87+
final PaginatedMucMessageFromOpenfireDatabaseQuery paginatedMucMessageFromOpenfireDatabaseQuery = new PaginatedMucMessageFromOpenfireDatabaseQuery(startDate, endDate, room, with);
88+
Log.debug("Request for message archive of room '{}' resulted in the following query data: {}", room.getJID(), paginatedMucMessageFromOpenfireDatabaseQuery);
89+
totalCount = paginatedMucMessageFromOpenfireDatabaseQuery.getTotalCount();
9090
if (totalCount == 0) {
9191
msgs = Collections.emptyList();
9292
} else {
93-
msgs = paginatedMucMessageDatabaseQuery.getPage(after, before, maxResults, isPagingBackwards);
93+
msgs = paginatedMucMessageFromOpenfireDatabaseQuery.getPage(after, before, maxResults, isPagingBackwards);
9494
}
9595
} else {
96-
final PaginatedMessageDatabaseQuery paginatedMessageDatabaseQuery = new PaginatedMessageDatabaseQuery(startDate, endDate, room.getJID(), with);
96+
final PaginatedMucMessageDatabaseQuery paginatedMessageDatabaseQuery = new PaginatedMucMessageDatabaseQuery(startDate, endDate, room.getJID(), messageOwner, with);
9797
Log.debug("Request for message archive of room '{}' resulted in the following query data: {}", room.getJID(), paginatedMessageDatabaseQuery);
9898
totalCount = paginatedMessageDatabaseQuery.getTotalCount();
9999
if (totalCount == 0) {
@@ -114,14 +114,14 @@ public Collection<ArchivedMessage> findMessages(Date startDate, Date endDate, JI
114114
final String first;
115115
final String last;
116116
if ( useStableID ) {
117-
final String firstSid = firstMessage.getStableId(owner);
117+
final String firstSid = firstMessage.getStableId(archiveOwner);
118118
if ( firstSid != null && !firstSid.isEmpty() ) {
119119
first = firstSid;
120120
} else {
121121
// Issue #98: Fall-back to using the database-identifier. Although not a stable-id, it at least gives the client the option to paginate.
122122
first = firstMessage.getId().toString();
123123
}
124-
final String lastSid = lastMessage.getStableId(owner);
124+
final String lastSid = lastMessage.getStableId(archiveOwner);
125125
if ( lastSid != null && !lastSid.isEmpty()) {
126126
last = lastSid;
127127
} else {
@@ -148,10 +148,10 @@ public Collection<ArchivedMessage> findMessages(Date startDate, Date endDate, JI
148148
else
149149
{
150150
if (JiveGlobals.getBooleanProperty("conversation.database.use-openfire-tables", false ) ) {
151-
final PaginatedMucMessageDatabaseQuery paginatedMucMessageDatabaseQuery = new PaginatedMucMessageDatabaseQuery(startDate, endDate, room, with);
152-
nextPage = paginatedMucMessageDatabaseQuery.getPage(afterForNextPage, beforeForNextPage, 1, isPagingBackwards);
151+
final PaginatedMucMessageFromOpenfireDatabaseQuery paginatedMucMessageFromOpenfireDatabaseQuery = new PaginatedMucMessageFromOpenfireDatabaseQuery(startDate, endDate, room, with);
152+
nextPage = paginatedMucMessageFromOpenfireDatabaseQuery.getPage(afterForNextPage, beforeForNextPage, 1, isPagingBackwards);
153153
} else {
154-
final PaginatedMessageDatabaseQuery paginatedMessageDatabaseQuery = new PaginatedMessageDatabaseQuery(startDate, endDate, room.getJID(), with);
154+
final PaginatedMucMessageDatabaseQuery paginatedMessageDatabaseQuery = new PaginatedMucMessageDatabaseQuery(startDate, endDate, room.getJID(), messageOwner, with);
155155
nextPage = paginatedMessageDatabaseQuery.getPage(afterForNextPage, beforeForNextPage, 1, isPagingBackwards);
156156
}
157157
}

0 commit comments

Comments
 (0)