001/*
002 *  Copyright 2010 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.plugins.externaldata.data.ldap;
017
018import java.util.HashMap;
019import java.util.LinkedHashMap;
020import java.util.Map;
021import java.util.regex.Matcher;
022import java.util.regex.Pattern;
023
024import org.apache.commons.lang.StringUtils;
025
026import org.ametys.core.datasource.DataSourceClientInteraction.DataSourceType;
027import org.ametys.plugins.externaldata.data.AbstractQuery;
028
029/**
030 * A LDAP query.
031 */
032public class LdapQuery extends AbstractQuery
033{
034    /** Attribute pattern (matches attributeName[attributeLabel]). */
035    public static final String ATTRIBUTE_PATTERN = "(\\w+)(?:\\[([^\\]]+)\\])?";
036    
037    /** Attribute matcher. */
038    public static final Pattern ATTRIBUTE_MATCHER = Pattern.compile(ATTRIBUTE_PATTERN);
039    
040    /** The LDAP attributes to return. */
041    protected String _attributes;
042    
043    /** The LDAP constraint, optionally contains parameters. */
044    protected String _constraint;
045    
046    /** Relative DN for users. */
047    protected String _relativeDN;
048    
049    /** The LDAP constraint, optionally contains parameters. */
050    protected String _scope;
051    
052    /** The decoded attributes. */
053    protected Map<String, String> _attributeMap;
054    
055    @Override
056    public DataSourceType getType()
057    {
058        return DataSourceType.LDAP;
059    }
060    
061    /**
062     * Get the LDAP attributes to return.
063     * @return the LDAP attributes.
064     */
065    public String getAttributes()
066    {
067        return _attributes;
068    }
069    
070    /**
071     * Set the LDAP attributes to return.
072     * @param attributes LDAP attributes to return.
073     */
074    public void setAttributes(String attributes)
075    {
076        this._attributes = attributes;
077    }
078    
079    /**
080     * Get the LDAP constraint.
081     * @return the LDAP constraint.
082     */
083    public String getConstraint()
084    {
085        return _constraint;
086    }
087    
088    /**
089     * Set the LDAP constraint.
090     * @param constraint the LDAP constraint to set.
091     */
092    public void setConstraint(String constraint)
093    {
094        this._constraint = constraint;
095    }
096    
097    /**
098     * Set relative DN for users
099     * @param relativeDN the LDAP relative DN for users
100     */
101    public void setRelativeDN(String relativeDN)
102    {
103        this._relativeDN = relativeDN;
104    }
105    
106    /**
107     * Get the relative DN for users
108     * @return the relative DN for users
109     */
110    public String getRelativeDN()
111    {
112        return _relativeDN;
113    }
114    
115    /**
116     * Get the LDAP scope.
117     * @return the LDAP scope
118     */
119    public String getScope()
120    {
121        return _scope;
122    }
123
124    /**
125     * Set the LDAP scope.
126     * @param scope the LDAP scope to set
127     */
128    public void setScope(String scope)
129    {
130        _scope = scope;
131    }
132    
133    @Override
134    public Map<String, String> getParameters()
135    {
136        if (_parameters == null)
137        {
138            _parameters = _buildParameters(_constraint);
139        }
140        return _parameters;
141    }
142    
143    @Override
144    public Map<String, String> getAdditionalConfiguration()
145    {
146        Map<String, String> additionalConf = new HashMap<>();
147        
148        additionalConf.put("attributes", _attributes);
149        additionalConf.put("constraint", _constraint);
150        additionalConf.put("scope", _scope);
151        additionalConf.put("relativeDN", _relativeDN);
152        
153        return additionalConf;
154    }
155    
156    /**
157     * Get attributes as Map.
158     * @return the attributes as a Map of attributeName -&gt; label.
159     */
160    public Map<String, String> getAttributesAsMap()
161    {
162        if (_attributeMap == null)
163        {
164            _attributeMap = _buildAttributesMap(_attributes);
165        }
166        return _attributeMap;
167    }
168    
169    /**
170     * Extract attributes from a query string in the form "attr1[label1], attr2[label2], attr3".
171     * @param query the query containing parameters.
172     * @return the attributes as a Map of label -&gt; attributeName. If no label was provided between brackets, the name is used.
173     */
174    protected Map<String, String> _buildAttributesMap(String query)
175    {
176        Map<String, String> attributes = new LinkedHashMap<>();
177        
178        if (query != null)
179        {
180            String[] attributeArray = query.split(",");
181            
182            for (String attribute : attributeArray)
183            {
184                String attributeTrimmed = attribute.trim();
185                Matcher matcher = ATTRIBUTE_MATCHER.matcher(attributeTrimmed);
186                while (matcher.find())
187                {
188                    if (matcher.groupCount() == 1)
189                    {
190                        String attrName = matcher.group(1);
191                        attributes.put(attrName, attrName);
192                    }
193                    else if (matcher.groupCount() > 1)
194                    {
195                        String attrName = matcher.group(1);
196                        String attrLabel = matcher.group(2);
197                        if (StringUtils.isBlank(attrLabel))
198                        {
199                            attrLabel = attrName;
200                        }
201                        attributes.put(attrLabel, attrName);
202                    }
203                }
204            }
205        }
206        
207        return attributes;
208    }
209}