| // 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); |
| } |
| } |
| } |