/**
* 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.core.services.internal.security.ldap;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
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.core.services.internal.security.model.EntryElement;
import org.openengsb.core.services.internal.security.model.EntryValue;
import org.openengsb.core.services.internal.security.model.PermissionData;
/**
* 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 an {@link Entry} whose {@link Dn} is baseDn followed by ou as Rdn. The attribute type of the Rdn is
* 'organizational unit'.
* */
public static Entry organizationalUnit(String ou, Dn baseDn) {
Dn dn = LdapUtils.concatDn(SchemaConstants.OU_ATTRIBUTE, ou, baseDn);
Entry entry = new DefaultEntry(dn);
try {
entry.add(SchemaConstants.OBJECT_CLASS_ATTRIBUTE, SchemaConstants.ORGANIZATIONAL_UNIT_OC);
entry.add(SchemaConstants.OU_ATTRIBUTE, ou);
} 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 = LdapUtils.concatDn(SchemaConstants.CN_ATTRIBUTE, name, baseDn);
Entry entry = new DefaultEntry(dn);
try {
entry.add(SchemaConstants.OBJECT_CLASS_ATTRIBUTE, SchemaConstants.NAMED_OBJECT_OC);
entry.add(SchemaConstants.CN_ATTRIBUTE, name);
} 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'. 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(String name, String description, Dn baseDn) throws LdapRuntimeException {
Entry entry = namedObject(name, baseDn);
addDescription(entry, description);
return entry;
}
/**
* Returns an {@link Entry} whose Dn is baseDn followed by classname as Rdn. The attribute type of the Rdn is
* javaClassName. The constructorArgument is treated as an optional description as explained in
* {@link #namedDescriptiveObject(String, String, Dn)}.
* */
public static Entry javaObject(String classname, String constructorArgument, Dn baseDn) {
Dn dn = LdapUtils.concatDn(SchemaConstants.JAVA_CLASS_NAME_ATTRIBUTE, classname, baseDn);
Entry entry = new DefaultEntry(dn);
try {
entry.add(SchemaConstants.OBJECT_CLASS_ATTRIBUTE, SchemaConstants.JAVA_CLASS_INSTANCE_OC);
entry.add(SchemaConstants.JAVA_CLASS_NAME_ATTRIBUTE, classname);
addDescription(entry, constructorArgument);
} catch (LdapException e) {
throw new LdapRuntimeException(e);
}
return entry;
}
/**
* Returns a list of entries representing a permissionSet. 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> globalPermissionSetStructure(String permissionSet) {
Entry permissionSetEntry = namedObject(permissionSet, SchemaConstants.ouGlobalPermissionSets());
Entry ouDirect = organizationalUnit("direct", permissionSetEntry.getDn());
Entry ouChildrenSets = organizationalUnit("childrenSets", permissionSetEntry.getDn());
Entry ouAttributes = organizationalUnit("attributes", permissionSetEntry.getDn());
return Arrays.asList(permissionSetEntry, ouAttributes, ouDirect, ouChildrenSets);
}
/**
* Returns a list of entries representing a list of {@link PermissionData}. 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> permissionStructureFromPermissionData(Collection<PermissionData> data, Dn baseDn) {
List<Entry> permissions = new LinkedList<Entry>();
List<Entry> properties = new LinkedList<Entry>();
List<Entry> propertyValues = new LinkedList<Entry>();
List<Entry> result = new LinkedList<Entry>();
for (PermissionData p : data) {
String permissionType = p.getType();
Entry permissionEntry = javaObject(permissionType, null, baseDn);
TimebasedOrderFilter.addId(permissionEntry, true);
permissions.add(permissionEntry);
for (EntryValue entryValue : p.getAttributes().values()) {
String propertyKey = entryValue.getKey();
Entry propertyEntry = namedObject(propertyKey, permissionEntry.getDn());
properties.add(propertyEntry);
for (EntryElement entryElement : entryValue.getValue()) {
String type = entryElement.getType();
String value = entryElement.getValue();
Entry propertyValueEntry = javaObject(type, value, propertyEntry.getDn());
TimebasedOrderFilter.addId(propertyValueEntry, true);
propertyValues.add(propertyValueEntry);
}
}
}
result.addAll(permissions);
result.addAll(properties);
result.addAll(propertyValues);
return result;
}
/**
* 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 addDescription(Entry entry, String description) {
try {
entry.add(SchemaConstants.OBJECT_CLASS_ATTRIBUTE, SchemaConstants.DESCRIPTIVE_OBJECT_OC);
if (description == null) {
entry.add(SchemaConstants.EMPTY_FLAG_ATTRIBUTE, String.valueOf(false)); // case 1
} else if (description.isEmpty()) {
entry.add(SchemaConstants.EMPTY_FLAG_ATTRIBUTE, String.valueOf(true)); // case 2
} else {
entry.add(SchemaConstants.STRING_ATTRIBUTE, description); // case 3
}
} catch (LdapException e) {
throw new LdapRuntimeException(e);
}
}
}