]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.enterprise/src/org/argeo/naming/LdifWriter.java
Improve CMS UI framework.
[lgpl/argeo-commons.git] / org.argeo.enterprise / src / org / argeo / naming / LdifWriter.java
1 package org.argeo.naming;
2
3 import static org.argeo.naming.LdapAttrs.DN;
4 import static org.argeo.naming.LdapAttrs.member;
5 import static org.argeo.naming.LdapAttrs.objectClass;
6 import static org.argeo.naming.LdapAttrs.uniqueMember;
7
8 import java.io.IOException;
9 import java.io.OutputStream;
10 import java.io.OutputStreamWriter;
11 import java.io.Writer;
12 import java.nio.charset.Charset;
13 import java.nio.charset.StandardCharsets;
14 import java.util.Base64;
15 import java.util.Map;
16 import java.util.SortedSet;
17 import java.util.TreeSet;
18
19 import javax.naming.NamingEnumeration;
20 import javax.naming.NamingException;
21 import javax.naming.directory.Attribute;
22 import javax.naming.directory.Attributes;
23 import javax.naming.ldap.LdapName;
24 import javax.naming.ldap.Rdn;
25
26 import org.argeo.osgi.useradmin.UserDirectoryException;
27
28 /** Basic LDIF writer */
29 public class LdifWriter {
30 private final static Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
31 private final Writer writer;
32
33 /** Writer must be closed by caller */
34 public LdifWriter(Writer writer) {
35 this.writer = writer;
36 }
37
38 /** Stream must be closed by caller */
39 public LdifWriter(OutputStream out) {
40 this(new OutputStreamWriter(out, DEFAULT_CHARSET));
41 }
42
43 public void writeEntry(LdapName name, Attributes attributes) throws IOException {
44 try {
45 // check consistency
46 Rdn nameRdn = name.getRdn(name.size() - 1);
47 Attribute nameAttr = attributes.get(nameRdn.getType());
48 if (!nameAttr.get().equals(nameRdn.getValue()))
49 throw new UserDirectoryException(
50 "Attribute " + nameAttr.getID() + "=" + nameAttr.get() + " not consistent with DN " + name);
51
52 writer.append(DN + ": ").append(name.toString()).append('\n');
53 Attribute objectClassAttr = attributes.get(objectClass.name());
54 if (objectClassAttr != null)
55 writeAttribute(objectClassAttr);
56 attributes: for (NamingEnumeration<? extends Attribute> attrs = attributes.getAll(); attrs.hasMore();) {
57 Attribute attribute = attrs.next();
58 if (attribute.getID().equals(DN) || attribute.getID().equals(objectClass.name()))
59 continue attributes;// skip DN attribute
60 if (attribute.getID().equals(member.name()) || attribute.getID().equals(uniqueMember.name()))
61 continue attributes;// skip member and uniqueMember attributes, so that they are always written last
62 writeAttribute(attribute);
63 }
64 // write member and uniqueMember attributes last
65 for (NamingEnumeration<? extends Attribute> attrs = attributes.getAll(); attrs.hasMore();) {
66 Attribute attribute = attrs.next();
67 if (attribute.getID().equals(member.name()) || attribute.getID().equals(uniqueMember.name()))
68 writeMemberAttribute(attribute);
69 }
70 writer.append('\n');
71 writer.flush();
72 } catch (NamingException e) {
73 throw new UserDirectoryException("Cannot write LDIF", e);
74 }
75 }
76
77 public void write(Map<LdapName, Attributes> entries) throws IOException {
78 for (LdapName dn : entries.keySet())
79 writeEntry(dn, entries.get(dn));
80 }
81
82 protected void writeAttribute(Attribute attribute) throws NamingException, IOException {
83 for (NamingEnumeration<?> attrValues = attribute.getAll(); attrValues.hasMore();) {
84 Object value = attrValues.next();
85 if (value instanceof byte[]) {
86 String encoded = Base64.getEncoder().encodeToString((byte[]) value);
87 writer.append(attribute.getID()).append(":: ").append(encoded).append('\n');
88 } else {
89 writer.append(attribute.getID()).append(": ").append(value.toString()).append('\n');
90 }
91 }
92 }
93
94 protected void writeMemberAttribute(Attribute attribute) throws NamingException, IOException {
95 // Note: duplicate entries will be swallowed
96 SortedSet<String> values = new TreeSet<>();
97 for (NamingEnumeration<?> attrValues = attribute.getAll(); attrValues.hasMore();) {
98 String value = attrValues.next().toString();
99 values.add(value);
100 }
101
102 for (String value : values) {
103 writer.append(attribute.getID()).append(": ").append(value).append('\n');
104 }
105 }
106 }