001/*
002 *  Copyright 2016 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.core.datasource;
017
018import java.io.File;
019import java.io.IOException;
020import java.util.ArrayList;
021import java.util.HashMap;
022import java.util.List;
023import java.util.Map;
024
025import org.apache.avalon.framework.configuration.Configuration;
026import org.apache.avalon.framework.configuration.ConfigurationException;
027import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
028import org.apache.commons.collections.MapUtils;
029import org.xml.sax.SAXException;
030
031import org.ametys.plugins.core.impl.checker.LDAPConnectionChecker;
032import org.ametys.runtime.i18n.I18nizableText;
033import org.ametys.runtime.model.checker.ItemChecker;
034import org.ametys.runtime.model.checker.ItemCheckerTestFailureException;
035import org.ametys.runtime.util.AmetysHomeHelper;
036
037/**
038 * This component handles SQL data sources. 
039 * It is associated with the configuration file $AMETYS_HOME/config/datasources-ldap.xml 
040 */
041public class LDAPDataSourceManager extends AbstractDataSourceManager
042{
043    /** Avalon Role */
044    public static final String ROLE = LDAPDataSourceManager.class.getName();
045    
046    /** LDAP parameter's name for base URL */
047    public static final String PARAM_BASE_URL = "baseURL";
048    /** LDAP parameter's name for base DN */
049    public static final String PARAM_BASE_DN = "baseDN";
050    /** LDAP parameter's name for use SSL */
051    public static final String PARAM_USE_SSL = "useSSL";
052    /** LDAP parameter's name for alias dereferencing */
053    public static final String PARAM_ALIAS_DEREFERENCING = "aliasDereferencing";
054    /** LDAP parameter's name for follow referrals property */
055    public static final String PARAM_FOLLOW_REFERRALS = "followReferrals";
056    /** LDAP parameter's name for authentication method */
057    public static final String PARAM_AUTHENTICATION_METHOD = "authenticationMethod";
058    /** LDAP parameter's name for administrator DN */
059    public static final String PARAM_ADMIN_DN = "adminDN";
060    /** LDAP parameter's name for administration password */
061    public static final String PARAM_ADMIN_PASSWORD = "adminPassword";
062    /** LDAP parameter's name for enabling server side sorting */
063    public static final String PARAM_SERVER_SIDE_SORTING = "serverSideSorting";
064
065    /** The id of the internal DataSource */
066    public static final String LDAP_DATASOURCE_PREFIX = "LDAP-";
067    
068    private static String __filename;
069    
070    /**
071     * Set the config filename. Only use for tests.
072     * @param filename Name with path of the config file
073     */
074    public static void setFilename(String filename)
075    {
076        __filename = filename;
077    }
078    
079    @Override
080    public File getFileConfiguration()
081    {
082        if (__filename != null)
083        {
084            return new File(__filename);
085        }
086        
087        return new File(AmetysHomeHelper.getAmetysHomeConfig(), "datasources-ldap.xml");
088    }
089    
090    @Override
091    protected String getDataSourcePrefixId()
092    {
093        return LDAP_DATASOURCE_PREFIX;
094    }
095    
096    @Override
097    protected Map<String, DataSourceDefinition> doReadConfiguration(File file)
098    {
099        Map<String, DataSourceDefinition> definitions = new HashMap<>();
100        
101        try
102        {
103            if (file.exists())
104            {
105                Configuration configuration = new DefaultConfigurationBuilder().buildFromFile(file);
106                for (Configuration dsConfig : configuration.getChildren("datasource"))
107                {
108                    String id = dsConfig.getAttribute("id");
109                    
110                    I18nizableText name = I18nizableText.parseI18nizableText(dsConfig.getChild("name"), "plugin.core");
111                    I18nizableText description = I18nizableText.parseI18nizableText(dsConfig.getChild("description"), "plugin.core", "");
112                    
113                    boolean isPrivate = dsConfig.getAttributeAsBoolean("private", false);
114                    boolean isDefault = dsConfig.getAttributeAsBoolean("default", false);
115                    
116                    Map<String, Object> parameters = new HashMap<>();
117                    
118                    Configuration[] paramsConfig = dsConfig.getChild("parameters").getChildren();
119                    for (Configuration paramConfig : paramsConfig)
120                    {
121                        String paramName = paramConfig.getName();
122                        Object value;
123                        
124                        if (paramName.equals(PARAM_USE_SSL) || paramName.equals(PARAM_FOLLOW_REFERRALS) || paramName.equals(PARAM_SERVER_SIDE_SORTING))
125                        {
126                            value = paramConfig.getValueAsBoolean(false);
127                        }
128                        else
129                        {
130                            value = paramConfig.getValue("");
131                        }
132                        
133                        parameters.put(paramConfig.getName(), value);
134                    }
135                    
136                    DataSourceDefinition dataSource = new DataSourceDefinition(id, name, description, parameters, isPrivate, isDefault);
137                    definitions.put(id, dataSource);
138                }
139            }
140            
141            return definitions;
142        }
143        catch (IOException | ConfigurationException | SAXException e)
144        {
145            throw new RuntimeException("Unable to parse datasource configuration file.", e);
146        }
147    }
148    
149    @Override
150    public void checkParameters(Map<String, Object> parameters) throws ItemCheckerTestFailureException
151    {
152        // Order the parameters
153        List<String> values = new ArrayList<> ();
154        values.add(parameters.get(PARAM_BASE_URL).toString());
155        values.add(parameters.get(PARAM_AUTHENTICATION_METHOD).toString());
156        values.add(parameters.get(PARAM_ADMIN_DN).toString());
157        values.add(parameters.get(PARAM_ADMIN_PASSWORD).toString());
158        values.add(parameters.get(PARAM_USE_SSL).toString());
159        values.add(parameters.get(PARAM_FOLLOW_REFERRALS).toString());
160        values.add(parameters.get(PARAM_BASE_DN).toString());
161        
162        ItemChecker paramChecker = new LDAPConnectionChecker();
163        paramChecker.check(values);
164    }
165    
166    @Override
167    protected void createDataSource(DataSourceDefinition dataSource)
168    {
169        // Empty
170    }
171    
172    @Override
173    protected void deleteDataSource(DataSourceDefinition dataSource)
174    {
175        // Empty
176    }
177
178    @Override
179    protected void editDataSource(DataSourceDefinition dataSource)
180    {
181        // Empty
182    }
183    
184    @Override
185    protected void internalSetDefaultDataSource()
186    {
187        // Arbitrarily set the LDAP default data source
188        if (MapUtils.isNotEmpty(_dataSourcesDef))
189        {
190            DataSourceDefinition defaultDataSourceDef = _dataSourcesDef.values().iterator().next();
191            defaultDataSourceDef.setDefault(true);
192            _dataSourcesDef.put(defaultDataSourceDef.getId(), defaultDataSourceDef);
193            
194            saveConfiguration();
195            editDataSource(defaultDataSourceDef);
196            
197        }
198    }
199}