| // 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.auth.ldap; |
| |
| import com.google.gerrit.common.data.ParameterizedString; |
| import com.google.gerrit.metrics.Timer0; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| 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.PartialResultException; |
| import javax.naming.directory.Attribute; |
| import javax.naming.directory.BasicAttribute; |
| 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 { |
| static final Set<String> ALL_ATTRIBUTES = null; |
| |
| private final String base; |
| private final SearchScope searchScope; |
| private final ParameterizedString pattern; |
| private final String[] returnAttributes; |
| |
| LdapQuery( |
| final String base, |
| final SearchScope searchScope, |
| final ParameterizedString pattern, |
| final Set<String> returnAttributes) { |
| this.base = base; |
| this.searchScope = searchScope; |
| |
| this.pattern = pattern; |
| |
| if (returnAttributes != null) { |
| this.returnAttributes = new String[returnAttributes.size()]; |
| returnAttributes.toArray(this.returnAttributes); |
| } else { |
| this.returnAttributes = null; |
| } |
| } |
| |
| List<String> getParameters() { |
| return pattern.getParameterNames(); |
| } |
| |
| List<Result> query(DirContext ctx, Map<String, String> params, Timer0 queryTimer) |
| throws NamingException { |
| final SearchControls sc = new SearchControls(); |
| final NamingEnumeration<SearchResult> res; |
| |
| sc.setSearchScope(searchScope.scope()); |
| sc.setReturningAttributes(returnAttributes); |
| try (Timer0.Context ignored = queryTimer.start()) { |
| res = ctx.search(base, pattern.getRawPattern(), pattern.bind(params), sc); |
| } |
| try { |
| final List<Result> r = new ArrayList<>(); |
| try { |
| while (res.hasMore()) { |
| r.add(new Result(res.next())); |
| } |
| } catch (PartialResultException e) { |
| // Ignored |
| } |
| return r; |
| } finally { |
| res.close(); |
| } |
| } |
| |
| class Result { |
| private final Map<String, Attribute> atts = new HashMap<>(); |
| |
| Result(SearchResult sr) { |
| if (returnAttributes != null) { |
| for (String attName : returnAttributes) { |
| final Attribute a = sr.getAttributes().get(attName); |
| if (a != null && a.size() > 0) { |
| atts.put(attName, a); |
| } |
| } |
| |
| } else { |
| NamingEnumeration<? extends Attribute> e = sr.getAttributes().getAll(); |
| while (e.hasMoreElements()) { |
| final Attribute a = e.nextElement(); |
| atts.put(a.getID(), a); |
| } |
| } |
| |
| atts.put("dn", new BasicAttribute("dn", sr.getNameInNamespace())); |
| } |
| |
| String getDN() throws NamingException { |
| return get("dn"); |
| } |
| |
| String get(String attName) throws NamingException { |
| final Attribute att = getAll(attName); |
| return att != null && 0 < att.size() ? String.valueOf(att.get(0)) : null; |
| } |
| |
| Attribute getAll(String attName) { |
| return atts.get(attName); |
| } |
| |
| Set<String> attributes() { |
| return Collections.unmodifiableSet(atts.keySet()); |
| } |
| |
| @Override |
| public String toString() { |
| try { |
| return getDN(); |
| } catch (NamingException e) { |
| return ""; |
| } |
| } |
| } |
| } |