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