static NamingEnumeration parseSearchResponse(String response, String searchBase)
throws NamingException
{
checkForError(response);
DXNamingEnumeration en = new DXNamingEnumeration();
Matcher responseMatcher = searchResultEntry.matcher(response);
// cycle through the available entries
while (responseMatcher.find())
{
String dn = responseMatcher.group(1);
BasicAttributes atts = new BasicAttributes();
if (dn.indexOf("requestID") > -1) // what numb nut would put a requestID in a searchResultEntry??
{
int reqPos = dn.indexOf("requestID");
int endPos = dn.lastIndexOf('"', reqPos);
dn = dn.substring(0, endPos);
}
if (dn.indexOf("&") > -1)
dn = unescape(dn);
log.finest("Parsing DSML: read DN: " + dn);
// turn pure pristine LDAP DN into un unbelievably screwed up JNDI Composite name, and then
// store it as a string SO NO ONE CAN EVER REALLY TELL WHAT THE HELL IT IS. God JNDI is
// broken - what a (*&*^ joke. Object Oriented? Yeah, we've heard of that...
dn = new CompositeName(dn).toString();
log.finest("converted DN to: " + dn);
String attribute = responseMatcher.group(2);
Matcher attributeMatcher = searchResultAttribute.matcher(attribute);
// cycle through individual attributes
while (attributeMatcher.find())
{
String attributeName = attributeMatcher.group(1);
BasicAttribute att = new BasicAttribute(attributeName);
String attributeValues = attributeMatcher.group(2);
log.finest("Parsing DSML: Attribute Name " + attributeName + " length: " + attributeValues.length());
Matcher valueMatcher = searchResultAttributeValues.matcher(attributeValues);
while (valueMatcher.find())
{
String typeInfo = valueMatcher.group(1);
String type = "string"; // the default value is string
if (typeInfo != null && typeInfo.length() > 6)
{
// don't bother using regexp - faster to use string handling (if insanely clever might modify attributeValues regexp??)
int typeInfoStart = typeInfo.indexOf("type=\"");
int typeInfoEnd = typeInfo.indexOf('\"', typeInfoStart + 6);
if (typeInfoStart != -1 && typeInfoEnd > typeInfoStart)
{
type = typeInfo.substring(typeInfoStart + 6, typeInfoEnd); // extract the type; e.g. xsd:base64Binary
if ((typeInfoStart = type.indexOf(':')) > -1) // trim any namespace from the type (e.g. 'xsd:')
type = type.substring(typeInfoStart + 1);
}
}
String value = valueMatcher.group(2);
if (type.equals("string")) // this is the usual case, and the default
{
if (value != null && value.indexOf('&') > -1)
value = unescape(value);
att.add(value);
}
else if (type.equals("anyURI"))
throw new NamingException("CA JNDI DSML Provider does not support 'anyURI' values");
else if (type.equals("base64Binary"))
{
try
{
System.out.println("PROCESSING BINARY VALUE " + attributeName);
byte[] data = CBBase64.decode(value);
System.out.println("RAW DATA: " + value.length() + " byte data " + data.length);
att.add(CBBase64.decode(value));
}
catch (CBBase64EncodingException e)
{
NamingException ne = new NamingException("unable to parse base64 value in entry: " + dn);
ne.setRootCause(e);
throw ne;
}
}
}
atts.put(att);
}
SearchResult currentResult = new SearchResult(dn, null, atts);
// The search result sets 'is relative' to true by default. Check if the
// DN in the search result contains the search base, if so set 'is relative'
// to false so that the search base is NOT added to the DN again. In otherwords
// check if the full DN has been returned in the search result...
if(dn.endsWith(searchBase))
currentResult.setRelative(false);
en.add(currentResult);
}
log.finest("Parsing DSML: final enumeration - \n" + en.toString());
return en;
}