]> git.argeo.org Git - lgpl/argeo-commons.git/blob - naming/LdifParser.java
Prepare next development cycle
[lgpl/argeo-commons.git] / naming / LdifParser.java
1 package org.argeo.util.naming;
2
3 import static org.argeo.osgi.useradmin.LdifName.dn;
4
5 import java.io.BufferedReader;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.io.InputStreamReader;
9 import java.util.ArrayList;
10 import java.util.Base64;
11 import java.util.List;
12 import java.util.SortedMap;
13 import java.util.TreeMap;
14
15 import javax.naming.InvalidNameException;
16 import javax.naming.NamingException;
17 import javax.naming.directory.Attribute;
18 import javax.naming.directory.Attributes;
19 import javax.naming.directory.BasicAttribute;
20 import javax.naming.directory.BasicAttributes;
21 import javax.naming.ldap.LdapName;
22 import javax.naming.ldap.Rdn;
23
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.argeo.osgi.useradmin.UserDirectoryException;
27
28 /** Basic LDIF parser. */
29 public class LdifParser {
30 private final static Log log = LogFactory.getLog(LdifParser.class);
31
32 protected Attributes addAttributes(SortedMap<LdapName, Attributes> res, int lineNumber, LdapName currentDn,
33 Attributes currentAttributes) {
34 try {
35 Rdn nameRdn = currentDn.getRdn(currentDn.size() - 1);
36 Attribute nameAttr = currentAttributes.get(nameRdn.getType());
37 if (nameAttr == null)
38 currentAttributes.put(nameRdn.getType(), nameRdn.getValue());
39 else if (!nameAttr.get().equals(nameRdn.getValue()))
40 throw new UserDirectoryException(
41 "Attribute " + nameAttr.getID() + "=" + nameAttr.get() + " not consistent with DN " + currentDn
42 + " (shortly before line " + lineNumber + " in LDIF file)");
43 Attributes previous = res.put(currentDn, currentAttributes);
44 if (log.isTraceEnabled())
45 log.trace("Added " + currentDn);
46 return previous;
47 } catch (NamingException e) {
48 throw new UserDirectoryException("Cannot add " + currentDn, e);
49 }
50 }
51
52 public SortedMap<LdapName, Attributes> read(InputStream in) throws IOException {
53 SortedMap<LdapName, Attributes> res = new TreeMap<LdapName, Attributes>();
54 try {
55 List<String> lines = new ArrayList<>();
56 try (BufferedReader br = new BufferedReader(new InputStreamReader(in))) {
57 String line;
58 while ((line = br.readLine()) != null) {
59 lines.add(line);
60 }
61 }
62 if (lines.size() == 0)
63 return res;
64 // add an empty new line since the last line is not checked
65 if (!lines.get(lines.size() - 1).equals(""))
66 lines.add("");
67
68 LdapName currentDn = null;
69 Attributes currentAttributes = null;
70 StringBuilder currentEntry = new StringBuilder();
71
72 readLines: for (int lineNumber = 0; lineNumber < lines.size(); lineNumber++) {
73 String line = lines.get(lineNumber);
74 boolean isLastLine = false;
75 if (lineNumber == lines.size() - 1)
76 isLastLine = true;
77 if (line.startsWith(" ")) {
78 currentEntry.append(line.substring(1));
79 if (!isLastLine)
80 continue readLines;
81 }
82
83 if (currentEntry.length() != 0 || isLastLine) {
84 // read previous attribute
85 StringBuilder attrId = new StringBuilder(8);
86 boolean isBase64 = false;
87 readAttrId: for (int i = 0; i < currentEntry.length(); i++) {
88 char c = currentEntry.charAt(i);
89 if (c == ':') {
90 if (i + 1 < currentEntry.length() && currentEntry.charAt(i + 1) == ':')
91 isBase64 = true;
92 currentEntry.delete(0, i + (isBase64 ? 2 : 1));
93 break readAttrId;
94 } else {
95 attrId.append(c);
96 }
97 }
98
99 String attributeId = attrId.toString();
100 String cleanValueStr = currentEntry.toString().trim();
101 Object attributeValue = isBase64 ? Base64.getDecoder().decode(cleanValueStr) : cleanValueStr;
102
103 // manage DN attributes
104 if (attributeId.equals(dn.name()) || isLastLine) {
105 if (currentDn != null) {
106 //
107 // ADD
108 //
109 Attributes previous = addAttributes(res, lineNumber, currentDn, currentAttributes);
110 if (previous != null) {
111 log.warn("There was already an entry with DN " + currentDn
112 + ", which has been discarded by a subsequent one.");
113 }
114 }
115
116 if (attributeId.equals(dn.name()))
117 try {
118 currentDn = new LdapName(attributeValue.toString());
119 currentAttributes = new BasicAttributes(true);
120 } catch (InvalidNameException e) {
121 log.error(attributeValue + " not a valid DN, skipping the entry.");
122 currentDn = null;
123 currentAttributes = null;
124 }
125 }
126
127 // store attribute
128 if (currentAttributes != null) {
129 Attribute attribute = currentAttributes.get(attributeId);
130 if (attribute == null) {
131 attribute = new BasicAttribute(attributeId);
132 currentAttributes.put(attribute);
133 }
134 attribute.add(attributeValue);
135 }
136 currentEntry = new StringBuilder();
137 }
138 currentEntry.append(line);
139 }
140 } finally {
141 in.close();
142 }
143 return res;
144 }
145 }