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