blob: d99d67e76de03d0fa0eea92d5a6c9ad5ce47eba9 [file] [log] [blame]
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.server.ldap;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
/** Supports issuing parameterized queries against an LDAP data source. */
class LdapQuery {
private final String base;
private final SearchScope searchScope;
private final String pattern;
private final String[] patternArgs;
private final String[] returnAttributes;
LdapQuery(final String base, final SearchScope searchScope,
final String pattern, final Set<String> returnAttributes) {
this.base = base;
this.searchScope = searchScope;
final StringBuilder p = new StringBuilder();
final List<String> a = new ArrayList<String>(4);
int i = 0;
while (i < pattern.length()) {
final int b = pattern.indexOf("${", i);
if (b < 0) {
break;
}
final int e = pattern.indexOf("}", b + 2);
if (e < 0) {
break;
}
p.append(pattern.substring(i, b));
p.append("{" + a.size() + "}");
a.add(pattern.substring(b + 2, e));
i = e + 1;
}
if (i < pattern.length()) {
p.append(pattern.substring(i));
}
this.pattern = p.toString();
this.patternArgs = new String[a.size()];
a.toArray(this.patternArgs);
this.returnAttributes = new String[returnAttributes.size()];
returnAttributes.toArray(this.returnAttributes);
}
String[] getParameters() {
return patternArgs;
}
List<Result> query(final DirContext ctx, final Map<String, String> params)
throws NamingException {
final SearchControls sc = new SearchControls();
final NamingEnumeration<SearchResult> res;
sc.setSearchScope(searchScope.scope());
sc.setReturningAttributes(returnAttributes);
res = ctx.search(base, pattern, bind(params), sc);
try {
final List<Result> r = new ArrayList<Result>();
while (res.hasMore()) {
r.add(new Result(res.next()));
}
return r;
} finally {
res.close();
}
}
private String[] bind(final Map<String, String> params) {
final String[] r = new String[patternArgs.length];
for (int i = 0; i < r.length; i++) {
r[i] = params.get(patternArgs[i]);
if (r[i] == null) {
r[i] = "";
}
}
return r;
}
class Result {
private final Map<String, String> atts = new HashMap<String, String>();
Result(final SearchResult sr) throws NamingException {
for (final String attName : returnAttributes) {
final Attribute a = sr.getAttributes().get(attName);
if (a != null && a.size() > 0) {
atts.put(attName, String.valueOf(a.get(0)));
}
}
atts.put("dn", sr.getNameInNamespace());
}
String get(final String attName) {
return atts.get(attName);
}
}
}