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.parameters.Parameters;
024import org.apache.avalon.framework.service.ServiceException;
025import org.apache.avalon.framework.service.ServiceManager;
026import org.apache.cocoon.acting.ServiceableAction;
027import org.apache.cocoon.environment.ObjectModelHelper;
028import org.apache.cocoon.environment.Redirector;
029import org.apache.cocoon.environment.Request;
030import org.apache.cocoon.environment.SourceResolver;
031import org.apache.commons.lang.StringUtils;
032
033import org.ametys.core.cocoon.ActionResultGenerator;
034import org.ametys.core.datasource.AbstractDataSourceManager.DataSourceDefinition;
035import org.ametys.core.datasource.DataSourceClientInteraction.DataSourceType;
036import org.ametys.core.datasource.LDAPDataSourceManager;
037import org.ametys.core.datasource.SQLDataSourceManager;
038import org.ametys.core.datasource.dbtype.SQLDatabaseTypeExtensionPoint;
039import org.ametys.core.datasource.dbtype.SQLDatabaseTypeManager;
040import org.ametys.core.util.I18nUtils;
041import org.ametys.core.util.JSONUtils;
042import org.ametys.plugins.core.impl.datasource.StaticSQLDatabaseType;
043import org.ametys.runtime.i18n.I18nizableText;
044import org.ametys.runtime.parameter.ParameterCheckerTestFailureException;
045import org.ametys.runtime.parameter.ParameterHelper;
046
047/**
048 * This action checks the validity of a data source's parameters
049 */
050public class CheckDataSourceAction extends ServiceableAction
051{
052    /** The id of the SQL data source checker */
053    private static final String __SQL_DATASOURCE_CHECKER_ID = "sql-connection-checker-datasource";
054    
055    /** The manager for SQL data source */
056    private SQLDataSourceManager _sqlDataSourceManager;
057    
058    /** The manager for SQL data source */
059    private LDAPDataSourceManager _ldapDataSourceManager;
060    
061    /** The manager for SQL database types */
062    private SQLDatabaseTypeManager _sqlDatabaseTypeManager;
063    
064    /** The extension point for SQL database types */
065    private SQLDatabaseTypeExtensionPoint _sqlDatabaseTypeExtensionPoint;
066    
067    /** Utility methods helping the management of internationalizable text */
068    private I18nUtils _i18nUtils;
069    
070    /** Helper component gathering utility methods for the management of JSON entities */
071    private JSONUtils _jsonUtils;
072    
073    @Override
074    public void service(ServiceManager serviceManager) throws ServiceException
075    {
076        _ldapDataSourceManager = (LDAPDataSourceManager) serviceManager.lookup(LDAPDataSourceManager.ROLE);
077        _sqlDataSourceManager = (SQLDataSourceManager) serviceManager.lookup(SQLDataSourceManager.ROLE);
078        _sqlDatabaseTypeManager = (SQLDatabaseTypeManager) serviceManager.lookup(SQLDatabaseTypeManager.ROLE);
079        _sqlDatabaseTypeExtensionPoint = (SQLDatabaseTypeExtensionPoint) serviceManager.lookup(SQLDatabaseTypeExtensionPoint.ROLE);
080        _i18nUtils = (I18nUtils) serviceManager.lookup(I18nUtils.ROLE);
081        _jsonUtils = (JSONUtils) serviceManager.lookup(JSONUtils.ROLE);
082    }
083    
084    @Override
085    public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception
086    {
087        Map<String, String> result = new HashMap<> ();
088        Request request = ObjectModelHelper.getRequest(objectModel);
089
090        String fieldCheckersInfoJSON = request.getParameter("fieldCheckersInfo");
091        Map<String, Object> fieldCheckersInfo = _jsonUtils.convertJsonToMap(fieldCheckersInfoJSON);
092        
093        Iterator<String> fieldCheckersIds = fieldCheckersInfo.keySet().iterator();
094        
095        while (fieldCheckersIds.hasNext())
096        {
097            String fieldCheckerId = fieldCheckersIds.next();
098            
099            @SuppressWarnings("unchecked")
100            Map<String, List<String>> fieldCheckerInfo = (Map<String, List<String>>) fieldCheckersInfo.get(fieldCheckerId);
101            List<String> values = fieldCheckerInfo.get("rawTestValues");
102            
103            String type = fieldCheckerId.equals(__SQL_DATASOURCE_CHECKER_ID) ? "SQL" : "LDAP";
104            
105            DataSourceType dsType = DataSourceType.valueOf(type);
106            try 
107            {
108                switch (dsType)
109                {
110                    case SQL:
111                        _checkSQLParameters(values);
112                        break;
113                        
114                    case LDAP:
115                        _checkLDAPParameters(values);
116                        break;
117                    
118                    default:
119                        throw new IllegalArgumentException("Unknow data source of type '" + type + "'. Unable to check data source parameters.");
120                }
121            }
122            catch (Throwable t)
123            {
124                getLogger().error("Data source test failed: \n" + t.getMessage(), t);
125                String msg = t.getMessage() != null ? t.getMessage() : "Unknown error";
126                
127                // We know we only have one parameter checker here
128                result.put(fieldCheckerId, msg);
129            }
130        }
131            
132        request.setAttribute(ActionResultGenerator.MAP_REQUEST_ATTR, result);
133        return result;
134    }
135    
136    private void _checkSQLParameters (List<String> values) throws ParameterCheckerTestFailureException
137    {
138        Map<String, String> sqlParameters = new HashMap<> ();
139        
140        String driverExtensionId = values.get(1);
141        StaticSQLDatabaseType sqlDatabaseType = (StaticSQLDatabaseType) _sqlDatabaseTypeExtensionPoint.getExtension(driverExtensionId);
142        String driver = sqlDatabaseType.getDriver();
143        
144        sqlParameters.put("driver", driverExtensionId);
145        if (StringUtils.isNotEmpty(driver))
146        {
147            I18nizableText driverNotFoundMessageKey = _sqlDatabaseTypeManager.getClassNotFoundMessage(driver);
148            sqlParameters.put("driverNotFoundMessage", _i18nUtils.translate(driverNotFoundMessageKey));
149        }
150        
151        sqlParameters.put("url", values.get(2));
152        sqlParameters.put("user", values.get(3));
153        
154        String password = values.get(4);
155        if (password == null)
156        {
157            // Get password from the registered data source if it exists
158            String dataSourceId = values.get(0);
159            DataSourceDefinition dataSourceDefinition = _sqlDataSourceManager.getDataSourceDefinition(dataSourceId);
160            if (dataSourceDefinition != null)
161            {
162                sqlParameters.put("password", dataSourceDefinition.getParameters().get("password"));
163            }
164        }
165        else
166        {
167            sqlParameters.put("password", password);
168        }
169        
170        _sqlDataSourceManager.checkParameters(sqlParameters);
171    }
172    
173    private void _checkLDAPParameters (List<String> values) throws ParameterCheckerTestFailureException
174    {
175        Map<String, String> ldapParameters = new HashMap<> ();
176        
177        ldapParameters.put(LDAPDataSourceManager.PARAM_BASE_URL, values.get(1));
178        ldapParameters.put(LDAPDataSourceManager.PARAM_BASE_DN, values.get(2));
179        ldapParameters.put(LDAPDataSourceManager.PARAM_USE_SSL, ParameterHelper.valueToString(values.get(3)));
180        
181        ldapParameters.put(LDAPDataSourceManager.PARAM_FOLLOW_REFERRALS, ParameterHelper.valueToString(values.get(4)));
182        
183        String authenticationMethod = values.get(5);
184        ldapParameters.put(LDAPDataSourceManager.PARAM_AUTHENTICATION_METHOD, authenticationMethod);
185        
186        ldapParameters.put(LDAPDataSourceManager.PARAM_ADMIN_DN, values.get(6));
187        
188        // A null password + an authentication method => the password is recorded
189        String adminPassword = values.get(7);
190        if (adminPassword == null && !authenticationMethod.equals("none"))
191        {
192            String dataSourceId = values.get(0);
193            DataSourceDefinition dataSourceDefinition = _ldapDataSourceManager.getDataSourceDefinition(dataSourceId);
194            if (dataSourceDefinition != null)
195            {
196                ldapParameters.put(LDAPDataSourceManager.PARAM_ADMIN_PASSWORD, dataSourceDefinition.getParameters().get(LDAPDataSourceManager.PARAM_ADMIN_PASSWORD));
197            }
198        }
199        else
200        {
201            ldapParameters.put(LDAPDataSourceManager.PARAM_ADMIN_PASSWORD, adminPassword);
202        }
203        
204        _ldapDataSourceManager.checkParameters(ldapParameters);
205    }
206}