/**
* Licensed to the Austrian Association for Software Tool Integration (AASTI)
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. The AASTI licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openengsb.connector.userprojects.ldap.internal.ldap;
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.apache.directory.shared.ldap.model.entry.DefaultEntry;
import org.apache.directory.shared.ldap.model.entry.Entry;
import org.apache.directory.shared.ldap.model.exception.LdapException;
import org.apache.directory.shared.ldap.model.name.Dn;
import org.openengsb.connector.userprojects.ldap.internal.LdapRuntimeException;
import org.openengsb.domain.userprojects.model.Assignment;
import org.openengsb.domain.userprojects.model.Attribute;
import org.openengsb.domain.userprojects.model.Credential;
import org.openengsb.domain.userprojects.model.Permission;
import org.openengsb.domain.userprojects.model.Project;
import org.openengsb.domain.userprojects.model.Role;
import org.openengsb.domain.userprojects.model.User;
/**
* Builds entries for various nodes in the DIT. The returned entries have a valid Dn and all provided attributes.
* */
public final class EntryFactory {
private EntryFactory() {
}
/**
* Returns a list of entries representing an assignment. The list should not be reordered since its order follows
* the tree structure of the DIT. It can be inserted into the DIT right away.
*/
public static List<Entry> assignmentStructure(Assignment assignment) {
List<Entry> entryList = new LinkedList<>();
entryList.add(namedObject(DnFactory.assignment(assignment)));
entryList.add(namedDescriptiveObject(DnFactory.assignmentProject(assignment), assignment.getProject()));
entryList.add(namedDescriptiveObject(DnFactory.assignmentUser(assignment), assignment.getUser()));
entryList.addAll(createAssignmentPermissionsEntries(assignment));
entryList.addAll(createAssignmentRolesEntries(assignment));
return entryList;
}
private static List<Entry> createAssignmentPermissionsEntries(Assignment assignment) {
List<Entry> entryList = new LinkedList<>();
Entry entry = organizationalUnit(DnFactory.assignmentPermissions(assignment));
entryList.add(entry);
for (String permission : assignment.getPermissions()) {
entryList.add(namedObject(DnFactory.assignmentPermission(assignment, permission)));
}
return entryList;
}
private static List<Entry> createAssignmentRolesEntries(Assignment assignment) {
List<Entry> entryList = new LinkedList<>();
Entry entry = organizationalUnit(DnFactory.assignmentRoles(assignment));
entryList.add(entry);
for (String role : assignment.getRoles()) {
entryList.add(namedObject(DnFactory.assignmentRole(assignment, role)));
}
return entryList;
}
/**
* Returns a list of entries representing a permission. The list should not be reordered since its order follows the
* tree structure of the DIT. It can be inserted into the DIT right away.
*/
public static List<Entry> permissionStructure(Permission permission) {
List<Entry> entryList = new LinkedList<>();
entryList.add(namedObject(DnFactory.permission(permission)));
entryList.add(namedDescriptiveObject(DnFactory.permissionAction(permission), permission.getAction()));
entryList
.add(namedDescriptiveObject(DnFactory.permissionComponent(permission), permission.getComponentName()));
return entryList;
}
/**
* Returns a list of entries representing a project. The list should not be reordered since its order follows the
* tree structure of the DIT. It can be inserted into the DIT right away.
*/
public static List<Entry> projectStructure(Project project) {
List<Entry> entryList = new LinkedList<>();
entryList.add(namedObject(DnFactory.project(project)));
entryList.addAll(createProjectAttributesEntries(project));
return entryList;
}
private static List<Entry> createProjectAttributesEntries(Project project) {
List<Entry> entryList = new LinkedList<>();
Entry userAttributesEntry = organizationalUnit(DnFactory.projectAttributes(project));
entryList.add(userAttributesEntry);
for (Attribute attribute : project.getAttributes()) {
entryList.add(namedDescriptiveObject(DnFactory.projectAttribute(project, attribute), attribute
.getValues().toArray(new String[] {})));
}
return entryList;
}
/**
* Returns a list of entries representing a role. The list should not be reordered since its order follows the tree
* structure of the DIT. It can be inserted into the DIT right away.
*/
public static List<Entry> roleStructure(Role role) {
List<Entry> entryList = new LinkedList<>();
entryList.add(namedObject(DnFactory.role(role)));
entryList.addAll(createRolePermissionsEntries(role));
entryList.addAll(createRoleSubrolesEntries(role));
return entryList;
}
private static List<Entry> createRolePermissionsEntries(Role role) {
List<Entry> entryList = new LinkedList<>();
Entry entry = organizationalUnit(DnFactory.rolePermissions(role));
entryList.add(entry);
for (String permission : role.getPermissions()) {
entryList.add(namedObject(DnFactory.rolePermission(role, permission)));
}
return entryList;
}
private static List<Entry> createRoleSubrolesEntries(Role role) {
List<Entry> entryList = new LinkedList<>();
Entry entry = organizationalUnit(DnFactory.roleSubroles(role));
entryList.add(entry);
for (String subrole : role.getRoles()) {
entryList.add(namedObject(DnFactory.roleSubrole(role, subrole)));
}
return entryList;
}
/**
* Returns a list of entries representing the {@link User} along with its credentials and attributes. The list
* should not be reordered since its order follows the tree structure of the DIT. It can be inserted into the DIT
* right away.
*/
public static List<Entry> userStructure(User user) {
List<Entry> entryList = new LinkedList<>();
entryList.add(namedObject(user.getUsername(), DnFactory.users()));
entryList.addAll(createCredentialsEntries(user));
entryList.addAll(createUserAttributesEntries(user));
return entryList;
}
private static List<Entry> createCredentialsEntries(User user) {
List<Entry> entryList = new LinkedList<>();
Entry credentialsEntry = organizationalUnit(DnFactory.userCredentials(user));
entryList.add(credentialsEntry);
for (Credential credential : user.getCredentials()) {
entryList.add(namedDescriptiveObject(DnFactory.userCredential(user, credential), credential.getValue()));
}
return entryList;
}
private static List<Entry> createUserAttributesEntries(User user) {
List<Entry> entryList = new LinkedList<>();
Entry userAttributesEntry = organizationalUnit(DnFactory.userAttributes(user));
entryList.add(userAttributesEntry);
for (Attribute attribute : user.getAttributes()) {
entryList.add(namedDescriptiveObject(DnFactory.userAttribute(user, attribute), attribute.getValues()
.toArray(new String[] {})));
}
return entryList;
}
/**
* Returns an {@link Entry} with the given {@link Dn}. The attribute type of the Rdn is 'organizational unit'.
* */
public static Entry organizationalUnit(Dn dn) {
Entry entry = new DefaultEntry(dn);
try {
entry.add(SchemaConstants.OBJECT_CLASS_ATTRIBUTE, SchemaConstants.ORGANIZATIONAL_UNIT_OC);
entry.add(SchemaConstants.OU_ATTRIBUTE, dn.getRdn().getName());
} catch (LdapException e) {
throw new LdapRuntimeException(e);
}
return entry;
}
/**
* Returns an {@link Entry} having the given {@link Dn}. The attribute type of the Rdn is 'common name'.
* */
public static Entry namedObject(Dn dn) {
Entry entry = new DefaultEntry(dn);
try {
entry.add(SchemaConstants.OBJECT_CLASS_ATTRIBUTE, SchemaConstants.NAMED_OBJECT_OC);
entry.add(SchemaConstants.CN_ATTRIBUTE, dn.getRdn().getName());
} catch (LdapException e) {
throw new LdapRuntimeException(e);
}
return entry;
}
/**
* Returns an {@link Entry} whose {@link Dn} is baseDn followed by name as Rdn. The attribute type of the Rdn is
* 'common name'.
* */
public static Entry namedObject(String name, Dn baseDn) {
Dn dn = Utils.concatDn(SchemaConstants.CN_ATTRIBUTE, name, baseDn);
return namedObject(dn);
}
/**
* Returns an {@link Entry} having the given {@link Dn}. The attribute type of the Rdn is 'common name'. The
* description is optional in that it may also be null or the empty String. Callers can rely on this distinction,
* i.e. storing an empty string will also retrieve an empty string and storing null will also retrieve null.
* */
public static Entry namedDescriptiveObject(Dn dn, String... descriptions) {
Entry entry = namedObject(dn);
addDescriptions(entry, descriptions);
return entry;
}
/**
* 3 possibilities:<br>
* 1) description is null -> emptyFlag = false, no description attribute <br>
* 2) description is empty -> emptyFlag = true, no description attribute <br>
* 3) description exists -> no emptyFlag, description attribute exists and has a value
* */
private static void addDescriptions(Entry entry, String... descriptions) {
try {
entry.add(SchemaConstants.OBJECT_CLASS_ATTRIBUTE, SchemaConstants.DESCRIPTIVE_OBJECT_OC);
if (descriptions == null) {
// case 1
entry.add(SchemaConstants.EMPTY_FLAG_ATTRIBUTE, String.valueOf(false));
} else if (descriptions.length == 1 && descriptions[0].isEmpty()) {
// case 2
entry.add(SchemaConstants.EMPTY_FLAG_ATTRIBUTE, String.valueOf(true));
} else {
// case 3
entry.add(SchemaConstants.STRING_ATTRIBUTE,
StringUtils.join(descriptions, ServerConfig.multipleValueSeparator));
}
} catch (LdapException e) {
throw new LdapRuntimeException(e);
}
}
}