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.util.HashSet; 019import java.util.Map; 020import java.util.Set; 021import java.util.regex.Pattern; 022 023import org.apache.avalon.framework.configuration.Configuration; 024import org.apache.avalon.framework.configuration.ConfigurationException; 025import org.apache.commons.collections.CollectionUtils; 026import org.apache.commons.lang3.StringUtils; 027 028import org.ametys.core.datasource.AbstractDataSourceManager.DataSourceDefinition; 029import org.ametys.runtime.i18n.I18nizableText; 030import org.ametys.runtime.parameter.DefaultValidator; 031import org.ametys.runtime.parameter.Errors; 032 033/** 034 * This validator validates that a type of SQL data sources is an authorized database type 035 * 036 */ 037public class SQLDatabaseTypeValidator extends DefaultValidator 038{ 039 private Set<String> _allowedDbTypes; 040 041 @Override 042 public void configure(Configuration configuration) throws ConfigurationException 043 { 044 _allowedDbTypes = new HashSet<>(); 045 046 Configuration validatorConfig = configuration.getChild("validation").getChild("custom-validator"); 047 048 _isMandatory = validatorConfig.getChild("mandatory", false) != null; 049 050 String regexp = validatorConfig.getChild("regexp").getValue(null); 051 if (regexp != null) 052 { 053 _regexp = Pattern.compile(regexp); 054 } 055 056 Configuration textConfig = validatorConfig.getChild("invalidText", false); 057 if (textConfig != null) 058 { 059 _invalidText = I18nizableText.parseI18nizableText(textConfig, "plugin." + _pluginName); 060 } 061 062 063 Configuration dbtypesConfig = validatorConfig.getChild("allowed-dbtypes", false); 064 if (dbtypesConfig != null) 065 { 066 String[] dbtypes = dbtypesConfig.getValue().split(","); 067 for (String dbtype : dbtypes) 068 { 069 CollectionUtils.addIgnoreNull(_allowedDbTypes, StringUtils.trimToNull(dbtype)); 070 } 071 } 072 } 073 074 /** 075 * Validates a single value. 076 * @param value the value to validate (can be <code>null</code>). 077 * @param errors the structure to populate if the validation failed. 078 */ 079 @Override 080 protected void validateSingleValue (Object value, Errors errors) 081 { 082 super.validateSingleValue(value, errors); 083 084 if (_allowedDbTypes.size() > 0 && value != null && value.toString().length() > 0) 085 { 086 String dataSourceId = value.toString(); 087 _validateDataSource(dataSourceId, errors); 088 } 089 } 090 091 @Override 092 protected void validateArrayValues (Object[] values, Errors errors) 093 { 094 if (_allowedDbTypes.size() > 0 && values != null && values.length > 0) 095 { 096 for (Object value : values) 097 { 098 String dataSourceId = value.toString(); 099 _validateDataSource(dataSourceId, errors); 100 } 101 } 102 } 103 104 private void _validateDataSource (String dataSourceId, Errors errors) 105 { 106 if (!_isValidDatasource(dataSourceId)) 107 { 108 if (getLogger().isDebugEnabled()) 109 { 110 getLogger().debug("The type of datasource of id '" + dataSourceId + "' is not an authorized database type."); 111 } 112 113 errors.addError(new I18nizableText("plugin.core", "PLUGINS_CORE_SQL_DATASOURCETYPE_VALIDATOR_FAILED")); 114 } 115 } 116 117 private boolean _isValidDatasource (String dataSourceId) 118 { 119 // FIXME Add a static method to get all data source definition in safe-mode ? 120 121 // Use static method because the SQLDataSourceManager may be not initialized yet 122 Map<String, DataSourceDefinition> dsDefinitions = SQLDataSourceManager.readDataSourceDefinition(SQLDataSourceManager.getStaticFileConfiguration()); 123 124 // Add the default datasource 125 boolean findDefault = false; 126 for (DataSourceDefinition dsDefinition : dsDefinitions.values()) 127 { 128 if (dsDefinition.isDefault()) 129 { 130 dsDefinitions.put(SQLDataSourceManager.SQL_DATASOURCE_PREFIX + AbstractDataSourceManager.DEFAULT_DATASOURCE_SUFFIX, dsDefinition.duplicate()); 131 findDefault = true; 132 break; 133 } 134 } 135 136 // Add the internal data source 137 DataSourceDefinition internalDsDefinition = SQLDataSourceManager.getInternalDataSourceDefinition(); 138 dsDefinitions.put(internalDsDefinition.getId(), internalDsDefinition); 139 140 if (!findDefault) 141 { 142 // The internal db is the default data source 143 dsDefinitions.put(SQLDataSourceManager.SQL_DATASOURCE_PREFIX + AbstractDataSourceManager.DEFAULT_DATASOURCE_SUFFIX, internalDsDefinition.duplicate()); 144 } 145 146 if (dsDefinitions.containsKey(dataSourceId)) 147 { 148 String dbtype = (String) dsDefinitions.get(dataSourceId).getParameters().get(SQLDataSourceManager.PARAM_DATABASE_TYPE); 149 return _allowedDbTypes.contains(dbtype); 150 } 151 152 return false; 153 } 154 155 @Override 156 public Map<String, Object> getConfiguration() 157 { 158 Map<String, Object> configuration = super.getConfiguration(); 159 configuration.put("allowedDbTypes", _allowedDbTypes); 160 return configuration; 161 } 162 163 @Override 164 public int hashCode() 165 { 166 final int prime = 31; 167 int result = super.hashCode(); 168 result = prime * result + ((_allowedDbTypes == null) ? 0 : _allowedDbTypes.hashCode()); 169 return result; 170 } 171 172 @Override 173 public boolean equals(Object obj) 174 { 175 if (this == obj) 176 { 177 return true; 178 } 179 if (!super.equals(obj)) 180 { 181 return false; 182 } 183 if (getClass() != obj.getClass()) 184 { 185 return false; 186 } 187 SQLDatabaseTypeValidator other = (SQLDatabaseTypeValidator) obj; 188 if (_allowedDbTypes == null) 189 { 190 if (other._allowedDbTypes != null) 191 { 192 return false; 193 } 194 } 195 else if (!_allowedDbTypes.equals(other._allowedDbTypes)) 196 { 197 return false; 198 } 199 return true; 200 } 201 202 203}