Index: development/mode/upgrade.xml
===================================================================
--- development/mode/upgrade.xml	(revision 38980)
+++ development/mode/upgrade.xml	(working copy)
@@ -162,7 +162,6 @@
         	<replacefilter token="org.ametys.runtime.plugins.core.ui.item.StaticAdminClientSideElement" value="org.ametys.plugins.core.ui.item.StaticAdminClientSideElement"/>
         	
             <replacefilter token="org.ametys.runtime.authentication.AuthenticationManager" value="org.ametys.core.authentication.AuthenticationManager"/>
-            <replacefilter token="org.ametys.runtime.datasource.DataSourceExtensionPoint" value="org.ametys.core.datasource.DataSourceExtensionPoint"/>
             <replacefilter token="org.ametys.runtime.observation.ObserverExtensionPoint" value="org.ametys.core.observation.ObserverExtensionPoint"/>
             <replacefilter token="org.ametys.runtime.plugins.core.right.RightContextConvertorExtentionPoint" value="org.ametys.core.right.RightContextConvertorExtentionPoint"/>
             <replacefilter token="org.ametys.runtime.plugins.core.right.RightsExtensionPoint" value="org.ametys.core.right.RightsExtensionPoint"/>
Index: ivy.xml
===================================================================
--- ivy.xml	(revision 38980)
+++ ivy.xml	(working copy)
@@ -51,8 +51,8 @@
   <dependencies>
     <!-- Common -->
     <dependency org="org.apache" name="cocoon" rev="2.1.12-ametys" conf="common_dependencies->serializers"/>
-
-    <dependency org="commons-dbcp" name="commons-dbcp" rev="1.4" conf="common_dependencies->default"/>
+    
+    <dependency org="org.apache.commons" name="commons-dbcp2" rev="2.1.1" conf="common_dependencies->default"/>
     <dependency org="commons-logging" name="commons-logging" rev="1.2" conf="common_dependencies->default"/>
     <dependency org="commons-io" name="commons-io" rev="2.4" conf="common_dependencies->default"/>
     <dependency org="commons-codec" name="commons-codec" rev="1.9" conf="common_dependencies->default"/>
Index: main/kernel/src/org/ametys/runtime/config/ConfigManager.java
===================================================================
--- main/kernel/src/org/ametys/runtime/config/ConfigManager.java	(revision 38980)
+++ main/kernel/src/org/ametys/runtime/config/ConfigManager.java	(working copy)
@@ -23,6 +23,7 @@
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
@@ -131,8 +132,8 @@
     }
 
     /**
-     * Returns false if the model is initialized and all parameters are valued
-     * @return false if the model is initialized and all parameters are valued
+     * Returns true if the model is initialized and all parameters are valued
+     * @return true if the model is initialized and all parameters are valued
      */
     public boolean isComplete()
     {
@@ -478,7 +479,7 @@
     {
         String id = parameter.getId();
         Object value = ParameterHelper.castValue(untypedValues.get(id), parameter.getType());
-
+        
         if (value == null && !"".equals(untypedValues.get(id)))
         {
             if (_logger.isWarnEnabled())
@@ -513,6 +514,13 @@
                 
                 _isComplete = false;
             }
+            
+            if (parameter.getType().equals(ParameterType.DATASOURCE))
+            {
+                // lookup sqldatasource manager
+                // get the data source descriptor
+                // SQLConnectionChecker.check(dataSourceParameters)
+            }
         }
         
         return value;
@@ -709,6 +717,27 @@
     }
     
     /**
+     * Retrieve configuration parameter ids of the given type
+     * @param type The type of configuration parameter we wish to retrieve
+     * @return the list of configuration parameter ids of that type
+     */
+    public List<String> getIdsByType(ParameterType type)
+    {
+        List<String> ids = new ArrayList<>();
+        for (String id : _params.keySet())
+        {
+            ConfigParameter configParameter = _params.get(id);
+            
+            if (configParameter.getType().equals(type))
+            {
+                ids.add(id);
+            }
+        }
+        
+        return ids;
+    }
+        
+    /**
      * Gets the parameter checker with its id
      * @param id the id of the parameter checker to get
      * @return the associated parameter checker descriptor
Index: main/kernel/src/org/ametys/runtime/parameter/ParameterCheckerDescriptor.java
===================================================================
--- main/kernel/src/org/ametys/runtime/parameter/ParameterCheckerDescriptor.java	(revision 38980)
+++ main/kernel/src/org/ametys/runtime/parameter/ParameterCheckerDescriptor.java	(working copy)
@@ -312,8 +312,8 @@
     }
     
     /**
-     * Retrieves the configuration of the parameter the parameter checker is attached to
-     * @return _uiRefParamId the configuration of the parameter
+     * Retrieves the id of the parameter the parameter checker is attached to
+     * @return _uiRefParamId the id of the parameter
      */
     public String getUiRefParamId()
     {
@@ -321,8 +321,8 @@
     }
     
     /**
-     * Sets the configuration of the parameter the parameter checker is attached to
-     * @param uiRefParamId the configuration of the parameter
+     * Sets the id of the parameter the parameter checker is attached to
+     * @param uiRefParamId the id of the parameter
      */
     public void setUiRefParamId(String uiRefParamId)
     {
Index: main/kernel/src/org/ametys/runtime/parameter/ParameterHelper.java
===================================================================
--- main/kernel/src/org/ametys/runtime/parameter/ParameterHelper.java	(revision 38980)
+++ main/kernel/src/org/ametys/runtime/parameter/ParameterHelper.java	(working copy)
@@ -56,7 +56,9 @@
         /** date values */
         DATE,
         /** binary values */
-        BINARY
+        BINARY,
+        /** datasource values */
+        DATASOURCE
     }
 
     // Logger for traces
@@ -128,6 +130,10 @@
             {
                 return value;
             }
+            else if (type == ParameterType.DATASOURCE)
+            {
+                return value;
+            }
             else if (type == ParameterType.LONG)
             {
                 return  new Long(value);
Index: main/kernel/src/org/ametys/runtime/plugin/plugin-4.0.xsd
===================================================================
--- main/kernel/src/org/ametys/runtime/plugin/plugin-4.0.xsd	(revision 38980)
+++ main/kernel/src/org/ametys/runtime/plugin/plugin-4.0.xsd	(working copy)
@@ -1034,6 +1034,7 @@
                                     <li>long</li>
                                     <li>double</li>
                                     <li>date (date and time)</li>
+                                    <li>datasource</li>
                                 </ul>
                             ]]>
                         </xsd:documentation>
@@ -1046,6 +1047,7 @@
                             <xsd:enumeration value="long"/>
                             <xsd:enumeration value="double"/>
                             <xsd:enumeration value="date"/>
+                            <xsd:enumeration value="datasource"/>
                         </xsd:restriction>
                     </xsd:simpleType>
                 </xsd:attribute>
Index: main/kernel/src/org/ametys/runtime/servlet/RuntimeServlet.java
===================================================================
--- main/kernel/src/org/ametys/runtime/servlet/RuntimeServlet.java	(revision 38980)
+++ main/kernel/src/org/ametys/runtime/servlet/RuntimeServlet.java	(working copy)
@@ -72,6 +72,8 @@
 import org.slf4j.MDC;
 import org.xml.sax.XMLReader;
 
+import org.ametys.core.datasource.ldap.LDAPDataSourceManager;
+import org.ametys.core.datasource.sql.SQLDataSourceManager;
 import org.ametys.runtime.config.Config;
 import org.ametys.runtime.config.ConfigManager;
 import org.ametys.runtime.data.AmetysHomeLock;
@@ -111,6 +113,7 @@
     /** The default ametys home path (relative to the servlet context)  */
     public static final String AMETYS_HOME_DEFAULT = "/WEB-INF/data";
 
+
     /** The run modes */
     public enum RunMode
     {
@@ -268,12 +271,18 @@
         _ametysHomeLock = new AmetysHomeLock(_ametysHome);
         _ametysHomeLock.acquire();
     }
-
+    
     private void _initAmetys() throws Exception
     {
         // WEB-INF/param/runtime.xml loading
         _loadRuntimeConfig();
-
+        
+        // SQL Datasources configuration file
+        SQLDataSourceManager.setFilename(RuntimeConfig.getInstance().getAmetysHome() + "/datasources-sql.xml");
+        
+        // LDAP Datasources configuration file
+        LDAPDataSourceManager.setFilename(RuntimeConfig.getInstance().getAmetysHome() + "/datasources-ldap.xml");
+        
         _createCocoon();
         
         // Upload initialization
@@ -417,13 +426,13 @@
             _logger.debug("Servlet destroyed - disposing Cocoon");
             _disposeCocoon();
         }
-        
+
         if (_ametysHomeLock != null)
         {
             _ametysHomeLock.release();
             _ametysHomeLock = null;
         }
-        
+
         _avalonContext = null;
         _logger = null;
         _loggerManager = null;
Index: main/plugin-admin/i18n/messages_en.xml
===================================================================
--- main/plugin-admin/i18n/messages_en.xml	(revision 38980)
+++ main/plugin-admin/i18n/messages_en.xml	(working copy)
@@ -245,4 +245,102 @@
     <message key="PLUGINS_ADMIN_SYSTEM_ERROR_SAVE">An error occurred on the server. The modifications on the welcome announcement have not been saved.</message>
     <message key="PLUGINS_ADMIN_SYSTEM_CONFIRM_DIALOG_TITLE">Replace the existing message</message>
     <message key="PLUGINS_ADMIN_SYSTEM_CONFIRM_DIALOG_TEXT">A message already exists in the selected language, do you want to replace it ?</message>
+    
+    <!-- +
+         | DATA SOURCES 
+         + -->
+         
+    <!-- Tool -->
+    <message key="PLUGINS_CORE_UITOOL_DATASOURCE_LABEL">Data sources</message>
+    <message key="PLUGINS_CORE_UITOOL_DATASOURCE_DESCRIPTION">Data sources management.</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_COL_ID">Identifier</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_COL_NAME">Name</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_COL_USED">Used</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_COL_PRIVATE">Private</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_COL_TYPE">Type</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_COL_BOOLEAN_YES">Yes</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_GROUP_SQL">SQL data source</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_GROUP_LDAP">LDAP repository</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_SQL_PRIVATE">Private SQL source</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_SQL_PUBLIC">Public SQL source</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_LDAP_PRIVATE">Private LDAP source</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_LDAP_PUBLIC">Public LDAP source</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DELETE_DATASOURCE_BOX_TITLE">Deletion</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DELETE_SINGLE_DATASOURCE_BOX_MESSAGE">Do you really want to delete this data source?</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DELETE_SEVERAL_DATASOURCE_BOX_MESSAGE">Do you really want to delete these data sources?</message>
+    
+    <!-- SQL -->
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_SQL_ADD">New SQL data source</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_SQL_DESCRIPTION">Add a SQL data source.</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_SQL_MODIFY">Modify a SQL data source</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_SQL_DESCRIPTION">Modify a SQL data source.</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_SQL_REMOVE">Delete one or several sources</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_SQL_DESCRIPTION">Delete a SQL data source.</message>
+    
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_ADD_TITLE">New SQL data source</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_EDIT_TITLE">Modification of a SQL data source</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_OK">Ok</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_CANCEL">Cancel</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_NAME">Name</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_NAME_DESCRIPTION">The data source name as it will appear when a data source has to be selected.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_DESCRIPTION">Description</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_DESCRIPTION_DESCRIPTION">Optional description for the data source</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_DRIVER">JDBC Driver</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_DRIVER_DESCRIPTION">The JDBC driver that will be used for this data source.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_URL">Url</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_URL_DESCRIPTION">The url where to find the database that must follow the template corresponding to the selected driver.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_USER">Identifier</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_USER_DESCRIPTION">Identifier of the data base user. Optional.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_PASSWORD">Password</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_PASSWORD_DESCRIPTION">Password allowing access to the database. Optional.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_PRIVATE">Private source</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_PRIVATE_DESCRIPTION">Check this box if you this data source to be private. It will only be visible in the administrator interface if this is the case.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_GET_DRIVERS_ERROR">A server error occurred while trying to retrieve the available drivers.</message>
+    
+    <!-- LDAP -->
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_LDAP_ADD">New LDAP repository</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_LDAP_DESCRIPTION">Add a LDAP repository.</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_LDAP_MODIFY">Modify a repository</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_LDAP_DESCRIPTION">Modify a LDAP repository.</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_LDAP_REMOVE">Delete one or several repositories</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_LDAP_DESCRIPTION">Delete one or several LDAP repositories.</message>
+        
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_ADD_TITLE">New LDAP repository</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_EDIT_TITLE">Modification of a LDAP repository</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_OK">Ok</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_CANCEL">Cancel</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_NAME">Name</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_NAME_DESCRIPTION">The data source name as it will appear when a data source has to be selected.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_DESCRIPTION">Description</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_DESCRIPTION_DESCRIPTION">Optional description for the data source</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_URL">Url</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_URL_DESCRIPTION">The url of the LDAP server.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_URL_REGEXP_TEXT">The url of the LDAP server is invalid. It has to be in the form 'ldap://server:389' or 'ldaps://server:389'.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_USESSL">Secured connection</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_USESSL_DESCRIPTION">Check this box if you prefer to use the 'ldaps' protocol over 'ldap' to establish a connection with the repository.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_BASEDN">Base DN</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_BASEDN_DESCRIPTION">Base DN for all access to the repository.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_FOLLOWREFERRALS">Follow referrals</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_FOLLOWREFERRALS_DESCRIPTION">Check this box to follow the references in the search results (mostly for dynamic LDAP groups).</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_ALIASDEREFERENCING">Alias dereferencing</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_ALIASDEREFERENCING_DESCRIPTION">Defines the alias dereferencing mode.&lt;br/&gt;- &lt;b&gt;Always: &lt;/b&gt;always dereference aliases&lt;br/&gt;- &lt;b&gt;Never: &lt;/b&gt;never dereferences aliases&lt;br/&gt;- &lt;b&gt;During resolution: &lt;/b&gt;dereferences aliases only during name resolution&lt;br/&gt;- &lt;b&gt;After resolution: &lt;/b&gt;dereferences aliases only after name resolution</message>
+    <message key="PLUGINS_ADMIN_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_ENUM_ALWAYS">Always</message>
+    <message key="PLUGINS_ADMIN_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_ENUM_NEVER">Never</message>
+    <message key="PLUGINS_ADMIN_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_ENUM_FINDING">During resolution</message>
+    <message key="PLUGINS_ADMIN_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_ENUM_SEARCHING">After resolution</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_AUTHENTICATIONMETHOD">Authentication method</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_AUTHENTICATIONMETHOD_DESCRIPTION">The type of authentication used between the application and the LDAP repository</message>
+    <message key="PLUGINS_ADMIN_DATASOURCE_CORE_LDAP_CONFIG_AUTH_METHOD_ENUM_NONE">Anonymous</message>
+    <message key="PLUGINS_ADMIN_DATASOURCE_CORE_LDAP_CONFIG_AUTH_METHOD_ENUM_SIMPLE">Simple</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_ADMINDN">Administrator DN</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_ADMINDN_DESCRIPTION">Absolute DN for a super user of the LDAP directory.</message> 
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_ADMINPASSWORD">Administrator password</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_ADMINPASSWORD_DESCRIPTION">The password of this user.</message>   
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_PRIVATE">Private source</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_PRIVATE_DESCRIPTION">Check this box if you this data source to be private. It will only be visible in the administrator workspace if this is the case.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_GET_DRIVERS_ERROR">A server error occurred while trying to retrieve the available drivers.</message>
+    
+    <message key="PLUGINS_ADMIN_DATASOURCES_GET_DATASOURCE_ERROR">A server error occurred, the data source was not found.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_ADD_DATASOURCE_ERROR">A server error occurred, the data source was not added.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_EDIT_DATASOURCE_ERROR">A server error occurred, the data source was not edited.</message>
 </catalogue>
\ No newline at end of file
Index: main/plugin-admin/i18n/messages_fr.xml
===================================================================
--- main/plugin-admin/i18n/messages_fr.xml	(revision 38980)
+++ main/plugin-admin/i18n/messages_fr.xml	(working copy)
@@ -245,4 +245,105 @@
     <message key="PLUGINS_ADMIN_SYSTEM_ERROR_SAVE">Une erreur est survenue sur le serveur. Les modifications n'ont pas été enregistrées.</message>
     <message key="PLUGINS_ADMIN_SYSTEM_CONFIRM_DIALOG_TITLE">Remplacer le message existant</message>
     <message key="PLUGINS_ADMIN_SYSTEM_CONFIRM_DIALOG_TEXT">Une annonnce existe déjà dans cette langue, voulez-vous le remplacer ?</message>
+    
+    
+    <!-- +
+         | DATA SOURCES 
+         + -->
+         
+    <!-- Tool -->
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_LABEL">Sources de données</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_DESCRIPTION">Gestion des sources de données.</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_COL_ID">Identifiant</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_COL_NAME">Nom</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_COL_USED">Utilisée</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_COL_PRIVATE">Privée</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_COL_TYPE">Type</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_COL_BOOLEAN_YES">Oui</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_GROUP_SQL">Source de données SQL</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_GROUP_LDAP">Annuaire LDAP</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_SQL_PRIVATE">Source SQL privée</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_SQL_PUBLIC">Source SQL publique</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_LDAP_PRIVATE">Source LDAP privée</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_LDAP_PUBLIC">Source LDAP publique</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DELETE_DATASOURCE_BOX_TITLE">Suppression</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DELETE_SINGLE_DATASOURCE_BOX_MESSAGE">Etes-vous sûr de vouloir supprimer cette source de données ?</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DELETE_SEVERAL_DATASOURCE_BOX_MESSAGE">Etes-vous sûr de vouloir supprimer ces sources de données ?</message>
+    
+    <!-- SQL -->
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_SQL_ADD">Nouvelle source SQL</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_SQL_ADD_DESCRIPTION">Permet d'ajouter une nouvelle source de données de type SQL.</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_SQL_MODIFY">Modifier une source</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_SQL_MODIFY_DESCRIPTION">Permet de modifier une source de données SQL.</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_SQL_REMOVE">Supprimer une ou des sources</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_SQL_REMOVE_DESCRIPTION">Permet de supprimer une ou plusieurs sources de données SQL.</message>
+    
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_ADD_TITLE">Nouvelle source de données SQL</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_EDIT_TITLE">Modification d'une source de données</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_OK">Ok</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_CANCEL">Annuler</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_NAME">Nom</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_NAME_DESCRIPTION">Le nom de la source de données à afficher lorsqu'une source de données sera demandée.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_DESCRIPTION">Description</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_DESCRIPTION_DESCRIPTION">Description optionnelle pour la source de données.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_DRIVER">Pilote JDBC</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_DRIVER_DESCRIPTION">Le pilote JDBC qui sera utilisé pour cette source de données.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_URL">Url</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_URL_DESCRIPTION">L'url où se trouve la base de données, qui doit suivre le modèle correspondant au pilote selectionné.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_USER">Identifiant</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_USER_DESCRIPTION">Identifiant de l'utilisateur de la base données. Optionnel.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_PASSWORD">Mot de passe</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_PASSWORD_DESCRIPTION">Mot de passe permettant d'accéder à la base de données. Optionnel.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_PRIVATE">Source privée</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_PRIVATE_DESCRIPTION">Cochez cette case si vous souhaitez que cette source de données soit privée. Elle ne sera visible que dans l'interface d'administration si c'est le cas.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_GET_DRIVERS_ERROR">Une erreur serveur s'est produit lors de la récupération des sources de données.</message>
+    
+    <!-- LDAP -->   
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_LDAP_ADD">Nouvel annuaire LDAP</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_LDAP_ADD_DESCRIPTION">Permet d'ajouter un nouvel annuaire LDAP.</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_LDAP_MODIFY">Modifier un annuaire</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_LDAP_MODIFY_DESCRIPTION">Permet de modifier un annuaire LDAP.</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_LDAP_REMOVE">Supprimer un ou des annuaires</message>
+    <message key="PLUGINS_ADMIN_UITOOL_DATASOURCE_LDAP_REMOVE_DESCRIPTION">Permet de supprimer un ou plusieurs annuaires LDAP.</message>
+
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_ADD_TITLE">Nouvel annuaire LDAP</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_EDIT_TITLE">Modification d'un annuaire LDAP</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_OK">Ok</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_CANCEL">Annuler</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_NAME">Nom</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_NAME_DESCRIPTION">Le nom de la source de données à afficher lorsqu'une source de données sera demandée.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_DESCRIPTION">Description</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_DESCRIPTION_DESCRIPTION">Description optionnelle pour la source de données.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_URL">Url</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_URL_DESCRIPTION">L'URL du serveur LDAP.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_URL_REGEXP_TEXT">L'URL du serveur LDAP est invalide. Elle doit être de la forme ldap://server:389 ou ldaps://server:389.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_USESSL">Connexon sécurisée</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_USESSL_DESCRIPTION">Cochez cette case si vous souhaiter utiliser le protocole 'ldaps' plutôt que 'ldap' pour établir la connexion à l'annuaire.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_BASEDN">DN de base</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_BASEDN_DESCRIPTION">DN de base pour tous les accès à l'annuaire.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_BASEDN">DN de base</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_BASEDN_DESCRIPTION">DN de base pour tous les accès à l'annuaire.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_FOLLOWREFERRALS">Suivre les références</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_FOLLOWREFERRALS_DESCRIPTION">Cochez cette option pour suivre les références dans les résultats de recherche (principalement pour les groupes LDAP dynamiques).</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_ALIASDEREFERENCING">Déréférencement des alias</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_ALIASDEREFERENCING_DESCRIPTION">Définit le mode de déréférencement des entrées de type alias.&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;- &lt;b&gt;Toujours : &lt;/b&gt;toujours déréférencer les alias&lt;br/&gt;- &lt;b&gt;Jamais : &lt;/b&gt;ne jamais déréférencer les alias&lt;br/&gt;- &lt;b&gt;Pendant résolution : &lt;/b&gt;déréférencer les alias uniquement pendant la résolution de nom&lt;br/&gt;- &lt;b&gt;Après résolution : &lt;/b&gt;déréférencer les alias uniquement après la résolution de nom&lt;br/&gt;&lt;/ul&gt;</message>
+    <message key="PLUGINS_ADMIN_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_ENUM_ALWAYS">Toujours</message>
+    <message key="PLUGINS_ADMIN_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_ENUM_NEVER">Jamais</message>
+    <message key="PLUGINS_ADMIN_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_ENUM_FINDING">Pendant résolution</message>
+    <message key="PLUGINS_ADMIN_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_ENUM_SEARCHING">Après résolution</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_AUTHENTICATIONMETHOD">Méthode d'authentification</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_AUTHENTICATIONMETHOD_DESCRIPTION">Type d'authentification utilisée entre l'application et l'annuaire LDAP.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCE_CORE_LDAP_CONFIG_AUTH_METHOD_ENUM_NONE">Anonyme</message>
+    <message key="PLUGINS_ADMIN_DATASOURCE_CORE_LDAP_CONFIG_AUTH_METHOD_ENUM_SIMPLE">Simple</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_ADMINDN">DN de l'administrateur</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_ADMINDN_DESCRIPTION">DN complet d'un utilisateur tout pouvoir dans l'annuaire LDAP.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_ADMINPASSWORD">Mot de passe administrateur</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_ADMINPASSWORD_DESCRIPTION">Le mot de passe de cet utilisateur.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_PRIVATE">Source privée</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_PRIVATE_DESCRIPTION">Cochez cette case si vous souhaitez que cette source de données soit privée. Elle ne sera visible que dans l'espace administrateur si c'est le cas.</message>
+    
+    <message key="PLUGINS_ADMIN_DATASOURCES_DIALOG_GET_DRIVERS_ERROR">Une erreur s'est produit pendant la recherche les drivers disponibles.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_GET_DATASOURCE_ERROR">Une erreur est survenue sur le serveur, la source de données n'a pas été trouvée.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_ADD_DATASOURCE_ERROR">Une erreur est survenue sur le serveur, la source de données n'a pas été ajoutée.</message>
+    <message key="PLUGINS_ADMIN_DATASOURCES_EDIT_DATASOURCE_ERROR">Une erreur est survenue sur le serveur, la source de données n'a pas été modifiée.</message>
 </catalogue>
\ No newline at end of file
Index: main/plugin-admin/plugin.xml
===================================================================
--- main/plugin-admin/plugin.xml	(revision 38980)
+++ main/plugin-admin/plugin.xml	(working copy)
@@ -18,7 +18,7 @@
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://www.ametys.org/schema/plugin http://www.ametys.org/schema/plugin-4.0.xsd"
         runtimeVersion="4.0" version="2.0">
-        
+    
     <extension-points>
         <extension-point id="org.ametys.runtime.plugins.admin.jvmstatus.monitoring.MonitoringExtensionPoint"
                          class="org.ametys.runtime.plugins.admin.jvmstatus.monitoring.MonitoringExtensionPoint"
@@ -1181,4 +1181,219 @@
             </extension>
         </extensions>
     </feature>
+    
+    <!-- +
+         |  DATASOURCES
+         + -->
+    <feature name="runtime.admin.datasource" safe="true">
+        
+        <components>
+            <component role="org.ametys.runtime.plugins.admin.datasource.DataSourceDAO"
+                       id="org.ametys.runtime.plugins.admin.datasource.DataSourceDAO"
+                       class="org.ametys.runtime.plugins.admin.datasource.DataSourceDAO"/>
+        </components>
+        
+        <extensions>
+            <extension id="org.ametys.plugins.admin.DataSource"
+                   point="org.ametys.core.ui.RibbonControlsManager"
+                   class="org.ametys.core.ui.StaticClientSideElement">
+                <class name="Ametys.ribbon.element.ui.button.OpenToolButtonController">
+                    <opentool-role>uitool-datasource</opentool-role>
+                    <label i18n="true">PLUGINS_ADMIN_UITOOL_DATASOURCE_LABEL</label>
+                    <description i18n="true">PLUGINS_ADMIN_UITOOL_DATASOURCE_DESCRIPTION</description>
+                    
+                    <help>org.ametys.plugins.admin.datasource</help>
+                    
+                    <icon-small file="true">img/datasource/datasource_16.png</icon-small>
+                    <icon-medium file="true">img/datasource/datasource_32.png</icon-medium>
+                    <icon-large file="true">img/datasource/datasource_48.png</icon-large>
+                </class>
+            </extension>
+                
+            <extension id="org.ametys.plugins.admin.DataSourceFactory"
+                       point="org.ametys.core.ui.UIToolsFactoriesManager"
+                       class="org.ametys.core.ui.StaticClientSideElement">
+                <class name="Ametys.tool.factory.UniqueToolFactory">
+                    <role>uitool-datasource</role>
+                    <toolClass>Ametys.plugins.admin.datasource.DataSourceTool</toolClass>
+                    
+                    <title i18n="true">PLUGINS_ADMIN_UITOOL_DATASOURCE_LABEL</title>
+                    <description i18n="true">PLUGINS_ADMIN_UITOOL_DATASOURCE_DESCRIPTION</description>
+                    
+                    <help>org.ametys.plugins.admin.datasource</help>
+        
+                    <icon-small file="true">img/datasource/datasource_16.png</icon-small>
+                    <icon-medium file="true">img/datasource/datasource_32.png</icon-medium>
+                    <icon-large file="true">img/datasource/datasource_48.png</icon-large>
+                </class>
+                <scripts>
+                    <file>js/Ametys/plugins/admin/datasource/DataSourceTool.js</file>
+                    <file>js/Ametys/plugins/admin/datasource/DataSourceTool/DataSource.js</file>
+                    <file>js/Ametys/plugins/admin/datasource/DataSourceDAO.js</file>
+                </scripts>
+            </extension>
+
+            <extension id="org.ametys.plugins.admin.datasources.Tab"
+                       point="org.ametys.core.ui.RibbonTabsManager"
+                       class="org.ametys.core.ui.StaticClientSideElement">
+                <class name="Ametys.ribbon.element.tab.TabController">
+                    <tool-role>^(uitool-datasource)$</tool-role>
+                </class>
+            </extension>
+
+            <extension id="org.ametys.plugins.admin.actions.datasources.sql.Add"
+                       point="org.ametys.core.ui.RibbonControlsManager"
+                       class="org.ametys.core.ui.StaticClientSideElement">
+               <class name="Ametys.ribbon.element.ui.ButtonController">
+                   <action>Ametys.plugins.admin.datasource.DataSourceActions.add</action>
+                   <type>SQL</type>
+                   
+                   <label i18n="true">PLUGINS_ADMIN_UITOOL_DATASOURCE_SQL_ADD</label>
+                   <description i18n="true">PLUGINS_ADMIN_UITOOL_DATASOURCE_SQL_ADD_DESCRIPTION</description>
+                   
+                   <icon-small file="true">img/datasource/datasource_16.png</icon-small>
+                   <icon-medium file="true">img/datasource/datasource_32.png</icon-medium>
+                   <icon-large file="true">img/datasource/datasource_48.png</icon-large>
+               </class>             
+               <scripts>
+                   <file>js/Ametys/plugins/admin/datasource/DataSourceActions.js</file>
+                   <file>js/Ametys/plugins/admin/datasource/DataSourceDAO.js</file>
+                   <file>js/Ametys/plugins/admin/datasource/EditSQLDataSourceHelper.js</file>
+               </scripts>                       
+            </extension>
+            
+            <extension id="org.ametys.plugins.admin.actions.datasources.sql.Modify"
+                       point="org.ametys.core.ui.RibbonControlsManager"
+                       class="org.ametys.core.ui.StaticClientSideElement">
+               <class name="Ametys.ribbon.element.ui.ButtonController">
+                   <action>Ametys.plugins.admin.datasource.DataSourceActions.modify</action>
+                   <type>SQL</type>
+
+                   <selection-enable-multiselection>false</selection-enable-multiselection>
+                   <selection-target-type>^datasource$</selection-target-type>
+                   <selection-target-parameter>
+                       <name>^type$</name>
+                       <value>SQL</value>
+                   </selection-target-parameter> 
+                   
+                   <label i18n="true">PLUGINS_ADMIN_UITOOL_DATASOURCE_SQL_MODIFY</label>
+                   <description i18n="true">PLUGINS_ADMIN_UITOOL_DATASOURCE_SQL_MODIFY_DESCRIPTION</description>
+                   
+                   <icon-small file="true">img/datasource/datasource_16.png</icon-small>
+                   <icon-medium file="true">img/datasource/datasource_32.png</icon-medium>
+                   <icon-large file="true">img/datasource/datasource_48.png</icon-large>
+               </class>             
+               <scripts>
+                   <file>js/Ametys/plugins/admin/datasource/DataSourceActions.js</file>
+                   <file>js/Ametys/plugins/admin/datasource/DataSourceDAO.js</file>
+                   <file>js/Ametys/plugins/admin/datasource/EditSQLDataSourceHelper.js</file>
+               </scripts>                       
+            </extension>
+            
+            <extension id="org.ametys.plugins.admin.actions.datasources.sql.Remove"
+                       point="org.ametys.core.ui.RibbonControlsManager"
+                       class="org.ametys.core.ui.StaticClientSideElement">
+               <class name="Ametys.plugins.admin.datasource.DeleteDataSourceController">
+                   <action>Ametys.plugins.admin.datasource.DataSourceActions.remove</action>
+                   <type>SQL</type>
+                   
+                   <selection-target-type>^datasource$</selection-target-type>
+                   <selection-target-parameter>
+                       <name>^inUse$</name>
+                       <value>false</value>
+                   </selection-target-parameter> 
+                   
+                   <label i18n="true">PLUGINS_ADMIN_UITOOL_DATASOURCE_SQL_REMOVE</label>
+                   <description i18n="true">PLUGINS_ADMIN_UITOOL_DATASOURCE_SQL_REMOVE_DESCRIPTION</description>
+                   
+                   <icon-small file="true">img/datasource/datasource_16.png</icon-small>
+                   <icon-medium file="true">img/datasource/datasource_32.png</icon-medium>
+                   <icon-large file="true">img/datasource/datasource_48.png</icon-large>
+               </class>             
+               <scripts>
+                   <file>js/Ametys/plugins/admin/datasource/DeleteDataSourceController.js</file>
+                   <file>js/Ametys/plugins/admin/datasource/DataSourceActions.js</file>
+                   <file>js/Ametys/plugins/admin/datasource/DataSourceDAO.js</file>
+               </scripts>                       
+            </extension>
+            
+            <extension id="org.ametys.plugins.admin.actions.datasources.ldap.Add"
+                       point="org.ametys.core.ui.RibbonControlsManager"
+                       class="org.ametys.core.ui.StaticClientSideElement">
+               <class name="Ametys.ribbon.element.ui.ButtonController">
+                   <action>Ametys.plugins.admin.datasource.DataSourceActions.add</action>
+                   <type>LDAP</type>
+                   
+                   <label i18n="true">PLUGINS_ADMIN_UITOOL_DATASOURCE_LDAP_ADD</label>
+                   <description i18n="true">PLUGINS_ADMIN_UITOOL_DATASOURCE_LDAP_ADD_DESCRIPTION</description>
+                   
+                   <icon-small file="true">img/datasource/datasource_16.png</icon-small>
+                   <icon-medium file="true">img/datasource/datasource_32.png</icon-medium>
+                   <icon-large file="true">img/datasource/datasource_48.png</icon-large>
+               </class>             
+               <scripts>
+                   <file>js/Ametys/plugins/admin/datasource/DataSourceActions.js</file>
+                   <file>js/Ametys/plugins/admin/datasource/DataSourceDAO.js</file>
+                   <file>js/Ametys/plugins/admin/datasource/EditLDAPDataSourceHelper.js</file>
+               </scripts>                       
+            </extension>
+            
+            <extension id="org.ametys.plugins.admin.actions.datasources.ldap.Modify"
+                       point="org.ametys.core.ui.RibbonControlsManager"
+                       class="org.ametys.core.ui.StaticClientSideElement">
+               <class name="Ametys.ribbon.element.ui.ButtonController">
+                   <action>Ametys.plugins.admin.datasource.DataSourceActions.modify</action>
+                   
+                   <type>LDAP</type>
+
+                   <selection-enable-multiselection>false</selection-enable-multiselection>
+                   <selection-target-type>^datasource$</selection-target-type>
+                   <selection-target-parameter>
+                       <name>^type$</name>
+                       <value>LDAP</value>
+                   </selection-target-parameter> 
+                   
+                   <label i18n="true">PLUGINS_ADMIN_UITOOL_DATASOURCE_LDAP_MODIFY</label>
+                   <description i18n="true">PLUGINS_ADMIN_UITOOL_DATASOURCE_LDAP_MODIFY_DESCRIPTION</description>
+                   
+                   <icon-small file="true">img/datasource/datasource_16.png</icon-small>
+                   <icon-medium file="true">img/datasource/datasource_32.png</icon-medium>
+                   <icon-large file="true">img/datasource/datasource_48.png</icon-large>
+               </class>             
+               <scripts>
+                   <file>js/Ametys/plugins/admin/datasource/DataSourceActions.js</file>
+                   <file>js/Ametys/plugins/admin/datasource/DataSourceDAO.js</file>
+                   <file>js/Ametys/plugins/admin/datasource/EditLDAPDataSourceHelper.js</file>
+               </scripts>                       
+            </extension>
+            
+            <extension id="org.ametys.plugins.admin.actions.datasources.ldap.Remove"
+                       point="org.ametys.core.ui.RibbonControlsManager"
+                       class="org.ametys.core.ui.StaticClientSideElement">
+               <class name="Ametys.plugins.admin.datasource.DeleteDataSourceController">
+                   <action>Ametys.plugins.admin.datasource.DataSourceActions.remove</action>
+                   
+                   <type>LDAP</type>
+                   
+                   <selection-target-type>^datasource$</selection-target-type>
+                   <selection-target-parameter>
+                       <name>^inUse$</name>
+                       <value>false</value>
+                   </selection-target-parameter> 
+                   
+                   <label i18n="true">PLUGINS_ADMIN_UITOOL_DATASOURCE_LDAP_REMOVE</label>
+                   <description i18n="true">PLUGINS_ADMIN_UITOOL_DATASOURCE_LDAP_REMOVE_DESCRIPTION</description>
+                   
+                   <icon-small file="true">img/datasource/datasource_16.png</icon-small>
+                   <icon-medium file="true">img/datasource/datasource_32.png</icon-medium>
+                   <icon-large file="true">img/datasource/datasource_48.png</icon-large>
+               </class>             
+               <scripts>
+                   <file>js/Ametys/plugins/admin/datasource/DeleteDataSourceController.js</file>
+                   <file>js/Ametys/plugins/admin/datasource/DataSourceActions.js</file>
+                   <file>js/Ametys/plugins/admin/datasource/DataSourceDAO.js</file>
+               </scripts>                       
+            </extension> 
+        </extensions>
+    </feature>
 </plugin>
\ No newline at end of file
Index: main/plugin-admin/resources/js/Ametys/plugins/admin/datasource/DataSourceActions.js
===================================================================
--- main/plugin-admin/resources/js/Ametys/plugins/admin/datasource/DataSourceActions.js	(revision 0)
+++ main/plugin-admin/resources/js/Ametys/plugins/admin/datasource/DataSourceActions.js	(revision 0)
@@ -0,0 +1,118 @@
+/*	
+ *  Copyright 2015 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * This singleton gathers the actions invoked when clicking the add/modify/remove data source buttons
+ * @private
+ */
+Ext.define('Ametys.plugins.admin.datasource.DataSourceActions', {
+	
+	singleton: true,
+	
+	/**
+	 * Add a data source
+	 * @param {Ametys.ribbon.element.ui.ButtonController} controller the controller calling this function
+	 */
+	add: function(controller)
+	{
+		switch (controller.getInitialConfig('type'))
+		{
+			case 'SQL':
+				Ametys.plugins.admin.datasource.EditSQLDataSourceHelper.add();
+				break;
+			case 'LDAP': 
+				Ametys.plugins.admin.datasource.EditLDAPDataSourceHelper.add();
+				break;
+			default:
+				throw 'Unrecognized data source type' + controller.getInitialConfig('type');
+		}
+	},
+	
+	/**
+	 * Modify the selected data source
+	 * @param {Ametys.ribbon.element.ui.ButtonController} controller the controller calling this function
+	 */
+	modify: function(controller)
+	{
+		var dataSourceTarget = controller.getMatchingTargets()[0];
+		if (dataSourceTarget != null)
+		{
+			switch (controller.getInitialConfig('type'))
+			{
+				case 'SQL':
+					Ametys.plugins.admin.datasource.EditSQLDataSourceHelper.edit(dataSourceTarget.getParameters().id);
+					break;
+				case 'LDAP': 
+					Ametys.plugins.admin.datasource.EditLDAPDataSourceHelper.edit(dataSourceTarget.getParameters().id);
+					break;
+				default:
+					throw 'Unrecognized data source type' + controller.getInitialConfig('type');
+			}
+		}
+	},
+	
+	/**
+	 * Remove the selected data source(s)
+	 * @param {Ametys.ribbon.element.ui.ButtonController} controller the controller calling this function
+	 */
+	remove: function(controller)
+	{
+		var dataSourceTargets = controller.getMatchingTargets();
+		if (dataSourceTargets.length > 0)
+		{
+			var dataSourceType = controller.getInitialConfig('type');
+			var message = dataSourceTargets.length == 1 ? "<i18n:text i18n:key='PLUGINS_ADMIN_UITOOL_DELETE_SINGLE_DATASOURCE_BOX_MESSAGE'/>"
+													    : "<i18n:text i18n:key='PLUGINS_ADMIN_UITOOL_DELETE_SEVERAL_DATASOURCE_BOX_MESSAGE'/>";
+			
+			Ametys.MessageBox.confirm (
+				"<i18n:text i18n:key='PLUGINS_ADMIN_UITOOL_DELETE_DATASOURCE_BOX_TITLE'/>",
+				message,
+				Ext.bind(this._removeConfirm, this, [dataSourceType, dataSourceTargets], 1),
+				this
+			);
+		}
+	},
+	
+	/**
+	 * Callback function invoked when the 'Yes' or 'No' button of the dialog box was clicked
+	 * Effectively deletes the selected data sources of does nothing.
+	 * @param {String} answer
+	 * @param {String} type the type of the data source
+	 * @param {Ametys.message.MessageTarget[]} dataSourceTargets the data source message targets.
+	 */
+	_removeConfirm: function(answer, type, dataSourceTargets)
+	{
+		if (answer == 'yes')
+		{
+			var ids = [];
+			Ext.Array.each(dataSourceTargets, function(dataSourceTarget){
+				ids.push(dataSourceTarget.getParameters().id);
+			});
+			
+			switch (type)
+			{
+				case 'SQL':
+					Ametys.plugins.admin.datasource.DataSourceDAO.removeSQLDataSource([ids], null, {});
+					break;
+				case 'LDAP': 
+					Ametys.plugins.admin.datasource.DataSourceDAO.removeLDAPDataSource([ids], null, {});
+					break;
+				default:
+					throw 'Unrecognized data source type' + type;
+			}
+		}
+	}
+});
\ No newline at end of file
Index: main/plugin-admin/resources/js/Ametys/plugins/admin/datasource/DataSourceDAO.js
===================================================================
--- main/plugin-admin/resources/js/Ametys/plugins/admin/datasource/DataSourceDAO.js	(revision 0)
+++ main/plugin-admin/resources/js/Ametys/plugins/admin/datasource/DataSourceDAO.js	(revision 0)
@@ -0,0 +1,472 @@
+/*
+ *  Copyright 2015 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * This tool displays the list of data sources 
+ * @private
+ */
+Ext.define('Ametys.plugins.admin.datasource.DataSourceDAO', {
+	
+	singleton: true,
+
+	constructor: function(config)
+	{
+		/**
+    	 * @callable
+    	 * @member Ametys.plugins.admin.datasource.DataSourceDAO
+    	 * @method getSQLDataSource
+    	 * Retrieve a data source from its id
+    	 * This calls the method 'getSQLDataSource' of the server DAO 'org.ametys.runtime.plugins.admin.datasource.DataSourceDAO'.
+    	 * @param {Object[]} parameters The parameters to transmit to the server method
+    	 * @param {String} parameters[0] The id of the data source to retrieve
+    	 * @param {Function} callback The function to call when the java process is over. Can be null. Use options.scope for the scope. 
+     	 * @param {Object} callback.returnedValue The data source information. Null on error (please note that when an error occurred, the callback may not be called depending on the value of errorMessage).
+		 * @param {Object} callback.args Other arguments specified in option.arguments
+		 * @param {Object[]} callback.parameters the parameters the server was called with
+		 * @param {Object} [options] Advanced options for the call.
+		 * @param {Boolean/String/Object} [options.errorMessage] Display an error message. See Ametys.data.ServerCall#callMethod errorMessage.
+		 * @param {Boolean/String/Object} [options.waitMessage] Display a waiting message. See Ametys.data.ServerCall#callMethod waitMessage.
+		 * @param {Number} [options.scope] This parameter is the scope used to call the callback. Moreover is the given class is a mixin of Ametys.data.ServerCaller, its methods #beforeServerCall and #afterServerCall will be used so see their documentation to look for additional options (such a refreshing on Ametys.ribbon.element.ui.ButtonController#beforeServerCall).
+		 * @param {Number} [options.priority] The message priority. See Ametys.data.ServerCall#callMethod for more information on the priority. PRIORITY_SYNCHRONOUS cannot be used here.
+		 * @param {String} [options.cancelCode] Cancel similar unachieved read operations. See Ametys.data.ServerCall#callMethod cancelCode.
+		 * @param {Object} [options.arguments] Additional arguments set in the callback.arguments parameter.                  
+		 * @param {Boolean} [options.ignoreCallbackOnError] If the server throws an exception, should the callback be called with a null parameter. See Ametys.data.ServerCall#callMethod ignoreOnError.
+    	 */
+		this.addCallables({
+		    role: "org.ametys.runtime.plugins.admin.datasource.DataSourceDAO",
+			methodName: "getSQLDataSource",
+     		errorMessage: {
+				category: this.self.getName(),
+				msg: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_GET_DATASOURCE_ERROR'/>"
+			}
+		});
+		
+		/**
+    	 * @callable
+    	 * @member Ametys.plugins.admin.datasource.DataSourceDAO
+    	 * @method addSQLDataSource
+    	 * Add a sql data source
+    	 * This calls the method 'addSQLDataSource' of the server DAO 'org.ametys.runtime.plugins.admin.datasource.DataSourceDAO'.
+    	 * @param {Object[]} parameters The parameters to transmit to the server method
+    	 * @param {Object} parameters[0] The parameters of the data source to create
+		 * @param {String} parameters[0].name the name of the data source
+		 * @param {String} parameters[0].description the optional description of the data source
+		 * @param {String} parameters[0].driver the driver used for this data source
+		 * @param {String} parameters[0].url the url of the database
+		 * @param {String} parameters[0].user the optional database identifier
+		 * @param {String} parameters[0].password the optional data base password
+		 * @param {Boolean} parameters[0].private is the data source public or private ?
+    	 * @param {Function} callback The function to call when the java process is over. Can be null. Use options.scope for the scope. 
+    	 * @param {String} callback.returnedValue the id of the created data source
+    	 * @param {Object} callback.args Other arguments specified in option.arguments
+		 * @param {Object[]} callback.parameters the parameters the server was called with 
+		 * @param {Object} [options] Advanced options for the call.
+		 * @param {Boolean/String/Object} [options.errorMessage] Display an error message. See Ametys.data.ServerCall#callMethod errorMessage.
+		 * @param {Boolean/String/Object} [options.waitMessage] Display a waiting message. See Ametys.data.ServerCall#callMethod waitMessage.
+		 * @param {Number} [options.scope] This parameter is the scope used to call the callback. Moreover is the given class is a mixin of Ametys.data.ServerCaller, its methods #beforeServerCall and #afterServerCall will be used so see their documentation to look for additional options (such a refreshing on Ametys.ribbon.element.ui.ButtonController#beforeServerCall).
+		 * @param {Number} [options.priority] The message priority. See Ametys.data.ServerCall#callMethod for more information on the priority. PRIORITY_SYNCHRONOUS cannot be used here.
+		 * @param {String} [options.cancelCode] Cancel similar unachieved read operations. See Ametys.data.ServerCall#callMethod cancelCode.
+		 * @param {Object} [options.arguments] Additional arguments set in the callback.arguments parameter.                  
+		 * @param {Boolean} [options.ignoreCallbackOnError] If the server throws an exception, should the callback be called with a null parameter. See Ametys.data.ServerCall#callMethod ignoreOnError.
+    	 */
+		this.addCallables({
+		    role: "org.ametys.runtime.plugins.admin.datasource.DataSourceDAO",
+			methodName: "addSQLDataSource",
+			callback: {
+         		handler: this._addSQLDataSourceCb,
+     		},
+     		errorMessage: {
+				category: this.self.getName(),
+				msg: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_ADD_DATASOURCE_ERROR'/>"
+			}
+		});
+		
+		/**
+    	 * @callable
+    	 * @member Ametys.plugins.admin.datasource.DataSourceDAO
+    	 * @method editSQLDataSource
+    	 * Edit a sql data source
+    	 * This calls the method 'editSQLDataSource' of the server DAO 'org.ametys.runtime.plugins.admin.datasource.DataSourceDAO'.
+    	 * @param {Object[]} parameters The parameters to transmit to the server method
+    	 * @param {Object} parameters[0] The parameters of the data source to create
+    	 * @param {String} parameters[0].id The id of the data source to edit
+		 * @param {String} parameters[0].name the name of the data source
+		 * @param {String} parameters[0].description the optional description of the data source
+		 * @param {String} parameters[0].driver the driver used for this data source
+		 * @param {String} parameters[0].url the url of the database
+		 * @param {String} parameters[0].user the optional database identifier
+		 * @param {String} parameters[0].password the optional data base password
+		 * @param {Boolean} parameters[0].private is the data source public or private ?
+    	 * @param {Function} callback The function to call when the java process is over. Can be null. Use options.scope for the scope. 
+     	 * @param {Object} callback.returnedValue The data source information. Null on error (please note that when an error occurred, the callback may not be called depending on the value of errorMessage).
+		 * @param {Object} callback.args Other arguments specified in option.arguments with
+		 * @param {Object[]} callback.parameters the parameters the server was called with
+		 * @param {Object} [options] Advanced options for the call.
+		 * @param {Boolean/String/Object} [options.errorMessage] Display an error message. See Ametys.data.ServerCall#callMethod errorMessage.
+		 * @param {Boolean/String/Object} [options.waitMessage] Display a waiting message. See Ametys.data.ServerCall#callMethod waitMessage.
+		 * @param {Number} [options.scope] This parameter is the scope used to call the callback. Moreover is the given class is a mixin of Ametys.data.ServerCaller, its methods #beforeServerCall and #afterServerCall will be used so see their documentation to look for additional options (such a refreshing on Ametys.ribbon.element.ui.ButtonController#beforeServerCall).
+		 * @param {Number} [options.priority] The message priority. See Ametys.data.ServerCall#callMethod for more information on the priority. PRIORITY_SYNCHRONOUS cannot be used here.
+		 * @param {String} [options.cancelCode] Cancel similar unachieved read operations. See Ametys.data.ServerCall#callMethod cancelCode.
+		 * @param {Object} [options.arguments] Additional arguments set in the callback.arguments parameter.                  
+		 * @param {Boolean} [options.ignoreCallbackOnError] If the server throws an exception, should the callback be called with a null parameter. See Ametys.data.ServerCall#callMethod ignoreOnError.
+    	 */
+		this.addCallables({
+			role: "org.ametys.runtime.plugins.admin.datasource.DataSourceDAO",
+			methodName: "editSQLDataSource",
+			callback: {
+         		handler: this._editSQLDataSourceCb,
+     		},
+     		errorMessage: {
+				category: this.self.getName(),
+				msg: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_EDIT_DATASOURCE_ERROR'/>"
+			}
+		});
+		
+		/**
+    	 * @callable
+    	 * @member Ametys.plugins.admin.datasource.DataSourceDAO
+    	 * @method removeSQLDataSource
+    	 * Remove the selected sql data source
+    	 * This calls the method 'removeSQLDataSource' of the server DAO 'org.ametys.runtime.plugins.admin.datasource.DataSourceDAO'.
+    	 * @param {Object[]} parameters The parameters to transmit to the server method
+    	 * @param {String} parameters[0] The ids of the data sources to remove
+    	 * @param {Function} callback The function to call when the java process is over. Can be null. Use options.scope for the scope. 
+     	 * @param {Object} callback.returnedValue The value returned by the server. Null on error (please note that when an error occurred, the callback may not be called depending on the value of errorMessage).
+		 * @param {Object} callback.args Other arguments specified in option.arguments with
+		 * @param {Object[]} callback.parameters the parameters the server was called with
+		 * @param {Object} [options] Advanced options for the call.
+		 * @param {Boolean/String/Object} [options.errorMessage] Display an error message. See Ametys.data.ServerCall#callMethod errorMessage.
+		 * @param {Boolean/String/Object} [options.waitMessage] Display a waiting message. See Ametys.data.ServerCall#callMethod waitMessage.
+		 * @param {Number} [options.scope] This parameter is the scope used to call the callback. Moreover is the given class is a mixin of Ametys.data.ServerCaller, its methods #beforeServerCall and #afterServerCall will be used so see their documentation to look for additional options (such a refreshing on Ametys.ribbon.element.ui.ButtonController#beforeServerCall).
+		 * @param {Number} [options.priority] The message priority. See Ametys.data.ServerCall#callMethod for more information on the priority. PRIORITY_SYNCHRONOUS cannot be used here.
+		 * @param {String} [options.cancelCode] Cancel similar unachieved read operations. See Ametys.data.ServerCall#callMethod cancelCode.
+		 * @param {Object} [options.arguments] Additional arguments set in the callback.arguments parameter.                  
+		 * @param {Boolean} [options.ignoreCallbackOnError] If the server throws an exception, should the callback be called with a null parameter. See Ametys.data.ServerCall#callMethod ignoreOnError.
+    	 */
+		this.addCallables({
+			role: "org.ametys.runtime.plugins.admin.datasource.DataSourceDAO",
+			methodName: "removeSQLDataSource",
+			callback: {
+         		handler: this._removeSQLDataSourceCb
+     		},
+     		errorMessage: {
+				category: this.self.getName(),
+				msg: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_EDIT_DATASOURCE_ERROR'/>"
+			}
+		});
+		
+		/**
+    	 * @callable
+    	 * @member Ametys.plugins.admin.datasource.DataSourceDAO
+    	 * @method getLDAPDataSource
+    	 * Retrieve a data source from its id
+    	 * This calls the method 'getLDAPDataSource' of the server DAO 'org.ametys.runtime.plugins.admin.datasource.DataSourceDAO'.
+    	 * @param {Object[]} parameters The parameters to transmit to the server method
+    	 * @param {String} parameters[0] The id of the data source to retrieve
+    	 * @param {Function} callback The function to call when the java process is over. Can be null. Use options.scope for the scope. 
+     	 * @param {Object} callback.returnedValue The data source information. Null on error (please note that when an error occurred, the callback may not be called depending on the value of errorMessage).
+		 * @param {Object} callback.args Other arguments specified in option.arguments
+		 * @param {Object[]} callback.parameters the parameters the server was called with
+		 * @param {Object} [options] Advanced options for the call.
+		 * @param {Boolean/String/Object} [options.errorMessage] Display an error message. See Ametys.data.ServerCall#callMethod errorMessage.
+		 * @param {Boolean/String/Object} [options.waitMessage] Display a waiting message. See Ametys.data.ServerCall#callMethod waitMessage.
+		 * @param {Number} [options.scope] This parameter is the scope used to call the callback. Moreover is the given class is a mixin of Ametys.data.ServerCaller, its methods #beforeServerCall and #afterServerCall will be used so see their documentation to look for additional options (such a refreshing on Ametys.ribbon.element.ui.ButtonController#beforeServerCall).
+		 * @param {Number} [options.priority] The message priority. See Ametys.data.ServerCall#callMethod for more information on the priority. PRIORITY_SYNCHRONOUS cannot be used here.
+		 * @param {String} [options.cancelCode] Cancel similar unachieved read operations. See Ametys.data.ServerCall#callMethod cancelCode.
+		 * @param {Object} [options.arguments] Additional arguments set in the callback.arguments parameter.                  
+		 * @param {Boolean} [options.ignoreCallbackOnError] If the server throws an exception, should the callback be called with a null parameter. See Ametys.data.ServerCall#callMethod ignoreOnError.
+    	 */
+		this.addCallables({
+		    role: "org.ametys.runtime.plugins.admin.datasource.DataSourceDAO",
+			methodName: "getLDAPDataSource",
+     		errorMessage: {
+				category: this.self.getName(),
+				msg: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_GET_DATASOURCE_ERROR'/>"
+			}
+		});
+		
+		/**
+    	 * @callable
+    	 * @member Ametys.plugins.admin.datasource.DataSourceDAO
+    	 * @method addLDAPDataSource
+    	 * Add a ldap data source
+    	 * This calls the method 'addLDAPDataSource' of the server DAO 'org.ametys.runtime.plugins.admin.datasource.DataSourceDAO'.
+    	 * @param {Object[]} parameters The parameters to transmit to the server method
+    	 * @param {Object} parameters[0] The parameters of the data source to create
+		 * @param {String} parameters[0].name the name of the data source
+		 * @param {String} parameters[0].baseURL the base url of the data source
+		 * @param {Boolean} parameters[0].useSSL True to use the protocol 'ldaps' instead of 'ldap'
+		 * @param {String} parameters[0].baseDN the base domain name
+		 * @param {String} parameters[0].aliasDerefencing the mode for alias dereferencing
+		 * @param {Boolean} parameters[0].followReferrals true to follow the referrals
+		 * @param {String} parameters[0].authenticationMethod the authentication method used to establish a connection with the data source
+		 * @param {String} parameters[0].adminDN the administrator domain name
+		 * @param {String} parameters[0].adminPassword the administrator's password
+		 * @param {Boolean} parameters[0].private is the data source public or private ?
+    	 * @param {Function} callback The function to call when the java process is over. Can be null. Use options.scope for the scope. 
+    	 * @param {String} callback.returnedValue the id of the created data source
+    	 * @param {Object} callback.args Other arguments specified in option.arguments
+		 * @param {Object[]} callback.parameters the parameters the server was called with 
+		 * @param {Object} [options] Advanced options for the call.
+		 * @param {Boolean/String/Object} [options.errorMessage] Display an error message. See Ametys.data.ServerCall#callMethod errorMessage.
+		 * @param {Boolean/String/Object} [options.waitMessage] Display a waiting message. See Ametys.data.ServerCall#callMethod waitMessage.
+		 * @param {Number} [options.scope] This parameter is the scope used to call the callback. Moreover is the given class is a mixin of Ametys.data.ServerCaller, its methods #beforeServerCall and #afterServerCall will be used so see their documentation to look for additional options (such a refreshing on Ametys.ribbon.element.ui.ButtonController#beforeServerCall).
+		 * @param {Number} [options.priority] The message priority. See Ametys.data.ServerCall#callMethod for more information on the priority. PRIORITY_SYNCHRONOUS cannot be used here.
+		 * @param {String} [options.cancelCode] Cancel similar unachieved read operations. See Ametys.data.ServerCall#callMethod cancelCode.
+		 * @param {Object} [options.arguments] Additional arguments set in the callback.arguments parameter.                  
+		 * @param {Boolean} [options.ignoreCallbackOnError] If the server throws an exception, should the callback be called with a null parameter. See Ametys.data.ServerCall#callMethod ignoreOnError.
+    	 */
+		this.addCallables({
+		    role: "org.ametys.runtime.plugins.admin.datasource.DataSourceDAO",
+			methodName: "addLDAPDataSource",
+			callback: {
+         		handler: this._addLDAPDataSourceCb,
+     		},
+     		errorMessage: {
+				category: this.self.getName(),
+				msg: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_ADD_DATASOURCE_ERROR'/>"
+			}
+		});
+		
+		/**
+    	 * @callable
+    	 * @member Ametys.plugins.admin.datasource.DataSourceDAO
+    	 * @method editLDAPDataSource
+    	 * Edit a ldap data source
+    	 * This calls the method 'editLDAPDataSource' of the server DAO 'org.ametys.runtime.plugins.admin.datasource.DataSourceDAO'.
+    	 * @param {Object[]} parameters The parameters to transmit to the server method
+    	 * @param {Object} parameters[0] The parameters of the data source to create
+		 * @param {String} parameters[0].name the name of the data source
+		 * @param {String} parameters[0].baseURL the base url of the data source
+		 * @param {Boolean} parameters[0].useSSL True to use the protocol 'ldaps' instead of 'ldap'
+		 * @param {String} parameters[0].baseDN the base domain name
+		 * @param {String} parameters[0].aliasDerefencing the mode for alias dereferencing
+		 * @param {Boolean} parameters[0].followReferrals true to follow the referrals
+		 * @param {String} parameters[0].authenticationMethod the authentication method used to establish a connection with the data source
+		 * @param {String} parameters[0].adminDN the administrator domain name
+		 * @param {String} parameters[0].adminPassword the administrator's password
+		 * @param {Boolean} parameters[0].private is the data source public or private ?
+    	 * @param {Function} callback The function to call when the java process is over. Can be null. Use options.scope for the scope. 
+     	 * @param {Object} callback.returnedValue The data source information. Null on error (please note that when an error occurred, the callback may not be called depending on the value of errorMessage).
+		 * @param {Object} callback.args Other arguments specified in option.arguments with
+		 * @param {Object[]} callback.parameters the parameters the server was called with
+		 * @param {Object} [options] Advanced options for the call.
+		 * @param {Boolean/String/Object} [options.errorMessage] Display an error message. See Ametys.data.ServerCall#callMethod errorMessage.
+		 * @param {Boolean/String/Object} [options.waitMessage] Display a waiting message. See Ametys.data.ServerCall#callMethod waitMessage.
+		 * @param {Number} [options.scope] This parameter is the scope used to call the callback. Moreover is the given class is a mixin of Ametys.data.ServerCaller, its methods #beforeServerCall and #afterServerCall will be used so see their documentation to look for additional options (such a refreshing on Ametys.ribbon.element.ui.ButtonController#beforeServerCall).
+		 * @param {Number} [options.priority] The message priority. See Ametys.data.ServerCall#callMethod for more information on the priority. PRIORITY_SYNCHRONOUS cannot be used here.
+		 * @param {String} [options.cancelCode] Cancel similar unachieved read operations. See Ametys.data.ServerCall#callMethod cancelCode.
+		 * @param {Object} [options.arguments] Additional arguments set in the callback.arguments parameter.                  
+		 * @param {Boolean} [options.ignoreCallbackOnError] If the server throws an exception, should the callback be called with a null parameter. See Ametys.data.ServerCall#callMethod ignoreOnError.
+    	 */
+		this.addCallables({
+			role: "org.ametys.runtime.plugins.admin.datasource.DataSourceDAO",
+			methodName: "editLDAPDataSource",
+			callback: {
+         		handler: this._editLDAPDataSourceCb,
+     		},
+     		errorMessage: {
+				category: this.self.getName(),
+				msg: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_EDIT_DATASOURCE_ERROR'/>"
+			}
+		});
+		
+		/**
+    	 * @callable
+    	 * @member Ametys.plugins.admin.datasource.DataSourceDAO
+    	 * @method removeLDAPDataSource
+    	 * Remove the selected ldap data source
+    	 * This calls the method 'removeLDAPDataSource' of the server DAO 'org.ametys.runtime.plugins.admin.datasource.DataSourceDAO'.
+    	 * @param {Object[]} parameters The parameters to transmit to the server method
+    	 * @param {String} parameters[0] The ids of the data sources to remove
+    	 * @param {Function} callback The function to call when the java process is over. Can be null. Use options.scope for the scope. 
+     	 * @param {Object} callback.returnedValue The value returned by the server. Null on error (please note that when an error occurred, the callback may not be called depending on the value of errorMessage).
+		 * @param {Object} callback.args Other arguments specified in option.arguments with
+		 * @param {Object[]} callback.parameters the parameters the server was called with
+		 * @param {Object} [options] Advanced options for the call.
+		 * @param {Boolean/String/Object} [options.errorMessage] Display an error message. See Ametys.data.ServerCall#callMethod errorMessage.
+		 * @param {Boolean/String/Object} [options.waitMessage] Display a waiting message. See Ametys.data.ServerCall#callMethod waitMessage.
+		 * @param {Number} [options.scope] This parameter is the scope used to call the callback. Moreover is the given class is a mixin of Ametys.data.ServerCaller, its methods #beforeServerCall and #afterServerCall will be used so see their documentation to look for additional options (such a refreshing on Ametys.ribbon.element.ui.ButtonController#beforeServerCall).
+		 * @param {Number} [options.priority] The message priority. See Ametys.data.ServerCall#callMethod for more information on the priority. PRIORITY_SYNCHRONOUS cannot be used here.
+		 * @param {String} [options.cancelCode] Cancel similar unachieved read operations. See Ametys.data.ServerCall#callMethod cancelCode.
+		 * @param {Object} [options.arguments] Additional arguments set in the callback.arguments parameter.                  
+		 * @param {Boolean} [options.ignoreCallbackOnError] If the server throws an exception, should the callback be called with a null parameter. See Ametys.data.ServerCall#callMethod ignoreOnError.
+    	 */
+		this.addCallables({
+			role: "org.ametys.runtime.plugins.admin.datasource.DataSourceDAO",
+			methodName: "removeLDAPDataSource",
+			callback: {
+         		handler: this._removeLDAPDataSourceCb
+     		},
+     		errorMessage: {
+				category: this.self.getName(),
+				msg: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_EDIT_DATASOURCE_ERROR'/>"
+			}
+		});
+	},
+	
+ 	/**
+	 * @private
+	 * Callback function invoked after the SQL data source is created
+	 * @param {String} id the id of the created data source
+	 * @param {Object} args The callback arguments
+	 * @param {Object[]} params The call parameters 
+	 */
+	_addSQLDataSourceCb: function(id, args, params)
+	{
+		Ext.create('Ametys.message.Message', {
+			type: Ametys.message.Message.CREATED,
+			targets: {
+				type: Ametys.message.MessageTarget.DATASOURCE,
+				parameters: {
+					id: id,
+					type: 'SQL'
+				}
+			}
+		});
+	},
+	
+ 	/**
+	 * @private
+	 * Callback function invoked after the SQL data source is edited
+	 * @param {Object} response The server's response
+	 * @param {Object} args The callback arguments
+	 * @param {Object[]} params The call parameters 
+	 */
+	_editSQLDataSourceCb: function(id, args, params)
+	{
+		Ext.create('Ametys.message.Message', {
+			type: Ametys.message.Message.MODIFIED,
+			targets: {
+				type: Ametys.message.MessageTarget.DATASOURCE,
+				parameters: {
+					id: params[0].id,
+					type: 'SQL'
+				}
+			}
+		});
+	},
+	
+ 	/**
+	 * @private
+	 * Callback function invoked after the SQL data source is (are) deleted
+	 * @param {Object} response the server's response
+	 * @param {Object} args The callback arguments
+	 * @param {Object[]} params The call parameters
+	 */
+	_removeSQLDataSourceCb: function(response, args, params)
+	{
+		var ids = params[0];
+		
+		Ext.Array.each(ids, function(id){
+			Ext.create('Ametys.message.Message', {
+				type: Ametys.message.Message.DELETED,
+				targets: {
+					type: Ametys.message.MessageTarget.DATASOURCE,
+					parameters: {
+						id: id,
+						type: 'SQL'
+					}
+				}
+			});
+		})
+	},
+	
+ 	/**
+	 * @private
+	 * Callback function invoked after the LDAP data source is created
+	 * @param {String} id the id of the created data source
+	 * @param {Object} args The callback arguments
+	 * @param {Object[]} params The call parameters 
+	 */
+	_addLDAPDataSourceCb: function(id, args, params)
+	{
+		Ext.create('Ametys.message.Message', {
+			type: Ametys.message.Message.CREATED,
+			targets: {
+				type: Ametys.message.MessageTarget.DATASOURCE,
+				parameters: {
+					id: id,
+					type: 'LDAP'
+				}
+			}
+		});
+	},
+	
+ 	/**
+	 * @private
+	 * Callback function invoked after the LDAP data source is edited
+	 * @param {Object} response The server's response
+	 * @param {Object} args The callback arguments
+	 * @param {Object[]} params The call parameters 
+	 */
+	_editLDAPDataSourceCb: function(id, args, params)
+	{
+		Ext.create('Ametys.message.Message', {
+			type: Ametys.message.Message.MODIFIED,
+			targets: {
+				type: Ametys.message.MessageTarget.DATASOURCE,
+				parameters: {
+					id: params[0].id,
+					type: 'LDAP'
+				}
+			}
+		});
+	},
+	
+ 	/**
+	 * @private
+	 * Callback function invoked after the LDAP data source is (are) deleted
+	 * @param {Object} response the server's response
+	 * @param {Object} args The callback arguments
+	 * @param {Object[]} params The call parameters
+	 */
+	_removeLDAPDataSourceCb: function(response, args, params)
+	{
+		var ids = params[0];
+		
+		Ext.Array.each(ids, function(id){
+			Ext.create('Ametys.message.Message', {
+				type: Ametys.message.Message.DELETED,
+				targets: {
+					type: Ametys.message.MessageTarget.DATASOURCE,
+					parameters: {
+						id: id,
+						type: 'LDAP'
+					}
+				}
+			});
+		})
+	}
+});
+
+Ext.define('Ametys.message.DataSourceMessageTarget', {
+	
+	override: 'Ametys.message.MessageTarget',
+	statics: 
+	{
+		/**
+		 * @member Ametys.message.MessageTarget
+		 * @readonly
+		 * @property {String} DATASOURCE The target of the message is a data source. The expected parameters are: 
+	 	 * @property {String} DATASOURCE.id The id of the data source
+	 	 * @property {String} DATASOURCE.type The type of the data source
+	 	 * @property {Boolean} [DATASOURCE.inUse] is the datasource in use ?
+		 */
+		DATASOURCE: "datasource"
+	}
+});
+
Index: main/plugin-admin/resources/js/Ametys/plugins/admin/datasource/DataSourceTool/DataSource.js
===================================================================
--- main/plugin-admin/resources/js/Ametys/plugins/admin/datasource/DataSourceTool/DataSource.js	(revision 0)
+++ main/plugin-admin/resources/js/Ametys/plugins/admin/datasource/DataSourceTool/DataSource.js	(revision 0)
@@ -0,0 +1,31 @@
+/*
+ *  Copyright 2015 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @private
+ * The model used in the {@link Ametys.plugins.admin.datasource.DataSourceTool} grid
+ */
+Ext.define('Ametys.plugins.admin.datasource.DataSourceTool.DataSource', {
+    extend: 'Ext.data.Model',
+    
+    fields: [
+       {name: 'id', mapping: 'id'},
+       {name: 'name', mapping: 'name'},
+       {name: 'inUse', mapping: 'inUse', type: 'boolean'},
+       {name: 'private', mapping: 'private', type: 'boolean'},
+       {name: 'type', mapping: 'type'}
+    ]
+});
\ No newline at end of file
Index: main/plugin-admin/resources/js/Ametys/plugins/admin/datasource/DataSourceTool.js
===================================================================
--- main/plugin-admin/resources/js/Ametys/plugins/admin/datasource/DataSourceTool.js	(revision 0)
+++ main/plugin-admin/resources/js/Ametys/plugins/admin/datasource/DataSourceTool.js	(revision 0)
@@ -0,0 +1,282 @@
+/*
+ *  Copyright 2015 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * This tool displays the list of data sources 
+ * @private
+ */
+Ext.define('Ametys.plugins.admin.datasource.DataSourceTool', {
+	extend: 'Ametys.tool.Tool',
+	
+	/**
+	 * @private
+	 * @property {Ext.grid.panel} _panel the data sources' grid panel
+	 */
+	
+	getMBSelectionInteraction: function() 
+	{
+		return Ametys.tool.Tool.MB_TYPE_ACTIVE;
+	},
+	
+	constructor: function(config)
+	{
+		this.callParent(arguments);
+		
+		// Bus messages listeners
+		Ametys.message.MessageBus.on(Ametys.message.Message.CREATED, this._onCreated, this);
+		Ametys.message.MessageBus.on(Ametys.message.Message.MODIFIED, this._onModified, this);
+		Ametys.message.MessageBus.on(Ametys.message.Message.DELETED, this._onDeleted, this);
+	},
+	
+	createPanel: function()
+	{
+		var store = Ext.create('Ext.data.Store', {
+			model: 'Ametys.plugins.admin.datasource.DataSourceTool.DataSource',
+	        groupField: 'type',
+			
+			autoLoad: true,
+			sortOnLoad: true,
+			
+	        proxy: {
+	        	type: 'ametys',
+				plugin: 'admin',
+				url: 'datasources/get',
+	        	reader: {
+	        		type: 'json',
+					rootProperty: 'datasources'
+	        	}
+	        }
+		});
+		
+		this._panel = Ext.create('Ext.grid.Panel', {
+			stateful: true,
+			stateId: this.self.getName() + "$grid",
+
+			store : store,
+			
+			selModel : {
+		    	mode: 'MULTI'
+		    },
+		    
+		    listeners: {
+		    	'selectionchange': {fn: this.sendCurrentSelection, scope: this}
+		    },
+		    
+		    features: [{
+		    	ftype: 'grouping',
+		        groupHeaderTpl: Ext.create('Ext.XTemplate',
+		            '<div>{name:this.formatName}</div>',
+	        	    {
+			        	formatName: function(name)
+				        {
+				        	switch (name)
+				        	{
+					        	case 'SQL':
+					        		return "<i18n:text i18n:key='PLUGINS_ADMIN_UITOOL_DATASOURCE_GROUP_SQL'/>";
+					        		
+					        	case 'LDAP':
+					        		return "<i18n:text i18n:key='PLUGINS_ADMIN_UITOOL_DATASOURCE_GROUP_LDAP'/>";
+					        	default:
+					        		throw 'Unrecognized type ' + name;
+				        	}
+				        }
+	        	    }
+	        	)
+		    }],
+			
+		    columns: [
+		        {stateId: 'grid-name', header: "<i18n:text i18n:key='PLUGINS_ADMIN_UITOOL_DATASOURCE_COL_NAME'/>", flex: 0.8, sortable: true, dataIndex:'name', renderer: this._renderName},
+		        {stateId: 'grid-private', header: "<i18n:text i18n:key='PLUGINS_ADMIN_UITOOL_DATASOURCE_COL_PRIVATE'/>", width: 60, sortable: true, dataIndex: 'private', renderer: this._renderBoolean},
+		        {stateId: 'grid-inUse', header: "<i18n:text i18n:key='PLUGINS_ADMIN_UITOOL_DATASOURCE_COL_USED'/>", width: 60, sortable: true, dataIndex: 'inUse', align :'center', renderer: this._renderBoolean},
+		        {stateId: 'grid-type', header: "<i18n:text i18n:key='PLUGINS_ADMIN_UITOOL_DATASOURCE_COL_TYPE'/>", width: 80, hidden: true, dataIndex: 'type'},
+		        {stateId: 'grid-id', header: "<i18n:text i18n:key='PLUGINS_ADMIN_UITOOL_DATASOURCE_COL_ID'/>", flex: 0.2, hidden: true, dataIndex: 'id'}
+		    ]
+		});
+		
+		return this._panel;
+	},
+	
+	sendCurrentSelection: function()
+	{
+		var targets = [];
+
+		var selectedDataSources = this._panel.getSelectionModel().getSelection();
+		Ext.Array.forEach(selectedDataSources, function(selectedDataSource) {
+			
+			target = Ext.create('Ametys.message.MessageTarget', {
+				type: Ametys.message.MessageTarget.DATASOURCE,
+				parameters: {
+					id: selectedDataSource.get('id'),
+					type: selectedDataSource.get('type'),
+					inUse: selectedDataSource.get('inUse')
+				}
+			});
+			
+			targets.push(target);
+		});
+		
+		Ext.create('Ametys.message.Message', {
+			type: Ametys.message.Message.SELECTION_CHANGED,
+			targets: targets
+		});
+	},
+	
+	/**
+	 * Renderer function for the name column
+	 * @param {String} value the value of the name
+	 * @param {Object} md the metadata of the selected cell
+	 * @param {Ext.data.Model} record The record for the current row
+	 * @return {String} the html representation of the name with an icon
+	 */
+	_renderName: function(value, md, record)
+	{
+		switch (record.get('type'))
+		{
+			case 'SQL':
+				return record.get('private') ? '<span><img src="' + Ametys.getPluginResourcesPrefix('admin') + '/img/datasource/sql_private_16.png" title="' + "<i18n:text i18n:key='PLUGINS_ADMIN_UITOOL_DATASOURCE_SQL_PRIVATE'/>" + '"/> ' + value + '</span>'
+											 : '<span><img src="' + Ametys.getPluginResourcesPrefix('admin') + '/img/datasource/sql_16.png" title="' + "<i18n:text i18n:key='PLUGINS_ADMIN_UITOOL_DATASOURCE_SQL_PUBLIC'/>" + '"/> ' + value + '</span>';
+			case 'LDAP':
+				return record.get('private') ? '<span><img src="' + Ametys.getPluginResourcesPrefix('admin') + '/img/datasource/ldap_private_16.png" title="' + "<i18n:text i18n:key='PLUGINS_ADMIN_UITOOL_DATASOURCE_LDAP_PRIVATE'/>" + '"/> ' + value + '</span>'
+						 : '<span><img src="' + Ametys.getPluginResourcesPrefix('admin') + '/img/datasource/ldap_16.png" title="' + "<i18n:text i18n:key='PLUGINS_ADMIN_UITOOL_DATASOURCE_LDAP_PUBLIC'/>" + '"/> ' + value + '</span>';
+			default:
+				throw 'Unrecognized type ' + record.get('type');
+		}
+	},
+	
+    /**
+     * @private
+     * Renderer function for a boolean
+     * @param {String|Boolean} value the restricted value
+     * @return {String} the html representation of the boolean as an icon.
+     */
+    _renderBoolean: function(value)
+    {
+        if (value == 'true' || (Ext.isBoolean(value) && value))
+        {
+            return '<img src="' + Ametys.getPluginResourcesPrefix('admin') + '/img/datasource/yes_16.png" title="' + "<i18n:text i18n:key='PLUGINS_ADMIN_UITOOL_DATASOURCE_COL_BOOLEAN_YES'/>" + '"/>'
+        }
+        else
+        {
+            return "";
+        }
+    },
+	
+	/**
+	 * Handler function invoked whenever a {@link Ametys.message.Message.CREATED} message is sent out on the 
+	 * message bus. Add the corresponding record to the grid panel's store.
+	 * @param {Ametys.message.Message} message the message
+	 */
+	_onCreated: function(message)
+	{
+		var target = message.getTarget(Ametys.message.MessageTarget.DATASOURCE);
+		if (target)
+		{
+			var id = target.getParameters().id;
+			switch (target.getParameters().type)
+			{
+				case 'SQL':
+					Ametys.plugins.admin.datasource.DataSourceDAO.getSQLDataSource([id], this._addDataSource, {scope: this});
+					break;
+					
+				case 'LDAP':
+					Ametys.plugins.admin.datasource.DataSourceDAO.getLDAPDataSource([id], this._addDataSource, {scope: this});
+					break;
+					
+				default:
+					throw 'Unrecognized datasource type : ' + target.getParameters().type
+			}
+			
+		}
+	},
+	
+ 	/**
+ 	 * Add the created data source to the store
+ 	 * @param {Object} datasource the data source
+ 	 */
+	_addDataSource: function(datasource)
+	{
+		var record = Ext.create('Ametys.plugins.admin.datasource.DataSourceTool.DataSource', datasource);
+		this._panel.getStore().addSorted(record);
+	},
+	
+	/**
+	 * Handler function invoked whenever a {@link Ametys.message.Message.MODIFIED} message is sent out on the 
+	 * message bus. Update the corresponding record of the grid panel's store.
+	 * @param {Ametys.message.Message} message the message
+	 */
+	_onModified: function (message)
+	{
+		var target = message.getTarget(Ametys.message.MessageTarget.DATASOURCE);
+		if (target)
+		{
+			var id = target.getParameters().id;
+			switch (target.getParameters().type)
+			{
+				case 'SQL':
+					Ametys.plugins.admin.datasource.DataSourceDAO.getSQLDataSource([id], Ext.bind(this._editDataSource, this, [id], 1), {scope: this});
+					break;
+					
+				case 'LDAP':
+					Ametys.plugins.admin.datasource.DataSourceDAO.getLDAPDataSource([id], Ext.bind(this._editDataSource, this, [id], 1), {scope: this});
+					break;
+					
+				default:
+					throw 'Unrecognized datasource type : ' + target.getParameters().type
+			}
+			
+		}
+	},
+	
+ 	/**
+ 	 * Edit the modified data source
+ 	 * @param {Object} datasource the data source
+ 	 */
+	_editDataSource: function(datasource, id)
+	{
+		var store = this._panel.getStore();
+		
+		var record = store.getById(id);
+		
+		record.beginEdit();
+		record.set('name', datasource.name);
+		record.set('inUse', datasource.inUse);
+		record.set('private', datasource['private']);
+		record.endEdit();
+		
+		record.commit();
+		
+		this._panel.getStore().sort();
+	},
+	
+	/**
+	 * Handler function invoked whenever a {@link Ametys.message.Message.DELETED} message 
+	 * is sent out on the message bus. Delete the corresponding record from the grid panel's store.
+	 * @param {Ametys.message.Message} message the message
+	 */
+	_onDeleted: function (message)
+	{
+		var target = message.getTarget(Ametys.message.MessageTarget.DATASOURCE);
+		if (target)
+		{
+			var id = target.getParameters().id;
+			var datasource = this._panel.getStore().getById(target.getParameters().id);
+			if (datasource)
+			{
+				this._panel.getStore().remove(datasource);
+			}
+		}
+	}
+});
Index: main/plugin-admin/resources/js/Ametys/plugins/admin/datasource/DeleteDataSourceController.js
===================================================================
--- main/plugin-admin/resources/js/Ametys/plugins/admin/datasource/DeleteDataSourceController.js	(revision 0)
+++ main/plugin-admin/resources/js/Ametys/plugins/admin/datasource/DeleteDataSourceController.js	(revision 0)
@@ -0,0 +1,43 @@
+/*
+ *  Copyright 2015 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * This class controls a ribbon button allowing to delete a data source
+ * @private
+ */
+Ext.define('Ametys.plugins.admin.datasource.DeleteDataSourceController', {
+	extend: 'Ametys.ribbon.element.ui.ButtonController',
+	
+	/**
+	 * @private
+	 * @property {String} _type the type of data source managed by this controller
+	 */
+	
+	constructor: function(config)
+	{
+		this._type = config.type;
+		this.callParent(arguments);
+	},
+	
+	updateState: function()
+	{
+		var targets = this.getMatchingTargets();
+		if (targets.length > 0)
+		{
+			this.setDisabled(targets[0].getParameters().type != this._type);
+		}
+	}
+});
Index: main/plugin-admin/resources/js/Ametys/plugins/admin/datasource/EditLDAPDataSourceHelper.js
===================================================================
--- main/plugin-admin/resources/js/Ametys/plugins/admin/datasource/EditLDAPDataSourceHelper.js	(revision 0)
+++ main/plugin-admin/resources/js/Ametys/plugins/admin/datasource/EditLDAPDataSourceHelper.js	(revision 0)
@@ -0,0 +1,396 @@
+/*
+ *  Copyright 2015 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * Helper for the edition of a SQL data source
+ * @private
+ */
+Ext.define('Ametys.plugins.admin.datasource.EditLDAPDataSourceHelper', {
+	singleton: true,
+	
+	/**
+	 * @private
+	 * @property {Boolean} _initialized True if the dialog box creation process is finished
+	 */
+	/**
+	 * @private
+	 * @property {String} _mode The current edition mode ('new' or 'edit')
+	 */
+	/**
+	 * @private
+	 * @property {Ametys.window.DialogBox} _box The dialog box
+	 */
+	/**
+	 * @private
+	 * @property {Ext.form.Panel} _form The form panel
+	 */
+	/**
+	 * @private
+	 * @property {Function} _callback the callback function
+	 */
+	
+	/**
+	 * Open dialog box to create a new LDAP data source
+	 * @param {Function} callback a callback function to invoke after the form is validated, can be null
+	 */
+	add: function (callback)
+	{
+		this._callback = callback;
+		this._mode = 'new';
+		this._open (null);
+	},
+	
+	/**
+	 * Open dialog box to edit a LDAP data source
+	 * @param {String} id the id of the selected data source
+	 */
+	edit: function (id)
+	{
+		this._mode = 'edit';
+		this._open (id);
+	},
+	
+	/**
+	 * @private
+	 * Show dialog box for LDAP data source edition
+	 * @param {String} id the id of the selected data source in 'edit' mode, null in 'new' mode
+	 */
+	_open: function (id)
+	{
+		var me = this;
+		function configureCallback (success)
+		{
+			if (success)
+			{
+				me._initForm (id);
+				me._box.show();
+			}
+		}
+		
+		// Create dialog box if needed
+		this._createDialogBox(configureCallback);
+	},
+	
+	/**
+	 * @private
+	 * Create the dialog box if it is not already the case
+	 * @param {Function} callback function invoked when the dialog box's drawing is finished
+	 */
+	_createDialogBox: function (callback)
+	{
+		if (!this._initialized)
+		{
+			this._form = Ext.create('Ametys.form.ConfigurableFormPanel', {
+				testURL: Ametys.getPluginDirectPrefix('admin') + '/datasource/test'
+			});
+			
+			this._box = Ext.create('Ametys.window.DialogBox', {
+				title: this._mode == 'new' ? "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_ADD_TITLE'/>" : "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_EDIT_TITLE'/>",
+				icon: Ametys.getPluginResourcesPrefix('admin') + '/img/datasource/' + (this._mode == 'new' ? 'add_16.png' : 'edit_16.png'),
+				
+				layout: 'fit',
+				width: 700,
+				items: [ this._form ],
+				
+				closeAction: 'hide',
+				buttons : [{
+					text: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_OK'/>",
+					handler: Ext.bind(this._ok, this)
+				}, {
+					text: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_CANCEL'/>",
+					handler: Ext.bind(function() {this._box.hide();}, this)
+				}]
+			});
+			
+			this._configureForm(callback);
+		}
+		else
+		{
+			this._box.setTitle(this._mode == 'new' ? "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_ADD_TITLE'/>" : "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_EDIT_TITLE'/>");
+			this._box.setIcon(Ametys.getPluginResourcesPrefix('admin') + '/img/datasource/' + (this._mode == 'new' ? 'add_16.png' : 'edit_16.png'));
+			callback(true);
+		}
+	},
+	
+	/**
+	 * @private
+	 * Callback for the form configuration process. Configures the {@link Ametys.form.ConfigurableFormPanel} of the dialog box
+	 * @param {Function} args.callback the callback function
+	 */
+	_configureForm: function(callback)
+	{
+		var configuration = {};
+		
+		// Enumerations
+		var authenticationMethodEnumeration = [];
+		var aliasDereferencingEnumeration = [];
+		
+		// Anonymous
+		authenticationMethodEnumeration.push({label: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCE_CORE_LDAP_CONFIG_AUTH_METHOD_ENUM_NONE'/>", value: 'none'});
+		// Simple
+		authenticationMethodEnumeration.push({label: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCE_CORE_LDAP_CONFIG_AUTH_METHOD_ENUM_SIMPLE'/>", value: 'simple'});
+		
+		// Always
+		aliasDereferencingEnumeration.push({label: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_ENUM_NEVER'/>", value: 'never'});
+		// Never
+		aliasDereferencingEnumeration.push({label: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_ENUM_ALWAYS'/>", value: 'always'});
+		// Finding
+		aliasDereferencingEnumeration.push({label: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_ENUM_FINDING'/>", value: 'finding'});
+		// Searching
+		aliasDereferencingEnumeration.push({label: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_ENUM_SEARCHING'/>", value: 'searching'});
+		
+		
+		// Id field
+		configuration.id = {
+			hidden: true,
+			type: 'string'
+		};
+		
+		// Type field
+		configuration.type = {
+			hidden: true,
+			type: 'string',
+			'default-value': 'LDAP'
+		};
+		
+		// Name field
+		configuration.name = {
+			type: 'string',
+	        label: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_NAME'/>",
+	        description: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_NAME_DESCRIPTION'/>",
+	        validation: {
+	        	mandatory: true
+	        }
+		};
+		
+		// Description field
+		configuration.description = {
+			type: 'string',
+			widget: 'edition.textarea',
+			'widget-params': {
+				charCounter: false
+			},
+	        label: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_DESCRIPTION'/>",
+	        description: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_DESCRIPTION_DESCRIPTION'/>"
+		};
+		
+		// Base URL field 
+		configuration.baseURL = {
+			type: 'string',
+			label: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_URL'/>",
+			description: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_URL_DESCRIPTION'/>",
+			'default-value': 'ldap://server:389',
+	        validation: {
+	        	mandatory: true,
+	        	regexp: new RegExp('^ldaps?://[\\w\\-.]*(:\d+)?'),
+	        	regexText: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_URL_REGEXP_TEXT'/>"
+	        }
+		};
+		
+		// Use SSL field
+		configuration.useSSL = {
+			type: 'boolean',
+			widget: 'edition.checkbox',
+			label: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_USESSL'/>",
+			description: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_USESSL_DESCRIPTION'/>",
+	        validation: {
+	        	mandatory: true
+	        }
+		};
+
+		// Base DN field
+		configuration.baseDN = {
+			type: 'string',
+			label: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_BASEDN'/>",
+			description: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_BASEDN_DESCRIPTION'/>",
+			'default-value': 'dc=company,dc=com'
+		};
+		
+		// Alias dereferencing mode field
+		configuration.aliasDereferencing = {
+			type: 'string',
+			enumeration: aliasDereferencingEnumeration,
+			label: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_ALIASDEREFERENCING'/>",
+			description: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_ALIASDEREFERENCING_DESCRIPTION'/>",
+			'default-value': 'always'
+		};
+		
+		// Follow referrals field
+		configuration.followReferrals = {
+			type: 'boolean',
+			widget: 'edition.checkbox',
+			label: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_FOLLOWREFERRALS'/>",
+			description: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_FOLLOWREFERRALS_DESCRIPTION'/>"
+		};
+		
+		// Authentication method field
+		configuration.authenticationMethod = {
+			type: 'string',
+			enumeration: authenticationMethodEnumeration,
+			label: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_AUTHENTICATIONMETHOD'/>",
+			description: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_AUTHENTICATIONMETHOD_DESCRIPTION'/>",
+			'default-value': 'none'
+		};
+		
+		// Administrator domain name field
+		configuration.adminDN = {
+			type: 'string',
+			label: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_ADMINDN'/>",
+			description: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_ADMINDN_DESCRIPTION'/>",
+			disableCondition: {condition: [{id: 'authenticationMethod', operator: 'eq', value: 'none'}]},
+			'default-value': 'cn=admin'
+		};
+		
+		// Administrator password field
+		configuration.adminPassword = {
+			type: 'password',
+			widget: 'edition.password',
+			label: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_ADMINPASSWORD'/>",
+			description: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_ADMINPASSWORD_DESCRIPTION'/>",
+			disableCondition: {condition: [{id: 'authenticationMethod', operator: 'eq', value: 'none'}]}
+		};
+		
+		// Private field
+		configuration['private'] = {
+			type: 'boolean',
+			widget: 'edition.checkbox',
+			label: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_PRIVATE'/>",
+			description: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_LDAP_FIELD_PRIVATE_DESCRIPTION'/>",
+			'param-checker': {
+				id: 'sql-connection-checker-datasource',
+				'small-icon-path': '/plugins/admin/resources/img/datasource/test_ldapconnect_16.png',
+				'medium-icon-path': '/plugins/admin/resources/img/datasource/test_ldapconnect_32.png',
+				'large-icon-path': '/plugins/admin/resources/img/datasource/test_ldapconnect_48.png',
+				'linked-params': ['baseURL', 'baseDN', 'authenticationMethod', 'adminDN', 'adminPassword', 'useSSL', 'followReferrals'],
+				'param-ref': 'private',
+				label: "<i18n:text i18n:key='PLUGINS_CORE_LDAP_CONNECTION_CHECKER_LABEL' i18n:catalogue='plugin.core-impl'/>",
+				description: "<i18n:text i18n:key='PLUGINS_CORE_LDAP_CONNECTION_CHECKER_DESC' i18n:catalogue='plugin.core-impl'/>",
+				order: 1
+			}
+		};
+		
+		this._form.configure(configuration);
+		callback(true);
+	},
+	
+ 	/**
+ 	 * @private
+ 	 * Initialize the fields of the form
+ 	 * @param {String} id the id of the data source if in 'edit' mode, null in 'new' mode
+ 	 */
+	_initForm: function (id)
+ 	{
+		var form = this._form.getForm();
+		
+		// Reset the parameter checker status to 'not tested' and reset the warnings
+		if (this._initialized)
+		{
+			this._form.reset();
+		}
+		
+		this._initialized = true;
+		
+ 		if (id == null) 
+        {
+ 			// FIXME chrome automatically sets the user and password fields...
+ 			this._form.setValues({});
+ 			form.reset();
+        }
+ 		else
+ 		{
+ 			Ametys.plugins.admin.datasource.DataSourceDAO.getLDAPDataSource([id], this._setValues, {scope: this});
+ 			form.findField('id').setValue(id);
+ 		}
+ 	},
+
+ 	
+ 	/**
+ 	 * @private
+ 	 * Fill the edition form with the given values
+ 	 * @param {Object} datasource the parameter values for the sql data source
+ 	 * @param {String} datasource.name the name of the data source
+ 	 * @param {String} datasource.description the optional description of the data source
+ 	 * @param {String} datasource.baseURL the url of the LDAP server
+ 	 * @param {Boolean} datasource.useSSL is the connection using the 'ldaps' protocol ?
+ 	 * @param {String} datasource.baseDN the base domain name
+ 	 * @param {String} datasource.aliasDerefencing the mode for alias dereferencing
+ 	 * @param {Boolean} datasource.followReferrals true to follow the referrals
+	 * @param {String} datasource.authenticationMethod the authentication method used to establish a connection with the data source
+	 * @param {String} datasource.adminDN the administrator domain name
+	 * @param {String} datasource.adminPassword the administrator's password
+	 * @param {Boolean} datasource.private is the data source public or private ?
+ 	 */
+ 	_setValues: function(datasource)
+ 	{
+ 		this._form.setValues({values: datasource});
+ 	},
+ 	
+ 	/**
+ 	 * @private
+ 	 * Check if the data source is valid
+ 	 */
+ 	_ok: function()
+ 	{
+ 		if (!this._form.isValid())
+		{
+ 			return;
+		}
+ 		
+ 		// Test the data source
+ 		var paramCheckersDAO = this._form._paramCheckersDAO;
+ 		
+ 		Ext.getBody().mask("<i18n:text i18n:key='PLUGINS_CORE_UI_LOADMASK_DEFAULT_MESSAGE' i18n:catalogue='plugin.core-ui'/>");
+ 		paramCheckersDAO.check(paramCheckersDAO._paramCheckers,
+ 							   true, 
+					           Ext.bind(function(success) 
+				      		   { 
+					              Ext.getBody().unmask(); 
+					              if (success) 
+					              { 
+					            	  this._okCb();
+					              }
+				      	  		}, this), false); 
+ 	},
+ 	
+ 	/**
+ 	 * @private
+ 	 * Submit the form's values
+ 	 */
+	_okCb: function()
+	{
+		var values = this._form.getValues();
+ 		values['private'] = this._form.getForm().findField('private').getValue();
+ 		values['useSSL'] = this._form.getForm().findField('useSSL').getValue();
+ 		values['followReferrals'] = this._form.getForm().findField('followReferrals').getValue();
+ 		
+ 		if (this._mode == 'new')
+		{
+ 			Ametys.plugins.admin.datasource.DataSourceDAO.addLDAPDataSource([values], 
+				function(id) {
+ 					this._box.hide();
+ 			 		if (Ext.isFunction(this._callback))
+ 					{
+ 			 			this._callback(id);
+ 					}
+ 				}, 
+ 				{scope: this, waitMessage: {target: this._box}});
+		}
+ 		else
+		{
+ 			Ametys.plugins.admin.datasource.DataSourceDAO.editLDAPDataSource([values], function() {this._box.hide();}, {scope: this, waitMessage: {target: this._box}});
+		}
+	}
+});
\ No newline at end of file
Index: main/plugin-admin/resources/js/Ametys/plugins/admin/datasource/EditSQLDataSourceHelper.js
===================================================================
--- main/plugin-admin/resources/js/Ametys/plugins/admin/datasource/EditSQLDataSourceHelper.js	(revision 0)
+++ main/plugin-admin/resources/js/Ametys/plugins/admin/datasource/EditSQLDataSourceHelper.js	(revision 0)
@@ -0,0 +1,404 @@
+/*
+ *  Copyright 2015 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * Helper for the edition of a SQL data source
+ * @private
+ */
+Ext.define('Ametys.plugins.admin.datasource.EditSQLDataSourceHelper', {
+	singleton: true,
+	
+	/**
+	 * @private
+	 * @property {Boolean} _initialized True if the dialog box creation process is finished
+	 */
+	/**
+	 * @private
+	 * @property {String} _mode The current edition mode ('new' or 'edit')
+	 */
+	/**
+	 * @private
+	 * @property {Ametys.window.DialogBox} _box The dialog box
+	 */
+	/**
+	 * @private
+	 * @property {Ext.form.Panel} _form The form panel
+	 */
+	/**
+	 * @private
+	 * @property {Object} _templates the mapping of driver value with their associated template
+	 */
+	/**
+	 * @private
+	 * @property {Function} _callback the callback function
+	 */
+	
+	/**
+	 * Open dialog box to create a new SQL data source
+	 * @param {Function} callback a callback function to invoke after the form is validated, can be null
+	 */
+	add: function (callback)
+	{
+		this._callback = callback;
+		this._mode = 'new';
+		this._open (null);
+	},
+	
+	/**
+	 * Open dialog box to edit a SQL data source
+	 * @param {String} id the id of the selected data source
+	 */
+	edit: function (id)
+	{
+		this._mode = 'edit';
+		this._open (id);
+	},
+	
+	/**
+	 * @private
+	 * Show dialog box for SQL data source edition
+	 * @param {String} id the id of the selected data source in 'edit' mode, null in 'new' mode
+	 */
+	_open: function (id)
+	{
+		var me = this;
+		function configureCallback (success)
+		{
+			if (success)
+			{
+				me._initForm (id);
+				me._box.show();
+			}
+		}
+		
+		// Create dialog box if needed
+		this._createDialogBox(configureCallback);
+	},
+	
+	/**
+	 * @private
+	 * Create the dialog box if it is not already the case
+	 * @param {Function} callback function invoked when the dialog box's drawing is finished
+	 */
+	_createDialogBox: function (callback)
+	{
+		if (!this._initialized)
+		{
+			this._form = Ext.create('Ametys.form.ConfigurableFormPanel', {
+				testURL: Ametys.getPluginDirectPrefix('admin') + '/datasource/test'
+			});
+			
+			this._box = Ext.create('Ametys.window.DialogBox', {
+				title: this._mode == 'new' ? "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_ADD_TITLE'/>" : "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_EDIT_TITLE'/>",
+				icon: Ametys.getPluginResourcesPrefix('admin') + '/img/datasource/' + (this._mode == 'new' ? 'add_16.png' : 'edit_16.png'),
+				
+				layout: 'fit',
+				width: 700,
+				items: [ this._form ],
+				
+				closeAction: 'hide',
+				buttons : [{
+					text: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_OK'/>",
+					handler: Ext.bind(this._ok, this)
+				}, {
+					text: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_CANCEL'/>",
+					handler: Ext.bind(function() {this._box.hide();}, this)
+				}]
+			});
+			
+			this._configureForm(callback);
+		}
+		else
+		{
+			this._box.setTitle(this._mode == 'new' ? "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_ADD_TITLE'/>" : "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_EDIT_TITLE'/>");
+			this._box.setIcon(Ametys.getPluginResourcesPrefix('admin') + '/img/datasource/' + (this._mode == 'new' ? 'add_16.png' : 'edit_16.png'));
+			callback(true);
+		}
+	},
+	
+	/**
+	 * @private
+	 * Configure the {@link Ametys.form.ConfigurableFormPanel}
+	 * @param {Function} callback function invoked when the form configuration is finished
+	 */
+	_configureForm: function(callback)
+	{
+		// Retrieve the handled database types
+		Ametys.data.ServerComm.callMethod({
+			role: "org.ametys.core.datasource.sql.dbtype.SQLDatabaseTypeManager",
+			methodName: "getSQLDatabaseTypes",
+			parameters: [],
+			callback: {
+				handler: this._configureFormCb,
+				arguments: {
+					callback: callback
+				},
+				scope: this
+			},
+			errorMessage: {
+				category: this.self.getName(),
+				msg: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_GET_DRIVERS_ERROR'/>"
+			}
+		});
+	},
+	
+	/**
+	 * @private
+	 * Callback for the form configuration process. Configures the {@link Ametys.form.ConfigurableFormPanel} of the dialog box
+	 * @param {Object} response the server's response
+	 * @param {Array} response.databaseTypes the array of database types
+	 * @param {String} response.databaseTypes.label the label of the current database type
+	 * @param {String} response.databaseTypes.value the value of the current database type
+	 * @param {String} response.databaseTypes.template the template associated to the current database type 
+	 * @param {Object} args the callback arguments
+	 * @param {Function} args.callback the callback function
+	 */
+	_configureFormCb: function(response, args)
+	{
+		var me = this;
+		
+		var databaseTypes = response.databaseTypes;
+		
+		var driverEnumeration = []; // The list of label-value pairs that will be displayed in the form
+		var templateMapping = {}; // The mapping of driver value and associated template
+		
+		Ext.Array.each(databaseTypes, function(databaseType){
+			driverEnumeration.push({label: databaseType.label, value: databaseType.value});
+			
+			templateMapping[databaseType.value] = databaseType.template;
+		});
+			
+		this._templates = templateMapping;
+		
+		var configuration = {};
+		
+		// Id field
+		configuration.id = {
+			hidden: true,
+			type: 'string'
+		};
+		
+		// Type field
+		configuration.type = {
+			hidden: true,
+			type: 'string',
+			'default-value': 'SQL'
+		};
+		
+		// Name field
+		configuration.name = {
+			type: 'string',
+	        label: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_NAME'/>",
+	        description: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_NAME_DESCRIPTION'/>",
+	        validation: {
+	        	mandatory: true
+	        }
+		};
+		
+		// Description field
+		configuration.description = {
+			type: 'string',
+			widget: 'edition.textarea',
+			'widget-params': {
+				charCounter: false
+			},
+	        label: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_DESCRIPTION'/>",
+	        description: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_DESCRIPTION_DESCRIPTION'/>"
+		};
+		
+		// Driver field 
+		configuration.driver = {
+			type: 'string',
+			enumeration: driverEnumeration,
+			label: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_DRIVER'/>",
+		    description: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_DRIVER_DESCRIPTION'/>",
+	        validation: {
+	        	mandatory: true
+	        }
+		};
+		
+		// Url field : depends on which jdbc driver is selected
+		configuration.url = {
+			type: 'string',
+			label: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_URL'/>",
+			description: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_URL_DESCRIPTION'/>",
+	        validation: {
+	        	mandatory: true
+	        }
+		};
+		
+		// user field
+		configuration.user = {
+			type: 'string',
+			label: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_USER'/>",
+			description: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_USER_DESCRIPTION'/>"
+		};
+		
+		// password field
+		configuration.password = {
+			type: 'password',
+			widget: 'edition.password',
+			label: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_PASSWORD'/>",
+			description: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_PASSWORD_DESCRIPTION'/>"
+		};
+		
+		// Private field
+		configuration['private'] = {
+			type: 'boolean',
+			widget: 'edition.checkbox',
+			label: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_PRIVATE'/>",
+			description: "<i18n:text i18n:key='PLUGINS_ADMIN_DATASOURCES_DIALOG_SQL_FIELD_PRIVATE_DESCRIPTION'/>",
+			'param-checker': {
+				id: 'sql-connection-checker-datasource',
+				'small-icon-path': '/plugins/admin/resources/img/datasource/test_sqlconnect_16.png',
+				'medium-icon-path': '/plugins/admin/resources/img/datasource/test_sqlconnect_32.png',
+				'large-icon-path': '/plugins/admin/resources/img/datasource/test_sqlconnect_48.png',
+				'linked-params': ['driver', 'url', 'user', 'password'],
+				'param-ref': 'private',
+				label: "<i18n:text i18n:key='PLUGINS_CORE_SQL_CONNECTION_CHECKER_LABEL' i18n:catalogue='plugin.core-impl'/>",
+				description: "<i18n:text i18n:key='PLUGINS_CORE_SQL_CONNECTION_CHECKER_DESC' i18n:catalogue='plugin.core-impl'/>",
+				order: 1
+			}
+		};
+		
+		this._form.configure(configuration);
+		
+		args.callback(true);
+	},
+	
+ 	/**
+ 	 * @private
+ 	 * Initialize the fields of the form
+ 	 * @param {String} id the id of the data source if in 'edit' mode, null in 'new' mode
+ 	 */
+	_initForm: function (id)
+ 	{
+		var form = this._form.getForm(); 
+		if (!this._initialized)
+		{
+			form.findField('driver').on('change', Ext.bind(this._onDriverChange, this));
+		}
+		
+		// Reset the parameter checker status to 'not tested' and reset the warnings
+		if (this._initialized)
+		{
+			this._form.reset();
+		}
+		
+		this._initialized = true;
+		
+ 		if (id == null) 
+        {
+ 			// FIXME chrome automatically sets the user and password fields... see CMS-6913
+ 	 		this._form.setValues({});
+ 	 		form.reset();
+        }
+ 		else
+ 		{
+ 			Ametys.plugins.admin.datasource.DataSourceDAO.getSQLDataSource([id], this._setValues, {scope: this});
+ 			form.findField('id').setValue(id);
+ 		}
+ 	},
+ 	
+ 	/**
+ 	 * @private
+ 	 * Fill the edition form with the given values
+ 	 * @param {Object} datasource the parameter values for the sql data source
+ 	 * @param {String} datasource.name the name of the data source
+ 	 * @param {String} datasource.description the optional description of the data source
+ 	 * @param {String} datasource.driver the driver used for this data source
+ 	 * @param {String} datasource.url the url of the sql data base
+ 	 * @param {String} datasource.user the optional user of the data base
+ 	 * @param {String} datasource.password the optional password to access the data base with the given user login
+ 	 * @param {Boolean} datasource.private is the data source public or private ?
+ 	 */
+ 	_setValues: function(datasource)
+ 	{
+ 		this._form.setValues({values: datasource});
+ 	},
+ 	
+ 	/**
+ 	 * @private
+ 	 * Check if the data source is valid
+ 	 */
+ 	_ok: function()
+ 	{
+ 		if (!this._form.isValid())
+		{
+ 			return;
+		}
+ 		
+ 		
+ 		// Test the data source
+ 		var paramCheckersDAO = this._form._paramCheckersDAO;
+ 		
+ 		Ext.getBody().mask("<i18n:text i18n:key='PLUGINS_CORE_UI_LOADMASK_DEFAULT_MESSAGE' i18n:catalogue='plugin.core-ui'/>");
+ 		paramCheckersDAO.check(paramCheckersDAO._paramCheckers,
+ 							   true, 
+					           Ext.bind(function(success) 
+				      		   { 
+					              Ext.getBody().unmask(); 
+					              if (success) 
+					              { 
+					            	  this._okCb();
+					              }
+				      	  		}, this), false); 
+ 	},
+ 	
+ 	/**
+ 	 * @private
+ 	 * Submit the form's values
+ 	 */
+	_okCb: function()
+	{
+    	var values = this._form.getValues();
+ 		values['private'] = this._form.getForm().findField('private').getValue();
+    	
+		if (this._mode == 'new')
+		{
+			Ametys.plugins.admin.datasource.DataSourceDAO.addSQLDataSource([values], 
+				function(id) {
+						this._box.hide();
+				 		if (Ext.isFunction(this._callback))
+						{
+				 			this._callback(id);
+						}
+					}, 
+				{scope: this, waitMessage: {target: this._box}}
+			);
+		}
+		else
+		{
+			Ametys.plugins.admin.datasource.DataSourceDAO.editSQLDataSource([values], function() {this._box.hide();}, {scope: this, waitMessage: {target: this._box}});
+		}
+	},
+ 	
+	/**
+	 * @private
+     * Function invoked when the value of the driver field changes
+     * @param {Ametys.form.widget.ComboBox} combo the combobox
+     * @param {String} newValue the new value of the field
+     * @param {String} oldValue the previous value of the field
+	 */
+	_onDriverChange: function(combo, newValue, oldValue)
+	{
+		if (oldValue != newValue)
+		{
+			var form = this._form.getForm();
+			form.findField('url').setValue(this._templates[newValue]);
+		}
+	}
+});
\ No newline at end of file
Index: main/plugin-admin/sitemap.xmap
===================================================================
--- main/plugin-admin/sitemap.xmap	(revision 38980)
+++ main/plugin-admin/sitemap.xmap	(working copy)
@@ -40,6 +40,9 @@
             <map:action name="config-save" src="org.ametys.runtime.plugins.admin.configuration.SaveConfigAction" logger="org.ametys.runtime.plugins.admin.action"/>
             <map:action name="config-test" src="org.ametys.runtime.plugins.admin.configuration.ParameterCheckerAction" logger="org.ametys.runtime.plugins.admin.action"/>
 			<map:action name="restart" src="org.ametys.runtime.plugins.admin.RestartAction" logger="org.ametys.runtime.plugins.admin.action"/>
+		  
+		    <map:action name="datasources" src="org.ametys.runtime.plugins.admin.datasource.GetDataSourcesAction" logger="org.ametys.plugins.admin.datasource.GetDataSourcesAction" />
+		    <map:action name="datasource-test" src="org.ametys.runtime.plugins.admin.datasource.CheckDataSourceAction" logger="org.ametys.runtime.plugins.admin.datasource.TestDataSourceAction" />
 		</map:actions>
         
         <map:readers>
@@ -285,6 +288,22 @@
                 </map:act>
             </map:match>
             
+            <!-- +
+                 | Data sources
+                 + -->
+            <map:match pattern="datasources/get">
+                <map:act type="datasources">
+                    <map:read type="json"/>
+                </map:act>
+            </map:match>
+            
+            <map:match pattern="datasource/test">
+                <map:act type="datasource-test">
+                    <map:generate type="action-result"/>
+                    <map:serialize type="xml"/>
+                </map:act>
+            </map:match>
+            
         </map:pipeline>
     </map:pipelines>
 </map:sitemap>
\ No newline at end of file
Index: main/plugin-admin/src/org/ametys/runtime/plugins/admin/datasource/CheckDataSourceAction.java
===================================================================
--- main/plugin-admin/src/org/ametys/runtime/plugins/admin/datasource/CheckDataSourceAction.java	(revision 0)
+++ main/plugin-admin/src/org/ametys/runtime/plugins/admin/datasource/CheckDataSourceAction.java	(revision 0)
@@ -0,0 +1,140 @@
+package org.ametys.runtime.plugins.admin.datasource;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.cocoon.acting.ServiceableAction;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Redirector;
+import org.apache.cocoon.environment.Request;
+import org.apache.cocoon.environment.SourceResolver;
+import org.apache.commons.lang.StringUtils;
+
+import org.ametys.core.cocoon.ActionResultGenerator;
+import org.ametys.core.datasource.ldap.LDAPDataSourceManager;
+import org.ametys.core.datasource.ldap.LDAPDataSourceManager.LDAPDataSourceDescriptor;
+import org.ametys.core.datasource.sql.SQLDataSourceManager;
+import org.ametys.core.datasource.sql.dbtype.SQLDatabaseTypeManager;
+import org.ametys.core.util.I18nUtils;
+import org.ametys.plugins.core.impl.checker.LDAPConnectionChecker;
+import org.ametys.plugins.core.impl.checker.SQLConnectionChecker;
+import org.ametys.runtime.i18n.I18nizableText;
+import org.ametys.runtime.parameter.ParameterChecker;
+
+/**
+ * Action allowing to check the validity of a combination of parameters to establish a SQL connection
+ */
+public class CheckDataSourceAction extends ServiceableAction
+{
+    /** The manager for SQL data source */
+    private SQLDataSourceManager _sqlDataSourceManager;
+    
+    /** The manager for SQL data source */
+    private LDAPDataSourceManager _ldapDataSourceManager;
+    
+    /** The manager for SQL database types */
+    private SQLDatabaseTypeManager _sqlDatabaseTypeManager;
+    
+    /** Utility methods helping the management of internationalizable text */
+    private I18nUtils _i18nUtils;
+    
+    @Override
+    public void service(ServiceManager serviceManager) throws ServiceException
+    {
+        _ldapDataSourceManager = (LDAPDataSourceManager) serviceManager.lookup(LDAPDataSourceManager.ROLE);
+        _sqlDataSourceManager = (SQLDataSourceManager) serviceManager.lookup(SQLDataSourceManager.ROLE);
+        _sqlDatabaseTypeManager = (SQLDatabaseTypeManager) serviceManager.lookup(SQLDatabaseTypeManager.ROLE);
+        _i18nUtils = (I18nUtils) serviceManager.lookup(I18nUtils.ROLE);
+    }
+    
+    @Override
+    public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception
+    {
+        Map<String, String> result = new HashMap<> ();
+        Request request = ObjectModelHelper.getRequest(objectModel);
+        
+        String type = request.getParameter("type");
+        Map<String, String> testParameters = new HashMap<> ();
+        ParameterChecker paramChecker = null;
+        
+        switch (type)
+        {
+            case "SQL":
+                String driver = request.getParameter("driver");
+                
+                if (StringUtils.isNotEmpty(driver))
+                {
+                    I18nizableText driverNotFoundMessageKey = _sqlDatabaseTypeManager.getClassNotFoundMessage(driver);
+                    testParameters.put("driverNotFoundMessage", _i18nUtils.translate(driverNotFoundMessageKey));
+                }
+                
+                testParameters.put("url", request.getParameter("url"));
+                testParameters.put("driver", request.getParameter("driver"));
+                testParameters.put("user", request.getParameter("user"));
+                
+                String password = request.getParameter("password");
+                
+                // A null password => the password is recorded
+                if (password == null)
+                {
+                    String dataSourceId = request.getParameter("id");
+                    Map<String, Object> sqlDataSourceDescription = _sqlDataSourceManager.getSQLDataSourceDescription(dataSourceId);
+                    testParameters.put("password", (String) sqlDataSourceDescription.get("password"));
+                }
+                else
+                {
+                    testParameters.put("password", password);
+                }
+                
+                paramChecker = new SQLConnectionChecker();
+                break;
+                
+            case "LDAP":
+                testParameters.put("baseURL", request.getParameter("baseURL"));
+                testParameters.put("useSSL", request.getParameter("useSSL"));
+                testParameters.put("baseDN", request.getParameter("baseDN"));
+                testParameters.put("followReferrals", request.getParameter("followReferrals"));
+                
+                String authenticationMethod = request.getParameter("authenticationMethod");
+                testParameters.put("authenticationMethod", authenticationMethod);
+                testParameters.put("adminDN", request.getParameter("adminDN"));
+                
+                String adminPassword = request.getParameter("adminPassword");
+                
+                // A null password + an authentication method => the password is recorded
+                if (adminPassword == null && !authenticationMethod.equals("none"))
+                {
+                    String dataSourceId = request.getParameter("id");
+                    LDAPDataSourceDescriptor ldapDataSourceDescription = _ldapDataSourceManager.getLDAPDataSourceDescription(dataSourceId);
+                    testParameters.put("adminPassword", ldapDataSourceDescription.getAdminPassword());
+                }
+                else
+                {
+                    testParameters.put("adminPassword", adminPassword);
+                }
+                
+                paramChecker = new LDAPConnectionChecker();
+                break;
+            
+            default:
+                throw new IllegalArgumentException("Invalid type for check: '" + type + "'.");
+        }
+        
+        try 
+        {
+            paramChecker.check(testParameters); 
+        }
+        catch (Throwable t)
+        {
+            getLogger().error("The test failed: \n" + t.getMessage(), t);
+            String msg = t.getMessage() != null ? t.getMessage() : "Unknown error";
+            result.put(request.getParameter("paramCheckersIds"), msg);
+        }
+        
+        request.setAttribute(ActionResultGenerator.MAP_REQUEST_ATTR, result);
+        return result;
+    }
+}
Index: main/plugin-admin/src/org/ametys/runtime/plugins/admin/datasource/DataSourceDAO.java
===================================================================
--- main/plugin-admin/src/org/ametys/runtime/plugins/admin/datasource/DataSourceDAO.java	(revision 0)
+++ main/plugin-admin/src/org/ametys/runtime/plugins/admin/datasource/DataSourceDAO.java	(revision 0)
@@ -0,0 +1,175 @@
+/*
+ *  Copyright 2015 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.ametys.runtime.plugins.admin.datasource;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.avalon.framework.component.Component;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
+
+import org.ametys.core.datasource.ldap.LDAPDataSourceManager;
+import org.ametys.core.datasource.ldap.LDAPDataSourceManager.LDAPDataSourceDescriptor;
+import org.ametys.core.datasource.sql.SQLDataSourceManager;
+import org.ametys.core.ui.Callable;
+import org.ametys.runtime.plugin.component.AbstractLogEnabled;
+
+/**
+ * DAO for the addition/edition/deletion of datasources. Handled data sources types are:
+ *  - SQL
+ *  - LDAP
+ *  - AD
+ */
+public class DataSourceDAO extends AbstractLogEnabled implements Component, Serviceable
+{
+    /** The SQL data source manager */
+    private SQLDataSourceManager _sqlDataSourceManager;
+    
+    /** The SQL data source manager */
+    private LDAPDataSourceManager _ldapDataSourceManager;
+    
+    @Override
+    public void service(ServiceManager manager) throws ServiceException
+    {
+        _sqlDataSourceManager = (SQLDataSourceManager) manager.lookup(SQLDataSourceManager.ROLE);
+        _ldapDataSourceManager = (LDAPDataSourceManager) manager.lookup(LDAPDataSourceManager.ROLE);
+    }
+    
+    /**
+     * Get the sql data source information
+     * @param id The id the data source
+     * @return The data source's information
+     * @throws Exception if an error occurs while retrieving the data source
+     */
+    @Callable
+    public Map<String, Object> getSQLDataSource (String id) throws Exception 
+    {
+        Map<String, Object> sqlDataSource = new HashMap<> ();
+
+        sqlDataSource.putAll(_sqlDataSourceManager.getSQLDataSourceDescription(id));
+        sqlDataSource.put("id", id);
+        sqlDataSource.put("type", "SQL");
+        
+        return sqlDataSource;
+    }
+    
+    /**
+     * Add a sql data source 
+     * @param parameters The parameters of the data source to create
+     * @return The id of the created data source
+     * @throws Exception if an error occurs while retrieving the data source
+     */
+    @Callable
+    public String addSQLDataSource (Map<String, Object> parameters) throws Exception 
+    {
+        return _sqlDataSourceManager.saveSQLDataSource(parameters);
+    }
+
+    /**
+     * Edit a sql data source 
+     * @param parameters The parameters of the data source to edit
+     * @throws Exception if an error occurs while retrieving the data source
+     */
+    @Callable
+    public void editSQLDataSource (Map<String, Object> parameters) throws Exception 
+    {
+        _sqlDataSourceManager.saveSQLDataSource(parameters);
+    }
+    
+    /**
+     * Remove one or several sql data sources 
+     * @param ids the ids of the data sources to remove
+     * @throws Exception if something goes wrong during the sql data source removal process
+     */
+    @Callable
+    public void removeSQLDataSource (List<String> ids) throws Exception
+    {
+        for (String id : ids)
+        {
+            _sqlDataSourceManager.removeSQLDataSource(id);
+        }
+    }
+    
+    /**
+     * Get the ldap data source information
+     * @param id The id the data source
+     * @return The data source's information
+     * @throws Exception if an error occurs while retrieving the data source
+     */
+    @Callable
+    public Map<String, Object> getLDAPDataSource (String id) throws Exception 
+    {
+        Map<String, Object> ldapDataSource = new HashMap<> ();
+        
+        LDAPDataSourceDescriptor dataSourceDescriptor = _ldapDataSourceManager.getLDAPDataSourceDescription(id);
+
+        ldapDataSource.put("id", id);
+        ldapDataSource.put("name", dataSourceDescriptor.getName());
+        ldapDataSource.put("description", dataSourceDescriptor.getDescription());
+        ldapDataSource.put("baseURL", dataSourceDescriptor.getBaseURL());
+        ldapDataSource.put("useSSL", dataSourceDescriptor.isUsingSSL());
+        ldapDataSource.put("baseDN", dataSourceDescriptor.getBaseDN());
+        ldapDataSource.put("aliasDereferencing", dataSourceDescriptor.getAliasDereferencing());
+        ldapDataSource.put("followReferrals", dataSourceDescriptor.isFollowingReferrals());
+        ldapDataSource.put("authenticationMethod", dataSourceDescriptor.getAuthenticationMethod());
+        ldapDataSource.put("adminDN", dataSourceDescriptor.getAdminDN());
+        ldapDataSource.put("adminPassword", dataSourceDescriptor.getAdminPassword());
+        ldapDataSource.put("private", dataSourceDescriptor.isPrivate());
+        ldapDataSource.put("type", "LDAP");
+        
+        return ldapDataSource;
+    }
+    
+    /**
+     * Add a ldap data source 
+     * @param parameters The parameters of the data source to create
+     * @return The id of the created data source
+     * @throws Exception if an error occurs while retrieving the data source
+     */
+    @Callable
+    public String addLDAPDataSource (Map<String, Object> parameters) throws Exception 
+    {
+        return _ldapDataSourceManager.saveLDAPDataSource(parameters);
+    }
+
+    /**
+     * Edit a ldap data source 
+     * @param parameters The parameters of the data source to edit
+     * @throws Exception if an error occurs while retrieving the data source
+     */
+    @Callable
+    public void editLDAPDataSource (Map<String, Object> parameters) throws Exception 
+    {
+        _ldapDataSourceManager.saveLDAPDataSource(parameters);
+    }
+    
+    /**
+     * Remove one or several ldap data source(s) 
+     * @param ids the ids of the data sources to remove
+     * @throws Exception if something goes wrong during the sql data source removal process
+     */
+    @Callable
+    public void removeLDAPDataSource (List<String> ids) throws Exception
+    {
+        for (String id : ids)
+        {
+            _ldapDataSourceManager.removeLDAPDataSource(id);
+        }
+    }
+}
Index: main/plugin-admin/src/org/ametys/runtime/plugins/admin/datasource/GetDataSourcesAction.java
===================================================================
--- main/plugin-admin/src/org/ametys/runtime/plugins/admin/datasource/GetDataSourcesAction.java	(revision 0)
+++ main/plugin-admin/src/org/ametys/runtime/plugins/admin/datasource/GetDataSourcesAction.java	(revision 0)
@@ -0,0 +1,183 @@
+/*
+ *  Copyright 2015 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.ametys.runtime.plugins.admin.datasource;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.cocoon.acting.ServiceableAction;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Redirector;
+import org.apache.cocoon.environment.Request;
+import org.apache.cocoon.environment.SourceResolver;
+import org.apache.commons.lang3.StringUtils;
+
+import org.ametys.core.cocoon.JSonReader;
+import org.ametys.core.datasource.ldap.LDAPDataSourceManager;
+import org.ametys.core.datasource.ldap.LDAPDataSourceManager.LDAPDataSourceDescriptor;
+import org.ametys.core.datasource.sql.SQLDataSourceManager;
+
+/**
+ * Retrieve the datasources and format them in JSON
+ */
+public class GetDataSourcesAction extends ServiceableAction
+{
+    /** The manager handling the SQL data sources */
+    private SQLDataSourceManager _sqlDataSourceManager; 
+    
+    /** The manager handling the LDAP data sources */
+    private LDAPDataSourceManager _ldapDataSourceManager; 
+    
+    @Override
+    public void service(ServiceManager serviceManager) throws ServiceException
+    {
+        _sqlDataSourceManager = (SQLDataSourceManager) serviceManager.lookup(SQLDataSourceManager.ROLE);
+        _ldapDataSourceManager = (LDAPDataSourceManager) serviceManager.lookup(LDAPDataSourceManager.ROLE);
+    }
+    
+    @Override
+    public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception
+    {
+        Map<String, Object> result = new HashMap<> ();
+
+        Request request = ObjectModelHelper.getRequest(objectModel);
+        String includePrivateAsString = request.getParameter("includePrivate"); 
+        String includeDefaultAsString = request.getParameter("includeDefault"); 
+        String type = request.getParameter("type");
+        
+        boolean includePrivate = includePrivateAsString == null || includePrivateAsString.equals("true"); // Default value is true
+        boolean includeDefault = includeDefaultAsString != null && includeDefaultAsString.equals("true"); // Default value is false
+        
+        List<Map<String, Object>> dataSources = new ArrayList<>();
+
+        if (StringUtils.isEmpty(type) || type.equals("SQL"))
+        {
+            dataSources.addAll(_getSQLDataSources (includePrivate, includeDefault));
+        }
+        
+        if (StringUtils.isEmpty(type) || type.equals("LDAP"))
+        {
+            dataSources.addAll(_getLDAPDataSources (includePrivate));
+        }
+        
+        result.put("datasources", dataSources);
+        
+        request.setAttribute(JSonReader.OBJECT_TO_READ, result);
+        return EMPTY_MAP;
+    }
+    
+    /**
+     * Get all sql data sources
+     * @param includePrivate true to include the private data sources
+     * @param includeDefault true to include the default data source 
+     * @return the sql data sources
+     * @throws Exception if an exception occurs while retrieving the SQL data sources
+     */
+    private List<Map<String, Object>> _getSQLDataSources (boolean includePrivate, boolean includeDefault) throws Exception
+    {
+        List<Map<String, Object>> dataSources = new ArrayList<>();
+        
+        Map<String, Map<String, Object>> dataSourcesDescriptions = _sqlDataSourceManager.getSQLDataSourcesDescriptions();
+        String defaultDataSourceId = _sqlDataSourceManager.getDefaultDataSourceId();
+        
+        for (String id : dataSourcesDescriptions.keySet())
+        {
+            Map<String, Object> dataSource = new HashMap<>();
+            Map<String, Object> dataSourceDescriptor = dataSourcesDescriptions.get(id);
+            if (id.equals(defaultDataSourceId))
+            {
+                if (includeDefault)
+                {
+                    dataSource.putAll(dataSourceDescriptor);
+
+                    dataSource.put("id", defaultDataSourceId);
+                    dataSource.put("name", _sqlDataSourceManager.getDefaultDataSourceName());
+                    dataSource.put("description", _sqlDataSourceManager.getDefaultDataSourceDescription());
+                    dataSource.put("type", "SQL");
+                    dataSource.put("inUse", _sqlDataSourceManager.isInUse(defaultDataSourceId));
+                    
+                    dataSources.add(dataSource);
+                }
+            }
+            else
+            {
+                dataSource.put("type", "SQL");
+                dataSource.put("private", false); // Default value
+                dataSource.put("inUse", _sqlDataSourceManager.isInUse(id));
+                
+                dataSource.putAll(dataSourceDescriptor);
+                dataSource.put("id", id);
+                
+                if (!((Boolean) dataSourceDescriptor.get("private")) || includePrivate)
+                {
+                    dataSources.add(dataSource);
+                }
+            }
+        }
+        
+        return dataSources;
+    }
+    
+    /**
+     * Get all ldap data sources
+     * @param includePrivate true to include the private data sources
+     * @return the ldap data sources
+     * @throws Exception if an exception occurs while retrieving the SQL data sources
+     */
+    private List<Map<String, Object>> _getLDAPDataSources (boolean includePrivate) throws Exception
+    {
+        List<Map<String, Object>> dataSources = new ArrayList<>();
+        
+        Map<String, LDAPDataSourceDescriptor> dataSourcesDescriptions = _ldapDataSourceManager.getLDAPDataSourcesDescriptions();
+        
+        for (String id : dataSourcesDescriptions.keySet())
+        {
+            Map<String, Object> dataSource = new HashMap<>();
+            LDAPDataSourceDescriptor dataSourceDescriptor = dataSourcesDescriptions.get(id);
+         
+            dataSource.put("type", "LDAP");
+            dataSource.put("private", false); // Default value
+            dataSource.put("inUse", _ldapDataSourceManager.isInUse(id));
+            
+            dataSource.put("id", id);
+            dataSource.put("name", dataSourceDescriptor.getName());
+            dataSource.put("description", dataSourceDescriptor.getDescription());
+            dataSource.put("baseURL", dataSourceDescriptor.getBaseURL());
+            dataSource.put("useSSL", dataSourceDescriptor.isUsingSSL());
+            dataSource.put("baseDN", dataSourceDescriptor.getBaseDN());
+            dataSource.put("aliasDereferencing", dataSourceDescriptor.getAliasDereferencing());
+            dataSource.put("followReferrals", dataSourceDescriptor.isFollowingReferrals());
+            dataSource.put("authenticationMethod", dataSourceDescriptor.getAuthenticationMethod());
+            dataSource.put("adminDN", dataSourceDescriptor.getAdminDN());
+            dataSource.put("adminPassword", dataSourceDescriptor.getAdminPassword());
+            dataSource.put("private", dataSourceDescriptor.isPrivate());
+            dataSource.put("type", "LDAP");
+            dataSource.put("id", id);
+            
+            if (!dataSourceDescriptor.isPrivate() || includePrivate)
+            {
+                dataSources.add(dataSource);
+            }
+        }
+        
+        return dataSources;
+    }
+}
Index: main/plugin-core/i18n/messages_en.xml
===================================================================
--- main/plugin-core/i18n/messages_en.xml	(revision 38980)
+++ main/plugin-core/i18n/messages_en.xml	(working copy)
@@ -249,7 +249,9 @@
     
 	<!-- PARAMETER CHECKERS -->
 	<message key="PLUGINS_CORE_MAIL_CONNECTION_CHECKER_LABEL">Check the connection to the mail server</message>
-    <message key="PLUGINS_CORE_MAIL_CONNECTION_CHECKER_DESC">This test checks if the given information allows the connection to the mail server.</message>
+	<message key="PLUGINS_CORE_MAIL_CONNECTION_CHECKER_DESC">This test checks if the given information allows the connection to the mail server.</message>
+    <message key="PLUGINS_CORE_LDAP_DN_CONNECTION_CHECKER_LABEL">Check the connection to the LDAP repository</message>
+    <message key="PLUGINS_CORE_LDAP_DN_CONNECTION_CHECKER_DESC">This test checks that the given data allows to establish a connection with the LDAP, and also verifies the DN.</message>
     
 	<!-- PROFILES ACTIONS -->
 	<message key="PLUGINS_CORE_RIGHTS_ASSIGNMENT_ADDUSER_LABEL">Add profile to user</message>
@@ -296,4 +298,9 @@
     <message key="PLUGINS_CORE_CAPTCHA_CONFIG_PUBLIC_KEY_DESCRIPTION">If you use reCaptcha, you must specify the site key provided by Google.</message>
     <message key="PLUGINS_CORE_CAPTCHA_CONFIG_SECRET_KEY">Secret key reCaptcha</message>
     <message key="PLUGINS_CORE_CAPTCHA_CONFIG_SECRET_KEY_DESCRIPTION">If you use reCaptcha, you must specify the secret key provided by Google.</message>
+    <!-- +
+         | DEFAULT DATA SOURCE
+         + -->
+    <message key="PLUGINS_CORE_DEFAULT_DATASOURCE_LABEL">Internal Derby database</message>
+    <message key="PLUGINS_CORE_DEFAULT_DATASOURCE_DESCRIPTION">Internal SQL database (Derby).</message>
 </catalogue>
Index: main/plugin-core/i18n/messages_fr.xml
===================================================================
--- main/plugin-core/i18n/messages_fr.xml	(revision 38980)
+++ main/plugin-core/i18n/messages_fr.xml	(working copy)
@@ -248,6 +248,8 @@
     <!--  PARAMETER CHECKERS -->
     <message key="PLUGINS_CORE_MAIL_CONNECTION_CHECKER_LABEL">Vérifier la connexion au serveur mail</message>
     <message key="PLUGINS_CORE_MAIL_CONNECTION_CHECKER_DESC">Ce test vérifie que les informations rentrées permettent bien d'établir une connexion avec le serveur d'envoi d'emails</message>
+    <message key="PLUGINS_CORE_LDAP_DN_CONNECTION_CHECKER_LABEL">Vérifier la connexion à l'annuaire LDAP</message>
+    <message key="PLUGINS_CORE_LDAP_DN_CONNECTION_CHECKER_DESC">Ce test vérifie que les informations entrées permettent bien d'établir une connection au LDAP, et vérifie que le DN est valide.</message>
     
     <!-- PROFILES ACTIONS -->
 	<message key="PLUGINS_CORE_RIGHTS_ASSIGNMENT_ADDUSER_LABEL">Affecter à un utilisateur</message>
@@ -296,4 +298,10 @@
     <message key="PLUGINS_CORE_CAPTCHA_REFRESH">Rafraichir l'image</message>
     <message key="PLUGINS_CORE_CAPTCHA_REFRESH_NOSCRIPT">Si l'image n'est pas suffisament claire, vous pouvez rafraichir la page.</message>
     
+    <!-- +
+         | DEFAULT DATA SOURCE
+         + -->
+    <message key="PLUGINS_CORE_DEFAULT_DATASOURCE_LABEL">Base Derby interne</message>
+    <message key="PLUGINS_CORE_DEFAULT_DATASOURCE_DESCRIPTION">Base de données SQL interne (Derby).</message>   
+    
 </catalogue>
Index: main/plugin-core/plugin.xml
===================================================================
--- main/plugin-core/plugin.xml	(revision 38980)
+++ main/plugin-core/plugin.xml	(working copy)
@@ -297,9 +297,6 @@
                          class="org.ametys.core.cocoon.SourceFactoriesExtensionPoint"
                          safe="true"/>
 
-        <extension-point id="org.ametys.core.datasource.DataSourceExtensionPoint"
-                         class="org.ametys.core.datasource.DataSourceExtensionPoint"/>
-
         <extension-point id="org.ametys.runtime.cocoon.SitemapConfigurationExtensionPoint"
                          class="org.ametys.runtime.cocoon.SitemapConfigurationExtensionPoint"
                          safe="true"/>
@@ -312,6 +309,11 @@
                          class="org.ametys.core.observation.ObserverExtensionPoint">
             <!-- Observer extension point -->
         </extension-point>
+        
+        <extension-point id="org.ametys.core.datasource.sql.dbtype.SQLDatabaseTypeExtensionPoint"
+                         class="org.ametys.core.datasource.sql.dbtype.SQLDatabaseTypeExtensionPoint"
+                         safe="true"/>
+        
     </extension-points>
     
     <feature name="util.servercommhelper" safe="true">
@@ -1313,4 +1315,35 @@
             </extension>
         </extensions>
      </feature>
+    
+        
+    <!-- +
+         | SQL DATA SOURCE 
+         + -->  
+    <feature name="runtime.core.datasource.sql" safe="true">
+        <components>
+            <component role="org.ametys.core.datasource.ConnectionHelper"
+                       id="org.ametys.core.datasource.ConnectionHelper"
+                       class="org.ametys.core.datasource.ConnectionHelper"/>
+            
+            <component role="org.ametys.core.datasource.sql.SQLDataSourceManager"
+                       id="org.ametys.core.datasource.sql.SQLDataSourceManager"
+                       class="org.ametys.core.datasource.sql.SQLDataSourceManager"/>
+                       
+           <component role="org.ametys.core.datasource.sql.dbtype.SQLDatabaseTypeManager"
+                       id="org.ametys.core.datasource.sql.dbtype.SQLDatabaseTypeManager"
+                       class="org.ametys.core.datasource.sql.dbtype.SQLDatabaseTypeManager"/>
+        </components>
+    </feature>
+    
+    <!-- +
+         | LDAP DATA SOURCE 
+         + -->  
+    <feature name="runtime.core.datasource.ldap.manager" safe="true">
+        <components>
+            <component role="org.ametys.core.datasource.ldap.LDAPDataSourceManager"
+                       id="org.ametys.core.datasource.ldap.LDAPDataSourceManager"
+                       class="org.ametys.core.datasource.ldap.LDAPDataSourceManager"/>
+        </components>
+    </feature>
 </plugin>
Index: main/plugin-core/src/org/ametys/core/datasource/AbstractMyBatisDAO.java
===================================================================
--- main/plugin-core/src/org/ametys/core/datasource/AbstractMyBatisDAO.java	(revision 38980)
+++ main/plugin-core/src/org/ametys/core/datasource/AbstractMyBatisDAO.java	(working copy)
@@ -44,6 +44,8 @@
 import org.apache.ibatis.transaction.TransactionFactory;
 import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
 
+import org.ametys.core.datasource.sql.SQLDataSourceManager;
+import org.ametys.runtime.config.Config;
 import org.ametys.runtime.plugin.PluginsManager;
 import org.ametys.runtime.plugin.component.AbstractLogEnabled;
 import org.ametys.runtime.plugin.component.PluginAware;
@@ -55,10 +57,10 @@
 public abstract class AbstractMyBatisDAO extends AbstractLogEnabled implements Contextualizable, Serviceable, PluginAware, Configurable, Initializable
 {
     private SqlSessionFactory _sessionFactory;
-    private DataSourceExtensionPoint _dsExtPoint;
+    private SQLDataSourceManager _sqlDataSourceManager;
     private String _contextPath;
     private String _pluginName;
-    private String _poolName;
+    private String _poolConfigParam;
     private Set<SqlMap> _sqlMaps;
     
     public void contextualize(org.apache.avalon.framework.context.Context context) throws ContextException
@@ -70,7 +72,7 @@
     @Override
     public void service(ServiceManager manager) throws ServiceException
     {
-        _dsExtPoint = (DataSourceExtensionPoint) manager.lookup(DataSourceExtensionPoint.ROLE);
+        _sqlDataSourceManager = (SQLDataSourceManager) manager.lookup(SQLDataSourceManager.ROLE);
     }
     
     public void setPluginInfo(String pluginName, String featureName)
@@ -80,8 +82,7 @@
     
     public void configure(Configuration configuration) throws ConfigurationException
     {
-        _poolName = configuration.getChild("datasource", true).getValue(ConnectionHelper.CORE_POOL_NAME);
-        
+        _poolConfigParam = configuration.getChild("datasource", true).getValue(ConnectionHelper.CORE_POOL_CONFIG_PARAM);
         _sqlMaps = new HashSet<>();
         Configuration[] sqlMaps = configuration.getChildren("sqlMap");
         for (Configuration sqlMapConf : sqlMaps)
@@ -117,17 +118,18 @@
     
     public void initialize() throws Exception
     {
-        DataSource dataSource = _dsExtPoint.getExtension(_poolName);
+        String dataSourceId = Config.getInstance().getValueAsString(_poolConfigParam);
+        DataSource dataSource = _sqlDataSourceManager.getSQLDataSource(dataSourceId);
         
         if (dataSource == null)
         {
-            throw new ConfigurationException("Invalid pool name: " + _poolName);
+            throw new ConfigurationException("Invalid pool configuration parameter: " + _poolConfigParam);
         }
         
         SqlSessionFactoryBuilder sessionFactoryBuilder = new SqlSessionFactoryBuilder();
         
         TransactionFactory transactionFactory = new JdbcTransactionFactory();
-        Environment env = new Environment(_poolName, transactionFactory, dataSource);
+        Environment env = new Environment(_poolConfigParam, transactionFactory, dataSource);
         
         org.apache.ibatis.session.Configuration config = new org.apache.ibatis.session.Configuration(env);
         config.setCacheEnabled(true);
@@ -170,7 +172,7 @@
                 
                 if (getLogger().isInfoEnabled())
                 {
-                    getLogger().info("Initialized mybatis mapper at location '{}' for pool '{}'", mapperLocation, _poolName);
+                    getLogger().info("Initialized mybatis mapper at location '{}' for pool '{}'", mapperLocation, _poolConfigParam);
                 }
 
                 XMLMapperBuilder mapperParser = new XMLMapperBuilder(mapperStream, config, mapperLocation, config.getSqlFragments());
Index: main/plugin-core/src/org/ametys/core/datasource/ConnectionHelper.java
===================================================================
--- main/plugin-core/src/org/ametys/core/datasource/ConnectionHelper.java	(revision 38980)
+++ main/plugin-core/src/org/ametys/core/datasource/ConnectionHelper.java	(working copy)
@@ -22,22 +22,30 @@
 
 import javax.sql.DataSource;
 
+import org.apache.avalon.framework.component.Component;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import org.ametys.core.datasource.sql.SQLDataSourceManager;
+
 /**
- * Helper class to retrieve java.sql.Connection from pools
+ * Helper component used to retrieve java.sql.Connection from pools
  */
-public final class ConnectionHelper
+public final class ConnectionHelper implements Component, Serviceable
 {
-    /**
-     * Constant for core Connection pool name
-     */
-    public static final String CORE_POOL_NAME = "runtime.datasource.core.jdbc.pool";
+    /** The id of the configuration parameter corresponding to the core connection pool */
+    public static final String CORE_POOL_CONFIG_PARAM = "runtime.datasource.core.jdbc.pool";
     
-    /**
-     * Enumeration for database type.<br>
-     */
+    /** Logger for traces */
+    private static Logger _logger = LoggerFactory.getLogger(ConnectionHelper.class.getName());
+    
+    /** The manager for SQL data source */
+    private static SQLDataSourceManager _sqlDataSourceManager;
+    
+    /** Enumeration for database type.&lt;br&gt; */
     public enum DatabaseType
     {
         /** Database type is unknown */
@@ -59,51 +67,33 @@
         DATABASE_HSQLDB
     }
     
-    // Logger for traces
-    private static Logger _logger = LoggerFactory.getLogger(ConnectionHelper.class.getName());
-
-    private static DataSourceExtensionPoint _extensionPoint;
-    
-    private ConnectionHelper()
+    @Override
+    public void service(ServiceManager serviceManager) throws ServiceException
     {
-        // empty constructor
+        _sqlDataSourceManager = (SQLDataSourceManager) serviceManager.lookup(SQLDataSourceManager.ROLE); 
     }
-    
-    /**
-     * Initializes the Datasources holding the actual Connections
-     * @param extensionPoint the application DataSourceExtensionPoint 
-     */
-    public static void setExtensionPoint(DataSourceExtensionPoint extensionPoint)
-    {
-        _extensionPoint = extensionPoint;
-    }
-    
+
     /**
      * Returns a Connection from the pool.
-     * @param poolName the name of the Avalon connection pool
+     * @param id the id of the data source configuration parameter
      * @return a java.sql.Connection to query a SQL database
      */
-    public static Connection getConnection(String poolName)
+    public static Connection getConnection(String id)
     {
-        if (_extensionPoint == null)
-        {
-            throw new IllegalStateException("ComponentSelector has not been properly set up. The method setSelector(selector) must be called before getting any Connection.");
-        }
-
         DataSource dataSource;
-        Connection conn = null;
-
+        Connection connection = null;
+        
         try
         {
-            dataSource =  _extensionPoint.getExtension(poolName);
-            conn = dataSource.getConnection();
+            dataSource =  _sqlDataSourceManager.getSQLDataSource(id);
+            connection = dataSource.getConnection();
         }
         catch (SQLException e)
         {
-            throw new RuntimeException("Unable to get Connection from pool " + poolName, e);
+            throw new RuntimeException("Unable to get Connection from pool " + id, e);
         }
 
-        return conn;
+        return connection;
     }
     
     /**
Index: main/plugin-core/src/org/ametys/core/datasource/DataSourceExtensionPoint.java
===================================================================
--- main/plugin-core/src/org/ametys/core/datasource/DataSourceExtensionPoint.java	(revision 38980)
+++ main/plugin-core/src/org/ametys/core/datasource/DataSourceExtensionPoint.java	(nonexistent)
@@ -1,143 +0,0 @@
-/*
- *  Copyright 2012 Anyware Services
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package org.ametys.core.datasource;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.sql.DataSource;
-
-import org.apache.avalon.framework.activity.Disposable;
-import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.commons.dbcp.ConnectionFactory;
-import org.apache.commons.dbcp.DriverManagerConnectionFactory;
-import org.apache.commons.dbcp.PoolableConnectionFactory;
-import org.apache.commons.dbcp.PoolingDataSource;
-import org.apache.commons.pool.ObjectPool;
-import org.apache.commons.pool.impl.GenericObjectPool;
-
-import org.ametys.runtime.config.Config;
-import org.ametys.runtime.plugin.AbstractExtensionPoint;
-
-/**
- * Extension point for declaring JDBC Datasources.
- */
-public class DataSourceExtensionPoint extends AbstractExtensionPoint<DataSource> implements Disposable
-{
-    /** Avalon Role */
-    public static final String ROLE = DataSourceExtensionPoint.class.getName();
-    
-    private static final String __CONFIG_ATTRIBUTE_NAME = "runtime-config-parameter";
-    
-    private Map<String, ObjectPool> _pools = new HashMap<>();
-
-    @SuppressWarnings("unused")
-    public void addExtension(String id, String pluginName, String featureName, Configuration configuration) throws ConfigurationException
-    {
-        String driver = _getValue(configuration.getChild("driver"));
-        String url = _getValue(configuration.getChild("dburl"));
-        String user = _getValue(configuration.getChild("user"));
-        String pass = _getValue(configuration.getChild("password"));
-        
-        try
-        {
-            Class.forName(driver);
-        }
-        catch (ClassNotFoundException e)
-        {
-            throw new ConfigurationException("Specified driver class does not exist: " + driver, e);
-        }
-        
-        GenericObjectPool connectionPool = new GenericObjectPool();
-        connectionPool.setMaxActive(-1);
-        connectionPool.setMaxIdle(10);
-        connectionPool.setMinIdle(2);
-        connectionPool.setTestOnBorrow(true);
-        connectionPool.setTestOnReturn(false);
-        connectionPool.setTestWhileIdle(true);
-        connectionPool.setTimeBetweenEvictionRunsMillis(1000 * 60 * 30);
-        
-        ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(url, user, pass);
-        new PoolableConnectionFactory(connectionFactory, connectionPool, null, _getValidationQuery(driver), false, true);
-        PoolingDataSource dataSource = new PoolingDataSource(connectionPool);
-        
-        _pools.put(id, connectionPool);
-        _extensions.put(id, dataSource);
-    }
-    
-    private String _getValue(Configuration configuration)
-    {
-        String configName = configuration.getAttribute(__CONFIG_ATTRIBUTE_NAME, null);
-        String value;
-        
-        if (configName == null)
-        {
-            // valeur du noeud courant
-            value = configuration.getValue(null);
-        }
-        else
-        {
-            value = Config.getInstance().getValueAsString(configName);
-        }
-        
-        return value;
-    }
-    
-    private String _getValidationQuery(String driver)
-    {
-        if ("oracle.jdbc.driver.OracleDriver".equals(driver) || "oracle.jdbc.OracleDriver".equals(driver))
-        {
-            return "SELECT 1 FROM DUAL";
-        }
-        else if ("org.apache.derby.jdbc.EmbeddedDriver".equals(driver))
-        {
-            return "SELECT 1 FROM SYS.SYSTABLES";
-        }
-        else if ("org.hsqldb.jdbcDriver".equals(driver) || "org.hsqldb.jdbc.JDBCDriver".equals(driver))
-        {
-            return "SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS";
-        }
-        else
-        {
-            return "SELECT 1";
-        }
-    }
-
-    public void initializeExtensions() throws Exception
-    {
-        ConnectionHelper.setExtensionPoint(this);
-    }
-    
-    @Override
-    public void dispose()
-    {
-        for (String id : _pools.keySet())
-        {
-            ObjectPool pool = _pools.get(id);
-            
-            try
-            {
-                pool.close();
-            }
-            catch (Exception e)
-            {
-                getLogger().warn("Unable to close pool when disposing", e);
-            }
-        }
-    }
-}
Index: main/plugin-core/src/org/ametys/core/datasource/ldap/LDAPDataSourceManager.java
===================================================================
--- main/plugin-core/src/org/ametys/core/datasource/ldap/LDAPDataSourceManager.java	(revision 0)
+++ main/plugin-core/src/org/ametys/core/datasource/ldap/LDAPDataSourceManager.java	(revision 0)
@@ -0,0 +1,468 @@
+/*
+ *  Copyright 2015 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.ametys.core.datasource.ldap;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.avalon.framework.activity.Initializable;
+import org.apache.avalon.framework.component.Component;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.xml.XMLUtils;
+import org.xml.sax.helpers.AttributesImpl;
+
+import org.ametys.core.util.StringUtils;
+import org.ametys.runtime.config.Config;
+import org.ametys.runtime.config.ConfigManager;
+import org.ametys.runtime.parameter.ParameterHelper.ParameterType;
+import org.ametys.runtime.plugin.component.AbstractLogEnabled;
+
+/**
+ * Avalon component handling the LDAP data sources. It manages the file $AMETYS_HOME/datasources-ldap.xml 
+ */
+public class LDAPDataSourceManager extends AbstractLogEnabled implements Component, Initializable
+{
+    /** Avalon Role */
+    public static final String ROLE = LDAPDataSourceManager.class.getName();
+    
+    /** The path of the datasources-ldap.xml file */
+    private static String _ldapDataSourcesFilePath;
+    
+    /** The representation of the datasources-ldap.xml file */
+    private Map<String, LDAPDataSourceDescriptor> _dataSourcesDescriptions;
+    
+    /**
+     * Set the name of the file that will be read by the manager
+     * @param fileName the name of the file
+     */
+    public static void setFilename(String fileName)
+    {
+        _ldapDataSourcesFilePath = fileName;
+    }
+    
+    @Override
+    public void initialize() throws Exception
+    {
+        _dataSourcesDescriptions = new HashMap<> ();
+        
+        File ldapDataSourceFile = new File(_ldapDataSourcesFilePath);
+        if (!ldapDataSourceFile.exists())
+        {
+            ldapDataSourceFile.getParentFile().mkdirs();
+            ldapDataSourceFile.createNewFile();
+        }
+        
+        if (ldapDataSourceFile.length() != 0)
+        {
+            Configuration configuration;
+            try (InputStream is = new FileInputStream(ldapDataSourceFile))
+            {
+                configuration = new DefaultConfigurationBuilder().build(is);
+            }
+            
+            // Initialize the connection pools
+            for (Configuration datasourceConfiguration : configuration.getChildren("datasource"))
+            {
+                String id = datasourceConfiguration.getAttribute("id");
+                
+                String name = datasourceConfiguration.getChild("name").getValue();
+                String description = datasourceConfiguration.getChild("description").getValue("");
+                String baseURL = datasourceConfiguration.getChild("baseURL").getValue();
+                String useSSL = datasourceConfiguration.getChild("useSSL").getValue("");
+                String baseDN = datasourceConfiguration.getChild("baseDN").getValue("");
+                String aliasDereferencing = datasourceConfiguration.getChild("aliasDereferencing").getValue("");
+                String followReferrals = datasourceConfiguration.getChild("followReferrals").getValue("");
+                String authenticationMethod = datasourceConfiguration.getChild("authenticationMethod").getValue("");
+                String adminDN = datasourceConfiguration.getChild("adminDN").getValue("");
+                String adminPassword = datasourceConfiguration.getChild("adminPassword").getValue("");
+                String privateAsString = datasourceConfiguration.getChild("private").getValue("");
+                
+                boolean isUsingSSL = useSSL.equals("true");
+                boolean isFollowingReferrals = followReferrals.equals("true");
+                boolean isPrivate = privateAsString.equals("true");
+                
+                _dataSourcesDescriptions.put(id, new LDAPDataSourceDescriptor(name, description, baseURL, isUsingSSL, baseDN, aliasDereferencing, isFollowingReferrals, authenticationMethod, adminDN, adminPassword, isPrivate));
+            }
+        }
+    }
+
+    /**
+     * Get the parameters of a LDAP data source (label, driver, url, login, password) 
+     * @param id the id of the wanted data source
+     * @return the data source's parameters values
+     * @throws Exception if an exception occurred when retrieving the ldap data source parameters
+     */
+    public LDAPDataSourceDescriptor getLDAPDataSourceDescription (String id) throws Exception
+    {
+        return _dataSourcesDescriptions.get(id);
+    }
+    
+    /**
+     * Get the existing LDAP data sources as JSON 
+     * @return the LDAP data sources descriptors
+     */
+    public Map<String, LDAPDataSourceDescriptor> getLDAPDataSourcesDescriptions ()
+    {
+        return _dataSourcesDescriptions;
+    }
+    
+    /**
+     * Determines if a data source is in use by a configuration parameter
+     * @param id The id of data source to check
+     * @return true if the data source is in use
+     */
+    public boolean isInUse (String id)
+    {
+        Config config = Config.getInstance();
+        if (config != null)
+        {
+            for (String dataSourceId : ConfigManager.getInstance().getIdsByType(ParameterType.DATASOURCE))
+            {
+                String dataSourceValue = config.getValueAsString(dataSourceId);
+                if (dataSourceValue != null && dataSourceValue.equals(id))
+                {
+                    return true;
+                }
+            }
+        }
+        
+        return false;
+    }
+    
+    /**
+     * Save a single data source
+     * @param parameters The parameters of the data source
+     * @throws Exception if an error occurs during the saving process
+     * @return the id of the created/edited data source 
+     */
+    public String saveLDAPDataSource (Map<String, Object> parameters) throws Exception
+    {
+        String id = (String) parameters.get("id");
+        
+        String name = (String) parameters.get("name");
+        String description = (String) parameters.get("description");
+        String baseURL = (String) parameters.get("baseURL");
+        boolean useSSL = (Boolean) parameters.get("useSSL");
+        String baseDN = (String) parameters.get("baseDN");
+        String aliasDereferencing = (String) parameters.get("aliasDereferencing");
+        boolean followReferrals = (Boolean) parameters.get("followReferrals");
+        String authenticationMethod = (String) parameters.get("authenticationMethod");
+        String adminDN = (String) parameters.get("adminDN");
+        String adminPassword = (String) parameters.get("adminPassword");
+        boolean isPrivate = (Boolean) parameters.get("private");
+        
+        LDAPDataSourceDescriptor ldapDataSourceDescriptor = null;
+        if (!_dataSourcesDescriptions.containsKey(id))
+        {
+            ldapDataSourceDescriptor = new LDAPDataSourceDescriptor(name, description, baseURL, useSSL, baseDN, aliasDereferencing, followReferrals, authenticationMethod, adminDN, adminPassword, isPrivate);
+            id = _addLDAPDataSource(ldapDataSourceDescriptor);
+        }
+        else
+        {
+            if (adminPassword == null)
+            {
+                // Get the recorded password : null password => saved password
+                adminPassword = _dataSourcesDescriptions.get(id).getAdminPassword();
+            }
+            ldapDataSourceDescriptor = new LDAPDataSourceDescriptor(name, description, baseURL, useSSL, baseDN, aliasDereferencing, followReferrals, authenticationMethod, adminDN, adminPassword, isPrivate);
+            _dataSourcesDescriptions.put(id, ldapDataSourceDescriptor);
+        }
+        
+        // Save changes in the file
+        _save();
+        
+        return id;
+    }
+    
+    /**
+     * Delete a data source with its id
+     * @param id The id of the data source to delete
+     * @throws Exception if an error occurs during the saving process 
+     */
+    public void removeLDAPDataSource (String id) throws Exception
+    {
+        _dataSourcesDescriptions.remove(id);
+        _save();
+    }
+    
+    /**
+     * Add a LDAP data source
+     * @param parameters the parameters of the new data source
+     * @return the id of the created data source 
+     */
+    private String _addLDAPDataSource(LDAPDataSourceDescriptor ldapDataSourceDescriptor)
+    {
+        String id = "LDAP-" + StringUtils.generateKey();
+        _dataSourcesDescriptions.put(id, ldapDataSourceDescriptor);
+        
+        return id;
+    }
+    
+    /**
+     * Save the LDAP data sources in the datasources-ldap.xml file
+     * @throws TransformerFactoryConfigurationError if an error occurs while configuring the transformer factory
+     * @throws ProcessingException if an error occurs during the saving process
+     */
+    private void _save() throws TransformerFactoryConfigurationError, ProcessingException
+    {
+        File ldapDataSourcesFile = new File(_ldapDataSourcesFilePath);
+        try
+        {
+            // Create file if it doest not already exist
+            if (!ldapDataSourcesFile.exists())
+            {
+                ldapDataSourcesFile.getParentFile().mkdirs();
+                ldapDataSourcesFile.createNewFile();
+            }
+            
+            // create a transformer for saving sax into a file
+            TransformerHandler th = ((SAXTransformerFactory) TransformerFactory.newInstance()).newTransformerHandler();
+
+            // create the result where to write
+            try (OutputStream os = new FileOutputStream(ldapDataSourcesFile))
+            {
+                StreamResult sResult = new StreamResult(os);
+                th.setResult(sResult);
+    
+                // create the format of result
+                Properties format = new Properties();
+                format.put(OutputKeys.METHOD, "xml");
+                format.put(OutputKeys.INDENT, "yes");
+                format.put(OutputKeys.ENCODING, "UTF-8");
+                th.getTransformer().setOutputProperties(format);
+    
+                // Send SAX events
+                th.startDocument();
+                XMLUtils.startElement(th, "datasources");
+                
+                AttributesImpl idAttr = new AttributesImpl();
+                
+                for (String id : _dataSourcesDescriptions.keySet())
+                {
+                    LDAPDataSourceDescriptor ldapDataSourceDescriptor = _dataSourcesDescriptions.get(id);
+                    
+                    idAttr.addAttribute("", "id", "id", "CDATA", id);
+                    XMLUtils.startElement(th, "datasource", idAttr);
+                    XMLUtils.createElement(th, "name", ldapDataSourceDescriptor.getName());
+                    XMLUtils.createElement(th, "description", ldapDataSourceDescriptor.getDescription());
+                    XMLUtils.createElement(th, "baseURL", ldapDataSourceDescriptor.getBaseURL());
+
+                    String isUsingSSL = ldapDataSourceDescriptor.isUsingSSL() ? "true" : "false";
+                    XMLUtils.createElement(th, "private", isUsingSSL);
+                    
+                    XMLUtils.createElement(th, "baseDN", ldapDataSourceDescriptor.getBaseDN());
+                    XMLUtils.createElement(th, "aliasDereferencing", ldapDataSourceDescriptor.getAliasDereferencing());
+                    
+                    String isFollowingReferrals = ldapDataSourceDescriptor.isFollowingReferrals() ? "true" : "false";
+                    XMLUtils.createElement(th, "private", isFollowingReferrals);
+                    
+                    XMLUtils.createElement(th, "authenticationMethod", ldapDataSourceDescriptor.getAuthenticationMethod());
+                    
+                    String adminDN = ldapDataSourceDescriptor.getAdminDN();
+                    XMLUtils.createElement(th, "adminDN", adminDN != null ? adminDN : "");
+                    
+                    String password = ldapDataSourceDescriptor.getAdminPassword();
+                    XMLUtils.createElement(th, "adminPassword", password != null ? password : "");
+                    
+                    String isPrivate = ldapDataSourceDescriptor.isPrivate() ? "true" : "false";
+                    XMLUtils.createElement(th, "private", isPrivate);
+                    XMLUtils.endElement(th, "datasource");
+                    idAttr.clear();
+                }
+                
+                XMLUtils.endElement(th, "datasources");
+                th.endDocument();
+            }
+        }
+        catch (Exception e)
+        {
+            throw new ProcessingException("Unable to save the ldap data sources values", e);
+        }
+    }
+    
+    /**
+     * Object representation of a LDAP data source
+     */
+    public class LDAPDataSourceDescriptor 
+    {
+        /** The name of the data source */
+        private String _name;
+        /** The optional description of the data source */
+        private String _description;
+        /** URL connection to the ldap server. */
+        private String _baseURL;
+        /** Use ssl for connecting to ldap server. */
+        private boolean _useSSL;
+        /** Base DN to the ldap server. */
+        private String _baseDN;
+        /** Alias dereferencing method */
+        private String _aliasDereferencing;
+        /** Enable following referrals. */
+        private boolean _followReferrals;
+        /** Authentication method used. */
+        private String _authenticationMethod;
+        /** Distinguished name of the admin used for searching. */
+        private String _adminDN;
+        /** Password associated with the admin. */
+        private String _adminPassword;
+        /** Is the data source private ? */
+        private boolean _isPrivate;
+        
+        /**
+         * Constructor for a LDAP data source descriptor
+         * @param name the name of the data source
+         * @param description the description of the data source
+         * @param baseURL the base URL of the data source
+         * @param useSSL is the data source using a secured connection ?
+         * @param baseDN the base domain name of the data source
+         * @param aliasDereferencing the alias dereferencing method used by the data source
+         * @param followReferrals is the data source following referrals ?
+         * @param authenticationMethod the authentication method used by the data source
+         * @param adminDN the administrator domain name of the data source
+         * @param adminPassword the password of the administrator
+         * @param isPrivate is the data source private ?
+         */
+        public LDAPDataSourceDescriptor(String name, String description, String baseURL, boolean useSSL, String baseDN, String aliasDereferencing, boolean followReferrals,
+                String authenticationMethod, String adminDN, String adminPassword, boolean isPrivate)
+        {
+            this._name = name;
+            this._description = description;
+            this._baseURL = baseURL;
+            this._useSSL = useSSL;
+            this._baseDN = baseDN;
+            this._aliasDereferencing = aliasDereferencing;
+            this._followReferrals = followReferrals;
+            this._authenticationMethod = authenticationMethod;
+            this._adminDN = adminDN;
+            this._adminPassword = adminPassword;
+            this._isPrivate = isPrivate;
+        }
+
+        /**
+         * Get the name of the data source
+         * @return the name of the data source
+         */
+        public String getName()
+        {
+            return _name;
+        }
+        
+        /**
+         * Get the description of the data source
+         * @return the description of the data source
+         */
+        public String getDescription()
+        {
+            return _description;
+        }
+        
+        /**
+         * Get the URL of the LDAP server
+         * @return the url of the LDAP server
+         */
+        public String getBaseURL()
+        {
+            return _baseURL;
+        }
+        
+        /***
+         * Is the data source using a secured connection ?
+         * @return true if the data source is using a secured connection
+         */
+        public boolean isUsingSSL()
+        {
+            return _useSSL;
+        }
+        
+        /**
+         * Get the base domain name of the data source
+         * @return the base domain name of the data source
+         */
+        public String getBaseDN()
+        {
+            return _baseDN;
+        }
+        
+        /**
+         * Get the alias dereferencing method used by the data source
+         * @return the alias dereferencing method used by the data source
+         */
+        public String getAliasDereferencing()
+        {
+            return _aliasDereferencing;
+        }
+        
+        /**
+         * Is the data source following referrals ?
+         * @return true if the data source is following referrals
+         */
+        public boolean isFollowingReferrals()
+        {
+            return _followReferrals;
+        }
+        
+        /**
+         * Get the authentication method used by the data source
+         * @return the authentication method used by the data source
+         */
+        public String getAuthenticationMethod()
+        {
+            return _authenticationMethod;
+        }
+        
+        /**
+         * Get the admin domain name
+         * @return the admin domain name
+         */
+        public String getAdminDN()
+        {
+            return _adminDN;
+        }
+        
+        /**
+         * Get the admin password
+         * @return the admin password
+         */
+        public String getAdminPassword()
+        {
+            return _adminPassword;
+        }
+        
+        /**
+         * Is the data source private ?
+         * @return true if the data source is private
+         */
+        public boolean isPrivate()
+        {
+            return _isPrivate;
+        }
+    }
+}
Index: main/plugin-core/src/org/ametys/core/datasource/sql/SQLDataSourceManager.java
===================================================================
--- main/plugin-core/src/org/ametys/core/datasource/sql/SQLDataSourceManager.java	(revision 0)
+++ main/plugin-core/src/org/ametys/core/datasource/sql/SQLDataSourceManager.java	(revision 0)
@@ -0,0 +1,556 @@
+/*
+ *  Copyright 2015 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.ametys.core.datasource.sql;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.sql.DataSource;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.avalon.framework.activity.Disposable;
+import org.apache.avalon.framework.activity.Initializable;
+import org.apache.avalon.framework.component.Component;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.xml.XMLUtils;
+import org.apache.commons.dbcp2.ConnectionFactory;
+import org.apache.commons.dbcp2.DriverManagerConnectionFactory;
+import org.apache.commons.dbcp2.PoolableConnection;
+import org.apache.commons.dbcp2.PoolableConnectionFactory;
+import org.apache.commons.dbcp2.PoolingDataSource;
+import org.apache.commons.pool2.ObjectPool;
+import org.apache.commons.pool2.impl.GenericObjectPool;
+import org.xml.sax.helpers.AttributesImpl;
+
+import org.ametys.core.util.StringUtils;
+import org.ametys.plugins.core.impl.checker.SQLConnectionChecker;
+import org.ametys.runtime.config.Config;
+import org.ametys.runtime.config.ConfigManager;
+import org.ametys.runtime.i18n.I18nizableText;
+import org.ametys.runtime.parameter.ParameterChecker;
+import org.ametys.runtime.parameter.ParameterHelper.ParameterType;
+import org.ametys.runtime.plugin.PluginsManager;
+import org.ametys.runtime.plugin.component.AbstractLogEnabled;
+import org.ametys.runtime.servlet.RuntimeConfig;
+
+/**
+ * Avalon component handling the SQL data sources. It manages the file $AMETYS_HOME/datasources-sql.xml 
+ */
+public class SQLDataSourceManager extends AbstractLogEnabled implements Component, Disposable, Initializable
+{
+    /** Avalon Role */
+    public static final String ROLE = SQLDataSourceManager.class.getName();
+    
+    /** The id of the default data source */
+    private static final String __DEFAULT_DATASOURCE_ID = "SQL-derby-internal";
+    
+    /** The key for the name of the default data source */
+    private static final I18nizableText __DEFAULT_DATASOURCE_NAME = new I18nizableText("plugin.core", "PLUGINS_CORE_DEFAULT_DATASOURCE_LABEL");
+    
+    /** The key for the description of the default data source */
+    private static final I18nizableText __DEFAULT_DATASOURCE_DESCRIPTION = new I18nizableText("plugin.core", "PLUGINS_CORE_DEFAULT_DATASOURCE_DESCRIPTION");
+
+    /** The driver of the default data source */
+    private static final String __DEFAULT_DATASOURCE_DRIVER = "org.apache.derby.jdbc.EmbeddedDriver";
+    
+    /** The path of the file to use */
+    private static String _sqlDataSourcesFilePath;
+
+    /** The map representation of the datasources-sql.xml file */
+    private Map<String, Map<String, Object>> _dataSourcesDescriptions;
+    
+    /** The mapping of the datasources with their ids */
+    private Map<String, DataSource> _dataSources;
+    
+    /** The connection pools */
+    private Map<String, ObjectPool> _pools = new HashMap<>();
+    
+    /**
+     * Set the name of the file that will be read by the manager
+     * @param fileName the name of the file
+     */
+    public static void setFilename(String fileName)
+    {
+        _sqlDataSourcesFilePath = fileName;
+    }
+    
+    @Override
+    public void dispose()
+    {
+        for (String id : _pools.keySet())
+        {
+            _dispose(id);
+        }
+    }
+
+    @Override
+    public void initialize() throws Exception
+    {
+        _dataSources = new HashMap<>();
+        _dataSourcesDescriptions = new HashMap<> ();
+        
+        File sqlDatasourcesFile = new File(_sqlDataSourcesFilePath);
+        if (!sqlDatasourcesFile.exists())
+        {
+            sqlDatasourcesFile.getParentFile().mkdirs();
+            sqlDatasourcesFile.createNewFile();
+        }
+        
+        // Initialize the default SQL data source
+        String defaultDataSourceURL = "jdbc:derby:" + RuntimeConfig.getInstance().getAmetysHome() + "/internal-db;create=true";
+        _initializeDataSource(__DEFAULT_DATASOURCE_ID, "", "", __DEFAULT_DATASOURCE_DRIVER, defaultDataSourceURL, null, null, false);
+        
+        if (sqlDatasourcesFile.length() != 0)
+        {
+            Configuration configuration;
+            try (InputStream is = new FileInputStream(sqlDatasourcesFile))
+            {
+                configuration = new DefaultConfigurationBuilder().build(is);
+            }
+            
+            // Initialize the connection pools
+            for (Configuration datasourceConfiguration : configuration.getChildren("datasource"))
+            {
+                String id = datasourceConfiguration.getAttribute("id");
+                
+                String driver = datasourceConfiguration.getChild("driver").getValue();
+                String url = datasourceConfiguration.getChild("url").getValue();
+                String user = datasourceConfiguration.getChild("user").getValue("");
+                String password = datasourceConfiguration.getChild("password").getValue("");
+
+                // Validate the used SQL data sources if not already in safe mode
+                if (isInUse(id) && !PluginsManager.getInstance().isSafeMode())
+                {
+                    Map<String, String> testParameters = new HashMap<> ();
+                    testParameters.put("driver", driver);
+                    testParameters.put("url", url);
+                    testParameters.put("user", user);
+                    testParameters.put("password", password);
+                    
+                    ParameterChecker paramChecker = new SQLConnectionChecker();
+                    try
+                    {
+                        paramChecker.check(testParameters);
+                    }
+                    catch (Throwable t)
+                    {
+                        throw new IllegalArgumentException("The SQL data source of id '" + id + "' is not valid", t);
+                    } 
+                }
+                
+                String name = datasourceConfiguration.getChild("name").getValue();
+                String description = datasourceConfiguration.getChild("description").getValue("");
+                String isPrivate = datasourceConfiguration.getChild("private").getValue("");
+                
+                _initializeDataSource(id, name, description, driver, url, user, password, isPrivate.equals("true"));
+            }
+        }
+    }
+
+    /**
+     * Get the id of the default data source
+     * @return the id of the default data source
+     */
+    public String getDefaultDataSourceId()
+    {
+        return __DEFAULT_DATASOURCE_ID;
+    }
+    
+    /**
+     * Get the i18n key for the default data source name
+     * @return the i18n key for the default data source name
+     */
+    public I18nizableText getDefaultDataSourceName()
+    {
+        return __DEFAULT_DATASOURCE_NAME;
+    }
+    
+    /**
+     * Get the i18n key for the default data source description
+     * @return the i18n key for the default data source description
+     */
+    public I18nizableText getDefaultDataSourceDescription()
+    {
+        return __DEFAULT_DATASOURCE_DESCRIPTION;
+    }
+    
+    /**
+     * Get the existing SQL data sources
+     * @return the SQL data sources
+     */
+    public Map<String, DataSource> getSQLDataSources ()
+    {
+        return _dataSources;
+    }
+    
+    /**
+     * Get the SQL data source by its identifier
+     * @param id The id of data source
+     * @return the SQL data source
+     */
+    public DataSource getSQLDataSource (String id)
+    {
+        return _dataSources.get(id);
+    }
+    
+    /**
+     * Get the parameters of a SQL data source (label, driver, url, login, password) 
+     * @param id the id of the wanted data source
+     * @return the data source's parameters values
+     * @throws Exception if an exception occurred when retrieving the sql data source parameters
+     */
+    public Map<String, Object> getSQLDataSourceDescription (String id) throws Exception
+    {
+        return _dataSourcesDescriptions.get(id);
+    }
+    
+    /**
+     * Get the existing SQL data sources as JSON 
+     * @return the SQL data sources JSON representation
+     */
+    public Map<String, Map<String, Object>> getSQLDataSourcesDescriptions ()
+    {
+        return _dataSourcesDescriptions;
+    }
+    
+    /**
+     * Determines if a data source is in use by a configuration parameter
+     * @param id The id of data source to check
+     * @return true if the data source is in use
+     */
+    public boolean isInUse (String id)
+    {
+        Config config = Config.getInstance();
+        if (config != null)
+        {
+            for (String dataSourceId : ConfigManager.getInstance().getIdsByType(ParameterType.DATASOURCE))
+            {
+                String dataSourceValue = config.getValueAsString(dataSourceId);
+                if (dataSourceValue != null && dataSourceValue.equals(id))
+                {
+                    return true;
+                }
+            }
+        }
+        
+        return false;
+    }
+    
+    /**
+     * Returns a Connection from the pool.
+     * @param poolId the id of the connection pool
+     * @return a java.sql.Connection to query a SQL database
+     */
+    public Connection getConnection(String poolId)
+    {
+        DataSource dataSource;
+        Connection connection = null;
+
+        try
+        {
+            dataSource =  getSQLDataSource(poolId);
+            connection = dataSource.getConnection();
+        }
+        catch (SQLException e)
+        {
+            throw new RuntimeException("Unable to get Connection from pool " + poolId, e);
+        }
+
+        return connection;
+    }
+    
+    /**
+     * Save a single data source
+     * @param parameters The parameters of the data source
+     * @throws Exception if an error occurs during the saving process
+     * @return the id of the created/edited data source 
+     */
+    public String saveSQLDataSource (Map<String, Object> parameters) throws Exception
+    {
+        String id = (String) parameters.get("id");
+        if (!_dataSourcesDescriptions.containsKey(id))
+        {
+            id = _addSQLDataSource(parameters);
+        }
+        else
+        {
+            if (parameters.get("password") == null)
+            {
+                // Get the recorded password : null password => saved password
+                parameters.put("password", _dataSourcesDescriptions.get(id).get("password"));
+            }
+            
+            _editSQLDataSource(parameters);
+        }
+        
+        // Update the stored data
+        _createAndSavePool((String) parameters.get("id"), (String) parameters.get("driver"), (String) parameters.get("url"), (String) parameters.get("user"), (String) parameters.get("password"));
+        
+        // Save changes in the file
+        _save();
+        
+        return id;
+    }
+    
+    /**
+     * Delete a data source with its id
+     * @param id The id of the data source to delete
+     * @throws Exception if an error occurs during the saving process 
+     */
+    public void removeSQLDataSource (String id) throws Exception
+    {
+        _deleteSQLDataSource(id);
+        _save();
+    }
+    
+    /**
+     * Add a SQL data source
+     * @param parameters the parameters of the new data source
+     * @return the id of the created data source 
+     */
+    private String _addSQLDataSource(Map<String, Object> parameters)
+    {
+        String id = "SQL-" + StringUtils.generateKey();
+        _dataSourcesDescriptions.put(id, parameters);
+
+        return id;
+    }
+
+    /**
+     * Edit a SQL data source
+     * @param parameters the parameters of the data source to edit
+     */
+    private void _editSQLDataSource(Map<String, Object> parameters)
+    {
+        String id = (String) parameters.get("id");
+        _dataSourcesDescriptions.put(id, parameters);
+    }
+    
+    /**
+     * Initialize a data source 
+     * @param id the id of the data source
+     * @param name the name of the data source
+     * @param description the description of the data source
+     * @param driver the driver of the data source
+     * @param url the url of the data source
+     * @param user the user. can be null
+     * @param password the password. can be null
+     * @param isPrivate is this data source private ?
+     */
+    private void _initializeDataSource(String id, String name, String description, String driver, String url, String user, String password, boolean isPrivate)
+    {
+        _createAndSavePool(id, driver, url, user, password);
+        
+        // Keep a map representation of the XML file to limit the read access
+        Map<String, Object> parameters = new HashMap<> ();
+        parameters.put("name", name);
+        parameters.put("description", description);
+        parameters.put("driver", driver);
+        parameters.put("url", url);
+        parameters.put("user", user);
+        parameters.put("password", password);
+        parameters.put("private", isPrivate);
+        
+        _dataSourcesDescriptions.put(id, parameters);
+    }
+    
+    /**
+     * Create and store the pools/data sources
+     * @param id the id of the data source
+     * @param driver the driver used by the data source 
+     * @param url the url where to find the data source
+     * @param user the login
+     * @param password the corresponding password
+     */
+    private void _createAndSavePool(String id, String driver, String url, String user, String password)
+    {
+        ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(url, user, password);
+        PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory, null);
+        
+        GenericObjectPool<PoolableConnection> connectionPool = new GenericObjectPool<>(poolableConnectionFactory);
+        connectionPool.setMaxTotal(-1);
+        connectionPool.setMaxIdle(10);
+        connectionPool.setMinIdle(2);
+        connectionPool.setTestOnBorrow(true);
+        connectionPool.setTestOnReturn(false);
+        connectionPool.setTestWhileIdle(true);
+        connectionPool.setTimeBetweenEvictionRunsMillis(1000 * 60 * 30);
+        
+        poolableConnectionFactory.setPool(connectionPool);
+        poolableConnectionFactory.setValidationQuery(_getValidationQuery(driver));
+        poolableConnectionFactory.setDefaultAutoCommit(true);
+        poolableConnectionFactory.setDefaultReadOnly(false);
+                 
+        PoolingDataSource<PoolableConnection> dataSource = new PoolingDataSource<>(connectionPool);
+        
+        // make sure the previous connection has been disposed
+        if (_pools.containsKey(id))
+        {
+            _dispose(id);
+        }
+        
+        // Store the connection pools and the data sources
+        _pools.put(id, connectionPool);
+        _dataSources.put(id, dataSource);
+    }
+    
+    /**
+     * Delete a SQL data source
+     * @param id the id of the data source to delete
+     */
+    private void _deleteSQLDataSource(String id)
+    {
+        _dataSourcesDescriptions.remove(id);
+        _dataSources.remove(id);
+        
+        // Dispose of the corresponding connection before removing it
+        _dispose(id);
+    }
+    
+    /**
+     * Save the SQL data sources in the datasources-sql.xml file
+     * @throws TransformerFactoryConfigurationError if an error occurs while configuring the transformer factory
+     * @throws ProcessingException if an error occurs during the saving process
+     */
+    private void _save() throws TransformerFactoryConfigurationError, ProcessingException
+    {
+        File sqlDatasourcesFile = new File(RuntimeConfig.getInstance().getAmetysHome() + "/datasources-sql.xml");
+        try
+        {
+            // Create file if it doest not already exist
+            if (!sqlDatasourcesFile.exists())
+            {
+                sqlDatasourcesFile.getParentFile().mkdirs();
+                sqlDatasourcesFile.createNewFile();
+            }
+            
+            // create a transformer for saving sax into a file
+            TransformerHandler th = ((SAXTransformerFactory) TransformerFactory.newInstance()).newTransformerHandler();
+
+            // create the result where to write
+            try (OutputStream os = new FileOutputStream(sqlDatasourcesFile))
+            {
+                StreamResult sResult = new StreamResult(os);
+                th.setResult(sResult);
+    
+                // create the format of result
+                Properties format = new Properties();
+                format.put(OutputKeys.METHOD, "xml");
+                format.put(OutputKeys.INDENT, "yes");
+                format.put(OutputKeys.ENCODING, "UTF-8");
+                th.getTransformer().setOutputProperties(format);
+    
+                // Send SAX events
+                th.startDocument();
+                XMLUtils.startElement(th, "datasources");
+                
+                AttributesImpl idAttr = new AttributesImpl();
+                
+                // Do not save the default data source in the file
+                Set<String> dataSourceDescriptionKeys = _dataSourcesDescriptions.keySet();
+                for (String id : dataSourceDescriptionKeys)
+                {
+                    if (id != __DEFAULT_DATASOURCE_ID)
+                    {
+                        Map<String, Object> datasourceParameters = _dataSourcesDescriptions.get(id);
+                        
+                        idAttr.addAttribute("", "id", "id", "CDATA", id);
+                        XMLUtils.startElement(th, "datasource", idAttr);
+                        XMLUtils.createElement(th, "name", (String) datasourceParameters.get("name"));
+                        XMLUtils.createElement(th, "description", (String) datasourceParameters.get("description"));
+                        XMLUtils.createElement(th, "driver", (String) datasourceParameters.get("driver"));
+                        XMLUtils.createElement(th, "url", (String) datasourceParameters.get("url"));
+                        XMLUtils.createElement(th, "user", (String) datasourceParameters.get("user"));
+                        
+                        String password = (String) datasourceParameters.get("password");
+                        XMLUtils.createElement(th, "password", password != null ? password : "");
+                        
+                        String isPrivate = (Boolean) datasourceParameters.get("private") ? "true" : "false";
+                        XMLUtils.createElement(th, "private", isPrivate);
+                        XMLUtils.endElement(th, "datasource");
+                        idAttr.clear();
+                    }
+                }
+                
+                XMLUtils.endElement(th, "datasources");
+                th.endDocument();
+            }
+        }
+        catch (Exception e)
+        {
+            throw new ProcessingException("Unable to save the sql data sources values", e);
+        }
+    }
+    
+    /**
+     * Get the appropriate validation query
+     * @param driver the driver 
+     * @return the validation query
+     */
+    private String _getValidationQuery(String driver)
+    {
+        if ("oracle.jdbc.driver.OracleDriver".equals(driver) || "oracle.jdbc.OracleDriver".equals(driver))
+        {
+            return "SELECT 1 FROM DUAL";
+        }
+        else if ("org.apache.derby.jdbc.EmbeddedDriver".equals(driver))
+        {
+            return "SELECT 1 FROM SYS.SYSTABLES";
+        }
+        else if ("org.hsqldb.jdbcDriver".equals(driver) || "org.hsqldb.jdbc.JDBCDriver".equals(driver))
+        {
+            return "SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS";
+        }
+        else
+        {
+            return "SELECT 1";
+        }
+    }
+    
+    /**
+     * Dispose of a connection pool
+     * @param id the id of the connection pool to dispose of
+     */
+    private void _dispose(String id)
+    {
+        try
+        {
+            _pools.get(id).close();
+        }
+        catch (Exception e)
+        {
+            getLogger().warn("Unable to close the edited connection pool", e);
+        }        
+        
+        _pools.remove(id);
+    }
+}
Index: main/plugin-core/src/org/ametys/core/datasource/sql/dbtype/SQLDatabaseType.java
===================================================================
--- main/plugin-core/src/org/ametys/core/datasource/sql/dbtype/SQLDatabaseType.java	(revision 0)
+++ main/plugin-core/src/org/ametys/core/datasource/sql/dbtype/SQLDatabaseType.java	(revision 0)
@@ -0,0 +1,55 @@
+/*
+ *  Copyright 2015 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.ametys.core.datasource.sql.dbtype;
+
+import org.ametys.runtime.i18n.I18nizableText;
+
+/**
+ * Interface for the SQL database types
+ */
+public interface SQLDatabaseType
+{
+    /**
+     * Get the id of the database type.
+     * @return the id. Can not be null.
+     */
+    public String getId();
+    
+    /**
+     * Get the label of the database type.
+     * @return the label
+     */
+    public I18nizableText getLabel();
+    
+    /**
+     * Get the driver of the database type.
+     * @return the driver. Can not be null.
+     */
+    public String getDriver();
+    
+    /**
+     * Get the url template to use for this database type
+     * @return the url template
+     */
+    public String getTemplate();
+    
+    /**
+     * Get the error message key when the specified driver was not found
+     * @return the error message 
+     */
+    public I18nizableText getDriverNotFoundMessage();
+}
+
Index: main/plugin-core/src/org/ametys/core/datasource/sql/dbtype/SQLDatabaseTypeEnumerator.java
===================================================================
--- main/plugin-core/src/org/ametys/core/datasource/sql/dbtype/SQLDatabaseTypeEnumerator.java	(revision 0)
+++ main/plugin-core/src/org/ametys/core/datasource/sql/dbtype/SQLDatabaseTypeEnumerator.java	(revision 0)
@@ -0,0 +1,53 @@
+/*
+ *  Copyright 2015 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.ametys.core.datasource.sql.dbtype;
+
+import java.util.Map;
+
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
+
+import org.ametys.runtime.i18n.I18nizableText;
+import org.ametys.runtime.parameter.Enumerator;
+
+/**
+ * Enumerator for {@link SQLDatabaseType}.
+ */
+public class SQLDatabaseTypeEnumerator implements Enumerator, Serviceable
+{
+    /** The extension point handling the database types */
+    private SQLDatabaseTypeExtensionPoint _sqlDatabaseTypeExtensionPoint;
+    
+    @Override
+    public void service(ServiceManager manager) throws ServiceException
+    {
+        _sqlDatabaseTypeExtensionPoint = (SQLDatabaseTypeExtensionPoint) manager.lookup(SQLDatabaseTypeExtensionPoint.ROLE);
+    }
+    
+    @Override
+    public I18nizableText getEntry(String value) throws Exception
+    {
+        SQLDatabaseType dbType = _sqlDatabaseTypeExtensionPoint.getExtension(value);
+        return dbType != null ? dbType.getLabel() : null;
+    }
+
+    @Override
+    public Map<Object, I18nizableText> getEntries() throws Exception
+    {
+        return _sqlDatabaseTypeExtensionPoint.getSQLDatabaseTypes();
+    }
+}
Index: main/plugin-core/src/org/ametys/core/datasource/sql/dbtype/SQLDatabaseTypeExtensionPoint.java
===================================================================
--- main/plugin-core/src/org/ametys/core/datasource/sql/dbtype/SQLDatabaseTypeExtensionPoint.java	(revision 0)
+++ main/plugin-core/src/org/ametys/core/datasource/sql/dbtype/SQLDatabaseTypeExtensionPoint.java	(revision 0)
@@ -0,0 +1,50 @@
+/*
+ *  Copyright 2015 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.ametys.core.datasource.sql.dbtype;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.ametys.runtime.i18n.I18nizableText;
+import org.ametys.runtime.plugin.component.AbstractThreadSafeComponentExtensionPoint;
+
+/**
+ * This class is in charge to load and initialize the {@link SQLDatabaseType} 
+ */
+public class SQLDatabaseTypeExtensionPoint extends AbstractThreadSafeComponentExtensionPoint<SQLDatabaseType>
+{
+    /** Avalon Role */
+    public static final String ROLE = SQLDatabaseTypeExtensionPoint.class.getName();
+    
+    /**
+     * Get the SQL database types with their label
+     * @return the SQL database types with their label
+     */
+    public Map<Object, I18nizableText> getSQLDatabaseTypes()
+    {
+        Map<Object, I18nizableText> db = new HashMap<>();
+        
+        Set<String> extensionsIds = getExtensionsIds();
+        for (String extensionId : extensionsIds)
+        {
+            SQLDatabaseType dbType = getExtension(extensionId);
+            db.put(extensionId, dbType.getLabel());
+        }
+        
+        return db;
+    }
+}
Index: main/plugin-core/src/org/ametys/core/datasource/sql/dbtype/SQLDatabaseTypeManager.java
===================================================================
--- main/plugin-core/src/org/ametys/core/datasource/sql/dbtype/SQLDatabaseTypeManager.java	(revision 0)
+++ main/plugin-core/src/org/ametys/core/datasource/sql/dbtype/SQLDatabaseTypeManager.java	(revision 0)
@@ -0,0 +1,85 @@
+package org.ametys.core.datasource.sql.dbtype;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.avalon.framework.component.Component;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
+
+import org.ametys.core.ui.Callable;
+import org.ametys.core.util.I18nUtils;
+import org.ametys.plugins.core.impl.datasource.StaticSQLDatabaseType;
+import org.ametys.runtime.i18n.I18nizableText;
+
+/**
+ * Manager handling the handled SQL database types
+ */
+public class SQLDatabaseTypeManager implements Component, Serviceable
+{
+    /** Avalon Role */
+    public static final String ROLE = SQLDatabaseTypeManager.class.getName();
+    
+    /** The extension point for SQL database types */
+    private SQLDatabaseTypeExtensionPoint _sqlDatabaseTypeExtensionPoint;
+    
+    /** Component containing i18n utility methods */
+    private I18nUtils _i18nUtils;
+    
+    @Override
+    public void service(ServiceManager serviceManager) throws ServiceException
+    {
+        _sqlDatabaseTypeExtensionPoint = (SQLDatabaseTypeExtensionPoint) serviceManager.lookup(SQLDatabaseTypeExtensionPoint.ROLE);
+        _i18nUtils = (I18nUtils) serviceManager.lookup(I18nUtils.ROLE);
+    }
+    
+    /**
+     * Retrieve the available sql drivers and the associated templates
+     * @return the available drivers in JSON 
+     */
+    @Callable
+    public Map<String, Object> getSQLDatabaseTypes()
+    {
+        Map<String, Object> result = new HashMap<> ();
+        List<Map<String, Object>> databaseTypes = new ArrayList<>();
+        
+        Map<Object, I18nizableText> sqlDatabaseTypes = _sqlDatabaseTypeExtensionPoint.getSQLDatabaseTypes();
+        for (Object extensionId : sqlDatabaseTypes.keySet())
+        {
+            Map<String, Object> databaseType = new HashMap<> ();
+            StaticSQLDatabaseType staticSQLDatabaseType = (StaticSQLDatabaseType) _sqlDatabaseTypeExtensionPoint.getExtension((String) extensionId);
+            
+            databaseType.put("label", _i18nUtils.translate(staticSQLDatabaseType.getLabel()));
+            databaseType.put("value", staticSQLDatabaseType.getDriver());
+            databaseType.put("template", staticSQLDatabaseType.getTemplate());
+            
+            databaseTypes.add(databaseType);
+        }
+        
+        result.put("databaseTypes", databaseTypes);
+        return result;
+    }
+    
+    /**
+     * Get the class not found message corresponding to a driver
+     * @param driver the driver
+     * @return the message to use in case the class of the driver was not found
+     */
+    public I18nizableText getClassNotFoundMessage(String driver)
+    {
+        Map<Object, I18nizableText> sqlDatabaseTypes = _sqlDatabaseTypeExtensionPoint.getSQLDatabaseTypes();
+        for (Object extensionId : sqlDatabaseTypes.keySet())
+        {
+            StaticSQLDatabaseType staticSQLDatabaseType = (StaticSQLDatabaseType) _sqlDatabaseTypeExtensionPoint.getExtension((String) extensionId);
+            if (staticSQLDatabaseType.getDriver().equals(driver))
+            {
+                return staticSQLDatabaseType.getDriverNotFoundMessage();
+            }
+        }
+        
+        return null;
+    }
+}
Index: main/plugin-core/src/org/ametys/core/util/ldap/AbstractLDAPConnector.java
===================================================================
--- main/plugin-core/src/org/ametys/core/util/ldap/AbstractLDAPConnector.java	(revision 38980)
+++ main/plugin-core/src/org/ametys/core/util/ldap/AbstractLDAPConnector.java	(working copy)
@@ -28,23 +28,30 @@
 import javax.naming.ldap.LdapContext;
 import javax.naming.ldap.PagedResultsControl;
 
-import org.apache.avalon.framework.configuration.Configurable;
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
 
+import org.ametys.core.datasource.ldap.LDAPDataSourceManager;
+import org.ametys.core.datasource.ldap.LDAPDataSourceManager.LDAPDataSourceDescriptor;
 import org.ametys.core.util.CachingComponent;
 import org.ametys.runtime.config.Config;
 
 /**
  * This abstract class contains all basic for a ldap connection using config parameters
  */
-public abstract class AbstractLDAPConnector extends CachingComponent<Object> implements Configurable
+public abstract class AbstractLDAPConnector extends CachingComponent<Object> implements Serviceable
 {
     // Check filter look
     private static final Pattern __FILTER = Pattern.compile("\\s*\\(.*\\)\\s*");
-
+    
+    /** The configuration parameter id of the LDAP data source */
+    private static final String __LDAP_PARAMETER_ID = "runtime.datasource.core.ldap";
+    
     /** URL connection to the ldap server. */
-    protected String _ldapUrl;
+    protected String _ldapUrl;  
     /** Base DN to the ldap server. */
     protected String _ldapBaseDN;
     /** Distinguished name of the admin used for searching. */
@@ -62,6 +69,34 @@
     
     /** Indicates if the LDAP server supports paging feature. */
     protected boolean _pagingSupported;
+
+    /** The LDAP data source manager */
+    private LDAPDataSourceManager _ldapDataSourceManager;
+    
+    @Override
+    public void initialize() throws Exception
+    {
+        super.initialize();
+        
+        String dataSourceId = Config.getInstance().getValueAsString(__LDAP_PARAMETER_ID);
+        LDAPDataSourceDescriptor ldapDataSourceDescriptor = _ldapDataSourceManager.getLDAPDataSourceDescription(dataSourceId); 
+        
+        _ldapUrl = ldapDataSourceDescriptor.getBaseURL();
+        _ldapBaseDN = ldapDataSourceDescriptor.getBaseDN();
+        _ldapAdminRelativeDN = ldapDataSourceDescriptor.getAdminDN();
+        _ldapAdminPassword = ldapDataSourceDescriptor.getAdminPassword();
+        _ldapAuthenticationMethod = ldapDataSourceDescriptor.getAuthenticationMethod();
+        _ldapUseSSL = ldapDataSourceDescriptor.isUsingSSL();
+        _ldapFollowReferrals = ldapDataSourceDescriptor.isFollowingReferrals();
+        _ldapAliasDerefMode = ldapDataSourceDescriptor.getAliasDereferencing();
+        
+        _pagingSupported = _testPagingSupported();
+    }
+    
+    public void service(ServiceManager serviceManager) throws ServiceException
+    {
+        _ldapDataSourceManager = (LDAPDataSourceManager) serviceManager.lookup(LDAPDataSourceManager.ROLE); 
+    }
     
     /**
      * Get the filter from configuration key and check it
@@ -101,32 +136,6 @@
             throw new ConfigurationException("Unable to parse scope", e);
         }
     }
-
-    @Override
-    public void configure(Configuration configuration) throws ConfigurationException
-    {
-        _ldapUrl = _getConfigParameter(configuration, "BaseUrl");
-        _ldapUseSSL = "true".equals(_getConfigParameter(configuration, "UseSSL"));
-        _ldapBaseDN = _getConfigParameter(configuration, "BaseDN");
-        _ldapFollowReferrals = "true".equals(_getConfigParameter(configuration, "FollowReferrals"));
-        
-        _ldapAuthenticationMethod = _getConfigParameter(configuration, "AuthenticationMethod");
-        if (!_ldapAuthenticationMethod.equals("none"))
-        {
-            _ldapAdminRelativeDN = _getConfigParameter(configuration, "AdminDN");
-            _ldapAdminPassword = _getConfigParameter(configuration, "AdminPassword");
-        }
-        
-        _ldapAliasDerefMode = _getConfigParameter(configuration, "AliasDereferencing");
-    }
-    
-    @Override
-    public void initialize() throws Exception
-    {
-        super.initialize();
-        
-        _pagingSupported = _testPagingSupported();
-    }
     
     /**
      * Test if paging is supported by the underlying directory server.
Index: main/plugin-core-impl/i18n/messages_en.xml
===================================================================
--- main/plugin-core-impl/i18n/messages_en.xml	(revision 38980)
+++ main/plugin-core-impl/i18n/messages_en.xml	(working copy)
@@ -27,48 +27,24 @@
     <!-- DATASOURCE CORE -->
     <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_JDBC_CATEGORY_DATASOURCE">Database</message>
     <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_JDBC_CATEGORY_DATASOURCE_GROUP_CORE">Kernel database connection</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_DRIVER_LABEL">Driver</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_DRIVER_DESCRIPTION">JDBC Driver fully qualified class name</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_URL_LABEL">Url</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_URL_DESCRIPTION">JDBC URL for connecting to the database</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_USER_LABEL">User</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_USER_DESCRIPTION">User name for connecting to the database</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_PASSWORD_LABEL">Password</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_PASSWORD_DESCRIPTION">Password associated with the user name for connecting to the database</message>
+    
     <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_CATEGORY_LDAP">LDAP directory</message>
     
-    <message key="PLUGINS_CORE_SQL_CONNECTION_CHECKER_LABEL">Check the connection to the kernel database</message>
+    <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_JDBC_DATASOURCE_LABEL">Kernel database</message>
+    <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_JDBC_DATASOURCE_DESCRIPTION">Specify here the data source that will be used as the kernel database. It will store, among other entities, the users, the groups, the rights' profiles...</message> 
+    
+    <message key="PLUGINS_CORE_SQL_CONNECTION_CHECKER_LABEL">Connection to the kernel database</message>
     <message key="PLUGINS_CORE_SQL_CONNECTION_CHECKER_DESC">This test checks if the given information allows the connection to the SQL kernel database.</message>
     
     <!-- DATASOURCE LDAP -->
     <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_CATEGORY_LDAP_GROUP_CORE">Server</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_BASEURL_LABEL">Url</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_BASEURL_DESCRIPTION">Url for LDAP server</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_BASEURL_INVALID">The url of the LDAP server is invalid. It has to be like 'ldap://server:389' or 'ldaps://server:389'.</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_BASEDN_LABEL">Base DN</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_BASEDN_DESCRIPTION">Base DN for the entire LDAP directory</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ADMINDN_LABEL">Administrator's DN</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ADMINDN_DESCRIPTION">Absolute DN for LDAP directory super-user</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ADMINPASSWORD_LABEL">Administrator password</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ADMINPASSWORD_DESCRIPTION">LDAP directory super-user password</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_FOLLOWREFERRALS_LABEL">Follow references</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_FOLLOWREFERRALS_DESCRIPTION">Check this option to enable following references (mainly for dynamic groups).</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_LABEL">Alias dereferencing</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_DESCRIPTION">Defines the alias dereferencing mode.&lt;br/&gt;- &lt;b&gt;always : &lt;/b&gt;always dereference aliases&lt;br/&gt;- &lt;b&gt;never : &lt;/b&gt;never dereferences aliases&lt;br/&gt;- &lt;b&gt;finding : &lt;/b&gt;dereferences aliases only during name resolution&lt;br/&gt;- &lt;b&gt;searching : &lt;/b&gt;dereferences aliases only after name resolution</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_ENUM_ALWAYS">always</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_ENUM_NEVER">never</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_ENUM_FINDING">finding</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_ENUM_SEARCHING">searching</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_AUTH_METHOD_LABEL">Authentication method</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_AUTH_METHOD_DESCRIPTION">Define the authentication method for LDAP directory</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_AUTH_METHOD_ENUM_NONE">Anonymous</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_AUTH_METHOD_ENUM_SIMPLE">Simple</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_SSL_LABEL">Secured connection</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_SSL_DESCRIPTION">Select to use the secure LDAP (ldaps)</message>
-    
-    <message key="PLUGINS_CORE_LDAP_DN_CONNECTION_CHECKER_LABEL">Check the connection to the LDAP repository</message>
-    <message key="PLUGINS_CORE_LDAP_DN_CONNECTION_CHECKER_DESC">This test checks if the provided information allow to establish a connection to the LDAP repository</message>
 
+    <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_LDAP_DATASOURCE_LABEL">LDAP connection</message>
+    <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_LDAP_DATASOURCE_DESCRIPTION">Specify here the data source to use to establish a LDAP connection.</message>
+
+    <message key="PLUGINS_CORE_LDAP_CONNECTION_CHECKER_LABEL">Connection to the LDAP repository</message>
+    <message key="PLUGINS_CORE_LDAP_CONNECTION_CHECKER_DESC">This test checks if the given information allows the connection to the LDAP repository.</message>
+    
     <!-- USER LDAP -->
     <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_CATEGORY_LDAP_GROUP_USERS">Users</message>
     <message key="PLUGINS_CORE_USERS_LDAPUSER_CONFIG_PEOPLEDN_LABEL">DN for people</message>
@@ -130,8 +106,17 @@
     <message key="PLUGINS_CORE_AUTHENTICATION_CAS_CONFIG_URL_DESCRIPTION">CAS server Url</message>
     <message key="PLUGINS_CORE_AUTHENTICATION_CAS_CONFIG_AUTHORIZEDPROXY_LABEL">Proxy chain</message>
     <message key="PLUGINS_CORE_AUTHENTICATION_CAS_CONFIG_AUTHORIZEDPROXY_DESCRIPTION">CAS server authorized proxy chain</message>
-        
-    <message key="PLUGINS_CORE_CAS_SERVER_CHECKER_LABEL">Check the CAS server URL</message>
-    <message key="PLUGINS_CORE_CAS_SERVER_CHECKER_DESC">This test checks if the provided url allows to establish a connection to the CAS server.</message>    
     
+    <message key="PLUGINS_CORE_CAS_SERVER_CHECKER_LABEL">Check the url of the CAS server</message>
+    <message key="PLUGINS_CORE_CAS_SERVER_CHECKER_DESC">This test checks that the specified url is valid by trying to establish a connection.</message>
+    <!-- +
+         | SQL DATABASE TYPES 
+         + -->
+    <message key="PLUGINS_CORE_DATASOURCE_DERBY_DRIVER_LABEL">Derby</message>
+    <message key="PLUGINS_CORE_DATASOURCE_MYSQL_DRIVER_LABEL">MySQL</message>
+    <message key="PLUGINS_CORE_DATASOURCE_HSQL_DRIVER_LABEL">HSQL</message>
+    <message key="PLUGINS_CORE_DATASOURCE_POSTGRESQL_DRIVER_LABEL">PostGreSQL</message>
+    <message key="PLUGINS_CORE_DATASOURCE_ORACLE_DRIVER_LABEL">Oracle</message>
+    <message key="PLUGINS_CORE_DATASOURCE_DRIVER_NOT_FOUND">The specified driver was not found.</message>
+    <message key="PLUGINS_CORE_DATASOURCE_ORACLE_DRIVER_NOT_FOUND">The specified Oracle JDBC driver was not found. If you want to download it, please visit: http://www.oracle.com/technetwork/indexes/downloads/index.html#drivers</message>
 </catalogue>
\ No newline at end of file
Index: main/plugin-core-impl/i18n/messages_fr.xml
===================================================================
--- main/plugin-core-impl/i18n/messages_fr.xml	(revision 38980)
+++ main/plugin-core-impl/i18n/messages_fr.xml	(working copy)
@@ -27,47 +27,22 @@
     <!-- DATASOURCE CORE -->
     <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_JDBC_CATEGORY_DATASOURCE">Base de données</message>
     <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_JDBC_CATEGORY_DATASOURCE_GROUP_CORE">Connexion à la base de données noyau</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_DRIVER_LABEL">Pilote</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_DRIVER_DESCRIPTION">Nom complet de la classe driver JDBC à charger</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_URL_LABEL">Url</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_URL_DESCRIPTION">Url JDBC de connexion au serveur de base de données</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_USER_LABEL">Utilisateur</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_USER_DESCRIPTION">Nom d'utilisateur à utiliser lors de la connexion au serveur de base de données</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_PASSWORD_LABEL">Mot de passe</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_PASSWORD_DESCRIPTION">Mot de passe associé au nom d'utilisateur à utiliser lors de la connexion au serveur de base de données</message>
     <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_CATEGORY_LDAP">Annuaire LDAP</message>
     
-    <message key="PLUGINS_CORE_SQL_CONNECTION_CHECKER_LABEL">Vérifier la connexion à la base noyau</message>
-    <message key="PLUGINS_CORE_SQL_CONNECTION_CHECKER_DESC">Ce test vérifie que les informations rentrées permettent bien d'établir une connexion avec la base de données noyau</message>
-
+    <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_JDBC_DATASOURCE_LABEL">Base de données noyau</message>
+    <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_JDBC_DATASOURCE_DESCRIPTION">Spécifiez ici la source de données à utiliser en tant que base de données noyau. Elle sera utilisée pour stocker, entre autres, les utilisateurs, les groupes, les profils de droits...</message>
+    
+    <message key="PLUGINS_CORE_SQL_CONNECTION_CHECKER_LABEL">Connexion à une base SQL</message>
+    <message key="PLUGINS_CORE_SQL_CONNECTION_CHECKER_DESC">Ce test vérifie que les informations rentrées permettent bien d'établir une connexion à la base de données.</message>
+    
     <!-- DATASOURCE LDAP -->
     <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_CATEGORY_LDAP_GROUP_CORE">Serveur</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_BASEURL_LABEL">Adresse</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_BASEURL_DESCRIPTION">Url du serveur LDAP</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_BASEURL_INVALID">L'url du serveur LDAP est invalide.&lt;br/&gt;Elle doit être de la forme ldap://server:389 ou ldaps://server:389.</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_BASEDN_LABEL">DN de base</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_BASEDN_DESCRIPTION">DN de base pour tout les accès à l'annuaire LDAP</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ADMINDN_LABEL">DN de l'administrateur</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ADMINDN_DESCRIPTION">DN complet d'un utilisateur tout pouvoir dans l'annuaire LDAP</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ADMINPASSWORD_LABEL">Mot de passe administrateur</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ADMINPASSWORD_DESCRIPTION">Mot de passe associé à cet utilisateur dans l'annuaire LDAP</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_FOLLOWREFERRALS_LABEL">Suivre les références</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_FOLLOWREFERRALS_DESCRIPTION">Cochez cette option pour suivre les références dans les résultats de recherche (principalement pour les groupes LDAP dynamiques).</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_LABEL">Déréférencement des alias</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_DESCRIPTION">Définit le mode de déréférencement des entrées de type alias.&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;- &lt;b&gt;always : &lt;/b&gt;toujours déréférencer les alias&lt;br/&gt;- &lt;b&gt;never : &lt;/b&gt;ne jamais déréférencer les alias&lt;br/&gt;- &lt;b&gt;finding : &lt;/b&gt;déréférencer les alias uniquement pendant la résolution de nom&lt;br/&gt;- &lt;b&gt;searching : &lt;/b&gt;déréférencer les alias uniquement après la résolution de nom&lt;br/&gt;&lt;/ul&gt;</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_ENUM_ALWAYS">always</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_ENUM_NEVER">never</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_ENUM_FINDING">finding</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_ENUM_SEARCHING">searching</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_AUTH_METHOD_LABEL">Méthode d'authentification</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_AUTH_METHOD_DESCRIPTION">Définit le type d'authentification possible entre l'application et l'annuaire LDAP</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_AUTH_METHOD_ENUM_NONE">Anonyme</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_AUTH_METHOD_ENUM_SIMPLE">Simple</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_SSL_LABEL">Connexion sécurisée</message>
-    <message key="PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_SSL_DESCRIPTION">Activer cette option pour utiliser le protocole ldaps au lieu de ldap</message>
+
+    <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_LDAP_DATASOURCE_LABEL">Connexion LDAP</message>
+    <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_LDAP_DATASOURCE_DESCRIPTION">Spécifiez ici le source de données à utiliser en tant que connexion LDAP.</message>
     
-    <message key="PLUGINS_CORE_LDAP_DN_CONNECTION_CHECKER_LABEL">Connexion à l'annuaire LDAP</message>
-    <message key="PLUGINS_CORE_LDAP_DN_CONNECTION_CHECKER_DESC">Ce test vérifie que les informations rentrées permettent bien d'établir une connexion à l'annuaire LDAP.</message>
+    <message key="PLUGINS_CORE_LDAP_CONNECTION_CHECKER_LABEL">Connexion à un annuaire LDAP</message>
+    <message key="PLUGINS_CORE_LDAP_CONNECTION_CHECKER_DESC">Ce test vérifie que les informations rentrées permettent bien d'établir une connexion à un LDAP.</message>
     
     <!-- USER LDAP -->
     <message key="PLUGINS_CORE_DATASOURCE_CORE_CONFIG_CATEGORY_LDAP_GROUP_USERS">Utilisateurs</message>
@@ -133,4 +108,15 @@
     
     <message key="PLUGINS_CORE_CAS_SERVER_CHECKER_LABEL">Vérifier l'url du serveur CAS</message>
     <message key="PLUGINS_CORE_CAS_SERVER_CHECKER_DESC">Ce test vérifie que le l'url spécifiée est valide en essayant d'établir une connexion.</message>    
+    <!-- +
+         | SQL DATABASE TYPES 
+         + -->
+    <message key="PLUGINS_CORE_DATASOURCE_DERBY_DRIVER_LABEL">Derby</message>
+    <message key="PLUGINS_CORE_DATASOURCE_MYSQL_DRIVER_LABEL">MySQL</message>
+    <message key="PLUGINS_CORE_DATASOURCE_HSQL_DRIVER_LABEL">HSQL</message>
+    <message key="PLUGINS_CORE_DATASOURCE_POSTGRESQL_DRIVER_LABEL">PostGreSQL</message>
+    <message key="PLUGINS_CORE_DATASOURCE_ORACLE_DRIVER_LABEL">Oracle</message>
+    <message key="PLUGINS_CORE_DATASOURCE_DRIVER_NOT_FOUND">Le driver choisi est introuvable.</message>
+    <message key="PLUGINS_CORE_DATASOURCE_ORACLE_DRIVER_NOT_FOUND">Le driver Oracle choisi est introuvable. Pour télécharger le driver, veuillez vous rendre sur le lien ci-après : http://www.oracle.com/technetwork/indexes/downloads/index.html#drivers</message>
+    
 </catalogue>
\ No newline at end of file
Index: main/plugin-core-impl/plugin.xml
===================================================================
--- main/plugin-core-impl/plugin.xml	(revision 38980)
+++ main/plugin-core-impl/plugin.xml	(working copy)
@@ -20,195 +20,47 @@
         runtimeVersion="4.0" version="2.0">
     
     <config>
-        <!-- +
-             | CORE DATASOURCE
-             + -->
-        <!-- JDBC -->
-        <param id="runtime.datasource.core.jdbc.driver" type="string">
+        <!-- DATASOURCE JDBC -->
+        <param id="runtime.datasource.core.jdbc.pool" type="datasource">
             <!-- 
                 This parameter contains the jdbc driver class to load to connect the core database pool.
              -->
-            <label i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_DRIVER_LABEL</label>
-            <description i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_DRIVER_DESCRIPTION</description>
+            <label i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_JDBC_DATASOURCE_LABEL</label>
+            <description i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_JDBC_DATASOURCE_DESCRIPTION</description>
+            <widget>edition.datasource-sql</widget>
+            <widget-params>
+                <param name="allowCreation">true</param>
+                <param name="allowPrivate">true</param>
+            </widget-params>
             <validation>
                 <mandatory/>
             </validation>
-            <default-value>com.mysql.jdbc.Driver</default-value>
             <category i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_JDBC_CATEGORY_DATASOURCE</category>
             <group i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_JDBC_CATEGORY_DATASOURCE_GROUP_CORE</group>
             <order>10</order>
         </param>
-        <param id="runtime.datasource.core.jdbc.url" type="string">
-            <!-- 
-                This parameter contains the jdbc url to connect the core database pool.
-             -->
-            <label i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_URL_LABEL</label>
-            <description i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_URL_DESCRIPTION</description>
-            <validation>
-                <mandatory/>
-            </validation>
-            <default-value>jdbc:mysql://servername/basename</default-value>
-            <category i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_JDBC_CATEGORY_DATASOURCE</category>
-            <group i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_JDBC_CATEGORY_DATASOURCE_GROUP_CORE</group>
-            <order>20</order>
-        </param>
-        <param id="runtime.datasource.core.jdbc.user" type="string">
-            <!-- 
-                This parameter contains the jdbc username to connect the core database pool.
-                @see:plugin{config/runtime.datasource.core.jdbc.passwd}
-             -->
-            <label i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_USER_LABEL</label>
-            <description i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_USER_DESCRIPTION</description>
-            <default-value>username</default-value>
-            <category i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_JDBC_CATEGORY_DATASOURCE</category>
-            <group i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_JDBC_CATEGORY_DATASOURCE_GROUP_CORE</group>
-            <order>30</order>
-        </param>
-        <param id="runtime.datasource.core.jdbc.passwd" type="password">
-            <!-- 
-                This parameter contains the jdbc password to connect the core database pool.
-                @see:plugin{config/runtime.datasource.core.jdbc.user}
-             -->
-            <label i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_PASSWORD_LABEL</label>
-            <description i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_PASSWORD_DESCRIPTION</description>
-            <category i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_JDBC_CATEGORY_DATASOURCE</category>
-            <group i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_JDBC_CATEGORY_DATASOURCE_GROUP_CORE</group>
-            <order>40</order>
-        </param>
         
-        <!-- LDAP -->
-        <param id="runtime.datasource.core.ldap.baseUrl" type="string">
-            <!-- 
-                This parameter contains the base url (protocol + server name + port) to connect to the core ldap connection.
-             -->
-            <label i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_BASEURL_LABEL</label>
-            <description i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_BASEURL_DESCRIPTION</description>
-            <validation>
-                <mandatory/>
-                <regexp>^ldaps?://[\w\-.]*(:\d+)?</regexp> 
-                <invalidText i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_BASEURL_INVALID</invalidText>
-            </validation>
-            <default-value>ldap://server:389</default-value>
-            <category i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_CATEGORY_LDAP</category>
-            <group i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_CATEGORY_LDAP_GROUP_CORE</group>
-            <order>10</order>
-        </param>
-        <param id="runtime.datasource.core.ldap.useSSL" type="boolean">
-            <!-- 
-                This parameter determines if the connection to the ldap server is secured or not.<br/>
-                Depending on the JVM, the use of 'ldaps' in the protocol is not supported.
-             -->
-            <label i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_SSL_LABEL</label>
-            <description i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_SSL_DESCRIPTION</description>
-            <validation>
-                <mandatory/>
-            </validation>
-            <default-value>false</default-value>
-            <category i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_CATEGORY_LDAP</category>
-            <group i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_CATEGORY_LDAP_GROUP_CORE</group>
-            <order>20</order>
-        </param>
-        <param id="runtime.datasource.core.ldap.baseDN" type="string">
-            <!-- 
-                This parameter contains the base of the DN to add to all search.
-                <br/>May be empty if search have to be done in several branches.
-             -->
-            <label i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_BASEDN_LABEL</label>
-            <description i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_BASEDN_DESCRIPTION</description>
-            <default-value>dc=ametys,dc=org</default-value>
-            <category i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_CATEGORY_LDAP</category>
-            <group i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_CATEGORY_LDAP_GROUP_CORE</group>
-            <order>30</order>
-        </param>
-        <param id="runtime.datasource.core.ldap.authMethod" type="string">
+        <!-- DATASOURCE LDAP -->
+        <!-- Server -->
+        <param id="runtime.datasource.core.ldap" type="datasource">
             <!-- 
-                This parameter determines if the connection to LDAP can be anonymous.
-                @see:plugin{config/runtime.datasource.core.ldap.adminDN}
-                @see:plugin{config/runtime.datasource.core.ldap.adminPasswd}
+                This parameter contains the ldap connection information used to connect to the ldap repository
              -->
-            <label i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_AUTH_METHOD_LABEL</label>
-            <description i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_AUTH_METHOD_DESCRIPTION</description>
-            <enumeration>
-                <entry>
-                    <label i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_AUTH_METHOD_ENUM_NONE</label>
-                    <value>none</value>
-                </entry>
-                <entry>
-                    <label i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_AUTH_METHOD_ENUM_SIMPLE</label>
-                    <value>simple</value>
-                </entry>
-            </enumeration>
+            <label i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_LDAP_DATASOURCE_LABEL</label>
+            <description i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_LDAP_DATASOURCE_DESCRIPTION</description>
+            <widget>edition.datasource-ldap</widget>
+            <widget-params>
+                <param name="allowCreation">true</param>
+                <param name="allowPrivate">true</param>
+            </widget-params>
             <validation>
                 <mandatory/>
             </validation>
-            <default-value>none</default-value>
             <category i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_CATEGORY_LDAP</category>
             <group i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_CATEGORY_LDAP_GROUP_CORE</group>
-            <order>40</order>
-        </param>
-        <param id="runtime.datasource.core.ldap.adminDN" type="string">
-            <!-- 
-                If the authMethod is not anonymous, this parameter contains the DN of the user to use to connect to the LDAP.
-                @see:plugin{config/runtime.datasource.core.ldap.authMethod}
-                @see:plugin{config/runtime.datasource.core.ldap.adminPasswd}
-             -->
-            <label i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ADMINDN_LABEL</label>
-            <description i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ADMINDN_DESCRIPTION</description>
-            <validation>
-                <mandatory/>
-            </validation>
-            <default-value>cn=admin</default-value>
-            <category i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_CATEGORY_LDAP</category>
-            <group i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_CATEGORY_LDAP_GROUP_CORE</group>
-            <order>50</order>
-            <disable-conditions>
-                <condition id="runtime.datasource.core.ldap.authMethod" operator="eq">none</condition>
-            </disable-conditions>
-        </param>
-        <param id="runtime.datasource.core.ldap.adminPasswd" type="password">
-            <!-- 
-                If the authMethod is not anonymous, this parameter contains the password of the user to use to connect to the LDAP.
-                @see:plugin{config/runtime.datasource.core.ldap.authMethod}
-                @see:plugin{config/runtime.datasource.core.ldap.adminDN}
-             -->
-            <label i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ADMINPASSWORD_LABEL</label>
-            <description i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ADMINPASSWORD_DESCRIPTION</description>
-            <category i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_CATEGORY_LDAP</category>
-            <group i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_CATEGORY_LDAP_GROUP_CORE</group>
-            <order>60</order>
-            <disable-conditions>
-                <condition id="runtime.datasource.core.ldap.authMethod" operator="eq">none</condition>
-            </disable-conditions>
-        </param>
-        <param id="runtime.datasource.core.ldap.aliasDereferencing" type="string">
-            <!-- 
-                This parameter controls the alias dereferencing mode.
-             -->
-            <label i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_LABEL</label>
-            <description i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_ALIAS_DEREF_DESCRIPTION</description>
-            <enumeration>
-                <custom-enumerator class="org.ametys.core.util.ldap.AliasDerefEnumerator"/>
-            </enumeration>
-            <default-value>always</default-value>
-            <category i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_CATEGORY_LDAP</category>
-            <group i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_CATEGORY_LDAP_GROUP_CORE</group>
-            <order>32</order>
-        </param>
-        <param id="runtime.datasource.core.ldap.followReferrals" type="boolean">
-            <!-- 
-                This parameters controls whether referral following is enabled (used for continuation references).
-             -->
-            <label i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_FOLLOWREFERRALS_LABEL</label>
-            <description i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_FOLLOWREFERRALS_DESCRIPTION</description>
-            <default-value>false</default-value>
-            <category i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_CATEGORY_LDAP</category>
-            <group i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_CATEGORY_LDAP_GROUP_CORE</group>
-            <order>35</order>
         </param>
         
-        <!-- +
-             | USERS
-             + -->
+        <!-- User -->
         <param id="runtime.users.ldap.peopleDN" type="string">
             <!-- 
                 When users are handled in the LDAP, this parameter contains the DN to append to the base DN to guide to users.
@@ -579,51 +431,6 @@
             <order>1</order>
         </param>
         
-        <param-checker id="ldap-connection-dn-checker" class="org.ametys.plugins.core.impl.checker.LDAPConnectionChecker">
-            <label i18n="true">PLUGINS_CORE_LDAP_DN_CONNECTION_CHECKER_LABEL</label>
-            <description i18n="true">PLUGINS_CORE_LDAP_DN_CONNECTION_CHECKER_DESC</description>
-            <icon-small>img/config/check/test_ldapconnect_16.png</icon-small>
-            <icon-medium>img/config/check/test_ldapconnect_32.png</icon-medium>
-            <icon-large>img/config/check/test_ldapconnect_48.png</icon-large>
-                        
-            <ui-ref>
-                <order>5</order>
-                <category i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_CATEGORY_LDAP</category>
-                <group i18n="true">PLUGINS_CORE_DATASOURCE_CORE_LDAP_CONFIG_CATEGORY_LDAP_GROUP_CORE</group>
-            </ui-ref>
-            
-            <linked-params>
-                <param-ref id="runtime.datasource.core.ldap.baseUrl"/>
-                <param-ref id="runtime.datasource.core.ldap.useSSL"/>
-                <param-ref id="runtime.datasource.core.ldap.baseDN"/>
-                <param-ref id="runtime.datasource.core.ldap.authMethod"/>
-                <param-ref id="runtime.datasource.core.ldap.adminDN"/>
-                <param-ref id="runtime.datasource.core.ldap.adminPasswd"/>
-                <param-ref id="runtime.datasource.core.ldap.followReferrals"/>
-            </linked-params>
-        </param-checker>
-        
-        <param-checker id="sql-connection-checker-kernel" class="org.ametys.plugins.core.impl.checker.SqlConnectionChecker">
-            <label i18n="true">PLUGINS_CORE_SQL_CONNECTION_CHECKER_LABEL</label>
-            <description i18n="true">PLUGINS_CORE_SQL_CONNECTION_CHECKER_DESC</description>
-            <icon-large>img/config/check/test_sqlconnect_48.png</icon-large>
-            <icon-medium>img/config/check/test_sqlconnect_32.png</icon-medium>
-            <icon-small>img/config/check/test_sqlconnect_16.png</icon-small>
-                        
-            <ui-ref>
-                <order>1</order>
-                <category i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_JDBC_CATEGORY_DATASOURCE</category>
-                <group i18n="true">PLUGINS_CORE_DATASOURCE_CORE_CONFIG_JDBC_CATEGORY_DATASOURCE_GROUP_CORE</group>
-            </ui-ref>
-            
-            <linked-params>
-                <param-ref id="runtime.datasource.core.jdbc.driver"/>
-                <param-ref id="runtime.datasource.core.jdbc.url"/>
-                <param-ref id="runtime.datasource.core.jdbc.user"/>
-                <param-ref id="runtime.datasource.core.jdbc.passwd"/>
-            </linked-params>
-        </param-checker>
-        
         <param-checker id="cas-server-checker" class="org.ametys.plugins.core.impl.checker.HttpUrlChecker">
             <label i18n="true">PLUGINS_CORE_CAS_SERVER_CHECKER_LABEL</label>
             <description i18n="true">PLUGINS_CORE_CAS_SERVER_CHECKER_DESC</description>
@@ -674,6 +481,15 @@
         </components>
     </feature>
     
+    <feature name="runtime.datasource.core" passive="true">
+        <!--
+            This feature defines the pool of connection to the database.
+         -->
+        <config>
+            <param-ref id="runtime.datasource.core.jdbc.pool"/>
+        </config>
+    </feature>
+    
     <feature name="runtime.user.impl.jdbc.core" depends="runtime.datasource.core">
         <!-- 
             This features defines the base jdbc implementation of users (based on core database pool) 
@@ -731,7 +547,7 @@
                 <param id="lastname"/>
                 <param id="email"/>
                 <salt column="salt"/>
-            </component>
+            </component> 
         </components>
     </feature>
     
@@ -764,14 +580,7 @@
             This features defines the base ldap implementation of users
          -->
         <config>
-            <param-ref id="runtime.datasource.core.ldap.baseUrl"/>
-            <param-ref id="runtime.datasource.core.ldap.useSSL"/>
-            <param-ref id="runtime.datasource.core.ldap.baseDN"/>
-            <param-ref id="runtime.datasource.core.ldap.authMethod"/>
-            <param-ref id="runtime.datasource.core.ldap.adminDN"/>
-            <param-ref id="runtime.datasource.core.ldap.adminPasswd"/>
-            <param-ref id="runtime.datasource.core.ldap.aliasDereferencing"/>
-            <param-ref id="runtime.datasource.core.ldap.followReferrals"/>
+            <param-ref id="runtime.datasource.core.ldap"/>
 
             <param-ref id="runtime.users.ldap.peopleDN"/>
             <param-ref id="runtime.users.ldap.baseFilter"/>
@@ -787,15 +596,6 @@
                        id="org.ametys.plugins.core.Ldap"
                        class="org.ametys.plugins.core.impl.user.ldap.LdapUsersManager"
                        logger="org.ametys.plugins.core.impl.user.ldap.simple">
-                <BaseUrl>runtime.datasource.core.ldap.baseUrl</BaseUrl>
-                <UseSSL>runtime.datasource.core.ldap.useSSL</UseSSL>
-                <BaseDN>runtime.datasource.core.ldap.baseDN</BaseDN>
-                <AuthenticationMethod>runtime.datasource.core.ldap.authMethod</AuthenticationMethod>
-                <AdminDN>runtime.datasource.core.ldap.adminDN</AdminDN>
-                <AdminPassword>runtime.datasource.core.ldap.adminPasswd</AdminPassword>
-                <AliasDereferencing>runtime.datasource.core.ldap.aliasDereferencing</AliasDereferencing>
-                <FollowReferrals>runtime.datasource.core.ldap.followReferrals</FollowReferrals>
-
                 <RelativeDN>runtime.users.ldap.peopleDN</RelativeDN>
                 <Filter>runtime.users.ldap.baseFilter</Filter>
                 <SearchScope>runtime.users.ldap.scope</SearchScope>
@@ -814,14 +614,7 @@
             @see:plugin{feature/runtime.user.impl.ldap}
          -->
         <config>
-            <param-ref id="runtime.datasource.core.ldap.baseUrl"/>
-            <param-ref id="runtime.datasource.core.ldap.useSSL"/>
-            <param-ref id="runtime.datasource.core.ldap.baseDN"/>
-            <param-ref id="runtime.datasource.core.ldap.authMethod"/>
-            <param-ref id="runtime.datasource.core.ldap.adminDN"/>
-            <param-ref id="runtime.datasource.core.ldap.adminPasswd"/>
-            <param-ref id="runtime.datasource.core.ldap.aliasDereferencing"/>
-            <param-ref id="runtime.datasource.core.ldap.followReferrals"/>
+            <param-ref id="runtime.datasource.core.ldap"/>
 
             <param-ref id="runtime.users.ldap.peopleDN"/>
             <param-ref id="runtime.users.ldap.baseFilter"/>
@@ -837,15 +630,6 @@
                        id="org.ametys.plugins.core.CredentialsAwareLdap"
                        class="org.ametys.plugins.core.impl.user.ldap.CredentialsAwareLdapUsersManager"
                        logger="org.ametys.plugins.core.impl.user.ldap.credential">
-                <BaseUrl>runtime.datasource.core.ldap.baseUrl</BaseUrl>
-                <UseSSL>runtime.datasource.core.ldap.useSSL</UseSSL>
-                <BaseDN>runtime.datasource.core.ldap.baseDN</BaseDN>
-                <AuthenticationMethod>runtime.datasource.core.ldap.authMethod</AuthenticationMethod>
-                <AdminDN>runtime.datasource.core.ldap.adminDN</AdminDN>
-                <AdminPassword>runtime.datasource.core.ldap.adminPasswd</AdminPassword>
-                <AliasDereferencing>runtime.datasource.core.ldap.aliasDereferencing</AliasDereferencing>
-                <FollowReferrals>runtime.datasource.core.ldap.followReferrals</FollowReferrals>
-
                 <RelativeDN>runtime.users.ldap.peopleDN</RelativeDN>
                 <Filter>runtime.users.ldap.baseFilter</Filter>
                 <SearchScope>runtime.users.ldap.scope</SearchScope>
@@ -858,21 +642,14 @@
         </components>
     </feature>
     
-    <feature name="runtime.user.impl.ldap.and.jdbc.credentialsaware">
+    <feature name="runtime.user.impl.ldap.and.jdbc.credentialsaware" depends="runtime.datasource.core">
         <!-- 
             This users manager will search for users into the ldap and into the sql db.
             @see:plugin{feature/runtime.user.impl.ldap.credentialsaware}
             @see:plugin{feature/runtime.user.impl.jdbc.credentialsaware.core}
          -->
         <config>
-            <param-ref id="runtime.datasource.core.ldap.baseUrl"/>
-            <param-ref id="runtime.datasource.core.ldap.useSSL"/>
-            <param-ref id="runtime.datasource.core.ldap.baseDN"/>
-            <param-ref id="runtime.datasource.core.ldap.authMethod"/>
-            <param-ref id="runtime.datasource.core.ldap.adminDN"/>
-            <param-ref id="runtime.datasource.core.ldap.adminPasswd"/>
-            <param-ref id="runtime.datasource.core.ldap.aliasDereferencing"/>
-            <param-ref id="runtime.datasource.core.ldap.followReferrals"/>
+            <param-ref id="runtime.datasource.core.ldap"/>
             
             <param-ref id="runtime.users.ldap.peopleDN"/>
             <param-ref id="runtime.users.ldap.baseFilter"/>
@@ -888,15 +665,6 @@
                        id="org.ametys.plugins.core.CredentialsAwareLdapAndJdbc"
                        class="org.ametys.plugins.core.impl.user.mixed.CredentialsAwareLdapAndJdbcUsersManager"
                        logger="org.ametys.plugins.core.impl.user.mixed.ldap.and.jdbc.credential">
-                <BaseUrl>runtime.datasource.core.ldap.baseUrl</BaseUrl>
-                <UseSSL>runtime.datasource.core.ldap.useSSL</UseSSL>
-                <BaseDN>runtime.datasource.core.ldap.baseDN</BaseDN>
-                <AuthenticationMethod>runtime.datasource.core.ldap.authMethod</AuthenticationMethod>
-                <AdminDN>runtime.datasource.core.ldap.adminDN</AdminDN>
-                <AdminPassword>runtime.datasource.core.ldap.adminPasswd</AdminPassword>
-                <AliasDereferencing>runtime.datasource.core.ldap.aliasDereferencing</AliasDereferencing>
-                <FollowReferrals>runtime.datasource.core.ldap.followReferrals</FollowReferrals>
-                
                 <RelativeDN>runtime.users.ldap.peopleDN</RelativeDN>
                 <Filter>runtime.users.ldap.baseFilter</Filter>
                 <SearchScope>runtime.users.ldap.scope</SearchScope>
@@ -962,14 +730,7 @@
             This features defines the base ldap implementation of groups where the group information is handle by the group object
          -->
         <config>
-            <param-ref id="runtime.datasource.core.ldap.baseUrl"/>
-            <param-ref id="runtime.datasource.core.ldap.useSSL"/>
-            <param-ref id="runtime.datasource.core.ldap.baseDN"/>
-            <param-ref id="runtime.datasource.core.ldap.authMethod"/>
-            <param-ref id="runtime.datasource.core.ldap.adminDN"/>
-            <param-ref id="runtime.datasource.core.ldap.adminPasswd"/>
-            <param-ref id="runtime.datasource.core.ldap.aliasDereferencing"/>
-            <param-ref id="runtime.datasource.core.ldap.followReferrals"/>
+            <param-ref id="runtime.datasource.core.ldap"/>
             
             <param-ref id="runtime.groups.ldap.groupDN"/>
             <param-ref id="runtime.groups.ldap.filter"/>
@@ -986,15 +747,6 @@
                        id="org.ametys.plugins.core.group.GroupDrivenLdap"
                        class="org.ametys.plugins.core.impl.group.ldap.GroupDrivenLdapGroupsManager"
                        logger="org.ametys.plugins.core.impl.group.groupdriven">
-                <BaseUrl>runtime.datasource.core.ldap.baseUrl</BaseUrl>
-                <UseSSL>runtime.datasource.core.ldap.useSSL</UseSSL>
-                <BaseDN>runtime.datasource.core.ldap.baseDN</BaseDN>
-                <AuthenticationMethod>runtime.datasource.core.ldap.authMethod</AuthenticationMethod>
-                <AdminDN>runtime.datasource.core.ldap.adminDN</AdminDN>
-                <AdminPassword>runtime.datasource.core.ldap.adminPasswd</AdminPassword>
-                <AliasDereferencing>runtime.datasource.core.ldap.aliasDereferencing</AliasDereferencing>
-                <FollowReferrals>runtime.datasource.core.ldap.followReferrals</FollowReferrals>
-                
                 <RelativeDN>runtime.groups.ldap.groupDN</RelativeDN>
                 <Filter>runtime.groups.ldap.filter</Filter>
                 <SearchScope>runtime.groups.ldap.scope</SearchScope>
@@ -1013,14 +765,7 @@
             This features defines the base ldap implementation of groups where the group information is handle by the user object
          -->
         <config>
-            <param-ref id="runtime.datasource.core.ldap.baseUrl"/>
-            <param-ref id="runtime.datasource.core.ldap.useSSL"/>
-            <param-ref id="runtime.datasource.core.ldap.baseDN"/>
-            <param-ref id="runtime.datasource.core.ldap.authMethod"/>
-            <param-ref id="runtime.datasource.core.ldap.adminDN"/>
-            <param-ref id="runtime.datasource.core.ldap.adminPasswd"/>
-            <param-ref id="runtime.datasource.core.ldap.aliasDereferencing"/>
-            <param-ref id="runtime.datasource.core.ldap.followReferrals"/>
+            <param-ref id="runtime.datasource.core.ldap"/>
             
             <param-ref id="runtime.groups.ldap.groupDN"/>
             <param-ref id="runtime.groups.ldap.filter"/>
@@ -1039,15 +784,6 @@
                        id="org.ametys.plugins.core.group.UsersDrivenLdap"
                        class="org.ametys.plugins.core.impl.group.ldap.UserDrivenLdapGroupsManager"
                        logger="org.ametys.plugins.core.impl.group.usersdriven">
-                <BaseUrl>runtime.datasource.core.ldap.baseUrl</BaseUrl>
-                <UseSSL>runtime.datasource.core.ldap.useSSL</UseSSL>
-                <BaseDN>runtime.datasource.core.ldap.baseDN</BaseDN>
-                <AuthenticationMethod>runtime.datasource.core.ldap.authMethod</AuthenticationMethod>
-                <AdminDN>runtime.datasource.core.ldap.adminDN</AdminDN>
-                <AdminPassword>runtime.datasource.core.ldap.adminPasswd</AdminPassword>
-                <AliasDereferencing>runtime.datasource.core.ldap.aliasDereferencing</AliasDereferencing>
-                <FollowReferrals>runtime.datasource.core.ldap.followReferrals</FollowReferrals>
-                
                 <RelativeDN>runtime.groups.ldap.groupDN</RelativeDN>
                 <Filter>runtime.groups.ldap.filter</Filter>
                 <SearchScope>runtime.groups.ldap.scope</SearchScope>
@@ -1063,26 +799,16 @@
         </components>
     </feature>
     
-    <feature name="runtime.groups.impl.ldap.and.jdbc.userDriven" depends="runtime.datasource.core">
+    <feature name="runtime.groups.impl.ldap.and.jdbc.userDriven">
         <!-- 
             This users manager will search for users into the ldap (users driven) and into the sql db.
             @see:plugin{feature/runtime.groups.impl.ldap.usersDriven}
             @see:plugin{feature/runtime.groups.impl.jdbc}
          -->
         <config>
-            <param-ref id="runtime.datasource.core.jdbc.driver"/>
-            <param-ref id="runtime.datasource.core.jdbc.url"/>
-            <param-ref id="runtime.datasource.core.jdbc.user"/>
-            <param-ref id="runtime.datasource.core.jdbc.passwd"/>
+            <param-ref id="runtime.datasource.core.jdbc.pool"/>
             
-            <param-ref id="runtime.datasource.core.ldap.baseUrl"/>
-            <param-ref id="runtime.datasource.core.ldap.useSSL"/>
-            <param-ref id="runtime.datasource.core.ldap.baseDN"/>
-            <param-ref id="runtime.datasource.core.ldap.authMethod"/>
-            <param-ref id="runtime.datasource.core.ldap.adminDN"/>
-            <param-ref id="runtime.datasource.core.ldap.adminPasswd"/>
-            <param-ref id="runtime.datasource.core.ldap.aliasDereferencing"/>
-            <param-ref id="runtime.datasource.core.ldap.followReferrals"/>
+            <param-ref id="runtime.datasource.core.ldap"/>
             
             <param-ref id="runtime.groups.ldap.groupDN"/>
             <param-ref id="runtime.groups.ldap.filter"/>
@@ -1101,15 +827,6 @@
                        id="org.ametys.plugins.core.group.UserDrivenLdapAndJdbc"
                        class="org.ametys.plugins.core.impl.group.mixed.UserDrivenLdapAndJdbcGroupsManager"
                        logger="org.ametys.plugins.core.impl.group.userdriven.ldap.and.jdbc">
-                <BaseUrl>runtime.datasource.core.ldap.baseUrl</BaseUrl>
-                <UseSSL>runtime.datasource.core.ldap.useSSL</UseSSL>
-                <BaseDN>runtime.datasource.core.ldap.baseDN</BaseDN>
-                <AuthenticationMethod>runtime.datasource.core.ldap.authMethod</AuthenticationMethod>
-                <AdminDN>runtime.datasource.core.ldap.adminDN</AdminDN>
-                <AdminPassword>runtime.datasource.core.ldap.adminPasswd</AdminPassword>
-                <AliasDereferencing>runtime.datasource.core.ldap.aliasDereferencing</AliasDereferencing>
-                <FollowReferrals>runtime.datasource.core.ldap.followReferrals</FollowReferrals>
-                
                 <RelativeDN>runtime.groups.ldap.groupDN</RelativeDN>
                 <Filter>runtime.groups.ldap.filter</Filter>
                 <SearchScope>runtime.groups.ldap.scope</SearchScope>
@@ -1146,19 +863,9 @@
             @see:plugin{feature/runtime.groups.impl.jdbc}
          -->
         <config>
-            <param-ref id="runtime.datasource.core.jdbc.driver"/>
-            <param-ref id="runtime.datasource.core.jdbc.url"/>
-            <param-ref id="runtime.datasource.core.jdbc.user"/>
-            <param-ref id="runtime.datasource.core.jdbc.passwd"/>
+            <param-ref id="runtime.datasource.core.jdbc.pool"/>
             
-            <param-ref id="runtime.datasource.core.ldap.baseUrl"/>
-            <param-ref id="runtime.datasource.core.ldap.useSSL"/>
-            <param-ref id="runtime.datasource.core.ldap.baseDN"/>
-            <param-ref id="runtime.datasource.core.ldap.authMethod"/>
-            <param-ref id="runtime.datasource.core.ldap.adminDN"/>
-            <param-ref id="runtime.datasource.core.ldap.adminPasswd"/>
-            <param-ref id="runtime.datasource.core.ldap.aliasDereferencing"/>
-            <param-ref id="runtime.datasource.core.ldap.followReferrals"/>
+            <param-ref id="runtime.datasource.core.ldap"/>
             
             <param-ref id="runtime.groups.ldap.groupDN"/>
             <param-ref id="runtime.groups.ldap.filter"/>
@@ -1175,15 +882,6 @@
                        id="org.ametys.plugins.core.group.GroupDrivenLdapAndJdbc"
                        class="org.ametys.plugins.core.impl.group.mixed.GroupDrivenLdapAndJdbcGroupsManager"
                        logger="org.ametys.plugins.core.impl.group.userdriven.ldap.and.jdbc">
-                <BaseUrl>runtime.datasource.core.ldap.baseUrl</BaseUrl>
-                <UseSSL>runtime.datasource.core.ldap.useSSL</UseSSL>
-                <BaseDN>runtime.datasource.core.ldap.baseDN</BaseDN>
-                <AuthenticationMethod>runtime.datasource.core.ldap.authMethod</AuthenticationMethod>
-                <AdminDN>runtime.datasource.core.ldap.adminDN</AdminDN>
-                <AdminPassword>runtime.datasource.core.ldap.adminPasswd</AdminPassword>
-                <AliasDereferencing>runtime.datasource.core.ldap.aliasDereferencing</AliasDereferencing>
-                <FollowReferrals>runtime.datasource.core.ldap.followReferrals</FollowReferrals>
-                
                 <RelativeDN>runtime.groups.ldap.groupDN</RelativeDN>
                 <Filter>runtime.groups.ldap.filter</Filter>
                 <SearchScope>runtime.groups.ldap.scope</SearchScope>
@@ -1377,29 +1075,6 @@
         </components>
     </feature>
     
-    <feature name="runtime.datasource.core" passive="true">
-        <!--
-            This feature defines the pool of connection to the database.
-         -->
-        <config>
-            <param-ref id="runtime.datasource.core.jdbc.driver"/>
-            <param-ref id="runtime.datasource.core.jdbc.url"/>
-            <param-ref id="runtime.datasource.core.jdbc.user"/>
-            <param-ref id="runtime.datasource.core.jdbc.passwd"/>
-        </config>
-        
-        <extensions>
-            <extension point="org.ametys.core.datasource.DataSourceExtensionPoint" 
-                       id="runtime.datasource.core.jdbc.pool"
-                       logger="org.ametys.plugins.core..datasource.core.jdbc.pool">
-                <driver runtime-config-parameter="runtime.datasource.core.jdbc.driver"/>
-                <dburl runtime-config-parameter="runtime.datasource.core.jdbc.url"/>
-                <user runtime-config-parameter="runtime.datasource.core.jdbc.user"/>
-                <password runtime-config-parameter="runtime.datasource.core.jdbc.passwd"/>
-            </extension>
-        </extensions>
-    </feature>
-    
     <feature name="runtime.user.preferences.empty" safe="true">
         <!-- 
             A users'preferences manager that do not store anything. Usefull, if you do not user users prefs. 
@@ -1530,4 +1205,78 @@
                        logger="org.ametys.plugins.core.impl.right.context.default"/>
         </components>
     </feature>
+    
+    <!-- +
+         | HANDLED SQL DATABASE TYPES
+         + -->
+          
+    <!-- Derby -->
+    <feature name="runtime.core.datasources.sql.derby" safe="true">
+        <extensions>
+            <extension point="org.ametys.core.datasource.sql.dbtype.SQLDatabaseTypeExtensionPoint"
+                       id="org.ametys.core.datasource.sql.dbtype.derby"
+                       class="org.ametys.plugins.core.impl.datasource.StaticSQLDatabaseType">
+                 <driver>org.apache.derby.jdbc.EmbeddedDriver</driver>
+                 <label i18n="true">PLUGINS_CORE_DATASOURCE_DERBY_DRIVER_LABEL</label>
+                 <template>jdbc:derby:path/to/db;create=true</template>
+                 <driver-not-found-message i18n="true">PLUGINS_CORE_DATASOURCE_DRIVER_NOT_FOUND</driver-not-found-message>
+            </extension>
+        </extensions>
+    </feature>
+    
+    <!-- MySQL -->
+    <feature name="runtime.core.datasources.sql.mysql" safe="true">
+        <extensions>        
+            <extension point="org.ametys.core.datasource.sql.dbtype.SQLDatabaseTypeExtensionPoint"
+                       id="org.ametys.core.datasource.sql.dbtype.mysql"
+                       class="org.ametys.plugins.core.impl.datasource.StaticSQLDatabaseType">
+                 <driver>com.mysql.jdbc.Driver</driver>
+                 <label i18n="true">PLUGINS_CORE_DATASOURCE_MYSQL_DRIVER_LABEL</label>
+                 <template>jdbc:mysql://&lt;servername&gt;/&lt;dbname&gt;</template>
+                 <driver-not-found-message i18n="true">PLUGINS_CORE_DATASOURCE_DRIVER_NOT_FOUND</driver-not-found-message>
+            </extension>
+        </extensions>
+    </feature>
+       
+    <!-- HSQL -->
+    <feature name="runtime.core.datasources.sql.hsql" safe="true">
+        <extensions>
+            <extension point="org.ametys.core.datasource.sql.dbtype.SQLDatabaseTypeExtensionPoint"
+                       id="org.ametys.core.datasource.sql.dbtype.hsql"
+                       class="org.ametys.plugins.core.impl.datasource.StaticSQLDatabaseType">
+                 <driver>org.hsqldb.jdbc.JDBCDriver</driver>
+                 <label i18n="true">PLUGINS_CORE_DATASOURCE_HSQL_DRIVER_LABEL</label>
+                 <template>jdbc:hsql:path/to/db</template>
+                 <driver-not-found-message i18n="true">PLUGINS_CORE_DATASOURCE_DRIVER_NOT_FOUND</driver-not-found-message>
+            </extension>
+        </extensions>
+    </feature>
+    
+    <!-- PostGreSQL -->
+    <feature name="runtime.core.datasources.sql.postgresql" safe="true">
+        <extensions>        
+            <extension point="org.ametys.core.datasource.sql.dbtype.SQLDatabaseTypeExtensionPoint"
+                       id="org.ametys.core.datasource.sql.dbtype.postgresql"
+                       class="org.ametys.plugins.core.impl.datasource.StaticSQLDatabaseType">
+                 <driver>org.postgresql.Driver</driver>
+                 <label i18n="true">PLUGINS_CORE_DATASOURCE_POSTGRESQL_DRIVER_LABEL</label>
+                 <template>jdbc:postgresql://&lt;servername&gt;/&lt;dbname&gt;</template>
+                 <driver-not-found-message i18n="true">PLUGINS_CORE_DATASOURCE_DRIVER_NOT_FOUND</driver-not-found-message>
+            </extension>
+        </extensions>
+    </feature>
+    
+    <!-- Oracle -->
+    <feature name="runtime.core.datasources.sql.oracle" safe="true">
+        <extensions>
+            <extension point="org.ametys.core.datasource.sql.dbtype.SQLDatabaseTypeExtensionPoint"
+                       id="org.ametys.core.datasource.sql.dbtype.oracle"
+                       class="org.ametys.plugins.core.impl.datasource.StaticSQLDatabaseType">
+                 <driver>oracle.jdbc.driver.OracleDriver</driver>
+                 <label i18n="true">PLUGINS_CORE_DATASOURCE_ORACLE_DRIVER_LABEL</label>
+                 <template>jdbc:oracle:thin:@&lt;hostname&gt;:&lt;port&gt;:&lt;sid&gt;</template>
+                 <driver-not-found-message i18n="true">PLUGINS_CORE_DATASOURCE_ORACLE_DRIVER_NOT_FOUND</driver-not-found-message>
+            </extension>
+        </extensions>
+    </feature>
 </plugin>
\ No newline at end of file
Index: main/plugin-core-impl/src/org/ametys/plugins/core/impl/authentication/FormBasedCredentialsProvider.java
===================================================================
--- main/plugin-core-impl/src/org/ametys/plugins/core/impl/authentication/FormBasedCredentialsProvider.java	(revision 38980)
+++ main/plugin-core-impl/src/org/ametys/plugins/core/impl/authentication/FormBasedCredentialsProvider.java	(working copy)
@@ -100,8 +100,8 @@
     /** Default cookie lifetime (15 days in seconds) */
     public static final int DEFAULT_COOKIE_LIFETIME = 1209600;
     
-    /** The pool name */
-    protected String _poolName;
+    /** The configuration parameter id of the connection pool */
+    protected String _poolConfigParam;
     /** Name of the user name html field */
     protected String _usernameField;
 
@@ -343,12 +343,12 @@
      */
     protected void _insertUserToken(String login, String salt, String hashedTokenAndSalt)
     {
-        Connection connection = null;
         PreparedStatement statement = null;
         ResultSet rs = null;
-        try
+
+        String dataSourceId = Config.getInstance().getValueAsString(_poolConfigParam);
+        try (Connection connection = ConnectionHelper.getConnection(dataSourceId);)
         {
-            connection = ConnectionHelper.getConnection(_poolName);
             DatabaseType dbType = ConnectionHelper.getDatabaseType(connection);
             
             if (dbType.equals(DatabaseType.DATABASE_ORACLE))
@@ -390,7 +390,6 @@
         finally
         {
             ConnectionHelper.cleanup(statement);       
-            ConnectionHelper.cleanup(connection);
         }
     }
     /**
@@ -399,18 +398,16 @@
      */
     protected void _deleteLoginFailedBDD(String login)
     {
-        Connection con = null;
         PreparedStatement stmt = null;
         ResultSet rs = null;
-        try
+        
+        String dataSourceId = Config.getInstance().getValueAsString(ConnectionHelper.CORE_POOL_CONFIG_PARAM);
+        try (Connection connection =  ConnectionHelper.getConnection(dataSourceId))
         {
-            // Effectuer la connexion à la base de données
-            con = ConnectionHelper.getConnection(ConnectionHelper.CORE_POOL_NAME);    
-            
             // Contruire la requête pour authentifier l'utilisateur
             String sql = "DELETE FROM Users_FormConnectionFailed WHERE login = ?";
             
-            stmt = con.prepareStatement(sql);
+            stmt = connection.prepareStatement(sql);
             stmt.setString(1, login);
             
             // Effectuer la requête
@@ -425,7 +422,6 @@
             // Fermer les ressources de connexion
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(con);
         }
         
     }
@@ -437,18 +433,17 @@
      */
     protected Integer _requestNbConnectBDD(String login)
     {
-        Connection con = null;
         PreparedStatement stmt = null;
         ResultSet rs = null;
-        try
+        
+        String dataSourceId = Config.getInstance().getValueAsString(ConnectionHelper.CORE_POOL_CONFIG_PARAM);
+        try (Connection connection =  ConnectionHelper.getConnection(dataSourceId);)
         {
-            // Effectuer la connexion à la base de données
-            con = ConnectionHelper.getConnection(ConnectionHelper.CORE_POOL_NAME);    
             
             // Contruire la requête pour authentifier l'utilisateur
             String sql = "SELECT nb_connect FROM Users_FormConnectionFailed WHERE login = ?";
             
-            stmt = con.prepareStatement(sql);
+            stmt = connection.prepareStatement(sql);
             stmt.setString(1, login);
     
             // Effectuer la requête
@@ -471,7 +466,6 @@
             // Fermer les ressources de connexion
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(con);
         }
     }
     
@@ -502,17 +496,15 @@
      */
     protected void _insertLoginNbConnectBDD(String login)
     {
-        Connection con = null;
         PreparedStatement stmt = null;
         ResultSet rs = null;
-        try
+        
+        String dataSourceId = Config.getInstance().getValueAsString(ConnectionHelper.CORE_POOL_CONFIG_PARAM);
+        try (Connection connection =  ConnectionHelper.getConnection(dataSourceId);)
         {
-         // Effectuer la connexion à la base de données
-            con = ConnectionHelper.getConnection(ConnectionHelper.CORE_POOL_NAME);    
-            
             String sqlUpdate = "INSERT INTO Users_FormConnectionFailed (login, nb_connect, last_connect) VALUES (?, ?, ?)";
            
-            stmt = con.prepareStatement(sqlUpdate);
+            stmt = connection.prepareStatement(sqlUpdate);
             stmt.setString(1, login);
             stmt.setInt(2, 1);
             
@@ -532,7 +524,6 @@
             // Fermer les ressources de connexion
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(con);
         }
     }
     
@@ -543,17 +534,15 @@
      */
     protected void _updateLoginNbConnectBDD(String login, Integer nbConnect)
     {
-        Connection con = null;
         PreparedStatement stmt = null;
         ResultSet rs = null;
-        try
-        {
-            // Effectuer la connexion à la base de données
-            con = ConnectionHelper.getConnection(ConnectionHelper.CORE_POOL_NAME);    
-            
+        
+        String dataSourceId = Config.getInstance().getValueAsString(ConnectionHelper.CORE_POOL_CONFIG_PARAM);
+        try (Connection connection =  ConnectionHelper.getConnection(dataSourceId);)
+        {   
             String sqlUpdate = "UPDATE Users_FormConnectionFailed SET nb_connect = ? WHERE login = ?";
            
-            stmt = con.prepareStatement(sqlUpdate);
+            stmt = connection.prepareStatement(sqlUpdate);
             stmt.setInt(1, nbConnect + 1);
             stmt.setString(2, login);
             
@@ -568,7 +557,6 @@
             // Fermer les ressources de connexion
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(con);
         }
     }
     
@@ -625,7 +613,7 @@
     @Override
     public void configure(Configuration configuration) throws ConfigurationException
     {
-        _poolName = configuration.getChild("pool").getValue(ConnectionHelper.CORE_POOL_NAME);
+        _poolConfigParam = configuration.getChild("pool").getValue(ConnectionHelper.CORE_POOL_CONFIG_PARAM);
         _usernameField = configuration.getChild("username-field").getValue("Username");
         _passwordField = configuration.getChild("password-field").getValue("Password");
         _rememberMeField =  configuration.getChild("rememberMe-field").getValue("rememberMe");
Index: main/plugin-core-impl/src/org/ametys/plugins/core/impl/authentication/token/TokenCredentials.java
===================================================================
--- main/plugin-core-impl/src/org/ametys/plugins/core/impl/authentication/token/TokenCredentials.java	(revision 38980)
+++ main/plugin-core-impl/src/org/ametys/plugins/core/impl/authentication/token/TokenCredentials.java	(working copy)
@@ -27,6 +27,7 @@
 
 import org.ametys.core.authentication.Credentials;
 import org.ametys.core.datasource.ConnectionHelper;
+import org.ametys.runtime.config.Config;
 
 /**
  * Credentials coming from more than one source.
@@ -61,7 +62,8 @@
      */
     public boolean checkToken()
     {
-        try (Connection connection = ConnectionHelper.getConnection(ConnectionHelper.CORE_POOL_NAME))
+        String dataSourceId = Config.getInstance().getValueAsString(ConnectionHelper.CORE_POOL_CONFIG_PARAM);
+        try (Connection connection = ConnectionHelper.getConnection(dataSourceId))
         {
             // Delete 2 weeks or more old entries
             try (PreparedStatement deleteStatement = _getDeleteOldUserTokenStatement(connection))
Index: main/plugin-core-impl/src/org/ametys/plugins/core/impl/checker/LDAPConnectionChecker.java
===================================================================
--- main/plugin-core-impl/src/org/ametys/plugins/core/impl/checker/LDAPConnectionChecker.java	(revision 38980)
+++ main/plugin-core-impl/src/org/ametys/plugins/core/impl/checker/LDAPConnectionChecker.java	(nonexistent)
@@ -1,128 +0,0 @@
-/*
- *  Copyright 2014 Anyware Services
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package org.ametys.plugins.core.impl.checker;
-
-import java.util.Hashtable;
-import java.util.Map;
-
-import javax.naming.Context;
-import javax.naming.NamingException;
-import javax.naming.directory.DirContext;
-import javax.naming.directory.InitialDirContext;
-
-import org.apache.avalon.framework.configuration.Configurable;
-import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.avalon.framework.logger.AbstractLogEnabled;
-
-import org.ametys.runtime.parameter.ParameterChecker;
-import org.ametys.runtime.parameter.ParameterCheckerTestFailureException;
-
-/**
- * Checks if the connection to the LDAP is possible and then verifies the DN. 
- */
-public class LDAPConnectionChecker extends AbstractLogEnabled implements ParameterChecker, Configurable
-{
-    private String _paramBaseDN;
-    private String _paramFollowReferrals;
-    private String _paramBaseUrl;
-    private String _paramAuthMethod;
-    private String _paramAdminDN;
-    private String _paramAdminPasswd;
-    private String _paramUseSSL;
-
-    @Override
-    public void configure(Configuration configuration) throws ConfigurationException
-    {
-        Configuration[] config = configuration.getChild("linked-params").getChildren();
-        if (config.length != 7)
-        {
-            throw new ConfigurationException("The LDAPConnectionChecker should have 7 linked params in the right order: baseUrl, useSSL, baseDN, authMethod, adminDN, adminPassws, followReferrals");
-        }
-        
-        int i = 0;
-        _paramBaseUrl = config[i++].getAttribute("id");
-        _paramUseSSL = config[i++].getAttribute("id");
-        _paramBaseDN = config[i++].getAttribute("id");
-        _paramAuthMethod = config[i++].getAttribute("id");
-        _paramAdminDN = config[i++].getAttribute("id");
-        _paramAdminPasswd = config[i++].getAttribute("id");
-        _paramFollowReferrals = config[i++].getAttribute("id");
-    }
-    
-    @Override
-    public void check(Map<String, String> configurationParameters) throws ParameterCheckerTestFailureException
-    {
-        Hashtable<String, String> env = new Hashtable<>();
-        
-        // Get the parameter values
-        String baseUrl = configurationParameters.get(_paramBaseUrl);
-        String authMethod = configurationParameters.get(_paramAuthMethod);
-        String adminDN = configurationParameters.get(_paramAdminDN);
-        String adminPassword = configurationParameters.get(_paramAdminPasswd);
-        String useSSL = configurationParameters.get(_paramUseSSL);
-        String followReferrals = configurationParameters.get(_paramFollowReferrals);
-        String baseDN = configurationParameters.get(_paramBaseDN);
-        
-        // Define the corresponding context
-        env.put(Context.PROVIDER_URL, baseUrl);
-        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
-        env.put(Context.SECURITY_AUTHENTICATION, authMethod);
-        
-        if (authMethod.equals("simple"))
-        {
-            env.put(Context.SECURITY_PRINCIPAL, adminDN);
-            env.put(Context.SECURITY_CREDENTIALS, adminPassword);
-        }
-        if (useSSL.equals("true"))
-        {
-            env.put(Context.SECURITY_PROTOCOL, "ssl");
-        }
-        if (followReferrals.equals("true"))
-        {
-            env.put(Context.REFERRAL, "follow");
-        }
-        
-        DirContext context = null;
-        try
-        {
-            // Try and connect
-            context = new InitialDirContext(env);
-            
-            // Check base DN
-            context.search(baseDN, null);
-        }
-        catch (NamingException e)
-        {
-            throw new ParameterCheckerTestFailureException(e);
-        }
-        finally
-        {
-            // Close environment
-            if (context != null)
-            {
-                try
-                {
-                    context.close();
-                }
-                catch (NamingException e)
-                {
-                    getLogger().error("Closing the LDAP connection during test failed.", e);
-                }
-            }
-        }
-    }
-}
Index: main/plugin-core-impl/src/org/ametys/plugins/core/impl/checker/SQLConnectionChecker.java
===================================================================
--- main/plugin-core-impl/src/org/ametys/plugins/core/impl/checker/SQLConnectionChecker.java	(revision 0)
+++ main/plugin-core-impl/src/org/ametys/plugins/core/impl/checker/SQLConnectionChecker.java	(revision 0)
@@ -0,0 +1,61 @@
+package org.ametys.plugins.core.impl.checker;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.util.Map;
+
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+
+import org.ametys.core.datasource.ConnectionHelper;
+import org.ametys.runtime.parameter.ParameterChecker;
+import org.ametys.runtime.parameter.ParameterCheckerTestFailureException;
+
+
+/**
+ * Checks if a SQL connection can be established 
+ */
+public class SQLConnectionChecker extends AbstractLogEnabled implements ParameterChecker
+{
+    @Override
+    public void check(Map<String, String> parameters) throws ParameterCheckerTestFailureException
+    {
+        String driver = parameters.get("driver");
+        String url = parameters.get("url");
+        String password = parameters.get("password");
+        String login = parameters.get("user");
+        String driverNotFoundMessage = parameters.get("driverNotFoundMessage");
+        
+        Connection connection = null;
+        try 
+        {
+            Class.forName(driver);
+            connection = DriverManager.getConnection(url, login, password);
+        }
+        catch (ClassNotFoundException cnfe)
+        {
+            if (driverNotFoundMessage != null)
+            {
+                throw new ParameterCheckerTestFailureException(driverNotFoundMessage, cnfe);
+            }
+            throw new ParameterCheckerTestFailureException("The given driver classpath was not found. Try to put the driver's jar in the WEB-INF/lib folder and reboot the application", cnfe);
+        }
+        catch (Exception e)
+        {
+            throw new ParameterCheckerTestFailureException(e.getMessage(), e);
+        }
+        finally
+        {
+            if (connection != null)
+            {
+                try
+                {
+                    ConnectionHelper.cleanup(connection);
+                }
+                catch (Exception e)
+                {
+                    throw new ParameterCheckerTestFailureException(e.getMessage(), e);
+                }
+            }
+        }
+    }
+}
Index: main/plugin-core-impl/src/org/ametys/plugins/core/impl/checker/SqlConnectionChecker.java
===================================================================
--- main/plugin-core-impl/src/org/ametys/plugins/core/impl/checker/SqlConnectionChecker.java	(revision 38980)
+++ main/plugin-core-impl/src/org/ametys/plugins/core/impl/checker/SqlConnectionChecker.java	(nonexistent)
@@ -1,95 +0,0 @@
-/*
- *  Copyright 2014 Anyware Services
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package org.ametys.plugins.core.impl.checker;
-
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.util.Map;
-
-import org.apache.avalon.framework.configuration.Configurable;
-import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.avalon.framework.logger.AbstractLogEnabled;
-
-import org.ametys.core.datasource.ConnectionHelper;
-import org.ametys.runtime.parameter.ParameterChecker;
-import org.ametys.runtime.parameter.ParameterCheckerTestFailureException;
-
-/**
- * Checks the SQL connection with the data written in the configuration panel
- */
-public class SqlConnectionChecker extends AbstractLogEnabled implements ParameterChecker, Configurable
-{
-    private Object _paramDriver;
-    private String _paramURL;
-    private String _paramUser;
-    private String _paramPasswd;
-
-    @Override
-    public void configure(Configuration configuration) throws ConfigurationException
-    {
-        Configuration[] config = configuration.getChild("linked-params").getChildren();
-        if (config.length != 4)
-        {
-            throw new ConfigurationException("The SqlConnectionChecker should have exactly 4 linked params in the following order: driver, url, user, password");
-        }
-        
-        int i = 0;
-        _paramDriver = config[i++].getAttribute("id");
-        _paramURL = config[i++].getAttribute("id");
-        _paramUser = config[i++].getAttribute("id");
-        _paramPasswd = config[i++].getAttribute("id");
-    }
-    
-    @Override
-    public void check(Map<String, String> configurationParameters) throws ParameterCheckerTestFailureException
-    {
-        String password = configurationParameters.get(_paramPasswd);
-        String driver = configurationParameters.get(_paramDriver);
-        String url = configurationParameters.get(_paramURL);
-        String login = configurationParameters.get(_paramUser);
-        
-        Connection connection = null;
-        try 
-        {
-            Class.forName(driver);
-            connection = DriverManager.getConnection(url, login, password);
-        }
-        catch (ClassNotFoundException cnfe)
-        {
-            throw new ParameterCheckerTestFailureException("The given driver classpath was not found. Try to put the driver's jar in the WEB-INF/lib folder and reboot the application", cnfe);
-        }
-        catch (Exception e)
-        {
-            throw new ParameterCheckerTestFailureException(e.getMessage(), e);
-        }
-        finally
-        {
-            if (connection != null)
-            {
-                try
-                {
-                    ConnectionHelper.cleanup(connection);
-                }
-                catch (Exception e)
-                {
-                    throw new ParameterCheckerTestFailureException(e.getMessage(), e);
-                }
-            }
-        }
-    }
-}
Index: main/plugin-core-impl/src/org/ametys/plugins/core/impl/datasource/StaticSQLDatabaseType.java
===================================================================
--- main/plugin-core-impl/src/org/ametys/plugins/core/impl/datasource/StaticSQLDatabaseType.java	(revision 0)
+++ main/plugin-core-impl/src/org/ametys/plugins/core/impl/datasource/StaticSQLDatabaseType.java	(revision 0)
@@ -0,0 +1,111 @@
+/*
+ *  Copyright 2015 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.ametys.plugins.core.impl.datasource;
+
+import org.apache.avalon.framework.configuration.Configurable;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+
+import org.ametys.core.datasource.sql.dbtype.SQLDatabaseType;
+import org.ametys.runtime.i18n.I18nizableText;
+import org.ametys.runtime.plugin.component.AbstractLogEnabled;
+import org.ametys.runtime.plugin.component.PluginAware;
+import org.ametys.runtime.util.ConfigurationHelper;
+
+/**
+ * Default implementation for a {@link SQLDatabaseType}.
+ */
+public class StaticSQLDatabaseType extends AbstractLogEnabled implements Configurable, SQLDatabaseType, PluginAware
+{
+    /** The id of the database type */
+    private String _id;
+    
+    /** The label of the database type */
+    private I18nizableText _label;
+
+    /** The driver of the database type */
+    private String _driver;
+    
+    /** The url template for this database type */
+    private String _template;
+    
+    /** The plugin's name */
+    private String _pluginName;
+    
+    /** The driver not found message */
+    private I18nizableText _driverNotFoundMessage;
+    
+    public void setPluginInfo(String pluginName, String featureName)
+    {
+        _pluginName = pluginName;
+    }
+    
+    @Override
+    public void configure(Configuration configuration) throws ConfigurationException
+    {
+        _id = configuration.getAttribute("id");
+        if (getLogger().isDebugEnabled())
+        {
+            getLogger().debug("Configuring database type '" + _id + "'");
+        }
+        
+        _label = ConfigurationHelper.parseI18nizableText(configuration.getChild("label"), "plugin." + _pluginName);
+        
+        _driver = configuration.getChild("driver").getValue();
+        try
+        {
+            Class.forName(_driver);
+        }
+        catch (ClassNotFoundException e)
+        {
+            getLogger().warn("The specified driver '" + _driver + "' was not found in the WEB-INF/lib directory of the application.", e);
+        }
+        
+        _driverNotFoundMessage = ConfigurationHelper.parseI18nizableText(configuration.getChild("driver-not-found-message"), "plugin." + _pluginName); 
+        
+        _template = configuration.getChild("template").getValue("");
+    }
+    
+    @Override
+    public String getId()
+    {
+        return _id;
+    }
+    
+    @Override
+    public I18nizableText getLabel() 
+    {
+        return _label;
+    }
+    
+    @Override
+    public String getDriver() 
+    {
+        return _driver;
+    }
+    
+    @Override
+    public String getTemplate()
+    {
+        return _template;
+    }
+    
+    @Override
+    public I18nizableText getDriverNotFoundMessage()
+    {
+        return _driverNotFoundMessage;
+    }
+}
Index: main/plugin-core-impl/src/org/ametys/plugins/core/impl/group/jdbc/ModifiableJdbcGroupsManager.java
===================================================================
--- main/plugin-core-impl/src/org/ametys/plugins/core/impl/group/jdbc/ModifiableJdbcGroupsManager.java	(revision 38980)
+++ main/plugin-core-impl/src/org/ametys/plugins/core/impl/group/jdbc/ModifiableJdbcGroupsManager.java	(working copy)
@@ -53,6 +53,7 @@
 import org.ametys.core.user.ModifiableUsersManager;
 import org.ametys.core.user.UserListener;
 import org.ametys.core.user.UsersManager;
+import org.ametys.runtime.config.Config;
 import org.ametys.runtime.plugin.PluginsManager;
 import org.ametys.runtime.plugin.component.AbstractLogEnabled;
 
@@ -68,8 +69,8 @@
     /** Group listeners */
     protected List<GroupListener> _listeners = new ArrayList<>();
 
-    /** The name of the jdbc pool to use */
-    protected String _poolName;
+    /** The id of the configuration parameter of the pool to use */
+    protected String _poolConfigParam;
     /** The name of the jdbc table containing the list of groups */
     protected String _groupsListTable;
     /** The name of the jdbc column in <code>_groupsListTable</code> containing the unique identifier of a group */
@@ -92,7 +93,7 @@
     @Override
     public void configure(Configuration configuration) throws ConfigurationException
     {
-        _poolName = configuration.getChild("pool").getValue();
+        _poolConfigParam = configuration.getChild("pool").getValue();
 
         Configuration listConfiguration = configuration.getChild("list");
         _groupsListTable = listConfiguration.getChild("table").getValue("Groups");
@@ -142,14 +143,12 @@
     {
         Group group = null;
 
-        Connection connection = null;
         PreparedStatement stmt = null;
         ResultSet rs = null;
-
-        try
+        
+        String dataSourceId = Config.getInstance().getValueAsString(_poolConfigParam);
+        try (Connection connection =  ConnectionHelper.getConnection(dataSourceId);)
         {
-            connection = ConnectionHelper.getConnection(_poolName);
-
             String sql = "SELECT " + _groupsListColLabel + " FROM " + _groupsListTable + " WHERE " + _groupsListColId + " =  ?";
             stmt = connection.prepareStatement(sql);
             stmt.setInt(1, Integer.parseInt(groupID));
@@ -183,7 +182,6 @@
         {
             ConnectionHelper.cleanup(rs);       
             ConnectionHelper.cleanup(stmt);       
-            ConnectionHelper.cleanup(connection);       
         }
 
         // Retourner le groupe trouvé ou null
@@ -203,15 +201,13 @@
     public Set<Group> getGroups()
     {
         Set<Group> groups = new LinkedHashSet<>();
-
-        Connection connection = null;
+        
         Statement stmt = null;
         ResultSet rs = null;
-
-        try
+        
+        String dataSourceId = Config.getInstance().getValueAsString(_poolConfigParam);
+        try (Connection connection =  ConnectionHelper.getConnection(dataSourceId);)
         {
-            connection = ConnectionHelper.getConnection(_poolName);
-
             stmt = connection.createStatement();
             String sql = _createGetGroupsClause();
 
@@ -243,7 +239,6 @@
         {
             ConnectionHelper.cleanup(rs);       
             ConnectionHelper.cleanup(stmt);       
-            ConnectionHelper.cleanup(connection);       
         }
 
         // Retourner l'ensemble des groupes
@@ -259,14 +254,12 @@
             return groups;
         }
         
-        Connection connection = null;
         PreparedStatement stmt = null;
         ResultSet rs = null;
-
-        try
+        
+        String dataSourceId = Config.getInstance().getValueAsString(_poolConfigParam);
+        try (Connection connection =  ConnectionHelper.getConnection(dataSourceId);)
         {
-            connection = ConnectionHelper.getConnection(_poolName);
-
             String sql = "SELECT " + _groupsCompositionColGroup + " FROM " + _groupsCompositionTable + " WHERE " + _groupsCompositionColUser + " = ?";
             stmt = connection.prepareStatement(sql);
             stmt.setString(1, login);
@@ -295,7 +288,6 @@
         {
             ConnectionHelper.cleanup(rs);       
             ConnectionHelper.cleanup(stmt);       
-            ConnectionHelper.cleanup(connection);       
         }
 
         // Retourner l'ensemble des groupes, éventuellement vide
@@ -309,13 +301,11 @@
      */
     public void removeUserGroups(String login)
     {
-        Connection connection = null;
         PreparedStatement stmt = null;
-
-        try
+        
+        String dataSourceId = Config.getInstance().getValueAsString(_poolConfigParam);
+        try (Connection connection =  ConnectionHelper.getConnection(dataSourceId);)
         {
-            connection = ConnectionHelper.getConnection(_poolName);
-
             String sql = "DELETE FROM " + _groupsCompositionTable + " WHERE Login = ?";
 
             stmt = connection.prepareStatement(sql);
@@ -337,7 +327,6 @@
         finally
         {
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
     }
 
@@ -401,15 +390,14 @@
     @Override
     public Group add(String name) throws InvalidModificationException
     {
-        Connection connection = null; 
-        PreparedStatement statement = null;
-        ResultSet rs = null;
-
         String id = null;
 
-        try
+        PreparedStatement statement = null;
+        ResultSet rs = null;
+        
+        String dataSourceId = Config.getInstance().getValueAsString(_poolConfigParam);
+        try (Connection connection =  ConnectionHelper.getConnection(dataSourceId);)
         {
-            connection = ConnectionHelper.getConnection(_poolName);
             DatabaseType datatype = ConnectionHelper.getDatabaseType(connection);
             
             if (datatype == DatabaseType.DATABASE_ORACLE)
@@ -503,7 +491,6 @@
         {
             ConnectionHelper.cleanup(rs);       
             ConnectionHelper.cleanup(statement);       
-            ConnectionHelper.cleanup(connection);       
         }
 
         return new Group(id, name);
@@ -512,13 +499,11 @@
     @Override
     public void remove(String groupID) throws InvalidModificationException
     {
-        Connection connection = null;
         PreparedStatement statement = null;
-
-        try
+        
+        String dataSourceId = Config.getInstance().getValueAsString(_poolConfigParam);
+        try (Connection connection =  ConnectionHelper.getConnection(dataSourceId);)
         {
-            connection = ConnectionHelper.getConnection(_poolName);
-
             statement = connection.prepareStatement("DELETE FROM " + _groupsListTable + " WHERE " + _groupsListColId + " = ?");
             statement.setInt(1, Integer.parseInt(groupID));
 
@@ -549,20 +534,17 @@
         finally
         {
             ConnectionHelper.cleanup(statement);       
-            ConnectionHelper.cleanup(connection);       
         }
     }
 
     @Override
     public void update(Group userGroup) throws InvalidModificationException
     {
-        Connection connection = null;
         PreparedStatement statement = null;
-
-        try
+        
+        String dataSourceId = Config.getInstance().getValueAsString(_poolConfigParam);
+        try (Connection connection =  ConnectionHelper.getConnection(dataSourceId);)
         {
-            connection = ConnectionHelper.getConnection(_poolName);
-
             // Start transaction.
             connection.setAutoCommit(false);
 
@@ -633,7 +615,6 @@
         finally
         {
             ConnectionHelper.cleanup(statement);
-            ConnectionHelper.cleanup(connection);
         }
     }
     
Index: main/plugin-core-impl/src/org/ametys/plugins/core/impl/group/ldap/AbstractLDAPGroupsManager.java
===================================================================
--- main/plugin-core-impl/src/org/ametys/plugins/core/impl/group/ldap/AbstractLDAPGroupsManager.java	(revision 38980)
+++ main/plugin-core-impl/src/org/ametys/plugins/core/impl/group/ldap/AbstractLDAPGroupsManager.java	(working copy)
@@ -21,6 +21,7 @@
 import java.util.List;
 import java.util.Map;
 
+import org.apache.avalon.framework.configuration.Configurable;
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
 import org.apache.cocoon.xml.XMLUtils;
@@ -36,7 +37,7 @@
 /**
  * This class is the base for groups manager using LDAP
  */
-public abstract class AbstractLDAPGroupsManager extends AbstractLDAPConnector implements GroupsManager
+public abstract class AbstractLDAPGroupsManager extends AbstractLDAPConnector implements GroupsManager, Configurable
 {
     /** The group DN relative to baseDN */
     protected String _groupsRelativeDN;
@@ -52,8 +53,6 @@
     @Override
     public void configure(Configuration configuration) throws ConfigurationException
     {
-        super.configure(configuration);
-        
         _groupsRelativeDN = _getConfigParameter(configuration, "RelativeDN");
         _groupsObjectFilter = _getFilter(configuration, "Filter");
         _groupsSearchScope = _getSearchScope(configuration, "SearchScope");
Index: main/plugin-core-impl/src/org/ametys/plugins/core/impl/right/profile/DefaultProfileBasedRightsManager.java
===================================================================
--- main/plugin-core-impl/src/org/ametys/plugins/core/impl/right/profile/DefaultProfileBasedRightsManager.java	(revision 38980)
+++ main/plugin-core-impl/src/org/ametys/plugins/core/impl/right/profile/DefaultProfileBasedRightsManager.java	(working copy)
@@ -69,6 +69,7 @@
 import org.ametys.core.user.User;
 import org.ametys.core.user.UserListener;
 import org.ametys.core.user.UsersManager;
+import org.ametys.runtime.config.Config;
 import org.ametys.runtime.i18n.I18nizableText;
 import org.ametys.runtime.request.RequestListener;
 import org.ametys.runtime.request.RequestListenerManager;
@@ -99,9 +100,9 @@
     /** The groups manager */
     protected GroupsManager _groupsManager;
 
-    /** The jdbc pool name */
-    protected String _poolName;
-
+    /** The id of the data source used */
+    protected String _dataSourceId;
+    
     /** The jdbc table name for profiles' list */
     protected String _tableProfile;
 
@@ -224,7 +225,7 @@
             throw new ConfigurationException(message, configuration);
         }
 
-        _poolName = poolName;
+        _dataSourceId = Config.getInstance().getValueAsString(poolName);
         _tableProfile = configuration.getChild("table-profile").getValue("Rights_Profile");
         _tableProfileRights = configuration.getChild("table-profile-rights").getValue("Rights_ProfileRights");
         _tableUserRights = configuration.getChild("table-profile-user").getValue("Rights_UserRights");
@@ -629,13 +630,11 @@
         {
             return new HashSet<>();
         }
-
-        Connection connection = ConnectionHelper.getConnection(_poolName);
-
+        
         PreparedStatement stmt = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             // On regarde d'abord parmi les droits affectés directement aux
             // utilisateurs
@@ -666,7 +665,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
 
         return profiles;
@@ -686,12 +684,10 @@
 
         Set<User> users = new HashSet<>();
 
-        Connection connection = ConnectionHelper.getConnection(_poolName);
-
         PreparedStatement stmt = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             String sql = "SELECT DISTINCT Login " + "FROM " + _tableUserRights + " WHERE Profile_Id = ? AND LOWER(Context) = ?";
 
@@ -729,7 +725,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
 
         return users;
@@ -749,12 +744,10 @@
 
         Set<Group> groups = new HashSet<>();
 
-        Connection connection = ConnectionHelper.getConnection(_poolName);
-
         PreparedStatement stmt = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             String sql = "SELECT DISTINCT Group_Id " + "FROM " + _tableGroupRights + " WHERE Profile_Id = ? AND LOWER(Context) = ? ";
 
@@ -792,7 +785,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
 
         return groups;
@@ -815,12 +807,10 @@
             return contexts;
         }
 
-        Connection connection = ConnectionHelper.getConnection(_poolName);
-
         PreparedStatement stmt = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             String sql = "SELECT UR.Context " + "FROM " + _tableUserRights + " UR WHERE UR.Login = ? AND UR.Profile_Id = ?";
 
@@ -853,7 +843,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
 
         return contexts;
@@ -912,12 +901,10 @@
 
         Set<String> profiles = new HashSet<>();
 
-        Connection connection = ConnectionHelper.getConnection(_poolName);
-
         PreparedStatement stmt = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             // On regarde d'abord parmi les droits affectés directement aux
             // utilisateurs
@@ -948,7 +935,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
 
         return profiles;
@@ -966,12 +952,10 @@
     {
         Set<String> contexts = new HashSet<>();
 
-        Connection connection = ConnectionHelper.getConnection(_poolName);
-
         PreparedStatement stmt = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             String sql = "SELECT GR.Context " + "FROM " + _tableGroupRights + " GR WHERE GR.Group_Id = ? AND GR.Profile_Id = ?";
 
@@ -1006,7 +990,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
 
         return contexts;
@@ -1017,11 +1000,10 @@
     {
         String lcContext = getFullContext (context);
 
-        Connection connection = ConnectionHelper.getConnection(_poolName);
-
         PreparedStatement stmt = null;
         ResultSet rs = null;
-        try
+
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             // Check if already exists
             String sql = "SELECT Profile_Id FROM " + _tableUserRights + " WHERE Profile_Id=? and Login=? and Context=?";
@@ -1072,7 +1054,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
     }
 
@@ -1081,11 +1062,10 @@
     {
         String lcContext = getFullContext (context);
 
-        Connection connection = ConnectionHelper.getConnection(_poolName);
-
         PreparedStatement stmt = null;
         ResultSet rs = null;
-        try
+
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             // Check if already exists
             String sql = "SELECT Profile_Id FROM " + _tableGroupRights + " WHERE Profile_Id=? and Group_Id=? and Context=?";
@@ -1136,7 +1116,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
     }
 
@@ -1145,11 +1124,9 @@
     {
         String lcContext = getFullContext (context);
 
-        Connection connection = ConnectionHelper.getConnection(_poolName);
-
         PreparedStatement stmt = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             // On regarde d'abord parmi les droits affectés directement aux
             // utilisateurs
@@ -1182,7 +1159,6 @@
         finally
         {
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
     }
 
@@ -1191,11 +1167,9 @@
     {
         String lcContext = getFullContext (context);
 
-        Connection connection = ConnectionHelper.getConnection(_poolName);
-
         PreparedStatement stmt = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             // On regarde d'abord parmi les droits affectés directement aux
             // utilisateurs
@@ -1229,7 +1203,6 @@
         finally
         {
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
     }
 
@@ -1239,9 +1212,7 @@
         String lcOldContext = getFullContext(oldContext);
         String lcNewContext = getFullContext(newContext);
 
-        Connection connection = ConnectionHelper.getConnection(_poolName);
-
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             updateContext(lcOldContext, lcNewContext, connection);
         }
@@ -1250,10 +1221,6 @@
             getLogger().error("Error in sql query", ex);
             throw new RightsException("Error in sql query", ex);
         }
-        finally
-        {
-            ConnectionHelper.cleanup(connection);
-        }
     }
 
     @Override
@@ -1261,9 +1228,7 @@
     {
         String lcContext = getFullContext(context);
 
-        Connection connection = ConnectionHelper.getConnection(_poolName);
-
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             removeAll(lcContext, connection);
         }
@@ -1272,10 +1237,6 @@
             getLogger().error("Error in sql query", ex);
             throw new RightsException("Error in sql query", ex);
         }
-        finally
-        {
-            ConnectionHelper.cleanup(connection);
-        }
     }
 
     @Override
@@ -1283,11 +1244,9 @@
     {
         String lcContext = getFullContext (context);
 
-        Connection connection = ConnectionHelper.getConnection(_poolName);
-
         PreparedStatement stmt = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             String sql = "DELETE FROM " + _tableGroupRights + " WHERE Group_Id = ? AND Profile_Id = ? AND LOWER(Context) = ?";
 
@@ -1318,7 +1277,6 @@
         finally
         {
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
     }
 
@@ -1327,11 +1285,9 @@
     {
         String lcContext = getFullContext (context);
 
-        Connection connection = ConnectionHelper.getConnection(_poolName);
-
         PreparedStatement stmt = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             // On regarde d'abord parmi les droits affectés directement aux
             // utilisateurs
@@ -1366,7 +1322,6 @@
         finally
         {
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
     }
 
@@ -1382,12 +1337,10 @@
 
         Set<User> users = new HashSet<>();
 
-        Connection connection = ConnectionHelper.getConnection(_poolName);
-
         PreparedStatement stmt = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             // On regarde d'abord parmi les droits affectés directement aux
             // utilisateurs
@@ -1421,7 +1374,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
 
         return users;
@@ -1440,12 +1392,10 @@
 
         Set<Group> groups = new HashSet<>();
 
-        Connection connection = ConnectionHelper.getConnection(_poolName);
-
         PreparedStatement stmt = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             // On regarde d'abord parmi les droits affectés directement aux
             // utilisateurs
@@ -1479,7 +1429,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
 
         return groups;
@@ -1596,11 +1545,10 @@
      */
     private RightResult hasUserOnlyRight(String login, String right) throws SQLException
     {
-        Connection connection = ConnectionHelper.getConnection(_poolName);
         PreparedStatement stmt = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             String sql = "SELECT UR.Login " + "FROM " + _tableProfileRights + " PR, " + _tableUserRights + " UR WHERE PR.Right_Id = ? " + "AND UR.Profile_Id = PR.Profile_Id " + "AND UR.Login = ?";
 
@@ -1628,7 +1576,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
     }
 
@@ -1668,11 +1615,10 @@
      */
     private RightResult hasUserOnlyRight(String login, String right, String context) throws SQLException
     {
-        Connection connection = ConnectionHelper.getConnection(_poolName);
         PreparedStatement stmt = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             String sql = buildSQLStatementForUser(context);
             stmt = connection.prepareStatement(sql);
@@ -1741,7 +1687,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
     }
 
@@ -1766,11 +1711,10 @@
     {
         Set<String> logins = new HashSet<>();
 
-        Connection connection = ConnectionHelper.getConnection(_poolName);
         PreparedStatement stmt = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             // On regarde d'abord parmi les droits affectés directement aux
             // utilisateurs
@@ -1806,7 +1750,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
     }
     
@@ -1814,11 +1757,10 @@
     {
         Set<String> logins = new HashSet<>();
         
-        Connection connection = ConnectionHelper.getConnection(_poolName);
         PreparedStatement stmt = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             // On regarde d'abord parmi les droits affectés directement aux
             // utilisateurs
@@ -1855,7 +1797,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
     }
     
@@ -1888,11 +1829,10 @@
             return rights;
         }
 
-        Connection connection = ConnectionHelper.getConnection(_poolName);
         PreparedStatement stmt = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             // On regarde d'abord parmi les droits affectés directement aux utilisateurs
             StringBuffer sql = new StringBuffer();
@@ -1935,7 +1875,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
     }
 
@@ -1962,11 +1901,10 @@
     private Map<String, Set<String>> _getUsersOnlyRightsFromDb(String login) throws SQLException
     {
         Map<String, Set<String>> rights = new HashMap<>();
-        Connection connection = ConnectionHelper.getConnection(_poolName);
         PreparedStatement stmt = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             // On regarde d'abord parmi les droits affectés directement aux utilisateurs
             StringBuffer sql = new StringBuffer();
@@ -2002,7 +1940,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
     }
 
@@ -2010,11 +1947,10 @@
     {
         Map<String, Set<String>> profiles = new HashMap<>();
 
-        Connection connection = ConnectionHelper.getConnection(_poolName);
         PreparedStatement stmt = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             // On regarde d'abord parmi les droits affectés directement aux utilisateurs
             StringBuffer sql = new StringBuffer();
@@ -2049,7 +1985,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
     }
 
@@ -2070,11 +2005,10 @@
      */
     private RightResult hasGroupOnlyRight(String login, String right) throws SQLException
     {
-        Connection connection = ConnectionHelper.getConnection(_poolName);
         PreparedStatement stmt = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             Set<String> groupsId = getGroupId(login);
             String groupSql = createGroupIdRequest(groupsId);
@@ -2108,7 +2042,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
     }
 
@@ -2147,11 +2080,10 @@
      */
     private RightResult hasGroupOnlyRight(String login, String right, String context) throws SQLException
     {
-        Connection connection = ConnectionHelper.getConnection(_poolName);
         PreparedStatement stmt = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             // Récupère la liste des groupes du user
             Set<String> groupsId = getGroupId(login);
@@ -2221,7 +2153,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
     }
 
@@ -2229,11 +2160,10 @@
     {
         Set<String> logins = new HashSet<>();
 
-        Connection connection = ConnectionHelper.getConnection(_poolName);
         PreparedStatement stmt = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             // Puis parmi les droits affectés aux groups auxquels appartient
             // l'utilisateur
@@ -2282,7 +2212,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
     }
     
@@ -2290,11 +2219,10 @@
     {
         Set<String> logins = new HashSet<>();
 
-        Connection connection = ConnectionHelper.getConnection(_poolName);
         PreparedStatement stmt = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             // Puis parmi les droits affectés aux groups auxquels appartient
             // l'utilisateur
@@ -2344,7 +2272,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
     }
 
@@ -2371,11 +2298,10 @@
     private Set<String> _getGroupsOnlyRightsFromDb(String login, String context) throws SQLException
     {
         Set<String> rights = new HashSet<>();
-        Connection connection = ConnectionHelper.getConnection(_poolName);
         PreparedStatement stmt = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             // Récupère la liste des groupes du user
             Set<String> userSGroup = _groupsManager.getUserGroups(login);
@@ -2447,7 +2373,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
     }
 
@@ -2474,11 +2399,10 @@
     private Map<String, Set<String>> _getGroupsOnlyRightsFromDb(String login) throws SQLException
     {
         Map<String, Set<String>> rights = new HashMap<>();
-        Connection connection = ConnectionHelper.getConnection(_poolName);
         PreparedStatement stmt = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             // Récupère la liste des groupes du user
             Set<String> userSGroup = _groupsManager.getUserGroups(login);
@@ -2543,7 +2467,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
     }
 
@@ -2551,11 +2474,10 @@
     {
         Map<String, Set<String>> profiles = new HashMap<>();
 
-        Connection connection = ConnectionHelper.getConnection(_poolName);
         PreparedStatement stmt = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
             // Récupère la liste des groupes du user
             Set<String> userSGroup = _groupsManager.getUserGroups(login);
@@ -2618,7 +2540,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
     }
 
@@ -3034,13 +2955,11 @@
     @Override
     public Profile getProfile(String id)
     {
-        Connection connection = null;
         PreparedStatement statement = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
-            connection = ConnectionHelper.getConnection(_poolName);
             statement = connection.prepareStatement("SELECT Label, Context FROM " + _tableProfile + " WHERE Id = ?");
             statement.setInt(1, Integer.parseInt(id));
 
@@ -3063,7 +2982,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(statement);
-            ConnectionHelper.cleanup(connection);
         }
     }
 
@@ -3078,13 +2996,11 @@
     {
         Integer id = null;
 
-        Connection connection = null;
         PreparedStatement statement = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
-            connection = ConnectionHelper.getConnection(_poolName);
             DatabaseType dbType = ConnectionHelper.getDatabaseType(connection);
 
             if (dbType == DatabaseType.DATABASE_ORACLE || dbType == DatabaseType.DATABASE_POSTGRES)
@@ -3175,7 +3091,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(statement);
-            ConnectionHelper.cleanup(connection);
         }
 
         if (id == null)
@@ -3197,13 +3112,11 @@
     {
         Set<Profile> profiles = new HashSet<>();
 
-        Connection connection = null;
         PreparedStatement stmt = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
-            connection = ConnectionHelper.getConnection(_poolName);
             if (context == null)
             {
                 stmt = connection.prepareStatement("SELECT Id, Label FROM " + _tableProfile + " WHERE Context is null");
@@ -3231,7 +3144,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
 
         return profiles;
@@ -3242,13 +3154,11 @@
     {
         Set<Profile> profiles = new HashSet<>();
 
-        Connection connection = null;
         Statement stmt = null;
         ResultSet rs = null;
 
-        try
+        try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
         {
-            connection = ConnectionHelper.getConnection(_poolName);
             stmt = connection.createStatement();
             rs = stmt.executeQuery("SELECT Id, Label, Context FROM " + _tableProfile);
 
@@ -3268,7 +3178,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
 
         return profiles;
@@ -3456,9 +3365,10 @@
         @Override
         public void rename(String newName)
         {
-            Connection connection = ConnectionHelper.getConnection(_poolName);
+            PreparedStatement stmt = null;
+            ResultSet rs = null;
 
-            try
+            try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
             {
                 PreparedStatement statement = connection.prepareStatement("UPDATE " + _tableProfile + " SET label = ? WHERE Id = ?");
                 statement.setString(1, newName);
@@ -3473,10 +3383,6 @@
             {
                 throw new RuntimeException(ex);
             }
-            finally
-            {
-                ConnectionHelper.cleanup(connection);
-            }
         }
 
         @Override
@@ -3484,13 +3390,13 @@
         {
             Set<String> rights = new HashSet<>();
 
-            Connection connection = ConnectionHelper.getConnection(_poolName);
+            ResultSet rs = null;
 
-            try
+            try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
             {
                 PreparedStatement statement = connection.prepareStatement("SELECT Right_Id FROM " + _tableProfileRights + " WHERE profile_Id = ?");
                 statement.setInt(1, Integer.parseInt(_id));
-                ResultSet rs = statement.executeQuery();
+                rs = statement.executeQuery();
 
                 while (rs.next())
                 {
@@ -3502,9 +3408,9 @@
             {
                 throw new RuntimeException(ex);
             }
-            finally
+            finally 
             {
-                ConnectionHelper.cleanup(connection);
+                ConnectionHelper.cleanup(rs);
             }
 
             return rights;
@@ -3537,15 +3443,13 @@
         @Override
         public void remove()
         {
-            Connection connection = null;
             PreparedStatement statement = null;
             PreparedStatement statement2 = null;
             PreparedStatement statement3 = null;
             PreparedStatement statement4 = null;
 
-            try
+            try (Connection connection =  ConnectionHelper.getConnection(_dataSourceId);)
             {
-                connection = ConnectionHelper.getConnection(_poolName);
 
                 statement = connection.prepareStatement("DELETE FROM " + _tableProfile + " WHERE Id = ?");
                 statement.setInt(1, Integer.parseInt(_id));
@@ -3573,7 +3477,6 @@
                 ConnectionHelper.cleanup(statement2);
                 ConnectionHelper.cleanup(statement3);
                 ConnectionHelper.cleanup(statement4);
-                ConnectionHelper.cleanup(connection);
             }
 
         }
@@ -3581,7 +3484,7 @@
         @Override
         public void startUpdate()
         {
-            _currentConnection = ConnectionHelper.getConnection(_poolName);
+            _currentConnection = ConnectionHelper.getConnection(_dataSourceId);
 
             try
             {
@@ -3632,7 +3535,7 @@
             }
             else
             {
-                return ConnectionHelper.getConnection(_poolName);
+                return ConnectionHelper.getConnection(_dataSourceId);
             }
         }
 
Index: main/plugin-core-impl/src/org/ametys/plugins/core/impl/right/profile/HierarchicalProfileBasedRightsManager.java
===================================================================
--- main/plugin-core-impl/src/org/ametys/plugins/core/impl/right/profile/HierarchicalProfileBasedRightsManager.java	(revision 38980)
+++ main/plugin-core-impl/src/org/ametys/plugins/core/impl/right/profile/HierarchicalProfileBasedRightsManager.java	(working copy)
@@ -199,7 +199,7 @@
         String lcOldContext = getFullContext(oldContext);
         String lcNewContext = getFullContext(newContext);
         
-        Connection connection = ConnectionHelper.getConnection(_poolName);
+        Connection connection = ConnectionHelper.getConnection(_dataSourceId);
         
         try
         {
@@ -241,7 +241,7 @@
     {
         String lcContext = getFullContext(context);
         
-        Connection connection = ConnectionHelper.getConnection(_poolName);
+        Connection connection = ConnectionHelper.getConnection(_dataSourceId);
         
         try
         {
Index: main/plugin-core-impl/src/org/ametys/plugins/core/impl/user/jdbc/CredentialsAwareJdbcUsersManager.java
===================================================================
--- main/plugin-core-impl/src/org/ametys/plugins/core/impl/user/jdbc/CredentialsAwareJdbcUsersManager.java	(revision 38980)
+++ main/plugin-core-impl/src/org/ametys/plugins/core/impl/user/jdbc/CredentialsAwareJdbcUsersManager.java	(working copy)
@@ -28,6 +28,7 @@
 import org.ametys.core.datasource.ConnectionHelper;
 import org.ametys.core.user.CredentialsAwareUsersManager;
 import org.ametys.core.util.StringUtils;
+import org.ametys.runtime.config.Config;
 import org.ametys.runtime.i18n.I18nizableText;
 import org.ametys.runtime.parameter.DefaultValidator;
 import org.ametys.runtime.parameter.ParameterHelper.ParameterType;
@@ -100,15 +101,12 @@
         String login = credentials.getLogin();
         String password = credentials.getPassword();
         
-        Connection con = null;
         PreparedStatement stmt = null;
         ResultSet rs = null;
-        try
+        
+        String dataSourceId = Config.getInstance().getValueAsString(_poolConfigParam);
+        try (Connection connection = ConnectionHelper.getConnection(dataSourceId);)
         {
-            // Effectuer la connexion à la base de données
-            // via un pool de connexion
-            con = ConnectionHelper.getConnection(_poolName);
-
             // Contruire la requête pour authentifier l'utilisateur
             String sql = "SELECT " + _parameters.get("login").getColumn() + ", " + _parameters.get("password").getColumn() + ", " + _saltColumn + " FROM " + _tableName + " WHERE " + _parameters.get("login").getColumn() + " = ?";
             if (getLogger().isDebugEnabled())
@@ -116,7 +114,7 @@
                 getLogger().debug(sql);
             }
 
-            stmt = con.prepareStatement(sql);
+            stmt = connection.prepareStatement(sql);
             stmt.setString(1, login);
 
             // Effectuer la requête
@@ -158,7 +156,6 @@
             // Fermer les ressources de connexion
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(con);
         }
     }
     
Index: main/plugin-core-impl/src/org/ametys/plugins/core/impl/user/jdbc/JdbcUsersManager.java
===================================================================
--- main/plugin-core-impl/src/org/ametys/plugins/core/impl/user/jdbc/JdbcUsersManager.java	(revision 38980)
+++ main/plugin-core-impl/src/org/ametys/plugins/core/impl/user/jdbc/JdbcUsersManager.java	(working copy)
@@ -52,6 +52,7 @@
 import org.ametys.core.user.User;
 import org.ametys.core.user.UsersManager;
 import org.ametys.core.util.CachingComponent;
+import org.ametys.runtime.config.Config;
 import org.ametys.runtime.i18n.I18nizableText;
 import org.ametys.runtime.parameter.AbstractParameterParser;
 import org.ametys.runtime.parameter.DefaultValidator;
@@ -74,8 +75,8 @@
     /** Plugin name */
     protected String _pluginName;
 
-    /** Connection pool */
-    protected String _poolName;
+    /** Configuration parameter id for the connection pool */
+    protected String _poolConfigParam;
 
     /** JDBC table name */
     protected String _tableName;
@@ -122,7 +123,7 @@
         _enumeratorManager.contextualize(_context);
         _enumeratorManager.service(_manager);
         
-        _poolName = configuration.getChild("pool").getValue();
+        _poolConfigParam = configuration.getChild("pool").getValue();
         _tableName = configuration.getChild("table").getValue("Users");
 
         _parameters = new LinkedHashMap<>();
@@ -784,11 +785,12 @@
         @SuppressWarnings("synthetic-access")
         public T runWithException() throws Exception
         {
-            Connection connection = ConnectionHelper.getConnection(_poolName);
+            String dataSourceId = Config.getInstance().getValueAsString(_poolConfigParam); 
+            
             PreparedStatement stmt = null;
             ResultSet rs = null;
             
-            try
+            try (Connection connection = ConnectionHelper.getConnection(dataSourceId))
             {
                 String sql = getSqlQuery(connection);
                 
@@ -811,7 +813,6 @@
             {
                 ConnectionHelper.cleanup(rs);
                 ConnectionHelper.cleanup(stmt);
-                ConnectionHelper.cleanup(connection);
             }
         }
         
Index: main/plugin-core-impl/src/org/ametys/plugins/core/impl/user/jdbc/ModifiableCredentialsAwareJdbcUsersManager.java
===================================================================
--- main/plugin-core-impl/src/org/ametys/plugins/core/impl/user/jdbc/ModifiableCredentialsAwareJdbcUsersManager.java	(revision 38980)
+++ main/plugin-core-impl/src/org/ametys/plugins/core/impl/user/jdbc/ModifiableCredentialsAwareJdbcUsersManager.java	(working copy)
@@ -30,6 +30,7 @@
 import org.ametys.core.datasource.ConnectionHelper;
 import org.ametys.core.user.CredentialsAwareUsersManager;
 import org.ametys.core.util.StringUtils;
+import org.ametys.runtime.config.Config;
 import org.ametys.runtime.i18n.I18nizableText;
 import org.ametys.runtime.parameter.DefaultValidator;
 import org.ametys.runtime.parameter.ParameterHelper.ParameterType;
@@ -101,15 +102,12 @@
         
         boolean updateNeeded = false;
         
-        Connection con = null;
         PreparedStatement stmt = null;
         ResultSet rs = null;
-        try
+        
+        String dataSourceId = Config.getInstance().getValueAsString(_poolConfigParam);
+        try (Connection connection = ConnectionHelper.getConnection(dataSourceId);)
         {
-            // Effectuer la connexion à la base de données
-            // via un pool de connexion
-            con = ConnectionHelper.getConnection(_poolName);
-
             // Contruire la requête pour authentifier l'utilisateur
             String sql = "SELECT " + _parameters.get("login").getColumn() + ", " + _parameters.get("password").getColumn() + ", " + _saltColumn + " FROM " + _tableName + " WHERE " + _parameters.get("login").getColumn() + " = ?";
             if (getLogger().isDebugEnabled())
@@ -117,7 +115,7 @@
                 getLogger().debug(sql);
             }
 
-            stmt = con.prepareStatement(sql);
+            stmt = connection.prepareStatement(sql);
             stmt.setString(1, login);
 
             // Effectuer la requête
@@ -172,7 +170,6 @@
             // Fermer les ressources de connexion
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(con);
             
             if (updateNeeded)
             {
@@ -189,13 +186,12 @@
     */
     protected void _updateToSSHAPassword(String login, String password)
     {
-        Connection con = null;
         PreparedStatement stmt = null;
         ResultSet rs = null;
-
-        try
+        
+        String dataSourceId = Config.getInstance().getValueAsString(_poolConfigParam);
+        try (Connection connection = ConnectionHelper.getConnection(dataSourceId);)
         {
-            con = ConnectionHelper.getConnection(_poolName);
 
             String generateSaltKey = RandomStringUtils.randomAlphanumeric(48);
             String newEncryptedPassword = DigestUtils.sha512Hex(generateSaltKey + password);
@@ -206,7 +202,7 @@
                 getLogger().debug(sqlUpdate);
             }
 
-            stmt = con.prepareStatement(sqlUpdate);
+            stmt = connection.prepareStatement(sqlUpdate);
             stmt.setString(1, newEncryptedPassword);
             stmt.setString(2, generateSaltKey);
             stmt.setString(3, login);
@@ -222,7 +218,6 @@
             // Fermer les ressources de connexion
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(con);
         }
     }
     
Index: main/plugin-core-impl/src/org/ametys/plugins/core/impl/user/jdbc/ModifiableJdbcUsersManager.java
===================================================================
--- main/plugin-core-impl/src/org/ametys/plugins/core/impl/user/jdbc/ModifiableJdbcUsersManager.java	(revision 38980)
+++ main/plugin-core-impl/src/org/ametys/plugins/core/impl/user/jdbc/ModifiableJdbcUsersManager.java	(working copy)
@@ -17,6 +17,7 @@
 
 import java.sql.Connection;
 import java.sql.PreparedStatement;
+import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -34,6 +35,7 @@
 import org.ametys.core.user.InvalidModificationException;
 import org.ametys.core.user.ModifiableUsersManager;
 import org.ametys.core.user.UserListener;
+import org.ametys.runtime.config.Config;
 import org.ametys.runtime.i18n.I18nizableText;
 import org.ametys.runtime.parameter.Enumerator;
 import org.ametys.runtime.parameter.Errors;
@@ -136,7 +138,6 @@
      */
     public void add(Map<String, String> userInformation) throws InvalidModificationException
     {
-        Connection con = null;
         PreparedStatement stmt = null;
 
         if (getLogger().isDebugEnabled())
@@ -154,12 +155,10 @@
         
         String login = userInformation.get("login");
 
-        try
+        String dataSourceId = Config.getInstance().getValueAsString(_poolConfigParam);
+        try (Connection connection = ConnectionHelper.getConnection(dataSourceId);)
         {
-            // Effectuer la connexion à la base de données via un pool de connexion
-            con = ConnectionHelper.getConnection(_poolName);
-
-            stmt = createAddStatement(con, userInformation);
+            stmt = createAddStatement(connection, userInformation);
 
             // Effectuer la requête et vérifier le résultat
             if (stmt.executeUpdate() != 1)
@@ -185,7 +184,6 @@
         {
             // Fermer les ressources de connexion
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(con);
         }
     }
 
@@ -270,7 +268,6 @@
      */
     public void update(Map<String, String> userInformation) throws InvalidModificationException
     {
-        Connection con = null;
         PreparedStatement stmt = null;
 
         Map<String, Errors> errorFields = new HashMap<>();
@@ -312,13 +309,11 @@
             throw new InvalidModificationException("Cannot update without login information");
         }
 
-        try
+        String dataSourceId = Config.getInstance().getValueAsString(_poolConfigParam);
+        try (Connection connection = ConnectionHelper.getConnection(dataSourceId);)
         {
-            // Effectuer la connexion à la base de données
-            // via un pool de connexion
-            con = ConnectionHelper.getConnection(_poolName);
 
-            stmt = createModifyStatement(con, userInformation);
+            stmt = createModifyStatement(connection, userInformation);
 
             // Effectuer la requête
             if (stmt.executeUpdate() != 1)
@@ -345,7 +340,6 @@
         {
             // Fermer les ressources de connexion
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(con);
         }
     }
 
@@ -411,13 +405,11 @@
 
     public void remove(String login) throws InvalidModificationException
     {
-        Connection con = null;
         PreparedStatement stmt = null;
 
-        try
+        String dataSourceId = Config.getInstance().getValueAsString(_poolConfigParam);
+        try (Connection connection = ConnectionHelper.getConnection(dataSourceId);)
         {
-            // Effectuer la connexion à la base de données via un pool de connexion
-            con = ConnectionHelper.getConnection(_poolName);
 
             // Contruire la requête pour supprimer un utilisateur
             String sqlRequest = "DELETE FROM " + _tableName + " WHERE " + _parameters.get("login").getColumn() + " = ?";
@@ -426,7 +418,7 @@
                 getLogger().debug(sqlRequest);
             }
 
-            stmt = con.prepareStatement(sqlRequest);
+            stmt = connection.prepareStatement(sqlRequest);
             stmt.setString(1, login);
 
             // Effectuer la requête et vérifier le résultat
@@ -453,7 +445,6 @@
         {
             // Fermer les ressources de connexion
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(con);
         }
     }
 }
Index: main/plugin-core-impl/src/org/ametys/plugins/core/impl/user/ldap/LdapUsersManager.java
===================================================================
--- main/plugin-core-impl/src/org/ametys/plugins/core/impl/user/ldap/LdapUsersManager.java	(revision 38980)
+++ main/plugin-core-impl/src/org/ametys/plugins/core/impl/user/ldap/LdapUsersManager.java	(working copy)
@@ -40,6 +40,7 @@
 import javax.naming.ldap.SortControl;
 
 import org.apache.avalon.framework.component.Component;
+import org.apache.avalon.framework.configuration.Configurable;
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
 import org.apache.avalon.framework.thread.ThreadSafe;
@@ -56,7 +57,7 @@
 /**
  * Use a ldap server for getting the list of users.
  */
-public class LdapUsersManager extends AbstractLDAPConnector implements UsersManager, ThreadSafe, Component
+public class LdapUsersManager extends AbstractLDAPConnector implements UsersManager, ThreadSafe, Component, Configurable
 {
     /** Relative DN for users. */
     protected String _usersRelativeDN;
@@ -82,8 +83,6 @@
     @Override
     public void configure(Configuration configuration) throws ConfigurationException
     {
-        super.configure(configuration);
-        
         _usersRelativeDN = _getConfigParameter(configuration, "RelativeDN");
         _usersObjectFilter = _getFilter(configuration, "Filter");
         _usersSearchScope = _getSearchScope(configuration, "SearchScope");
Index: main/plugin-core-impl/src/org/ametys/plugins/core/impl/userpref/JdbcPlainUserPreferencesStorage.java
===================================================================
--- main/plugin-core-impl/src/org/ametys/plugins/core/impl/userpref/JdbcPlainUserPreferencesStorage.java	(revision 38980)
+++ main/plugin-core-impl/src/org/ametys/plugins/core/impl/userpref/JdbcPlainUserPreferencesStorage.java	(working copy)
@@ -39,6 +39,7 @@
 import org.ametys.core.userpref.DefaultUserPreferencesStorage;
 import org.ametys.core.userpref.UserPreferencesException;
 import org.ametys.core.userpref.UserPreferencesStorage;
+import org.ametys.runtime.config.Config;
 import org.ametys.runtime.parameter.ParameterHelper;
 import org.ametys.runtime.parameter.ParameterHelper.ParameterType;
 
@@ -71,8 +72,8 @@
 public class JdbcPlainUserPreferencesStorage extends AbstractLogEnabled implements UserPreferencesStorage, ThreadSafe, Configurable
 {
     
-    /** Connection pool name. */
-    protected String _poolName;
+    /** The id of the configuration parameter corresponding to the connection pool to use. */
+    protected String _poolConfigParam;
     
     /** The database table in which the preferences are stored. */
     protected String _databaseTable;
@@ -96,7 +97,7 @@
     public void configure(Configuration configuration) throws ConfigurationException
     {
         // Default to the core pool.
-        _poolName = configuration.getChild("pool").getValue(ConnectionHelper.CORE_POOL_NAME);
+        _poolConfigParam = configuration.getChild("pool").getValue(ConnectionHelper.CORE_POOL_CONFIG_PARAM);
         // The table configuration is mandatory.
         _databaseTable = configuration.getChild("table").getValue();
         // Default to "login".
@@ -142,13 +143,12 @@
     {
         Map<String, String> prefs = new HashMap<>();
         
-        Connection connection = null;
         PreparedStatement stmt = null;
         ResultSet rs = null;
         
-        try
+        String dataSourceId = Config.getInstance().getValueAsString(_poolConfigParam);
+        try (Connection connection = ConnectionHelper.getConnection(dataSourceId);)
         {
-            connection = ConnectionHelper.getConnection(_poolName);
             
             StringBuilder query = new StringBuilder();
             query.append("SELECT * FROM ").append(_databaseTable).append(" WHERE ").append(_loginColumn).append(" = ?");
@@ -203,19 +203,17 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
     }
     
     @Override
     public void removeUserPreferences(String login, String storageContext, Map<String, String> contextVars) throws UserPreferencesException
     {
-        Connection connection = null;
         PreparedStatement stmt = null;
         
-        try
+        String dataSourceId = Config.getInstance().getValueAsString(_poolConfigParam);
+        try (Connection connection = ConnectionHelper.getConnection(dataSourceId);)
         {
-            connection = ConnectionHelper.getConnection(_poolName);
             
             StringBuilder query = new StringBuilder();
             query.append("DELETE FROM ").append(_databaseTable).append(" WHERE ").append(_loginColumn).append(" = ?");
@@ -243,17 +241,15 @@
         finally
         {
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
     }
     
     @Override
     public void setUserPreferences(String login, String storageContext, Map<String, String> contextVars, Map<String, String> preferences) throws UserPreferencesException
     {
-        Connection connection = null;
-        try
+        String dataSourceId = Config.getInstance().getValueAsString(_poolConfigParam);
+        try (Connection connection = ConnectionHelper.getConnection(dataSourceId);)
         {
-            connection = ConnectionHelper.getConnection(_poolName);
             
             // Test if the preferences already exist.
             if (dataExists(connection, login, storageContext))
@@ -271,10 +267,6 @@
             getLogger().error(message, e);
             throw new UserPreferencesException(message, e);
         }
-        finally
-        {
-            ConnectionHelper.cleanup(connection);
-        }
     }
     
     @Override
@@ -298,7 +290,8 @@
                     query.append(" AND ").append(_contextColumn).append(" = ?");
                 }
                 
-                connection = ConnectionHelper.getConnection(_poolName);
+                String dataSourceId = Config.getInstance().getValueAsString(_poolConfigParam);
+                connection = ConnectionHelper.getConnection(dataSourceId);
                 
                 statement = connection.prepareStatement(query.toString());
                 statement.setString(1, column);
Index: main/plugin-core-impl/src/org/ametys/plugins/core/impl/userpref/JdbcXmlUserPreferencesStorage.java
===================================================================
--- main/plugin-core-impl/src/org/ametys/plugins/core/impl/userpref/JdbcXmlUserPreferencesStorage.java	(revision 38980)
+++ main/plugin-core-impl/src/org/ametys/plugins/core/impl/userpref/JdbcXmlUserPreferencesStorage.java	(working copy)
@@ -56,6 +56,7 @@
 import org.ametys.core.userpref.DefaultUserPreferencesStorage;
 import org.ametys.core.userpref.UserPreferencesException;
 import org.ametys.core.userpref.UserPrefsHandler;
+import org.ametys.runtime.config.Config;
 import org.ametys.runtime.parameter.ParameterHelper;
 import org.ametys.runtime.parameter.ParameterHelper.ParameterType;
 
@@ -70,7 +71,7 @@
     protected SAXParser _saxParser;
     
     /** Connection pool name. */
-    protected String _poolName;
+    protected String _pool;
     
     /** The database table in which the preferences are stored. */
     protected String _databaseTable;
@@ -78,7 +79,7 @@
     @Override
     public void configure(Configuration configuration) throws ConfigurationException
     {
-        _poolName = configuration.getChild("pool").getValue(ConnectionHelper.CORE_POOL_NAME);
+        _pool = configuration.getChild("pool").getValue(ConnectionHelper.CORE_POOL_CONFIG_PARAM);
         _databaseTable = configuration.getChild("table").getValue();
     }
     
@@ -93,14 +94,13 @@
     {
         Map<String, String> prefs = new HashMap<>();
         
-        Connection connection = null;
         PreparedStatement stmt = null;
         ResultSet rs = null;
         @SuppressWarnings("resource") InputStream dataIs = null;
         
-        try
+        String dataSourceId = Config.getInstance().getValueAsString(_pool);
+        try (Connection connection = ConnectionHelper.getConnection(dataSourceId);)
         {
-            connection = ConnectionHelper.getConnection(_poolName);
             DatabaseType dbType = ConnectionHelper.getDatabaseType(connection);
             
             stmt = connection.prepareStatement("SELECT * FROM " + _databaseTable + " WHERE login = ? AND context = ?");
@@ -146,19 +146,17 @@
             IOUtils.closeQuietly(dataIs);
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
     }
     
     @Override
     public void removeUserPreferences(String login, String storageContext, Map<String, String> contextVars) throws UserPreferencesException
     {
-        Connection connection = null;
         PreparedStatement stmt = null;
         
-        try
+        String dataSourceId = Config.getInstance().getValueAsString(_pool);
+        try (Connection connection = ConnectionHelper.getConnection(dataSourceId);)
         {
-            connection = ConnectionHelper.getConnection(_poolName);
             
             stmt = connection.prepareStatement("DELETE FROM " + _databaseTable + " WHERE login = ? AND context = ?");
             stmt.setString(1, login);
@@ -175,7 +173,6 @@
         finally
         {
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
     }
     
@@ -184,8 +181,9 @@
     {
         byte[] prefBytes = _getPreferencesXmlBytes(preferences);
         
+        String dataSourceId = Config.getInstance().getValueAsString(_pool);
         try (InputStream dataIs = new ByteArrayInputStream(prefBytes);
-             Connection connection = ConnectionHelper.getConnection(_poolName))
+             Connection connection = ConnectionHelper.getConnection(dataSourceId))
         {
             
             DatabaseType dbType = ConnectionHelper.getDatabaseType(connection);
Index: main/plugin-core-ui/i18n/messages_en.xml
===================================================================
--- main/plugin-core-ui/i18n/messages_en.xml	(revision 38980)
+++ main/plugin-core-ui/i18n/messages_en.xml	(working copy)
@@ -286,7 +286,8 @@
     <message key="PLUGINS_CORE_UI_CONFIGURABLE_FORM_PARAM_CHECKER_UI_REF_GROUP">On the group</message>
     <message key="PLUGINS_CORE_UI_CONFIGURABLE_FORM_PARAM_CHECKER_UI_REF_PARAMETER">On the parameter</message>
     <message key="PLUGINS_CORE_UI_CONFIGURABLE_FORM_PARAM_CHECKER_ERROR">Error while performing the parameter verification.</message>
-    <message key="PLUGINS_CORE_UI_CONFIGURABLE_FORM_PARAM_CHECKER_ERROR_TEXT">verification(s) have failed.&lt;br/&gt;Press the 'Details' button for further information or see the application's logs.</message>
+    <message key="PLUGINS_CORE_UI_CONFIGURABLE_FORM_PARAM_CHECKER_ERROR_TEXT">verification have failed.&lt;br/&gt;Press the 'Details' button for further information or see the application's logs.</message>
+    <message key="PLUGINS_CORE_UI_CONFIGURABLE_FORM_PARAM_CHECKER_SINGLE_ERROR_TEXT">The verification has failed.&lt;br/&gt;Press the 'Details' button for further information or see the application's logs.</message>
     <message key="PLUGINS_CORE_UI_CONFIGURABLE_FORM_PARAM_CHECKER_STATUS_SUCCESS">Success</message>
     <message key="PLUGINS_CORE_UI_CONFIGURABLE_FORM_PARAM_CHECKER_STATUS_FAILURE">Failure</message>
     <message key="PLUGINS_CORE_UI_CONFIGURABLE_FORM_PARAM_CHECKER_STATUS_NOT_TESTED">Not tested</message>
@@ -412,8 +413,14 @@
 	<message key="PLUGINS_CORE_UI_PROFILES_TREE_BTN_COLLAPSE_TOOTIP">Collapse all</message>
 	<message key="PLUGINS_CORE_UI_PROFILES_TREE_CONTEXT_TOOLTIP">Context</message>
 	<message key="PLUGINS_CORE_UI_PROFILES_TREE_GET_PROFILES_RIGHTS_ERROR">An error occured : unable to get list of profiles</message>
-    <message key="PLUGINS_CORE_UI_PROFILES_TREE_FILTER_INVALID">The search filter must contain at least 3 characters</message>
     
+    <!-- DATASOURCES -->
+    <message key="PLUGINS_CORE_UI_WIDGET_DATASOURCE_BUTTON_DEFAULT_TOOLTIP">Add a new data source</message>        
+    <message key="PLUGINS_CORE_UI_WIDGET_SQL_DATASOURCE_BUTTON_TOOLTIP">Add a new SQL data source</message>   
+    <message key="PLUGINS_CORE_UI_WIDGET_LDAP_DATASOURCE_BUTTON_TOOLTIP">Add a new LDAP data source</message>  
+
+    <message key="PLUGINS_CORE_UI_PROFILES_TREE_FILTER_INVALID">The search filter must contain at least 3 characters</message>
+
     <!-- +
          | Announce
          + -->
Index: main/plugin-core-ui/i18n/messages_fr.xml
===================================================================
--- main/plugin-core-ui/i18n/messages_fr.xml	(revision 38980)
+++ main/plugin-core-ui/i18n/messages_fr.xml	(working copy)
@@ -287,7 +287,8 @@
     <message key="PLUGINS_CORE_UI_CONFIGURABLE_FORM_PARAM_CHECKER_UI_REF_GROUP">Sur le groupe</message>
     <message key="PLUGINS_CORE_UI_CONFIGURABLE_FORM_PARAM_CHECKER_UI_REF_PARAMETER">Sur le paramètre</message>
     <message key="PLUGINS_CORE_UI_CONFIGURABLE_FORM_PARAM_CHECKER_ERROR">Erreur lors de la vérification des paramètres</message>
-    <message key="PLUGINS_CORE_UI_CONFIGURABLE_FORM_PARAM_CHECKER_ERROR_TEXT">vérifications(s) a (ont) échoué.&lt;br/&gt;Appuyez sur 'Détails' pour en savoir plus ou consultez les journaux de l'application.</message>
+    <message key="PLUGINS_CORE_UI_CONFIGURABLE_FORM_PARAM_CHECKER_ERROR_TEXT">vérifications ont échoué.&lt;br/&gt;Appuyez sur 'Détails' pour en savoir plus ou consultez les journaux de l'application.</message>
+    <message key="PLUGINS_CORE_UI_CONFIGURABLE_FORM_PARAM_CHECKER_SINGLE_ERROR_TEXT">La vérification a échoué.&lt;br/&gt;Appuyez sur 'Détails' pour en savoir plus ou consultez les journaux de l'application.</message>
     <message key="PLUGINS_CORE_UI_CONFIGURABLE_FORM_PARAM_CHECKER_STATUS_SUCCESS">Succès</message>
     <message key="PLUGINS_CORE_UI_CONFIGURABLE_FORM_PARAM_CHECKER_STATUS_FAILURE">Echec</message>
     <message key="PLUGINS_CORE_UI_CONFIGURABLE_FORM_PARAM_CHECKER_STATUS_NOT_TESTED">Non testé</message>
@@ -415,6 +416,11 @@
     <message key="PLUGINS_CORE_UI_PROFILES_TREE_GET_PROFILES_RIGHTS_ERROR">Une erreur est survenue: impossible de récupérer la liste des profils de droits</message>
     <message key="PLUGINS_CORE_UI_PROFILES_TREE_FILTER_INVALID">Le filtre de recherche doit contenir au moins 3 caractères</message>
     
+    <!-- DATASOURCES -->
+    <message key="PLUGINS_CORE_UI_WIDGET_DATASOURCE_BUTTON_DEFAULT_TOOLTIP">Ajouter une nouvelle source de données</message>        
+    <message key="PLUGINS_CORE_UI_WIDGET_SQL_DATASOURCE_BUTTON_TOOLTIP">Ajouter une nouvelle source de données SQL</message>    
+    <message key="PLUGINS_CORE_UI_WIDGET_LDAP_DATASOURCE_BUTTON_TOOLTIP">Ajouter une nouvelle source de données LDAP</message>    
+    
     <!-- +
          | Announce
          + -->
Index: main/plugin-core-ui/plugin.xml
===================================================================
--- main/plugin-core-ui/plugin.xml	(revision 38980)
+++ main/plugin-core-ui/plugin.xml	(working copy)
@@ -411,7 +411,45 @@
                 <!-- scripts are loaded as static to be extensible -->                 
             </extension>
         </extensions>
+    </feature>
+    <feature name="widgets.default.datasource.sql" safe="true">
+        <extensions>
+            <extension id="edition.datasource-sql"
+                       point="org.ametys.core.ui.widgets.WidgetsManager"
+                       class="org.ametys.core.ui.widgets.StaticClientSideWidget">
+               <class name="Ametys.form.widget.SQLDataSource">
+                    <ftypes>datasource</ftypes>
+                    <supports-enumerated>false</supports-enumerated> 
+                    <supports-non-enumerated>true</supports-non-enumerated> 
+                    <supports-multiple>false</supports-multiple> 
+                    <supports-non-multiple>true</supports-non-multiple>
+                </class>
+                <scripts>
+                    <file>js/Ametys/form/widget/AbstractDataSource.js</file>
+                    <file>js/Ametys/form/widget/SQLDataSource.js</file>
+                </scripts>
+            </extension> 
+        </extensions>
     </feature>  
+    <feature name="widgets.default.datasource.ldap" safe="true">
+        <extensions>
+            <extension id="edition.datasource-ldap"
+                       point="org.ametys.core.ui.widgets.WidgetsManager"
+                       class="org.ametys.core.ui.widgets.StaticClientSideWidget">
+               <class name="Ametys.form.widget.LDAPDataSource">
+                    <ftypes>datasource</ftypes>
+                    <supports-enumerated>false</supports-enumerated> 
+                    <supports-non-enumerated>true</supports-non-enumerated> 
+                    <supports-multiple>false</supports-multiple> 
+                    <supports-non-multiple>true</supports-non-multiple>
+                </class>
+                <scripts>
+                    <file>js/Ametys/form/widget/AbstractDataSource.js</file>
+                    <file>js/Ametys/form/widget/LDAPDataSource.js</file>
+                </scripts>
+            </extension> 
+        </extensions>
+    </feature> 
     <feature name="widgets.others.tricheckbox" safe="true">
         <extensions>
             <extension id="edition.tricheckbox"
@@ -1370,7 +1408,6 @@
                     <mode>all</mode>
                     
                     <selection-target-type>^form$</selection-target-type>
-                    
                     <label i18n="true">PLUGINS_CORE_UI_CONFIGURABLE_FORM_TEST_CONTROLLER_RUN_ALL_TESTS</label>
                     <description i18n="true">PLUGINS_CORE_UI_CONFIGURABLE_FORM_TEST_CONTROLLER_RUN_ALL_TESTS_DESC</description>
                     
@@ -1393,7 +1430,6 @@
                     
                     <selection-target-type>^form$</selection-target-type>
                     
-
                     <label i18n="true">PLUGINS_CORE_UI_CONFIGURABLE_FORM_TEST_CONTROLLER_RUN_MISSED_TESTS</label>
                     <description i18n="true">PLUGINS_CORE_UI_CONFIGURABLE_FORM_TEST_CONTROLLER_RUN_MISSED_TESTS_DESC</description>
                     
Index: main/plugin-core-ui/resources/js/Ametys/form/ConfigurableFormPanel/ParameterCheckersDAO.js
===================================================================
--- main/plugin-core-ui/resources/js/Ametys/form/ConfigurableFormPanel/ParameterCheckersDAO.js	(revision 38980)
+++ main/plugin-core-ui/resources/js/Ametys/form/ConfigurableFormPanel/ParameterCheckersDAO.js	(working copy)
@@ -558,6 +558,7 @@
 		Ext.Array.each(this._paramCheckers, function(paramChecker){
 			var button = Ext.getCmp(paramChecker.buttonId),
 				helpBox = Ext.getCmp(paramChecker.helpBoxId),
+				notTested = paramChecker.getStatus() == Ametys.form.ConfigurableFormPanel.ParameterChecker.STATUS_NOT_TESTED,
 				success = paramChecker.getStatus() == Ametys.form.ConfigurableFormPanel.ParameterChecker.STATUS_SUCCESS,
 				failure = paramChecker.getStatus() == Ametys.form.ConfigurableFormPanel.ParameterChecker.STATUS_FAILURE,
 				warning = paramChecker.getStatus() == Ametys.form.ConfigurableFormPanel.ParameterChecker.STATUS_WARNING,
@@ -568,7 +569,7 @@
 				linkedParamField._warnings = linkedParamField._warnings || {};
 				
 				var activeWarnings = linkedParamField.getActiveWarnings();
-				if (success)
+				if (success || notTested)
 				{
 					Ext.Array.remove(activeWarnings, warningMsg);
 					linkedParamField._warnings[paramChecker.id] = null;
@@ -636,7 +637,7 @@
 		{
 			Ametys.log.ErrorDialog.display({
 				title: "<i18n:text i18n:key='PLUGINS_CORE_UI_CONFIGURABLE_FORM_PARAM_CHECKER_ERROR'/>", 
-				text: nbErrors + " <i18n:text i18n:key='PLUGINS_CORE_UI_CONFIGURABLE_FORM_PARAM_CHECKER_ERROR_TEXT'/>",
+				text: nbErrors > 1 ? nbErrors + " <i18n:text i18n:key='PLUGINS_CORE_UI_CONFIGURABLE_FORM_PARAM_CHECKER_ERROR_TEXT'/>" : "<i18n:text i18n:key='PLUGINS_CORE_UI_CONFIGURABLE_FORM_PARAM_CHECKER_SINGLE_ERROR_TEXT'/>",
 	    		category: this.self.getName(),
 	    		details: details
 			});
Index: main/plugin-core-ui/resources/js/Ametys/form/widget/AbstractDataSource.js
===================================================================
--- main/plugin-core-ui/resources/js/Ametys/form/widget/AbstractDataSource.js	(revision 0)
+++ main/plugin-core-ui/resources/js/Ametys/form/widget/AbstractDataSource.js	(revision 0)
@@ -0,0 +1,321 @@
+/*
+ *  Copyright 2015 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * Abstract field displaying a combobox allowing to select one of the available data sources. Optionally, 
+ * this field can allow the addition of other data sources. 
+ * You can override #getStore and you must provide a function #creationHandler
+ */
+Ext.define('Ametys.form.widget.AbstractDataSource', {
+    extend: 'Ametys.form.AbstractFieldsWrapper',
+	
+    /**
+     * @cfg {Boolean} [allowPrivate=false] True to also show private data sources
+     */
+	allowPrivate: false,
+	
+    /**
+     * @cfg {Boolean} [allowCreation=false] True to allow the creation of new data sources
+     */
+	allowCreation: false,
+	
+	/**
+	 * @cfg {String} dataSourceType the type of the data source
+	 */
+	/**
+	 * @cfg {Function} creationFunction the function used to add a new data source
+	 */
+	/**
+	 * @cfg {Boolean} [includeDefault=true] include the default data source ?
+	 */
+	includeDefault: true,
+	
+	/**
+	 * @cfg {String} tooltipText the text of the tooltip
+	 */
+	tooltipText: "<i18n:text i18n:key='PLUGINS_CORE_UI_WIDGET_DATASOURCE_BUTTON_DEFAULT_TOOLTIP'/>",
+	
+	/**
+	 * @private
+	 * @property {Ext.data.Store} _store the combo box's store
+	 */
+	/**
+	 * @private
+	 * @property {Ext.data.Record} _selectedRecord the record that is currently selected, null if none.
+	 */
+	/**
+	 * @private
+	 * @property {Ext.data.Store} _store The combobox store
+	 */
+	/**
+	 * @private
+	 * @property {String} _dataSourceToSelect The id of the data source to select 
+	 */
+	
+	initComponent: function()
+	{
+		this.items = [];
+		
+    	this.items[0] = Ext.create('Ext.form.field.ComboBox', 
+    			        {
+	    		  	        flex: 1,
+	    		  	        
+  	    	    		    store: this.getStore(),
+  	    	    		    
+  	    	    		    // FIXME set value => config tool dirty
+	  	    	            autoLoadOnValue: true,
+  	    	    		    
+	  	    	            valueField: 'id',
+  	    	    		    displayField: 'name',
+  	    	    		    
+  	    	    		    listeners: {
+  	    	    		    	select: Ext.bind(this._onSelect, this),
+  	    	    		    	click: {fn: Ext.bind(this._onClick, this), element: 'inputEl'},
+  	    	    		    	scope: this
+  	    	    		    }
+      			        });
+    	
+    	if (this.allowCreation)
+		{
+    		this.items[1] = Ext.create('Ext.button.Button', 
+    						{ 
+				    			width: 20,
+				    			handler: Ext.bind(this.creationHandler, this),
+				    			icon: Ametys.getPluginResourcesPrefix('core-ui') + '/img/datasource/widget_add_16.png',
+				    			tooltip: this.tooltipText
+				    		}); 
+		}
+    	
+    	this.callParent();
+	},
+	
+	constructor: function(config)
+	{
+		this.callParent(arguments);
+		
+		config.allowPrivate = Ext.isBoolean(config.allowPrivate) ? config.allowPrivate : config.allowPrivate == 'true';
+		config.allowCreation = Ext.isBoolean(config.allowCreation) ? config.allowCreation : config.allowCreation == 'true';
+		config.includeDefault = Ext.isBoolean(config.includeDefault) ? config.includeDefault : config.includeDefault == 'true';
+		
+		this._selectedRecord = null;
+		
+		// Bus messages listeners
+		Ametys.message.MessageBus.on(Ametys.message.Message.CREATED, this._onCreated, this);
+		Ametys.message.MessageBus.on(Ametys.message.Message.MODIFIED, this._onModified, this);
+		Ametys.message.MessageBus.on(Ametys.message.Message.DELETED, this._onDeleted, this);
+	},
+	
+	/**
+	 * @private
+	 * Get the underlying combo box
+	 * @return {Ext.form.field.ComboBox} The combobox
+	 */
+	_getCombobox: function()
+	{
+		return this.items.get(0);
+	},
+	
+    setValue: function(value) 
+    {
+    	this._getCombobox().setValue(value ? value : null);
+    },
+
+    getValue: function() 
+    {
+    	return this._getCombobox().getValue();
+    },
+    
+	/**
+	 * Get the store used by the combo box
+	 * @return {Ext.data.Store} the store
+	 */
+	getStore: function()
+	{
+		if (this._store == null)
+		{
+			this._store = Ext.create('Ext.data.Store',
+					{
+				fields: [ 'id', {name: 'name', type: 'string', sortType: Ext.data.SortTypes.asNonAccentedUCString}],
+				
+				proxy: {
+					type: 'ametys',
+					plugin: 'admin',
+					url: 'datasources/get',
+					reader: {
+						type: 'json',
+						rootProperty: 'datasources'
+					}
+				},
+				
+				sorters: 'name',
+				
+				listeners: {
+					beforeload: {fn: this._onBeforeLoad, scope: this}
+				}
+			});
+		}
+		
+		return this._store;
+	},
+	
+	/**
+	 * Handler when the 'Add data source' button is clicked
+	 */
+	creationHandler: function()
+	{
+		throw new Error("The method #creationHandler is not implemented in " + this.self.getName());
+	},
+	
+	/**
+	 * Function invoked right before the store is loaded
+	 * @param {Ext.data.Store} store the store
+	 * @param {Ext.data.operation.Operation} The {@link Ext.data.operation.Operation} object that will be passed to the Proxy to load the Store
+	 */
+	_onBeforeLoad: function(store, operation)
+	{
+		var me = this;
+
+		operation.setParams(Ext.apply(operation.getParams() || {}, {
+			includePrivate: me.allowPrivate,
+			includeDefault: me.includeDefault,
+			type: me.dataSourceType
+		}));
+	},
+	
+	/**
+	 * Function invoked whenever a record is selected
+	 * @param {Ext.form.field.ComboBox} comboBox the combo box
+	 * @param {Ext.data.Record} record the selected record
+	 */
+	_onSelect: function(comboBox, record)
+	{
+		this._selectedRecord = record;
+		this.setValue(record.get('id'));
+	},
+	
+	/**
+	 * @private
+	 * Function invoked when the combo box is clicked
+	 */
+	_onClick: function()
+	{
+		var combo = this._getCombobox();
+		
+		// Do not collapse when the combo box is already expanded
+		if (!combo.readOnly && !combo.disabled && !combo.isExpanded) 
+		{
+			combo.onTriggerClick();
+		}
+	},
+	
+	/**
+	 * Handler function invoked whenever a {@link Ametys.message.Message.CREATED}
+	 * message is sent out on the message bus. Add the corresponding record to the grid panel's store.
+	 * @param {Ametys.message.Message} message the message
+	 */
+	_onCreated: function(message)
+	{
+		var me = this;
+		var target = message.getTarget(Ametys.message.MessageTarget.DATASOURCE);
+		if (target)
+		{
+			// load callback in #_selectNewDataSource is not called if the store is reloaded
+			this._store.reload({
+				callback: function() {
+					if (this._dataSourceToSelect != null)
+					{
+						this.setValue(this._dataSourceToSelect);
+						this._dataSourceToSelect = null;
+					}
+				},
+				scope: this
+			});
+		}
+	},
+	
+	/**
+	 * Handler function invoked whenever a {@link Ametys.message.Message.MODIFIED}
+	 * message is sent out on the message bus. Add the corresponding record to the grid panel's store.
+	 * @param {Ametys.message.Message} message the message
+	 */
+	_onModified: function(message)
+	{
+		var target = message.getTarget(Ametys.message.MessageTarget.DATASOURCE);
+		if (target)
+		{
+			var id = target.getParameters().id;
+			if (this._selectedRecord && this._selectedRecord.get('id') == id)
+			{
+				this._store.load({
+					callback: function() {
+						var record = this._store.getById(id);
+						this.setValue(record.get('name'));
+					},
+					scope: this
+				});
+			}
+			else
+			{
+				this._store.reload();
+			}
+		}
+	},
+	
+	/**
+	 * Handler function invoked whenever a {@link Ametys.message.Message.CREATED}
+	 * message is sent out on the message bus. Add the corresponding record to the grid panel's store.
+	 * @param {Ametys.message.Message} message the message
+	 */
+	_onDeleted: function(message)
+	{
+		var target = message.getTarget(Ametys.message.MessageTarget.DATASOURCE);
+		if (target)
+		{
+			var id = target.getParameters().id;
+			if (this._selectedRecord && this._selectedRecord.get('id') == id)
+			{
+				this._store.load({
+					callback: function() {
+						this._getCombobox().setValue(null);
+					},
+					scope: this
+				});
+			}
+			else
+			{
+				this._store.reload();
+			}
+		}
+	},
+	
+	/**
+	 * Select the created data source in the combo box
+	 * @param {String} id the id of the new data source
+	 */
+	_selectNewDataSource: function(id)
+	{
+		var me = this;
+		
+		if (this._store.getById(id) != null)
+		{
+			this.setValue(id);
+		}
+		else
+		{
+			this._dataSourceToSelect = id;
+		}
+	}
+});
Index: main/plugin-core-ui/resources/js/Ametys/form/widget/LDAPDataSource.js
===================================================================
--- main/plugin-core-ui/resources/js/Ametys/form/widget/LDAPDataSource.js	(revision 0)
+++ main/plugin-core-ui/resources/js/Ametys/form/widget/LDAPDataSource.js	(revision 0)
@@ -0,0 +1,33 @@
+/*
+ *  Copyright 2015 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * Field displaying a combobox allowing to select one of the available LDAP data sources. Optionally, 
+ * this field can allow the addition of other LDAP data sources. 
+ */
+Ext.define('Ametys.form.widget.LDAPDataSource', {
+	extend: 'Ametys.form.widget.AbstractDataSource',
+    alias: ['widget.datasource-ldap'],
+	
+    dataSourceType: 'LDAP',
+	tooltipText: "<i18n:text i18n:key='PLUGINS_CORE_UI_WIDGET_LDAP_DATASOURCE_BUTTON_TOOLTIP'/>",
+	
+	creationHandler: function()
+	{
+		this._addingDataSource = true;
+		Ametys.plugins.admin.datasource.EditLDAPDataSourceHelper.add(Ext.bind(this._selectNewDataSource, this));
+	}
+});
Index: main/plugin-core-ui/resources/js/Ametys/form/widget/SQLDataSource.js
===================================================================
--- main/plugin-core-ui/resources/js/Ametys/form/widget/SQLDataSource.js	(revision 0)
+++ main/plugin-core-ui/resources/js/Ametys/form/widget/SQLDataSource.js	(revision 0)
@@ -0,0 +1,32 @@
+/*
+ *  Copyright 2015 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * Field displaying a combobox allowing to select one of the available SQL data sources. Optionally, 
+ * this field can allow the addition of other SQL data sources. 
+ */
+Ext.define('Ametys.form.widget.SQLDataSource', {
+    extend: 'Ametys.form.widget.AbstractDataSource',
+    alias: ['widget.datasource-sql'],
+	
+    dataSourceType: 'SQL',
+	tooltipText: "<i18n:text i18n:key='PLUGINS_CORE_UI_WIDGET_SQL_DATASOURCE_BUTTON_TOOLTIP'/>",
+
+	creationHandler: function()
+	{
+		Ametys.plugins.admin.datasource.EditSQLDataSourceHelper.add(Ext.bind(this._selectNewDataSource, this));
+	}
+});
Index: main/workspace-admin/i18n/messages_en.xml
===================================================================
--- main/workspace-admin/i18n/messages_en.xml	(revision 38980)
+++ main/workspace-admin/i18n/messages_en.xml	(working copy)
@@ -46,4 +46,7 @@
     <message key="RIBBON_ADMINISTRATION_TABS_TAB_CONFIG_LABEL">Configuration</message>
     <message key="RIBBON_ADMINISTRATION_TABS_TAB_CONFIG_GROUPS_GROUP_ACTIONS">Actions</message>
     
+    <message key="RIBBON_ADMINISTRATION_TABS_TAB_HOME_GROUP_GROUP_DATASOURCE_LABEL">Data sources</message>
+    <message key="RIBBON_ADMINISTRATION_TABS_TAB_DATASOURCES_GROUPS_GROUP_SQL_ACTIONS">SQL</message>
+    <message key="RIBBON_ADMINISTRATION_TABS_TAB_DATASOURCES_GROUPS_GROUP_LDAP_ACTIONS">LDAP</message>
 </catalogue>
\ No newline at end of file
Index: main/workspace-admin/i18n/messages_fr.xml
===================================================================
--- main/workspace-admin/i18n/messages_fr.xml	(revision 38980)
+++ main/workspace-admin/i18n/messages_fr.xml	(working copy)
@@ -45,5 +45,8 @@
     
     <message key="RIBBON_ADMINISTRATION_TABS_TAB_CONFIG_LABEL">Configuration</message>
     <message key="RIBBON_ADMINISTRATION_TABS_TAB_CONFIG_GROUPS_GROUP_ACTIONS">Actions</message>
-
+    
+    <message key="RIBBON_ADMINISTRATION_TABS_TAB_HOME_GROUP_GROUP_DATASOURCE_LABEL">Source de données</message>
+    <message key="RIBBON_ADMINISTRATION_TABS_TAB_DATASOURCES_GROUPS_GROUP_SQL_ACTIONS">SQL</message>
+    <message key="RIBBON_ADMINISTRATION_TABS_TAB_DATASOURCES_GROUPS_GROUP_LDAP_ACTIONS">LDAP</message>
 </catalogue>
\ No newline at end of file
Index: main/workspace-admin/src/org/ametys/runtime/workspaces/admin/admin-safe-ribbon-noconfig.xml
===================================================================
--- main/workspace-admin/src/org/ametys/runtime/workspaces/admin/admin-safe-ribbon-noconfig.xml	(revision 38980)
+++ main/workspace-admin/src/org/ametys/runtime/workspaces/admin/admin-safe-ribbon-noconfig.xml	(working copy)
@@ -47,6 +47,13 @@
                     </medium>
                     <small/>
                 </group>
+                <group label="workspace.admin:RIBBON_ADMINISTRATION_TABS_TAB_HOME_GROUP_GROUP_DATASOURCE_LABEL" icon="">
+                    <large/>
+                    <medium>
+                        <control id="org.ametys.plugins.admin.DataSource"/>
+                    </medium>
+                    <small/>
+                </group>
             </groups>
         </tab>
         
@@ -157,5 +164,29 @@
                 </group>
             </groups>
         </tab>
+        
+        <!-- Contextual tab for data sources -->
+        <tab id="org.ametys.plugins.admin.datasources.Tab" label="workspace.admin:RIBBON_ADMINISTRATION_TABS_TAB_HOME_GROUP_GROUP_DATASOURCE_LABEL" contextualLabel="workspace.admin:RIBBON_ADMINISTRATION_TABS_TAB_HOME_GROUP_GROUP_DATASOURCE_LABEL" contextualColor="1" contextualGroup="DATASOURCES">
+            <groups>
+                <group label="workspace.admin:RIBBON_ADMINISTRATION_TABS_TAB_DATASOURCES_GROUPS_GROUP_SQL_ACTIONS" icon="">
+                    <large/>
+                    <medium>
+                        <control id="org.ametys.plugins.admin.actions.datasources.ldap.Add"/>
+                        <control id="org.ametys.plugins.admin.actions.datasources.ldap.Modify"/>
+                        <control id="org.ametys.plugins.admin.actions.datasources.ldap.Remove"/>
+                    </medium>
+                    <small/>
+                </group>
+                <group label="workspace.admin:RIBBON_ADMINISTRATION_TABS_TAB_DATASOURCES_GROUPS_GROUP_LDAP_ACTIONS" icon="">
+                    <large/>
+                    <medium>
+                        <control id="org.ametys.plugins.admin.actions.datasources.ldap.Add"/>
+                        <control id="org.ametys.plugins.admin.actions.datasources.ldap.Modify"/>
+                        <control id="org.ametys.plugins.admin.actions.datasources.ldap.Remove"/>
+                    </medium>
+                    <small/>
+                </group>
+            </groups>
+        </tab>
     </tabs>
 </ribbon>
Index: main/workspace-admin/src/org/ametys/runtime/workspaces/admin/admin-safe-ribbon.xml
===================================================================
--- main/workspace-admin/src/org/ametys/runtime/workspaces/admin/admin-safe-ribbon.xml	(revision 38980)
+++ main/workspace-admin/src/org/ametys/runtime/workspaces/admin/admin-safe-ribbon.xml	(working copy)
@@ -54,6 +54,13 @@
                     </medium>
                     <small/>
                 </group>
+                <group label="workspace.admin:RIBBON_ADMINISTRATION_TABS_TAB_HOME_GROUP_GROUP_DATASOURCE_LABEL" icon="">
+                    <large/>
+                    <medium>
+                        <control id="org.ametys.plugins.admin.DataSource"/>
+                    </medium>
+                    <small/>
+                </group>
             </groups>
         </tab>
         
@@ -177,5 +184,29 @@
                 </group>
             </groups>
         </tab>
+        
+        <!-- Contextual tab for data sources -->
+        <tab id="org.ametys.plugins.admin.datasources.Tab" label="workspace.admin:RIBBON_ADMINISTRATION_TABS_TAB_HOME_GROUP_GROUP_DATASOURCE_LABEL" contextualLabel="workspace.admin:RIBBON_ADMINISTRATION_TABS_TAB_HOME_GROUP_GROUP_DATASOURCE_LABEL" contextualColor="1" contextualGroup="DATASOURCES">
+            <groups>
+                <group label="workspace.admin:RIBBON_ADMINISTRATION_TABS_TAB_DATASOURCES_GROUPS_GROUP_SQL_ACTIONS" icon="">
+                    <large/>
+                    <medium>
+                        <control id="org.ametys.plugins.admin.actions.datasources.sql.Add"/>
+                        <control id="org.ametys.plugins.admin.actions.datasources.sql.Modify"/>
+                        <control id="org.ametys.plugins.admin.actions.datasources.sql.Remove"/>
+                    </medium>
+                    <small/>
+                </group>
+                <group label="workspace.admin:RIBBON_ADMINISTRATION_TABS_TAB_DATASOURCES_GROUPS_GROUP_LDAP_ACTIONS" icon="">
+                    <large/>
+                    <medium>
+                        <control id="org.ametys.plugins.admin.actions.datasources.ldap.Add"/>
+                        <control id="org.ametys.plugins.admin.actions.datasources.ldap.Modify"/>
+                        <control id="org.ametys.plugins.admin.actions.datasources.ldap.Remove"/>
+                    </medium>
+                    <small/>
+                </group>
+            </groups>
+        </tab>
     </tabs>
 </ribbon>
Index: test/environments/configs/config1.xml
===================================================================
--- test/environments/configs/config1.xml	(revision 38980)
+++ test/environments/configs/config1.xml	(working copy)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright 2009 Anyware Services
+   Copyright 2015 Anyware Services
 
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
@@ -13,31 +13,31 @@
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
-   -->
+-->
    
 <!-- 
     CORRECT DATASOURCE CONFIG TO MYSQL TEST BASE
     CORRECT runtime2 config
  -->
 <config>
-<runtime.datasource.core.jdbc.user>Ametys_Runtime</runtime.datasource.core.jdbc.user>
-<runtime.datasource.core.jdbc.driver>com.mysql.jdbc.Driver</runtime.datasource.core.jdbc.driver>
-<runtime.datasource.core.jdbc.passwd>Ametys_Runtime</runtime.datasource.core.jdbc.passwd>
-<runtime.datasource.core.jdbc.url>jdbc:mysql://mysql-dev.anyware.corp/Ametys_Runtime_Test</runtime.datasource.core.jdbc.url>
-<runtime.authentication.basic.realm>realm</runtime.authentication.basic.realm>
-<runtime.upload.max-size>10000000</runtime.upload.max-size>
-<runtime.debug.ui>0</runtime.debug.ui>
-<runtime.cache.xslt>false</runtime.cache.xslt>
-<runtime.log.abnormal.time>false</runtime.log.abnormal.time>
-<smtp.mail.host>smtp.anyware.corp</smtp.mail.host>
-<smtp.mail.port>993</smtp.mail.port>
-<smtp.mail.security.protocol>none</smtp.mail.security.protocol>
-<smtp.mail.user></smtp.mail.user>
-<smtp.mail.password></smtp.mail.password>
-<smtp.mail.from>test@ametys.org</smtp.mail.from>
-<smtp.mail.sysadminto>ametys@ametys.org</smtp.mail.sysadminto>
-<param2>param2</param2>
-<param4>4</param4>
+	<runtime.datasource.core.jdbc.pool>SQL-test</runtime.datasource.core.jdbc.pool>
+	<runtime.authentication.basic.realm>realm</runtime.authentication.basic.realm>
+	<runtime.upload.max-size>10000000</runtime.upload.max-size>
+	<runtime.debug.ui>0</runtime.debug.ui>
+	<runtime.cache.xslt>false</runtime.cache.xslt>
+	<runtime.log.abnormal.time>false</runtime.log.abnormal.time>
+	<smtp.mail.host>mail.anyware.corp</smtp.mail.host>
+	<smtp.mail.port>993</smtp.mail.port>
+	<smtp.mail.security.protocol>none</smtp.mail.security.protocol>
+	<smtp.mail.user></smtp.mail.user>
+	<smtp.mail.password></smtp.mail.password>
+	<smtp.mail.from>test@ametys.org</smtp.mail.from>
+	<smtp.mail.sysadminto>ametys@ametys.org</smtp.mail.sysadminto>
+	<param2>param2</param2>
+	<param4>4</param4>
+	<runtime.captcha.type>jcaptcha</runtime.captcha.type>
+    <runtime.captcha.recaptcha.publickey/>
+    <runtime.captcha.recaptcha.secretkey/>
 <runtime.captcha.type>jcaptcha</runtime.captcha.type>
 <runtime.captcha.recaptcha.publickey/>
 <runtime.captcha.recaptcha.secretkey/>
Index: test/environments/configs/config2.xml
===================================================================
--- test/environments/configs/config2.xml	(revision 38980)
+++ test/environments/configs/config2.xml	(working copy)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright 2009 Anyware Services
+   Copyright 2015 Anyware Services
 
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
Index: test/environments/configs/config3.xml
===================================================================
--- test/environments/configs/config3.xml	(revision 38980)
+++ test/environments/configs/config3.xml	(working copy)
@@ -22,24 +22,14 @@
     USER DRIVEN LDAP CONFIG
  -->
 <config>
-<runtime.datasource.core.jdbc.user>Ametys_Runtime</runtime.datasource.core.jdbc.user>
-<runtime.datasource.core.jdbc.driver>com.mysql.jdbc.Driver</runtime.datasource.core.jdbc.driver>
-<runtime.datasource.core.jdbc.passwd>Ametys_Runtime</runtime.datasource.core.jdbc.passwd>
-<runtime.datasource.core.jdbc.url>jdbc:mysql://mysql-dev.anyware.corp/Ametys_Runtime_Test</runtime.datasource.core.jdbc.url>
+<runtime.datasource.core.jdbc.pool>SQL-test</runtime.datasource.core.jdbc.pool>
 <runtime.authentication.basic.realm>realm</runtime.authentication.basic.realm>
 <runtime.upload.max-size>10000000</runtime.upload.max-size>
 <runtime.debug.ui>0</runtime.debug.ui>
 <runtime.cache.xslt>false</runtime.cache.xslt>
 <runtime.log.abnormal.time>false</runtime.log.abnormal.time>
 
-<runtime.datasource.core.ldap.baseUrl>ldap://ldap-dev.anyware.corp</runtime.datasource.core.ldap.baseUrl>
-<runtime.datasource.core.ldap.useSSL>false</runtime.datasource.core.ldap.useSSL>
-<runtime.datasource.core.ldap.baseDN>dc=ametys-test-groups,dc=org</runtime.datasource.core.ldap.baseDN>
-<runtime.datasource.core.ldap.authMethod>none</runtime.datasource.core.ldap.authMethod>
-<runtime.datasource.core.ldap.adminDN></runtime.datasource.core.ldap.adminDN>
-<runtime.datasource.core.ldap.adminPasswd></runtime.datasource.core.ldap.adminPasswd>
-<runtime.datasource.core.ldap.aliasDereferencing>always</runtime.datasource.core.ldap.aliasDereferencing>
-<runtime.datasource.core.ldap.followReferrals>false</runtime.datasource.core.ldap.followReferrals>
+<runtime.datasource.core.ldap>LDAP-test-groups</runtime.datasource.core.ldap>
 
 
 <runtime.users.ldap.peopleDN>ou=people</runtime.users.ldap.peopleDN>
Index: test/environments/configs/config4.xml
===================================================================
--- test/environments/configs/config4.xml	(revision 38980)
+++ test/environments/configs/config4.xml	(working copy)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright 2009 Anyware Services
+   Copyright 2015 Anyware Services
 
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
-   -->
+-->
 
 <!-- 
     DATASOURCE CONFIG
@@ -21,24 +21,14 @@
     GROUP DRIVEN LDAP CONFIG
  -->
 <config>
-<runtime.datasource.core.jdbc.user>Ametys_Runtime</runtime.datasource.core.jdbc.user>
-<runtime.datasource.core.jdbc.driver>com.mysql.jdbc.Driver</runtime.datasource.core.jdbc.driver>
-<runtime.datasource.core.jdbc.passwd>Ametys_Runtime</runtime.datasource.core.jdbc.passwd>
-<runtime.datasource.core.jdbc.url>jdbc:mysql://mysql-dev.anyware.corp/Ametys_Runtime_Test</runtime.datasource.core.jdbc.url>
+<runtime.datasource.core.jdbc.pool>SQL-test</runtime.datasource.core.jdbc.pool>
 <runtime.authentication.basic.realm>realm</runtime.authentication.basic.realm>
 <runtime.upload.max-size>10000000</runtime.upload.max-size>
 <runtime.debug.ui>0</runtime.debug.ui>
 <runtime.cache.xslt>false</runtime.cache.xslt>
 <runtime.log.abnormal.time>false</runtime.log.abnormal.time>
 
-<runtime.datasource.core.ldap.baseUrl>ldap://ldap-dev.anyware.corp</runtime.datasource.core.ldap.baseUrl>
-<runtime.datasource.core.ldap.useSSL>false</runtime.datasource.core.ldap.useSSL>
-<runtime.datasource.core.ldap.baseDN>dc=ametys-test-users,dc=org</runtime.datasource.core.ldap.baseDN>
-<runtime.datasource.core.ldap.authMethod>none</runtime.datasource.core.ldap.authMethod>
-<runtime.datasource.core.ldap.adminDN></runtime.datasource.core.ldap.adminDN>
-<runtime.datasource.core.ldap.adminPasswd></runtime.datasource.core.ldap.adminPasswd>
-<runtime.datasource.core.ldap.aliasDereferencing>always</runtime.datasource.core.ldap.aliasDereferencing>
-<runtime.datasource.core.ldap.followReferrals>false</runtime.datasource.core.ldap.followReferrals>
+<runtime.datasource.core.ldap>LDAP-test-users</runtime.datasource.core.ldap>
 
 <runtime.users.ldap.peopleDN>ou=people</runtime.users.ldap.peopleDN>
 <runtime.users.ldap.baseFilter>(objectclass=inetOrgPerson)</runtime.users.ldap.baseFilter>
Index: test/environments/configs/config_derby.xml
===================================================================
--- test/environments/configs/config_derby.xml	(revision 38980)
+++ test/environments/configs/config_derby.xml	(nonexistent)
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-   Copyright 2011 Anyware Services
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-   -->
-   
-<config>
-    <runtime.datasource.core.jdbc.driver>org.apache.derby.jdbc.EmbeddedDriver</runtime.datasource.core.jdbc.driver>
-    <runtime.datasource.core.jdbc.url>jdbc:derby:tmp/derby;create=true</runtime.datasource.core.jdbc.url>
-    <runtime.datasource.core.jdbc.user/>
-    <runtime.datasource.core.jdbc.passwd/>
-    <runtime.authentication.basic.realm>realm</runtime.authentication.basic.realm>
-    <runtime.upload.max-size>10000000</runtime.upload.max-size>
-    <runtime.debug.ui>0</runtime.debug.ui>
-    <runtime.cache.xslt>false</runtime.cache.xslt>
-    <runtime.log.abnormal.time>false</runtime.log.abnormal.time>
-    <smtp.mail.host>smtp.anyware.corp</smtp.mail.host>
-    <smtp.mail.port>993</smtp.mail.port>
-    <smtp.mail.user></smtp.mail.user>
-    <smtp.mail.security.protocol>none</smtp.mail.security.protocol>
-    <smtp.mail.password></smtp.mail.password>
-    <smtp.mail.from>test@ametys.org</smtp.mail.from>
-    <smtp.mail.sysadminto>ametys@ametys.org</smtp.mail.sysadminto>
-    <runtime.captcha.type>jcaptcha</runtime.captcha.type>
-    <runtime.captcha.recaptcha.publickey/>
-    <runtime.captcha.recaptcha.secretkey/>
-</config>
Index: test/environments/configs/config_hsqldb.xml
===================================================================
--- test/environments/configs/config_hsqldb.xml	(revision 38980)
+++ test/environments/configs/config_hsqldb.xml	(nonexistent)
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-   Copyright 2013 Anyware Services
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-   -->
-   
-<config>
-    <runtime.datasource.core.jdbc.driver>org.hsqldb.jdbc.JDBCDriver</runtime.datasource.core.jdbc.driver>
-    <runtime.datasource.core.jdbc.url>jdbc:hsqldb:tmp/hsqldb</runtime.datasource.core.jdbc.url>
-    <runtime.datasource.core.jdbc.user/>
-    <runtime.datasource.core.jdbc.passwd/>
-    <runtime.authentication.basic.realm>realm</runtime.authentication.basic.realm>
-    <runtime.upload.max-size>10000000</runtime.upload.max-size>
-    <runtime.debug.ui>0</runtime.debug.ui>
-    <runtime.cache.xslt>false</runtime.cache.xslt>
-    <runtime.log.abnormal.time>false</runtime.log.abnormal.time>
-    <smtp.mail.host>smtp.anyware.corp</smtp.mail.host>
-    <smtp.mail.port>993</smtp.mail.port>
-    <smtp.mail.security.protocol>none</smtp.mail.security.protocol>
-    <smtp.mail.user></smtp.mail.user>
-    <smtp.mail.password></smtp.mail.password>
-    <smtp.mail.from>test@ametys.org</smtp.mail.from>
-    <smtp.mail.sysadminto>ametys@ametys.org</smtp.mail.sysadminto>
-    <runtime.captcha.type>jcaptcha</runtime.captcha.type>
-    <runtime.captcha.recaptcha.publickey/>
-    <runtime.captcha.recaptcha.secretkey/>
-</config>
Index: test/environments/configs/config_oracle.xml
===================================================================
--- test/environments/configs/config_oracle.xml	(revision 38980)
+++ test/environments/configs/config_oracle.xml	(nonexistent)
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-   Copyright 2011 Anyware Services
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-   -->
-   
-<config>
-    <runtime.datasource.core.jdbc.driver>oracle.jdbc.driver.OracleDriver</runtime.datasource.core.jdbc.driver>
-    <runtime.datasource.core.jdbc.url>jdbc:oracle:thin:@oracle10.anyware.corp:1521:XE</runtime.datasource.core.jdbc.url>
-    <runtime.datasource.core.jdbc.user>Ametys_Runtime</runtime.datasource.core.jdbc.user>
-    <runtime.datasource.core.jdbc.passwd>Ametys_Runtime</runtime.datasource.core.jdbc.passwd>
-    <runtime.authentication.basic.realm>realm</runtime.authentication.basic.realm>
-    <runtime.upload.max-size>10000000</runtime.upload.max-size>
-    <runtime.debug.ui>0</runtime.debug.ui>
-    <runtime.cache.xslt>false</runtime.cache.xslt>
-    <runtime.log.abnormal.time>false</runtime.log.abnormal.time>
-    <smtp.mail.host>smtp.anyware.corp</smtp.mail.host>
-    <smtp.mail.port>993</smtp.mail.port>
-    <smtp.mail.security.protocol>none</smtp.mail.security.protocol>
-    <smtp.mail.user></smtp.mail.user>
-    <smtp.mail.password></smtp.mail.password>
-    <smtp.mail.from>test@ametys.org</smtp.mail.from>
-    <smtp.mail.sysadminto>ametys@ametys.org</smtp.mail.sysadminto>
-    <runtime.captcha.type>jcaptcha</runtime.captcha.type>
-    <runtime.captcha.recaptcha.publickey/>
-    <runtime.captcha.recaptcha.secretkey/>
-</config>
Index: test/environments/configs/config_postgres.xml
===================================================================
--- test/environments/configs/config_postgres.xml	(revision 38980)
+++ test/environments/configs/config_postgres.xml	(nonexistent)
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-   Copyright 2011 Anyware Services
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-   -->
-   
-<config>
-<runtime.datasource.core.jdbc.user>ametys_runtime</runtime.datasource.core.jdbc.user>
-<runtime.datasource.core.jdbc.driver>org.postgresql.Driver</runtime.datasource.core.jdbc.driver>
-<runtime.datasource.core.jdbc.passwd>ametys_runtime</runtime.datasource.core.jdbc.passwd>
-<runtime.datasource.core.jdbc.url>jdbc:postgresql://goldorak/ametys_runtime_test</runtime.datasource.core.jdbc.url>
-<runtime.authentication.basic.realm>realm</runtime.authentication.basic.realm>
-<runtime.upload.max-size>10000000</runtime.upload.max-size>
-<runtime.debug.ui>0</runtime.debug.ui>
-<runtime.cache.xslt>false</runtime.cache.xslt>
-<runtime.log.abnormal.time>false</runtime.log.abnormal.time>
-<smtp.mail.host>smtp.anyware.corp</smtp.mail.host>
-<smtp.mail.port>993</smtp.mail.port>
-<smtp.mail.security.protocol>none</smtp.mail.security.protocol>
-<smtp.mail.user></smtp.mail.user>
-<smtp.mail.password></smtp.mail.password>
-<smtp.mail.from>test@ametys.org</smtp.mail.from>
-<smtp.mail.sysadminto>ametys@ametys.org</smtp.mail.sysadminto>
-<runtime.captcha.type>jcaptcha</runtime.captcha.type>
-<runtime.captcha.recaptcha.publickey/>
-<runtime.captcha.recaptcha.secretkey/>
-</config>
Index: test/environments/configs/datasource-derby.xml
===================================================================
--- test/environments/configs/datasource-derby.xml	(revision 0)
+++ test/environments/configs/datasource-derby.xml	(revision 0)
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright 2015 Anyware Services
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   -->
+<datasources>
+    <datasource id="SQL-test">
+        <name>Ametys Test Derby</name>
+        <driver>org.apache.derby.jdbc.EmbeddedDriver</driver>
+        <url>jdbc:derby:tmp/derby;create=true</url>
+        <user/>
+        <password/>
+    </datasource>
+</datasources>
+
Index: test/environments/configs/datasource-hsql.xml
===================================================================
--- test/environments/configs/datasource-hsql.xml	(revision 0)
+++ test/environments/configs/datasource-hsql.xml	(revision 0)
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright 2015 Anyware Services
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   -->
+<datasources>
+    <datasource id="SQL-test">
+        <name>Ametys Test HSQL</name>
+        <driver>org.hsqldb.jdbc.JDBCDriver</driver>
+        <url>jdbc:hsqldb:tmp/hsqldb</url>
+        <user/>
+        <password/>
+    </datasource>
+</datasources>
+
Index: test/environments/configs/datasource-ldap.xml
===================================================================
--- test/environments/configs/datasource-ldap.xml	(revision 0)
+++ test/environments/configs/datasource-ldap.xml	(revision 0)
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright 2015 Anyware Services
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<datasources>
+    <datasource id="LDAP-test-users">
+        <name>LDAP Anyware Users</name>
+        <description />
+        <baseURL>ldap://ldap-dev.anyware.corp</baseURL>
+        <useSSL>false</useSSL>
+        <baseDN>dc=ametys-test-users,dc=org</baseDN>
+        <aliasDereferencing>always</aliasDereferencing>
+        <authenticationMethod>none</authenticationMethod>
+        <followReferrals>false</followReferrals>
+        <adminDN />
+        <adminPassword />
+    </datasource>
+    <datasource id="LDAP-test-groups">
+        <name>LDAP Anyware Users</name>
+        <description />
+        <baseURL>ldap://ldap-dev.anyware.corp</baseURL>
+        <useSSL>false</useSSL>
+        <baseDN>dc=ametys-test-groups,dc=org</baseDN>
+        <aliasDereferencing>always</aliasDereferencing>
+        <authenticationMethod>none</authenticationMethod>
+        <followReferrals>false</followReferrals>
+        <adminDN />
+        <adminPassword />
+    </datasource>
+</datasources>
\ No newline at end of file
Index: test/environments/configs/datasource-mysql.xml
===================================================================
--- test/environments/configs/datasource-mysql.xml	(revision 0)
+++ test/environments/configs/datasource-mysql.xml	(revision 0)
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright 2015 Anyware Services
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   -->
+<datasources>
+	<datasource id="SQL-test">
+		<name>Ametys Test MySQL</name>
+		<driver>com.mysql.jdbc.Driver</driver>
+		<url>jdbc:mysql://mysql-dev.anyware.corp/Ametys_Runtime_Test</url>
+		<user>Ametys_Runtime</user>
+		<password>Ametys_Runtime</password>
+	</datasource>
+</datasources>
+
Index: test/environments/configs/datasource-oracle.xml
===================================================================
--- test/environments/configs/datasource-oracle.xml	(revision 0)
+++ test/environments/configs/datasource-oracle.xml	(revision 0)
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright 2015 Anyware Services
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   -->
+<datasources>
+    <datasource id="SQL-test">
+        <name>Ametys Test Oracle</name>
+        <driver>oracle.jdbc.driver.OracleDriver</driver>
+        <url>jdbc:oracle:thin:@oracle10.anyware.corp:1521:XE</url>
+        <user>Ametys_Runtime</user>
+        <password>Ametys_Runtime</password>
+    </datasource>
+</datasources>
Index: test/environments/configs/datasource-postgresql.xml
===================================================================
--- test/environments/configs/datasource-postgresql.xml	(revision 0)
+++ test/environments/configs/datasource-postgresql.xml	(revision 0)
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright 2015 Anyware Services
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   -->
+<datasources>
+    <datasource id="SQL-test">
+        <name>Ametys Test Derby</name>
+        <driver>org.postgresql.Driver</driver>
+        <url>jdbc:postgresql://goldorak/ametys_runtime_test</url>
+        <user>ametys_runtime</user>
+        <password>ametys_runtime</password>
+    </datasource>
+</datasources>
+
Index: test/environments/configs/datasource-sql.xml
===================================================================
Index: test/src/org/ametys/runtime/test/AbstractJDBCTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/AbstractJDBCTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/AbstractJDBCTestCase.java	(working copy)
@@ -21,12 +21,14 @@
 import java.util.List;
 
 import org.ametys.core.datasource.ConnectionHelper;
+import org.ametys.runtime.config.Config;
 
 /**
  * Abstract test case for jdbc Runtime test cases.
  */
 public abstract class AbstractJDBCTestCase extends AbstractRuntimeTestCase
 {
+
     /**
      * Reset the database and insert the scripts. Needs the Init class.
      * @param scripts A list of script to play on db. Scripts should reset tables.
@@ -34,20 +36,13 @@
      */
     protected void _setDatabase(List<File> scripts) throws Exception
     {
-        Connection connection = null;
-        
-        try
+        String dataSourceId = Config.getInstance().getValueAsString(ConnectionHelper.CORE_POOL_CONFIG_PARAM);
+        try (Connection connection = ConnectionHelper.getConnection(dataSourceId))
         {
-            connection = ConnectionHelper.getConnection(ConnectionHelper.CORE_POOL_NAME);
-            
             for (File script : scripts)
             {
                 ScriptRunner.runScript(connection, new FileInputStream(script));
             }
         }
-        finally
-        {
-            ConnectionHelper.cleanup(connection);
-        }
     }
 }
Index: test/src/org/ametys/runtime/test/AllDerbyTestSuite.java
===================================================================
--- test/src/org/ametys/runtime/test/AllDerbyTestSuite.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/AllDerbyTestSuite.java	(working copy)
@@ -15,9 +15,6 @@
  */
 package org.ametys.runtime.test;
 
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
 import org.ametys.runtime.test.groups.jdbc.DerbyJdbcGroupsTestCase;
 import org.ametys.runtime.test.rights.profile.DerbyProfileBasedRightsManagerTestCase;
 import org.ametys.runtime.test.rights.profile.hierarchical.DerbyHierarchicalProfileBasedRightsManagerTestCase;
@@ -27,6 +24,9 @@
 import org.ametys.runtime.test.users.jdbc.modifiable.DerbyModifiableJdbcUsersTestCase;
 import org.ametys.runtime.test.users.jdbc.modifiablecredentialsaware.DerbyModifiableCredentialsAwareJdbcUsersTestCase;
 
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
 /**
  * Test suite grouping all Runtime tests
  */
Index: test/src/org/ametys/runtime/test/AllMysqlTestSuite.java
===================================================================
--- test/src/org/ametys/runtime/test/AllMysqlTestSuite.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/AllMysqlTestSuite.java	(working copy)
@@ -15,9 +15,6 @@
  */
 package org.ametys.runtime.test;
 
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
 import org.ametys.runtime.test.groups.jdbc.MysqlJdbcGroupsTestCase;
 import org.ametys.runtime.test.rights.profile.MysqlProfileBasedRightsManagerTestCase;
 import org.ametys.runtime.test.rights.profile.hierarchical.MysqlHierarchicalProfileBasedRightsManagerTestCase;
@@ -27,6 +24,9 @@
 import org.ametys.runtime.test.users.jdbc.modifiable.MysqlModifiableJdbcUsersTestCase;
 import org.ametys.runtime.test.users.jdbc.modifiablecredentialsaware.MysqlModifiableCredentialsAwareJdbcUsersTestCase;
 
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
 /**
  * Test suite grouping all Mysql-based tests
  */
Index: test/src/org/ametys/runtime/test/AllOracleTestSuite.java
===================================================================
--- test/src/org/ametys/runtime/test/AllOracleTestSuite.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/AllOracleTestSuite.java	(working copy)
@@ -15,9 +15,6 @@
  */
 package org.ametys.runtime.test;
 
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
 import org.ametys.runtime.test.groups.jdbc.OracleJdbcGroupsTestCase;
 import org.ametys.runtime.test.rights.profile.OracleProfileBasedRightsManagerTestCase;
 import org.ametys.runtime.test.rights.profile.hierarchical.OracleHierarchicalProfileBasedRightsManagerTestCase;
@@ -27,6 +24,9 @@
 import org.ametys.runtime.test.users.jdbc.modifiable.OracleModifiableJdbcUsersTestCase;
 import org.ametys.runtime.test.users.jdbc.modifiablecredentialsaware.OracleModifiableCredentialsAwareJdbcUsersTestCase;
 
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
 /**
  * Test suite grouping all Runtime tests
  */
Index: test/src/org/ametys/runtime/test/AllPostgresTestSuite.java
===================================================================
--- test/src/org/ametys/runtime/test/AllPostgresTestSuite.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/AllPostgresTestSuite.java	(working copy)
@@ -15,9 +15,6 @@
  */
 package org.ametys.runtime.test;
 
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
 import org.ametys.runtime.test.groups.jdbc.PostgresJdbcGroupsTestCase;
 import org.ametys.runtime.test.rights.profile.PostgresProfileBasedRightsManagerTestCase;
 import org.ametys.runtime.test.rights.profile.hierarchical.PostgresHierarchicalProfileBasedRightsManagerTestCase;
@@ -27,6 +24,9 @@
 import org.ametys.runtime.test.users.jdbc.modifiable.PostgresModifiableJdbcUsersTestCase;
 import org.ametys.runtime.test.users.jdbc.modifiablecredentialsaware.PostgresModifiableCredentialsAwareJdbcUsersTestCase;
 
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
 /**
  * Test suite grouping all Runtime tests
  */
Index: test/src/org/ametys/runtime/test/AllTests.java
===================================================================
--- test/src/org/ametys/runtime/test/AllTests.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/AllTests.java	(working copy)
@@ -15,9 +15,6 @@
  */
 package org.ametys.runtime.test;
 
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
 import org.ametys.runtime.test.administrator.jvmstatus.RequestCountListenerTestCase;
 import org.ametys.runtime.test.administrator.jvmstatus.SessionCountListenerTestCase;
 import org.ametys.runtime.test.cocoon.XHTMLSerializerTestCase;
@@ -43,6 +40,9 @@
 import org.ametys.runtime.test.util.I18nTestCase;
 import org.ametys.runtime.test.util.JSONTestCase;
 
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
 /**
  * Test suite grouping all Runtime tests
  */
Index: test/src/org/ametys/runtime/test/AmetysHomeTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/AmetysHomeTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/AmetysHomeTestCase.java	(working copy)
@@ -45,7 +45,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        _startApplication("test/environments/runtimes/runtime01.xml", "test/environments/configs/config1.xml", "test/environments/webapp1");
+        _startApplication("test/environments/runtimes/runtime01.xml", "test/environments/configs/config1.xml", null, null, "test/environments/webapp1");
         super.setUp();
     }
     
Index: test/src/org/ametys/runtime/test/JdbcTestSuite.java
===================================================================
--- test/src/org/ametys/runtime/test/JdbcTestSuite.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/JdbcTestSuite.java	(working copy)
@@ -15,9 +15,6 @@
  */
 package org.ametys.runtime.test;
 
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
 import org.ametys.runtime.test.groups.jdbc.AllGroupsTestSuite;
 import org.ametys.runtime.test.rights.profile.AllProfileBasedRightsManagerTestSuite;
 import org.ametys.runtime.test.rights.profile.hierarchical.AllHierarchicalProfileBasedRightsManagerTestSuite;
@@ -27,6 +24,9 @@
 import org.ametys.runtime.test.users.jdbc.modifiable.AllModifiableUsersTestSuite;
 import org.ametys.runtime.test.users.jdbc.modifiablecredentialsaware.AllModifiableCredentialsAwareJdbcUsersTestSuite;
 
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
 /**
  * Test suite grouping all JDBC-related runtime tests.
  */
Index: test/src/org/ametys/runtime/test/RuntimeConfigTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/RuntimeConfigTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/RuntimeConfigTestCase.java	(working copy)
@@ -83,7 +83,7 @@
      */
     public void testVersion() throws Exception
     {
-        CocoonWrapper cocoon = _startApplication("test/environments/runtimes/runtime01.xml", "test/environments/configs/config1.xml", "test/environments/webapp1");
+        CocoonWrapper cocoon = _startApplication("test/environments/runtimes/runtime01.xml", "test/environments/configs/config1.xml", null, null, "test/environments/webapp1");
         
         XPathProcessor xpath = (XPathProcessor) Init.getPluginServiceManager().lookup(XPathProcessor.ROLE);
         assertEquals("2.0.1", xpath.evaluateAsString(AmetysXSLTHelper.versions(), "Component[Name='Application']/Version"));
Index: test/src/org/ametys/runtime/test/WorkspacesTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/WorkspacesTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/WorkspacesTestCase.java	(working copy)
@@ -28,7 +28,7 @@
      */
     public void testValidWorkspace() throws Exception
     {
-        CocoonWrapper cocoon = _startApplication("test/environments/runtimes/runtime01.xml", "test/environments/configs/config1.xml", "test/environments/webapp2");
+        CocoonWrapper cocoon = _startApplication("test/environments/runtimes/runtime01.xml", "test/environments/configs/config1.xml", null, null, "test/environments/webapp2");
         
         assertTrue(WorkspaceManager.getInstance().getWorkspaceNames().contains("admin"));
         
@@ -53,7 +53,7 @@
         
         try
         {
-            cocoon = _startApplication("test/environments/runtimes/runtime01.xml", "test/environments/configs/config1.xml", "test/environments/webapp3");
+            cocoon = _startApplication("test/environments/runtimes/runtime01.xml", "test/environments/configs/config1.xml", null, null, "test/environments/webapp3");
             fail("WorskpaceManager must have failed");
         }
         catch (IllegalArgumentException e)
Index: test/src/org/ametys/runtime/test/groups/jdbc/AbstractJdbcGroupsTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/groups/jdbc/AbstractJdbcGroupsTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/groups/jdbc/AbstractJdbcGroupsTestCase.java	(working copy)
@@ -37,6 +37,7 @@
 import org.ametys.core.group.InvalidModificationException;
 import org.ametys.core.group.ModifiableGroupsManager;
 import org.ametys.plugins.core.impl.group.jdbc.ModifiableJdbcGroupsManager;
+import org.ametys.runtime.config.Config;
 import org.ametys.runtime.test.AbstractJDBCTestCase;
 import org.ametys.runtime.test.Init;
 
@@ -64,11 +65,12 @@
      * Reset the db
      * @param runtimeFilename The file name in runtimes env dir
      * @param configFileName The file name in config env dir
+     * @param sqlDataSourceFileName The file name in config env dir
      * @throws Exception if an error occurs
      */
-    protected void _resetDB(String runtimeFilename, String configFileName) throws Exception
+    protected void _resetDB(String runtimeFilename, String configFileName, String sqlDataSourceFileName) throws Exception
     {
-        _startApplication("test/environments/runtimes/" + runtimeFilename, "test/environments/configs/" + configFileName, "test/environments/webapp1");
+        _startApplication("test/environments/runtimes/" + runtimeFilename, "test/environments/configs/" + configFileName, "test/environments/configs/" + sqlDataSourceFileName, null, "test/environments/webapp1");
         
         _setDatabase(Arrays.asList(getScripts()));
 
@@ -231,13 +233,12 @@
     {
         List<String> result = new ArrayList<>();
 
-        Connection connection = null;
         PreparedStatement stmt = null;
         ResultSet rs = null;
         
-        try
+        String dataSourceId = Config.getInstance().getValueAsString(ConnectionHelper.CORE_POOL_CONFIG_PARAM);
+        try (Connection connection = ConnectionHelper.getConnection(dataSourceId);)
         {
-            connection = ConnectionHelper.getConnection(ConnectionHelper.CORE_POOL_NAME);
             stmt = connection.prepareStatement("SELECT Id FROM Groups order by Id");
             
             rs = stmt.executeQuery();
@@ -250,7 +251,6 @@
         {
             ConnectionHelper.cleanup(rs);
             ConnectionHelper.cleanup(stmt);
-            ConnectionHelper.cleanup(connection);
         }
         
         return result;
Index: test/src/org/ametys/runtime/test/groups/jdbc/DerbyJdbcGroupsTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/groups/jdbc/DerbyJdbcGroupsTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/groups/jdbc/DerbyJdbcGroupsTestCase.java	(working copy)
@@ -27,7 +27,7 @@
     protected void setUp() throws Exception
     {
         super.setUp();
-        _resetDB("runtime4.xml", "config_derby.xml");
+        _resetDB("runtime4.xml", "config1.xml", "datasource-derby.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/groups/jdbc/HsqlJdbcGroupsTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/groups/jdbc/HsqlJdbcGroupsTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/groups/jdbc/HsqlJdbcGroupsTestCase.java	(working copy)
@@ -27,7 +27,7 @@
     protected void setUp() throws Exception
     {
         super.setUp();
-        _resetDB("runtime4.xml", "config_hsqldb.xml");
+        _resetDB("runtime4.xml", "config1.xml", "datasource-hsql.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/groups/jdbc/MysqlJdbcGroupsTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/groups/jdbc/MysqlJdbcGroupsTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/groups/jdbc/MysqlJdbcGroupsTestCase.java	(working copy)
@@ -27,7 +27,7 @@
     protected void setUp() throws Exception
     {
         super.setUp();
-        _resetDB("runtime4.xml", "config1.xml");
+        _resetDB("runtime4.xml", "config1.xml", "datasource-mysql.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/groups/jdbc/OracleJdbcGroupsTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/groups/jdbc/OracleJdbcGroupsTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/groups/jdbc/OracleJdbcGroupsTestCase.java	(working copy)
@@ -27,7 +27,7 @@
     protected void setUp() throws Exception
     {
         super.setUp();
-        _resetDB("runtime4.xml", "config_oracle.xml");
+        _resetDB("runtime4.xml", "config1.xml", "datasource-oracle.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/groups/jdbc/PostgresJdbcGroupsTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/groups/jdbc/PostgresJdbcGroupsTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/groups/jdbc/PostgresJdbcGroupsTestCase.java	(working copy)
@@ -27,7 +27,7 @@
     protected void setUp() throws Exception
     {
         super.setUp();
-        _resetDB("runtime4.xml", "config_postgres.xml");
+        _resetDB("runtime4.xml", "config1.xml", "datasource-postgresql.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/groups/ldap/GroupDrivenLdapGroupsTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/groups/ldap/GroupDrivenLdapGroupsTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/groups/ldap/GroupDrivenLdapGroupsTestCase.java	(working copy)
@@ -30,7 +30,8 @@
     {
         super.setUp();
         
-        _startApplication("test/environments/runtimes/runtime8.xml", "test/environments/configs/config3.xml", "test/environments/webapp1");
+        _startApplication("test/environments/runtimes/runtime8.xml", "test/environments/configs/config3.xml", null, "test/environments/configs/datasource-ldap.xml", "test/environments/webapp1");
+        
         _groupsManager = (GroupsManager) Init.getPluginServiceManager().lookup(GroupsManager.ROLE);
     }
     
Index: test/src/org/ametys/runtime/test/groups/ldap/UserDrivenLdapGroupsTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/groups/ldap/UserDrivenLdapGroupsTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/groups/ldap/UserDrivenLdapGroupsTestCase.java	(working copy)
@@ -29,8 +29,8 @@
     protected void setUp() throws Exception
     {
         super.setUp();
-        
-        _startApplication("test/environments/runtimes/runtime9.xml", "test/environments/configs/config4.xml", "test/environments/webapp1");
+
+        _startApplication("test/environments/runtimes/runtime9.xml", "test/environments/configs/config4.xml", null, "test/environments/configs/datasource-ldap.xml", "test/environments/webapp1");
         _groupsManager = (GroupsManager) Init.getPluginServiceManager().lookup(GroupsManager.ROLE);
     }
     
Index: test/src/org/ametys/runtime/test/groups/others/EmptyGroupsTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/groups/others/EmptyGroupsTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/groups/others/EmptyGroupsTestCase.java	(working copy)
@@ -37,7 +37,7 @@
      */
     public void testEmpty() throws Exception
     {
-        CocoonWrapper cocoon = _startApplication("test/environments/runtimes/runtime01.xml", "test/environments/configs/config1.xml", "test/environments/webapp1");
+        CocoonWrapper cocoon = _startApplication("test/environments/runtimes/runtime01.xml", "test/environments/configs/config1.xml", null, null, "test/environments/webapp1");
         
         GroupsManager groupsManager = (GroupsManager) Init.getPluginServiceManager().lookup(GroupsManager.ROLE);
         
Index: test/src/org/ametys/runtime/test/plugins/PluginsTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/plugins/PluginsTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/plugins/PluginsTestCase.java	(working copy)
@@ -37,7 +37,7 @@
      */
     public void testInit() throws Exception
     {
-        CocoonWrapper cocoon = _startApplication("test/environments/runtimes/runtime01.xml", "test/environments/configs/config1.xml", "test/environments/webapp1");
+        CocoonWrapper cocoon = _startApplication("test/environments/runtimes/runtime01.xml", "test/environments/configs/config1.xml", null, null, "test/environments/webapp1");
         
         assertTrue(Init.isOk());
         
@@ -50,7 +50,7 @@
      */
     public void testLocation() throws Exception
     {
-        CocoonWrapper cocoon = _startApplication("test/environments/runtimes/runtime02.xml", "test/environments/configs/config1.xml", "test/environments/webapp1");
+        CocoonWrapper cocoon = _startApplication("test/environments/runtimes/runtime02.xml", "test/environments/configs/config1.xml", null, null, "test/environments/webapp1");
         
         assertTrue(PluginsManager.getInstance().getPluginNames().contains("test"));
         assertEquals("location1", PluginsManager.getInstance().getPluginLocation("test").getParentFile().getName());
@@ -64,7 +64,7 @@
      */
     public void testExtensionPoint() throws Exception
     {
-        CocoonWrapper cocoon = _startApplication("test/environments/runtimes/runtime11.xml", "test/environments/configs/config1.xml", "test/environments/webapp1");
+        CocoonWrapper cocoon = _startApplication("test/environments/runtimes/runtime11.xml", "test/environments/configs/config1.xml", null, null, "test/environments/webapp1");
         
         assertTrue(PluginsManager.getInstance().getPluginNames().contains("test"));
 
@@ -99,7 +99,7 @@
      */
     public void testFeatures() throws Exception
     {
-        CocoonWrapper cocoon = _startApplication("test/environments/runtimes/runtime12.xml", "test/environments/configs/config1.xml", "test/environments/webapp1");
+        CocoonWrapper cocoon = _startApplication("test/environments/runtimes/runtime12.xml", "test/environments/configs/config1.xml", null, null, "test/environments/webapp1");
         
         Map<String, Feature> activeFeatures = PluginsManager.getInstance().getFeatures();
         Map<String, InactivityCause> inactiveFeatures = PluginsManager.getInstance().getInactiveFeatures();
Index: test/src/org/ametys/runtime/test/rights/basic/BasicRightsManagerTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/rights/basic/BasicRightsManagerTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/rights/basic/BasicRightsManagerTestCase.java	(working copy)
@@ -33,9 +33,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        
-        _startApplication("test/environments/runtimes/runtime12.xml", "test/environments/configs/config1.xml", "test/environments/webapp1");
+        _startApplication("test/environments/runtimes/runtime12.xml", "test/environments/configs/config1.xml", null, null, "test/environments/webapp1");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/rights/profile/AbstractProfileBasedRightsManagerTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/rights/profile/AbstractProfileBasedRightsManagerTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/rights/profile/AbstractProfileBasedRightsManagerTestCase.java	(working copy)
@@ -52,11 +52,14 @@
      * Reset the db
      * @param runtimeFilename The file name in runtimes env dir
      * @param configFileName The file name in config env dir
+     * @param sqlDataSourceFileName The file name in config env dir
      * @throws Exception if an error occurs
      */
-    protected void _resetDB(String runtimeFilename, String configFileName) throws Exception
+    protected void _resetDB(String runtimeFilename, String configFileName, String sqlDataSourceFileName) throws Exception
     {
-        _startApplication("test/environments/runtimes/" + runtimeFilename, "test/environments/configs/" + configFileName, "test/environments/webapp1");
+        super.setUp();
+        
+        _startApplication("test/environments/runtimes/" + runtimeFilename, "test/environments/configs/" + configFileName, "test/environments/configs/" + sqlDataSourceFileName, null, "test/environments/webapp1");
 
         _setDatabase(Arrays.asList(getScripts()));
 
Index: test/src/org/ametys/runtime/test/rights/profile/DerbyProfileBasedRightsManagerTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/rights/profile/DerbyProfileBasedRightsManagerTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/rights/profile/DerbyProfileBasedRightsManagerTestCase.java	(working copy)
@@ -26,9 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        
-        _resetDB("runtime4.xml", "config_derby.xml");
+        _resetDB("runtime4.xml", "config1.xml", "datasource-derby.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/rights/profile/HsqlProfileBasedRightsManagerTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/rights/profile/HsqlProfileBasedRightsManagerTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/rights/profile/HsqlProfileBasedRightsManagerTestCase.java	(working copy)
@@ -26,9 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        
-        _resetDB("runtime4.xml", "config_hsqldb.xml");
+        _resetDB("runtime4.xml", "config1.xml", "datasource-hsql.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/rights/profile/MysqlProfileBasedRightsManagerTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/rights/profile/MysqlProfileBasedRightsManagerTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/rights/profile/MysqlProfileBasedRightsManagerTestCase.java	(working copy)
@@ -26,9 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        
-        _resetDB("runtime4.xml", "config1.xml");
+        _resetDB("runtime4.xml", "config1.xml", "datasource-mysql.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/rights/profile/OracleProfileBasedRightsManagerTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/rights/profile/OracleProfileBasedRightsManagerTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/rights/profile/OracleProfileBasedRightsManagerTestCase.java	(working copy)
@@ -26,9 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        
-        _resetDB("runtime4.xml", "config_oracle.xml");
+        _resetDB("runtime4.xml", "config1.xml", "datasource-oracle.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/rights/profile/PostgresProfileBasedRightsManagerTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/rights/profile/PostgresProfileBasedRightsManagerTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/rights/profile/PostgresProfileBasedRightsManagerTestCase.java	(working copy)
@@ -26,9 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        
-        _resetDB("runtime4.xml", "config_postgres.xml");
+        _resetDB("runtime4.xml", "config1.xml", "datasource-postgresql.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/rights/profile/hierarchical/AbstractHierarchicalProfileBasedRightsManagerTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/rights/profile/hierarchical/AbstractHierarchicalProfileBasedRightsManagerTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/rights/profile/hierarchical/AbstractHierarchicalProfileBasedRightsManagerTestCase.java	(working copy)
@@ -53,11 +53,14 @@
      * Reset the db
      * @param runtimeFilename The file name in runtimes env dir
      * @param configFileName The file name in config env dir
+     * @param sqlDataSourceFileName The file name in config env dir
      * @throws Exception if an error occurs
      */
-    protected void _resetDB(String runtimeFilename, String configFileName) throws Exception
+    protected void _resetDB(String runtimeFilename, String configFileName, String sqlDataSourceFileName) throws Exception
     {
-        _startApplication("test/environments/runtimes/" + runtimeFilename, "test/environments/configs/" + configFileName, "test/environments/webapp1");
+        super.setUp();
+        
+        _startApplication("test/environments/runtimes/" + runtimeFilename, "test/environments/configs/" + configFileName, "test/environments/configs/" + sqlDataSourceFileName, null, "test/environments/webapp1");
 
         _setDatabase(Arrays.asList(getScripts()));
 
Index: test/src/org/ametys/runtime/test/rights/profile/hierarchical/DerbyHierarchicalProfileBasedRightsManagerTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/rights/profile/hierarchical/DerbyHierarchicalProfileBasedRightsManagerTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/rights/profile/hierarchical/DerbyHierarchicalProfileBasedRightsManagerTestCase.java	(working copy)
@@ -26,9 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        
-        _resetDB("runtime5.xml", "config_derby.xml");
+        _resetDB("runtime5.xml", "config1.xml", "datasource-derby.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/rights/profile/hierarchical/HsqlHierarchicalProfileBasedRightsManagerTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/rights/profile/hierarchical/HsqlHierarchicalProfileBasedRightsManagerTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/rights/profile/hierarchical/HsqlHierarchicalProfileBasedRightsManagerTestCase.java	(working copy)
@@ -26,9 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        
-        _resetDB("runtime5.xml", "config_hsqldb.xml");
+        _resetDB("runtime5.xml", "config1.xml", "datasource-hsql.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/rights/profile/hierarchical/MysqlHierarchicalProfileBasedRightsManagerTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/rights/profile/hierarchical/MysqlHierarchicalProfileBasedRightsManagerTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/rights/profile/hierarchical/MysqlHierarchicalProfileBasedRightsManagerTestCase.java	(working copy)
@@ -26,9 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        
-        _resetDB("runtime5.xml", "config1.xml");
+        _resetDB("runtime5.xml", "config1.xml", "datasource-mysql.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/rights/profile/hierarchical/OracleHierarchicalProfileBasedRightsManagerTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/rights/profile/hierarchical/OracleHierarchicalProfileBasedRightsManagerTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/rights/profile/hierarchical/OracleHierarchicalProfileBasedRightsManagerTestCase.java	(working copy)
@@ -26,9 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        
-        _resetDB("runtime5.xml", "config_oracle.xml");
+        _resetDB("runtime5.xml", "config1.xml", "datasource-oracle.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/rights/profile/hierarchical/PostgresHierarchicalProfileBasedRightsManagerTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/rights/profile/hierarchical/PostgresHierarchicalProfileBasedRightsManagerTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/rights/profile/hierarchical/PostgresHierarchicalProfileBasedRightsManagerTestCase.java	(working copy)
@@ -26,9 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        
-        _resetDB("runtime5.xml", "config_postgres.xml");
+        _resetDB("runtime5.xml", "config1.xml", "datasource-postgresql.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/ui/DesktopManagerTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/ui/DesktopManagerTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/ui/DesktopManagerTestCase.java	(working copy)
@@ -40,9 +40,8 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        
-        _startApplication("test/environments/runtimes/runtime01.xml", "test/environments/configs/config1.xml", "test/environments/webapp2");
+        _startApplication("test/environments/runtimes/runtime01.xml", "test/environments/configs/config1.xml", null, null, "test/environments/webapp2");
+
         
         _desktopManager = (DesktopManager) Init.getPluginServiceManager().lookup("DesktopManagerTest");
         _jsonUtils = (JSONUtils) Init.getPluginServiceManager().lookup(JSONUtils.ROLE);
Index: test/src/org/ametys/runtime/test/ui/StaticUIItemFactoryTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/ui/StaticUIItemFactoryTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/ui/StaticUIItemFactoryTestCase.java	(working copy)
@@ -33,10 +33,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        
-        _startApplication("test/environments/runtimes/runtime01.xml", "test/environments/configs/config1.xml", "test/environments/webapp2");
-        
+        _startApplication("test/environments/runtimes/runtime01.xml", "test/environments/configs/config1.xml", null, null, "test/environments/webapp2");
         _desktopManager = (DesktopManager) Init.getPluginServiceManager().lookup("DesktopManagerTest");
     }
     
Index: test/src/org/ametys/runtime/test/userpref/AbstractUserPreferencesTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/userpref/AbstractUserPreferencesTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/userpref/AbstractUserPreferencesTestCase.java	(working copy)
@@ -55,11 +55,12 @@
      * Reset the db
      * @param runtimeFilename The file name in runtimes env dir
      * @param configFileName The file name in config env dir
+     * @param sqlDataSourceFileName the configuration file name for data sources
      * @throws Exception if an error occurs
      */
-    protected void _resetDB(String runtimeFilename, String configFileName) throws Exception
+    protected void _resetDB(String runtimeFilename, String configFileName, String sqlDataSourceFileName) throws Exception
     {
-        _startApplication("test/environments/runtimes/" + runtimeFilename, "test/environments/configs/" + configFileName, "test/environments/webapp1");
+        _startApplication("test/environments/runtimes/" + runtimeFilename, "test/environments/configs/" + configFileName, "test/environments/configs/" + sqlDataSourceFileName, null, "test/environments/webapp1");
         
         _setDatabase(Arrays.asList(getScripts()));
 
Index: test/src/org/ametys/runtime/test/userpref/DerbyUserPreferencesTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/userpref/DerbyUserPreferencesTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/userpref/DerbyUserPreferencesTestCase.java	(working copy)
@@ -27,7 +27,7 @@
     protected void setUp() throws Exception
     {
         super.setUp();
-        _resetDB("runtime4.xml", "config_derby.xml");
+        _resetDB("runtime4.xml", "config1.xml", "datasource-derby.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/userpref/MysqlUserPreferencesTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/userpref/MysqlUserPreferencesTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/userpref/MysqlUserPreferencesTestCase.java	(working copy)
@@ -27,7 +27,7 @@
     protected void setUp() throws Exception
     {
         super.setUp();
-        _resetDB("runtime4.xml", "config1.xml");
+        _resetDB("runtime4.xml", "config1.xml", "datasource-mysql.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/userpref/OracleUserPreferencesTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/userpref/OracleUserPreferencesTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/userpref/OracleUserPreferencesTestCase.java	(working copy)
@@ -27,7 +27,7 @@
     protected void setUp() throws Exception
     {
         super.setUp();
-        _resetDB("runtime4.xml", "config_oracle.xml");
+        _resetDB("runtime4.xml", "config1.xml", "datasource-oracle.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/userpref/PostgresUserPreferencesTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/userpref/PostgresUserPreferencesTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/userpref/PostgresUserPreferencesTestCase.java	(working copy)
@@ -27,7 +27,7 @@
     protected void setUp() throws Exception
     {
         super.setUp();
-        _resetDB("runtime4.xml", "config_postgres.xml");
+        _resetDB("runtime4.xml", "config1.xml", "datasource-postgresql.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/users/jdbc/AbstractJDBCUsersManagerTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/users/jdbc/AbstractJDBCUsersManagerTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/users/jdbc/AbstractJDBCUsersManagerTestCase.java	(working copy)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2009 Anyware Services
+ *  Copyright 2009 Anyware Services_configureRuntime
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -34,11 +34,12 @@
      * Reset the db
      * @param runtimeFilename The file name in runtimes env dir
      * @param configFileName The file name in config env dir
+     * @param sqlDataSourceFileName the path of the data sources configuration file
      * @throws Exception if an error occurs
      */
-    protected void _resetDB(String runtimeFilename, String configFileName) throws Exception
+    protected void _resetDB(String runtimeFilename, String configFileName, String sqlDataSourceFileName) throws Exception
     {
-        _startApplication("test/environments/runtimes/" + runtimeFilename, "test/environments/configs/" + configFileName, "test/environments/webapp1");
+        _startApplication("test/environments/runtimes/" + runtimeFilename, "test/environments/configs/" + configFileName, "test/environments/configs/" + sqlDataSourceFileName, null, "test/environments/webapp1");
 
         _setDatabase(Arrays.asList(getScripts()));
         
Index: test/src/org/ametys/runtime/test/users/jdbc/DerbyJdbcUsersTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/users/jdbc/DerbyJdbcUsersTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/users/jdbc/DerbyJdbcUsersTestCase.java	(working copy)
@@ -26,8 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        _resetDB("runtime4.xml", "config_derby.xml");
+        _resetDB("runtime4.xml", "config1.xml", "datasource-derby.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/users/jdbc/HsqlJdbcUsersTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/users/jdbc/HsqlJdbcUsersTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/users/jdbc/HsqlJdbcUsersTestCase.java	(working copy)
@@ -26,8 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        _resetDB("runtime4.xml", "config_hsqldb.xml");
+        _resetDB("runtime4.xml", "config1.xml", "datasource-hsql.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/users/jdbc/MysqlJdbcUsersTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/users/jdbc/MysqlJdbcUsersTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/users/jdbc/MysqlJdbcUsersTestCase.java	(working copy)
@@ -22,12 +22,10 @@
  */
 public class MysqlJdbcUsersTestCase extends AbstractJdbcUnmodifiableUsersTestCase
 {
-
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        _resetDB("runtime4.xml", "config1.xml");
+        _resetDB("runtime4.xml", "config1.xml", "datasource-mysql.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/users/jdbc/OracleJdbcUsersTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/users/jdbc/OracleJdbcUsersTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/users/jdbc/OracleJdbcUsersTestCase.java	(working copy)
@@ -26,8 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        _resetDB("runtime4.xml", "config_oracle.xml");
+        _resetDB("runtime4.xml", "config1.xml", "datasource-oracle.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/users/jdbc/PostgresJdbcUsersTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/users/jdbc/PostgresJdbcUsersTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/users/jdbc/PostgresJdbcUsersTestCase.java	(working copy)
@@ -26,8 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        _resetDB("runtime4.xml", "config_postgres.xml");
+        _resetDB("runtime4.xml", "config1.xml", "datasource-postgresql.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/users/jdbc/credentialsaware/AbstractCredentialsAwareJdbcUsersTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/users/jdbc/credentialsaware/AbstractCredentialsAwareJdbcUsersTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/users/jdbc/credentialsaware/AbstractCredentialsAwareJdbcUsersTestCase.java	(working copy)
@@ -26,6 +26,7 @@
 import org.ametys.core.user.CredentialsAwareUsersManager;
 import org.ametys.core.user.ModifiableUsersManager;
 import org.ametys.plugins.core.impl.user.jdbc.CredentialsAwareJdbcUsersManager;
+import org.ametys.runtime.config.Config;
 import org.ametys.runtime.test.users.jdbc.AbstractJDBCUsersManagerTestCase;
 
 /**
@@ -104,13 +105,12 @@
      */
     protected void _checkSHA2Password() throws Exception
     {
-        Connection connection = null;
         PreparedStatement stmt = null;
         ResultSet rs = null;
         
-        try
+        String dataSourceId = Config.getInstance().getValueAsString(ConnectionHelper.CORE_POOL_CONFIG_PARAM);
+        try (Connection connection = ConnectionHelper.getConnection(dataSourceId);)
         {
-            connection = ConnectionHelper.getConnection(ConnectionHelper.CORE_POOL_NAME);
             
             String sql = "SELECT password, salt FROM Users WHERE login = ?";
             
@@ -128,10 +128,6 @@
                 assertTrue (storedPassword.length() == 128);
             }
         }
-        finally
-        {
-            ConnectionHelper.cleanup(connection);
-        }
     }
     
 }
Index: test/src/org/ametys/runtime/test/users/jdbc/credentialsaware/DerbyCredentialsAwareJdbcUsersTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/users/jdbc/credentialsaware/DerbyCredentialsAwareJdbcUsersTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/users/jdbc/credentialsaware/DerbyCredentialsAwareJdbcUsersTestCase.java	(working copy)
@@ -26,8 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        _resetDB("runtime7.xml", "config_derby.xml");
+        _resetDB("runtime7.xml", "config1.xml", "datasource-derby.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/users/jdbc/credentialsaware/HsqlCredentialsAwareJdbcUsersTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/users/jdbc/credentialsaware/HsqlCredentialsAwareJdbcUsersTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/users/jdbc/credentialsaware/HsqlCredentialsAwareJdbcUsersTestCase.java	(working copy)
@@ -26,8 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        _resetDB("runtime7.xml", "config_hsqldb.xml");
+        _resetDB("runtime7.xml", "config1.xml", "datasource-hsql.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/users/jdbc/credentialsaware/MysqlCredentialsAwareJdbcUsersTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/users/jdbc/credentialsaware/MysqlCredentialsAwareJdbcUsersTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/users/jdbc/credentialsaware/MysqlCredentialsAwareJdbcUsersTestCase.java	(working copy)
@@ -26,8 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        _resetDB("runtime7.xml", "config1.xml");
+        _resetDB("runtime7.xml", "config1.xml", "datasource-mysql.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/users/jdbc/credentialsaware/OracleCredentialsAwareJdbcUsersTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/users/jdbc/credentialsaware/OracleCredentialsAwareJdbcUsersTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/users/jdbc/credentialsaware/OracleCredentialsAwareJdbcUsersTestCase.java	(working copy)
@@ -26,8 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        _resetDB("runtime7.xml", "config_oracle.xml");
+        _resetDB("runtime7.xml", "config1.xml", "datasource-oracle.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/users/jdbc/credentialsaware/PostgresCredentialsAwareJdbcUsersTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/users/jdbc/credentialsaware/PostgresCredentialsAwareJdbcUsersTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/users/jdbc/credentialsaware/PostgresCredentialsAwareJdbcUsersTestCase.java	(working copy)
@@ -17,6 +17,8 @@
 
 import java.io.File;
 
+import org.ametys.core.datasource.sql.SQLDataSourceManager;
+
 /**
  * PostgreSQL-specific credentials aware JDBC UsersManager test case.
  */
@@ -26,8 +28,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        _resetDB("runtime7.xml", "config_postgres.xml");
+        _resetDB("runtime7.xml", "config1.xml", "datasource-postgresql.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/users/jdbc/modifiable/DerbyModifiableJdbcUsersTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/users/jdbc/modifiable/DerbyModifiableJdbcUsersTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/users/jdbc/modifiable/DerbyModifiableJdbcUsersTestCase.java	(working copy)
@@ -26,8 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        _resetDB("runtime5.xml", "config_derby.xml");
+        _resetDB("runtime5.xml", "config1.xml", "datasource-derby.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/users/jdbc/modifiable/HsqlModifiableJdbcUsersTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/users/jdbc/modifiable/HsqlModifiableJdbcUsersTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/users/jdbc/modifiable/HsqlModifiableJdbcUsersTestCase.java	(working copy)
@@ -26,8 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        _resetDB("runtime5.xml", "config_hsqldb.xml");
+        _resetDB("runtime5.xml", "config1.xml", "datasource-hsql.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/users/jdbc/modifiable/MysqlModifiableJdbcUsersTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/users/jdbc/modifiable/MysqlModifiableJdbcUsersTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/users/jdbc/modifiable/MysqlModifiableJdbcUsersTestCase.java	(working copy)
@@ -26,8 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        _resetDB("runtime5.xml", "config1.xml");
+        _resetDB("runtime5.xml", "config1.xml", "datasource-mysql.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/users/jdbc/modifiable/OracleModifiableJdbcUsersTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/users/jdbc/modifiable/OracleModifiableJdbcUsersTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/users/jdbc/modifiable/OracleModifiableJdbcUsersTestCase.java	(working copy)
@@ -26,8 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        _resetDB("runtime5.xml", "config_oracle.xml");
+        _resetDB("runtime5.xml", "config1.xml", "datasource-oracle.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/users/jdbc/modifiable/PostgresModifiableJdbcUsersTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/users/jdbc/modifiable/PostgresModifiableJdbcUsersTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/users/jdbc/modifiable/PostgresModifiableJdbcUsersTestCase.java	(working copy)
@@ -26,8 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        _resetDB("runtime5.xml", "config_postgres.xml");
+        _resetDB("runtime5.xml", "config1.xml", "datasource-postgresql.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/users/jdbc/modifiablecredentialsaware/DerbyModifiableCredentialsAwareJdbcUsersTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/users/jdbc/modifiablecredentialsaware/DerbyModifiableCredentialsAwareJdbcUsersTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/users/jdbc/modifiablecredentialsaware/DerbyModifiableCredentialsAwareJdbcUsersTestCase.java	(working copy)
@@ -26,8 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        _resetDB("runtime6.xml", "config_derby.xml");
+        _resetDB("runtime6.xml", "config1.xml", "datasource-derby.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/users/jdbc/modifiablecredentialsaware/HsqlModifiableCredentialsAwareJdbcUsersTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/users/jdbc/modifiablecredentialsaware/HsqlModifiableCredentialsAwareJdbcUsersTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/users/jdbc/modifiablecredentialsaware/HsqlModifiableCredentialsAwareJdbcUsersTestCase.java	(working copy)
@@ -26,8 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        _resetDB("runtime6.xml", "config_hsqldb.xml");
+        _resetDB("runtime6.xml", "config1.xml", "datasource-hsql.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/users/jdbc/modifiablecredentialsaware/MysqlModifiableCredentialsAwareJdbcUsersTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/users/jdbc/modifiablecredentialsaware/MysqlModifiableCredentialsAwareJdbcUsersTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/users/jdbc/modifiablecredentialsaware/MysqlModifiableCredentialsAwareJdbcUsersTestCase.java	(working copy)
@@ -26,8 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        _resetDB("runtime6.xml", "config1.xml");
+        _resetDB("runtime6.xml", "config1.xml", "datasource-mysql.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/users/jdbc/modifiablecredentialsaware/OracleModifiableCredentialsAwareJdbcUsersTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/users/jdbc/modifiablecredentialsaware/OracleModifiableCredentialsAwareJdbcUsersTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/users/jdbc/modifiablecredentialsaware/OracleModifiableCredentialsAwareJdbcUsersTestCase.java	(working copy)
@@ -26,8 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        _resetDB("runtime6.xml", "config_oracle.xml");
+        _resetDB("runtime6.xml", "config1.xml", "datasource-oracle.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/users/jdbc/modifiablecredentialsaware/PostgresModifiableCredentialsAwareJdbcUsersTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/users/jdbc/modifiablecredentialsaware/PostgresModifiableCredentialsAwareJdbcUsersTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/users/jdbc/modifiablecredentialsaware/PostgresModifiableCredentialsAwareJdbcUsersTestCase.java	(working copy)
@@ -26,8 +26,7 @@
     @Override
     protected void setUp() throws Exception
     {
-        super.setUp();
-        _resetDB("runtime6.xml", "config_postgres.xml");
+        _resetDB("runtime6.xml", "config1.xml", "datasource-postgresql.xml");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/users/ldap/CredentialAwareLdapUsersTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/users/ldap/CredentialAwareLdapUsersTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/users/ldap/CredentialAwareLdapUsersTestCase.java	(working copy)
@@ -30,7 +30,7 @@
     @Override
     protected void _startApp() throws Exception
     {
-        _startApplication("test/environments/runtimes/runtime9.xml", "test/environments/configs/config4.xml", "test/environments/webapp1");
+        _startApplication("test/environments/runtimes/runtime9.xml", "test/environments/configs/config4.xml", null, "test/environments/configs/datasource-ldap.xml", "test/environments/webapp1");
         
         _usersManager = (UsersManager) Init.getPluginServiceManager().lookup(UsersManager.ROLE);
     }
Index: test/src/org/ametys/runtime/test/users/ldap/LdapUsersTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/users/ldap/LdapUsersTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/users/ldap/LdapUsersTestCase.java	(working copy)
@@ -57,8 +57,7 @@
      */
     protected void _startApp() throws Exception
     {
-        _startApplication("test/environments/runtimes/runtime8.xml", "test/environments/configs/config3.xml", "test/environments/webapp1");
-        
+        _startApplication("test/environments/runtimes/runtime8.xml", "test/environments/configs/config3.xml", null, "test/environments/configs/datasource-ldap.xml", "test/environments/webapp1");
         _usersManager = (UsersManager) Init.getPluginServiceManager().lookup(UsersManager.ROLE);
     }
     
Index: test/src/org/ametys/runtime/test/users/others/StaticUsersTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/users/others/StaticUsersTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/users/others/StaticUsersTestCase.java	(working copy)
@@ -41,7 +41,7 @@
     {
         super.setUp();
         
-        _startApplication("test/environments/runtimes/runtime01.xml", "test/environments/configs/config1.xml", "test/environments/webapp1");
+        _startApplication("test/environments/runtimes/runtime01.xml", "test/environments/configs/config1.xml", null, null, "test/environments/webapp1");
     }
     
     @Override
Index: test/src/org/ametys/runtime/test/util/I18nTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/util/I18nTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/util/I18nTestCase.java	(working copy)
@@ -38,10 +38,9 @@
     @Override
     protected void setUp() throws Exception
     {
+        _startApplication("test/environments/runtimes/runtime01.xml", "test/environments/configs/config1.xml", null, null, "test/environments/webapp2");
         super.setUp();
         
-        _startApplication("test/environments/runtimes/runtime01.xml", "test/environments/configs/config1.xml", "test/environments/webapp2");
-        
         ServiceManager manager = Init.getPluginServiceManager();
         _i18nUtils = (I18nUtils) manager.lookup(I18nUtils.ROLE);
     }
Index: test/src/org/ametys/runtime/test/util/JSONTestCase.java
===================================================================
--- test/src/org/ametys/runtime/test/util/JSONTestCase.java	(revision 38980)
+++ test/src/org/ametys/runtime/test/util/JSONTestCase.java	(working copy)
@@ -40,10 +40,9 @@
     @Override
     protected void setUp() throws Exception
     {
+        _startApplication("test/environments/runtimes/runtime01.xml", "test/environments/configs/config1.xml", null, null, "test/environments/webapp2");
         super.setUp();
         
-        _startApplication("test/environments/runtimes/runtime01.xml", "test/environments/configs/config1.xml", "test/environments/webapp2");
-        
         ServiceManager manager = Init.getPluginServiceManager();
         _jsonUtils = (JSONUtils) manager.lookup(JSONUtils.ROLE);
         _desktopManager = (DesktopManager) manager.lookup("DesktopManagerTest");
Index: test-env/src/org/ametys/runtime/test/AbstractRuntimeTestCase.java
===================================================================
--- test-env/src/org/ametys/runtime/test/AbstractRuntimeTestCase.java	(revision 38980)
+++ test-env/src/org/ametys/runtime/test/AbstractRuntimeTestCase.java	(working copy)
@@ -25,19 +25,21 @@
 import javax.xml.validation.Schema;
 import javax.xml.validation.SchemaFactory;
 
-import junit.framework.TestCase;
-
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.xml.sax.XMLReader;
 
+import org.ametys.core.datasource.ldap.LDAPDataSourceManager;
+import org.ametys.core.datasource.sql.SQLDataSourceManager;
 import org.ametys.runtime.config.Config;
 import org.ametys.runtime.data.AmetysHomeLock;
 import org.ametys.runtime.data.AmetysHomeLockException;
 import org.ametys.runtime.servlet.RuntimeConfig;
 
+import junit.framework.TestCase;
+
 /**
  * Abstract test case for all Runtime test cases.
  */
@@ -45,6 +47,12 @@
 {
     /** Ametys home directory path relative to the context path of the test environment. **/
     public static final String AMETYS_HOME_DIR = "/WEB-INF/data";
+
+    /** Default SQL datasource file */
+    private static String __DEFAULT_SQL_DATASOURCE_FILE = "test/environments/configs/datasource-sql.xml";
+    
+    /** Default LDAP datasource file */
+    private static String __DEFAULT_LDAP_DATASOURCE_FILE = "test/environments/configs/datasource-ldap.xml"; 
     
     /** The cocoon wrapper. */
     protected CocoonWrapper _cocoon;
@@ -189,14 +197,21 @@
      * Starts the application. This a shorthand to _configureRuntime, then _startCocoon.
      * @param runtimeFile the name of the runtime file used
      * @param configFile the name of the config file
+     * @param sqlDataSourceFile the path of the sql data sources configuration file, can be null to use the default file
+     * @param ldapDataSourceFile the path of the ldap data sources configuration file, can be null to use the default file
      * @param contextPath the environment application
      * @return the CocoonWrapper used to process URIs
-     * @throws Exception if an error occured
+     * @throws Exception if an error occurred
      */
-    protected CocoonWrapper _startApplication(String runtimeFile, String configFile, String contextPath) throws Exception
+    protected CocoonWrapper _startApplication(String runtimeFile, String configFile, String sqlDataSourceFile, String ldapDataSourceFile, String contextPath) throws Exception
     {
         _configureRuntime(runtimeFile, contextPath);
+        
         Config.setFilename(configFile);
+        
+        SQLDataSourceManager.setFilename(sqlDataSourceFile != null  ? sqlDataSourceFile : __DEFAULT_SQL_DATASOURCE_FILE);
+        LDAPDataSourceManager.setFilename(ldapDataSourceFile != null ? ldapDataSourceFile : __DEFAULT_LDAP_DATASOURCE_FILE);
+        
         return _startCocoon(contextPath);
     }
 }
Index: test-env/src/org/ametys/runtime/test/ScriptRunner.java
===================================================================
--- test-env/src/org/ametys/runtime/test/ScriptRunner.java	(revision 38980)
+++ test-env/src/org/ametys/runtime/test/ScriptRunner.java	(working copy)
@@ -28,6 +28,7 @@
 import org.slf4j.LoggerFactory;
 
 import org.ametys.core.datasource.ConnectionHelper;
+import org.ametys.runtime.config.Config;
 
 /**
  * Tool to run SQL scripts.<p>
@@ -75,17 +76,11 @@
      */
     public static void runScript(InputStream is) throws IOException, SQLException
     {
-        Connection connection = null;
-        
-        try
+        String dataSourceId = Config.getInstance().getValueAsString(ConnectionHelper.CORE_POOL_CONFIG_PARAM);
+        try (Connection connection = ConnectionHelper.getConnection(dataSourceId);)
         {
-            connection = ConnectionHelper.getConnection(ConnectionHelper.CORE_POOL_NAME);
             runScript(connection, is);
         }
-        finally
-        {
-            ConnectionHelper.cleanup(connection);
-        }
     }
 
     /**
