Juan Hernandez has uploaded a new change for review.

Change subject: [WIP] Introduce new directory interface
......................................................................

[WIP] Introduce new directory interface

This change introduces a new Directory interface that represents the
connection between the engine and a generic directory server, like LDAP,
for example, but without the LDAP specific concepts that we currently
use.

It also introduces the DirectoryManager class that is responsible for
loading implementations of the Directory class using the Java service
provider mechanism, so they will be pluggable.

Note that at the moment the new classes introduced by this change are
not used anywhere, they are intended to make the engine less dependent
on LDAP concepts, but that will happen in other changes.

Note also that this change doesn't introduce any implementation of the
interfaces, that will come in other changes as well.

Change-Id: If84a0c9d6553d81cdbbe224972696f169cca90d4
Signed-off-by: Juan Hernandez <juan.hernan...@redhat.com>
---
A 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/directory/DirectoryManager.java
A 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/directory/DirectorySpi.java
A 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/users/Directory.java
A 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/users/DirectoryEntry.java
A 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/users/DirectoryEntryStatus.java
A 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/users/DirectoryGroup.java
A 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/users/DirectoryUser.java
7 files changed, 506 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/96/15596/1

diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/directory/DirectoryManager.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/directory/DirectoryManager.java
new file mode 100644
index 0000000..fd20c98
--- /dev/null
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/directory/DirectoryManager.java
@@ -0,0 +1,109 @@
+package org.ovirt.engine.core.bll.directory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ServiceLoader;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+import org.ovirt.engine.core.common.users.Directory;
+
+/**
+ * The directory manager is responsible for managing a collection of directory
+ * objects, like LDAP directories, for example.
+ *
+ * Directory implementations are loaded using the {@link ServiceLoader} class,
+ * so if you want to add a new one you will need to create the class that
+ * implements this interface and a file named
+ * <code>org.ovirt.engine.core.bll.directory.DirectorySpi</code> inside the
+ * <code>META-INF/services</code> directory of your jar file. The content of
+ * this file should be the fully qualified class name.
+ */
+public class DirectoryManager {
+    // The log:
+    private static final Logger log = Logger.getLogger(DirectoryManager.class);
+
+    // This is a singleton, and this is the instance:
+    private static volatile DirectoryManager instance;
+
+    /**
+     * Get an instance of the directory manager.
+     */
+    public static DirectoryManager getInstance() {
+        if (instance == null) {
+            synchronized(DirectoryManager.class) {
+                if (instance == null) {
+                    instance = new DirectoryManager();
+                }
+            }
+        }
+        return instance;
+    }
+
+    // Here we store the set of directory implementations loaded from the class
+    // path using the service loader mechanism:
+    private List<DirectorySpi> implementations = new ArrayList<>(2);
+
+    /**
+     * Create the singleton. This constructor is not intended to be used 
outside
+     * of this class.
+     */
+    private DirectoryManager() {
+        loadImplementations();
+    }
+
+    /**
+     * Loads the directory implementations that are available in the class path
+     * using the service loader mechanism.
+     */
+    private void loadImplementations() {
+        ServiceLoader<DirectorySpi> loader =
+            ServiceLoader.load(DirectorySpi.class);
+        for (DirectorySpi implementation : loader) {
+            implementations.add(implementation);
+            log.info(
+                "Loaded directory implementation \"" +
+                 implementation.getClass().getName() + "\"."
+            );
+        }
+    }
+
+    /**
+     * Returns the list of directories managed by all the directory
+     * implementations that have been previously loaded.
+     */
+    public List<Directory> getDirectories() {
+        List<Directory> directories = new ArrayList<Directory>();
+        for (DirectorySpi implementation : implementations) {
+            directories.addAll(implementation.getDirectories());
+        }
+        return directories;
+    }
+
+    /**
+     * Gets the directory instance that manages the directory for the given
+     * name.
+     *
+     * @param name the name of the directory
+     * @return the requested directory instance or <code>null</code> if no such
+     *   implementation can be found
+     */
+    public Directory getDirectory(String name) {
+        // Try with all the implementations and all the directories supported
+        // by each of them:
+        for (DirectorySpi implementation : implementations) {
+            for (Directory directory : implementation.getDirectories()) {
+                if (StringUtils.equals(directory.getName(), name)) {
+                    return directory;
+                }
+            }
+        }
+
+        // No luck, no directory matches the given name:
+        log.warn(
+            "There is no instance to manage directory \"" + name + "\", will " 
+
+            "return null."
+        );
+        return null;
+    }
+}
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/directory/DirectorySpi.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/directory/DirectorySpi.java
new file mode 100644
index 0000000..fdf455b
--- /dev/null
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/directory/DirectorySpi.java
@@ -0,0 +1,17 @@
+package org.ovirt.engine.core.bll.directory;
+
+import java.util.List;
+
+import org.ovirt.engine.core.common.users.Directory;
+
+/**
+ * This interface is to be implemented by the classes that provide access to
+ * directory services. Each of these implementations can support a set of
+ * directories.
+ */
+public interface DirectorySpi {
+    /**
+     * Retrieves the set of directories managed by this implementation.
+     */
+    List<Directory> getDirectories();
+}
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/users/Directory.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/users/Directory.java
new file mode 100644
index 0000000..5527b56
--- /dev/null
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/users/Directory.java
@@ -0,0 +1,85 @@
+package org.ovirt.engine.core.common.users;
+
+import java.util.Set;
+
+import org.ovirt.engine.core.compat.Guid;
+
+/**
+ * A directory is an object that manages a collection of users and groups,
+ * usually stored in an external system like an LDAP database.
+ */
+public interface Directory {
+    /**
+     * Returns the name of the directory, which usually is the name of the
+     * underlying domain, for example, for an LDAP directory the name should be
+     * based on the suffix of the LDAP database, so if the suffix is
+     * dc=example,dc=com then the name should be example.com. However this is
+     * not enforced at all, implementations can use whatever they find
+     * suitable.
+     */
+    String getName();
+
+    /**
+     * Retrieves an user from the directory given its name. The name is 
expected
+     * to be unique.
+     *
+     * @param name the name of the user
+     * @return the user corresponding to the given name or
+     *   <code>null</code> if no such user can be found
+     */
+    DirectoryUser findUserByName(String name);
+
+    /**
+     * Retrieves an user from the directory given its identifier. Note that 
this
+     * identifier is the one assigned by the engine to the user, not the one
+     * used by the directory itself. It is the responsibility of the directory
+     * implementation to translate this identifier in whatever the actual
+     * directory needs.
+     *
+     * @param id the identifier of the user
+     * @return the user corresponding to the given identifier or
+     *   <code>null</code> if no such user can be found
+     */
+    DirectoryUser findUserById(Guid id);
+
+    /**
+     * Retrieves a set of users from the directory given their identifiers.
+     *
+     * @param ids the set of identifiers
+     * @return a set containing an user for each identifier in the given set
+     *   with no particular order, note that the returned set may contain less
+     *   elements than the given set of identifiers and that it may be in a
+     *   different order
+     */
+    Set<DirectoryUser> findUsersById(Set<Guid> ids);
+
+    /**
+     * Retrieves a group from the directory given its identifier. Note that 
this
+     * identifier is the one assigned by the engine to the group, not the one
+     * used directly by the directory itself. It is the responsibility of the
+     * broker to translate this identifier into whatever the actual directory
+     * needs.
+     *
+     * @param id the identifier of the group
+     * @return the group corresponding to the given identifier or
+     *   <code>null</code> if no such group can be found
+     */
+    DirectoryGroup findGroupById(Guid id);
+
+    /**
+     * Search the directory looking for users that match the given search 
query.
+     *
+     * @param query the query
+     * @return a list containing the users that match the given query
+     */
+    Set<DirectoryUser> findUsersByQuery(String query);
+
+    /**
+     * Search the directory looking for groups that match the given search
+     * query.
+     *
+     * @param query the query
+     * @return a list containing the groups that match the given query
+     */
+    Set<DirectoryGroup> findGroupsByQuery(String query);
+}
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/users/DirectoryEntry.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/users/DirectoryEntry.java
new file mode 100644
index 0000000..6fb51b8
--- /dev/null
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/users/DirectoryEntry.java
@@ -0,0 +1,109 @@
+package org.ovirt.engine.core.common.users;
+
+import org.ovirt.engine.core.common.businessentities.IVdcQueryable;
+import org.ovirt.engine.core.common.utils.ObjectUtils;
+import org.ovirt.engine.core.compat.Guid;
+
+public class DirectoryEntry extends IVdcQueryable {
+    // Serialization id:
+    private static final long serialVersionUID = -5689096270467866486L;
+
+    // Reference to the directory where this entry was originated:
+    private Directory directory;
+
+    // The attributes of the entry:
+    private Guid id = new Guid();
+    private String name;
+    private DirectoryEntryStatus status = DirectoryEntryStatus.INACTIVE;
+
+    public DirectoryEntry(Directory directory, Guid id, String name) {
+        this.directory = directory;
+        this.id = id;
+        this.name = name;
+    }
+
+    public Guid getId() {
+        return id;
+    }
+
+    public void setId(Guid id) {
+        this.id = id;
+    }
+
+    public Directory getDirectory() {
+        return directory;
+    }
+
+    public void setDirectory(Directory directory) {
+        this.directory = directory;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public DirectoryEntryStatus getStatus() {
+        return status;
+    }
+
+    public void setStatus(DirectoryEntryStatus status) {
+        this.status = status;
+    }
+
+    @Override
+    public Object getQueryableId() {
+        return id;
+    }
+
+    /**
+     * Return the FQN of a user in a form of user@domain. If the domain is
+     * empty then only return the user name.
+     */
+    public String getFQN() {
+        // Empty user name or a user with empty domain will be returned as is:
+        if (name == null || name.length() == 0 || name.contains("@") || 
directory == null) {
+            return name;
+        } else {
+            return name + "@" + directory.getName();
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = super.hashCode();
+        result = prime * result + (id == null? 0: id.hashCode());
+        result = prime * result + (name == null? 0: name.hashCode());
+        result = prime * result + (status == null? 0: status.hashCode());
+        result = prime * result + (directory == null? 0: directory.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        DirectoryEntry other = (DirectoryEntry) obj;
+        return
+            ObjectUtils.objectsEqual(id, other.id) &&
+            ObjectUtils.objectsEqual(name, other.name) &&
+            ObjectUtils.objectsEqual(status, other.status) &&
+            ObjectUtils.objectsEqual(directory, other.directory)
+        ;
+    }
+
+    public String toString() {
+        return name + "@" + directory.getName();
+    }
+}
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/users/DirectoryEntryStatus.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/users/DirectoryEntryStatus.java
new file mode 100644
index 0000000..64b7baf
--- /dev/null
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/users/DirectoryEntryStatus.java
@@ -0,0 +1,38 @@
+package org.ovirt.engine.core.common.users;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.ovirt.engine.core.common.businessentities.Identifiable;
+
+/**
+ * A directory entry is active if it was found in the directory during the last
+ * check performed by the engine.
+ */
+public enum DirectoryEntryStatus implements Identifiable {
+    INACTIVE(0),
+    ACTIVE(1);
+
+    private int value;
+
+    private static Map<Integer, DirectoryEntryStatus> mappings = new 
HashMap<Integer, DirectoryEntryStatus>();
+
+    static {
+        for (DirectoryEntryStatus status : values()) {
+            mappings.put(status.getValue(), status);
+        }
+    }
+
+    private DirectoryEntryStatus(int value) {
+        this.value = value;
+    }
+
+    @Override
+    public int getValue() {
+        return value;
+    }
+
+    public static DirectoryEntryStatus forValue(int value) {
+        return mappings.get(value);
+    }
+}
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/users/DirectoryGroup.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/users/DirectoryGroup.java
new file mode 100644
index 0000000..f675bfc
--- /dev/null
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/users/DirectoryGroup.java
@@ -0,0 +1,12 @@
+package org.ovirt.engine.core.common.users;
+
+import org.ovirt.engine.core.compat.Guid;
+
+public class DirectoryGroup extends DirectoryEntry {
+    // Serialization identifier:
+    private static final long serialVersionUID = 7446478647138904658L;
+
+    public DirectoryGroup(Directory directory, Guid id, String name) {
+        super(directory, id, name);
+    }
+}
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/users/DirectoryUser.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/users/DirectoryUser.java
new file mode 100644
index 0000000..fd71a89
--- /dev/null
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/users/DirectoryUser.java
@@ -0,0 +1,136 @@
+package org.ovirt.engine.core.common.users;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.ovirt.engine.core.common.utils.ObjectUtils;
+import org.ovirt.engine.core.compat.Guid;
+
+public class DirectoryUser extends DirectoryEntry {
+    // Serialization id:
+    private static final long serialVersionUID = -5689096270467866486L;
+
+    // The attributes of the user, as extracted from the underlying directory:
+    private String password;
+    private String firstName;
+    private String lastName;
+    private String title;
+    private String email;
+    private String department;
+
+    // Flag indicating if this user has the administrator role:
+    private boolean isAdmin = false;
+
+    // The list of groups this user belongs to:
+    private List<DirectoryGroup> groups = new ArrayList<DirectoryGroup>(0);
+
+    public DirectoryUser(Directory directory, Guid id, String name) {
+        super(directory, id, name);
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getFirstName() {
+        return firstName;
+    }
+
+    public void setFirstName(String firstName) {
+        this.firstName = firstName;
+    }
+
+    public String getLastName() {
+        return lastName;
+    }
+
+    public void setLastName(String lastName) {
+        this.lastName = lastName;
+    }
+
+    public boolean isAdmin() {
+        return isAdmin;
+    }
+
+    public void setAdmin(boolean isAdmin) {
+        this.isAdmin = isAdmin;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public String getDepartment() {
+        return department;
+    }
+
+    public void setDepartment(String department) {
+        this.department = department;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    /**
+     * Returns the list of groups that this user belongs to. Note that the list
+     * returned may be unmodifiable, so don't try to alter it in any way.
+     */
+    public List<DirectoryGroup> getGroups() {
+        return groups;
+    }
+
+    public void setGroups(List<DirectoryGroup> groups) {
+        this.groups = groups;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = super.hashCode();
+        result = prime * result + (password == null? 0: password.hashCode());
+        result = prime * result + (firstName == null? 0: firstName.hashCode());
+        result = prime * result + (lastName == null? 0: lastName.hashCode());
+        result = prime * result + (title == null? 0: title.hashCode());
+        result = prime * result + (email == null? 0: email.hashCode());
+        result = prime * result + (department == null? 0: 
department.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        if (!super.equals(obj)) {
+            return false;
+        }
+        DirectoryUser other = (DirectoryUser) obj;
+        return
+            ObjectUtils.objectsEqual(password, other.password) &&
+            ObjectUtils.objectsEqual(department, other.department) &&
+            ObjectUtils.objectsEqual(firstName, other.firstName) &&
+            ObjectUtils.objectsEqual(lastName, other.lastName) &&
+            ObjectUtils.objectsEqual(email, other.email) &&
+            ObjectUtils.objectsEqual(department, other.department)
+        ;
+    }
+}


-- 
To view, visit http://gerrit.ovirt.org/15596
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: If84a0c9d6553d81cdbbe224972696f169cca90d4
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Juan Hernandez <juan.hernan...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to