]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.security.core/src/org/argeo/util/naming/LdifParser.java
Continue framework clean up.
[lgpl/argeo-commons.git] / org.argeo.security.core / src / org / argeo / util / naming / LdifParser.java
1 package org.argeo.util.naming;
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 import org.argeo.osgi.useradmin.UserDirectoryException;
25
26 /** Basic LDIF parser. */
27 public class LdifParser {
28 private final static Log log = LogFactory.getLog(LdifParser.class);
29
30 protected Attributes addAttributes(SortedMap<LdapName, Attributes> res,
31 int lineNumber, LdapName currentDn, Attributes currentAttributes) {
32 try {
33 Rdn nameRdn = currentDn.getRdn(currentDn.size() - 1);
34 Attribute nameAttr = currentAttributes.get(nameRdn.getType());
35 if (nameAttr == null)
36 currentAttributes.put(nameRdn.getType(), nameRdn.getValue());
37 else if (!nameAttr.get().equals(nameRdn.getValue()))
38 throw new UserDirectoryException("Attribute "
39 + nameAttr.getID() + "=" + nameAttr.get()
40 + " not consistent with DN " + currentDn
41 + " (shortly before line " + lineNumber
42 + " 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 = IOUtils.readLines(in);
56 // add an empty new line since the last line is not checked
57 if (!lines.get(lines.size() - 1).equals(""))
58 lines.add("");
59
60 LdapName currentDn = null;
61 Attributes currentAttributes = null;
62 StringBuilder currentEntry = new StringBuilder();
63
64 readLines: for (int lineNumber = 0; lineNumber < lines.size(); lineNumber++) {
65 String line = lines.get(lineNumber);
66 boolean isLastLine = false;
67 if (lineNumber == lines.size() - 1)
68 isLastLine = true;
69 if (line.startsWith(" ")) {
70 currentEntry.append(line.substring(1));
71 if (!isLastLine)
72 continue readLines;
73 }
74
75 if (currentEntry.length() != 0 || isLastLine) {
76 // read previous attribute
77 StringBuilder attrId = new StringBuilder(8);
78 boolean isBase64 = false;
79 readAttrId: for (int i = 0; i < currentEntry.length(); i++) {
80 char c = currentEntry.charAt(i);
81 if (c == ':') {
82 if (i + 1 < currentEntry.length()
83 && currentEntry.charAt(i + 1) == ':')
84 isBase64 = true;
85 currentEntry.delete(0, i + (isBase64 ? 2 : 1));
86 break readAttrId;
87 } else {
88 attrId.append(c);
89 }
90 }
91
92 String attributeId = attrId.toString();
93 String cleanValueStr = currentEntry.toString().trim();
94 Object attributeValue = isBase64 ? Base64
95 .decodeBase64(cleanValueStr) : cleanValueStr;
96
97 // manage DN attributes
98 if (attributeId.equals(dn.name()) || isLastLine) {
99 if (currentDn != null) {
100 //
101 // ADD
102 //
103 Attributes previous = addAttributes(res,
104 lineNumber, currentDn, currentAttributes);
105 if (previous != null) {
106 log.warn("There was already an entry with DN "
107 + currentDn
108 + ", which has been discarded by a subsequent one.");
109 }
110 }
111
112 if (attributeId.equals(dn.name()))
113 try {
114 currentDn = new LdapName(
115 attributeValue.toString());
116 currentAttributes = new BasicAttributes(true);
117 } catch (InvalidNameException e) {
118 log.error(attributeValue
119 + " not a valid DN, skipping the entry.");
120 currentDn = null;
121 currentAttributes = null;
122 }
123 }
124
125 // store attribute
126 if (currentAttributes != null) {
127 Attribute attribute = currentAttributes
128 .get(attributeId);
129 if (attribute == null) {
130 attribute = new BasicAttribute(attributeId);
131 currentAttributes.put(attribute);
132 }
133 attribute.add(attributeValue);
134 }
135 currentEntry = new StringBuilder();
136 }
137 currentEntry.append(line);
138 }
139 } finally {
140 IOUtils.closeQuietly(in);
141 }
142 return res;
143 }
144 }