1 package org
.argeo
.util
.naming
;
3 import static org
.argeo
.osgi
.useradmin
.LdifName
.dn
;
5 import java
.io
.IOException
;
6 import java
.io
.InputStream
;
8 import java
.util
.SortedMap
;
9 import java
.util
.TreeMap
;
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
;
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
;
26 /** Basic LDIF parser. */
27 public class LdifParser
{
28 private final static Log log
= LogFactory
.getLog(LdifParser
.class);
30 protected Attributes
addAttributes(SortedMap
<LdapName
, Attributes
> res
,
31 int lineNumber
, LdapName currentDn
, Attributes currentAttributes
) {
33 Rdn nameRdn
= currentDn
.getRdn(currentDn
.size() - 1);
34 Attribute nameAttr
= currentAttributes
.get(nameRdn
.getType());
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
43 Attributes previous
= res
.put(currentDn
, currentAttributes
);
44 if (log
.isTraceEnabled())
45 log
.trace("Added " + currentDn
);
47 } catch (NamingException e
) {
48 throw new UserDirectoryException("Cannot add " + currentDn
, e
);
52 public SortedMap
<LdapName
, Attributes
> read(InputStream in
) throws IOException
{
53 SortedMap
<LdapName
, Attributes
> res
= new TreeMap
<LdapName
, Attributes
>();
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(""))
60 LdapName currentDn
= null;
61 Attributes currentAttributes
= null;
62 StringBuilder currentEntry
= new StringBuilder();
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)
69 if (line
.startsWith(" ")) {
70 currentEntry
.append(line
.substring(1));
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
);
82 if (i
+ 1 < currentEntry
.length()
83 && currentEntry
.charAt(i
+ 1) == ':')
85 currentEntry
.delete(0, i
+ (isBase64 ?
2 : 1));
92 String attributeId
= attrId
.toString();
93 String cleanValueStr
= currentEntry
.toString().trim();
94 Object attributeValue
= isBase64 ? Base64
95 .decodeBase64(cleanValueStr
) : cleanValueStr
;
97 // manage DN attributes
98 if (attributeId
.equals(dn
.name()) || isLastLine
) {
99 if (currentDn
!= null) {
103 Attributes previous
= addAttributes(res
,
104 lineNumber
, currentDn
, currentAttributes
);
105 if (previous
!= null) {
106 log
.warn("There was already an entry with DN "
108 + ", which has been discarded by a subsequent one.");
112 if (attributeId
.equals(dn
.name()))
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.");
121 currentAttributes
= null;
126 if (currentAttributes
!= null) {
127 Attribute attribute
= currentAttributes
129 if (attribute
== null) {
130 attribute
= new BasicAttribute(attributeId
);
131 currentAttributes
.put(attribute
);
133 attribute
.add(attributeValue
);
135 currentEntry
= new StringBuilder();
137 currentEntry
.append(line
);
140 IOUtils
.closeQuietly(in
);