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