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.runtime.plugins.admin.datasource;
017
018import java.util.HashMap;
019import java.util.Iterator;
020import java.util.List;
021import java.util.Map;
022
023import org.apache.avalon.framework.component.Component;
024import org.apache.avalon.framework.service.ServiceException;
025import org.apache.avalon.framework.service.ServiceManager;
026import org.apache.avalon.framework.service.Serviceable;
027import org.apache.commons.lang3.StringUtils;
028
029import org.ametys.core.datasource.AbstractDataSourceManager.DataSourceDefinition;
030import org.ametys.core.datasource.DataSourceClientInteraction.DataSourceType;
031import org.ametys.core.datasource.LDAPDataSourceManager;
032import org.ametys.core.datasource.SQLDataSourceManager;
033import org.ametys.core.datasource.dbtype.SQLDatabaseTypeExtensionPoint;
034import org.ametys.core.datasource.dbtype.SQLDatabaseTypeManager;
035import org.ametys.core.ui.Callable;
036import org.ametys.plugins.core.impl.datasource.StaticSQLDatabaseType;
037import org.ametys.runtime.model.checker.ItemCheckerTestFailureException;
038import org.ametys.runtime.plugin.component.AbstractLogEnabled;
039
040/**
041 * Checks the validity of a data source's parameters
042 */
043public class CheckDataSourceHelper extends AbstractLogEnabled implements Component, Serviceable
044{
045    /** The avalon role */
046    public static final String ROLE = CheckDataSourceHelper.class.getName();
047    
048    /** The id of the SQL data source checker */
049    private static final String __SQL_DATASOURCE_CHECKER_ID = "sql-connection-checker-datasource";
050    
051    /** The manager for SQL data source */
052    private SQLDataSourceManager _sqlDataSourceManager;
053    
054    /** The manager for SQL data source */
055    private LDAPDataSourceManager _ldapDataSourceManager;
056    
057    /** The manager for SQL database types */
058    private SQLDatabaseTypeManager _sqlDatabaseTypeManager;
059    
060    /** The extension point for SQL database types */
061    private SQLDatabaseTypeExtensionPoint _sqlDatabaseTypeExtensionPoint;
062    
063    @Override
064    public void service(ServiceManager serviceManager) throws ServiceException
065    {
066        _ldapDataSourceManager = (LDAPDataSourceManager) serviceManager.lookup(LDAPDataSourceManager.ROLE);
067        _sqlDataSourceManager = (SQLDataSourceManager) serviceManager.lookup(SQLDataSourceManager.ROLE);
068        _sqlDatabaseTypeManager = (SQLDatabaseTypeManager) serviceManager.lookup(SQLDatabaseTypeManager.ROLE);
069        _sqlDatabaseTypeExtensionPoint = (SQLDatabaseTypeExtensionPoint) serviceManager.lookup(SQLDatabaseTypeExtensionPoint.ROLE);
070    }
071    
072    /**
073     * Check the datasource configuration values for the requested checkers
074     * @param fieldCheckersInfo a JSON map of the checkers info
075     * @return a map with each failed checker id and the associated message
076     */
077    @Callable(rights = "Runtime_Rights_Admin_Access", context = "/admin")
078    public Map<String, Object> check(Map<String, Object> fieldCheckersInfo)
079    {
080        Map<String, Object> result = new HashMap<> ();
081        
082        Iterator<String> fieldCheckersIds = fieldCheckersInfo.keySet().iterator();
083        
084        while (fieldCheckersIds.hasNext())
085        {
086            String fieldCheckerId = fieldCheckersIds.next();
087            
088            @SuppressWarnings("unchecked")
089            Map<String, List<Object>> fieldCheckerInfo = (Map<String, List<Object>>) fieldCheckersInfo.get(fieldCheckerId);
090            List<Object> values = fieldCheckerInfo.get("rawTestValues");
091            
092            String type = fieldCheckerId.equals(__SQL_DATASOURCE_CHECKER_ID) ? "SQL" : "LDAP";
093            
094            DataSourceType dsType = DataSourceType.valueOf(type);
095            try
096            {
097                switch (dsType)
098                {
099                    case SQL:
100                        _checkSQLParameters(values);
101                        break;
102                        
103                    case LDAP:
104                        _checkLDAPParameters(values);
105                        break;
106                    
107                    default:
108                        throw new IllegalArgumentException("Unknow data source of type '" + type + "'. Unable to check data source parameters.");
109                }
110            }
111            catch (Throwable t)
112            {
113                getLogger().error("Data source check failed: \n" + t.getMessage(), t);
114                String msg = t.getMessage() != null ? t.getMessage() : "Unknown error";
115                
116                // We know we only have one parameter checker here
117                result.put(fieldCheckerId, msg);
118            }
119        }
120        
121        return result;
122    }
123    
124    private void _checkSQLParameters (List<Object> values) throws ItemCheckerTestFailureException
125    {
126        Map<String, Object> sqlParameters = new HashMap<> ();
127        
128        String driverExtensionId = (String) values.get(1);
129        StaticSQLDatabaseType sqlDatabaseType = (StaticSQLDatabaseType) _sqlDatabaseTypeExtensionPoint.getExtension(driverExtensionId);
130        String driver = sqlDatabaseType.getDriver();
131        
132        sqlParameters.put("driver", driverExtensionId);
133        if (StringUtils.isNotEmpty(driver))
134        {
135            sqlParameters.put("driverNotFoundMessage", _sqlDatabaseTypeManager.getClassNotFoundMessage(driver));
136        }
137        
138        sqlParameters.put("url", values.get(2));
139        sqlParameters.put("user", values.get(3));
140        
141        String password = (String) values.get(4);
142        if (password == null)
143        {
144            // Get password from the registered data source if it exists
145            String dataSourceId = (String) values.get(0);
146            DataSourceDefinition dataSourceDefinition = _sqlDataSourceManager.getDataSourceDefinition(dataSourceId);
147            if (dataSourceDefinition != null)
148            {
149                sqlParameters.put("password", dataSourceDefinition.getParameters().get("password"));
150            }
151        }
152        else
153        {
154            sqlParameters.put("password", password);
155        }
156        
157        _sqlDataSourceManager.checkParameters(sqlParameters);
158    }
159    
160    private void _checkLDAPParameters (List<Object> values) throws ItemCheckerTestFailureException
161    {
162        Map<String, Object> ldapParameters = new HashMap<> ();
163        
164        ldapParameters.put(LDAPDataSourceManager.PARAM_BASE_URL, values.get(1));
165        ldapParameters.put(LDAPDataSourceManager.PARAM_BASE_DN, values.get(2));
166        ldapParameters.put(LDAPDataSourceManager.PARAM_USE_SSL, values.get(3));
167        ldapParameters.put(LDAPDataSourceManager.PARAM_FOLLOW_REFERRALS, values.get(4));
168        
169        String authenticationMethod = (String) values.get(5);
170        ldapParameters.put(LDAPDataSourceManager.PARAM_AUTHENTICATION_METHOD, authenticationMethod);
171        
172        ldapParameters.put(LDAPDataSourceManager.PARAM_ADMIN_DN, values.get(6));
173        
174        // A null password + an authentication method => the password is recorded
175        String adminPassword = (String) values.get(7);
176        if (adminPassword == null && !authenticationMethod.equals("none"))
177        {
178            String dataSourceId = (String) values.get(0);
179            DataSourceDefinition dataSourceDefinition = _ldapDataSourceManager.getDataSourceDefinition(dataSourceId);
180            if (dataSourceDefinition != null)
181            {
182                ldapParameters.put(LDAPDataSourceManager.PARAM_ADMIN_PASSWORD, dataSourceDefinition.getParameters().get(LDAPDataSourceManager.PARAM_ADMIN_PASSWORD));
183            }
184        }
185        else
186        {
187            ldapParameters.put(LDAPDataSourceManager.PARAM_ADMIN_PASSWORD, adminPassword);
188        }
189        
190        _ldapDataSourceManager.checkParameters(ldapParameters);
191    }
192}