This is an automated email from the ASF dual-hosted git repository.

remm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/main by this push:
     new 5376d45  Improve the reusability of UserDatabase code
5376d45 is described below

commit 5376d45258b8bf496951a99eab435517d2ed70f0
Author: remm <r...@apache.org>
AuthorDate: Tue Aug 17 14:56:24 2021 +0200

    Improve the reusability of UserDatabase code
    
    Add intermediate concrete implementation classes. Add hooks to allow
    partail database updates on save. Will likely make alternate
    implementations more realistic.
---
 java/org/apache/catalina/UserDatabase.java         |  27 ++++
 .../users/{MemoryGroup.java => GenericGroup.java}  |  60 ++++----
 .../users/{MemoryRole.java => GenericRole.java}    |  44 +++---
 .../users/{MemoryUser.java => GenericUser.java}    | 126 ++++++++--------
 java/org/apache/catalina/users/MemoryGroup.java    | 116 +--------------
 java/org/apache/catalina/users/MemoryRole.java     |  36 +----
 java/org/apache/catalina/users/MemoryUser.java     | 158 +--------------------
 webapps/docs/changelog.xml                         |   5 +
 8 files changed, 138 insertions(+), 434 deletions(-)

diff --git a/java/org/apache/catalina/UserDatabase.java 
b/java/org/apache/catalina/UserDatabase.java
index 8bac810..9242170 100644
--- a/java/org/apache/catalina/UserDatabase.java
+++ b/java/org/apache/catalina/UserDatabase.java
@@ -156,6 +156,33 @@ public interface UserDatabase {
 
 
     /**
+     * Signal the specified {@link Group} from this user database has been
+     * modified.
+     *
+     * @param group The group that has been modified
+     */
+    public default void modifiedGroup(Group group) {}
+
+
+    /**
+     * Signal the specified {@link Role} from this user database has been
+     * modified.
+     *
+     * @param role The role that has been modified
+     */
+    public default void modifiedRole(Role role) {}
+
+
+    /**
+     * Signal the specified {@link User} from this user database has been
+     * modified.
+     *
+     * @param user The user that has been modified
+     */
+    public default void modifiedUser(User user) {}
+
+
+    /**
      * Save any updated information to the persistent storage location for this
      * user database.
      *
diff --git a/java/org/apache/catalina/users/MemoryGroup.java 
b/java/org/apache/catalina/users/GenericGroup.java
similarity index 73%
copy from java/org/apache/catalina/users/MemoryGroup.java
copy to java/org/apache/catalina/users/GenericGroup.java
index aad4180..d59e57d 100644
--- a/java/org/apache/catalina/users/MemoryGroup.java
+++ b/java/org/apache/catalina/users/GenericGroup.java
@@ -25,17 +25,15 @@ import java.util.concurrent.CopyOnWriteArrayList;
 import org.apache.catalina.Role;
 import org.apache.catalina.User;
 import org.apache.catalina.UserDatabase;
-import org.apache.tomcat.util.buf.StringUtils;
 
 
 /**
- * <p>Concrete implementation of {@link org.apache.catalina.Group} for the
- * {@link MemoryUserDatabase} implementation of {@link UserDatabase}.</p>
+ * <p>Concrete implementation of {@link org.apache.catalina.Group} for a
+ * {@link UserDatabase}.</p>
  *
  * @author Craig R. McClanahan
- * @since 4.1
  */
-public class MemoryGroup extends AbstractGroup {
+public class GenericGroup<UD extends UserDatabase> extends AbstractGroup {
 
 
     // ----------------------------------------------------------- Constructors
@@ -43,19 +41,23 @@ public class MemoryGroup extends AbstractGroup {
 
     /**
      * Package-private constructor used by the factory method in
-     * {@link MemoryUserDatabase}.
+     * {@link UserDatabase}.
      *
-     * @param database The {@link MemoryUserDatabase} that owns this group
+     * @param database The {@link UserDatabase} that owns this group
      * @param groupname Group name of this group
      * @param description Description of this group
+     * @param roles The roles of this group
      */
-    MemoryGroup(MemoryUserDatabase database,
-                String groupname, String description) {
+    GenericGroup(UD database,
+                String groupname, String description, List<Role> roles) {
 
         super();
         this.database = database;
-        setGroupname(groupname);
-        setDescription(description);
+        this.groupname = groupname;
+        this.description = description;
+        if (roles != null) {
+            this.roles.addAll(roles);
+        }
 
     }
 
@@ -64,9 +66,9 @@ public class MemoryGroup extends AbstractGroup {
 
 
     /**
-     * The {@link MemoryUserDatabase} that owns this group.
+     * The {@link UserDatabase} that owns this group.
      */
-    protected final MemoryUserDatabase database;
+    protected final UD database;
 
 
     /**
@@ -123,7 +125,9 @@ public class MemoryGroup extends AbstractGroup {
      */
     @Override
     public void addRole(Role role) {
-        roles.addIfAbsent(role);
+        if (roles.addIfAbsent(role)) {
+            database.modifiedGroup(this);
+        }
     }
 
 
@@ -145,7 +149,9 @@ public class MemoryGroup extends AbstractGroup {
      */
     @Override
     public void removeRole(Role role) {
-        roles.remove(role);
+        if (roles.remove(role)) {
+            database.modifiedGroup(this);
+        }
     }
 
 
@@ -154,27 +160,11 @@ public class MemoryGroup extends AbstractGroup {
      */
     @Override
     public void removeRoles() {
-        roles.clear();
+        if (!roles.isEmpty()) {
+            roles.clear();
+            database.modifiedGroup(this);
+        }
     }
 
 
-    /**
-     * <p>Return a String representation of this group in XML format.</p>
-     */
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder("<group groupname=\"");
-        sb.append(groupname);
-        sb.append("\"");
-        if (description != null) {
-            sb.append(" description=\"");
-            sb.append(description);
-            sb.append("\"");
-        }
-        sb.append(" roles=\"");
-        StringUtils.join(roles, ',', Role::getRolename, sb);
-        sb.append("\"");
-        sb.append("/>");
-        return sb.toString();
-    }
 }
diff --git a/java/org/apache/catalina/users/MemoryRole.java 
b/java/org/apache/catalina/users/GenericRole.java
similarity index 63%
copy from java/org/apache/catalina/users/MemoryRole.java
copy to java/org/apache/catalina/users/GenericRole.java
index b8f4970..c6b0eba 100644
--- a/java/org/apache/catalina/users/MemoryRole.java
+++ b/java/org/apache/catalina/users/GenericRole.java
@@ -21,13 +21,12 @@ import org.apache.catalina.UserDatabase;
 
 
 /**
- * <p>Concrete implementation of {@link org.apache.catalina.Role} for the
- * {@link MemoryUserDatabase} implementation of {@link UserDatabase}.</p>
+ * <p>Concrete implementation of {@link org.apache.catalina.Role} for a
+ * {@link UserDatabase}.</p>
  *
  * @author Craig R. McClanahan
- * @since 4.1
  */
-public class MemoryRole extends AbstractRole {
+public class GenericRole<UD extends UserDatabase> extends AbstractRole {
 
 
     // ----------------------------------------------------------- Constructors
@@ -35,19 +34,19 @@ public class MemoryRole extends AbstractRole {
 
     /**
      * Package-private constructor used by the factory method in
-     * {@link MemoryUserDatabase}.
+     * {@link UserDatabase}.
      *
-     * @param database The {@link MemoryUserDatabase} that owns this role
+     * @param database The {@link UserDatabase} that owns this role
      * @param rolename Role name of this role
      * @param description Description of this role
      */
-    MemoryRole(MemoryUserDatabase database,
+    GenericRole(UD database,
                String rolename, String description) {
 
         super();
         this.database = database;
-        setRolename(rolename);
-        setDescription(description);
+        this.rolename = rolename;
+        this.description = description;
 
     }
 
@@ -56,9 +55,9 @@ public class MemoryRole extends AbstractRole {
 
 
     /**
-     * The {@link MemoryUserDatabase} that owns this role.
+     * The {@link UserDatabase} that owns this role.
      */
-    protected final MemoryUserDatabase database;
+    protected final UserDatabase database;
 
 
     // ------------------------------------------------------------- Properties
@@ -73,24 +72,17 @@ public class MemoryRole extends AbstractRole {
     }
 
 
-    // --------------------------------------------------------- Public Methods
+    @Override
+    public void setDescription(String description) {
+        database.modifiedRole(this);
+        super.setDescription(description);
+    }
 
 
-    /**
-     * <p>Return a String representation of this role in XML format.</p>
-     */
     @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder("<role rolename=\"");
-        sb.append(rolename);
-        sb.append("\"");
-        if (description != null) {
-            sb.append(" description=\"");
-            sb.append(description);
-            sb.append("\"");
-        }
-        sb.append("/>");
-        return sb.toString();
+    public void setRolename(String rolename) {
+        database.modifiedRole(this);
+        super.setRolename(rolename);
     }
 
 
diff --git a/java/org/apache/catalina/users/MemoryUser.java 
b/java/org/apache/catalina/users/GenericUser.java
similarity index 62%
copy from java/org/apache/catalina/users/MemoryUser.java
copy to java/org/apache/catalina/users/GenericUser.java
index 007dd56..77b70b4 100644
--- a/java/org/apache/catalina/users/MemoryUser.java
+++ b/java/org/apache/catalina/users/GenericUser.java
@@ -18,22 +18,20 @@ package org.apache.catalina.users;
 
 
 import java.util.Iterator;
+import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
 
 import org.apache.catalina.Group;
 import org.apache.catalina.Role;
 import org.apache.catalina.UserDatabase;
-import org.apache.tomcat.util.buf.StringUtils;
-import org.apache.tomcat.util.security.Escape;
 
 /**
- * <p>Concrete implementation of {@link org.apache.catalina.User} for the
- * {@link MemoryUserDatabase} implementation of {@link UserDatabase}.</p>
+ * <p>Concrete implementation of {@link org.apache.catalina.User} for a
+ * {@link UserDatabase}.</p>
  *
  * @author Craig R. McClanahan
- * @since 4.1
  */
-public class MemoryUser extends AbstractUser {
+public class GenericUser<UD extends UserDatabase> extends AbstractUser {
 
 
     // ----------------------------------------------------------- Constructors
@@ -41,21 +39,30 @@ public class MemoryUser extends AbstractUser {
 
     /**
      * Package-private constructor used by the factory method in
-     * {@link MemoryUserDatabase}.
+     * {@link UserDatabase}.
      *
-     * @param database The {@link MemoryUserDatabase} that owns this user
+     * @param database The {@link UserDatabase} that owns this user
      * @param username Logon username of the new user
      * @param password Logon password of the new user
      * @param fullName Full name of the new user
+     * @param groups The groups of this user
+     * @param roles The roles of this user
      */
-    MemoryUser(MemoryUserDatabase database, String username,
-               String password, String fullName) {
+    GenericUser(UD database, String username,
+               String password, String fullName, List<Group> groups,
+               List<Role> roles) {
 
         super();
         this.database = database;
-        setUsername(username);
-        setPassword(password);
-        setFullName(fullName);
+        this.username = username;
+        this.password = password;
+        this.fullName = fullName;
+        if (groups != null) {
+            this.groups.addAll(groups);
+        }
+        if (roles != null) {
+            this.roles.addAll(roles);
+        }
 
     }
 
@@ -64,9 +71,9 @@ public class MemoryUser extends AbstractUser {
 
 
     /**
-     * The {@link MemoryUserDatabase} that owns this user.
+     * The {@link UserDatabase} that owns this user.
      */
-    protected final MemoryUserDatabase database;
+    protected final UD database;
 
 
     /**
@@ -121,7 +128,9 @@ public class MemoryUser extends AbstractUser {
      */
     @Override
     public void addGroup(Group group) {
-        groups.addIfAbsent(group);
+        if (groups.addIfAbsent(group)) {
+            database.modifiedUser(this);
+        }
     }
 
 
@@ -132,7 +141,9 @@ public class MemoryUser extends AbstractUser {
      */
     @Override
     public void addRole(Role role) {
-        roles.addIfAbsent(role);
+        if (roles.addIfAbsent(role)) {
+            database.modifiedUser(this);
+        }
     }
 
 
@@ -167,7 +178,9 @@ public class MemoryUser extends AbstractUser {
      */
     @Override
     public void removeGroup(Group group) {
-        groups.remove(group);
+        if (groups.remove(group)) {
+            database.modifiedUser(this);
+        }
     }
 
 
@@ -176,7 +189,10 @@ public class MemoryUser extends AbstractUser {
      */
     @Override
     public void removeGroups() {
-        groups.clear();
+        if (!groups.isEmpty()) {
+            groups.clear();
+            database.modifiedUser(this);
+        }
     }
 
 
@@ -187,7 +203,9 @@ public class MemoryUser extends AbstractUser {
      */
     @Override
     public void removeRole(Role role) {
-        roles.remove(role);
+        if (roles.remove(role)) {
+            database.modifiedUser(this);
+        }
     }
 
 
@@ -196,62 +214,32 @@ public class MemoryUser extends AbstractUser {
      */
     @Override
     public void removeRoles() {
+        if (!roles.isEmpty()) {
+            database.modifiedUser(this);
+        }
         roles.clear();
     }
 
 
-    /**
-     * <p>Return a String representation of this user in XML format.</p>
-     *
-     * <p><strong>IMPLEMENTATION NOTE</strong> - For backwards compatibility,
-     * the reader that processes this entry will accept either
-     * <code>username</code> or <code>name</code> for the username
-     * property.</p>
-     * @return the XML representation
-     */
-    public String toXml() {
-
-        StringBuilder sb = new StringBuilder("<user username=\"");
-        sb.append(Escape.xml(username));
-        sb.append("\" password=\"");
-        sb.append(Escape.xml(password));
-        sb.append("\"");
-        if (fullName != null) {
-            sb.append(" fullName=\"");
-            sb.append(Escape.xml(fullName));
-            sb.append("\"");
-        }
-        sb.append(" groups=\"");
-        StringUtils.join(groups, ',', (x) -> Escape.xml(x.getGroupname()), sb);
-        sb.append("\"");
-        sb.append(" roles=\"");
-        StringUtils.join(roles, ',', (x) -> Escape.xml(x.getRolename()), sb);
-        sb.append("\"");
-        sb.append("/>");
-        return sb.toString();
+    @Override
+    public void setFullName(String fullName) {
+        database.modifiedUser(this);
+        super.setFullName(fullName);
     }
 
 
-    /**
-     * <p>Return a String representation of this user.</p>
-     */
     @Override
-    public String toString() {
-
-        StringBuilder sb = new StringBuilder("User username=\"");
-        sb.append(Escape.xml(username));
-        sb.append("\"");
-        if (fullName != null) {
-            sb.append(", fullName=\"");
-            sb.append(Escape.xml(fullName));
-            sb.append("\"");
-        }
-        sb.append(", groups=\"");
-        StringUtils.join(groups, ',', (x) -> Escape.xml(x.getGroupname()), sb);
-        sb.append("\"");
-        sb.append(", roles=\"");
-        StringUtils.join(roles, ',', (x) -> Escape.xml(x.getRolename()), sb);
-        sb.append("\"");
-        return sb.toString();
+    public void setPassword(String password) {
+        database.modifiedUser(this);
+        super.setPassword(password);
     }
+
+
+    @Override
+    public void setUsername(String username) {
+        database.modifiedUser(this);
+        // Note: changing the user name is a problem ...
+        super.setUsername(username);
+    }
+
 }
diff --git a/java/org/apache/catalina/users/MemoryGroup.java 
b/java/org/apache/catalina/users/MemoryGroup.java
index aad4180..f1008ff 100644
--- a/java/org/apache/catalina/users/MemoryGroup.java
+++ b/java/org/apache/catalina/users/MemoryGroup.java
@@ -17,13 +17,7 @@
 package org.apache.catalina.users;
 
 
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-
 import org.apache.catalina.Role;
-import org.apache.catalina.User;
 import org.apache.catalina.UserDatabase;
 import org.apache.tomcat.util.buf.StringUtils;
 
@@ -35,10 +29,7 @@ import org.apache.tomcat.util.buf.StringUtils;
  * @author Craig R. McClanahan
  * @since 4.1
  */
-public class MemoryGroup extends AbstractGroup {
-
-
-    // ----------------------------------------------------------- Constructors
+public class MemoryGroup extends GenericGroup<MemoryUserDatabase> {
 
 
     /**
@@ -51,110 +42,7 @@ public class MemoryGroup extends AbstractGroup {
      */
     MemoryGroup(MemoryUserDatabase database,
                 String groupname, String description) {
-
-        super();
-        this.database = database;
-        setGroupname(groupname);
-        setDescription(description);
-
-    }
-
-
-    // ----------------------------------------------------- Instance Variables
-
-
-    /**
-     * The {@link MemoryUserDatabase} that owns this group.
-     */
-    protected final MemoryUserDatabase database;
-
-
-    /**
-     * The set of {@link Role}s associated with this group.
-     */
-    protected final CopyOnWriteArrayList<Role> roles = new 
CopyOnWriteArrayList<>();
-
-
-    // ------------------------------------------------------------- Properties
-
-
-    /**
-     * Return the set of {@link Role}s assigned specifically to this group.
-     */
-    @Override
-    public Iterator<Role> getRoles() {
-        return roles.iterator();
-    }
-
-
-    /**
-     * Return the {@link UserDatabase} within which this Group is defined.
-     */
-    @Override
-    public UserDatabase getUserDatabase() {
-        return this.database;
-    }
-
-
-    /**
-     * Return the set of {@link org.apache.catalina.User}s that are members of 
this group.
-     */
-    @Override
-    public Iterator<User> getUsers() {
-        List<User> results = new ArrayList<>();
-        Iterator<User> users = database.getUsers();
-        while (users.hasNext()) {
-            User user = users.next();
-            if (user.isInGroup(this)) {
-                results.add(user);
-            }
-        }
-        return results.iterator();
-    }
-
-
-    // --------------------------------------------------------- Public Methods
-
-
-    /**
-     * Add a new {@link Role} to those assigned specifically to this group.
-     *
-     * @param role The new role
-     */
-    @Override
-    public void addRole(Role role) {
-        roles.addIfAbsent(role);
-    }
-
-
-    /**
-     * Is this group specifically assigned the specified {@link Role}?
-     *
-     * @param role The role to check
-     */
-    @Override
-    public boolean isInRole(Role role) {
-        return roles.contains(role);
-    }
-
-
-    /**
-     * Remove a {@link Role} from those assigned to this group.
-     *
-     * @param role The old role
-     */
-    @Override
-    public void removeRole(Role role) {
-        roles.remove(role);
-    }
-
-
-    /**
-     * Remove all {@link Role}s from those assigned to this group.
-     */
-    @Override
-    public void removeRoles() {
-        roles.clear();
+        super(database, groupname, description, null);
     }
 
 
diff --git a/java/org/apache/catalina/users/MemoryRole.java 
b/java/org/apache/catalina/users/MemoryRole.java
index b8f4970..10f6d22 100644
--- a/java/org/apache/catalina/users/MemoryRole.java
+++ b/java/org/apache/catalina/users/MemoryRole.java
@@ -27,10 +27,7 @@ import org.apache.catalina.UserDatabase;
  * @author Craig R. McClanahan
  * @since 4.1
  */
-public class MemoryRole extends AbstractRole {
-
-
-    // ----------------------------------------------------------- Constructors
+public class MemoryRole extends GenericRole<MemoryUserDatabase> {
 
 
     /**
@@ -43,39 +40,10 @@ public class MemoryRole extends AbstractRole {
      */
     MemoryRole(MemoryUserDatabase database,
                String rolename, String description) {
-
-        super();
-        this.database = database;
-        setRolename(rolename);
-        setDescription(description);
-
-    }
-
-
-    // ----------------------------------------------------- Instance Variables
-
-
-    /**
-     * The {@link MemoryUserDatabase} that owns this role.
-     */
-    protected final MemoryUserDatabase database;
-
-
-    // ------------------------------------------------------------- Properties
-
-
-    /**
-     * Return the {@link UserDatabase} within which this role is defined.
-     */
-    @Override
-    public UserDatabase getUserDatabase() {
-        return this.database;
+        super(database, rolename, description);
     }
 
 
-    // --------------------------------------------------------- Public Methods
-
-
     /**
      * <p>Return a String representation of this role in XML format.</p>
      */
diff --git a/java/org/apache/catalina/users/MemoryUser.java 
b/java/org/apache/catalina/users/MemoryUser.java
index 007dd56..f271fb2 100644
--- a/java/org/apache/catalina/users/MemoryUser.java
+++ b/java/org/apache/catalina/users/MemoryUser.java
@@ -17,11 +17,6 @@
 package org.apache.catalina.users;
 
 
-import java.util.Iterator;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-import org.apache.catalina.Group;
-import org.apache.catalina.Role;
 import org.apache.catalina.UserDatabase;
 import org.apache.tomcat.util.buf.StringUtils;
 import org.apache.tomcat.util.security.Escape;
@@ -33,10 +28,7 @@ import org.apache.tomcat.util.security.Escape;
  * @author Craig R. McClanahan
  * @since 4.1
  */
-public class MemoryUser extends AbstractUser {
-
-
-    // ----------------------------------------------------------- Constructors
+public class MemoryUser extends GenericUser<MemoryUserDatabase> {
 
 
     /**
@@ -50,153 +42,7 @@ public class MemoryUser extends AbstractUser {
      */
     MemoryUser(MemoryUserDatabase database, String username,
                String password, String fullName) {
-
-        super();
-        this.database = database;
-        setUsername(username);
-        setPassword(password);
-        setFullName(fullName);
-
-    }
-
-
-    // ----------------------------------------------------- Instance Variables
-
-
-    /**
-     * The {@link MemoryUserDatabase} that owns this user.
-     */
-    protected final MemoryUserDatabase database;
-
-
-    /**
-     * The set of {@link Group}s that this user is a member of.
-     */
-    protected final CopyOnWriteArrayList<Group> groups = new 
CopyOnWriteArrayList<>();
-
-
-    /**
-     * The set of {@link Role}s associated with this user.
-     */
-    protected final CopyOnWriteArrayList<Role> roles = new 
CopyOnWriteArrayList<>();
-
-
-    // ------------------------------------------------------------- Properties
-
-
-    /**
-     * Return the set of {@link Group}s to which this user belongs.
-     */
-    @Override
-    public Iterator<Group> getGroups() {
-        return groups.iterator();
-    }
-
-
-    /**
-     * Return the set of {@link Role}s assigned specifically to this user.
-     */
-    @Override
-    public Iterator<Role> getRoles() {
-        return roles.iterator();
-    }
-
-
-    /**
-     * Return the {@link UserDatabase} within which this User is defined.
-     */
-    @Override
-    public UserDatabase getUserDatabase() {
-        return this.database;
-    }
-
-
-    // --------------------------------------------------------- Public Methods
-
-
-    /**
-     * Add a new {@link Group} to those this user belongs to.
-     *
-     * @param group The new group
-     */
-    @Override
-    public void addGroup(Group group) {
-        groups.addIfAbsent(group);
-    }
-
-
-    /**
-     * Add a new {@link Role} to those assigned specifically to this user.
-     *
-     * @param role The new role
-     */
-    @Override
-    public void addRole(Role role) {
-        roles.addIfAbsent(role);
-    }
-
-
-    /**
-     * Is this user in the specified group?
-     *
-     * @param group The group to check
-     */
-    @Override
-    public boolean isInGroup(Group group) {
-        return groups.contains(group);
-    }
-
-
-    /**
-     * Is this user specifically assigned the specified {@link Role}?  This
-     * method does <strong>NOT</strong> check for roles inherited based on
-     * {@link Group} membership.
-     *
-     * @param role The role to check
-     */
-    @Override
-    public boolean isInRole(Role role) {
-        return roles.contains(role);
-    }
-
-
-    /**
-     * Remove a {@link Group} from those this user belongs to.
-     *
-     * @param group The old group
-     */
-    @Override
-    public void removeGroup(Group group) {
-        groups.remove(group);
-    }
-
-
-    /**
-     * Remove all {@link Group}s from those this user belongs to.
-     */
-    @Override
-    public void removeGroups() {
-        groups.clear();
-    }
-
-
-    /**
-     * Remove a {@link Role} from those assigned to this user.
-     *
-     * @param role The old role
-     */
-    @Override
-    public void removeRole(Role role) {
-        roles.remove(role);
-    }
-
-
-    /**
-     * Remove all {@link Role}s from those assigned to this user.
-     */
-    @Override
-    public void removeRoles() {
-        roles.clear();
+        super(database, username, password, fullName, null, null);
     }
 
 
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index eee49bb..3008837 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -127,6 +127,11 @@
         <code>false</code>. Fixed via pull request <pr>438</pr> provided by
         Robert Rodewald. (markt)
       </fix>
+      <update>
+        Improve the reusability of the <code>UserDatabase</code> by adding
+        intermediate concrete implementation classes and allowing to do
+        partial database updates on <code>save</code>. (remm)
+      </update>
     </changelog>
   </subsection>
   <subsection name="Coyote">

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to