diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledActivityRecord.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledActivityRecord.java
index 95b1a256d..ba4fbc694 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledActivityRecord.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledActivityRecord.java
@@ -19,8 +19,9 @@
package org.apache.guacamole.auth.jdbc.base;
-
+import java.nio.ByteBuffer;
import java.util.Date;
+import java.util.UUID;
import org.apache.guacamole.net.auth.ActivityRecord;
/**
@@ -33,16 +34,72 @@ public class ModeledActivityRecord implements ActivityRecord {
*/
private final ActivityRecordModel model;
+ /**
+ * The UUID uniquely identifies this record, or null if no such unique
+ * identifier exists.
+ */
+ private final UUID uuid;
+
+ /**
+ * Generates a UUID that uniquely identifies the record represented by the
+ * given ActivityRecordModel. The UUID generated is a type 3 name UUID and
+ * is guaranteed to be unique so long as the provided UUID namespace
+ * corresponds to the namespace of the record ID within the model.
+ *
+ * IMPORTANT: Changing this function such that different UUIDs will be
+ * generated for the same records relative to past releases can potentially
+ * break compatibility with established history record associations. Any
+ * such change should be made with great care to avoid breaking history
+ * functionality that may be provided by third-party extensions.
+ *
+ * @param namespace
+ * The UUID namespace of the type 3 name UUID to generate. This
+ * namespace should correspond to the source of IDs for the model
+ * such that the combination of this namespace with the numeric record
+ * ID will always be unique and deterministic across all activity
+ * records, regardless of record type.
+ *
+ * @param model
+ * The model object representing the activity record.
+ *
+ * @return
+ * The UUID uniquely identifies the record represented by the given
+ * model, or null if no such unique identifier can be generated (there
+ * is no corresponding record ID).
+ */
+ private static UUID getUUID(UUID namespace, ActivityRecordModel model) {
+
+ Integer id = model.getRecordID();
+ if (id == null)
+ return null;
+
+ // Convert record ID to a name UUID in the given namespace
+ return UUID.nameUUIDFromBytes(ByteBuffer.allocate(24)
+ .putLong(namespace.getMostSignificantBits())
+ .putLong(namespace.getLeastSignificantBits())
+ .putLong(id)
+ .array());
+
+ }
+
/**
* Creates a new ModeledActivityRecord backed by the given model object.
* Changes to this record will affect the backing model object, and changes
* to the backing model object will affect this record.
- *
+ *
+ * @param namespace
+ * The UUID namespace of the type 3 name UUID to generate for the
+ * record. This namespace should correspond to the source of IDs for
+ * the model such that the combination of this namespace with the
+ * numeric record ID will always be unique and deterministic across all
+ * activity records, regardless of record type.
+ *
* @param model
* The model object to use to back this activity record.
*/
- public ModeledActivityRecord(ActivityRecordModel model) {
+ public ModeledActivityRecord(UUID namespace, ActivityRecordModel model) {
this.model = model;
+ this.uuid = getUUID(namespace, model);
}
@Override
@@ -70,4 +127,9 @@ public class ModeledActivityRecord implements ActivityRecord {
return false;
}
+ @Override
+ public UUID getUUID() {
+ return uuid;
+ }
+
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordSet.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordSet.java
index 2f559e930..baf005675 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordSet.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordSet.java
@@ -23,6 +23,7 @@ import com.google.inject.Inject;
import java.util.Collection;
import java.util.List;
import java.util.Set;
+import java.util.UUID;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSearchTerm;
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSortPredicate;
@@ -38,6 +39,15 @@ import org.apache.guacamole.net.auth.ConnectionRecord;
*/
public class ConnectionRecordSet extends ModeledActivityRecordSet {
+ /**
+ * The namespace for the type 3 UUIDs generated for connection history
+ * records. This UUID namespace is itself a type 3 UUID within the "ns:OID"
+ * namespace for the OID "1.3.6.1.4.1.18060.18.2.1.2", which has been
+ * specifically allocated for Apache Guacamole database connection
+ * history records.
+ */
+ public static final UUID UUID_NAMESPACE = UUID.fromString("8b55f070-95f4-3d31-93ee-9c5845e7aa40");
+
/**
* Service for managing connection objects.
*/
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnectionRecord.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnectionRecord.java
index 9f34385cf..b02ca14c1 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnectionRecord.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnectionRecord.java
@@ -43,7 +43,7 @@ public class ModeledConnectionRecord extends ModeledActivityRecord
* The model object to use to back this connection record.
*/
public ModeledConnectionRecord(ConnectionRecordModel model) {
- super(model);
+ super(ConnectionRecordSet.UUID_NAMESPACE, model);
this.model = model;
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserRecordSet.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserRecordSet.java
index c5c9f6a6c..a1ccf1212 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserRecordSet.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserRecordSet.java
@@ -23,6 +23,7 @@ import com.google.inject.Inject;
import java.util.Collection;
import java.util.List;
import java.util.Set;
+import java.util.UUID;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSearchTerm;
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSortPredicate;
@@ -38,6 +39,15 @@ import org.apache.guacamole.net.auth.AuthenticatedUser;
*/
public class UserRecordSet extends ModeledActivityRecordSet {
+ /**
+ * The namespace for the type 3 UUIDs generated for user history records.
+ * This UUID namespace is itself a type 3 UUID within the "ns:OID"
+ * namespace for the OID "1.3.6.1.4.1.18060.18.2.1.1", which has been
+ * specifically allocated for Apache Guacamole database user history
+ * records.
+ */
+ public static final UUID UUID_NAMESPACE = UUID.fromString("e104741a-c949-3947-8d79-f3f2cdce7d6f");
+
/**
* Service for managing user objects.
*/
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java
index 6f6d05625..03010e835 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java
@@ -546,7 +546,7 @@ public class UserService extends ModeledDirectoryObjectService
+
@@ -40,6 +41,7 @@