Merge branch 'master' of https://gitbox.apache.org/repos/asf/directory-studio
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
new file mode 100644
index 0000000..648ddcd
--- /dev/null
+++ b/.github/workflows/codeql-analysis.yml
@@ -0,0 +1,71 @@
+# For most projects, this workflow file will not need changing; you simply need
+# to commit it to your repository.
+#
+# You may wish to alter this file to override the set of languages analyzed,
+# or to provide custom queries or build logic.
+#
+# ******** NOTE ********
+# We have attempted to detect the languages in your repository. Please check
+# the `language` matrix defined below to confirm you have the correct set of
+# supported CodeQL languages.
+#
+name: "CodeQL"
+
+on:
+  push:
+    branches: [ master ]
+  pull_request:
+    # The branches below must be a subset of the branches above
+    branches: [ master ]
+  schedule:
+    - cron: '42 18 * * 3'
+
+jobs:
+  analyze:
+    name: Analyze
+    runs-on: ubuntu-latest
+    permissions:
+      actions: read
+      contents: read
+      security-events: write
+
+    strategy:
+      fail-fast: false
+      matrix:
+        language: [ 'java' ]
+        # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
+        # Learn more:
+        # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
+
+    steps:
+    - name: Checkout repository
+      uses: actions/checkout@v2
+
+    # Initializes the CodeQL tools for scanning.
+    - name: Initialize CodeQL
+      uses: github/codeql-action/init@v1
+      with:
+        languages: ${{ matrix.language }}
+        # If you wish to specify custom queries, you can do so here or in a config file.
+        # By default, queries listed here will override any specified in a config file.
+        # Prefix the list here with "+" to use these queries and those in the config file.
+        # queries: ./path/to/local/query, your-org/your-repo/queries@main
+
+    # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).
+    # If this step fails, then you should remove it and run the build manually (see below)
+    #- name: Autobuild
+    #  uses: github/codeql-action/autobuild@v1
+
+    # ℹī¸ Command-line programs to run using the OS shell.
+    # 📚 https://git.io/JvXDl
+
+    # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines
+    #    and modify them (or add more) to build your code if your project
+    #    uses a compiled language
+
+    - run: |
+        mvn -f pom-first.xml clean install
+        mvn clean install
+
+    - name: Perform CodeQL Analysis
+      uses: github/codeql-action/analyze@v1
diff --git a/Jenkinsfile b/Jenkinsfile
index c6052fb..40dd12a 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -33,14 +33,12 @@
         retry(2)
       }
       agent {
-        docker {
-          label 'ubuntu && !H28 && !H36 && !H40'
-          image 'apachedirectory/maven-build:jdk-8'
-          //args '-v $HOME/.m2:/home/hnelson/.m2'
-        }
+        label 'ubuntu'
       }
       steps {
-        sh 'export DISPLAY=:99; env; ps aux'
+        script {
+          inTestLab('jdk-11', { sh 'export DISPLAY=:99; env; ps aux' })
+        }
       }
       post {
         always {
@@ -50,20 +48,18 @@
     }
     stage ('Build and Test') {
       parallel {
-        stage ('Linux Java 8') {
+        stage ('Linux Java 11') {
           options {
             timeout(time: 4, unit: 'HOURS')
             retry(2)
           }
           agent {
-            docker {
-              label 'ubuntu && !H28 && !H36 && !H40'
-              image 'apachedirectory/maven-build:jdk-8'
-              //args '-v $HOME/.m2:/home/hnelson/.m2'
-            }
+            label 'ubuntu'
           }
           steps {
-            sh 'export DISPLAY=:99; mvn -V -U -f pom-first.xml clean install && mvn -V clean install -Dorg.eclipse.swtbot.search.timeout=20000 -Denable-ui-tests'
+            script {
+              inTestLab('jdk-11', { sh 'export DISPLAY=:99; mvn -V -U -f pom-first.xml clean install && mvn -V clean install -Dorg.eclipse.swtbot.search.timeout=20000 -Denable-ui-tests' })
+            }
           }
           post {
             always {
@@ -73,20 +69,18 @@
             }
           }
         }
-        stage ('Linux Java 11') {
+        stage ('Linux Java 17') {
           options {
             timeout(time: 4, unit: 'HOURS')
             retry(2)
           }
           agent {
-            docker {
-              label 'ubuntu && !H28 && !H36 && !H40'
-              image 'apachedirectory/maven-build:jdk-11'
-              //args '-v $HOME/.m2:/home/hnelson/.m2'
-            }
+            label 'ubuntu'
           }
           steps {
-            sh 'export DISPLAY=:99; mvn -V -U -f pom-first.xml clean install && mvn -V clean install -Dorg.eclipse.swtbot.search.timeout=20000 -Denable-ui-tests'
+            script {
+              inTestLab('jdk-17', { sh 'export DISPLAY=:99; mvn -V -U -f pom-first.xml clean install && mvn -V clean install -Dorg.eclipse.swtbot.search.timeout=20000 -Denable-ui-tests' })
+            }
           }
           post {
             always {
@@ -96,30 +90,7 @@
             }
           }
         }
-        stage ('Linux Java 14') {
-          options {
-            timeout(time: 4, unit: 'HOURS')
-            retry(2)
-          }
-          agent {
-            docker {
-              label 'ubuntu && !H28 && !H36 && !H40'
-              image 'apachedirectory/maven-build:jdk-14'
-              //args '-v $HOME/.m2:/home/hnelson/.m2'
-            }
-          }
-          steps {
-            sh 'export DISPLAY=:99; mvn -V -U -f pom-first.xml clean install && mvn -V clean install -Dorg.eclipse.swtbot.search.timeout=20000 -Denable-ui-tests'
-          }
-          post {
-            always {
-              junit '**/target/surefire-reports/*.xml'
-              archiveArtifacts artifacts:'tests/test.integration.ui/screenshots/*', allowEmptyArchive:true
-              deleteDir()
-            }
-          }
-        }
-        stage ('Windows Java 8') {
+        stage ('Windows Java 11') {
           options {
             timeout(time: 4, unit: 'HOURS')
             retry(2)
@@ -129,7 +100,8 @@
           }
           steps {
             bat '''
-            set JAVA_HOME=F:\\jenkins\\tools\\java\\latest1.8
+            rmdir /S /Q F:\\hudson\\m2_repository\\p2\\osgi\\bundle\\org.apache.directory.api.ldap.model
+            set JAVA_HOME=F:\\jenkins\\tools\\java\\latest11
             set MAVEN_OPTS="-Xmx512m"
             call F:\\jenkins\\tools\\maven\\latest3\\bin\\mvn -V -U -f pom-first.xml clean install
             call F:\\jenkins\\tools\\maven\\latest3\\bin\\mvn -V clean install -Dorg.eclipse.swtbot.search.timeout=20000 -Denable-ui-tests
@@ -160,3 +132,14 @@
   }
 }
 
+def inTestLab(String dockerImageTag, Closure action){
+  docker.image('coheigea/kerby').withRun('-h kerby.example.com -v $(pwd)/tools/testlab/kerby-data:/kerby-data') { kerby ->
+    docker.image('osixia/openldap:1.5.0').withRun('-h openldap.example.com -v $(pwd)/tools/testlab/ldap.keytab:/etc/krb5.keytab -v $(pwd)/tools/testlab/krb5.conf:/etc/krb5.conf -e LDAP_TLS_VERIFY_CLIENT=never') { openldap ->
+      docker.image('389ds/dirsrv').withRun('-h fedora389ds.example.com -v $(pwd)/tools/testlab/ldap.keytab:/etc/krb5.keytab -v $(pwd)/tools/testlab/krb5.conf:/etc/krb5.conf -e DS_DM_PASSWORD=admin', 'bash -c "zypper install -y cyrus-sasl-crammd5 cyrus-sasl-digestmd5 cyrus-sasl-gssapi; set -m; /usr/lib/dirsrv/dscontainer -r & while ! /usr/lib/dirsrv/dscontainer -H; do sleep 5; done; sleep 5; /usr/sbin/dsconf localhost backend create --suffix dc=example,dc=org --be-name example; fg"') { fedora389ds ->
+        docker.image("apachedirectory/maven-build:${dockerImageTag}").inside("-v ${env.WORKSPACE}/tools/testlab/krb5.conf:/etc/krb5.conf --link=${kerby.id}:kerby.example.com --link=${openldap.id}:openldap.example.com -e OPENLDAP_HOST=openldap.example.com -e OPENLDAP_PORT=389 -e OPENLDAP_PORT_SSL=636 --link=${fedora389ds.id}:fedora389ds.example.com -e FEDORA_389DS_HOST=fedora389ds.example.com -e FEDORA_389DS_PORT=3389 -e FEDORA_389DS_PORT_SSL=3636") {
+          action()
+        }
+      }
+    }
+  }
+}
diff --git a/NOTICE b/NOTICE
index d0d47b2..d2bed13 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,5 +1,5 @@
 Apache Directory Studio
-Copyright 2006-2020 The Apache Software Foundation
+Copyright 2006-2021 The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
diff --git a/README.md b/README.md
index 981c46e..1e9d1f9 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@
 
 ### Prerequisites
 
-* JDK 8 or newer
+* JDK 11 or newer
 * Maven 3 or newer
 * Sufficient heap space for Maven: `export MAVEN_OPTS="-Xmx512m"`
 
@@ -55,14 +55,18 @@
 
 ### Tests
 
-* Unit tests included in src/test/java of each plugin are executed automatically and run in 'test' phase
-* Core integration tests in tests/test.integration.core are executed automatically and run in 'integration-test' phase
-* SWTBot based UI integration tests in tests/test.integration.ui are disabled by default. They can be enabled with `-Denable-ui-tests`.
-  A failing test generates a screenshot. To not block the developer computer they can run within a virtual framebuffer:
+* Unit tests included in `src/test/java` of each plugin are executed automatically and run in 'test' phase
+* Core integration tests in `tests/test.integration.core` are executed automatically and run in 'integration-test' phase
+* UI integration tests based on SWTBot in `tests/test.integration.ui` are disabled by default. They can be enabled with `-Denable-ui-tests`. A failing test generates a screenshot. To not block the developer computer they can run within a virtual framebuffer:
 
     export DISPLAY=:99
     Xvfb :99 -screen 0 1024x768x16 &
 
+* The core and UI integration tests run against ApacheDS, OpenLDAP, and 389ds. The ApacheDS is always started in embedded mode. The others are expected to run, e.g. with the following commands, otherwise those tests are skipped. 
+
+    docker run -it --rm -p 20389:389 -p 20636:636 --name openldap -e LDAP_TLS_VERIFY_CLIENT=never osixia/openldap:1.3.0
+    docker run -it --rm -p 21389:3389 -p 21636:3636  --name fedora389ds -e DS_DM_PASSWORD=admin 389ds/dirsrv bash -c "set -m; /usr/lib/dirsrv/dscontainer -r & while ! /usr/lib/dirsrv/dscontainer -H; do sleep 5; done; sleep 5; /usr/sbin/dsconf localhost backend create --suffix dc=example,dc=org --be-name example; fg"
+	
 ### Build issues
 
 Tycho doesn't handle snapshot dependencies well. The first time a snapshot dependency is used within the build it is cached in `~/.m2/repository/p2`. Afterwards any change in the dependency (e.g. ApacheDS or LDAP API) is not considered unless it is deleted from the cache.
@@ -109,220 +113,6 @@
 * Open the product configuration 'org.apache.directory.studio.product' with the Product Configuration Editor
 * Click the link 'Launch an Eclipse application'
 
-
-## Release
-
-### Licenses
-
-The root directory contains LICENSE and NOTICE files for the source distribution.
-The product directory contains LICENSE and NOTICE files for the binary distributions, including licenses for bundled dependencies.
-
-
-### Release artifacts
-
-We release the following artifacts:
-
-* Source zip (the main artifact we vote on)
-* Maven artifacts
-    * poms
-    * plugins: pom, jar, javadoc, src
-    * features: pom, jar, src
-    * helps: pom, jar, src
-* P2 repositories
-    * the main features (LDAP Browser, Schema Editor, ApacheDS)
-    * dependencies
-* Product archives and installers for
-    * Linux GTK 64bit tar.gz
-    * maxOS 64bit dmg
-    * Windows 64bit exe installer and zip
-* Userguides
-
-### Signing keys
-
-Define the PGP key used to sign the artifacts and the Apple signing ID used to sign the DMG:
-
-    export RELEASE_KEY=28686142
-    export APPLE_SIGNING_ID=2GLGAFWEQD
-
-Note: those are Stefan's keys, replace with your own.
-
-### Preparation
-Update the copyright year. Full text search/replace "2006-2020". Also change in `plugins/rcp/src/main/resources/splash.bmp` image.
-
-Test the release build: rat check, javadoc and source jar generation, installer generation, GPG signing, userguide generation:
-
-    mvn -f pom-first.xml clean install
-    mvn -Papache-release,windows,macos -Duserguides clean install
-
-Note: During creation of the macOS installer (DMG) the ApacheDirectoryStudio.app is signed with the ASF "Developer ID Application" key. See https://issues.apache.org/jira/browse/INFRA-16978 for the process to get one.
-
-Test the build and sign process for distribution packages:
-
-    export VERSION=2.0.0-SNAPSHOT
-    cd dist
-    ./dist.sh
-
-Test the distribution packages:
-
-* Test generated bin archives, installers, and update site (if possible on all platforms).
-* Review generated user guides (pdf, html, Eclipse help)
-* Review the generated source archive
-* Verify signatures and checksums
-
-Run UI tests (if possible on all platforms):
-
-    mvn clean install -Denable-ui-tests
-
-### Release build steps
-
-As Tycho doesn't support the maven-release-plugin the release process is as follows:
-
-#### Define release version
-
-We use a release number scheme that suites for both, Maven and Eclipse.
-
-    <MAJOR>.<MINOR>.<PATCH>.v<YYYYMMDD>[-M<X>|RC<X>]
-
-Example for milestone version: `2.0.0.v20150529-M9`. Example for GA version: `2.0.1.v20150529`.
-
-Define a variable for later use:
-
-    export VERSION=2.0.0.v20150529-M9
-
-#### Create and checkout branch
-
-    git checkout -b $VERSION-prepare
-    git push origin $VERSION-prepare
-
-#### Remove OpenLDAP feature
-
-As long as the `org.apache.directory.studio.openldap.feature` is not ready for release it needs to be removed from `product/org.apache.directory.studio.product`.
-
-#### Set the version and commit
-
-    find . -name pom-first.xml | xargs sed -i 's/2.0.0-SNAPSHOT/'$VERSION'/'
-    find . -name pom-first.xml | xargs sed -i 's/2.0.0.qualifier/'$VERSION'/'
-    sed -i 's/2.0.0-SNAPSHOT/'$VERSION'/' pom.xml
-    mvn -f pom-first.xml clean install
-    git checkout pom.xml
-    mvn org.eclipse.tycho:tycho-versions-plugin:1.2.0:set-version -DnewVersion=$VERSION
-    git commit -am "Set version number for release $VERSION"
-    git push origin $VERSION-prepare
-
-#### Create the release tag
-
-    git tag $VERSION
-    git push origin $VERSION
-
-#### Clone the repo and checkout the tag into a fresh directory
-
-Run the actual release within a fresh checkout to ensure no previous build artifacts are used.
-
-    mkdir studio-release
-    cd studio-release
-    git clone https://gitbox.apache.org/repos/asf/directory-studio.git .
-    git checkout $VERSION
-
-#### Build the release and deploy to staging Nexus repository
-
-    mvn -f pom-first.xml clean install
-    mvn -Papache-release,windows,macos -Duserguides -DretryFailedDeploymentCount=3 clean deploy
-
-#### Close the staging Nexus repository
-
-See https://repository.apache.org/#stagingRepositories
-
-#### Package and sign distribution packages
-
-There is a script that collects and signs all update sites and distribution packages.
-
-Run the dist script:
-
-    cd dist
-    ./dist.sh
-
-Afterwards all distribution packages and user guides are located in `target`.
-
-#### Upload the distribution packages to SVN
-
-    cd target/dist/$VERSION
-    svn mkdir https://dist.apache.org/repos/dist/dev/directory/studio/$VERSION -m "Create dev area for release $VERSION"
-    svn co https://dist.apache.org/repos/dist/dev/directory/studio/$VERSION .
-    svn add *
-    svn commit -m "Add release $VERSION"
-    cd ../../..
-
-#### Upload the user guides to SVN
-
-    cd target/ug/$VERSION
-    svn mkdir https://svn.apache.org/repos/infra/websites/production/directory/content/studio/users-guide/$VERSION -m "Create user guides area for release $VERSION"
-    svn co https://svn.apache.org/repos/infra/websites/production/directory/content/studio/users-guide/$VERSION .
-    svn add *
-    svn commit -m "Add release $VERSION"
-    cd ../../..
-
-Note 1: This publishes the user guides directly to the production CMS!
-
-Note 2: In `content/extpaths.txt` the parent folder is already whitelisted.
-
-### Call the vote
-
-Start the vote.
-
-### Publish
-
-After successful vote publish the artifacts.
-
-Release artifacts in Nexus.
-
-Move distribution packages from `dev` area to `release`:
-
-	svn mv https://dist.apache.org/repos/dist/dev/directory/studio/$VERSION https://dist.apache.org/repos/dist/release/directory/studio/$VERSION -m "Release $VERSION"
-
-Wait 24h for mirror rsync.
-
-#### Update site
-
-The update site https://svn.apache.org/repos/asf/directory/site/trunk/content/studio/update needs to be updated.
-
-In the following files
-
-* `compositeArtifacts--xml.html`
-* `compositeContent--xml.html`
-* `product/compositeArtifacts--xml.html`
-* `product/compositeContent--xml.html`
-
-change the location path to the new release and also update the `p2.timestamp` to the current timestamp milliseconds (hint: `date +%s000`)
-
-#### Website
-
-Update news and download links
-
-* `lib/path.pm`: `$version_studio` and `$version_studio_name`
-* `content/index.mdtext`: version string
-* `content/studio/changelog.mdtext`
-* `content/studio/news.mdtext`
-* `content/studio/users-guide.mdtext`
-
-#### Eclipse Marketplace
-
-Update entry in Eclipse Marketplace: <https://marketplace.eclipse.org/content/apache-directory-studio>
-
-Also test to install the plugins from marketplace.
-
-#### Update Apache Reporter
-
-Add release to <https://reporter.apache.org/?directory>
-
-#### Send announce email
-
-Send the release announce email.
-
-#### Cleanup
-
-Delete old releases from `https://dist.apache.org/repos/dist/release/directory/studio/`, ensure they were already archived to `https://archive.apache.org/dist/directory/studio/`.
-
-
 ## Misc tips and tricks
 
 How to search features, plugins, versions in P2 repo?
@@ -338,6 +128,5 @@
 
 List all IUs within a repository:
 
-    provliu http://download.eclipse.org/eclipse/updates/4.15/
-
+    provliu http://download.eclipse.org/eclipse/updates/4.18/
 
diff --git a/RELEASE.md b/RELEASE.md
new file mode 100644
index 0000000..048d82b
--- /dev/null
+++ b/RELEASE.md
@@ -0,0 +1,242 @@
+> Licensed to the Apache Software Foundation (ASF) under one
+> or more contributor license agreements.  See the NOTICE file
+> distributed with this work for additional information
+> regarding copyright ownership.  The ASF licenses this file
+> to you 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.
+
+
+## Release
+
+### Licenses
+
+The root directory contains LICENSE and NOTICE files for the source distribution.
+The product directory contains LICENSE and NOTICE files for the binary distributions, including licenses for bundled dependencies.
+
+
+### Release artifacts
+
+We release the following artifacts:
+
+* Source zip (the main artifact we vote on)
+* Maven artifacts
+    * poms
+    * plugins: pom, jar, javadoc, src
+    * features: pom, jar, src
+    * helps: pom, jar, src
+* P2 repositories
+    * the main features (LDAP Browser, Schema Editor, ApacheDS)
+    * dependencies
+* Product archives and installers for
+    * Linux GTK 64bit tar.gz
+    * maxOS 64bit dmg
+    * Windows 64bit exe installer and zip
+* Userguides
+
+### Signing keys
+
+Define the PGP key used to sign the artifacts and the Apple signing ID used to sign the DMG:
+
+    export RELEASE_KEY=28686142
+    export APPLE_SIGNING_ID=2GLGAFWEQD
+
+Note: those are Stefan's keys, replace with your own.
+
+### Preparation
+Update the copyright year. Full text search/replace "2006-2021". Also change in `plugins/rcp/src/main/resources/splash.bmp` image.
+
+Test the release build: rat check, javadoc and source jar generation, installer generation, GPG signing, userguide generation:
+
+    mvn -f pom-first.xml clean install
+    mvn -Papache-release,windows,macos -Duserguides clean install
+
+Note: During creation of the macOS installer (DMG) the ApacheDirectoryStudio.app is signed with the ASF "Developer ID Application" key. See https://issues.apache.org/jira/browse/INFRA-16978 for the process to get one.
+
+Test the notarization of the macOS installer (requires app-specific password generated at https://appleid.apple.com/):
+
+    cd installers/macos/target
+    xcrun altool --notarize-app --primary-bundle-id "org.apache.directory.studio" --username "you@apache.org" --password "app-specific-password" --file ApacheDirectoryStudio-*.dmg
+
+Wait for the successful notarization (email notification).
+
+Test the build and sign process for distribution packages:
+
+    export VERSION=2.0.0-SNAPSHOT
+    cd dist
+    ./dist.sh
+
+Test the distribution packages:
+
+* Test generated bin archives, installers, and update site (if possible on all platforms).
+* Review generated user guides (pdf, html, Eclipse help)
+* Review the generated source archive
+* Verify signatures and checksums
+
+Run UI tests (if possible on all platforms):
+
+    mvn clean install -Denable-ui-tests
+
+### Release build steps
+
+As Tycho doesn't support the maven-release-plugin the release process is as follows:
+
+#### Define release version
+
+We use a release number scheme that suites for both, Maven and Eclipse.
+
+    <MAJOR>.<MINOR>.<PATCH>.v<YYYYMMDD>[-M<X>|RC<X>]
+
+Example for milestone version: `2.0.0.v20150529-M9`. Example for GA version: `2.0.1.v20150529`.
+
+Define a variable for later use:
+
+    export VERSION=2.0.0.v20150529-M9
+
+#### Create and checkout branch
+
+    git checkout -b $VERSION-prepare
+    git push origin $VERSION-prepare
+
+#### Remove OpenLDAP feature
+
+As long as the `org.apache.directory.studio.openldap.feature` is not ready for release it needs to be removed from `product/org.apache.directory.studio.product` then commit
+
+    git commit -am "Remove openldap feature for release"
+
+#### Set the version and commit
+
+    find . -name pom-first.xml | xargs sed -i 's/2.0.0-SNAPSHOT/'$VERSION'/'
+    find . -name pom-first.xml | xargs sed -i 's/2.0.0.qualifier/'$VERSION'/'
+    sed -i 's/2.0.0-SNAPSHOT/'$VERSION'/' pom.xml
+    mvn -f pom-first.xml clean install
+    git checkout pom.xml
+    mvn org.eclipse.tycho:tycho-versions-plugin:1.7.0:set-version -DnewVersion=$VERSION
+    git commit -am "Set version number for release $VERSION"
+    git push origin $VERSION-prepare
+
+#### Create the release tag
+
+    git tag $VERSION
+    git push origin $VERSION
+
+#### Clone the repo and checkout the tag into a fresh directory
+
+Run the actual release within a fresh checkout to ensure no previous build artifacts are used.
+
+    mkdir studio-release
+    cd studio-release
+    git clone https://gitbox.apache.org/repos/asf/directory-studio.git .
+    git checkout $VERSION
+
+#### Build the release and deploy to staging Nexus repository
+
+    mvn -f pom-first.xml clean install
+    mvn -Papache-release,windows,macos -Duserguides -DretryFailedDeploymentCount=3 clean deploy
+
+#### Close the staging Nexus repository
+
+See https://repository.apache.org/#stagingRepositories
+
+#### Notarize the macOS installer
+
+    cd installers/macos/target
+    xcrun altool --notarize-app --primary-bundle-id "org.apache.directory.studio" --username "you@apache.org" --password "app-specific-password" --file ApacheDirectoryStudio-*.dmg
+
+Wait for the successful notarization (email notification), then staple (attach) the notarization ticket to the DMG:
+
+    xcrun stapler staple ApacheDirectoryStudio-*.dmg
+
+#### Package and sign distribution packages
+
+There is a script that collects and signs all update sites and distribution packages.
+
+Run the dist script:
+
+    cd dist
+    ./dist.sh
+
+Afterwards all distribution packages and user guides are located in `target`.
+
+#### Upload the distribution packages to SVN
+
+    cd target/dist/$VERSION
+    svn mkdir https://dist.apache.org/repos/dist/dev/directory/studio/$VERSION -m "Create dev area for release $VERSION"
+    svn co https://dist.apache.org/repos/dist/dev/directory/studio/$VERSION .
+    svn add *
+    svn commit -m "Add release $VERSION"
+    cd ../../..
+
+#### Upload the user guides
+
+Upload the content of `target/ug/$VERSION` using WebDAVs to `nightlies.apache.org/directory/studio/$VERSION/userguide`.
+
+### Call the vote
+
+Start the vote.
+
+### Publish
+
+After successful vote publish the artifacts.
+
+Release artifacts in Nexus.
+
+Move distribution packages from `dev` area to `release`:
+
+	svn mv https://dist.apache.org/repos/dist/dev/directory/studio/$VERSION https://dist.apache.org/repos/dist/release/directory/studio/$VERSION -m "Release $VERSION"
+
+Wait 24h for mirror rsync.
+
+#### Update site
+
+The update site needs to be updated.
+
+In the following files
+
+* `static/studio/update/compositeArtifacts--xml.html`
+* `static/studio/update/compositeContent--xml.html`
+* `static/studio/update/product/compositeArtifacts--xml.html`
+* `static/studio/update/product/compositeContent--xml.html`
+
+change the location path to the new release and also update the `p2.timestamp` to the current timestamp milliseconds (hint: `date +%s000`)
+
+#### Website
+
+Update version, changelog, and news:
+
+* `config.toml`: `version_studio` and `version_studio_name`
+* `static/studio/.htaccess`
+* `source/studio/changelog.md`
+* `source/studio/news.md`
+
+#### Eclipse Marketplace
+
+Update entry in Eclipse Marketplace: <https://marketplace.eclipse.org/content/apache-directory-studio>
+
+Also test to install the plugins from marketplace.
+
+#### Mac Ports
+
+Update entry in Mac Ports: <https://ports.macports.org/port/directory-studio>
+
+#### Update Apache Reporter
+
+Add release to <https://reporter.apache.org/addrelease.html?directory>
+
+#### Send announce email
+
+Send the release announce email.
+
+#### Cleanup
+
+Delete old releases from `https://dist.apache.org/repos/dist/release/directory/studio/`, ensure they were already archived to `https://archive.apache.org/dist/directory/studio/`.
+
diff --git a/eclipse-trgt-platform/pom-first.xml b/eclipse-trgt-platform/pom-first.xml
index 5272968..22ed568 100644
--- a/eclipse-trgt-platform/pom-first.xml
+++ b/eclipse-trgt-platform/pom-first.xml
@@ -74,6 +74,18 @@
       <version>${org.apache.commons.pool.version}</version>
     </dependency>
 
+    <!-- Bouncycastle modules -->
+    <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bcprov-jdk15on</artifactId>
+      <version>${org.bouncycastle.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bcpkix-jdk15on</artifactId>
+      <version>${org.bouncycastle.version}</version>
+    </dependency>
 
     <!-- Mina modules -->
     <dependency>
diff --git a/eclipse-trgt-platform/template/org.apache.directory.studio.eclipse-trgt-platform.template b/eclipse-trgt-platform/template/org.apache.directory.studio.eclipse-trgt-platform.template
index d67e090..41bdc78 100644
--- a/eclipse-trgt-platform/template/org.apache.directory.studio.eclipse-trgt-platform.template
+++ b/eclipse-trgt-platform/template/org.apache.directory.studio.eclipse-trgt-platform.template
@@ -19,13 +19,15 @@
   @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 -->
 <?pde version="3.8"?>
-<target name="Apache Directory Studio Platform" sequenceNumber="453">
+<target name="Apache Directory Studio Platform" sequenceNumber="485">
   <locations>
 
     <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="true" type="InstallableUnit">
       <!-- External jars -->
+      <unit id="bcprov" version="1.62.0"/>
+      <unit id="bcpkix" version="1.62.0"/>
       <unit id="org.apache.servicemix.bundles.antlr" version="2.7.7.5"/>
-      <unit id="org.apache.servicemix.bundles.dom4j" version="2.1.1.1"/>
+      <unit id="org.apache.servicemix.bundles.dom4j" version="2.1.3.1"/>
       <unit id="org.apache.servicemix.bundles.xpp3" version="1.1.4.c"/>
       <unit id="com.github.ben-manes.caffeine" version="${com.github.ben-manes.caffeine.bundleversion}"/>
       <unit id="org.apache.httpcomponents.httpclient" version="${org.apache.httpcomponents.httpclient.bundleversion}"/>
@@ -108,32 +110,33 @@
     </location>
 
     <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="true" type="InstallableUnit">
-      <unit id="org.eclipse.rcp.feature.group" version="4.15.0.v20200305-0155"/>
-      <unit id="org.eclipse.rcp.source.feature.group" version="4.15.0.v20200305-0155"/>
-      <unit id="org.eclipse.platform.feature.group" version="4.15.0.v20200305-0155"/>
-      <unit id="org.eclipse.platform.source.feature.group" version="4.15.0.v20200305-0155"/>
-      <unit id="org.eclipse.jdt.feature.group" version="3.18.300.v20200305-0155"/>
-      <unit id="org.eclipse.jdt.source.feature.group" version="3.18.300.v20200305-0155"/>
-      <unit id="org.eclipse.pde.feature.group" version="3.14.300.v20200305-0155"/>
-      <unit id="org.eclipse.pde.source.feature.group" version="3.14.300.v20200305-0155"/>
-      <unit id="org.eclipse.equinox.p2.user.ui.feature.group" version="2.4.700.v20200222-1600"/>
-      <unit id="org.eclipse.equinox.executable.feature.group" version="3.8.700.v20200207-2156"/>
-      <repository location="http://download.eclipse.org/eclipse/updates/4.15"/>
+      <unit id="org.eclipse.rcp.feature.group" version="4.18.0.v20201202-1800"/>
+      <unit id="org.eclipse.rcp.source.feature.group" version="4.18.0.v20201202-1800"/>
+      <unit id="org.eclipse.platform.feature.group" version="4.18.0.v20201202-1800"/>
+      <unit id="org.eclipse.platform.source.feature.group" version="4.18.0.v20201202-1800"/>
+      <unit id="org.eclipse.jdt.feature.group" version="3.18.600.v20201202-1800"/>
+      <unit id="org.eclipse.jdt.source.feature.group" version="3.18.600.v20201202-1800"/>
+      <unit id="org.eclipse.pde.feature.group" version="3.14.600.v20201202-1800"/>
+      <unit id="org.eclipse.pde.source.feature.group" version="3.14.600.v20201202-1800"/>
+      <unit id="org.eclipse.equinox.p2.user.ui.feature.group" version="2.4.1000.v20201106-1246"/>
+      <unit id="org.eclipse.equinox.executable.feature.group" version="3.8.1000.v20200915-1508"/>
+      <repository location="http://download.eclipse.org/eclipse/updates/4.18"/>
     </location>
 
     <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="true" type="InstallableUnit">
       <unit id="javax.xml.stream" version="1.0.1.v201004272200"/>
       <unit id="org.slf4j.api" version="1.7.2.v20121108-1250"/>
       <unit id="org.slf4j.log4j" version="1.7.2.v20130115-1340"/>
-      <repository location="http://download.eclipse.org/tools/orbit/downloads/drops/R20200224183213/repository/"/>
+      <repository location="http://download.eclipse.org/tools/orbit/downloads/2020-12/"/>
     </location>
 
     <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="true" type="InstallableUnit">
-      <unit id="org.eclipse.swtbot.eclipse.feature.group" version="2.8.0.201906121535"/>
+      <unit id="org.eclipse.swtbot.eclipse.feature.group" version="3.0.0.202006031738"/>
+      <unit id="org.eclipse.swtbot.junit5.feature.group" version="3.0.0.202006031738"/>
       <unit id="org.hamcrest.core" version="1.3.0.v20180420-1519"/>
       <unit id="org.hamcrest.library" version="1.3.0.v20180524-2246"/>
       <unit id="org.apache.log4j" version="1.2.15.v201012070815"/>
-      <repository location="http://download.eclipse.org/technology/swtbot/releases/2.8.0/"/>
+      <repository location="http://download.eclipse.org/technology/swtbot/releases/3.0.0/"/>
     </location>
 
     <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="true" type="InstallableUnit">
diff --git a/features/apacheds.feature/feature.xml b/features/apacheds.feature/feature.xml
index 6af760d..be17f2a 100644
--- a/features/apacheds.feature/feature.xml
+++ b/features/apacheds.feature/feature.xml
@@ -12,7 +12,7 @@
    </description>
 
    <copyright>
-      Copyright © 2006-2020 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.
+      Copyright © 2006-2021 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.
    </copyright>
 
    <license url="http://www.apache.org/licenses/LICENSE-2.0.html">
diff --git a/features/ldapbrowser.feature/feature.xml b/features/ldapbrowser.feature/feature.xml
index d2a116c..df9c94a 100644
--- a/features/ldapbrowser.feature/feature.xml
+++ b/features/ldapbrowser.feature/feature.xml
@@ -12,7 +12,7 @@
    </description>
 
    <copyright>
-      Copyright © 2006-2020 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.
+      Copyright © 2006-2021 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.
    </copyright>
 
    <license url="http://www.apache.org/licenses/LICENSE-2.0.html">
diff --git a/features/ldifeditor.feature/feature.xml b/features/ldifeditor.feature/feature.xml
index c70f6f3..331ed9b 100644
--- a/features/ldifeditor.feature/feature.xml
+++ b/features/ldifeditor.feature/feature.xml
@@ -12,7 +12,7 @@
    </description>
 
    <copyright>
-      Copyright © 2006-2020 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.
+      Copyright © 2006-2021 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.
    </copyright>
 
    <license url="http://www.apache.org/licenses/LICENSE-2.0.html">
diff --git a/features/nls.feature/feature.xml b/features/nls.feature/feature.xml
index c09da8f..de0808d 100644
--- a/features/nls.feature/feature.xml
+++ b/features/nls.feature/feature.xml
@@ -11,7 +11,7 @@
    </description>
 
    <copyright>
-      Copyright © 2006-2020 The Apache Software Foundation, Licensed
+      Copyright © 2006-2021 The Apache Software Foundation, Licensed
 under the Apache License, Version 2.0.
    </copyright>
 
diff --git a/features/openldap.feature/feature.xml b/features/openldap.feature/feature.xml
index fbe76d3..2caa415 100644
--- a/features/openldap.feature/feature.xml
+++ b/features/openldap.feature/feature.xml
@@ -11,7 +11,7 @@
    </description>
 
    <copyright>
-      Copyright © 2006-2020 The Apache Software Foundation, Licensed
+      Copyright © 2006-2021 The Apache Software Foundation, Licensed
 under the Apache License, Version 2.0.
    </copyright>
 
diff --git a/features/rcp.feature/feature.xml b/features/rcp.feature/feature.xml
index 441f9b0..def333d 100644
--- a/features/rcp.feature/feature.xml
+++ b/features/rcp.feature/feature.xml
@@ -12,7 +12,7 @@
    </description>
 
    <copyright>
-      Copyright © 2006-2020 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.
+      Copyright © 2006-2021 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.
    </copyright>
 
    <license url="http://www.apache.org/licenses/LICENSE-2.0.html">
diff --git a/features/schemaeditor.feature/feature.xml b/features/schemaeditor.feature/feature.xml
index 9cd327b..e8d3fa1 100644
--- a/features/schemaeditor.feature/feature.xml
+++ b/features/schemaeditor.feature/feature.xml
@@ -12,7 +12,7 @@
    </description>
 
    <copyright>
-      Copyright © 2006-2020 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.
+      Copyright © 2006-2021 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.
    </copyright>
 
    <license url="http://www.apache.org/licenses/LICENSE-2.0.html">
diff --git a/helps/apacheds.help/pom-first.xml b/helps/apacheds.help/pom-first.xml
index f20b3f4..62969a7 100644
--- a/helps/apacheds.help/pom-first.xml
+++ b/helps/apacheds.help/pom-first.xml
@@ -45,7 +45,6 @@
             <Bundle-SymbolicName>${project.artifactId};singleton:=true</Bundle-SymbolicName>
             <Bundle-Localization>plugin</Bundle-Localization>
             <Eclipse-LazyStart>true</Eclipse-LazyStart>
-            <Export-Package>!</Export-Package>
           </instructions>
         </configuration>
         <executions>
diff --git a/helps/apacheds.help/src/main/docbook/0_index.xml b/helps/apacheds.help/src/main/docbook/0_index.xml
index 8adf5c0..7aa112e 100644
--- a/helps/apacheds.help/src/main/docbook/0_index.xml
+++ b/helps/apacheds.help/src/main/docbook/0_index.xml
@@ -44,7 +44,7 @@
 		<subtitle>User's Guide</subtitle>
 		<releaseinfo>Version ${pom.version}</releaseinfo>
 		<copyright>
-			<year>2006-2020</year>
+			<year>2006-2021</year>
 			<holder>The Apache Software Foundation</holder>
 		</copyright>
 		<legalnotice>
diff --git a/helps/ldapbrowser.help/pom-first.xml b/helps/ldapbrowser.help/pom-first.xml
index 6dd7d90..3ed3568 100644
--- a/helps/ldapbrowser.help/pom-first.xml
+++ b/helps/ldapbrowser.help/pom-first.xml
@@ -45,7 +45,6 @@
             <Bundle-SymbolicName>${project.artifactId};singleton:=true</Bundle-SymbolicName>
             <Bundle-Localization>plugin</Bundle-Localization>
             <Eclipse-LazyStart>true</Eclipse-LazyStart>
-            <Export-Package>!</Export-Package>
           </instructions>
         </configuration>
         <executions>
diff --git a/helps/ldapbrowser.help/src/main/docbook/0_index.xml b/helps/ldapbrowser.help/src/main/docbook/0_index.xml
index 2fdf459..aecbe7b 100644
--- a/helps/ldapbrowser.help/src/main/docbook/0_index.xml
+++ b/helps/ldapbrowser.help/src/main/docbook/0_index.xml
@@ -103,7 +103,7 @@
 		<subtitle>User's Guide</subtitle>
 		<releaseinfo>Version ${pom.version}</releaseinfo>
 		<copyright>
-			<year>2006-2020</year>
+			<year>2006-2021</year>
 			<holder>The Apache Software Foundation</holder>
 		</copyright>
 		<legalnotice>
diff --git a/helps/ldapbrowser.help/src/main/docbook/2.40_tools_newconnection_wizard.xml b/helps/ldapbrowser.help/src/main/docbook/2.40_tools_newconnection_wizard.xml
index 19f1a6d..c5312b6 100644
--- a/helps/ldapbrowser.help/src/main/docbook/2.40_tools_newconnection_wizard.xml
+++ b/helps/ldapbrowser.help/src/main/docbook/2.40_tools_newconnection_wizard.xml
@@ -574,15 +574,15 @@
 								Specify the modify mode for attributes with an equality matching rule.
 								Description of options:
 								<itemizedlist spacing="normal" mark="bullet">
-									<listitem>Optimized Modify Operations: uses add/delete by default, 
-									uses replace if operation count is less</listitem>
+									<listitem>Default: uses add/delete by default, 
+									uses replace for X-ORDERED attributes</listitem>
 									<listitem>Always REPLACE: always uses replace operations to perform 
 									entry modifications</listitem>
 									<listitem>Always ADD/DELETE: always uses add and/or delete operations 
 									to perform entry modifications</listitem>
 								</itemizedlist>
 							</entry>
-							<entry>Optimized Modify Operations</entry>
+							<entry>Default</entry>
 						</row>
 						<row>
 							<entry>Modify Mode (no equality matching rule)</entry>
@@ -590,8 +590,8 @@
 								Specify the modify mode for attributes with *no* equality matching rule.
 								Description of options:
 								<itemizedlist spacing="normal" mark="bullet">
-									<listitem>Optimized Modify Operations: uses add/delete by default, 
-									uses replace if operation count is less</listitem>
+									<listitem>Default: uses add/delete by default, 
+									uses replace for X-ORDERED attributes</listitem>
 									<listitem>Always REPLACE: always uses replace operations to perform 
 									entry modifications</listitem>
 									<listitem>Always ADD/DELETE: always uses add and/or delete operations 
@@ -599,18 +599,18 @@
 								</itemizedlist>
 								Recommended values for various LDAP servers:
 								<itemizedlist spacing="normal" mark="bullet">
-									<listitem>ApacheDS: Optimized Modify Operations or REPLACE</listitem>
+									<listitem>ApacheDS: Default or REPLACE</listitem>
 									<listitem>OpenLDAP: REPLACE</listitem>
-									<listitem>OpenDS / SunDSEE: Optimized Modify Operations or REPLACE</listitem>
-									<listitem>FedoraDS / 389DS: Optimized Modify Operations 
+									<listitem>OpenDS / SunDSEE: Default or REPLACE</listitem>
+									<listitem>FedoraDS / 389DS: Default 
 									(missing equality matching rules for many standard attribute types)</listitem>
-									<listitem>Active Directory: Optimized Modify Operations 
+									<listitem>Active Directory: Default 
 									(exposes no equality matching rules at all)</listitem>
-									<listitem>eDirectory: Optimized Modify Operations 
+									<listitem>eDirectory: Default 
 									(exposes no equality matching rules at all)</listitem>
 								</itemizedlist>
 							</entry>
-							<entry>Optimized Modify Operations</entry>
+							<entry>Default</entry>
 						</row>
 						<row>
 							<entry>Modify Order</entry>
diff --git a/helps/ldapbrowser.help/src/main/docbook/2.80_tools_connection_properties.xml b/helps/ldapbrowser.help/src/main/docbook/2.80_tools_connection_properties.xml
index c080548..68ed5f4 100644
--- a/helps/ldapbrowser.help/src/main/docbook/2.80_tools_connection_properties.xml
+++ b/helps/ldapbrowser.help/src/main/docbook/2.80_tools_connection_properties.xml
@@ -437,8 +437,8 @@
 							Specify the modify mode for attributes with an equality matching rule.
 							Description of options:
 							<itemizedlist spacing="normal" mark="bullet">
-								<listitem>Optimized Modify Operations: uses add/delete by default, 
-								uses replace if operation count is less</listitem>
+								<listitem>Default: uses add/delete by default, 
+								uses replace for X-ORDERED attributes</listitem>
 								<listitem>Always REPLACE: always uses replace operations to perform 
 								entry modifications</listitem>
 								<listitem>Always ADD/DELETE: always uses add and/or delete operations 
@@ -452,8 +452,8 @@
 							Specify the modify mode for attributes with *no* equality matching rule.
 							Description of options:
 							<itemizedlist spacing="normal" mark="bullet">
-								<listitem>Optimized Modify Operations: uses add/delete by default, 
-								uses replace if operation count is less</listitem>
+								<listitem>Default: uses add/delete by default, 
+								uses replace for X-ORDERED attributes</listitem>
 								<listitem>Always REPLACE: always uses replace operations to perform 
 								entry modifications</listitem>
 								<listitem>Always ADD/DELETE: always uses add and/or delete operations 
@@ -461,14 +461,14 @@
 							</itemizedlist>
 							Recommended values for various LDAP servers:
 							<itemizedlist spacing="normal" mark="bullet">
-								<listitem>ApacheDS: Optimized Modify Operations or REPLACE</listitem>
+								<listitem>ApacheDS: Default or REPLACE</listitem>
 								<listitem>OpenLDAP: REPLACE</listitem>
-								<listitem>OpenDS / SunDSEE: Optimized Modify Operations or REPLACE</listitem>
-								<listitem>FedoraDS / 389DS: Optimized Modify Operations 
+								<listitem>OpenDS / SunDSEE: Default or REPLACE</listitem>
+								<listitem>FedoraDS / 389DS: Default 
 								(missing equality matching rules for many standard attribute types)</listitem>
-								<listitem>Active Directory: Optimized Modify Operations 
+								<listitem>Active Directory: Default 
 								(exposes no equality matching rules at all)</listitem>
-								<listitem>eDirectory: Optimized Modify Operations 
+								<listitem>eDirectory: Default 
 								(exposes no equality matching rules at all)</listitem>
 							</itemizedlist>
 						</entry>
diff --git a/helps/ldapbrowser.help/src/main/resources/about.html b/helps/ldapbrowser.help/src/main/resources/about.html
index 33b6def..1f85691 100644
--- a/helps/ldapbrowser.help/src/main/resources/about.html
+++ b/helps/ldapbrowser.help/src/main/resources/about.html
@@ -9,7 +9,7 @@
 
 <h3>Copyright</h3>
 
-<p>Copyright (c) 2006-2020 The Apache Software Foundation. All rights reserved.</p>
+<p>Copyright (c) 2006-2021 The Apache Software Foundation. All rights reserved.</p>
 
 <h3>License</h3>
 
diff --git a/helps/ldifeditor.help/pom-first.xml b/helps/ldifeditor.help/pom-first.xml
index e914b0d..89f0130 100644
--- a/helps/ldifeditor.help/pom-first.xml
+++ b/helps/ldifeditor.help/pom-first.xml
@@ -45,7 +45,6 @@
             <Bundle-SymbolicName>${project.artifactId};singleton:=true</Bundle-SymbolicName>
             <Bundle-Localization>plugin</Bundle-Localization>
             <Eclipse-LazyStart>true</Eclipse-LazyStart>
-            <Export-Package>!</Export-Package>
           </instructions>
         </configuration>
         <executions>
diff --git a/helps/ldifeditor.help/src/main/docbook/0_index.xml b/helps/ldifeditor.help/src/main/docbook/0_index.xml
index c214a70..143252b 100644
--- a/helps/ldifeditor.help/src/main/docbook/0_index.xml
+++ b/helps/ldifeditor.help/src/main/docbook/0_index.xml
@@ -34,7 +34,7 @@
 		<subtitle>User's Guide</subtitle>
 		<releaseinfo>Version ${pom.version}</releaseinfo>
 		<copyright>
-			<year>2006-2020</year>
+			<year>2006-2021</year>
 			<holder>The Apache Software Foundation</holder>
 		</copyright>
 		<legalnotice>
diff --git a/helps/ldifeditor.help/src/main/resources/about.html b/helps/ldifeditor.help/src/main/resources/about.html
index 33b6def..1f85691 100644
--- a/helps/ldifeditor.help/src/main/resources/about.html
+++ b/helps/ldifeditor.help/src/main/resources/about.html
@@ -9,7 +9,7 @@
 
 <h3>Copyright</h3>
 
-<p>Copyright (c) 2006-2020 The Apache Software Foundation. All rights reserved.</p>
+<p>Copyright (c) 2006-2021 The Apache Software Foundation. All rights reserved.</p>
 
 <h3>License</h3>
 
diff --git a/helps/rcp.help/pom-first.xml b/helps/rcp.help/pom-first.xml
index 17e2d71..a9cec02 100644
--- a/helps/rcp.help/pom-first.xml
+++ b/helps/rcp.help/pom-first.xml
@@ -45,7 +45,6 @@
             <Bundle-SymbolicName>${project.artifactId};singleton:=true</Bundle-SymbolicName>
             <Bundle-Localization>plugin</Bundle-Localization>
             <Eclipse-LazyStart>true</Eclipse-LazyStart>
-            <Export-Package>!</Export-Package>
           </instructions>
         </configuration>
         <executions>
diff --git a/helps/rcp.help/src/main/docbook/0_index.xml b/helps/rcp.help/src/main/docbook/0_index.xml
index 2667812..f86d218 100644
--- a/helps/rcp.help/src/main/docbook/0_index.xml
+++ b/helps/rcp.help/src/main/docbook/0_index.xml
@@ -13,6 +13,7 @@
   <!ENTITY apache_directory_studio SYSTEM "3.1.1_apache_directory_studio.xml">
   <!ENTITY general SYSTEM "3.1.2_general.xml">
   <!ENTITY network_connections SYSTEM "3.1.2.1_network_connections.xml">
+  <!ENTITY appearance SYSTEM "3.1.2.2_appearance.xml">
   <!ENTITY help SYSTEM "3.1.3_help.xml">
   <!ENTITY help_content SYSTEM "3.1.3.1_help_content.xml">
   <!ENTITY install_update SYSTEM "3.1.4_install_update.xml">
@@ -43,7 +44,7 @@
 		<subtitle>User's Guide</subtitle>
 		<releaseinfo>Version ${pom.version}</releaseinfo>
 		<copyright>
-			<year>2006-2020</year>
+			<year>2006-2021</year>
 			<holder>The Apache Software Foundation</holder>
 		</copyright>
 		<legalnotice>
diff --git a/helps/rcp.help/src/main/docbook/3.1.2.1_network_connections.xml b/helps/rcp.help/src/main/docbook/3.1.2.1_network_connections.xml
index 1745ebd..cb29a1e 100644
--- a/helps/rcp.help/src/main/docbook/3.1.2.1_network_connections.xml
+++ b/helps/rcp.help/src/main/docbook/3.1.2.1_network_connections.xml
@@ -124,12 +124,5 @@
 			</mediaobject>
 		</screenshot>
 	</para>
-	<para>
-		1. The SOCKS proxy support in Java 1.4 had certain limitations.
-		Due to these limitations, the setting of the SOCKS system
-		properties is not performed when a 1.4 VM is used. The SOCKS
-		proxy may still be used by some tooling when running on a 1.4 VM
-		(e.g. CVS). However, users should use a 1.5 (or 5.0) VM if they
-		require full SOCKS proxy support.
-	</para>
+
 </section>
\ No newline at end of file
diff --git a/helps/rcp.help/src/main/docbook/3.1.2.2_appearance.xml b/helps/rcp.help/src/main/docbook/3.1.2.2_appearance.xml
new file mode 100644
index 0000000..ea654fc
--- /dev/null
+++ b/helps/rcp.help/src/main/docbook/3.1.2.2_appearance.xml
@@ -0,0 +1,39 @@
+<!--
+	Licensed to the Apache Software Foundation (ASF) under one
+	or more contributor license agreements.  See the NOTICE file
+	distributed with this work for additional information
+	regarding copyright ownership.  The ASF licenses this file
+	to you 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.
+-->
+<section id="appearance">
+	<title>Appearance</title>
+	<para>
+		The Appearance preferences page allows you to configure a theme,
+		e.g. dark mode or light mode.
+	</para>
+	<para>
+		Here is what the Appearance preferences page looks like:
+	</para>
+	<para>
+		<screenshot>
+			<mediaobject>
+				<imageobject>
+					<imagedata scale="50"
+						fileref="images/appearance.png" format="PNG" />
+				</imageobject>
+			</mediaobject>
+		</screenshot>
+	</para>
+
+</section>
\ No newline at end of file
diff --git a/helps/rcp.help/src/main/docbook/3.1.2_general.xml b/helps/rcp.help/src/main/docbook/3.1.2_general.xml
index 5d91d8a..6398bee 100644
--- a/helps/rcp.help/src/main/docbook/3.1.2_general.xml
+++ b/helps/rcp.help/src/main/docbook/3.1.2_general.xml
@@ -110,6 +110,7 @@
 		</screenshot>
 	</para>
 	
+    &appearance;
     &network_connections;
 
 </section>
\ No newline at end of file
diff --git a/helps/rcp.help/src/main/resources/html/images/appearance.png b/helps/rcp.help/src/main/resources/html/images/appearance.png
new file mode 100644
index 0000000..506990a
--- /dev/null
+++ b/helps/rcp.help/src/main/resources/html/images/appearance.png
Binary files differ
diff --git a/helps/schemaeditor.help/pom-first.xml b/helps/schemaeditor.help/pom-first.xml
index 84c46b6..2924ea9 100644
--- a/helps/schemaeditor.help/pom-first.xml
+++ b/helps/schemaeditor.help/pom-first.xml
@@ -45,7 +45,6 @@
             <Bundle-SymbolicName>${project.artifactId};singleton:=true</Bundle-SymbolicName>
             <Bundle-Localization>plugin</Bundle-Localization>
             <Eclipse-LazyStart>true</Eclipse-LazyStart>
-            <Export-Package>!</Export-Package>
           </instructions>
         </configuration>
         <executions>
diff --git a/helps/schemaeditor.help/src/main/docbook/0_index.xml b/helps/schemaeditor.help/src/main/docbook/0_index.xml
index fa25564..16fa958 100644
--- a/helps/schemaeditor.help/src/main/docbook/0_index.xml
+++ b/helps/schemaeditor.help/src/main/docbook/0_index.xml
@@ -60,7 +60,7 @@
 		<subtitle>User's Guide</subtitle>
 		<releaseinfo>Version ${pom.version}</releaseinfo>
 		<copyright>
-			<year>2006-2020</year>
+			<year>2006-2021</year>
 			<holder>The Apache Software Foundation</holder>
 		</copyright>
 		<legalnotice>
diff --git a/helps/schemaeditor.help/src/main/resources/about.html b/helps/schemaeditor.help/src/main/resources/about.html
index 33b6def..1f85691 100644
--- a/helps/schemaeditor.help/src/main/resources/about.html
+++ b/helps/schemaeditor.help/src/main/resources/about.html
@@ -9,7 +9,7 @@
 
 <h3>Copyright</h3>
 
-<p>Copyright (c) 2006-2020 The Apache Software Foundation. All rights reserved.</p>
+<p>Copyright (c) 2006-2021 The Apache Software Foundation. All rights reserved.</p>
 
 <h3>License</h3>
 
diff --git a/installers/macos/src/dmg/createDMG.sh b/installers/macos/src/dmg/createDMG.sh
index 0626ec1..17d10b9 100755
--- a/installers/macos/src/dmg/createDMG.sh
+++ b/installers/macos/src/dmg/createDMG.sh
@@ -39,7 +39,7 @@
 ln -s /Applications dmg/Applications
 
 # Codesign the App with the ASF key, and verify
-codesign --force --deep -s ${APPLE_SIGNING_ID} dmg/ApacheDirectoryStudio.app
+codesign --force --deep --timestamp --options runtime --entitlements entitlements.plist -s ${APPLE_SIGNING_ID} dmg/ApacheDirectoryStudio.app
 codesign -dv --verbose=4 dmg/ApacheDirectoryStudio.app
 
 # Creating the disk image
diff --git a/installers/macos/src/dmg/entitlements.plist b/installers/macos/src/dmg/entitlements.plist
new file mode 100644
index 0000000..41c9a91
--- /dev/null
+++ b/installers/macos/src/dmg/entitlements.plist
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You 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.
+-->
+<plist version="1.0">
+<dict>
+    <key>com.apple.security.cs.allow-jit</key>
+    <true/>
+    <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
+    <true/>
+    <key>com.apple.security.cs.disable-executable-page-protection</key>
+    <true/>
+    <key>com.apple.security.cs.allow-dyld-environment-variables</key>
+    <true/>
+    <key>com.apple.security.cs.disable-library-validation</key>
+    <true/>
+</dict>
+</plist>
\ No newline at end of file
diff --git a/installers/windows/src/nsis/windows_installer.nsi b/installers/windows/src/nsis/windows_installer.nsi
index e6d3d6e..61de146 100755
--- a/installers/windows/src/nsis/windows_installer.nsi
+++ b/installers/windows/src/nsis/windows_installer.nsi
@@ -212,6 +212,8 @@
         # Configuring registries for the uninstaller

         WriteRegStr "${INSTDIR_REG_ROOT}" "${INSTDIR_REG_KEY}" "DisplayName" "${Application} - (remove only)"

         WriteRegStr "${INSTDIR_REG_ROOT}" "${INSTDIR_REG_KEY}" "DisplayIcon" "$INSTDIR\uninstall.exe"

+        WriteRegStr "${INSTDIR_REG_ROOT}" "${INSTDIR_REG_KEY}" "DisplayVersion" "${BrandingVersion}"

+        WriteRegStr "${INSTDIR_REG_ROOT}" "${INSTDIR_REG_KEY}" "Publisher" "The Apache Software Foundation"

         WriteRegStr "${INSTDIR_REG_ROOT}" "${INSTDIR_REG_KEY}" "UninstallString" '"$INSTDIR\uninstall.exe"'

         WriteRegDWORD "${INSTDIR_REG_ROOT}" "${INSTDIR_REG_KEY}" "NoModify" "1"

         WriteRegDWORD "${INSTDIR_REG_ROOT}" "${INSTDIR_REG_KEY}" "NoRepair" "1"

diff --git a/plugins/aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/model/ProtectedItemWrapper.java b/plugins/aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/model/ProtectedItemWrapper.java
index 37ea3f2..4138f28 100644
--- a/plugins/aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/model/ProtectedItemWrapper.java
+++ b/plugins/aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/model/ProtectedItemWrapper.java
@@ -220,7 +220,7 @@
             for ( Iterator<AttributeType> it = aav.iterator(); it.hasNext(); )
             {
                 AttributeType attributeType = it.next();
-                values.add( attributeType.toString() );
+                values.add( attributeType.getName() );
             }
         }
         else if ( item instanceof AttributeValueItem )
@@ -240,7 +240,7 @@
             for ( Iterator<AttributeType> it = sv.iterator(); it.hasNext(); )
             {
                 AttributeType attributeType = it.next();
-                values.add( attributeType.toString() );
+                values.add( attributeType.getName() );
             }
         }
         else if ( item instanceof RangeOfValuesItem )
diff --git a/plugins/aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/sourceeditor/ACITextAttributeProvider.java b/plugins/aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/sourceeditor/ACITextAttributeProvider.java
index c81d9bb..71a07ec 100644
--- a/plugins/aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/sourceeditor/ACITextAttributeProvider.java
+++ b/plugins/aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/sourceeditor/ACITextAttributeProvider.java
@@ -24,6 +24,7 @@
 import java.util.Map;
 
 import org.apache.directory.studio.common.ui.CommonUIConstants;
+import org.apache.directory.studio.common.ui.CommonUIPlugin;
 import org.eclipse.jface.text.TextAttribute;
 import org.eclipse.swt.SWT;
 
@@ -38,7 +39,6 @@
     public static final String DEFAULT_ATTRIBUTE = "__pos_aci_default_attribute"; //$NON-NLS-1$
     public static final String KEYWORD_ATTRIBUTE = "__pos_aci_keyword_attribute"; //$NON-NLS-1$
     public static final String STRING_ATTRIBUTE = "__pos_aci_string_attribute"; //$NON-NLS-1$
-    public static final String GRANT_DENY_ATTRIBUTE = "__pos_aci_grant_deny_attribute"; //$NON-NLS-1$
     public static final String IDENTIFICATION_ATTRIBUTE = "__pos_aci_identification_attribute"; //$NON-NLS-1$
     public static final String PRECEDENCE_ATTRIBUTE = "__pos_aci_precedence_attribute"; //$NON-NLS-1$
     public static final String AUTHENTICATIONLEVEL_ATTRIBUTE = "__pos_aci_authenticationlevel_attribute"; //$NON-NLS-1$
@@ -56,18 +56,17 @@
      */
     public ACITextAttributeProvider()
     {
-        attributes.put( DEFAULT_ATTRIBUTE, new TextAttribute( CommonUIConstants.BLACK_COLOR ) );
-        attributes.put( KEYWORD_ATTRIBUTE, new TextAttribute( CommonUIConstants.M_PURPLE_COLOR, null, SWT.BOLD ) );
-        attributes.put( STRING_ATTRIBUTE, new TextAttribute( CommonUIConstants.BLUE_COLOR ) );
-        attributes.put( GRANT_DENY_ATTRIBUTE, new TextAttribute( CommonUIConstants.M_GREY_COLOR ) );
-        attributes.put( GRANT_VALUE, new TextAttribute( CommonUIConstants.ML_GREEN_COLOR ) );
-        attributes.put( DENY_VALUE, new TextAttribute( CommonUIConstants.ML_RED_COLOR ) );
-        attributes.put( IDENTIFICATION_ATTRIBUTE, new TextAttribute( CommonUIConstants.M_RED_COLOR, null, SWT.BOLD ) );
-        attributes.put( PRECEDENCE_ATTRIBUTE, new TextAttribute( CommonUIConstants.M_BLUE_COLOR, null, SWT.BOLD ) );
-        attributes.put( AUTHENTICATIONLEVEL_ATTRIBUTE, new TextAttribute( CommonUIConstants.M_GREEN_COLOR, null, SWT.BOLD ) );
-        attributes.put( ITEMORUSERFIRST_ATTRIBUTE, new TextAttribute( CommonUIConstants.M_PURPLE_COLOR, null, SWT.BOLD ) );
-        attributes.put( USER_ATTRIBUTE, new TextAttribute( CommonUIConstants.R0_G127_B255_COLOR, null, SWT.BOLD ) );
-
+        CommonUIPlugin plugin = CommonUIPlugin.getDefault();
+        attributes.put( DEFAULT_ATTRIBUTE, new TextAttribute( plugin.getColor( CommonUIConstants.DEFAULT_COLOR ) ) );
+        attributes.put( KEYWORD_ATTRIBUTE, new TextAttribute( plugin.getColor( CommonUIConstants.ATTRIBUTE_TYPE_COLOR ), null, SWT.BOLD ) );
+        attributes.put( STRING_ATTRIBUTE, new TextAttribute( plugin.getColor( CommonUIConstants.VALUE_COLOR ) ) );
+        attributes.put( GRANT_VALUE, new TextAttribute( plugin.getColor( CommonUIConstants.ADD_COLOR ) ) );
+        attributes.put( DENY_VALUE, new TextAttribute( plugin.getColor( CommonUIConstants.DELETE_COLOR ) ) );
+        attributes.put( IDENTIFICATION_ATTRIBUTE, new TextAttribute( plugin.getColor( CommonUIConstants.KEYWORD_1_COLOR ), null, SWT.BOLD ) );
+        attributes.put( PRECEDENCE_ATTRIBUTE, new TextAttribute( plugin.getColor( CommonUIConstants.KEYWORD_1_COLOR ), null, SWT.BOLD ) );
+        attributes.put( AUTHENTICATIONLEVEL_ATTRIBUTE, new TextAttribute( plugin.getColor( CommonUIConstants.KEYWORD_1_COLOR ), null, SWT.BOLD ) );
+        attributes.put( ITEMORUSERFIRST_ATTRIBUTE, new TextAttribute( plugin.getColor( CommonUIConstants.KEYWORD_1_COLOR ), null, SWT.BOLD ) );
+        attributes.put( USER_ATTRIBUTE, new TextAttribute( plugin.getColor( CommonUIConstants.KEYWORD_1_COLOR ), null, SWT.BOLD ) );
     }
 
 
diff --git a/plugins/apacheds.configuration/about.ini b/plugins/apacheds.configuration/about.ini
index 53585a8..40c57e9 100644
--- a/plugins/apacheds.configuration/about.ini
+++ b/plugins/apacheds.configuration/about.ini
@@ -1,2 +1,2 @@
 featureImage=studio.png
-aboutText=Apache Directory Studio ApacheDS - ApacheDS (Apache Directory Server) specific tools: configuration editor for ApacheDS and a launchable ApacheDS.\n\nVersion: ${unqualifiedVersion}.${buildQualifier}\n\nCopyright \u00A9 2006-2020 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.\nVisit http://directory.apache.org/studio
+aboutText=Apache Directory Studio ApacheDS - ApacheDS (Apache Directory Server) specific tools: configuration editor for ApacheDS and a launchable ApacheDS.\n\nVersion: ${unqualifiedVersion}.${buildQualifier}\n\nCopyright \u00A9 2006-2021 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.\nVisit http://directory.apache.org/studio
diff --git a/plugins/apacheds.configuration/src/main/java/org/apache/directory/studio/apacheds/configuration/editor/ServerConfigurationEditorPage.java b/plugins/apacheds.configuration/src/main/java/org/apache/directory/studio/apacheds/configuration/editor/ServerConfigurationEditorPage.java
index 5c7f10b..415abe0 100644
--- a/plugins/apacheds.configuration/src/main/java/org/apache/directory/studio/apacheds/configuration/editor/ServerConfigurationEditorPage.java
+++ b/plugins/apacheds.configuration/src/main/java/org/apache/directory/studio/apacheds/configuration/editor/ServerConfigurationEditorPage.java
@@ -28,6 +28,7 @@
 import org.apache.directory.studio.apacheds.configuration.actions.EditorExportConfigurationAction;
 import org.apache.directory.studio.apacheds.configuration.actions.EditorImportConfigurationAction;
 import org.apache.directory.studio.common.ui.CommonUIConstants;
+import org.apache.directory.studio.common.ui.CommonUIPlugin;
 import org.apache.directory.studio.connection.core.Connection;
 import org.eclipse.jface.action.IToolBarManager;
 import org.eclipse.jface.action.Separator;
@@ -460,7 +461,7 @@
     {
         Label label = toolkit.createLabel( parent,
             NLS.bind( Messages.getString( "ServerConfigurationEditorPage.DefaultWithValue" ), text ), SWT.WRAP ); //$NON-NLS-1$
-        label.setForeground( CommonUIConstants.M_GREY_COLOR );
+        label.setForeground( CommonUIPlugin.getDefault().getColor( CommonUIConstants.KEYWORD_1_COLOR ) );
 
         return label;
     }
diff --git a/plugins/common.core/src/main/java/org/apache/directory/studio/common/core/jobs/CommonCorePlugin.java b/plugins/common.core/src/main/java/org/apache/directory/studio/common/core/jobs/CommonCorePlugin.java
index 8c22d06..f6508c0 100644
--- a/plugins/common.core/src/main/java/org/apache/directory/studio/common/core/jobs/CommonCorePlugin.java
+++ b/plugins/common.core/src/main/java/org/apache/directory/studio/common/core/jobs/CommonCorePlugin.java
@@ -70,7 +70,6 @@
         plugin = null;
 
         studioProgressMonitorWatcherJob.stop();
-        studioProgressMonitorWatcherJob.join();
         studioProgressMonitorWatcherJob = null;
 
         super.stop( context );
diff --git a/plugins/common.core/src/main/java/org/apache/directory/studio/common/core/jobs/StudioProgressMonitor.java b/plugins/common.core/src/main/java/org/apache/directory/studio/common/core/jobs/StudioProgressMonitor.java
index 3214067..6dcbb40 100644
--- a/plugins/common.core/src/main/java/org/apache/directory/studio/common/core/jobs/StudioProgressMonitor.java
+++ b/plugins/common.core/src/main/java/org/apache/directory/studio/common/core/jobs/StudioProgressMonitor.java
@@ -285,7 +285,7 @@
                     
                     if ( indexOfAny > -1 )
                     {
-                        exceptionMessage = exceptionMessage.substring( 0, indexOfAny - 1 );
+                        exceptionMessage = exceptionMessage.substring( 0, indexOfAny );
                     }
                     
                     buffer.append( "\n - " ).append( exceptionMessage ); //$NON-NLS-1$
diff --git a/plugins/common.ui/plugin.xml b/plugins/common.ui/plugin.xml
index 04fb3b2..da7f6eb 100644
--- a/plugins/common.ui/plugin.xml
+++ b/plugins/common.ui/plugin.xml
@@ -27,4 +27,22 @@
             name="%Pref_StudioPage_name">
       </page>
    </extension>
+   <extension
+         point="org.eclipse.core.runtime.preferences">
+      <initializer
+            class="org.apache.directory.studio.common.ui.CommonUIPreferencesInitializer">
+      </initializer>
+   </extension>
+
+  <extension point="org.eclipse.e4.ui.css.swt.theme">
+    <stylesheet uri="resources/css/dark.css">
+      <themeid refid="org.eclipse.e4.ui.css.theme.e4_dark">
+      </themeid>
+    </stylesheet>
+    <stylesheet uri="resources/css/default.css">
+      <themeid refid="org.eclipse.e4.ui.css.theme.e4_default">
+      </themeid>
+    </stylesheet>
+  </extension>
+
 </plugin>
diff --git a/plugins/common.ui/resources/css/dark.css b/plugins/common.ui/resources/css/dark.css
new file mode 100644
index 0000000..8e1a408
--- /dev/null
+++ b/plugins/common.ui/resources/css/dark.css
@@ -0,0 +1,40 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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. 
+ *  
+ */
+
+/* Overrides default preference values defined in CommonUIPreferencesInitializer */
+
+IEclipsePreferences#org-apache-directory-studio-common-ui {
+	preferences:
+		'defaultColor=255,255,255'       /* white        */
+		'disabledColor=192,192,192'      /* silver       */
+		'errorColor=255,69,0'            /* orangered    */
+		'commentColor=46,139,87'         /* seagren      */
+		'keyword1Color=192,192,192'      /* silver       */
+		'keyword2Color=201,105,30'       /* chocolate    */
+		'objectClassColor=50,205,50'     /* limegreen    */
+		'attributeTypeColor=238,130,238' /* violet       */
+		'oidColor=255,99,71'             /* tomato       */
+		'separatorColor=255,99,71'       /* tomato       */
+		'valueColor=135,206,250'         /* lightskyblu  */
+		'addColor=50,205,50'             /* limegreen    */
+		'deleteColor=255,69,0'           /* orangered    */
+		'modifyColor=218,165,32'         /* goldenrod    */
+		'renameColor=30,144,255'         /* dodgerblue   */
+}
diff --git a/plugins/common.ui/resources/css/default.css b/plugins/common.ui/resources/css/default.css
new file mode 100644
index 0000000..5ce69da
--- /dev/null
+++ b/plugins/common.ui/resources/css/default.css
@@ -0,0 +1,40 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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. 
+ *  
+ */
+
+/* Overrides default preference values defined in CommonUIPreferencesInitializer */
+
+IEclipsePreferences#org-apache-directory-studio-common-ui {
+	preferences:
+		'defaultColor=0,0,0'             /* black        */
+		'disabledColor=105,105,105'      /* dimgray      */
+		'errorColor=255,69,0'            /* orangered    */
+		'commentColor=143,188,143'       /* darkseegreen */
+		'keyword1Color=105,105,105'      /* dimgray      */
+		'keyword2Color=201,105,30'       /* chocolate    */
+		'objectClassColor=0,128,0'       /* green        */
+		'attributeTypeColor=128,0,128'   /* purple       */
+		'oidColor=255,0,0'               /* red          */
+		'separatorColor=255,0,0'         /* red          */
+		'valueColor=0,0,128'             /* navy         */
+		'addColor=50,205,50'             /* limegreen    */
+		'deleteColor=255,69,0'           /* orangered    */
+		'modifyColor=218,165,32'         /* goldenrod    */
+		'renameColor=30,144,255'         /* dodgerblue   */
+}
diff --git a/plugins/common.ui/src/main/java/org/apache/directory/studio/common/ui/CommonUIConstants.java b/plugins/common.ui/src/main/java/org/apache/directory/studio/common/ui/CommonUIConstants.java
index 958cb97..7b40661 100644
--- a/plugins/common.ui/src/main/java/org/apache/directory/studio/common/ui/CommonUIConstants.java
+++ b/plugins/common.ui/src/main/java/org/apache/directory/studio/common/ui/CommonUIConstants.java
@@ -20,9 +20,6 @@
 
 package org.apache.directory.studio.common.ui;
 
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.RGB;
-
 
 /**
  * Constants used in the connection UI plugin.
@@ -47,82 +44,25 @@
     /** The pull-down image */
     public static final String IMG_PULLDOWN = "resources/icons/pulldown.gif"; //$NON-NLS-1$
 
-    /** 
-     * The various colors in use. Each color have gradients, from black to white (ie from 0 to 255). We 
-     * use colors by increments of 31 :
-     * <ul>
-     * <li>0 : Black or no color</li>
-     * <li>31 : Black Dark color (BD_[color]) for instance BD_GREEN</li>
-     * <li>63 : Dark color (D_[color]) for instance D_GREEN</li>
-     * <li>95 : Mid Dark Color(MD_[color]) for instance MD_GREEN</li>
-     * <li>127 : Mid color (M_[color]), for instance M_GREEN</li>
-     * <li>159 : Mid Light color (ML_[color]), for instance ML_GREEN</li>
-     * <li>191 : Light color (L_[color]), for instance L_GREEN</li>
-     * <li>224 : White Light color (WL_[color]), for instance WL_GREEN</li>
-     * <li>255 : Full color ([color]), for instance GREEN</li>
-     * </ul>
-     **/
-    // To see the world in black and white
-    public static final RGB BLACK = new RGB( 0, 0, 0 );
-    public static Color BLACK_COLOR;
-    public static final RGB WHITE = new RGB( 255, 255, 255 );
-    public static Color WHITE_COLOR;
-    
-    // 7 shade of greys... From dark to light, with combinaisons
-    public static final RGB BD_GREY = new RGB( 31, 31, 31 );    // Black Dark grey
-    public static Color BD_GREY_COLOR;
-    public static final RGB D_GREY = new RGB( 63, 63, 63 );     // Dark grey
-    public static Color D_GREY_COLOR;
-    public static final RGB MD_GREY = new RGB( 95, 95, 95 );    // Medium Dark grey
-    public static Color MD_GREY_COLOR;
-    public static final RGB M_GREY = new RGB( 127, 127, 127 );  // Grey
-    public static Color M_GREY_COLOR;
-    public static final RGB ML_GREY = new RGB( 159, 159, 159 ); // Medium Light grey
-    public static Color ML_GREY_COLOR;
-    public static final RGB L_GREY = new RGB( 191, 191, 191 );  // Light grey
-    public static Color L_GREY_COLOR;
-    public static final RGB WL_GREY = new RGB( 224, 224, 224 ); // White Light grey
-    public static Color WL_GREY_COLOR;
-    
-    // Red
-    public static final RGB M_RED = new RGB( 127, 0, 0 );       // Medium red
-    public static Color M_RED_COLOR;
-    public static final RGB ML_RED = new RGB( 159, 0, 0 );      // Medium light red
-    public static Color ML_RED_COLOR;
-    public static final RGB RED = new RGB( 255, 0, 0 );         // Full red
-    public static Color RED_COLOR;
-    
-    // Green
-    public static final RGB M_GREEN = new RGB( 0, 127, 0 );     // Medium green
-    public static Color M_GREEN_COLOR;
-    public static final RGB ML_GREEN = new RGB( 0, 159, 0 );    // Medium Light green
-    public static Color ML_GREEN_COLOR;
-    public static final RGB GREEN = new RGB( 0, 255, 0 );       // Full green
-    public static Color GREEN_COLOR;
-    
-    // Blue
-    public static final RGB M_BLUE = new RGB( 0, 0, 127 );      // Medium blue
-    public static Color M_BLUE_COLOR;
-    public static final RGB L_BLUE = new RGB( 0, 0, 191 );      // Light blue 
-    public static Color L_BLUE_COLOR;
-    public static final RGB BLUE = new RGB( 0, 0, 255 );        // Full blue
-    public static Color BLUE_COLOR;
-    
-    // Purple
-    public static final RGB M_PURPLE = new RGB( 127, 0, 127 );  // Middle purple
-    public static Color M_PURPLE_COLOR;
-    public static final RGB PURPLE = new RGB( 255, 0, 255 );    // Full purple
-    public static Color PURPLE_COLOR;
+    /*
+     * Names of semantic colors. Actual color values are theme specific and defined in default.css and dark.css.
+     */
+    public static final String DEFAULT_COLOR = "defaultColor";
+    public static final String DISABLED_COLOR = "disabledColor";
+    public static final String ERROR_COLOR = "errorColor";
+    public static final String COMMENT_COLOR = "commentColor";
+    public static final String KEYWORD_1_COLOR = "keyword1Color";
+    public static final String KEYWORD_2_COLOR = "keyword2Color";
+    public static final String OBJECT_CLASS_COLOR = "objectClassColor";
+    public static final String ATTRIBUTE_TYPE_COLOR = "attributeTypeColor";
+    public static final String VALUE_COLOR = "valueColor";
+    public static final String OID_COLOR = "oidColor";
+    public static final String SEPARATOR_COLOR = "separatorColor";
+    public static final String ADD_COLOR = "addColor";
+    public static final String DELETE_COLOR = "deleteColor";
+    public static final String MODIFY_COLOR = "modifyColor";
+    public static final String RENAME_COLOR = "renameColor";
 
-    // Other colors
-    public static final RGB R0_G127_B255 = new RGB( 0, 127, 255 );
-    public static Color R0_G127_B255_COLOR;
-    public static final RGB R95_G63_B159 = new RGB( 95, 63, 159 );
-    public static Color R95_G63_B159_COLOR;
-    public static final RGB R63_G127_B63 = new RGB( 63, 127, 63 );
-    public static Color R63_G127_B63_COLOR;
-
-    // Some specific colors
-    
     public static final String IMG_INFORMATION = "resources/icons/information.gif"; //$NON-NLS-1$
+
 }
diff --git a/plugins/common.ui/src/main/java/org/apache/directory/studio/common/ui/CommonUIPlugin.java b/plugins/common.ui/src/main/java/org/apache/directory/studio/common/ui/CommonUIPlugin.java
index 4215e66..9cee28a 100644
--- a/plugins/common.ui/src/main/java/org/apache/directory/studio/common/ui/CommonUIPlugin.java
+++ b/plugins/common.ui/src/main/java/org/apache/directory/studio/common/ui/CommonUIPlugin.java
@@ -28,9 +28,14 @@
 import org.eclipse.core.runtime.FileLocator;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.jface.resource.ColorRegistry;
 import org.eclipse.jface.resource.ImageDescriptor;
 import org.eclipse.swt.graphics.Color;
 import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.ui.PlatformUI;
 import org.eclipse.ui.plugin.AbstractUIPlugin;
 import org.osgi.framework.BundleContext;
 
@@ -46,6 +51,8 @@
     /** The plugin properties */
     private PropertyResourceBundle properties;
 
+    /** The color registry */
+    private ColorRegistry colorRegistry;
 
     /**
      * The constructor
@@ -62,43 +69,11 @@
     public void start( BundleContext context ) throws Exception
     {
         super.start( context );
-        
-        // Create the colors we use
-        CommonUIConstants.BLACK_COLOR = new Color( null, CommonUIConstants.BLACK );
-        CommonUIConstants.WHITE_COLOR = new Color( null, CommonUIConstants.WHITE );
-        
-        // Greys
-        CommonUIConstants.BD_GREY_COLOR = new Color( null, CommonUIConstants.M_GREY );
-        CommonUIConstants.D_GREY_COLOR = new Color( null, CommonUIConstants.M_GREY );
-        CommonUIConstants.MD_GREY_COLOR = new Color( null, CommonUIConstants.M_GREY );
-        CommonUIConstants.M_GREY_COLOR = new Color( null, CommonUIConstants.M_GREY );
-        CommonUIConstants.ML_GREY_COLOR = new Color( null, CommonUIConstants.M_GREY );
-        CommonUIConstants.L_GREY_COLOR = new Color( null, CommonUIConstants.M_GREY );
-        CommonUIConstants.WL_GREY_COLOR = new Color( null, CommonUIConstants.M_GREY );
-        
-        // Reds
-        CommonUIConstants.M_RED_COLOR = new Color( null, CommonUIConstants.M_RED );
-        CommonUIConstants.ML_RED_COLOR = new Color( null, CommonUIConstants.ML_RED );
-        CommonUIConstants.RED_COLOR = new Color( null, CommonUIConstants.RED );
-        
-        // Greens
-        CommonUIConstants.M_GREEN_COLOR = new Color( null, CommonUIConstants.M_GREEN );
-        CommonUIConstants.ML_GREEN_COLOR = new Color( null, CommonUIConstants.ML_GREEN );
-        CommonUIConstants.GREEN_COLOR = new Color( null, CommonUIConstants.GREEN );
-        
-        // Blues
-        CommonUIConstants.M_BLUE_COLOR = new Color( null, CommonUIConstants.M_BLUE );
-        CommonUIConstants.L_BLUE_COLOR = new Color( null, CommonUIConstants.L_BLUE );
-        CommonUIConstants.BLUE_COLOR = new Color( null, CommonUIConstants.BLUE );
-        
-        // Purples
-        CommonUIConstants.M_PURPLE_COLOR = new Color( null, CommonUIConstants.M_PURPLE );
-        CommonUIConstants.PURPLE_COLOR = new Color( null, CommonUIConstants.PURPLE );
-        
-        // Other colors
-        CommonUIConstants.R0_G127_B255_COLOR = new Color( null, CommonUIConstants.R0_G127_B255 );
-        CommonUIConstants.R95_G63_B159_COLOR = new Color( null, CommonUIConstants.R95_G63_B159 );
-        CommonUIConstants.R63_G127_B63_COLOR = new Color( null, CommonUIConstants.R63_G127_B63 );
+
+        if ( colorRegistry == null )
+        {
+            colorRegistry = new ColorRegistry( PlatformUI.getWorkbench().getDisplay() );
+        }
     }
 
 
@@ -108,42 +83,11 @@
     public void stop( BundleContext context ) throws Exception
     {
         plugin = null;
-        
-        // Dispose the colors
-        CommonUIConstants.BLACK_COLOR.dispose();
-        CommonUIConstants.WHITE_COLOR.dispose();
-        
-        // greys
-        CommonUIConstants.M_GREY_COLOR.dispose();
-        CommonUIConstants.BD_GREY_COLOR.dispose();
-        CommonUIConstants.D_GREY_COLOR.dispose();
-        CommonUIConstants.MD_GREY_COLOR.dispose();
-        CommonUIConstants.M_GREY_COLOR.dispose();
-        CommonUIConstants.ML_GREY_COLOR.dispose();
-        CommonUIConstants.L_GREY_COLOR.dispose();
-        CommonUIConstants.WL_GREY_COLOR.dispose();
 
-        //Reds
-        CommonUIConstants.M_RED_COLOR.dispose();
-        CommonUIConstants.ML_RED_COLOR.dispose();
-        CommonUIConstants.RED_COLOR.dispose();
-        
-        // Greens
-        CommonUIConstants.M_GREEN_COLOR.dispose();
-        CommonUIConstants.ML_GREEN_COLOR.dispose();
-        CommonUIConstants.GREEN_COLOR.dispose();
-
-        // Blues
-        CommonUIConstants.M_BLUE_COLOR.dispose();
-        CommonUIConstants.L_BLUE_COLOR.dispose();
-        CommonUIConstants.BLUE_COLOR.dispose();
-        
-        // Purple
-        CommonUIConstants.M_PURPLE_COLOR.dispose();
-        CommonUIConstants.PURPLE_COLOR.dispose();
-        
-        // Other colors
-        CommonUIConstants.R0_G127_B255_COLOR.dispose();
+        if ( colorRegistry != null )
+        {
+            colorRegistry = null;
+        }
 
         super.stop( context );
     }
@@ -239,4 +183,45 @@
 
         return properties;
     }
+
+
+    /**
+     * Use this method to get SWT colors. A ColorRegistry is used to manage
+     * the RGB->Color mapping.
+     * <p>
+     * Note: Don't dispose the returned color. It is disposed automatically
+     * when the plugin is stopped.
+     *
+     * @param rgb the rgb color data
+     * @return The SWT Color
+     */
+    public Color getColor( RGB rgb )
+    {
+        if ( !colorRegistry.hasValueFor( rgb.toString() ) )
+        {
+            colorRegistry.put( rgb.toString(), rgb );
+        }
+
+        return colorRegistry.get( rgb.toString() );
+    }
+
+
+    /**
+     * Returns the current value of the color-valued preference with the
+     * given name in the preference store.
+     * Return <code>null</code> if it's the default, This is important
+     * to not override the system color when a high-contrast theme is used.
+     */
+    public Color getColor( String name )
+    {
+        IPreferenceStore store = getPreferenceStore();
+        if ( store.isDefault( name ) )
+        {
+            return null;
+        }
+        RGB rgb = PreferenceConverter.getColor( store, name );
+        Color color = getColor( rgb );
+        return color;
+    }
+
 }
diff --git a/plugins/common.ui/src/main/java/org/apache/directory/studio/common/ui/CommonUIPreferencesInitializer.java b/plugins/common.ui/src/main/java/org/apache/directory/studio/common/ui/CommonUIPreferencesInitializer.java
new file mode 100644
index 0000000..6bcaaa4
--- /dev/null
+++ b/plugins/common.ui/src/main/java/org/apache/directory/studio/common/ui/CommonUIPreferencesInitializer.java
@@ -0,0 +1,61 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.studio.common.ui;
+
+
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.jface.preference.IPreferenceStore;
+
+
+/**
+ * This class is used to set default preference values.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class CommonUIPreferencesInitializer extends AbstractPreferenceInitializer
+{
+    /**
+     * {@inheritDoc}
+     */
+    public void initializeDefaultPreferences()
+    {
+        IPreferenceStore store = CommonUIPlugin.getDefault().getPreferenceStore();
+
+        // Actual colors are defined in default.css and dark.css
+        String dflt = IPreferenceStore.STRING_DEFAULT_DEFAULT;
+        store.setDefault( CommonUIConstants.DEFAULT_COLOR, dflt );
+        store.setDefault( CommonUIConstants.DISABLED_COLOR, dflt );
+        store.setDefault( CommonUIConstants.ERROR_COLOR, dflt );
+        store.setDefault( CommonUIConstants.COMMENT_COLOR, dflt );
+        store.setDefault( CommonUIConstants.KEYWORD_1_COLOR, dflt );
+        store.setDefault( CommonUIConstants.KEYWORD_2_COLOR, dflt );
+        store.setDefault( CommonUIConstants.OBJECT_CLASS_COLOR, dflt );
+        store.setDefault( CommonUIConstants.ATTRIBUTE_TYPE_COLOR, dflt );
+        store.setDefault( CommonUIConstants.VALUE_COLOR, dflt );
+        store.setDefault( CommonUIConstants.OID_COLOR, dflt );
+        store.setDefault( CommonUIConstants.SEPARATOR_COLOR, dflt );
+        store.setDefault( CommonUIConstants.ADD_COLOR, dflt );
+        store.setDefault( CommonUIConstants.DELETE_COLOR, dflt );
+        store.setDefault( CommonUIConstants.MODIFY_COLOR, dflt );
+        store.setDefault( CommonUIConstants.RENAME_COLOR, dflt );
+    }
+
+}
diff --git a/plugins/connection.core/pom-first.xml b/plugins/connection.core/pom-first.xml
index 56255eb..91cd68c 100644
--- a/plugins/connection.core/pom-first.xml
+++ b/plugins/connection.core/pom-first.xml
@@ -55,7 +55,7 @@
             <Import-Package>
  org.apache.commons.lang3,
  org.apache.commons.lang3.exception,
- org.apache.commons.codec.digest",
+ org.apache.commons.codec.digest,
  org.apache.http.conn.ssl,
  org.dom4j,
  org.dom4j.io
diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ConnectionCorePlugin.java b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ConnectionCorePlugin.java
index ad6af27..e9d861e 100644
--- a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ConnectionCorePlugin.java
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ConnectionCorePlugin.java
@@ -41,7 +41,11 @@
 import org.eclipse.core.runtime.Platform;
 import org.eclipse.core.runtime.Plugin;
 import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.InstanceScope;
 import org.osgi.framework.BundleContext;
+import org.osgi.service.prefs.BackingStoreException;
 
 
 /**
@@ -95,7 +99,6 @@
     /** The plugin properties */
     private PropertyResourceBundle properties;
 
-
     /**
      * The constructor
      */
@@ -481,7 +484,8 @@
             connectionListeners = new ArrayList<IConnectionListener>();
 
             IExtensionRegistry registry = Platform.getExtensionRegistry();
-            IExtensionPoint extensionPoint = registry.getExtensionPoint( "org.apache.directory.studio.connectionlistener" ); //$NON-NLS-1$
+            IExtensionPoint extensionPoint = registry
+                .getExtensionPoint( "org.apache.directory.studio.connectionlistener" ); //$NON-NLS-1$
             IConfigurationElement[] members = extensionPoint.getConfigurationElements();
             for ( IConfigurationElement member : members )
             {
@@ -494,7 +498,8 @@
                 {
                     getLog().log(
                         new Status( IStatus.ERROR, ConnectionCoreConstants.PLUGIN_ID, 1,
-                            Messages.error__unable_to_create_connection_listener + member.getAttribute( "class" ), e ) ); //$NON-NLS-1$
+                            Messages.error__unable_to_create_connection_listener + member.getAttribute( "class" ), //$NON-NLS-1$
+                            e ) );
                 }
             }
         }
@@ -568,4 +573,98 @@
         return defaultKrb5LoginModule;
     }
 
+
+    public IEclipsePreferences getDefaultScopePreferences()
+    {
+        return DefaultScope.INSTANCE.getNode( ConnectionCoreConstants.PLUGIN_ID );
+    }
+
+
+    public void flushDefaultScopePreferences()
+    {
+        try
+        {
+            getDefaultScopePreferences().flush();
+        }
+        catch ( BackingStoreException e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
+
+
+    public IEclipsePreferences getInstanceScopePreferences()
+    {
+        return InstanceScope.INSTANCE.getNode( ConnectionCoreConstants.PLUGIN_ID );
+    }
+
+
+    public void flushInstanceScopePreferences()
+    {
+        try
+        {
+            getInstanceScopePreferences().flush();
+        }
+        catch ( BackingStoreException e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
+
+
+    public int getModificationLogsFileCount()
+    {
+        return Platform.getPreferencesService().getInt( ConnectionCoreConstants.PLUGIN_ID,
+            ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_COUNT, -1, null );
+    }
+
+
+    public int getModificationLogsFileSize()
+    {
+        return Platform.getPreferencesService().getInt( ConnectionCoreConstants.PLUGIN_ID,
+            ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_SIZE, -1, null );
+    }
+
+
+    public boolean isModificationLogsEnabled()
+    {
+        return Platform.getPreferencesService().getBoolean( ConnectionCoreConstants.PLUGIN_ID,
+            ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_ENABLE, true, null );
+    }
+
+
+    public String getMModificationLogsMaskedAttributes()
+    {
+        return Platform.getPreferencesService().getString( ConnectionCoreConstants.PLUGIN_ID,
+            ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_MASKED_ATTRIBUTES, null, null );
+    }
+
+
+    public int getSearchLogsFileCount()
+    {
+        return Platform.getPreferencesService().getInt( ConnectionCoreConstants.PLUGIN_ID,
+            ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_COUNT, -1, null );
+    }
+
+
+    public int getSearchLogsFileSize()
+    {
+        return Platform.getPreferencesService().getInt( ConnectionCoreConstants.PLUGIN_ID,
+            ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_SIZE, -1, null );
+    }
+
+
+    public boolean isSearchRequestLogsEnabled()
+    {
+        return Platform.getPreferencesService().getBoolean( ConnectionCoreConstants.PLUGIN_ID,
+            ConnectionCoreConstants.PREFERENCE_SEARCHREQUESTLOGS_ENABLE, true, null );
+    }
+
+
+    public boolean isSearchResultEntryLogsEnabled()
+    {
+        return Platform.getPreferencesService().getBoolean( ConnectionCoreConstants.PLUGIN_ID,
+            ConnectionCoreConstants.PREFERENCE_SEARCHRESULTENTRYLOGS_ENABLE, false, null );
+    }
+
 }
diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ConnectionCorePreferencesInitializer.java b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ConnectionCorePreferencesInitializer.java
index 7b4af45..35f7d3d 100644
--- a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ConnectionCorePreferencesInitializer.java
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ConnectionCorePreferencesInitializer.java
@@ -23,6 +23,7 @@
 
 import org.eclipse.core.runtime.Preferences;
 import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
 
 
 /**
@@ -38,6 +39,7 @@
     public void initializeDefaultPreferences()
     {
         Preferences preferences = ConnectionCorePlugin.getDefault().getPluginPreferences();
+        IEclipsePreferences defaultPreferences = ConnectionCorePlugin.getDefault().getDefaultScopePreferences();
 
         // LDAP connection settings
         preferences.setDefault( ConnectionCoreConstants.PREFERENCE_VALIDATE_CERTIFICATES, true );
@@ -46,18 +48,21 @@
         preferences.setDefault( ConnectionCoreConstants.PREFERENCE_USE_KRB5_SYSTEM_PROPERTIES, false );
 
         // Modification Logs
-        preferences.setDefault( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_ENABLE, true );
-        preferences.setDefault( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_COUNT, 10 );
-        preferences.setDefault( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_SIZE, 100 );
+        defaultPreferences.putBoolean( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_ENABLE, true );
+        defaultPreferences.put( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_MASKED_ATTRIBUTES, "" );
+        defaultPreferences.putInt( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_COUNT, 10 );
+        defaultPreferences.putInt( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_SIZE, 100 );
 
         // Search Logs
-        preferences.setDefault( ConnectionCoreConstants.PREFERENCE_SEARCHREQUESTLOGS_ENABLE, true );
-        preferences.setDefault( ConnectionCoreConstants.PREFERENCE_SEARCHRESULTENTRYLOGS_ENABLE, false );
-        preferences.setDefault( ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_COUNT, 10 );
-        preferences.setDefault( ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_SIZE, 100 );
+        defaultPreferences.putBoolean( ConnectionCoreConstants.PREFERENCE_SEARCHREQUESTLOGS_ENABLE, true );
+        defaultPreferences.putBoolean( ConnectionCoreConstants.PREFERENCE_SEARCHRESULTENTRYLOGS_ENABLE, false );
+        defaultPreferences.putInt( ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_COUNT, 10 );
+        defaultPreferences.putInt( ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_SIZE, 100 );
 
         // Connections Passwords Keystore
         preferences.setDefault( ConnectionCoreConstants.PREFERENCE_CONNECTIONS_PASSWORDS_KEYSTORE,
             ConnectionCoreConstants.PREFERENCE_CONNECTIONS_PASSWORDS_KEYSTORE_OFF );
+
+        ConnectionCorePlugin.getDefault().flushDefaultScopePreferences();
     }
 }
diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ConnectionFolderManager.java b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ConnectionFolderManager.java
index 84f4216..ee39b25 100644
--- a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ConnectionFolderManager.java
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ConnectionFolderManager.java
@@ -23,7 +23,6 @@
 
 import java.io.File;
 import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.ArrayList;
@@ -35,7 +34,8 @@
 import org.apache.directory.studio.connection.core.event.ConnectionEventRegistry;
 import org.apache.directory.studio.connection.core.event.ConnectionUpdateListener;
 import org.apache.directory.studio.connection.core.io.ConnectionIO;
-import org.apache.directory.studio.connection.core.io.ConnectionIOException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
 
 
 /**
@@ -365,21 +365,23 @@
      */
     private synchronized void saveConnectionFolders()
     {
+        File file = new File( getConnectionFolderStoreFileName() );
+        File tempFile = new File( getConnectionFolderStoreFileName() + ConnectionManager.TEMP_SUFFIX );
+
         // To avoid a corrupt file, save object to a temp file first 
-        try
+        try ( FileOutputStream fileOutputStream = new FileOutputStream( tempFile ) )
         {
-            ConnectionIO.saveConnectionFolders( folderList, new FileOutputStream( getConnectionFolderStoreFileName()
-                + ConnectionManager.TEMP_SUFFIX ) );
+            ConnectionIO.saveConnectionFolders( folderList, fileOutputStream );
         }
         catch ( IOException e )
         {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
+            Status status = new Status( IStatus.ERROR, ConnectionCoreConstants.PLUGIN_ID,
+                Messages.error__saving_connections + e.getMessage(), e );
+            ConnectionCorePlugin.getDefault().getLog().log( status );
+            return;
         }
 
         // move temp file to good file
-        File file = new File( getConnectionFolderStoreFileName() );
-        File tempFile = new File( getConnectionFolderStoreFileName() + ConnectionManager.TEMP_SUFFIX );
         if ( file.exists() )
         {
             file.delete();
@@ -392,8 +394,10 @@
         }
         catch ( IOException e )
         {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
+            Status status = new Status( IStatus.ERROR, ConnectionCoreConstants.PLUGIN_ID,
+                Messages.error__saving_connections + e.getMessage(), e );
+            ConnectionCorePlugin.getDefault().getLog().log( status );
+            return;
         }
     }
 
@@ -405,25 +409,18 @@
     {
         ConnectionEventRegistry.suspendEventFiringInCurrentThread();
 
-        try
+        File file = new File( getConnectionFolderStoreFileName() );
+        if ( file.exists() )
         {
-            folderList = ConnectionIO.loadConnectionFolders( new FileInputStream( getConnectionFolderStoreFileName() ) );
-        }
-        catch ( Exception e )
-        {
-            // If loading failed, try with temp file
-            try
+            try ( FileInputStream fileInputStream = new FileInputStream( file ) )
             {
-                folderList = ConnectionIO.loadConnectionFolders( new FileInputStream(
-                    getConnectionFolderStoreFileName() + ConnectionManager.TEMP_SUFFIX ) );
+                folderList = ConnectionIO.loadConnectionFolders( fileInputStream );
             }
-            catch ( FileNotFoundException e1 )
+            catch ( Exception e )
             {
-                // TODO Auto-generated catch block
-            }
-            catch ( ConnectionIOException e1 )
-            {
-                // TODO Auto-generated catch block
+                Status status = new Status( IStatus.ERROR, ConnectionCoreConstants.PLUGIN_ID,
+                    Messages.error__loading_connections + e.getMessage(), e );
+                ConnectionCorePlugin.getDefault().getLog().log( status );
             }
         }
 
diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ConnectionManager.java b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ConnectionManager.java
index af28362..d509d29 100644
--- a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ConnectionManager.java
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ConnectionManager.java
@@ -23,7 +23,6 @@
 
 import java.io.File;
 import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.HashSet;
@@ -33,7 +32,6 @@
 import org.apache.directory.studio.connection.core.event.ConnectionEventRegistry;
 import org.apache.directory.studio.connection.core.event.ConnectionUpdateListener;
 import org.apache.directory.studio.connection.core.io.ConnectionIO;
-import org.apache.directory.studio.connection.core.io.ConnectionIOException;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IConfigurationElement;
 import org.eclipse.core.runtime.IExtensionPoint;
@@ -360,29 +358,29 @@
     public synchronized void saveConnections()
     {
         Set<ConnectionParameter> connectionParameters = new HashSet<>();
-        
+
         for ( Connection connection : connectionList )
         {
             connectionParameters.add( connection.getConnectionParameter() );
         }
 
+        File file = new File( getConnectionStoreFileName() );
+        File tempFile = new File( getConnectionStoreFileName() + TEMP_SUFFIX );
+
         // To avoid a corrupt file, save object to a temp file first 
-        try
+        try ( FileOutputStream fileOutputStream = new FileOutputStream( tempFile ) )
         {
-            ConnectionIO
-                .save( connectionParameters, new FileOutputStream( getConnectionStoreFileName() + TEMP_SUFFIX ) );
+            ConnectionIO.save( connectionParameters, fileOutputStream );
         }
         catch ( IOException e )
         {
             Status status = new Status( IStatus.ERROR, ConnectionCoreConstants.PLUGIN_ID,
                 Messages.error__saving_connections + e.getMessage(), e );
             ConnectionCorePlugin.getDefault().getLog().log( status );
+            return;
         }
 
         // move temp file to good file
-        File file = new File( getConnectionStoreFileName() );
-        File tempFile = new File( getConnectionStoreFileName() + TEMP_SUFFIX );
-        
         if ( file.exists() )
         {
             file.delete();
@@ -398,6 +396,7 @@
             Status status = new Status( IStatus.ERROR, ConnectionCoreConstants.PLUGIN_ID,
                 Messages.error__saving_connections + e.getMessage(), e );
             ConnectionCorePlugin.getDefault().getLog().log( status );
+            return;
         }
     }
 
@@ -409,24 +408,14 @@
     {
         Set<ConnectionParameter> connectionParameters = null;
 
-        try
+        File file = new File( getConnectionStoreFileName() );
+        if ( file.exists() )
         {
-            connectionParameters = ConnectionIO.load( new FileInputStream( getConnectionStoreFileName() ) );
-        }
-        catch ( Exception e )
-        {
-            // If loading failed, try with temp file
-            try
+            try ( FileInputStream fileInputStream = new FileInputStream( file ) )
             {
-                connectionParameters = ConnectionIO.load( new FileInputStream( getConnectionStoreFileName()
-                    + TEMP_SUFFIX ) );
+                connectionParameters = ConnectionIO.load( fileInputStream );
             }
-            catch ( FileNotFoundException e1 )
-            {
-                // ignore, this is a fresh workspace
-                return;
-            }
-            catch ( ConnectionIOException e1 )
+            catch ( Exception e )
             {
                 Status status = new Status( IStatus.ERROR, ConnectionCoreConstants.PLUGIN_ID,
                     Messages.error__loading_connections + e.getMessage(), e );
diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ConnectionParameter.java b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ConnectionParameter.java
index caa01df..6ef9acf 100644
--- a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ConnectionParameter.java
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ConnectionParameter.java
@@ -55,6 +55,13 @@
 
         /** Encryption using Start TLS extension. */
         START_TLS
+
+        ;
+
+        public boolean isEncrytped()
+        {
+            return this != NONE;
+        }
     }
 
     /**
@@ -77,19 +84,16 @@
         SASL_CRAM_MD5(3),
 
         /** SASL authentication using GSSAPI. */
-        SASL_GSSAPI(4),
-        
-        /** SASL PLAIN authentication */
-        SASL_PLAIN(5);
-        
-        
+        SASL_GSSAPI(4);
+
         private int value;
-        
+
         private AuthenticationMethod( int value )
         {
             this.value = value;
         }
 
+
         public int getValue()
         {
             return value;
@@ -165,11 +169,10 @@
 
     /** The extended properties. */
     private Map<String, String> extendedProperties;
-    
+
     /** The connection timeout. Default to 30 seconds */
     private long timeoutMillis = 30000L;
 
-
     /**
      * Creates a new instance of ConnectionParameter.
      */
@@ -756,7 +759,7 @@
     public int getExtendedIntProperty( String key )
     {
         String s = extendedProperties.get( key );
-        
+
         if ( s != null )
         {
             return Integer.parseInt( s );
@@ -790,7 +793,7 @@
     public boolean getExtendedBoolProperty( String key )
     {
         String s = extendedProperties.get( key );
-        
+
         if ( s != null )
         {
             return Boolean.parseBoolean( s );
diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ILdapLogger.java b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ILdapLogger.java
index fd00f59..9e3dfee 100644
--- a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ILdapLogger.java
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/ILdapLogger.java
@@ -20,17 +20,23 @@
 package org.apache.directory.studio.connection.core;
 
 
+import java.io.File;
 import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
 
 import javax.naming.directory.SearchControls;
 
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.entry.Modification;
-import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.message.Referral;
 import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.api.util.Strings;
 import org.apache.directory.studio.connection.core.Connection.AliasDereferencingMethod;
+import org.apache.directory.studio.connection.core.io.StudioLdapException;
+import org.apache.directory.studio.connection.core.io.api.StudioSearchResult;
+import org.eclipse.core.runtime.Platform;
 
 
 /**
@@ -49,7 +55,10 @@
      * @param controls the controls
      * @param ex the LDAP exception if an error occurred, null otherwise
      */
-    void logChangetypeAdd( Connection connection, final Entry entry, final Control[] controls, LdapException ex );
+    default void logChangetypeAdd( Connection connection, final Entry entry, final Control[] controls,
+        StudioLdapException ex )
+    {
+    }
 
 
     /**
@@ -61,8 +70,11 @@
      * @param ex the LDAP exception if an error occurred, null otherwise
      * 
      */
-    void logChangetypeDelete( Connection connection, final Dn dn, final Control[] controls,
-        LdapException ex );
+    default void logChangetypeDelete( Connection connection, final Dn dn, final Control[] controls,
+        StudioLdapException ex )
+    {
+
+    }
 
 
     /**
@@ -74,8 +86,10 @@
      * @param ex the LDAP exception if an error occurred, null otherwise
      * @param controls the controls
      */
-    void logChangetypeModify( Connection connection, final Dn dn,
-        final Collection<Modification> modifications, final Control[] controls, LdapException ex );
+    default void logChangetypeModify( Connection connection, final Dn dn,
+        final Collection<Modification> modifications, final Control[] controls, StudioLdapException ex )
+    {
+    }
 
 
     /**
@@ -88,8 +102,10 @@
      * @param controls the controls
      * @param ex the LDAP exception if an error occurred, null otherwise
      */
-    void logChangetypeModDn( Connection connection, final Dn oldDn, final Dn newDn,
-        final boolean deleteOldRdn, final Control[] controls, LdapException ex );
+    default void logChangetypeModDn( Connection connection, final Dn oldDn, final Dn newDn,
+        final boolean deleteOldRdn, final Control[] controls, StudioLdapException ex )
+    {
+    }
 
 
     /**
@@ -152,9 +168,25 @@
      * @param requestNum the request number
      * @param ex the LDAP exception if an error occurred, null otherwise
      */
-    void logSearchRequest( Connection connection, String searchBase, String filter,
+    default void logSearchRequest( Connection connection, String searchBase, String filter,
         SearchControls searchControls, AliasDereferencingMethod aliasesDereferencingMethod,
-        Control[] controls, long requestNum, LdapException ex );
+        Control[] controls, long requestNum, StudioLdapException ex )
+    {
+    }
+
+
+    /**
+     * Logs a search result entry.
+     * 
+     * @param connection the connection
+     * @param studioSearchResult the search result entry
+     * @param requestNum the request number
+     * @param ex the LDAP exception if an error occurred, null otherwise
+     */
+    default void logSearchResultEntry( Connection connection, StudioSearchResult studioSearchResult, long requestNum,
+        StudioLdapException ex )
+    {
+    }
 
 
     /**
@@ -166,8 +198,10 @@
      * @param requestNum the request number
      * @param ex the LDAP exception if an error occurred, null otherwise
      */
-    void logSearchResultReference( Connection connection, Referral referral,
-        ReferralsInfo referralsInfo, long requestNum, LdapException ex );
+    default void logSearchResultReference( Connection connection, Referral referral,
+        ReferralsInfo referralsInfo, long requestNum, StudioLdapException ex )
+    {
+    }
 
 
     /**
@@ -178,6 +212,53 @@
      * @param requestNum the request number
      * @param ex the LDAP exception if an error occurred, null otherwise
      */
-    void logSearchResultDone( Connection connection, long count, long requestNum, LdapException ex );
+    default void logSearchResultDone( Connection connection, long count, long requestNum, StudioLdapException ex )
+    {
+    }
 
+    /**
+     * Gets the masked attributes.
+     * 
+     * @return the masked attributes
+     */
+    default Set<String> getMaskedAttributes()
+    {
+        Set<String> maskedAttributes = new HashSet<String>();
+
+        String maskedAttributeString = Platform.getPreferencesService().getString( ConnectionCoreConstants.PLUGIN_ID,
+            ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_MASKED_ATTRIBUTES, "", null );
+        String[] splitted = maskedAttributeString.split( "," ); //$NON-NLS-1$
+
+        for ( String s : splitted )
+        {
+            maskedAttributes.add( Strings.toLowerCaseAscii( s ) );
+        }
+
+        return maskedAttributes;
+    }
+
+
+    /**
+     * Deletes a file. Retries up to 5 times to work around Windows file delete issues.
+     */
+    default void deleteFileWithRetry( File file )
+    {
+        for ( int i = 0; i < 6; i++ )
+        {
+            if ( file != null && file.exists() )
+            {
+                if ( file.delete() )
+                {
+                    break;
+                }
+                try
+                {
+                    Thread.sleep( 500L );
+                }
+                catch ( InterruptedException e )
+                {
+                }
+            }
+        }
+    }
 }
diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/Messages.java b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/Messages.java
index 865636c..9f6bd9c 100644
--- a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/Messages.java
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/Messages.java
@@ -89,5 +89,6 @@
 
     public static String DirectoryApiConnectionWrapper_NoConnection;
     public static String DirectoryApiConnectionWrapper_UnableToConnect;
+    public static String DirectoryApiConnectionWrapper_UnsecuredConnection;
 
 }
diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/event/ConnectionEventRegistry.java b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/event/ConnectionEventRegistry.java
index 39e759b..c0e9ab7 100644
--- a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/event/ConnectionEventRegistry.java
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/event/ConnectionEventRegistry.java
@@ -92,7 +92,7 @@
 
                 fireTimeStamps.add( now );
 
-                if ( fireTimeStamps.size() > 5 )
+                if ( fireTimeStamps.size() > 10 )
                 {
                     String message = "Warning: More then " + fireTimeStamps.size() + " events were fired per second!"; //$NON-NLS-1$ //$NON-NLS-2$
                     ConnectionCorePlugin.getDefault().getLog().log(
diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/ConnectionWrapper.java b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/ConnectionWrapper.java
index 3c6f919..51194dd 100644
--- a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/ConnectionWrapper.java
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/ConnectionWrapper.java
@@ -23,6 +23,7 @@
 import java.util.Collection;
 
 import javax.naming.directory.SearchControls;
+import javax.net.ssl.SSLSession;
 
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.entry.Modification;
@@ -31,9 +32,9 @@
 import org.apache.directory.api.ldap.model.message.ExtendedResponse;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.studio.common.core.jobs.StudioProgressMonitor;
-import org.apache.directory.studio.connection.core.ReferralsInfo;
 import org.apache.directory.studio.connection.core.Connection.AliasDereferencingMethod;
 import org.apache.directory.studio.connection.core.Connection.ReferralHandlingMethod;
+import org.apache.directory.studio.connection.core.ReferralsInfo;
 import org.apache.directory.studio.connection.core.io.api.StudioSearchResultEnumeration;
 
 
@@ -81,6 +82,22 @@
 
 
     /**
+     * Checks if the connection is secured.
+     * 
+     * @return true, if is secured
+     */
+    boolean isSecured();
+
+
+    /**
+     * Gets the {@link SSLSession} associated with the connection.
+     * 
+     * @return the {@link SSLSession} associated with the connection or null if the connection is not secured
+     */
+    SSLSession getSslSession();
+
+
+    /**
      * Sets the binary attributes.
      * 
      * @param binaryAttributes the binary attributes
diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/StudioLdapException.java b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/StudioLdapException.java
new file mode 100644
index 0000000..4057a4d
--- /dev/null
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/StudioLdapException.java
@@ -0,0 +1,74 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.studio.connection.core.io;
+
+
+import java.util.Locale;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.exception.ExceptionUtils;
+import org.apache.directory.api.ldap.model.exception.LdapContextNotEmptyException;
+import org.apache.directory.api.ldap.model.exception.LdapEntryAlreadyExistsException;
+import org.apache.directory.api.ldap.model.exception.LdapOperationException;
+import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
+
+
+public class StudioLdapException extends Exception
+{
+    private static final long serialVersionUID = -1L;
+
+    public StudioLdapException( Exception exception )
+    {
+        super( exception );
+    }
+
+
+    @Override
+    public String getMessage()
+    {
+        String message = "";
+        Throwable cause = getCause();
+        if ( cause instanceof LdapOperationException )
+        {
+            LdapOperationException loe = ( LdapOperationException ) cause;
+            ResultCodeEnum rc = loe.getResultCode();
+            String template = " [LDAP result code %d - %s]"; //$NON-NLS-1$
+            message += String.format( Locale.ROOT, template, rc.getResultCode(), rc.getMessage() );
+        }
+        if ( StringUtils.isNotBlank( cause.getMessage() ) )
+        {
+            message += " " + cause.getMessage(); //$NON-NLS-1$
+        }
+        return message;
+    }
+
+
+    public static boolean isEntryAlreadyExistsException( Exception exception )
+    {
+        return ExceptionUtils.indexOfThrowable( exception, LdapEntryAlreadyExistsException.class ) > -1;
+    }
+
+
+    public static boolean isContextNotEmptyException( Exception exception )
+    {
+        return ExceptionUtils.indexOfThrowable( exception, LdapContextNotEmptyException.class ) > -1;
+    }
+
+}
diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/StudioTrustManager.java b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/StudioTrustManager.java
index dada4d0..5edb0e1 100644
--- a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/StudioTrustManager.java
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/StudioTrustManager.java
@@ -54,7 +54,6 @@
     private X509TrustManager jvmTrustManager;
     private String host;
 
-
     /**
      * Creates a new instance of StudioTrustManager.
      * 
diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/api/DirectoryApiConnectionWrapper.java b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/api/DirectoryApiConnectionWrapper.java
index b7ebdb3..049888b 100644
--- a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/api/DirectoryApiConnectionWrapper.java
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/api/DirectoryApiConnectionWrapper.java
@@ -25,8 +25,10 @@
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
 
 import javax.naming.directory.SearchControls;
+import javax.net.ssl.SSLSession;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.TrustManagerFactory;
 import javax.net.ssl.X509TrustManager;
@@ -74,7 +76,6 @@
 import org.apache.directory.ldap.client.api.SaslCramMd5Request;
 import org.apache.directory.ldap.client.api.SaslDigestMd5Request;
 import org.apache.directory.ldap.client.api.SaslGssApiRequest;
-import org.apache.directory.ldap.client.api.SaslPlainRequest;
 import org.apache.directory.ldap.client.api.exception.InvalidConnectionException;
 import org.apache.directory.studio.common.core.jobs.StudioProgressMonitor;
 import org.apache.directory.studio.connection.core.Connection;
@@ -91,6 +92,7 @@
 import org.apache.directory.studio.connection.core.ReferralsInfo;
 import org.apache.directory.studio.connection.core.io.ConnectionWrapper;
 import org.apache.directory.studio.connection.core.io.ConnectionWrapperUtils;
+import org.apache.directory.studio.connection.core.io.StudioLdapException;
 import org.apache.directory.studio.connection.core.io.StudioTrustManager;
 import org.eclipse.core.runtime.Preferences;
 import org.eclipse.osgi.util.NLS;
@@ -106,34 +108,18 @@
     /** The search request number */
     private static int searchRequestNum = 0;
 
-    /** The connection*/
+    /** The Studio connection  */
     private Connection connection;
 
-    /** The LDAP Connection Configuration */
-    private LdapConnectionConfig ldapConnectionConfig;
-
-    /** The LDAP Connection */
+    /** The LDAP connection */
     private LdapNetworkConnection ldapConnection;
 
     /** The binary attribute detector */
     private DefaultConfigurableBinaryAttributeDetector binaryAttributeDetector;
 
-    /** Indicates if the wrapper is connected */
-    private boolean isConnected = false;
-
     /** The current job thread */
     private Thread jobThread;
 
-    /** The bind principal */
-    private String bindPrincipal;
-
-    /** The bind password */
-    private String bindPassword;
-
-    /** The SASL PLAIN authzid */
-    private String authzId;
-
-
     /**
      * Creates a new instance of DirectoryApiConnectionWrapper.
      * 
@@ -151,7 +137,6 @@
     public void connect( StudioProgressMonitor monitor )
     {
         ldapConnection = null;
-        isConnected = false;
         jobThread = null;
 
         try
@@ -169,9 +154,8 @@
     private void doConnect( final StudioProgressMonitor monitor ) throws Exception
     {
         ldapConnection = null;
-        isConnected = true;
 
-        ldapConnectionConfig = new LdapConnectionConfig();
+        LdapConnectionConfig ldapConnectionConfig = new LdapConnectionConfig();
         ldapConnectionConfig.setLdapHost( connection.getHost() );
         ldapConnectionConfig.setLdapPort( connection.getPort() );
 
@@ -187,6 +171,8 @@
         binaryAttributeDetector = new DefaultConfigurableBinaryAttributeDetector();
         ldapConnectionConfig.setBinaryAttributeDetector( binaryAttributeDetector );
 
+        AtomicReference<StudioTrustManager> studioTrustmanager = new AtomicReference<>();
+
         if ( ( connection.getEncryptionMethod() == EncryptionMethod.LDAPS )
             || ( connection.getEncryptionMethod() == EncryptionMethod.START_TLS ) )
         {
@@ -209,6 +195,7 @@
                     trustManagers[i] = new StudioTrustManager( ( X509TrustManager ) defaultTrustManagers[i] );
                     trustManagers[i].setHost( connection.getHost() );
                 }
+                studioTrustmanager.set( trustManagers[0] );
 
                 ldapConnectionConfig.setTrustManagers( trustManagers );
             }
@@ -223,6 +210,12 @@
         {
             public void run()
             {
+                /*
+                 * Use local temp variable while the connection is being established and secured.
+                 * This process can take a while and the user might be asked to inspect the server
+                 * certificate. During that process the connection must not be used.
+                 */
+                LdapNetworkConnection ldapConnectionUnderConstruction = null;
                 try
                 {
                     // Set lower timeout for connecting
@@ -230,26 +223,45 @@
                     ldapConnectionConfig.setTimeout( Math.min( oldTimeout, 5000L ) );
 
                     // Connecting
-                    ldapConnection = new LdapNetworkConnection( ldapConnectionConfig );
-                    boolean connected = ldapConnection.connect();
+                    ldapConnectionUnderConstruction = new LdapNetworkConnection( ldapConnectionConfig );
+                    ldapConnectionUnderConstruction.connect();
 
-                    if ( !connected )
+                    // DIRSTUDIO-1219: Establish TLS layer if TLS is enabled and SSL is not
+                    if ( ldapConnectionConfig.isUseTls() && !ldapConnectionConfig.isUseSsl() )
+                    {
+                        ldapConnectionUnderConstruction.startTls();
+                    }
+
+                    // Set original timeout again
+                    ldapConnectionConfig.setTimeout( oldTimeout );
+                    ldapConnectionUnderConstruction.setTimeOut( oldTimeout );
+
+                    // Now set the LDAP connection once the (optional) security layer is in place
+                    ldapConnection = ldapConnectionUnderConstruction;
+
+                    if ( !isConnected() )
                     {
                         throw new Exception( Messages.DirectoryApiConnectionWrapper_UnableToConnect );
                     }
 
-                    // Set old timeout again
-                    ldapConnectionConfig.setTimeout( oldTimeout );
+                    // DIRSTUDIO-1219: Verify secure connection if ldaps:// or StartTLS is configured
+                    if ( ldapConnectionConfig.isUseTls() || ldapConnectionConfig.isUseSsl() )
+                    {
+                        if ( !isSecured() )
+                        {
+                            throw new Exception( Messages.DirectoryApiConnectionWrapper_UnsecuredConnection );
+                        }
+                    }
                 }
                 catch ( Exception e )
                 {
-                    exception = e;
+                    exception = toStudioLdapException( e );
 
                     try
                     {
-                        if ( ldapConnection != null )
+                        if ( ldapConnectionUnderConstruction != null )
                         {
-                            ldapConnection.close();
+                            ldapConnectionUnderConstruction.close();
                         }
                     }
                     catch ( Exception exception )
@@ -298,7 +310,6 @@
             ldapConnection = null;
             binaryAttributeDetector = null;
         }
-        isConnected = false;
     }
 
 
@@ -329,26 +340,9 @@
     }
 
 
-    private BindResponse bindSaslPlain() throws LdapException
-    {
-        SaslPlainRequest saslPlainRequest = new SaslPlainRequest();
-        saslPlainRequest.setUsername( bindPrincipal );
-        saslPlainRequest.setCredentials( bindPassword );
-        saslPlainRequest.setAuthorizationId( authzId );
-        saslPlainRequest
-            .setQualityOfProtection( connection.getConnectionParameter().getSaslQop() );
-        saslPlainRequest.setSecurityStrength( connection.getConnectionParameter()
-            .getSaslSecurityStrength() );
-        saslPlainRequest.setMutualAuthentication( connection.getConnectionParameter()
-            .isSaslMutualAuthentication() );
-
-        return ldapConnection.bindSaslPlain( bindPrincipal, bindPassword, authzId );
-    }
-
-
     private void doBind( final StudioProgressMonitor monitor ) throws Exception
     {
-        if ( ldapConnection != null && isConnected )
+        if ( isConnected() )
         {
             InnerRunnable runnable = new InnerRunnable()
             {
@@ -391,21 +385,14 @@
                                 monitor.reportError( Messages.model__no_credentials, exception );
                                 throw exception;
                             }
-                            bindPrincipal = credentials.getBindPrincipal();
-                            bindPassword = credentials.getBindPassword();
+                            String bindPrincipal = credentials.getBindPrincipal();
+                            String bindPassword = credentials.getBindPassword();
 
                             switch ( connection.getConnectionParameter().getAuthMethod() )
                             {
                                 case SIMPLE:
                                     // Simple Authentication
                                     bindResponse = bindSimple( bindPrincipal, bindPassword );
-
-                                    break;
-
-                                case SASL_PLAIN:
-                                    // SASL Plain authentication
-                                    bindResponse = bindSaslPlain();
-
                                     break;
 
                                 case SASL_CRAM_MD5:
@@ -493,7 +480,7 @@
                     }
                     catch ( Exception e )
                     {
-                        exception = e;
+                        exception = toStudioLdapException( e );
                     }
                 }
             };
@@ -533,6 +520,22 @@
     /**
      * {@inheritDoc}
      */
+    public boolean isSecured()
+    {
+        return isConnected() && ldapConnection.isSecured();
+    }
+
+
+    @Override
+    public SSLSession getSslSession()
+    {
+        return isConnected() ? ldapConnection.getSslSession() : null;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
     public void setBinaryAttributes( Collection<String> binaryAttributes )
     {
         if ( binaryAttributeDetector != null )
@@ -593,23 +596,21 @@
                 }
                 catch ( Exception e )
                 {
-                    exception = e;
+                    exception = toStudioLdapException( e );
                 }
 
-                LdapException le = toLdapException( exception );
-
                 for ( ILdapLogger logger : getLdapLoggers() )
                 {
                     if ( searchResultEnumeration != null )
                     {
                         logger.logSearchRequest( connection, searchBase, filter, searchControls,
-                            aliasesDereferencingMethod, controls, requestNum, le );
+                            aliasesDereferencingMethod, controls, requestNum, exception );
                     }
                     else
                     {
                         logger.logSearchRequest( connection, searchBase, filter, searchControls,
-                            aliasesDereferencingMethod, controls, requestNum, le );
-                        logger.logSearchResultDone( connection, 0, requestNum, le );
+                            aliasesDereferencingMethod, controls, requestNum, exception );
+                        logger.logSearchResultDone( connection, 0, requestNum, exception );
                     }
                 }
             }
@@ -750,14 +751,12 @@
                 }
                 catch ( Exception e )
                 {
-                    exception = e;
+                    exception = toStudioLdapException( e );
                 }
 
-                LdapException le = toLdapException( exception );
-
                 for ( ILdapLogger logger : getLdapLoggers() )
                 {
-                    logger.logChangetypeModify( connection, dn, modifications, controls, le );
+                    logger.logChangetypeModify( connection, dn, modifications, controls, exception );
                 }
             }
         };
@@ -831,14 +830,12 @@
                 }
                 catch ( Exception e )
                 {
-                    exception = e;
+                    exception = toStudioLdapException( e );
                 }
 
-                LdapException le = toLdapException( exception );
-
                 for ( ILdapLogger logger : getLdapLoggers() )
                 {
-                    logger.logChangetypeModDn( connection, oldDn, newDn, deleteOldRdn, controls, le );
+                    logger.logChangetypeModDn( connection, oldDn, newDn, deleteOldRdn, controls, exception );
                 }
             }
         };
@@ -912,14 +909,12 @@
                 }
                 catch ( Exception e )
                 {
-                    exception = e;
+                    exception = toStudioLdapException( e );
                 }
 
-                LdapException le = toLdapException( exception );
-
                 for ( ILdapLogger logger : getLdapLoggers() )
                 {
-                    logger.logChangetypeAdd( connection, entry, controls, le );
+                    logger.logChangetypeAdd( connection, entry, controls, exception );
                 }
             }
         };
@@ -990,14 +985,12 @@
                 }
                 catch ( Exception e )
                 {
-                    exception = e;
+                    exception = toStudioLdapException( e );
                 }
 
-                LdapException le = toLdapException( exception );
-
                 for ( ILdapLogger logger : getLdapLoggers() )
                 {
-                    logger.logChangetypeDelete( connection, dn, controls, le );
+                    logger.logChangetypeDelete( connection, dn, controls, exception );
                 }
             }
         };
@@ -1021,6 +1014,7 @@
         }
     }
 
+
     @Override
     public ExtendedResponse extended( ExtendedRequest request, StudioProgressMonitor monitor )
     {
@@ -1049,12 +1043,9 @@
                 }
                 catch ( Exception e )
                 {
-                    exception = e;
+                    exception = toStudioLdapException( e );
                 }
 
-                // TODO: logging?
-                LdapException le = toLdapException( exception );
-
                 for ( ILdapLogger logger : getLdapLoggers() )
                 {
                 }
@@ -1090,10 +1081,9 @@
     abstract class InnerRunnable implements Runnable
     {
         protected StudioSearchResultEnumeration searchResultEnumeration = null;
-        protected Exception exception = null;
+        protected StudioLdapException exception = null;
         protected boolean canceled = false;
 
-
         /**
          * Gets the exception.
          * 
@@ -1146,7 +1136,6 @@
 
     }
 
-
     private boolean checkAndHandleReferral( ResultResponse response, StudioProgressMonitor monitor,
         ReferralsInfo referralsInfo, ReferralHandlingDataConsumer consumer ) throws LdapException
     {
@@ -1192,7 +1181,6 @@
         String referralDn;
         ReferralsInfo newReferralsInfo;
 
-
         ReferralHandlingData( ConnectionWrapper connectionWrapper, String referralDn, ReferralsInfo newReferralsInfo )
         {
             this.connectionWrapper = connectionWrapper;
@@ -1201,12 +1189,11 @@
         }
     }
 
-
     private void checkConnectionAndRunAndMonitor( final InnerRunnable runnable, final StudioProgressMonitor monitor )
         throws Exception
     {
         // check connection
-        if ( !isConnected || ldapConnection == null )
+        if ( !isConnected() )
         {
             doConnect( monitor );
             doBind( monitor );
@@ -1260,11 +1247,8 @@
                         {
                         }
 
-                        isConnected = false;
                         ldapConnection = null;
                     }
-
-                    isConnected = false;
                 }
             };
 
@@ -1294,7 +1278,6 @@
         private String krb5LoginModule;
         private AppConfigurationEntry[] configList = null;
 
-
         public InnerConfiguration( String krb5LoginModule )
         {
             this.krb5LoginModule = krb5LoginModule;
@@ -1333,7 +1316,6 @@
         }
     }
 
-
     private List<ILdapLogger> getLdapLoggers()
     {
         return ConnectionCorePlugin.getDefault().getLdapLoggers();
@@ -1357,7 +1339,7 @@
     }
 
 
-    private LdapException toLdapException( Exception exception )
+    private StudioLdapException toStudioLdapException( Exception exception )
     {
         if ( exception == null )
         {
@@ -1365,11 +1347,11 @@
         }
         else if ( exception instanceof LdapException )
         {
-            return ( LdapException ) exception;
+            return new StudioLdapException( ( LdapException ) exception );
         }
         else
         {
-            return new LdapException( exception.getMessage(), exception );
+            return new StudioLdapException( exception );
         }
     }
 
diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/api/LdifModificationLogger.java b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/api/LdifModificationLogger.java
index ee73cd0..8144b62 100644
--- a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/api/LdifModificationLogger.java
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/api/LdifModificationLogger.java
@@ -23,15 +23,15 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.lang.reflect.Field;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Date;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+import java.util.StringJoiner;
 import java.util.logging.FileHandler;
 import java.util.logging.Formatter;
 import java.util.logging.Handler;
@@ -39,26 +39,21 @@
 import java.util.logging.LogRecord;
 import java.util.logging.Logger;
 
-import javax.naming.directory.SearchControls;
-
 import org.apache.directory.api.ldap.model.entry.Attribute;
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.entry.Modification;
 import org.apache.directory.api.ldap.model.entry.Value;
-import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.message.Control;
-import org.apache.directory.api.ldap.model.message.Referral;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.name.Rdn;
 import org.apache.directory.api.util.Strings;
 import org.apache.directory.studio.connection.core.Connection;
-import org.apache.directory.studio.connection.core.Connection.AliasDereferencingMethod;
 import org.apache.directory.studio.connection.core.ConnectionCoreConstants;
 import org.apache.directory.studio.connection.core.ConnectionCorePlugin;
 import org.apache.directory.studio.connection.core.ConnectionManager;
 import org.apache.directory.studio.connection.core.Controls;
 import org.apache.directory.studio.connection.core.ILdapLogger;
-import org.apache.directory.studio.connection.core.ReferralsInfo;
+import org.apache.directory.studio.connection.core.io.StudioLdapException;
 import org.apache.directory.studio.ldifparser.LdifFormatParameters;
 import org.apache.directory.studio.ldifparser.model.container.LdifChangeAddRecord;
 import org.apache.directory.studio.ldifparser.model.container.LdifChangeDeleteRecord;
@@ -76,8 +71,9 @@
 import org.apache.directory.studio.ldifparser.model.lines.LdifNewrdnLine;
 import org.apache.directory.studio.ldifparser.model.lines.LdifNewsuperiorLine;
 import org.apache.directory.studio.ldifparser.model.lines.LdifSepLine;
-import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
-import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.InstanceScope;
 
 
 /**
@@ -103,52 +99,48 @@
     /** The loggers. */
     private Map<String, Logger> loggers = new HashMap<String, Logger>();
 
-
     /**
      * Creates a new instance of LdifModificationLogger.
      */
     public LdifModificationLogger()
     {
-        ConnectionCorePlugin.getDefault().getPluginPreferences().addPropertyChangeListener(
-            new IPropertyChangeListener()
+        IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode( ConnectionCoreConstants.PLUGIN_ID );
+        prefs.addPreferenceChangeListener( event -> {
+            if ( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_COUNT.equals( event.getKey() )
+                || ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_SIZE.equals( event.getKey() ) )
             {
-                public void propertyChange( PropertyChangeEvent event )
+                // dispose all loggers/handlers
+                for ( Logger logger : loggers.values() )
                 {
-                    if ( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_COUNT.equals( event.getProperty() )
-                        || ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_SIZE.equals( event.getProperty() ) )
+                    for ( Handler handler : logger.getHandlers() )
                     {
-                        // dispose all loggers/handlers
-                        for ( Logger logger : loggers.values() )
-                        {
-                            for ( Handler handler : logger.getHandlers() )
-                            {
-                                handler.close();
-                            }
-                        }
-
-                        // delete files with index greater than new file count
-                        for ( FileHandler fh : fileHandlers.values() )
-                        {
-                            try
-                            {
-                                File[] logFiles = getLogFiles( fh );
-                                for ( int i = getFileCount(); i < logFiles.length; i++ )
-                                {
-                                    if ( logFiles[i] != null && logFiles[i].exists() )
-                                    {
-                                        logFiles[i].delete();
-                                    }
-                                }
-                            }
-                            catch ( Exception e )
-                            {
-                            }
-                        }
-
-                        loggers.clear();
+                        handler.close();
                     }
                 }
-            } );
+
+                // delete files with index greater than new file count
+                Connection[] connections = ConnectionCorePlugin.getDefault().getConnectionManager().getConnections();
+                for ( Connection connection : connections )
+                {
+                    try
+                    {
+                        File[] logFiles = getLogFiles( connection );
+                        for ( int i = getFileCount(); i < logFiles.length; i++ )
+                        {
+                            if ( logFiles[i] != null && logFiles[i].exists() )
+                            {
+                                logFiles[i].delete();
+                            }
+                        }
+                    }
+                    catch ( Exception e )
+                    {
+                    }
+                }
+
+                loggers.clear();
+            }
+        } );
     }
 
 
@@ -202,12 +194,18 @@
                 handler.close();
             }
 
+            File[] files = getLogFiles( connection );
+            for ( File file : files )
+            {
+                deleteFileWithRetry( file );
+            }
+
             loggers.remove( id );
         }
     }
 
 
-    private void log( String text, LdapException ex, Connection connection )
+    private void log( String text, StudioLdapException ex, Connection connection )
     {
         String id = connection.getId();
         if ( !loggers.containsKey( id ) )
@@ -220,28 +218,26 @@
 
         if ( loggers.containsKey( id ) )
         {
-            Logger logger = loggers.get( id );
+            StringJoiner lines = new StringJoiner( "" );
             DateFormat df = new SimpleDateFormat( ConnectionCoreConstants.DATEFORMAT );
             df.setTimeZone( ConnectionCoreConstants.UTC_TIME_ZONE );
 
             if ( ex != null )
             {
-                logger.log( Level.ALL, LdifCommentLine
+                lines.add( LdifCommentLine
                     .create( "#!RESULT ERROR" ).toFormattedString( LdifFormatParameters.DEFAULT ) ); //$NON-NLS-1$
             }
             else
             {
-                logger.log( Level.ALL, LdifCommentLine
+                lines.add( LdifCommentLine
                     .create( "#!RESULT OK" ).toFormattedString( LdifFormatParameters.DEFAULT ) ); //$NON-NLS-1$
             }
 
-            logger
-                .log(
-                    Level.ALL,
-                    LdifCommentLine
-                        .create( "#!CONNECTION ldap://" + connection.getHost() + ":" + connection.getPort() ) //$NON-NLS-1$//$NON-NLS-2$
-                        .toFormattedString( LdifFormatParameters.DEFAULT ) );
-            logger.log( Level.ALL, LdifCommentLine
+            lines.add(
+                LdifCommentLine
+                    .create( "#!CONNECTION ldap://" + connection.getHost() + ":" + connection.getPort() ) //$NON-NLS-1$//$NON-NLS-2$
+                    .toFormattedString( LdifFormatParameters.DEFAULT ) );
+            lines.add( LdifCommentLine
                 .create( "#!DATE " + df.format( new Date() ) ).toFormattedString( LdifFormatParameters.DEFAULT ) ); //$NON-NLS-1$
 
             if ( ex != null )
@@ -250,10 +246,12 @@
                 errorComment = errorComment.replaceAll( "\r", " " ); //$NON-NLS-1$ //$NON-NLS-2$
                 errorComment = errorComment.replaceAll( "\n", " " ); //$NON-NLS-1$ //$NON-NLS-2$
                 LdifCommentLine errorCommentLine = LdifCommentLine.create( errorComment );
-                logger.log( Level.ALL, errorCommentLine.toFormattedString( LdifFormatParameters.DEFAULT ) );
+                lines.add( errorCommentLine.toFormattedString( LdifFormatParameters.DEFAULT ) );
             }
 
-            logger.log( Level.ALL, text );
+            lines.add( text );
+            Logger logger = loggers.get( id );
+            logger.log( Level.ALL, lines.toString() );
         }
     }
 
@@ -261,7 +259,8 @@
     /**
      * {@inheritDoc}
      */
-    public void logChangetypeAdd( Connection connection, final Entry entry, final Control[] controls, LdapException ex )
+    public void logChangetypeAdd( Connection connection, final Entry entry, final Control[] controls,
+        StudioLdapException ex )
     {
         if ( !isModificationLogEnabled() )
         {
@@ -277,7 +276,7 @@
             String attributeName = attribute.getUpId();
             for ( Value value : attribute )
             {
-                if ( maskedAttributes.contains( Strings.toLowerCase( attributeName ) ) )
+                if ( maskedAttributes.contains( Strings.toLowerCaseAscii( attributeName ) ) )
                 {
                     record.addAttrVal( LdifAttrValLine.create( attributeName, "**********" ) ); //$NON-NLS-1$
                 }
@@ -305,7 +304,7 @@
      * {@inheritDoc}
      */
     public void logChangetypeDelete( Connection connection, final Dn dn, final Control[] controls,
-        LdapException ex )
+        StudioLdapException ex )
     {
         if ( !isModificationLogEnabled() )
         {
@@ -326,7 +325,7 @@
      * {@inheritDoc}
      */
     public void logChangetypeModify( Connection connection, final Dn dn,
-        final Collection<Modification> modifications, final Control[] controls, LdapException ex )
+        final Collection<Modification> modifications, final Control[] controls, StudioLdapException ex )
     {
         if ( !isModificationLogEnabled() )
         {
@@ -357,7 +356,7 @@
             }
             for ( Value value : item.getAttribute() )
             {
-                if ( maskedAttributes.contains( Strings.toLowerCase( attributeName ) ) )
+                if ( maskedAttributes.contains( Strings.toLowerCaseAscii( attributeName ) ) )
                 {
                     modSpec.addAttrVal( LdifAttrValLine.create( attributeName, "**********" ) ); //$NON-NLS-1$
                 }
@@ -388,7 +387,7 @@
      * {@inheritDoc}
      */
     public void logChangetypeModDn( Connection connection, final Dn oldDn, final Dn newDn,
-        final boolean deleteOldRdn, final Control[] controls, LdapException ex )
+        final boolean deleteOldRdn, final Control[] controls, StudioLdapException ex )
     {
         if ( !isModificationLogEnabled() )
         {
@@ -412,42 +411,12 @@
 
 
     /**
-     * {@inheritDoc}
-     */
-    public void logSearchRequest( Connection connection, String searchBase, String filter,
-        SearchControls searchControls, AliasDereferencingMethod aliasesDereferencingMethod,
-        Control[] controls, long requestNum, LdapException ex )
-    {
-        // don't log searches
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public void logSearchResultReference( Connection connection, Referral referral,
-        ReferralsInfo referralsInfo, long requestNum, LdapException ex )
-    {
-        // don't log searches 
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public void logSearchResultDone( Connection connection, long count, long requestNum, LdapException ex )
-    {
-        // don't log searches 
-    }
-
-
-    /**
      * Adds control lines to the record
      *
      * @param record the recored
      * @param controls the controls
      */
-    private static void addControlLines( LdifChangeRecord record,Control[] controls )
+    private static void addControlLines( LdifChangeRecord record, Control[] controls )
     {
         if ( controls != null )
         {
@@ -483,7 +452,7 @@
 
         try
         {
-            return getLogFiles( fileHandlers.get( id ) );
+            return getLogFiles( connection );
         }
         catch ( Exception e )
         {
@@ -498,51 +467,30 @@
      * @param fileHandler the file handler
      * 
      * @return the log files
-     * 
-     * @throws Exception the exception
      */
-    private static File[] getLogFiles( FileHandler fileHandler ) throws Exception
+    private static File[] getLogFiles( Connection connection )
     {
-        Field field = getFieldFromClass( "java.util.logging.FileHandler", "files" ); //$NON-NLS-1$ //$NON-NLS-2$
-        field.setAccessible( true );
-        File[] files = ( File[] ) field.get( fileHandler );
+        String logfileNamePattern = ConnectionManager.getModificationLogFileName( connection );
+        File file = new File( logfileNamePattern );
+        String pattern = file.getName().replace( "%u", "\\d+" ).replace( "%g", "\\d+" );
+        File dir = file.getParentFile();
+        File[] files = dir.listFiles( ( d, f ) -> {
+            return f.matches( pattern );
+        } );
+        Arrays.sort( files );
         return files;
     }
 
 
     /**
-     * Gets the field from class.
-     * 
-     * @param className the class name
-     * @param fieldName the field name
-     * 
-     * @return the field from class
-     * 
-     * @throws Exception the exception
-     */
-    private static Field getFieldFromClass( String className, String fieldName ) throws Exception
-    {
-        Class<?> clazz = Class.forName( className );
-        Field[] fields = clazz.getDeclaredFields();
-
-        for ( int i = 0; i < fields.length; i++ )
-        {
-            if ( fields[i].getName().equals( fieldName ) )
-                return fields[i];
-        }
-        return null;
-    }
-
-
-    /**
      * Checks if modification log is enabled.
      * 
      * @return true, if modification log is enabled
      */
     private boolean isModificationLogEnabled()
     {
-        return ConnectionCorePlugin.getDefault().getPluginPreferences().getBoolean(
-            ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_ENABLE );
+        return Platform.getPreferencesService().getBoolean( ConnectionCoreConstants.PLUGIN_ID,
+            ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_ENABLE, true, null );
     }
 
 
@@ -553,8 +501,8 @@
      */
     private int getFileCount()
     {
-        return ConnectionCorePlugin.getDefault().getPluginPreferences().getInt(
-            ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_COUNT );
+        return Platform.getPreferencesService().getInt( ConnectionCoreConstants.PLUGIN_ID,
+            ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_COUNT, 10, null );
     }
 
 
@@ -565,30 +513,8 @@
      */
     private int getFileSizeInKb()
     {
-        return ConnectionCorePlugin.getDefault().getPluginPreferences().getInt(
-            ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_SIZE );
-    }
-
-
-    /**
-     * Gets the masked attributes.
-     * 
-     * @return the masked attributes
-     */
-    private Set<String> getMaskedAttributes()
-    {
-        Set<String> maskedAttributes = new HashSet<String>();
-
-        String maskedAttributeString = ConnectionCorePlugin.getDefault().getPluginPreferences().getString(
-            ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_MASKED_ATTRIBUTES );
-        String[] splitted = maskedAttributeString.split( "," ); //$NON-NLS-1$
-
-        for ( String s : splitted )
-        {
-            maskedAttributes.add( Strings.toLowerCase( s ) );
-        }
-
-        return maskedAttributes;
+        return Platform.getPreferencesService().getInt( ConnectionCoreConstants.PLUGIN_ID,
+            ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_SIZE, 100, null );
     }
 
 
diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/api/LdifSearchLogger.java b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/api/LdifSearchLogger.java
index d2772af..0e44938 100644
--- a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/api/LdifSearchLogger.java
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/api/LdifSearchLogger.java
@@ -23,14 +23,16 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.lang.reflect.Field;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
+import java.util.StringJoiner;
 import java.util.logging.FileHandler;
 import java.util.logging.Formatter;
 import java.util.logging.Handler;
@@ -41,13 +43,13 @@
 import javax.naming.directory.SearchControls;
 
 import org.apache.commons.lang3.StringUtils;
+import org.apache.directory.api.ldap.model.entry.Attribute;
 import org.apache.directory.api.ldap.model.entry.Entry;
-import org.apache.directory.api.ldap.model.entry.Modification;
-import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.entry.Value;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.message.Referral;
-import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.url.LdapUrl;
+import org.apache.directory.api.util.Strings;
 import org.apache.directory.studio.connection.core.Connection;
 import org.apache.directory.studio.connection.core.Connection.AliasDereferencingMethod;
 import org.apache.directory.studio.connection.core.ConnectionCoreConstants;
@@ -56,12 +58,16 @@
 import org.apache.directory.studio.connection.core.ILdapLogger;
 import org.apache.directory.studio.connection.core.ReferralsInfo;
 import org.apache.directory.studio.connection.core.Utils;
+import org.apache.directory.studio.connection.core.io.StudioLdapException;
 import org.apache.directory.studio.ldifparser.LdifFormatParameters;
+import org.apache.directory.studio.ldifparser.model.container.LdifContentRecord;
+import org.apache.directory.studio.ldifparser.model.lines.LdifAttrValLine;
 import org.apache.directory.studio.ldifparser.model.lines.LdifCommentLine;
+import org.apache.directory.studio.ldifparser.model.lines.LdifDnLine;
 import org.apache.directory.studio.ldifparser.model.lines.LdifLineBase;
 import org.apache.directory.studio.ldifparser.model.lines.LdifSepLine;
-import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
-import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.InstanceScope;
 
 
 /**
@@ -87,52 +93,48 @@
     /** The loggers. */
     private Map<String, Logger> loggers = new HashMap<String, Logger>();
 
-
     /**
      * Creates a new instance of LdifSearchLogger.
      */
     public LdifSearchLogger()
     {
-        ConnectionCorePlugin.getDefault().getPluginPreferences().addPropertyChangeListener(
-            new IPropertyChangeListener()
+        IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode( ConnectionCoreConstants.PLUGIN_ID );
+        prefs.addPreferenceChangeListener( event -> {
+            if ( ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_COUNT.equals( event.getKey() )
+                || ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_SIZE.equals( event.getKey() ) )
             {
-                public void propertyChange( PropertyChangeEvent event )
+                // dispose all loggers/handlers
+                for ( Logger logger : loggers.values() )
                 {
-                    if ( ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_COUNT.equals( event.getProperty() )
-                        || ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_SIZE.equals( event.getProperty() ) )
+                    for ( Handler handler : logger.getHandlers() )
                     {
-                        // dispose all loggers/handlers
-                        for ( Logger logger : loggers.values() )
-                        {
-                            for ( Handler handler : logger.getHandlers() )
-                            {
-                                handler.close();
-                            }
-                        }
-
-                        // delete files with index greater than new file count
-                        for ( FileHandler fh : fileHandlers.values() )
-                        {
-                            try
-                            {
-                                File[] logFiles = getLogFiles( fh );
-                                for ( int i = getFileCount(); i < logFiles.length; i++ )
-                                {
-                                    if ( logFiles[i] != null && logFiles[i].exists() )
-                                    {
-                                        logFiles[i].delete();
-                                    }
-                                }
-                            }
-                            catch ( Exception e )
-                            {
-                            }
-                        }
-
-                        loggers.clear();
+                        handler.close();
                     }
                 }
-            } );
+
+                // delete files with index greater than new file count
+                Connection[] connections = ConnectionCorePlugin.getDefault().getConnectionManager().getConnections();
+                for ( Connection connection : connections )
+                {
+                    try
+                    {
+                        File[] logFiles = getLogFiles( connection );
+                        for ( int i = getFileCount(); i < logFiles.length; i++ )
+                        {
+                            if ( logFiles[i] != null && logFiles[i].exists() )
+                            {
+                                logFiles[i].delete();
+                            }
+                        }
+                    }
+                    catch ( Exception e )
+                    {
+                    }
+                }
+
+                loggers.clear();
+            }
+        } );
     }
 
 
@@ -186,12 +188,18 @@
                 handler.close();
             }
 
+            File[] files = getLogFiles( connection );
+            for ( File file : files )
+            {
+                deleteFileWithRetry( file );
+            }
+
             loggers.remove( id );
         }
     }
 
 
-    private void log( String text, String type, LdapException ex, Connection connection )
+    private void log( String text, String type, StudioLdapException ex, Connection connection )
     {
         String id = connection.getId();
         if ( !loggers.containsKey( id ) )
@@ -204,29 +212,27 @@
 
         if ( loggers.containsKey( id ) )
         {
-            Logger logger = loggers.get( id );
+            StringJoiner lines = new StringJoiner( "" );
             DateFormat df = new SimpleDateFormat( ConnectionCoreConstants.DATEFORMAT );
             df.setTimeZone( ConnectionCoreConstants.UTC_TIME_ZONE );
 
             if ( ex != null )
             {
-                logger.log( Level.ALL, LdifCommentLine
-                    .create( "#!" + type + " ERROR" ).toFormattedString( LdifFormatParameters.DEFAULT ) ); //$NON-NLS-1$ //$NON-NLS-2$
+                lines.add( LdifCommentLine.create( "#!" + type + " ERROR" ) //$NON-NLS-1$//$NON-NLS-2$
+                    .toFormattedString( LdifFormatParameters.DEFAULT ) );
             }
             else
             {
-                logger.log( Level.ALL, LdifCommentLine
-                    .create( "#!" + type + " OK" ).toFormattedString( LdifFormatParameters.DEFAULT ) ); //$NON-NLS-1$ //$NON-NLS-2$
+                lines.add( LdifCommentLine.create( "#!" + type + " OK" ) //$NON-NLS-1$ //$NON-NLS-2$
+                    .toFormattedString( LdifFormatParameters.DEFAULT ) );
             }
 
-            logger
-                .log(
-                    Level.ALL,
-                    LdifCommentLine
-                        .create( "#!CONNECTION ldap://" + connection.getHost() + ":" + connection.getPort() ) //$NON-NLS-1$//$NON-NLS-2$
-                        .toFormattedString( LdifFormatParameters.DEFAULT ) );
-            logger.log( Level.ALL, LdifCommentLine
-                .create( "#!DATE " + df.format( new Date() ) ).toFormattedString( LdifFormatParameters.DEFAULT ) ); //$NON-NLS-1$
+            lines.add(
+                LdifCommentLine
+                    .create( "#!CONNECTION ldap://" + connection.getHost() + ":" + connection.getPort() ) //$NON-NLS-1$//$NON-NLS-2$
+                    .toFormattedString( LdifFormatParameters.DEFAULT ) );
+            lines.add( LdifCommentLine.create( "#!DATE " + df.format( new Date() ) ) //$NON-NLS-1$
+                .toFormattedString( LdifFormatParameters.DEFAULT ) );
 
             if ( ex != null )
             {
@@ -234,10 +240,12 @@
                 errorComment = errorComment.replaceAll( "\r", " " ); //$NON-NLS-1$ //$NON-NLS-2$
                 errorComment = errorComment.replaceAll( "\n", " " ); //$NON-NLS-1$ //$NON-NLS-2$
                 LdifCommentLine errorCommentLine = LdifCommentLine.create( errorComment );
-                logger.log( Level.ALL, errorCommentLine.toFormattedString( LdifFormatParameters.DEFAULT ) );
+                lines.add( errorCommentLine.toFormattedString( LdifFormatParameters.DEFAULT ) );
             }
 
-            logger.log( Level.ALL, text );
+            lines.add( text );
+            Logger logger = loggers.get( id );
+            logger.log( Level.ALL, lines.toString() );
         }
     }
 
@@ -245,48 +253,9 @@
     /**
      * {@inheritDoc}
      */
-    public void logChangetypeAdd( Connection connection, final Entry entry, final Control[] controls, LdapException ex )
-    {
-        // don't log changetypes
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public void logChangetypeDelete( Connection connection, final Dn dn, final Control[] controls,
-        LdapException ex )
-    {
-        // don't log changetypes
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public void logChangetypeModify( Connection connection, final Dn dn,
-        final Collection<Modification> modifications, final Control[] controls, LdapException ex )
-    {
-        // don't log changetypes
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public void logChangetypeModDn( Connection connection, final Dn oldDn, final Dn newDn,
-        final boolean deleteOldRdn, final Control[] controls, LdapException ex )
-    {
-        // don't log changetypes
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
     public void logSearchRequest( Connection connection, String searchBase, String filter,
         SearchControls searchControls, AliasDereferencingMethod aliasesDereferencingMethod,
-        Control[] controls, long requestNum, LdapException ex )
+        Control[] controls, long requestNum, StudioLdapException ex )
     {
         if ( !isSearchRequestLogEnabled() )
         {
@@ -348,8 +317,60 @@
     /**
      * {@inheritDoc}
      */
+    public void logSearchResultEntry( Connection connection, StudioSearchResult studioSearchResult, long requestNum,
+        StudioLdapException ex )
+    {
+        if ( !isSearchResultEntryLogEnabled() )
+        {
+            return;
+        }
+
+        String formattedString;
+        if ( studioSearchResult != null )
+        {
+            Set<String> maskedAttributes = getMaskedAttributes();
+            Entry entry = studioSearchResult.getEntry();
+
+            LdifContentRecord record = new LdifContentRecord( LdifDnLine.create( entry.getDn().getName() ) );
+            for ( Attribute attribute : entry )
+            {
+                String attributeName = attribute.getUpId();
+                for ( Value value : attribute )
+                {
+                    if ( maskedAttributes.contains( Strings.toLowerCaseAscii( attributeName ) ) )
+                    {
+                        record.addAttrVal( LdifAttrValLine.create( attributeName, "**********" ) ); //$NON-NLS-1$
+                    }
+                    else
+                    {
+                        if ( value.isHumanReadable() )
+                        {
+                            record.addAttrVal( LdifAttrValLine.create( attributeName, value.getString() ) );
+                        }
+                        else
+                        {
+                            record.addAttrVal( LdifAttrValLine.create( attributeName, value.getBytes() ) );
+                        }
+                    }
+                }
+            }
+            record.finish( LdifSepLine.create() );
+            formattedString = record.toFormattedString( LdifFormatParameters.DEFAULT );
+        }
+        else
+        {
+            formattedString = LdifFormatParameters.DEFAULT.getLineSeparator();
+        }
+
+        log( formattedString, "SEARCH RESULT ENTRY (" + requestNum + ")", ex, connection ); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
     public void logSearchResultReference( Connection connection, Referral referral,
-        ReferralsInfo referralsInfo, long requestNum, LdapException ex )
+        ReferralsInfo referralsInfo, long requestNum, StudioLdapException ex )
     {
         if ( !isSearchResultEntryLogEnabled() )
         {
@@ -373,7 +394,7 @@
     /**
      * {@inheritDoc}
      */
-    public void logSearchResultDone( Connection connection, long count, long requestNum, LdapException ex )
+    public void logSearchResultDone( Connection connection, long count, long requestNum, StudioLdapException ex )
     {
         if ( !isSearchRequestLogEnabled() )
         {
@@ -413,7 +434,7 @@
 
         try
         {
-            return getLogFiles( fileHandlers.get( id ) );
+            return getLogFiles( connection );
         }
         catch ( Exception e )
         {
@@ -428,51 +449,29 @@
      * @param fileHandler the file handler
      * 
      * @return the log files
-     * 
-     * @throws Exception the exception
      */
-    private static File[] getLogFiles( FileHandler fileHandler ) throws Exception
+    private static File[] getLogFiles( Connection connection )
     {
-        Field field = getFieldFromClass( "java.util.logging.FileHandler", "files" ); //$NON-NLS-1$ //$NON-NLS-2$
-        field.setAccessible( true );
-        File[] files = ( File[] ) field.get( fileHandler );
+        String logfileNamePattern = ConnectionManager.getSearchLogFileName( connection );
+        File file = new File( logfileNamePattern );
+        String pattern = file.getName().replace( "%u", "\\d+" ).replace( "%g", "\\d+" );
+        File dir = file.getParentFile();
+        File[] files = dir.listFiles( ( d, f ) -> {
+            return f.matches( pattern );
+        } );
+        Arrays.sort( files );
         return files;
     }
 
 
     /**
-     * Gets the field from class.
-     * 
-     * @param className the class name
-     * @param fieldName the field name
-     * 
-     * @return the field from class
-     * 
-     * @throws Exception the exception
-     */
-    private static Field getFieldFromClass( String className, String fieldName ) throws Exception
-    {
-        Class<?> clazz = Class.forName( className );
-        Field[] fields = clazz.getDeclaredFields();
-
-        for ( int i = 0; i < fields.length; i++ )
-        {
-            if ( fields[i].getName().equals( fieldName ) )
-                return fields[i];
-        }
-        return null;
-    }
-
-
-    /**
      * Checks if search request log is enabled.
      * 
      * @return true, if search request log is enabled
      */
     private boolean isSearchRequestLogEnabled()
     {
-        return ConnectionCorePlugin.getDefault().getPluginPreferences().getBoolean(
-            ConnectionCoreConstants.PREFERENCE_SEARCHREQUESTLOGS_ENABLE );
+        return ConnectionCorePlugin.getDefault().isSearchRequestLogsEnabled();
     }
 
 
@@ -483,8 +482,7 @@
      */
     private boolean isSearchResultEntryLogEnabled()
     {
-        return ConnectionCorePlugin.getDefault().getPluginPreferences().getBoolean(
-            ConnectionCoreConstants.PREFERENCE_SEARCHRESULTENTRYLOGS_ENABLE );
+        return ConnectionCorePlugin.getDefault().isSearchResultEntryLogsEnabled();
     }
 
 
@@ -495,8 +493,7 @@
      */
     private int getFileCount()
     {
-        return ConnectionCorePlugin.getDefault().getPluginPreferences().getInt(
-            ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_COUNT );
+        return ConnectionCorePlugin.getDefault().getSearchLogsFileCount();
     }
 
 
@@ -507,8 +504,7 @@
      */
     private int getFileSizeInKb()
     {
-        return ConnectionCorePlugin.getDefault().getPluginPreferences().getInt(
-            ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_SIZE );
+        return ConnectionCorePlugin.getDefault().getSearchLogsFileSize();
     }
 
 
diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/api/StudioSearchResultEnumeration.java b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/api/StudioSearchResultEnumeration.java
index d563966..79f70f1 100644
--- a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/api/StudioSearchResultEnumeration.java
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/io/api/StudioSearchResultEnumeration.java
@@ -28,8 +28,6 @@
 
 import javax.naming.directory.SearchControls;
 
-import org.apache.directory.api.ldap.codec.api.LdapApiService;
-import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
 import org.apache.directory.api.ldap.model.cursor.CursorException;
 import org.apache.directory.api.ldap.model.cursor.SearchCursor;
 import org.apache.directory.api.ldap.model.entry.DefaultEntry;
@@ -268,6 +266,12 @@
             {
                 resultEntryCounter++;
                 StudioSearchResult ssr = new StudioSearchResult( currentSearchResultEntry, connection, false, null );
+
+                for ( ILdapLogger logger : ConnectionCorePlugin.getDefault().getLdapLoggers() )
+                {
+                    logger.logSearchResultEntry( connection, ssr, requestNum, null );
+                }
+
                 return ssr;
             }
 
diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/jobs/CheckNetworkParameterRunnable.java b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/jobs/CheckNetworkParameterRunnable.java
index e3aa989..a0ef158 100644
--- a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/jobs/CheckNetworkParameterRunnable.java
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/jobs/CheckNetworkParameterRunnable.java
@@ -21,6 +21,8 @@
 package org.apache.directory.studio.connection.core.jobs;
 
 
+import javax.net.ssl.SSLSession;
+
 import org.apache.directory.studio.common.core.jobs.StudioProgressMonitor;
 import org.apache.directory.studio.connection.core.Connection;
 import org.apache.directory.studio.connection.core.Messages;
@@ -36,7 +38,7 @@
 {
 
     private Connection connection;
-
+    private SSLSession sslSession;
 
     /**
      * Creates a new instance of CheckNetworkParameterJob.
@@ -78,6 +80,7 @@
         monitor.worked( 1 );
 
         connection.getConnectionWrapper().connect( monitor );
+        this.sslSession = connection.getConnectionWrapper().getSslSession();
         connection.getConnectionWrapper().disconnect();
     }
 
@@ -98,4 +101,10 @@
     {
         return null;
     }
+
+
+    public SSLSession getSslSession()
+    {
+        return sslSession;
+    }
 }
diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/messages.properties b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/messages.properties
index 5619285..aafd382 100644
--- a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/messages.properties
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/messages.properties
@@ -56,3 +56,4 @@
 
 DirectoryApiConnectionWrapper_NoConnection=No Connection
 DirectoryApiConnectionWrapper_UnableToConnect=Unable to connect
+DirectoryApiConnectionWrapper_UnsecuredConnection=Unsecured connection
diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/messages_de.properties b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/messages_de.properties
index ad95505..cb40eb0 100644
--- a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/messages_de.properties
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/messages_de.properties
@@ -58,3 +58,4 @@
 
 DirectoryApiConnectionWrapper_NoConnection=Keine Verbindung
 DirectoryApiConnectionWrapper_UnableToConnect=Verbindung nicht möglich
+DirectoryApiConnectionWrapper_UnsecuredConnection=Unsichere Verbindung
diff --git a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/messages_fr.properties b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/messages_fr.properties
index ba7e52b..74cd0fa 100644
--- a/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/messages_fr.properties
+++ b/plugins/connection.core/src/main/java/org/apache/directory/studio/connection/core/messages_fr.properties
@@ -58,3 +58,4 @@
 
 DirectoryApiConnectionWrapper_NoConnection=Pas de connexion
 DirectoryApiConnectionWrapper_UnableToConnect=Impossible de se connecter
+DirectoryApiConnectionWrapper_UnsecuredConnection=Connexion non s\u00E9curis\u00E9e
diff --git a/plugins/connection.core/src/main/resources/org/apache/directory/studio/connection/core/OIDDescriptions.properties b/plugins/connection.core/src/main/resources/org/apache/directory/studio/connection/core/OIDDescriptions.properties
index e4b68b2..eb4ea35 100644
--- a/plugins/connection.core/src/main/resources/org/apache/directory/studio/connection/core/OIDDescriptions.properties
+++ b/plugins/connection.core/src/main/resources/org/apache/directory/studio/connection/core/OIDDescriptions.properties
@@ -822,3 +822,18 @@
 2.16.840.1.113719.1.14.100.85=ResetDriverStatsRequest

 2.16.840.1.113719.1.27.99.1=Superior References

 2.16.840.1.113719.1.27.101.40=LDAP_CONTROL_SSTATREQUEST

+

+#2012-11-10 eDirectory syntaxes (http://www.novell.com/documentation/developer/ldapover/ldap_enu/?page=/documentation/developer/ldapover/ldap_enu/data/a3xfo7x.html)

+2.16.840.1.113719.1.1.5.1.6=Case Ignore List (SYN_CI_LIST)

+2.16.840.1.113719.1.1.5.1.12=Tagged Data (SYN_NET_ADDRESS)

+2.16.840.1.113719.1.1.5.1.13=Octet List (SYN_OCTET_LIST)

+2.16.840.1.113719.1.1.5.1.14=Tagged String (SYN_EMAIL_ADDRESS)

+2.16.840.1.113719.1.1.5.1.15=Tagged Name and String (SYN_PATH)

+2.16.840.1.113719.1.1.5.1.16=NDS Replica Pointer (SYN_REPLICA_POINTER)

+2.16.840.1.113719.1.1.5.1.17=NDS ACL (SYN_OBJECT_ACL)

+2.16.840.1.113719.1.1.5.1.19=NDS Timestamp (SYN_TIMESTAMP)

+2.16.840.1.113719.1.1.5.1.22=Counter (SYN_COUNTER)

+2.16.840.1.113719.1.1.5.1.23=Tagged Name (SYN_BACK_LINK)

+2.16.840.1.113719.1.1.5.1.25=Typed Name (SYN_TYPED_NAME)

+2.16.840.1.113719.1.1.5.1.0=Unknown (SYN_UNKNOWN)

+

diff --git a/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/AuthenticationParameterPage.java b/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/AuthenticationParameterPage.java
index 87842a5..f59b136 100644
--- a/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/AuthenticationParameterPage.java
+++ b/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/AuthenticationParameterPage.java
@@ -84,9 +84,6 @@
     /** The URL simple constant */
     private static final String X_AUTH_METHOD_SIMPLE = "Simple"; //$NON-NLS-1$
 
-    /** The URL PLAIN constant */
-    private static final String X_AUTH_METHOD_PLAIN = "PLAIN"; //$NON-NLS-1$
-
     /** The URL DIGEST-MD5 constant */
     private static final String X_AUTH_METHOD_DIGEST_MD5 = "DIGEST-MD5"; //$NON-NLS-1$
 
@@ -145,9 +142,6 @@
     /** The text widget to input bind password */
     private Text bindPasswordText;
 
-    /** The text widget to input the SASL PLAIN autzid (if selected) */
-    private Text authzidText;
-
     /** The checkbox to choose if the bind password should be saved on disk */
     private Button saveBindPasswordButton;
 
@@ -173,7 +167,6 @@
     private Text krb5ConfigManualHostText;
     private Text krb5ConfigManualPortText;
 
-
     /**
      * Gets the authentication method.
      * 
@@ -223,20 +216,9 @@
     }
 
 
-    /**
-     * Gets the bind authzid.
-     * 
-     * @return the authzid
-     */
-    private String getAuthzid()
-    {
-        return authzidText.getText();
-    }
-
-
     private String getSaslRealm()
     {
-        return saslRealmText.getText();
+        return Strings.isEmpty( saslRealmText.getText() ) ? null : saslRealmText.getText();
     }
 
 
@@ -378,10 +360,6 @@
             ConnectionUIConstants.DIALOGSETTING_KEY_PRINCIPAL_HISTORY );
         bindPrincipalCombo = BaseWidgetUtils.createCombo( composite, dnHistory, -1, 2 );
 
-        BaseWidgetUtils.createLabel( composite, Messages.getString( "AuthenticationParameterPage.Authzid" ), 1 ); //$NON-NLS-1$
-        authzidText = BaseWidgetUtils.createText( composite, "SASL PLAIN only", 2 ); //$NON-NLS-1$
-        authzidText.setEnabled( false );
-
         BaseWidgetUtils.createLabel( composite, Messages.getString( "AuthenticationParameterPage.BindPassword" ), 1 ); //$NON-NLS-1$
         bindPasswordText = BaseWidgetUtils.createPasswordText( composite, StringUtils.EMPTY, 2 ); //$NON-NLS-1$
 
@@ -1031,10 +1009,6 @@
     {
         switch ( parameter.getAuthMethod() )
         {
-            case SASL_PLAIN :
-                ldapUrl.getExtensions().add( new Extension( false, X_AUTH_METHOD, X_AUTH_METHOD_PLAIN ) );
-                break;
-                
             case SASL_CRAM_MD5:
                 ldapUrl.getExtensions().add( new Extension( false, X_AUTH_METHOD, X_AUTH_METHOD_CRAM_MD5 ) );
                 break;
@@ -1078,7 +1052,6 @@
 
         switch ( parameter.getAuthMethod() )
         {
-            case SASL_PLAIN:
             case SASL_CRAM_MD5:
             case SASL_DIGEST_MD5:
             case SASL_GSSAPI:
diff --git a/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/ConnectionLabelProvider.java b/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/ConnectionLabelProvider.java
index 4b6f2eb..b1e4831 100644
--- a/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/ConnectionLabelProvider.java
+++ b/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/ConnectionLabelProvider.java
@@ -59,13 +59,17 @@
         {
             Connection conn = ( Connection ) obj;
 
+            boolean isConnected = conn.getConnectionWrapper().isConnected();
+            boolean isSecured = conn.getConnectionWrapper().isSecured();
+            String unsecuredWarning = isConnected && !isSecured ? " UNSECURED! " : ""; //$NON-NLS-1$ //$NON-NLS-2$
+
             if ( conn.getEncryptionMethod() == EncryptionMethod.LDAPS )
             {
-                return conn.getName() + " (LDAPS)"; //$NON-NLS-1$
+                return conn.getName() + unsecuredWarning + " (LDAPS)"; //$NON-NLS-1$
             }
             else if ( conn.getEncryptionMethod() == EncryptionMethod.START_TLS )
             {
-                return conn.getName() + " (StartTLS)"; //$NON-NLS-1$
+                return conn.getName() + unsecuredWarning + " (StartTLS)"; //$NON-NLS-1$
             }
             else
             {
@@ -99,18 +103,21 @@
         {
             Connection conn = ( Connection ) obj;
 
-            if ( ( conn.getEncryptionMethod() == EncryptionMethod.LDAPS )
-                || ( conn.getEncryptionMethod() == EncryptionMethod.START_TLS ) )
+            boolean isConnected = conn.getConnectionWrapper().isConnected();
+            boolean isSecured = conn.getConnectionWrapper().isSecured();
+            boolean isEncryptionConfigured = conn.getEncryptionMethod().isEncrytped();
+
+            if ( isConnected )
             {
-                return conn.getConnectionWrapper().isConnected() ? ConnectionUIPlugin.getDefault().getImage(
+                return isSecured ? ConnectionUIPlugin.getDefault().getImage(
                     ConnectionUIConstants.IMG_CONNECTION_SSL_CONNECTED )
                     : ConnectionUIPlugin.getDefault().getImage(
-                        ConnectionUIConstants.IMG_CONNECTION_SSL_DISCONNECTED );
+                        ConnectionUIConstants.IMG_CONNECTION_CONNECTED );
             }
             else
             {
-                return conn.getConnectionWrapper().isConnected() ? ConnectionUIPlugin.getDefault().getImage(
-                    ConnectionUIConstants.IMG_CONNECTION_CONNECTED )
+                return isEncryptionConfigured ? ConnectionUIPlugin.getDefault().getImage(
+                    ConnectionUIConstants.IMG_CONNECTION_SSL_DISCONNECTED )
                     : ConnectionUIPlugin.getDefault().getImage(
                         ConnectionUIConstants.IMG_CONNECTION_DISCONNECTED );
             }
diff --git a/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/NetworkParameterPage.java b/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/NetworkParameterPage.java
index 5bcd3d7..70f3aca 100644
--- a/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/NetworkParameterPage.java
+++ b/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/NetworkParameterPage.java
@@ -21,9 +21,14 @@
 package org.apache.directory.studio.connection.ui.widgets;
 
 
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
+
 import org.apache.commons.lang3.StringUtils;
 import org.apache.directory.api.ldap.model.url.LdapUrl;
 import org.apache.directory.api.ldap.model.url.LdapUrl.Extension;
@@ -41,6 +46,7 @@
 import org.apache.directory.studio.connection.ui.ConnectionUIConstants;
 import org.apache.directory.studio.connection.ui.ConnectionUIPlugin;
 import org.apache.directory.studio.connection.ui.RunnableContextRunner;
+import org.apache.directory.studio.connection.ui.dialogs.CertificateInfoDialog;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.jface.dialogs.IDialogSettings;
 import org.eclipse.jface.dialogs.MessageDialog;
@@ -116,6 +122,9 @@
     /** The combo to select the encryption method */
     private Combo encryptionMethodCombo;
 
+    /** The button to fetch and show the server's certificate */
+    private Button viewServerCertificateButton;
+
     /** The button to check the connection parameters */
     private Button checkConnectionButton;
 
@@ -316,11 +325,14 @@
                 .getString( "NetworkParameterPage.WarningCertificateValidation" ), 2 ); //$NON-NLS-1$
         }
 
-        BaseWidgetUtils.createSpacer( groupComposite, 2 );
-        checkConnectionButton = new Button( groupComposite, SWT.PUSH );
+        BaseWidgetUtils.createSpacer( groupComposite, 1 );
         GridData gridData = new GridData();
         gridData.horizontalAlignment = SWT.RIGHT;
         gridData.verticalAlignment = SWT.BOTTOM;
+        viewServerCertificateButton = new Button( groupComposite, SWT.PUSH );
+        viewServerCertificateButton.setLayoutData( gridData );
+        viewServerCertificateButton.setText( Messages.getString( "NetworkParameterPage.ViewCertificate" ) ); //$NON-NLS-1$
+        checkConnectionButton = new Button( groupComposite, SWT.PUSH );
         checkConnectionButton.setLayoutData( gridData );
         checkConnectionButton.setText( Messages.getString( "NetworkParameterPage.CheckNetworkParameter" ) ); //$NON-NLS-1$
 
@@ -340,7 +352,11 @@
     {
         // set enabled/disabled state of check connection button
         checkConnectionButton.setEnabled( !hostCombo.getText().equals( StringUtils.EMPTY ) &&
-            !portCombo.getText().equals( StringUtils.EMPTY ) ); //$NON-NLS-1$ //$NON-NLS-2$
+            !portCombo.getText().equals( StringUtils.EMPTY ) );
+
+        // set enabled/disabled state of show server certificate button
+        viewServerCertificateButton.setEnabled( checkConnectionButton.isEnabled()
+            && getEncyrptionMethod() != EncryptionMethod.NONE );
 
         // validate input fields
         message = null;
@@ -451,10 +467,46 @@
 
                 if ( status.isOK() )
                 {
-                    MessageDialog.openInformation( Display.getDefault().getActiveShell(), Messages
-                        .getString( "NetworkParameterPage.CheckNetworkParameter" ), //$NON-NLS-1$
-                        Messages
-                            .getString( "NetworkParameterPage.ConnectionEstablished" ) ); //$NON-NLS-1$
+                    String title = Messages.getString( "NetworkParameterPage.CheckNetworkParameter" ); //$NON-NLS-1$
+                    String message = Messages.getString( "NetworkParameterPage.ConnectionEstablished" ); //$NON-NLS-1$
+
+                    SSLSession sslSession = runnable.getSslSession();
+                    if ( sslSession != null )
+                    {
+                        message += "\n\nProtocol: " + sslSession.getProtocol();
+                        message += "\nCipher Suite: " + sslSession.getCipherSuite();
+                    }
+                    MessageDialog.openInformation( Display.getDefault().getActiveShell(), title, message );
+                }
+            }
+        } );
+
+        viewServerCertificateButton.addSelectionListener( new SelectionAdapter()
+        {
+            @Override
+            public void widgetSelected( SelectionEvent event )
+            {
+                Connection connection = getTestConnection();
+                CheckNetworkParameterRunnable runnable = new CheckNetworkParameterRunnable( connection );
+                IStatus status = RunnableContextRunner.execute( runnable, runnableContext, true );
+
+                if ( status.isOK() )
+                {
+                    try
+                    {
+                        SSLSession sslSession = runnable.getSslSession();
+                        Certificate[] certificates = sslSession.getPeerCertificates();
+                        X509Certificate[] serverCertificates = new X509Certificate[certificates.length];
+                        for ( int i = 0; i < certificates.length; i++ )
+                        {
+                            serverCertificates[i] = ( X509Certificate ) certificates[i];
+                        }
+                        new CertificateInfoDialog( Display.getDefault().getActiveShell(), serverCertificates ).open();
+                    }
+                    catch ( SSLPeerUnverifiedException e )
+                    {
+                        throw new RuntimeException( e );
+                    }
                 }
             }
         } );
diff --git a/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/messages.properties b/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/messages.properties
index beb6919..685715c 100644
--- a/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/messages.properties
+++ b/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/messages.properties
@@ -129,3 +129,4 @@
 NetworkParameterPage.WarningCertificateValidation = Warning: Certificate validation is disabled, \nbe aware of invalid certificates or man-in-the-middle attacks!
 NetworkParameterPage.CertificateValidationLink    = Server certificates for LDAP connections can be managed in the '<a>Certificate Validation</a>' preference page.
 NetworkParameterPage.Timeout                      = Connection timeout (s):
+NetworkParameterPage.ViewCertificate              = View Certificate...
diff --git a/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/messages_de.properties b/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/messages_de.properties
index 4757d50..8b9e1b8 100644
--- a/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/messages_de.properties
+++ b/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/messages_de.properties
@@ -124,4 +124,5 @@
 NetworkParameterPage.UseStartTLS                  = StartTLS Erweiterung
 NetworkParameterPage.WarningCertificateValidation = Warnung: Zertifikat Validierung ist deaktiviert,\nsind Sie sich der Gefahr von ung\u00FCltigen Zertifikaten\noder 'man-in-the-middle' Angriffen bewusst!
 NetworkParameterPage.CertificateValidationLink    = Server-Zertifikate f\u00FCr LDAP-Verbindungen k\u00F6nnen in der '<a>Zertifikatsvalidierung</a>' Pr\u00E4ferenz Seite verwaltet werden.
-NetworkParameterPage.Timeout                      = Abfallzeit (s) :
+NetworkParameterPage.Timeout                      = Timeout (s) :
+NetworkParameterPage.ViewCertificate              = Zertifikat anzeigen...
diff --git a/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/messages_fr.properties b/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/messages_fr.properties
index 39c8df9..1342c3d 100644
--- a/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/messages_fr.properties
+++ b/plugins/connection.ui/src/main/java/org/apache/directory/studio/connection/ui/widgets/messages_fr.properties
@@ -126,3 +126,4 @@
 NetworkParameterPage.WarningCertificateValidation = Attention : La validation des certificats est d\u00E9sactiv\u00E9e, \nm\u00E9fiez-vous des certificats invalides ou des attaques par interposition (man-in-the-middle)\!
 NetworkParameterPage.CertificateValidationLink    = Les certificats serveur pour les connexions LDAP sont administrables dans la page de pr\u00E9f\u00E9rence '<a>Validation de certificat</a>'.
 NetworkParameterPage.Timeout                      = Expiration de la connection (s):
+NetworkParameterPage.ViewCertificate              = Afficher le certificat...
diff --git a/plugins/ldapbrowser.common/plugin.xml b/plugins/ldapbrowser.common/plugin.xml
index a826dad..21dd5f8 100644
--- a/plugins/ldapbrowser.common/plugin.xml
+++ b/plugins/ldapbrowser.common/plugin.xml
@@ -51,6 +51,7 @@
     <initializer class="org.apache.directory.studio.ldapbrowser.common.BrowserCommonPreferencesInitializer"/>
   </extension> 
 
+
   <extension
       point="org.eclipse.ui.preferencePages">
     <page
diff --git a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/BrowserCommonActivator.java b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/BrowserCommonActivator.java
index b625543..9bd90b2 100644
--- a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/BrowserCommonActivator.java
+++ b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/BrowserCommonActivator.java
@@ -40,6 +40,7 @@
 import org.eclipse.swt.graphics.FontData;
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.graphics.RGB;
+import org.eclipse.ui.PlatformUI;
 import org.eclipse.ui.editors.text.templates.ContributionContextTypeRegistry;
 import org.eclipse.ui.editors.text.templates.ContributionTemplateStore;
 import org.eclipse.ui.plugin.AbstractUIPlugin;
@@ -99,12 +100,12 @@
 
         if ( fontRegistry == null )
         {
-            fontRegistry = new FontRegistry( getWorkbench().getDisplay() );
+            fontRegistry = new FontRegistry( PlatformUI.getWorkbench().getDisplay() );
         }
 
         if ( colorRegistry == null )
         {
-            colorRegistry = new ColorRegistry( getWorkbench().getDisplay() );
+            colorRegistry = new ColorRegistry( PlatformUI.getWorkbench().getDisplay() );
         }
 
         valueEditorPreferences = new ValueEditorsPreferences();
diff --git a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/BrowserCommonPreferencesInitializer.java b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/BrowserCommonPreferencesInitializer.java
index de344b1..edd85fb 100644
--- a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/BrowserCommonPreferencesInitializer.java
+++ b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/BrowserCommonPreferencesInitializer.java
@@ -37,7 +37,6 @@
 import org.eclipse.jface.preference.PreferenceConverter;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.graphics.FontData;
-import org.eclipse.swt.graphics.RGB;
 import org.eclipse.swt.widgets.Display;
 
 
@@ -60,8 +59,7 @@
         store.setDefault( BrowserCommonConstants.PREFERENCE_COUNT_LIMIT, 1000 );
         store.setDefault( BrowserCommonConstants.PREFERENCE_TIME_LIMIT, 0 );
 
-        // Colors and Fonts
-        RGB rgbBlack = Display.getDefault().getSystemColor( SWT.COLOR_BLACK ).getRGB();
+        // Fonts
         FontData[] fontData = Display.getDefault().getSystemFont().getFontData();
         FontData fontDataNormal = new FontData( fontData[0].getName(), fontData[0].getHeight(), SWT.NORMAL );
         FontData fontDataItalic = new FontData( fontData[0].getName(), fontData[0].getHeight(), SWT.ITALIC );
@@ -69,13 +67,13 @@
         FontData fontDataBoldItalic = new FontData( fontData[0].getName(), fontData[0].getHeight(), SWT.BOLD
             | SWT.ITALIC );
         // Attributes colors and fonts
-        PreferenceConverter.setDefault( store, BrowserCommonConstants.PREFERENCE_OBJECTCLASS_COLOR, rgbBlack );
+        store.setDefault( BrowserCommonConstants.PREFERENCE_OBJECTCLASS_COLOR, IPreferenceStore.STRING_DEFAULT_DEFAULT );
         PreferenceConverter.setDefault( store, BrowserCommonConstants.PREFERENCE_OBJECTCLASS_FONT, fontDataBoldItalic );
-        PreferenceConverter.setDefault( store, BrowserCommonConstants.PREFERENCE_MUSTATTRIBUTE_COLOR, rgbBlack );
+        store.setDefault( BrowserCommonConstants.PREFERENCE_MUSTATTRIBUTE_COLOR, IPreferenceStore.STRING_DEFAULT_DEFAULT );
         PreferenceConverter.setDefault( store, BrowserCommonConstants.PREFERENCE_MUSTATTRIBUTE_FONT, fontDataBold );
-        PreferenceConverter.setDefault( store, BrowserCommonConstants.PREFERENCE_MAYATTRIBUTE_COLOR, rgbBlack );
+        store.setDefault( BrowserCommonConstants.PREFERENCE_MAYATTRIBUTE_COLOR, IPreferenceStore.STRING_DEFAULT_DEFAULT );
         PreferenceConverter.setDefault( store, BrowserCommonConstants.PREFERENCE_MAYATTRIBUTE_FONT, fontDataNormal );
-        PreferenceConverter.setDefault( store, BrowserCommonConstants.PREFERENCE_OPERATIONALATTRIBUTE_COLOR, rgbBlack );
+        store.setDefault( BrowserCommonConstants.PREFERENCE_MAYATTRIBUTE_COLOR, IPreferenceStore.STRING_DEFAULT_DEFAULT );
         PreferenceConverter.setDefault( store, BrowserCommonConstants.PREFERENCE_OPERATIONALATTRIBUTE_FONT,
             fontDataItalic );
 
diff --git a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/actions/OpenQuickSearchAction.java b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/actions/OpenQuickSearchAction.java
index 6efa6a5..b2130ec 100644
--- a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/actions/OpenQuickSearchAction.java
+++ b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/actions/OpenQuickSearchAction.java
@@ -24,7 +24,6 @@
 import org.apache.directory.studio.connection.core.Utils;
 import org.apache.directory.studio.ldapbrowser.common.BrowserCommonActivator;
 import org.apache.directory.studio.ldapbrowser.common.BrowserCommonConstants;
-import org.apache.directory.studio.ldapbrowser.common.widgets.browser.BrowserWidget;
 import org.apache.directory.studio.ldapbrowser.core.jobs.SearchRunnable;
 import org.apache.directory.studio.ldapbrowser.core.jobs.StudioBrowserJob;
 import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection;
@@ -45,19 +44,6 @@
  */
 public class OpenQuickSearchAction extends BrowserAction
 {
-    /** The browser widget */
-    private BrowserWidget widget;
-
-
-    /**
-     * Creates a new instance of OpenQuickSearchAction.
-     */
-    public OpenQuickSearchAction( BrowserWidget widget )
-    {
-        this.widget = widget;
-    }
-
-
     /**
      * {@inheritDoc}
      */
@@ -68,7 +54,7 @@
         if ( browserConnection != null )
         {
             // Getting the current quick search
-            IQuickSearch quickSearch = widget.getQuickSearch();
+            IQuickSearch quickSearch = browserConnection.getQuickSearch();
 
             // Creating a new quick search with the currently selected entry
             // if there's no current quick search or quick search isn't selected
@@ -88,7 +74,7 @@
 
                 // Creating a new quick search
                 quickSearch = new QuickSearch( searchBase, browserConnection );
-                widget.setQuickSearch( quickSearch );
+                browserConnection.setQuickSearch( quickSearch );
             }
 
             // Creating and opening the dialog
@@ -201,7 +187,7 @@
     {
         if ( getSelectedSearches().length == 1 )
         {
-            return getSelectedSearches()[0].equals( widget.getQuickSearch() );
+            return getSelectedSearches()[0] instanceof IQuickSearch;
         }
 
         return false;
diff --git a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/dialogs/HexDialog.java b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/dialogs/HexDialog.java
index 7f7829a..d97864b 100644
--- a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/dialogs/HexDialog.java
+++ b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/dialogs/HexDialog.java
@@ -35,7 +35,10 @@
 import org.eclipse.jface.dialogs.IDialogConstants;
 import org.eclipse.jface.resource.JFaceResources;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
 import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.FileDialog;
@@ -52,6 +55,8 @@
 public class HexDialog extends Dialog
 {
 
+    public static final String LOAD_FILE_NAME_TOOLTIP = "LoadFileName";
+
     /** The default title. */
     private static final String DIALOG_TITLE = Messages.getString( "HexDialog.HexEditor" ); //$NON-NLS-1$
 
@@ -64,6 +69,9 @@
     /** The button ID for the save button. */
     private static final int SAVE_BUTTON_ID = 9999;
 
+    /** Hidden text to set the filename, used for UI tests. */
+    private Text loadFilenameText;
+
     /** The current data. */
     private byte[] currentData;
 
@@ -134,18 +142,7 @@
             String returnedFileName = fileDialog.open();
             if ( returnedFileName != null )
             {
-                try
-                {
-                    File file = new File( returnedFileName );
-                    currentData = FileUtils.readFileToByteArray( file );
-                    hexText.setText( toFormattedHex( currentData ) );
-                }
-                catch ( IOException e )
-                {
-                    ConnectionUIPlugin.getDefault().getExceptionHandler().handleException(
-                        new Status( IStatus.ERROR, BrowserCommonConstants.PLUGIN_ID, IStatus.ERROR, Messages
-                            .getString( "HexDialog.CantReadFile" ), e ) ); //$NON-NLS-1$
-                }
+                loadFile( returnedFileName );
             }
         }
         else
@@ -157,6 +154,23 @@
     }
 
 
+    private void loadFile( String fileName )
+    {
+        try
+        {
+            File file = new File( fileName );
+            currentData = FileUtils.readFileToByteArray( file );
+            hexText.setText( toFormattedHex( currentData ) );
+        }
+        catch ( IOException e )
+        {
+            ConnectionUIPlugin.getDefault().getExceptionHandler().handleException(
+                new Status( IStatus.ERROR, BrowserCommonConstants.PLUGIN_ID, IStatus.ERROR, Messages
+                    .getString( "HexDialog.CantReadFile" ), e ) ); //$NON-NLS-1$
+        }
+    }
+
+
     /**
      * Small helper.
      */
@@ -187,11 +201,23 @@
      */
     protected void createButtonsForButtonBar( Composite parent )
     {
+        ((GridLayout) parent.getLayout()).numColumns++;
+        loadFilenameText = new Text( parent, SWT.NONE );
+        loadFilenameText.setToolTipText( LOAD_FILE_NAME_TOOLTIP );
+        loadFilenameText.setBackground( parent.getBackground() );
+        loadFilenameText.addModifyListener( new ModifyListener()
+        {
+            public void modifyText( ModifyEvent e )
+            {
+                loadFile( loadFilenameText.getText() );
+            }
+        } );
+
         if ( isEditable( currentData ) )
         {
            createButton( parent, EDIT_AS_TEXT_BUTTON_ID, Messages.getString( "HexDialog.EditAsText" ), false ); //$NON-NLS-1$
         }
-        
+
         createButton( parent, LOAD_BUTTON_ID, Messages.getString( "HexDialog.LoadDataButton" ), false ); //$NON-NLS-1$
         createButton( parent, SAVE_BUTTON_ID, Messages.getString( "HexDialog.SaveDataButton" ), false ); //$NON-NLS-1$
         createButton( parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, false );
@@ -255,7 +281,7 @@
             sb.append( s ).append( " " ); //$NON-NLS-1$
 
             // extra space after 8 hex numbers
-            if ( ( i + 1 ) % 8 == 0 )
+            if ( ( i + 1 ) % 8 == 0 && ( i + 1 ) % 16 != 0 )
             {
                 sb.append( " " ); //$NON-NLS-1$
             }
@@ -272,16 +298,15 @@
                     }
                     i++;
                 }
-                sb.append( " " ); //$NON-NLS-1$
             }
 
             // print ASCII characters after 16 hex numbers 
             if ( ( i + 1 ) % 16 == 0 )
             {
-                sb.append( "   " ); //$NON-NLS-1$
+                sb.append( "    " ); //$NON-NLS-1$
                 for ( int x = i - 16 + 1; x <= i && x < data.length; x++ )
                 {
-                    // print ASCII charachter if printable
+                    // print ASCII character if printable
                     // otherwise print a dot
                     if ( data[x] > 32 && data[x] < 127 )
                     {
diff --git a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/dialogs/preferences/AttributesPreferencePage.java b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/dialogs/preferences/AttributesPreferencePage.java
index ce13520..5b104f9 100644
--- a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/dialogs/preferences/AttributesPreferencePage.java
+++ b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/dialogs/preferences/AttributesPreferencePage.java
@@ -134,10 +134,9 @@
             attributeItalicButtons[i] = BaseWidgetUtils.createCheckbox( colorsAndFontsComposite, Messages
                 .getString( "AttributesPreferencePage.Italic" ), 1 ); //$NON-NLS-1$
 
-            FontData[] fontDatas = PreferenceConverter.getFontDataArray( BrowserCommonActivator.getDefault()
-                .getPreferenceStore(), ATTRIBUTE_FONT_CONSTANTS[i] );
-            RGB rgb = PreferenceConverter.getColor( BrowserCommonActivator.getDefault().getPreferenceStore(),
-                ATTRIBUTE_COLOR_CONSTANTS[i] );
+            FontData[] fontDatas = PreferenceConverter.getFontDataArray( getPreferenceStore(),
+                ATTRIBUTE_FONT_CONSTANTS[i] );
+            RGB rgb = PreferenceConverter.getColor( getPreferenceStore(), ATTRIBUTE_COLOR_CONSTANTS[i] );
             setColorsAndFonts( i, fontDatas, rgb );
         }
 
@@ -214,14 +213,12 @@
         // Attributes Colors And Fonts
         for ( int i = 0; i < ATTRIBUTE_TYPES.length; i++ )
         {
-            FontData[] fontDatas = PreferenceConverter.getFontDataArray( BrowserCommonActivator.getDefault()
-                .getPreferenceStore(), ATTRIBUTE_FONT_CONSTANTS[i] );
+            FontData[] fontDatas = PreferenceConverter.getFontDataArray( getPreferenceStore(),
+                ATTRIBUTE_FONT_CONSTANTS[i] );
             setFontData( fontDatas, attributeBoldButtons[i], attributeItalicButtons[i] );
             RGB rgb = attributeColorSelectors[i].getColorValue();
-            PreferenceConverter.setValue( BrowserCommonActivator.getDefault().getPreferenceStore(),
-                ATTRIBUTE_FONT_CONSTANTS[i], fontDatas );
-            PreferenceConverter.setValue( BrowserCommonActivator.getDefault().getPreferenceStore(),
-                ATTRIBUTE_COLOR_CONSTANTS[i], rgb );
+            PreferenceConverter.setValue( getPreferenceStore(), ATTRIBUTE_FONT_CONSTANTS[i], fontDatas );
+            PreferenceConverter.setValue( getPreferenceStore(), ATTRIBUTE_COLOR_CONSTANTS[i], rgb );
         }
 
         return true;
@@ -240,10 +237,11 @@
         // Attributes Colors And Fonts
         for ( int i = 0; i < ATTRIBUTE_TYPES.length; i++ )
         {
-            FontData[] fontDatas = PreferenceConverter.getDefaultFontDataArray( BrowserCommonActivator.getDefault()
-                .getPreferenceStore(), ATTRIBUTE_FONT_CONSTANTS[i] );
-            RGB rgb = PreferenceConverter.getDefaultColor( BrowserCommonActivator.getDefault().getPreferenceStore(),
-                ATTRIBUTE_COLOR_CONSTANTS[i] );
+            FontData[] fontDatas = PreferenceConverter.getDefaultFontDataArray( getPreferenceStore(),
+                ATTRIBUTE_FONT_CONSTANTS[i] );
+            getPreferenceStore().setToDefault( ATTRIBUTE_FONT_CONSTANTS[i] );
+            RGB rgb = PreferenceConverter.getDefaultColor( getPreferenceStore(), ATTRIBUTE_COLOR_CONSTANTS[i] );
+            getPreferenceStore().setToDefault( ATTRIBUTE_COLOR_CONSTANTS[i] );
             setColorsAndFonts( i, fontDatas, rgb );
         }
 
diff --git a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/filtereditor/FilterDamagerRepairer.java b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/filtereditor/FilterDamagerRepairer.java
index 8b8c6bd..8e6773e 100644
--- a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/filtereditor/FilterDamagerRepairer.java
+++ b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/filtereditor/FilterDamagerRepairer.java
@@ -22,6 +22,7 @@
 
 
 import org.apache.directory.studio.common.ui.CommonUIConstants;
+import org.apache.directory.studio.common.ui.CommonUIPlugin;
 import org.apache.directory.studio.ldapbrowser.core.model.filter.parser.LdapFilterParser;
 import org.apache.directory.studio.ldapbrowser.core.model.filter.parser.LdapFilterToken;
 import org.eclipse.jface.text.DocumentEvent;
@@ -34,6 +35,7 @@
 import org.eclipse.jface.text.presentation.IPresentationRepairer;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.graphics.Color;
 
 
 /**
@@ -44,18 +46,6 @@
 public class FilterDamagerRepairer implements IPresentationDamager, IPresentationRepairer
 {
 
-    private static final TextAttribute DEFAULT_TEXT_ATTRIBUTE = new TextAttribute( CommonUIConstants.BLACK_COLOR );
-
-    private static final TextAttribute AND_OR_NOT_TEXT_ATTRIBUTE = new TextAttribute( CommonUIConstants.M_GREEN_COLOR, null, SWT.BOLD );
-
-    private static final TextAttribute ATTRIBUTE_TEXT_ATTRIBUTE = new TextAttribute( CommonUIConstants.M_PURPLE_COLOR );
-
-    private static final TextAttribute FILTER_TYPE_TEXT_ATTRIBUTE = new TextAttribute( CommonUIConstants.RED_COLOR, null, SWT.BOLD );
-
-    private static final TextAttribute VALUE_TEXT_ATTRIBUTE = new TextAttribute( CommonUIConstants.M_BLUE_COLOR );
-
-    private static final TextAttribute PARENTHESIS_TEXT_ATTRIBUTE = new TextAttribute( CommonUIConstants.BLACK_COLOR, null, SWT.BOLD );
-
     /** The filter parser. */
     private LdapFilterParser parser;
 
@@ -98,6 +88,13 @@
      */
     public void createPresentation( TextPresentation presentation, ITypedRegion damage )
     {
+        TextAttribute DEFAULT_TEXT_ATTRIBUTE = new TextAttribute( getColor(CommonUIConstants.DEFAULT_COLOR) );
+        TextAttribute AND_OR_NOT_TEXT_ATTRIBUTE = new TextAttribute( getColor(CommonUIConstants.KEYWORD_1_COLOR), null, SWT.BOLD );
+        TextAttribute ATTRIBUTE_TEXT_ATTRIBUTE = new TextAttribute( getColor(CommonUIConstants.ATTRIBUTE_TYPE_COLOR) );
+        TextAttribute FILTER_TYPE_TEXT_ATTRIBUTE = new TextAttribute( getColor(CommonUIConstants.SEPARATOR_COLOR), null, SWT.BOLD );
+        TextAttribute VALUE_TEXT_ATTRIBUTE = new TextAttribute( getColor(CommonUIConstants.VALUE_COLOR) );
+        TextAttribute PARENTHESIS_TEXT_ATTRIBUTE = new TextAttribute( getColor(CommonUIConstants.DEFAULT_COLOR), null, SWT.BOLD );
+
         // parse the filter
         parser.parse( this.document.get() );
 
@@ -145,6 +142,12 @@
     }
 
 
+    private Color getColor( String name )
+    {
+        return CommonUIPlugin.getDefault().getColor( name );
+    }
+
+
     /**
      * Adds the style range.
      * 
diff --git a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/filtereditor/FilterReconcilingStrategy.java b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/filtereditor/FilterReconcilingStrategy.java
index 54a695a..77290d7 100644
--- a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/filtereditor/FilterReconcilingStrategy.java
+++ b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/filtereditor/FilterReconcilingStrategy.java
@@ -25,6 +25,7 @@
 import java.util.List;
 
 import org.apache.directory.studio.common.ui.CommonUIConstants;
+import org.apache.directory.studio.common.ui.CommonUIPlugin;
 import org.apache.directory.studio.ldapbrowser.core.model.filter.LdapFilter;
 import org.apache.directory.studio.ldapbrowser.core.model.filter.parser.LdapFilterParser;
 import org.apache.directory.studio.ldapbrowser.core.model.filter.parser.LdapFilterToken;
@@ -41,6 +42,7 @@
 import org.eclipse.jface.text.source.IAnnotationModelExtension;
 import org.eclipse.jface.text.source.ISourceViewer;
 import org.eclipse.jface.text.source.MatchingCharacterPainter;
+import org.eclipse.swt.graphics.Color;
 
 
 /**
@@ -61,7 +63,6 @@
     /** The paint manager. */
     private PaintManager paintManager;
 
-
     /**
      * Creates a new instance of FilterReconcilingStrategy.
      * 
@@ -88,16 +89,19 @@
         }
 
         // add annotation painter
-        if ( paintManager == null && sourceViewer.getAnnotationModel() instanceof IAnnotationModelExtension )
+        Color annotationColor = CommonUIPlugin.getDefault().getColor( CommonUIConstants.KEYWORD_1_COLOR );
+        if ( paintManager == null && annotationColor != null
+            && sourceViewer.getAnnotationModel() instanceof IAnnotationModelExtension )
         {
             AnnotationPainter ap = new AnnotationPainter( sourceViewer, null );
             ap.addAnnotationType( "DEFAULT" ); //$NON-NLS-1$
-            ap.setAnnotationTypeColor( "DEFAULT", CommonUIConstants.RED_COLOR ); //$NON-NLS-1$
+            ap.setAnnotationTypeColor( "DEFAULT", //$NON-NLS-1$
+                CommonUIPlugin.getDefault().getColor( CommonUIConstants.ERROR_COLOR ) );
             sourceViewer.getAnnotationModel().addAnnotationModelListener( ap );
 
             FilterCharacterPairMatcher cpm = new FilterCharacterPairMatcher( sourceViewer, parser );
             MatchingCharacterPainter mcp = new MatchingCharacterPainter( sourceViewer, cpm );
-            mcp.setColor( CommonUIConstants.ML_GREY_COLOR );
+            mcp.setColor( annotationColor );
 
             paintManager = new PaintManager( sourceViewer );
             paintManager.addPainter( ap );
@@ -137,8 +141,9 @@
                 {
                     int start = invalidFilters[i].getStartToken().getOffset();
                     int stop = invalidFilters[i].getStopToken() != null ? invalidFilters[i].getStopToken().getOffset()
-                        + invalidFilters[i].getStopToken().getLength() : start
-                        + invalidFilters[i].getStartToken().getLength();
+                        + invalidFilters[i].getStopToken().getLength()
+                        : start
+                            + invalidFilters[i].getStartToken().getLength();
 
                     Annotation annotation = new Annotation( "DEFAULT", true, invalidFilters[i].toString() ); //$NON-NLS-1$
                     Position position = new Position( start, stop - start );
diff --git a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserActionGroup.java b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserActionGroup.java
index 19ce485..68dd46f 100644
--- a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserActionGroup.java
+++ b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserActionGroup.java
@@ -108,8 +108,7 @@
         showQuickSearchAction = new ShowQuickSearchAction( mainWidget.getQuickSearchWidget() );
         collapseAllAction = new CollapseAllAction( viewer );
 
-        browserActionMap.put( OPEN_QUICK_SEARCH_ACTION, new BrowserViewActionProxy( viewer, new OpenQuickSearchAction(
-            mainWidget ) ) );
+        browserActionMap.put( OPEN_QUICK_SEARCH_ACTION, new BrowserViewActionProxy( viewer, new OpenQuickSearchAction() ) );
         browserActionMap.put( UP_ACTION, new BrowserViewActionProxy( viewer, new UpAction( viewer ) ) );
         browserActionMap.put( REFRESH_ACTION, new BrowserViewActionProxy( viewer, new RefreshAction() ) );
         browserActionMap.put( FILTER_CHILDREN_ACTION, new BrowserViewActionProxy( viewer, new FilterChildrenAction() ) );
diff --git a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserContentProvider.java b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserContentProvider.java
index 87436e8..b4d9573 100644
--- a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserContentProvider.java
+++ b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserContentProvider.java
@@ -60,9 +60,6 @@
  */
 public class BrowserContentProvider implements ITreeContentProvider
 {
-    /** The browser widget */
-    private BrowserWidget widget;
-
     /** The viewer. */
     private TreeViewer viewer;
 
@@ -106,7 +103,6 @@
      */
     public BrowserContentProvider( BrowserWidget widget, BrowserPreferences preferences, BrowserSorter sorter )
     {
-        this.widget = widget;
         this.viewer = widget.getViewer();
         this.preferences = preferences;
         this.sorter = sorter;
@@ -367,6 +363,14 @@
                 }
             }
 
+            List<Object> objects = new ArrayList<Object>();
+
+            IQuickSearch quickSearch = getQuickSearchForEntry( parentEntry );
+            if ( quickSearch != null )
+            {
+                objects.add( quickSearch );
+            }
+
             if ( !parentEntry.isChildrenInitialized() )
             {
                 new StudioBrowserJob( new InitializeChildrenRunnable( false, parentEntry ) ).execute();
@@ -382,14 +386,6 @@
 
                 IEntry[] results = parentEntry.getChildren();
 
-                List<Object> objects = new ArrayList<Object>();
-
-                if ( widget.getQuickSearch() != null
-                    && parentEntry.getDn().equals( widget.getQuickSearch().getSearchBase() ) )
-                {
-                    objects.add( widget.getQuickSearch() );
-                }
-
                 if ( parentEntry.getTopPageChildrenRunnable() != null )
                 {
                     objects.add( parentEntry.getTopPageChildrenRunnable() );
@@ -408,14 +404,6 @@
             {
                 BrowserEntryPage[] entryPages = getEntryPages( parentEntry );
 
-                List<Object> objects = new ArrayList<Object>();
-
-                if ( widget.getQuickSearch() != null
-                    && parentEntry.getDn().equals( widget.getQuickSearch().getSearchBase() ) )
-                {
-                    objects.add( widget.getQuickSearch() );
-                }
-
                 objects.addAll( Arrays.asList( entryPages ) );
 
                 return objects.toArray();
@@ -555,7 +543,7 @@
         if ( parent instanceof IEntry )
         {
             IEntry parentEntry = ( IEntry ) parent;
-            return parentEntry.hasChildren();
+            return parentEntry.hasChildren() || getQuickSearchForEntry( parentEntry ) != null;
         }
         else if ( parent instanceof SearchContinuation )
         {
@@ -588,6 +576,19 @@
     }
 
 
+    private IQuickSearch getQuickSearchForEntry( IEntry parentEntry )
+    {
+        IQuickSearch quickSearch = parentEntry.getBrowserConnection().getQuickSearch();
+        if ( quickSearch != null
+            && parentEntry.getDn().equals( quickSearch.getSearchBase() ) )
+        {
+            return quickSearch;
+        }
+
+        return null;
+    }
+
+
     private BrowserEntryPage[] getEntryPages( final IEntry parentEntry )
     {
         BrowserEntryPage[] entryPages;
diff --git a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserQuickSearchWidget.java b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserQuickSearchWidget.java
index b28b8cf..bdfb6d8 100644
--- a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserQuickSearchWidget.java
+++ b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserQuickSearchWidget.java
@@ -333,7 +333,7 @@
         quickSearch.getSearchParameter().setFilter( filter.toString() );
 
         // set new quick search
-        browserWidget.setQuickSearch( quickSearch );
+        conn.setQuickSearch( quickSearch );
 
         // execute quick search
         new StudioBrowserJob( new SearchRunnable( new ISearch[]
diff --git a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserUniversalListener.java b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserUniversalListener.java
index 244d6a4..984f1ae 100644
--- a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserUniversalListener.java
+++ b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserUniversalListener.java
@@ -277,9 +277,9 @@
 
         if ( ( search instanceof IQuickSearch ) && ( searchUpdateEvent.getDetail() == EventDetail.SEARCH_REMOVED ) )
         {
-            if ( widget.getQuickSearch() == search )
+            if ( search.getBrowserConnection().getQuickSearch() == search )
             {
-                widget.setQuickSearch( null );
+                search.getBrowserConnection().setQuickSearch( null );
             }
         }
 
diff --git a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserWidget.java b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserWidget.java
index f7ef227..70856a2 100644
--- a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserWidget.java
+++ b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserWidget.java
@@ -24,7 +24,6 @@
 import org.apache.directory.studio.common.ui.widgets.BaseWidgetUtils;
 import org.apache.directory.studio.common.ui.widgets.ViewFormWidget;
 import org.apache.directory.studio.ldapbrowser.common.dialogs.SelectEntryDialog;
-import org.apache.directory.studio.ldapbrowser.core.model.IQuickSearch;
 import org.eclipse.jface.action.IMenuManager;
 import org.eclipse.jface.action.IToolBarManager;
 import org.eclipse.jface.viewers.TreeViewer;
@@ -65,9 +64,6 @@
     /** The tree viewer. */
     private TreeViewer viewer;
 
-    /** The quick search. */
-    private IQuickSearch quickSearch;
-
 
     /**
      * Creates a new instance of BrowserWidget.
@@ -246,26 +242,4 @@
     {
         return viewer;
     }
-
-
-    /**
-     * Sets the quick search.
-     * 
-     * @param quickSearch the new quick search
-     */
-    public void setQuickSearch( IQuickSearch quickSearch )
-    {
-        this.quickSearch = quickSearch;
-    }
-
-
-    /**
-     * Gets the quick search.
-     * 
-     * @return the quick search
-     */
-    public IQuickSearch getQuickSearch()
-    {
-        return quickSearch;
-    }
 }
diff --git a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/connection/messages.properties b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/connection/messages.properties
index fd9548f..b1d9963 100644
--- a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/connection/messages.properties
+++ b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/connection/messages.properties
@@ -38,11 +38,11 @@
 EditorParameterPage.ModifyGroup=Entry Modifcation
 EditorParameterPage.ModifyMode=Modify Mode:
 EditorParameterPage.ModifyModeAddDel=Always use ADD and/or DELETE
-EditorParameterPage.ModifyModeDefault=Optimized Modify Operations
+EditorParameterPage.ModifyModeDefault=Default
 EditorParameterPage.ModifyModeNoEMR=Modify Mode (no equality matching rule):
-EditorParameterPage.ModifyModeNoEMRTooltip=Specify the modify mode for attributes with *no* equality matching rule.\n\nDescription of options:\n* Optimized Modify Operations: uses add/delete by default, uses replace if operation count is less\n* Always use REPLACE: always uses replace operations to perform entry modifications\n* Always use ADD and/or DELETE: always uses add and/or delete operations to perform entry modifications\n\nRecommended values for various LDAP servers:\n* ApacheDS: Optimized Modify Operations or REPLACE\n* OpenLDAP: REPLACE\n* OpenDS / SunDSEE: Optimized Modify Operations or REPLACE\n* FedoraDS / 389DS: Optimized Modify Operations (missing equality matching rules for many standard attribute types)\n* Active Directory: Optimized Modify Operations (exposes no equality matching rules at all)\n* eDirectory: Optimized Modify Operations (exposes no equality matching rules at all)
+EditorParameterPage.ModifyModeNoEMRTooltip=Specify the modify mode for attributes with *no* equality matching rule.\n\nDescription of options:\n* Default: uses add/delete by default, uses replace for X-ORDERED attributes\n* Always use REPLACE: always uses replace operations to perform entry modifications\n* Always use ADD and/or DELETE: always uses add and/or delete operations to perform entry modifications\n\nRecommended values for various LDAP servers:\n* ApacheDS: Default or REPLACE\n* OpenLDAP: REPLACE\n* OpenDS / SunDSEE: Default or REPLACE\n* FedoraDS / 389DS: Defult (missing equality matching rules for many standard attribute types)\n* Active Directory: Default (exposes no equality matching rules at all)\n* eDirectory: Default (exposes no equality matching rules at all)
 EditorParameterPage.ModifyModeReplace=Always use REPLACE
-EditorParameterPage.ModifyModeTooltip=Specify the modify mode for attributes with an equality matching rule.\n\nDescription of options:\n* Optimized Modify Operations: uses add/delete by default, uses replace if operation count is less\n* Always REPLACE: always uses replace operations to perform entry modifications\n* Always ADD/DELETE: always uses add and/or delete operations to perform entry modifications\n\nRecommended value: Optimized Modify Operations
+EditorParameterPage.ModifyModeTooltip=Specify the modify mode for attributes with an equality matching rule.\n\nDescription of options:\n* Default: uses add/delete by default, uses replace for X-ORDERED attributes\n* Always REPLACE: always uses replace operations to perform entry modifications\n* Always ADD/DELETE: always uses add and/or delete operations to perform entry modifications\n\nRecommended value: Default
 EditorParameterPage.ModifyOrder=Modify Order:
 EditorParameterPage.ModifyOrderAddFirst=ADD First
 EditorParameterPage.ModifyOrderDelFirst=DELETE First
diff --git a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/entryeditor/EntryEditorWidget.java b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/entryeditor/EntryEditorWidget.java
index 12b78cc..57f3527 100644
--- a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/entryeditor/EntryEditorWidget.java
+++ b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/entryeditor/EntryEditorWidget.java
@@ -86,7 +86,7 @@
         quickFilterWidget.createComposite( parent );
 
         // create tree widget and viewer
-        tree = new Tree( parent, SWT.MULTI | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION
+        tree = new Tree( parent, SWT.VIRTUAL | SWT.MULTI | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION
             | SWT.HIDE_SELECTION );
         GridData data = new GridData( GridData.FILL_BOTH );
         data.widthHint = 450;
diff --git a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/entryeditor/EntryEditorWidgetLabelProvider.java b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/entryeditor/EntryEditorWidgetLabelProvider.java
index 3acca40..1ee5a33 100644
--- a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/entryeditor/EntryEditorWidgetLabelProvider.java
+++ b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/entryeditor/EntryEditorWidgetLabelProvider.java
@@ -22,12 +22,14 @@
 
 
 import org.apache.directory.studio.common.ui.CommonUIConstants;
+import org.apache.directory.studio.common.ui.CommonUIPlugin;
 import org.apache.directory.studio.ldapbrowser.common.BrowserCommonActivator;
 import org.apache.directory.studio.ldapbrowser.common.BrowserCommonConstants;
 import org.apache.directory.studio.ldapbrowser.core.model.IAttribute;
 import org.apache.directory.studio.ldapbrowser.core.model.IValue;
 import org.apache.directory.studio.valueeditors.IValueEditor;
 import org.apache.directory.studio.valueeditors.ValueEditorManager;
+import org.eclipse.jface.preference.IPreferenceStore;
 import org.eclipse.jface.preference.PreferenceConverter;
 import org.eclipse.jface.viewers.IColorProvider;
 import org.eclipse.jface.viewers.IFontProvider;
@@ -64,7 +66,6 @@
     /** The value editor manager. */
     private ValueEditorManager valueEditorManager;
 
-
     /**
      * Creates a new instance of EntryEditorWidgetLabelProvider.
      * 
@@ -115,7 +116,8 @@
             {
                 return NLS
                     .bind(
-                        Messages.getString( "EntryEditorWidgetLabelProvider.AttributeLabel" ), attribute.getDescription(), getNumberOfValues( attribute ) ); //$NON-NLS-1$
+                        Messages.getString( "EntryEditorWidgetLabelProvider.AttributeLabel" ), //$NON-NLS-1$
+                        attribute.getDescription(), getNumberOfValues( attribute ) );
             }
             else
             {
@@ -262,15 +264,15 @@
         {
             if ( value.isEmpty() )
             {
-                return CommonUIConstants.RED_COLOR;
+                return CommonUIPlugin.getDefault().getColor( CommonUIConstants.ERROR_COLOR );
             }
         }
-        
+
         if ( attribute != null && value == null )
         {
             if ( !attribute.isConsistent() )
             {
-                return CommonUIConstants.RED_COLOR;
+                return CommonUIPlugin.getDefault().getColor( CommonUIConstants.ERROR_COLOR );
             }
         }
 
@@ -279,27 +281,19 @@
         {
             if ( attribute.isObjectClassAttribute() )
             {
-                RGB rgb = PreferenceConverter.getColor( BrowserCommonActivator.getDefault().getPreferenceStore(),
-                    BrowserCommonConstants.PREFERENCE_OBJECTCLASS_COLOR );
-                return BrowserCommonActivator.getDefault().getColor( rgb );
+                return getColorIfNotDefaultElseNull( BrowserCommonConstants.PREFERENCE_OBJECTCLASS_COLOR );
             }
             else if ( attribute.isMustAttribute() )
             {
-                RGB rgb = PreferenceConverter.getColor( BrowserCommonActivator.getDefault().getPreferenceStore(),
-                    BrowserCommonConstants.PREFERENCE_MUSTATTRIBUTE_COLOR );
-                return BrowserCommonActivator.getDefault().getColor( rgb );
+                return getColorIfNotDefaultElseNull( BrowserCommonConstants.PREFERENCE_MUSTATTRIBUTE_COLOR );
             }
             else if ( attribute.isOperationalAttribute() )
             {
-                RGB rgb = PreferenceConverter.getColor( BrowserCommonActivator.getDefault().getPreferenceStore(),
-                    BrowserCommonConstants.PREFERENCE_OPERATIONALATTRIBUTE_COLOR );
-                return BrowserCommonActivator.getDefault().getColor( rgb );
+                return getColorIfNotDefaultElseNull( BrowserCommonConstants.PREFERENCE_OPERATIONALATTRIBUTE_COLOR );
             }
             else
             {
-                RGB rgb = PreferenceConverter.getColor( BrowserCommonActivator.getDefault().getPreferenceStore(),
-                    BrowserCommonConstants.PREFERENCE_MAYATTRIBUTE_COLOR );
-                return BrowserCommonActivator.getDefault().getColor( rgb );
+                return getColorIfNotDefaultElseNull( BrowserCommonConstants.PREFERENCE_MAYATTRIBUTE_COLOR );
             }
         }
         else
@@ -309,6 +303,20 @@
     }
 
 
+    private Color getColorIfNotDefaultElseNull( String color )
+    {
+        BrowserCommonActivator plugin = BrowserCommonActivator.getDefault();
+        IPreferenceStore preferenceStore = plugin.getPreferenceStore();
+
+        if ( preferenceStore.isDefault( color ) )
+        {
+            return null;
+        }
+        RGB rgb = PreferenceConverter.getColor( preferenceStore, color );
+        return plugin.getColor( rgb );
+    }
+
+
     /**
      * {@inheritDoc}
      */
diff --git a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/wizards/NewEntryAttributesWizardPage.java b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/wizards/NewEntryAttributesWizardPage.java
index b6409ea..ebba3c7 100644
--- a/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/wizards/NewEntryAttributesWizardPage.java
+++ b/plugins/ldapbrowser.common/src/main/java/org/apache/directory/studio/ldapbrowser/common/wizards/NewEntryAttributesWizardPage.java
@@ -184,7 +184,7 @@
 
                 // remove empty must attributes
                 // necessary when navigating back, modifying object classes
-                // and Dn and navigation forward again.
+                // and Dn and navigating forward again.
                 Collection<AttributeType> oldMusts = SchemaUtils.getMustAttributeTypeDescriptions( newEntry );
                 for ( AttributeType oldMust : oldMusts )
                 {
diff --git a/plugins/ldapbrowser.common/src/test/java/org/apache/directory/studio/ldapbrowser/common/widgets/entryeditor/EntryEditorWidgetSorterTest.java b/plugins/ldapbrowser.common/src/test/java/org/apache/directory/studio/ldapbrowser/common/widgets/entryeditor/EntryEditorWidgetSorterTest.java
index 59aad89..c39e943 100644
--- a/plugins/ldapbrowser.common/src/test/java/org/apache/directory/studio/ldapbrowser/common/widgets/entryeditor/EntryEditorWidgetSorterTest.java
+++ b/plugins/ldapbrowser.common/src/test/java/org/apache/directory/studio/ldapbrowser/common/widgets/entryeditor/EntryEditorWidgetSorterTest.java
@@ -22,14 +22,14 @@
 
 
 import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
+import static org.hamcrest.MatcherAssert.assertThat;
 
 import org.apache.directory.studio.ldapbrowser.core.model.IAttribute;
 import org.apache.directory.studio.ldapbrowser.core.model.impl.Attribute;
 import org.apache.directory.studio.ldapbrowser.core.model.impl.DummyEntry;
 import org.apache.directory.studio.ldapbrowser.core.model.impl.Value;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 
 /**
@@ -45,7 +45,7 @@
     private Value empytValue2;
 
 
-    @Before
+    @BeforeEach
     public void setup()
     {
         sorter = new EntryEditorWidgetSorter( null );
diff --git a/plugins/ldapbrowser.common/src/test/java/org/apache/directory/studio/ldapbrowser/common/widgets/search/ReturningAttributesWidgetTest.java b/plugins/ldapbrowser.common/src/test/java/org/apache/directory/studio/ldapbrowser/common/widgets/search/ReturningAttributesWidgetTest.java
index ca63891..5fa6e18 100644
--- a/plugins/ldapbrowser.common/src/test/java/org/apache/directory/studio/ldapbrowser/common/widgets/search/ReturningAttributesWidgetTest.java
+++ b/plugins/ldapbrowser.common/src/test/java/org/apache/directory/studio/ldapbrowser/common/widgets/search/ReturningAttributesWidgetTest.java
@@ -21,11 +21,11 @@
 package org.apache.directory.studio.ldapbrowser.common.widgets.search;
 
 
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 
 /**
diff --git a/plugins/ldapbrowser.common/src/test/java/org/apache/directory/studio/valueeditors/ValueEditorUtilsTest.java b/plugins/ldapbrowser.common/src/test/java/org/apache/directory/studio/valueeditors/ValueEditorUtilsTest.java
index 275b0b8..bf16565 100644
--- a/plugins/ldapbrowser.common/src/test/java/org/apache/directory/studio/valueeditors/ValueEditorUtilsTest.java
+++ b/plugins/ldapbrowser.common/src/test/java/org/apache/directory/studio/valueeditors/ValueEditorUtilsTest.java
@@ -21,12 +21,12 @@
 package org.apache.directory.studio.valueeditors;
 
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.nio.charset.StandardCharsets;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 
 /**
diff --git a/plugins/ldapbrowser.core/about.html b/plugins/ldapbrowser.core/about.html
index 975701a..84373e6 100644
--- a/plugins/ldapbrowser.core/about.html
+++ b/plugins/ldapbrowser.core/about.html
@@ -9,7 +9,7 @@
 
 <h3>Copyright</h3>
 
-<p>Copyright (c) 2006-2020 The Apache Software Foundation. All rights reserved.</p>
+<p>Copyright (c) 2006-2021 The Apache Software Foundation. All rights reserved.</p>
 
 <h3>License</h3>
 
diff --git a/plugins/ldapbrowser.core/pom-first.xml b/plugins/ldapbrowser.core/pom-first.xml
index cece9ab..bb34e8d 100644
--- a/plugins/ldapbrowser.core/pom-first.xml
+++ b/plugins/ldapbrowser.core/pom-first.xml
@@ -32,15 +32,6 @@
   <description/>
   <packaging>bundle</packaging>
 
-  <dependencies>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>${junit.version}</version>
-      <scope>test</scope>
-    </dependency>
-  </dependencies>
-  
   <build>
     <plugins>
       <!-- Embedded artifacts -->
diff --git a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/CopyEntriesRunnable.java b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/CopyEntriesRunnable.java
index 50e9c06..ea87931 100644
--- a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/CopyEntriesRunnable.java
+++ b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/CopyEntriesRunnable.java
@@ -43,6 +43,7 @@
 import org.apache.directory.studio.connection.core.Connection.AliasDereferencingMethod;
 import org.apache.directory.studio.connection.core.Connection.ReferralHandlingMethod;
 import org.apache.directory.studio.connection.core.Controls;
+import org.apache.directory.studio.connection.core.io.StudioLdapException;
 import org.apache.directory.studio.connection.core.io.api.StudioSearchResultEnumeration;
 import org.apache.directory.studio.connection.core.jobs.StudioConnectionBulkRunnableWithProgress;
 import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
@@ -317,7 +318,8 @@
 
                 while ( dummyMonitor.errorsReported() )
                 {
-                    if ( dialog != null && dummyMonitor.getException() instanceof LdapEntryAlreadyExistsException )
+                    if ( dialog != null
+                        && StudioLdapException.isEntryAlreadyExistsException( dummyMonitor.getException() ) )
                     {
                         // open dialog
                         dialog.setExistingEntry( targetBrowserConnection, newLdapDn );
diff --git a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/DeleteEntriesRunnable.java b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/DeleteEntriesRunnable.java
index b7bd125..a9b2935 100644
--- a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/DeleteEntriesRunnable.java
+++ b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/DeleteEntriesRunnable.java
@@ -31,7 +31,6 @@
 
 import javax.naming.directory.SearchControls;
 
-import org.apache.directory.api.ldap.model.exception.LdapContextNotEmptyException;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.studio.common.core.jobs.StudioProgressMonitor;
@@ -40,6 +39,7 @@
 import org.apache.directory.studio.connection.core.Connection.AliasDereferencingMethod;
 import org.apache.directory.studio.connection.core.Connection.ReferralHandlingMethod;
 import org.apache.directory.studio.connection.core.StudioControl;
+import org.apache.directory.studio.connection.core.io.StudioLdapException;
 import org.apache.directory.studio.connection.core.io.api.StudioSearchResultEnumeration;
 import org.apache.directory.studio.connection.core.jobs.StudioConnectionBulkRunnableWithProgress;
 import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
@@ -276,7 +276,7 @@
                 new String[]
                     { "" + numberOfDeletedEntries } ) ); //$NON-NLS-1$
         }
-        else if ( dummyMonitor.getException() instanceof LdapContextNotEmptyException )
+        else if ( StudioLdapException.isContextNotEmptyException( dummyMonitor.getException() ) )
         {
             // do not follow referrals or dereference aliases when deleting entries
             AliasDereferencingMethod aliasDereferencingMethod = AliasDereferencingMethod.NEVER;
diff --git a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ExportLdifRunnable.java b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ExportLdifRunnable.java
index 2879339..f559468 100644
--- a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ExportLdifRunnable.java
+++ b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ExportLdifRunnable.java
@@ -28,6 +28,7 @@
 import java.util.List;
 
 import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.lang3.ArrayUtils;
 import org.apache.directory.api.ldap.model.entry.Attribute;
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.entry.Value;
@@ -273,7 +274,7 @@
                     if ( responseControl instanceof PagedResults )
                     {
                         PagedResults prc = ( PagedResults ) responseControl;
-                        if ( prc.getCookieValue() > 0 )
+                        if ( ArrayUtils.isNotEmpty( prc.getCookie() ) )
                         {
                             // search again: pass the response control cookie to the request control
                             byte[] cookie = prc.getCookie();
diff --git a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ImportLdifRunnable.java b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ImportLdifRunnable.java
index cf7b569..d0c301d 100644
--- a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ImportLdifRunnable.java
+++ b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ImportLdifRunnable.java
@@ -42,7 +42,6 @@
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.entry.Modification;
 import org.apache.directory.api.ldap.model.entry.ModificationOperation;
-import org.apache.directory.api.ldap.model.exception.LdapEntryAlreadyExistsException;
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
 import org.apache.directory.api.ldap.model.exception.LdapSchemaException;
@@ -52,6 +51,7 @@
 import org.apache.directory.studio.connection.core.Connection;
 import org.apache.directory.studio.connection.core.ConnectionCoreConstants;
 import org.apache.directory.studio.connection.core.Controls;
+import org.apache.directory.studio.connection.core.io.StudioLdapException;
 import org.apache.directory.studio.connection.core.jobs.StudioConnectionBulkRunnableWithProgress;
 import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
 import org.apache.directory.studio.ldapbrowser.core.events.BulkModificationEvent;
@@ -445,7 +445,7 @@
                 .createEntry( entry, getControls( record ), monitor, null );
 
             if ( monitor.errorsReported() && updateIfEntryExists
-                && monitor.getException() instanceof LdapEntryAlreadyExistsException )
+                && StudioLdapException.isEntryAlreadyExistsException( monitor.getException() ) )
             {
                 // creation failed with Error 68, now try to update the existing entry
                 monitor.reset();
diff --git a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/InitializeChildrenRunnable.java b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/InitializeChildrenRunnable.java
index 47e1e14..32eeb12 100644
--- a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/InitializeChildrenRunnable.java
+++ b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/InitializeChildrenRunnable.java
@@ -25,6 +25,7 @@
 import java.util.Arrays;
 import java.util.List;
 
+import org.apache.commons.lang3.ArrayUtils;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.message.SearchScope;
 import org.apache.directory.api.ldap.model.message.controls.PagedResults;
@@ -65,7 +66,6 @@
     /** The paged search control, only used internally. */
     private PagedResults pagedSearchControl;
 
-
     /**
      * Creates a new instance of InitializeChildrenRunnable.
      * 
@@ -198,7 +198,7 @@
     {
         monitor.reportProgress( BrowserCoreMessages.bind( BrowserCoreMessages.jobs__init_entries_progress_sub,
             new String[]
-                { parent.getDn().getName() } ) );
+            { parent.getDn().getName() } ) );
 
         // clear old children
         clearCaches( parent, purgeAllCaches );
@@ -262,7 +262,7 @@
                 {
                     if ( search.isPagedSearchScrollMode() )
                     {
-                        if ( prRequestControl.getCookieValue() > 0 )
+                        if ( ArrayUtils.isNotEmpty( prRequestControl.getCookie() ) )
                         {
                             // create top page search runnable, same as original search
                             InitializeChildrenRunnable topPageChildrenRunnable = new InitializeChildrenRunnable(
@@ -270,7 +270,7 @@
                             parent.setTopPageChildrenRunnable( topPageChildrenRunnable );
                         }
 
-                        if ( prResponseControl.getCookieValue() > 0 )
+                        if ( ArrayUtils.isNotEmpty( prResponseControl.getCookie() ) )
                         {
                             PagedResults newPrc = Controls.newPagedResultsControl( prRequestControl.getSize(),
                                 prResponseControl.getCookie() );
@@ -282,7 +282,7 @@
                     else
                     {
                         // transparently continue search, till count limit is reached
-                        if ( prResponseControl.getCookieValue() > 0
+                        if ( ArrayUtils.isNotEmpty( prResponseControl.getCookie() )
                             && ( search.getCountLimit() == 0 || search.getSearchResults().length < search
                                 .getCountLimit() ) )
                         {
@@ -359,7 +359,7 @@
         ISearchResult[] srs = search.getSearchResults();
         monitor.reportProgress( BrowserCoreMessages.bind( BrowserCoreMessages.jobs__init_entries_progress_subcount,
             new String[]
-                { srs == null ? Integer.toString( 0 ) : Integer.toString( srs.length ), parent.getDn().getName() } ) );
+            { srs == null ? Integer.toString( 0 ) : Integer.toString( srs.length ), parent.getDn().getName() } ) );
     }
 
 
diff --git a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/MoveEntriesRunnable.java b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/MoveEntriesRunnable.java
index 3b18a26..f0a50e5 100644
--- a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/MoveEntriesRunnable.java
+++ b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/MoveEntriesRunnable.java
@@ -29,13 +29,13 @@
 
 import javax.naming.directory.SearchControls;
 
-import org.apache.directory.api.ldap.model.exception.LdapContextNotEmptyException;
 import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.studio.common.core.jobs.StudioProgressMonitor;
 import org.apache.directory.studio.connection.core.Connection;
 import org.apache.directory.studio.connection.core.Controls;
+import org.apache.directory.studio.connection.core.io.StudioLdapException;
 import org.apache.directory.studio.connection.core.jobs.StudioConnectionBulkRunnableWithProgress;
 import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
 import org.apache.directory.studio.ldapbrowser.core.events.BulkModificationEvent;
@@ -181,7 +181,7 @@
             // do a simulated rename, if renaming of a non-leaf entry is not supported.
             if ( dummyMonitor.errorsReported() )
             {
-                if ( dialog != null && dummyMonitor.getException() instanceof LdapContextNotEmptyException )
+                if ( dialog != null && StudioLdapException.isContextNotEmptyException( dummyMonitor.getException() ) )
                 {
                     // open dialog
                     if ( numAdd == 0 )
diff --git a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/RenameEntryRunnable.java b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/RenameEntryRunnable.java
index 7b718e5..f6c3bc6 100644
--- a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/RenameEntryRunnable.java
+++ b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/RenameEntryRunnable.java
@@ -28,7 +28,6 @@
 
 import javax.naming.directory.SearchControls;
 
-import org.apache.directory.api.ldap.model.exception.LdapContextNotEmptyException;
 import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.name.Dn;
@@ -36,6 +35,7 @@
 import org.apache.directory.studio.common.core.jobs.StudioProgressMonitor;
 import org.apache.directory.studio.connection.core.Connection;
 import org.apache.directory.studio.connection.core.Controls;
+import org.apache.directory.studio.connection.core.io.StudioLdapException;
 import org.apache.directory.studio.connection.core.jobs.StudioConnectionBulkRunnableWithProgress;
 import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
 import org.apache.directory.studio.ldapbrowser.core.events.EntryRenamedEvent;
@@ -166,7 +166,7 @@
         // do a simulated rename, if renaming of a non-leaf entry is not supported.
         if ( dummyMonitor.errorsReported() && !monitor.isCanceled() )
         {
-            if ( dialog != null && dummyMonitor.getException() instanceof LdapContextNotEmptyException )
+            if ( dialog != null && StudioLdapException.isContextNotEmptyException( dummyMonitor.getException() ) )
             {
                 // open dialog
                 dialog.setEntryInfo( browserConnection, oldDn, newDn );
diff --git a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/SearchRunnable.java b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/SearchRunnable.java
index e0cf39f..0932ac7 100644
--- a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/SearchRunnable.java
+++ b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/SearchRunnable.java
@@ -31,13 +31,13 @@
 
 import javax.naming.directory.SearchControls;
 
+import org.apache.commons.lang3.ArrayUtils;
 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
 import org.apache.directory.api.ldap.model.entry.Attribute;
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.message.Control;
 import org.apache.directory.api.ldap.model.message.SearchScope;
 import org.apache.directory.api.ldap.model.message.controls.PagedResults;
-import org.apache.directory.api.ldap.model.message.controls.PagedResultsImpl;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.url.LdapUrl;
 import org.apache.directory.api.util.Strings;
@@ -47,7 +47,6 @@
 import org.apache.directory.studio.connection.core.Connection.AliasDereferencingMethod;
 import org.apache.directory.studio.connection.core.Connection.ReferralHandlingMethod;
 import org.apache.directory.studio.connection.core.StudioControl;
-import org.apache.directory.studio.connection.core.StudioPagedResultsControl;
 import org.apache.directory.studio.connection.core.io.api.StudioSearchResult;
 import org.apache.directory.studio.connection.core.io.api.StudioSearchResultEnumeration;
 import org.apache.directory.studio.connection.core.jobs.StudioConnectionBulkRunnableWithProgress;
@@ -240,7 +239,7 @@
                         nextPageSearch.getControls().add( nextPrc );
                         if ( search.isPagedSearchScrollMode() )
                         {
-                            if ( prRequestControl.getCookieValue() > 0 )
+                            if ( ArrayUtils.isNotEmpty( prRequestControl.getCookie() ) )
                             {
                                 // create top page search runnable, same as original search
                                 ISearch topPageSearch = ( ISearch ) search.clone();
@@ -248,7 +247,7 @@
                                 SearchRunnable topPageSearchRunnable = new SearchRunnable( search, topPageSearch );
                                 search.setTopPageSearchRunnable( topPageSearchRunnable );
                             }
-                            if ( prResponseControl.getCookieValue() > 0 )
+                            if ( ArrayUtils.isNotEmpty( prResponseControl.getCookie() ) )
                             {
                                 // create next page search runnable
                                 SearchRunnable nextPageSearchRunnable = new SearchRunnable( search, nextPageSearch );
@@ -258,7 +257,7 @@
                         else
                         {
                             // transparently continue search, till count limit is reached
-                            if ( prResponseControl.getCookieValue() > 0
+                            if ( ArrayUtils.isNotEmpty( prResponseControl.getCookie() )
                                 && ( search.getCountLimit() == 0 || search.getSearchResults().length < search
                                     .getCountLimit() ) )
                             {
@@ -406,7 +405,8 @@
                             search.getResponseControls().add( control );
                             if ( control instanceof PagedResults )
                             {
-                                search.setCountLimitExceeded( ( ( PagedResults ) control ).getCookieValue() > 0 );
+                                search.setCountLimitExceeded(
+                                    ArrayUtils.isNotEmpty( ( ( PagedResults ) control ).getCookie() ) );
                             }
                         }
                     }
diff --git a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/model/IBrowserConnection.java b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/model/IBrowserConnection.java
index 6dae532..d679c10 100644
--- a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/model/IBrowserConnection.java
+++ b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/model/IBrowserConnection.java
@@ -456,6 +456,22 @@
 
 
     /**
+     * Sets the quick search.
+     * 
+     * @param quickSearch the new quick search
+     */
+     void setQuickSearch( IQuickSearch quickSearch );
+
+
+    /**
+     * Gets the quick search.
+     * 
+     * @return the quick search
+     */
+    IQuickSearch getQuickSearch();
+
+
+    /**
      * Gets the root DSE.
      * 
      * @return the root DSE
diff --git a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/model/IEntry.java b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/model/IEntry.java
index d7a942f..b7741e3 100644
--- a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/model/IEntry.java
+++ b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/model/IEntry.java
@@ -24,18 +24,11 @@
 import java.io.Serializable;
 import java.util.Collection;
 
-import org.apache.directory.api.ldap.model.entry.Attribute;
-import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
-import org.apache.directory.api.ldap.model.entry.DefaultEntry;
-import org.apache.directory.api.ldap.model.entry.Entry;
-import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.name.Rdn;
 import org.apache.directory.api.ldap.model.schema.ObjectClass;
 import org.apache.directory.api.ldap.model.url.LdapUrl;
 import org.apache.directory.studio.connection.core.ConnectionPropertyPageProvider;
-import org.apache.directory.studio.connection.core.io.LdapRuntimeException;
 import org.apache.directory.studio.connection.core.jobs.StudioConnectionBulkRunnableWithProgress;
 import org.apache.directory.studio.ldapbrowser.core.propertypageproviders.EntryPropertyPageProvider;
 import org.eclipse.core.runtime.IAdaptable;
@@ -471,38 +464,4 @@
      */
     Collection<ObjectClass> getObjectClassDescriptions();
 
-
-    default Entry toEntry()
-    {
-        try
-        {
-            Entry entry = new DefaultEntry( getDn() );
-            for ( IAttribute iAttribute : getAttributes() )
-            {
-                Attribute attribute = new DefaultAttribute( iAttribute.getType() );
-                for ( IValue iValue : iAttribute.getValues() )
-                {
-                    Object rawValue = iValue.getRawValue();
-                    if ( rawValue instanceof String )
-                    {
-                        attribute.add( ( String ) rawValue );
-                    }
-                    else if ( rawValue instanceof byte[] )
-                    {
-                        attribute.add( ( byte[] ) rawValue );
-                    }
-                    else
-                    {
-                        attribute.add( ( String ) null );
-                    }
-                }
-                entry.add( attribute );
-            }
-            return entry;
-        }
-        catch ( LdapException e )
-        {
-            throw new LdapRuntimeException( e );
-        }
-    }
 }
diff --git a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/model/impl/BrowserConnection.java b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/model/impl/BrowserConnection.java
index 38150f3..6717710 100644
--- a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/model/impl/BrowserConnection.java
+++ b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/model/impl/BrowserConnection.java
@@ -37,6 +37,7 @@
 import org.apache.directory.studio.ldapbrowser.core.internal.search.LdapSearchPageScoreComputer;
 import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection;
 import org.apache.directory.studio.ldapbrowser.core.model.IEntry;
+import org.apache.directory.studio.ldapbrowser.core.model.IQuickSearch;
 import org.apache.directory.studio.ldapbrowser.core.model.IRootDSE;
 import org.apache.directory.studio.ldapbrowser.core.model.ISearch;
 import org.apache.directory.studio.ldapbrowser.core.model.schema.Schema;
@@ -69,6 +70,9 @@
     /** The bookmark manager. */
     private BookmarkManager bookmarkManager;
 
+    /** The quick search. */
+    private IQuickSearch quickSearch;
+
     /** The dn to entry cache. */
     private volatile Map<String, IEntry> dnToEntryCache;
 
@@ -495,6 +499,24 @@
     }
 
 
+    /** 
+     * {@inheritDoc}
+     */
+    public void setQuickSearch( IQuickSearch quickSearch )
+    {
+        this.quickSearch = quickSearch;
+    }
+
+
+    /** 
+     * {@inheritDoc}
+     */
+    public IQuickSearch getQuickSearch()
+    {
+        return quickSearch;
+    }
+
+
     /**
      * {@inheritDoc}
      */
@@ -586,6 +608,9 @@
     protected synchronized void uncacheEntry( IEntry entry )
     {
         dnToEntryCache.remove( Utils.getNormalizedOidString( entry.getDn(), getSchema() ) );
+        setAttributeInfo( entry, null );
+        setChildrenInfo( entry, null );
+        setChildrenFilter(entry, null);
     }
 
 
@@ -607,17 +632,6 @@
 
 
     /**
-     * Removes the entry from the cache.
-     * 
-     * @param dn the Dn of the entry to remove from cache
-     */
-    protected synchronized void uncacheEntry( Dn dn )
-    {
-        dnToEntryCache.remove( Utils.getNormalizedOidString( dn, getSchema() ) );
-    }
-
-
-    /**
      * Gets the children filter of the entry.
      * 
      * @param entry the entry
diff --git a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/model/impl/DummyConnection.java b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/model/impl/DummyConnection.java
index 9a0dbd8..43d5845 100644
--- a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/model/impl/DummyConnection.java
+++ b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/model/impl/DummyConnection.java
@@ -28,6 +28,7 @@
 import org.apache.directory.studio.ldapbrowser.core.SearchManager;
 import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection;
 import org.apache.directory.studio.ldapbrowser.core.model.IEntry;
+import org.apache.directory.studio.ldapbrowser.core.model.IQuickSearch;
 import org.apache.directory.studio.ldapbrowser.core.model.IRootDSE;
 import org.apache.directory.studio.ldapbrowser.core.model.schema.Schema;
 
@@ -389,6 +390,23 @@
     /** 
      * {@inheritDoc}
      */
+    public void setQuickSearch( IQuickSearch quickSearch )
+    {
+    }
+
+
+    /** 
+     * {@inheritDoc}
+     */
+    public IQuickSearch getQuickSearch()
+    {
+        return null;
+    }
+
+
+    /** 
+     * {@inheritDoc}
+     */
     public LdapUrl getUrl()
     {
         return null;
diff --git a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/utils/ModelConverter.java b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/utils/ModelConverter.java
index 34e2163..1ee7a31 100644
--- a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/utils/ModelConverter.java
+++ b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/utils/ModelConverter.java
@@ -336,14 +336,14 @@
         {
             for ( IValue value : iAttribute.getValues() )
             {
-                String attributeType = value.getAttribute().getType();
+                String attributeDescription = value.getAttribute().getDescription();
                 if ( value.isString() )
                 {
-                    ldapApiEntry.add( attributeType, value.getStringValue() );
+                    ldapApiEntry.add( attributeDescription, value.getStringValue() );
                 }
                 else
                 {
-                    ldapApiEntry.add( attributeType, value.getBinaryValue() );
+                    ldapApiEntry.add( attributeDescription, value.getBinaryValue() );
                 }
             }
         }
diff --git a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/utils/Utils.java b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/utils/Utils.java
index af5b4fa..2cc7bad 100644
--- a/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/utils/Utils.java
+++ b/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/utils/Utils.java
@@ -30,6 +30,7 @@
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -406,7 +407,7 @@
         ModifyOrder modifyAddDeleteOrder = oldEntry.getBrowserConnection().getModifyAddDeleteOrder();
 
         // get all attribute descriptions
-        Set<String> attributeDescriptions = new HashSet<>();
+        Set<String> attributeDescriptions = new LinkedHashSet<>();
         
         for ( IAttribute oldAttr : oldEntry.getAttributes() )
         {
@@ -487,6 +488,10 @@
                 {
                     // delete all
                     modSpec = LdifModSpec.createDelete( attributeDescription );
+                    for ( IValue value : oldAttribute.getValues() )
+                    {
+                        modSpec.addAttrVal( computeDiffCreateAttrValLine( value ) );
+                    }
                 }
                 
                 modSpec.finish( LdifModSpecSepLine.create() );
@@ -558,16 +563,12 @@
                     /*
                      *  we use add/del in the following cases:
                      *  - add/del is forced in the connection configuration
-                     *  - only values to add
-                     *  - only values to delete
-                     *  - the sum of adds and deletes is smaller or equal than the number of replaces
+                     *  - for attributes w/o X-ORDERED 'VALUES'
                      *  
                      *  we use replace in the following cases:
-                     *  - the number of replaces is smaller to the sum of adds and deletes
                      *  - for attributes with X-ORDERED 'VALUES'
                      */
-                    if ( isAddDelForced || ( toAdd.size() + toDel.size() <= newAttrValLines.size() && !isOrderedValue )
-                        || ( !toDel.isEmpty() && toAdd.isEmpty() ) || ( !toAdd.isEmpty() && toDel.isEmpty() ) )
+                    if ( isAddDelForced || !isOrderedValue )
                     {
                         // add/del del/add
                         LdifModSpec addModSpec = LdifModSpec.createAdd( attributeDescription );
diff --git a/plugins/ldapbrowser.core/src/test/java/org/apache/directory/studio/ldapbrowser/core/model/LdapFilterParserErrorTolerantTest.java b/plugins/ldapbrowser.core/src/test/java/org/apache/directory/studio/ldapbrowser/core/model/LdapFilterParserErrorTolerantTest.java
index efaedd7..132b2bd 100755
--- a/plugins/ldapbrowser.core/src/test/java/org/apache/directory/studio/ldapbrowser/core/model/LdapFilterParserErrorTolerantTest.java
+++ b/plugins/ldapbrowser.core/src/test/java/org/apache/directory/studio/ldapbrowser/core/model/LdapFilterParserErrorTolerantTest.java
@@ -21,7 +21,11 @@
 package org.apache.directory.studio.ldapbrowser.core.model;
 
 
-import junit.framework.TestCase;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import org.apache.directory.studio.ldapbrowser.core.model.filter.LdapFilter;
 import org.apache.directory.studio.ldapbrowser.core.model.filter.LdapFilterComponent;
@@ -29,17 +33,19 @@
 import org.apache.directory.studio.ldapbrowser.core.model.filter.parser.LdapFilterParser;
 import org.apache.directory.studio.ldapbrowser.core.model.filter.parser.LdapFilterToken;
 
+import org.junit.jupiter.api.Test;
+
 
 /**
  * Tests the filter parser for error tolerance. 
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class LdapFilterParserErrorTolerantTest extends TestCase
+public class LdapFilterParserErrorTolerantTest
 {
     private LdapFilterParser parser = new LdapFilterParser();
 
-
+    @Test
     public void testLpar()
     {
         parser.parse( "(" ); //$NON-NLS-1$
@@ -62,6 +68,7 @@
     }
 
 
+    @Test
     public void testLparAttr()
     {
         parser.parse( "(objectClass" ); //$NON-NLS-1$
@@ -94,6 +101,7 @@
     }
 
 
+    @Test
     public void testLparAttrEquals()
     {
         parser.parse( "(objectClass=" ); //$NON-NLS-1$
@@ -132,6 +140,7 @@
     }
 
 
+    @Test
     public void testLparAttrEqualsRpar()
     {
         parser.parse( "(objectClass=)" ); //$NON-NLS-1$
diff --git a/plugins/ldapbrowser.core/src/test/java/org/apache/directory/studio/ldapbrowser/core/model/LdapFilterParserTest.java b/plugins/ldapbrowser.core/src/test/java/org/apache/directory/studio/ldapbrowser/core/model/LdapFilterParserTest.java
index 23f551f..897f6dc 100644
--- a/plugins/ldapbrowser.core/src/test/java/org/apache/directory/studio/ldapbrowser/core/model/LdapFilterParserTest.java
+++ b/plugins/ldapbrowser.core/src/test/java/org/apache/directory/studio/ldapbrowser/core/model/LdapFilterParserTest.java
@@ -21,17 +21,21 @@
 package org.apache.directory.studio.ldapbrowser.core.model;
 
 
-import junit.framework.TestCase;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import org.apache.directory.studio.ldapbrowser.core.model.filter.parser.LdapFilterParser;
 
+import org.junit.jupiter.api.Test;
+
 
 /**
  * Tests the filter parser.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class LdapFilterParserTest extends TestCase
+public class LdapFilterParserTest
 {
     private LdapFilterParser parser = new LdapFilterParser();
 
@@ -39,6 +43,7 @@
     /**
      * Tests an equals filter
      */
+    @Test
     public void testEqualsFilter()
     {
         parser.parse( "(cn=test)" ); //$NON-NLS-1$
@@ -51,6 +56,7 @@
     /**
      * Tests an greater equals filter
      */
+    @Test
     public void testGreaterEqualsFilter()
     {
         parser.parse( "(cn>=test)" ); //$NON-NLS-1$
@@ -63,6 +69,7 @@
     /**
      * Tests an less equals filter
      */
+    @Test
     public void testLessEqualsFilter()
     {
         parser.parse( "(cn<=test)" ); //$NON-NLS-1$
@@ -75,6 +82,7 @@
     /**
      * Tests an aprox filter
      */
+    @Test
     public void testAproxFilter()
     {
         parser.parse( "(cn~=test)" ); //$NON-NLS-1$
@@ -87,6 +95,7 @@
     /**
      * Tests an substring filter
      */
+    @Test
     public void testSubstringFilter()
     {
         parser.parse( "(cn=te*st)" ); //$NON-NLS-1$
@@ -99,6 +108,7 @@
     /**
      * Tests an present filter
      */
+    @Test
     public void testPresentFilter()
     {
         parser.parse( "(cn=*)" ); //$NON-NLS-1$
@@ -111,6 +121,7 @@
     /**
      * Tests an simple filter
      */
+    @Test
     public void testRFC4515_1()
     {
         parser.parse( "(cn=Babs Jensen)" ); //$NON-NLS-1$
@@ -123,6 +134,7 @@
     /**
      * Tests an not filter
      */
+    @Test
     public void testRFC4515_2()
     {
         parser.parse( "(!(cn=Tim Howes))" ); //$NON-NLS-1$
@@ -135,6 +147,7 @@
     /**
      * Tests an and/or filter
      */
+    @Test
     public void testRFC4515_3()
     {
         parser.parse( "(&(objectClass=Person)(|(sn=Jensen)(cn=Babs J*)))" ); //$NON-NLS-1$
@@ -147,6 +160,7 @@
     /**
      * Tests an substring filter
      */
+    @Test
     public void testRFC4515_4()
     {
         parser.parse( "(o=univ*of*mich*)" ); //$NON-NLS-1$
@@ -159,6 +173,7 @@
     /**
      * Tests an empty assertion value
      */
+    @Test
     public void testRFC4515_5()
     {
         parser.parse( "(seeAlso=)" ); //$NON-NLS-1$
@@ -175,6 +190,7 @@
      * The first example shows the use of the escaping mechanism to
      * represent parenthesis characters.  
      */
+    @Test
     public void testEscapeRFC4515_1()
     {
         parser.parse( "(o=Parens R Us \\28for all your parenthetical needs\\29)" ); //$NON-NLS-1$
@@ -193,6 +209,7 @@
      * a "*" in an assertion value, preventing it from being interpreted as
      * a substring indicator.
      */
+    @Test
     public void testEscapeRFC4515_2()
     {
         parser.parse( "(cn=*\\2A*)" ); //$NON-NLS-1$
@@ -208,6 +225,7 @@
      * From RFC4515:
      * The third illustrates the escaping of the backslash character.
      */
+    @Test
     public void testEscapeRFC4515_3()
     {
         parser.parse( "(filename=C:\\5cMyFile)" ); //$NON-NLS-1$
@@ -225,6 +243,7 @@
      * 00 00 00 04 (hex), illustrating the use of the escaping mechanism to
      * represent arbitrary data, including NUL characters.
      */
+    @Test
     public void testEscapeRFC4515_4()
     {
         parser.parse( "(bin=\\00\\00\\00\\04)" ); //$NON-NLS-1$
@@ -245,6 +264,7 @@
      * SMALL LETTER C WITH CARON (U+010D), LATIN SMALL LETTER I (U+0069),
      * and LATIN SMALL LETTER C WITH ACUTE (U+0107).
      */
+    @Test
     public void testEscapeRFC4515_5()
     {
         parser.parse( "(sn=Lu\\c4\\8di\\c4\\87)" ); //$NON-NLS-1$
@@ -261,6 +281,7 @@
      * The sixth and final example demonstrates assertion of a BER-encoded
      * value.
      */
+    @Test
     public void testEscapeRFC4515_6()
     {
         parser.parse( "(1.3.6.1.4.1.1466.0=\\04\\02\\48\\69)" ); //$NON-NLS-1$
@@ -276,6 +297,7 @@
      * From RFC4515:
      * The first example shows use of the matching rule "caseExactMatch."
      */
+    @Test
     public void testExtensibleFilterRFC4515_1()
     {
         parser.parse( "(cn:caseExactMatch:=Fred Flintstone)" ); //$NON-NLS-1$
@@ -292,6 +314,7 @@
      * The second example demonstrates use of a MatchingRuleAssertion form
      * without a matchingRule.
      */
+    @Test
     public void testExtensibleFilterRFC4515_2()
     {
         parser.parse( "(cn:=Betty Rubble)" ); //$NON-NLS-1$
@@ -311,6 +334,7 @@
      * entry's distinguished name should be considered part of the entry
      * when evaluating the match (indicated by the use of ":dn").
      */
+    @Test
     public void testExtensibleFilterRFC4515_3()
     {
         parser.parse( "(sn:dn:2.4.6.8.10:=Barney Rubble)" ); //$NON-NLS-1$
@@ -328,6 +352,7 @@
      * components should be considered part of the entry when doing the
      * match.
      */
+    @Test
     public void testExtensibleFilterRFC4515_4()
     {
         parser.parse( "(o:dn:=Ace Industry)" ); //$NON-NLS-1$
@@ -345,6 +370,7 @@
      * supporting the matching rule given (since the &lt;attr> has been
      * omitted).
      */
+    @Test
     public void testExtensibleFilterRFC4515_5()
     {
         parser.parse( "(:1.2.3:=Wilma Flintstone)" ); //$NON-NLS-1$
@@ -363,6 +389,7 @@
      * supporting the matching rule contained in the Dn should also be
      * considered.
      */
+    @Test
     public void testExtensibleFilterRFC4515_6()
     {
         parser.parse( "(:Dn:2.4.6.8.10:=Dino)" ); //$NON-NLS-1$
@@ -375,6 +402,7 @@
     /**
      * Test for DIRSTUIO-210.
      */
+    @Test
     public void testDIRSTUDIO210()
     {
         parser.parse( "(objectClass>=z*) " ); //$NON-NLS-1$
@@ -387,6 +415,7 @@
     /**
      * Test for DIRSTUIO-279.
      */
+    @Test
     public void testDIRSTUDIO279()
     {
         parser.parse( " (&\n    (objectClass=person)\n    (cn=a*)\n) " ); //$NON-NLS-1$
diff --git a/plugins/ldapbrowser.core/src/test/java/org/apache/directory/studio/ldapbrowser/core/model/PasswordTest.java b/plugins/ldapbrowser.core/src/test/java/org/apache/directory/studio/ldapbrowser/core/model/PasswordTest.java
index 13f94a1..2e6522f 100644
--- a/plugins/ldapbrowser.core/src/test/java/org/apache/directory/studio/ldapbrowser/core/model/PasswordTest.java
+++ b/plugins/ldapbrowser.core/src/test/java/org/apache/directory/studio/ldapbrowser/core/model/PasswordTest.java
@@ -21,7 +21,11 @@
 package org.apache.directory.studio.ldapbrowser.core.model;
 
 
-import junit.framework.TestCase;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import org.junit.jupiter.api.Test;
 
 
 /**
@@ -29,11 +33,12 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class PasswordTest extends TestCase
+public class PasswordTest
 {
     /**
      * Null Password should not be accepted
      */
+    @Test
     public void testNullPassword()
     {
         try
@@ -51,6 +56,7 @@
     /**
      * 
      */
+    @Test
     public void testPasswordSHAEncrypted()
     {
         Password password = new Password( "{SHA}5en6G6MezRroT3XKqkdPOmY/BfQ=" ); //$NON-NLS-1$
@@ -62,6 +68,7 @@
     /**
      * 
      */
+    @Test
     public void testPasswordSHAEncryptedLowercase()
     {
         Password password = new Password( "{sha}5en6G6MezRroT3XKqkdPOmY/BfQ=" ); //$NON-NLS-1$
@@ -73,6 +80,7 @@
     /**
      * 
      */
+    @Test
     public void testPasswordSSHAEncrypted()
     {
         Password password = new Password( "{SSHA}mjVVxasFkk59wMW4L1Ldt+YCblfhULHs03WW7g==" ); //$NON-NLS-1$
@@ -84,6 +92,7 @@
     /**
      * 
      */
+    @Test
     public void testPasswordSSHAEncryptedLowercase()
     {
         Password password = new Password( "{ssha}mjVVxasFkk59wMW4L1Ldt+YCblfhULHs03WW7g==" ); //$NON-NLS-1$
@@ -95,6 +104,7 @@
     /**
      * 
      */
+    @Test
     public void testPasswordMD5Encrypted()
     {
         Password password = new Password( "{MD5}Xr4ilOzQ4PCOq3aQ0qbuaQ==" ); //$NON-NLS-1$
@@ -106,6 +116,7 @@
     /**
      * 
      */
+    @Test
     public void testPasswordMD5EncryptedLowercase()
     {
         Password password = new Password( "{md5}Xr4ilOzQ4PCOq3aQ0qbuaQ==" ); //$NON-NLS-1$
@@ -117,6 +128,7 @@
     /**
      * 
      */
+    @Test
     public void testPasswordSMD5Encrypted()
     {
         Password password = new Password( "{SMD5}tQ9wo/VBuKsqBtylMMCcORbnYOJFMyDJ" ); //$NON-NLS-1$
@@ -128,6 +140,7 @@
     /**
      * 
      */
+    @Test
     public void testPasswordSMD5EncryptedLowercase()
     {
         Password password = new Password( "{smd5}tQ9wo/VBuKsqBtylMMCcORbnYOJFMyDJ" ); //$NON-NLS-1$
@@ -139,6 +152,7 @@
     /**
      * 
      */
+    @Test
     public void testPasswordCRYPTEncrypted()
     {
         Password password = new Password( "{CRYPT}qFkH8Z1woBlXw" ); //$NON-NLS-1$
@@ -150,6 +164,7 @@
     /**
      * 
      */
+    @Test
     public void testPasswordCRYPTEncryptedLowercase()
     {
         Password password = new Password( "{crypt}qFkH8Z1woBlXw" ); //$NON-NLS-1$
@@ -161,6 +176,7 @@
     /**
      * 
      */
+    @Test
     public void testPasswordBadAlgorithm()
     {
         Password password = new Password( "{CRYPTE}qFkH8Z1woBlXw" ); //$NON-NLS-1$
diff --git a/plugins/ldapbrowser.core/src/test/java/org/apache/directory/studio/ldapbrowser/core/model/schema/SchemaPT.java b/plugins/ldapbrowser.core/src/test/java/org/apache/directory/studio/ldapbrowser/core/model/schema/SchemaPT.java
deleted file mode 100644
index ad525da..0000000
--- a/plugins/ldapbrowser.core/src/test/java/org/apache/directory/studio/ldapbrowser/core/model/schema/SchemaPT.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *   Licensed to the Apache Software Foundation (ASF) under one
- *   or more contributor license agreements.  See the NOTICE file
- *   distributed with this work for additional information
- *   regarding copyright ownership.  The ASF licenses this file
- *   to you 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.apache.directory.studio.ldapbrowser.core.model.schema;
-
-
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-
-import org.junit.Test;
-
-
-/**
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
-public class SchemaPT
-{
-
-    @Test
-    public void testLoadSchemaFromLdifPerformance() throws Exception
-    {
-        Schema schema = null;
-        for ( int i = 0; i < 100; i++ )
-        {
-            InputStream stream = SchemaPT.class.getResourceAsStream( "/default_schema.ldif" );
-            Reader reader = new InputStreamReader( stream );
-            schema = new Schema();
-            schema.loadFromLdif( reader );
-        }
-        System.out.println( schema.getDn() );
-    }
-
-}
diff --git a/plugins/ldapbrowser.core/src/test/java/org/apache/directory/studio/ldapbrowser/core/utils/AttributeComparatorTest.java b/plugins/ldapbrowser.core/src/test/java/org/apache/directory/studio/ldapbrowser/core/utils/AttributeComparatorTest.java
index aab0ece..26d17f8 100644
--- a/plugins/ldapbrowser.core/src/test/java/org/apache/directory/studio/ldapbrowser/core/utils/AttributeComparatorTest.java
+++ b/plugins/ldapbrowser.core/src/test/java/org/apache/directory/studio/ldapbrowser/core/utils/AttributeComparatorTest.java
@@ -20,8 +20,8 @@
 package org.apache.directory.studio.ldapbrowser.core.utils;
 
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.util.List;
 
@@ -38,8 +38,8 @@
 import org.apache.directory.studio.ldifparser.model.container.LdifContentRecord;
 import org.apache.directory.studio.ldifparser.model.lines.LdifAttrValLine;
 import org.apache.directory.studio.ldifparser.model.lines.LdifDnLine;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 
 public class AttributeComparatorTest
@@ -63,8 +63,7 @@
 
     private AttributeComparator comparator;
 
-
-    @Before
+    @BeforeEach
     public void setup() throws Exception
     {
         ConnectionEventRegistry.suspendEventFiringInCurrentThread();
@@ -139,10 +138,10 @@
         assertEquals( 0, less + greater );
     }
 
-
     // TODO: objectclass, may, operational
     // TODO: objectclass < must < may < operational
 
+
     @Test
     public void testValuesDiffer()
     {
diff --git a/plugins/ldapbrowser.ui/about.ini b/plugins/ldapbrowser.ui/about.ini
index ca59c89..796f9c0 100644
--- a/plugins/ldapbrowser.ui/about.ini
+++ b/plugins/ldapbrowser.ui/about.ini
@@ -1,2 +1,2 @@
 featureImage=studio.png
-aboutText=Apache Directory Studio LDAP Browser - Tools for browsing and editing LDAP servers.\n\nVersion: ${unqualifiedVersion}.${buildQualifier}\n\nCopyright \u00A9 2006-2020 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.\nVisit http://directory.apache.org/studio
+aboutText=Apache Directory Studio LDAP Browser - Tools for browsing and editing LDAP servers.\n\nVersion: ${unqualifiedVersion}.${buildQualifier}\n\nCopyright \u00A9 2006-2021 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.\nVisit http://directory.apache.org/studio
\ No newline at end of file
diff --git a/plugins/ldapbrowser.ui/plugin_fr.properties b/plugins/ldapbrowser.ui/plugin_fr.properties
index 4441394..758ecaa 100644
--- a/plugins/ldapbrowser.ui/plugin_fr.properties
+++ b/plugins/ldapbrowser.ui/plugin_fr.properties
@@ -18,17 +18,17 @@
 ActionSet_LdapMenuActionSet_label=Menu LDAP
 
 Editor_SingleTabEntryEditor_shortname=Editeur d'entr\u00E9e tabulaire
-Editor_SingleTabEntryEditor_fullname=Editeur d'entr\u00E9e tabulaire (à onglet unique)
-Editor_SingleTabEntryEditor_description=Chaque entr\u00E9e est ouverte dans le m\u00EAme \u00E9diteur à onglet unique.
+Editor_SingleTabEntryEditor_fullname=Editeur d'entr\u00E9e tabulaire (\u00E0 onglet unique)
+Editor_SingleTabEntryEditor_description=Chaque entr\u00E9e est ouverte dans le m\u00EAme \u00E9diteur \u00E0 onglet unique.
 Editor_MultiTabEntryEditor_shortname=Editeur d'entr\u00E9e tabulaire
-Editor_MultiTabEntryEditor_fullname=Editeur d'entr\u00E9e tabulaire (à onglets multiples)
-Editor_MultiTabEntryEditor_description=Chaque entr\u00E9e est ouverte dans un \u00E9diteur à onglet s\u00E9par\u00E9.
+Editor_MultiTabEntryEditor_fullname=Editeur d'entr\u00E9e tabulaire (\u00E0 onglets multiples)
+Editor_MultiTabEntryEditor_description=Chaque entr\u00E9e est ouverte dans un \u00E9diteur \u00E0 onglet s\u00E9par\u00E9.
 Editor_SingleTabLdifEntryEditor_shortname=Editeur d'entr\u00E9e LDIF
-Editor_SingleTabLdifEntryEditor_fullname=Editeur d'entr\u00E9e LDIF (à onglet unique)
-Editor_SingleTabLdifEntryEditor_description=Chaque entr\u00E9e est ouverte dans le m\u00EAme \u00E9diteur à onglet unique.
+Editor_SingleTabLdifEntryEditor_fullname=Editeur d'entr\u00E9e LDIF (\u00E0 onglet unique)
+Editor_SingleTabLdifEntryEditor_description=Chaque entr\u00E9e est ouverte dans le m\u00EAme \u00E9diteur \u00E0 onglet unique.
 Editor_MultiTabLdifEntryEditor_shortname=Editeur d'entr\u00E9e LDIF
-Editor_MultiTabLdifEntryEditor_fullname=Editeur d'entr\u00E9e LDIF (à onglets multiples)
-Editor_MultiTabLdifEntryEditor_description=Chaque entr\u00E9e est ouverte dans un \u00E9diteur à onglet s\u00E9par\u00E9.
+Editor_MultiTabLdifEntryEditor_fullname=Editeur d'entr\u00E9e LDIF (\u00E0 onglets multiples)
+Editor_MultiTabLdifEntryEditor_description=Chaque entr\u00E9e est ouverte dans un \u00E9diteur \u00E0 onglet s\u00E9par\u00E9.
 
 Editor_SearchResultEditor_name=Editeur de recherche
 Editor_SchemaBrowser_name=Explorateur de sch\u00E9ma
diff --git a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/actions/PasswordModifyExtendedOperationAction.java b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/actions/PasswordModifyExtendedOperationAction.java
index 4a9bc0b..216ecab 100644
--- a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/actions/PasswordModifyExtendedOperationAction.java
+++ b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/actions/PasswordModifyExtendedOperationAction.java
@@ -123,6 +123,8 @@
     public boolean isEnabled()
     {
         return getConnectionAndEntry() != null
+            && getConnectionAndEntry().connection != null
+            && getConnectionAndEntry().connection.getRootDSE() != null
             && getConnectionAndEntry().connection.getRootDSE()
                 .isExtensionSupported( PasswordModifyRequest.EXTENSION_OID );
     }
diff --git a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/dialogs/preferences/ModificationLogsPreferencePage.java b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/dialogs/preferences/ModificationLogsPreferencePage.java
index 3765c26..3694014 100644
--- a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/dialogs/preferences/ModificationLogsPreferencePage.java
+++ b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/dialogs/preferences/ModificationLogsPreferencePage.java
@@ -25,9 +25,8 @@
 import org.apache.directory.studio.connection.core.ConnectionCoreConstants;
 import org.apache.directory.studio.connection.core.ConnectionCorePlugin;
 import org.apache.directory.studio.ldapbrowser.ui.BrowserUIPlugin;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
 import org.eclipse.jface.preference.PreferencePage;
-import org.eclipse.swt.events.VerifyEvent;
-import org.eclipse.swt.events.VerifyListener;
 import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
@@ -51,7 +50,6 @@
     private Text logFileSizeText;
     private Text maskedAttributesText;
 
-
     /**
      * Creates a new instance of ModificationLogsPreferencePage.
      */
@@ -82,8 +80,6 @@
         BaseWidgetUtils.createSpacer( composite, 1 );
         enableModificationLogging = BaseWidgetUtils.createCheckbox( composite, Messages
             .getString( "ModificationLogsPreferencePage.EnableModificationLogs" ), 1 ); //$NON-NLS-1$
-        enableModificationLogging.setSelection( ConnectionCorePlugin.getDefault().getPluginPreferences().getBoolean(
-            ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_ENABLE ) );
 
         BaseWidgetUtils.createSpacer( composite, 1 );
         BaseWidgetUtils.createSpacer( composite, 1 );
@@ -92,8 +88,6 @@
             1 ), Messages.getString( "ModificationLogsPreferencePage.MaskedAttributes" ), 1 ); //$NON-NLS-1$
         Composite maskedAttributesComposite = BaseWidgetUtils.createColumnContainer( maskedAttributesGroup, 1, 1 );
         maskedAttributesText = BaseWidgetUtils.createText( maskedAttributesComposite, "", 1 ); //$NON-NLS-1$
-        maskedAttributesText.setText( ConnectionCorePlugin.getDefault().getPluginPreferences().getString(
-            ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_MASKED_ATTRIBUTES ) );
         String maskedAttributesHelp = Messages.getString( "ModificationLogsPreferencePage.CommaSeparatedList" ); //$NON-NLS-1$
         BaseWidgetUtils.createWrappedLabel( maskedAttributesComposite, maskedAttributesHelp, 1 );
 
@@ -105,61 +99,70 @@
         Composite rotateComposite = BaseWidgetUtils.createColumnContainer( rotateGroup, 5, 1 );
         BaseWidgetUtils.createLabel( rotateComposite, Messages.getString( "ModificationLogsPreferencePage.Use" ), 1 ); //$NON-NLS-1$
         logFileCountText = BaseWidgetUtils.createText( rotateComposite, "", 3, 1 ); //$NON-NLS-1$
-        logFileCountText.setText( ConnectionCorePlugin.getDefault().getPluginPreferences().getString(
-            ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_COUNT ) );
-        logFileCountText.addVerifyListener( new VerifyListener()
-        {
-            public void verifyText( VerifyEvent e )
+        logFileCountText.addVerifyListener( e -> {
+            if ( !e.text.matches( "[0-9]*" ) ) //$NON-NLS-1$
             {
-                if ( !e.text.matches( "[0-9]*" ) ) //$NON-NLS-1$
-                {
-                    e.doit = false;
-                }
-                if ( "".equals( logFileCountText.getText() ) && e.text.matches( "[0]" ) ) //$NON-NLS-1$ //$NON-NLS-2$
-                {
-                    e.doit = false;
-                }
+                e.doit = false;
+            }
+            if ( "".equals( logFileCountText.getText() ) && e.text.matches( "[0]" ) ) //$NON-NLS-1$ //$NON-NLS-2$
+            {
+                e.doit = false;
             }
         } );
+        logFileCountText.addModifyListener( e -> validate() );
         BaseWidgetUtils.createLabel( rotateComposite, Messages
             .getString( "ModificationLogsPreferencePage.LogFilesEach" ), 1 ); //$NON-NLS-1$
         logFileSizeText = BaseWidgetUtils.createText( rotateComposite, "", 5, 1 ); //$NON-NLS-1$
-        logFileSizeText.setText( ConnectionCorePlugin.getDefault().getPluginPreferences().getString(
-            ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_SIZE ) );
-        logFileSizeText.addVerifyListener( new VerifyListener()
-        {
-            public void verifyText( VerifyEvent e )
+        logFileSizeText.addVerifyListener( e -> {
+            if ( !e.text.matches( "[0-9]*" ) ) //$NON-NLS-1$
             {
-                if ( !e.text.matches( "[0-9]*" ) ) //$NON-NLS-1$
-                {
-                    e.doit = false;
-                }
-                if ( "".equals( logFileSizeText.getText() ) && e.text.matches( "[0]" ) ) //$NON-NLS-1$ //$NON-NLS-2$
-                {
-                    e.doit = false;
-                }
+                e.doit = false;
+            }
+            if ( "".equals( logFileSizeText.getText() ) && e.text.matches( "[0]" ) ) //$NON-NLS-1$ //$NON-NLS-2$
+            {
+                e.doit = false;
             }
         } );
+        logFileSizeText.addModifyListener( e -> validate() );
         BaseWidgetUtils.createLabel( rotateComposite, Messages.getString( "ModificationLogsPreferencePage.KB" ), 1 ); //$NON-NLS-1$
 
+        setValues();
+
         applyDialogFont( composite );
         return composite;
     }
 
 
+    private void setValues()
+    {
+        enableModificationLogging.setSelection( ConnectionCorePlugin.getDefault().isModificationLogsEnabled() );
+        maskedAttributesText.setText( ConnectionCorePlugin.getDefault().getMModificationLogsMaskedAttributes() );
+        logFileCountText.setText( "" + ConnectionCorePlugin.getDefault().getModificationLogsFileCount() );
+        logFileSizeText.setText( "" + ConnectionCorePlugin.getDefault().getModificationLogsFileSize() );
+    }
+
+
+    public void validate()
+    {
+        setValid( logFileCountText.getText().matches( "[0-9]+" ) && logFileSizeText.getText().matches( "[0-9]+" ) );
+    }
+
+
     /**
      * {@inheritDoc}
      */
     public boolean performOk()
     {
-        ConnectionCorePlugin.getDefault().getPluginPreferences().setValue(
-            ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_ENABLE, enableModificationLogging.getSelection() );
-        ConnectionCorePlugin.getDefault().getPluginPreferences().setValue(
-            ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_COUNT, logFileCountText.getText() );
-        ConnectionCorePlugin.getDefault().getPluginPreferences().setValue(
-            ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_SIZE, logFileSizeText.getText() );
-        ConnectionCorePlugin.getDefault().getPluginPreferences().setValue(
-            ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_MASKED_ATTRIBUTES, maskedAttributesText.getText() );
+        IEclipsePreferences instancePreferences = ConnectionCorePlugin.getDefault().getInstanceScopePreferences();
+        instancePreferences.putBoolean( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_ENABLE,
+            enableModificationLogging.getSelection() );
+        instancePreferences.put( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_MASKED_ATTRIBUTES,
+            maskedAttributesText.getText() );
+        instancePreferences.putInt( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_COUNT,
+            Integer.parseInt( logFileCountText.getText() ) );
+        instancePreferences.putInt( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_SIZE,
+            Integer.parseInt( logFileSizeText.getText() ) );
+        ConnectionCorePlugin.getDefault().flushInstanceScopePreferences();
         return true;
     }
 
@@ -169,14 +172,13 @@
      */
     protected void performDefaults()
     {
-        enableModificationLogging.setSelection( ConnectionCorePlugin.getDefault().getPluginPreferences()
-            .getDefaultBoolean( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_ENABLE ) );
-        logFileCountText.setText( ConnectionCorePlugin.getDefault().getPluginPreferences().getDefaultString(
-            ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_COUNT ) );
-        logFileSizeText.setText( ConnectionCorePlugin.getDefault().getPluginPreferences().getDefaultString(
-            ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_SIZE ) );
-        maskedAttributesText.setText( ConnectionCorePlugin.getDefault().getPluginPreferences().getDefaultString(
-            ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_MASKED_ATTRIBUTES ) );
+        IEclipsePreferences instancePreferences = ConnectionCorePlugin.getDefault().getInstanceScopePreferences();
+        instancePreferences.remove( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_ENABLE );
+        instancePreferences.remove( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_MASKED_ATTRIBUTES );
+        instancePreferences.remove( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_COUNT );
+        instancePreferences.remove( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_SIZE );
+        ConnectionCorePlugin.getDefault().flushInstanceScopePreferences();
+        setValues();
         super.performDefaults();
     }
 
diff --git a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/dialogs/preferences/SearchLogsPreferencePage.java b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/dialogs/preferences/SearchLogsPreferencePage.java
index 9cfe234..1697782 100644
--- a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/dialogs/preferences/SearchLogsPreferencePage.java
+++ b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/dialogs/preferences/SearchLogsPreferencePage.java
@@ -25,9 +25,8 @@
 import org.apache.directory.studio.connection.core.ConnectionCoreConstants;
 import org.apache.directory.studio.connection.core.ConnectionCorePlugin;
 import org.apache.directory.studio.ldapbrowser.ui.BrowserUIPlugin;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
 import org.eclipse.jface.preference.PreferencePage;
-import org.eclipse.swt.events.VerifyEvent;
-import org.eclipse.swt.events.VerifyListener;
 import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
@@ -51,7 +50,6 @@
     private Text logFileCountText;
     private Text logFileSizeText;
 
-
     /**
      * Creates a new instance of SearchResultEditorPreferencePage.
      */
@@ -82,73 +80,79 @@
         BaseWidgetUtils.createSpacer( composite, 1 );
         enableSearchRequestLogging = BaseWidgetUtils.createCheckbox( composite, Messages
             .getString( "SearchLogsPreferencePage.EnableRequestLogs" ), 1 ); //$NON-NLS-1$
-        enableSearchRequestLogging.setSelection( ConnectionCorePlugin.getDefault().getPluginPreferences().getBoolean(
-            ConnectionCoreConstants.PREFERENCE_SEARCHREQUESTLOGS_ENABLE ) );
         enableSearchResultEntryLogging = BaseWidgetUtils.createCheckbox( composite, Messages
             .getString( "SearchLogsPreferencePage.EnableResultLogs" ), 1 ); //$NON-NLS-1$
-        enableSearchResultEntryLogging.setSelection( ConnectionCorePlugin.getDefault().getPluginPreferences()
-            .getBoolean( ConnectionCoreConstants.PREFERENCE_SEARCHRESULTENTRYLOGS_ENABLE ) );
 
         Group rotateGroup = BaseWidgetUtils.createGroup( BaseWidgetUtils.createColumnContainer( composite, 1, 1 ),
             Messages.getString( "SearchLogsPreferencePage.LogFileRotation" ), 1 ); //$NON-NLS-1$
         Composite rotateComposite = BaseWidgetUtils.createColumnContainer( rotateGroup, 5, 1 );
         BaseWidgetUtils.createLabel( rotateComposite, Messages.getString( "SearchLogsPreferencePage.Use" ), 1 ); //$NON-NLS-1$
         logFileCountText = BaseWidgetUtils.createText( rotateComposite, "", 3, 1 ); //$NON-NLS-1$
-        logFileCountText.setText( ConnectionCorePlugin.getDefault().getPluginPreferences().getString(
-            ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_COUNT ) );
-        logFileCountText.addVerifyListener( new VerifyListener()
-        {
-            public void verifyText( VerifyEvent e )
+        logFileCountText.addVerifyListener( e -> {
+            if ( !e.text.matches( "[0-9]*" ) ) //$NON-NLS-1$
             {
-                if ( !e.text.matches( "[0-9]*" ) ) //$NON-NLS-1$
-                {
-                    e.doit = false;
-                }
-                if ( "".equals( logFileCountText.getText() ) && e.text.matches( "[0]" ) ) //$NON-NLS-1$ //$NON-NLS-2$
-                {
-                    e.doit = false;
-                }
+                e.doit = false;
+            }
+            if ( "".equals( logFileCountText.getText() ) && e.text.matches( "[0]" ) ) //$NON-NLS-1$ //$NON-NLS-2$
+            {
+                e.doit = false;
             }
         } );
-        BaseWidgetUtils.createLabel( rotateComposite, Messages.getString( "SearchLogsPreferencePage.LogFilesEach" ), 1 ); //$NON-NLS-1$
+        logFileCountText.addModifyListener( e -> validate() );
+        BaseWidgetUtils.createLabel( rotateComposite, Messages.getString( "SearchLogsPreferencePage.LogFilesEach" ), //$NON-NLS-1$
+            1 );
         logFileSizeText = BaseWidgetUtils.createText( rotateComposite, "", 5, 1 ); //$NON-NLS-1$
-        logFileSizeText.setText( ConnectionCorePlugin.getDefault().getPluginPreferences().getString(
-            ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_SIZE ) );
-        logFileSizeText.addVerifyListener( new VerifyListener()
-        {
-            public void verifyText( VerifyEvent e )
+        logFileSizeText.addVerifyListener( e -> {
+            if ( !e.text.matches( "[0-9]*" ) ) //$NON-NLS-1$
             {
-                if ( !e.text.matches( "[0-9]*" ) ) //$NON-NLS-1$
-                {
-                    e.doit = false;
-                }
-                if ( "".equals( logFileSizeText.getText() ) && e.text.matches( "[0]" ) ) //$NON-NLS-1$ //$NON-NLS-2$
-                {
-                    e.doit = false;
-                }
+                e.doit = false;
+            }
+            if ( "".equals( logFileSizeText.getText() ) && e.text.matches( "[0]" ) ) //$NON-NLS-1$ //$NON-NLS-2$
+            {
+                e.doit = false;
             }
         } );
+        logFileSizeText.addModifyListener( e -> validate() );
         BaseWidgetUtils.createLabel( rotateComposite, Messages.getString( "SearchLogsPreferencePage.KB" ), 1 ); //$NON-NLS-1$
 
+        setValues();
+
         applyDialogFont( composite );
         return composite;
     }
 
 
+    private void setValues()
+    {
+        enableSearchRequestLogging.setSelection( ConnectionCorePlugin.getDefault().isSearchRequestLogsEnabled() );
+        enableSearchResultEntryLogging
+            .setSelection( ConnectionCorePlugin.getDefault().isSearchResultEntryLogsEnabled() );
+        logFileCountText.setText( "" + ConnectionCorePlugin.getDefault().getSearchLogsFileCount() );
+        logFileSizeText.setText( "" + ConnectionCorePlugin.getDefault().getSearchLogsFileSize() );
+    }
+
+
+    public void validate()
+    {
+        setValid( logFileCountText.getText().matches( "[0-9]+" ) && logFileSizeText.getText().matches( "[0-9]+" ) );
+    }
+
+
     /**
      * {@inheritDoc}
      */
     public boolean performOk()
     {
-        ConnectionCorePlugin.getDefault().getPluginPreferences().setValue(
-            ConnectionCoreConstants.PREFERENCE_SEARCHREQUESTLOGS_ENABLE, enableSearchRequestLogging.getSelection() );
-        ConnectionCorePlugin.getDefault().getPluginPreferences().setValue(
-            ConnectionCoreConstants.PREFERENCE_SEARCHRESULTENTRYLOGS_ENABLE,
+        IEclipsePreferences instancePreferences = ConnectionCorePlugin.getDefault().getInstanceScopePreferences();
+        instancePreferences.putBoolean( ConnectionCoreConstants.PREFERENCE_SEARCHREQUESTLOGS_ENABLE,
+            enableSearchRequestLogging.getSelection() );
+        instancePreferences.putBoolean( ConnectionCoreConstants.PREFERENCE_SEARCHRESULTENTRYLOGS_ENABLE,
             enableSearchResultEntryLogging.getSelection() );
-        ConnectionCorePlugin.getDefault().getPluginPreferences().setValue(
-            ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_COUNT, logFileCountText.getText() );
-        ConnectionCorePlugin.getDefault().getPluginPreferences().setValue(
-            ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_SIZE, logFileSizeText.getText() );
+        instancePreferences.putInt( ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_COUNT,
+            Integer.parseInt( logFileCountText.getText() ) );
+        instancePreferences.putInt( ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_SIZE,
+            Integer.parseInt( logFileSizeText.getText() ) );
+        ConnectionCorePlugin.getDefault().flushInstanceScopePreferences();
         return true;
     }
 
@@ -158,14 +162,13 @@
      */
     protected void performDefaults()
     {
-        enableSearchRequestLogging.setSelection( ConnectionCorePlugin.getDefault().getPluginPreferences()
-            .getDefaultBoolean( ConnectionCoreConstants.PREFERENCE_SEARCHREQUESTLOGS_ENABLE ) );
-        enableSearchResultEntryLogging.setSelection( ConnectionCorePlugin.getDefault().getPluginPreferences()
-            .getDefaultBoolean( ConnectionCoreConstants.PREFERENCE_SEARCHRESULTENTRYLOGS_ENABLE ) );
-        logFileCountText.setText( ConnectionCorePlugin.getDefault().getPluginPreferences().getDefaultString(
-            ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_COUNT ) );
-        logFileSizeText.setText( ConnectionCorePlugin.getDefault().getPluginPreferences().getDefaultString(
-            ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_SIZE ) );
+        IEclipsePreferences instancePreferences = ConnectionCorePlugin.getDefault().getInstanceScopePreferences();
+        instancePreferences.remove( ConnectionCoreConstants.PREFERENCE_SEARCHREQUESTLOGS_ENABLE );
+        instancePreferences.remove( ConnectionCoreConstants.PREFERENCE_SEARCHRESULTENTRYLOGS_ENABLE );
+        instancePreferences.remove( ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_COUNT );
+        instancePreferences.remove( ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_SIZE );
+        ConnectionCorePlugin.getDefault().flushInstanceScopePreferences();
+        setValues();
         super.performDefaults();
     }
 
diff --git a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/editors/schemabrowser/AttributeTypeDescriptionDetailsPage.java b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/editors/schemabrowser/AttributeTypeDescriptionDetailsPage.java
index 75bb51f..fdc90a7 100644
--- a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/editors/schemabrowser/AttributeTypeDescriptionDetailsPage.java
+++ b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/editors/schemabrowser/AttributeTypeDescriptionDetailsPage.java
@@ -29,9 +29,11 @@
 import org.apache.directory.api.ldap.model.schema.ObjectClass;
 import org.apache.directory.api.ldap.model.schema.UsageEnum;
 import org.apache.directory.studio.common.ui.CommonUIConstants;
+import org.apache.directory.studio.common.ui.CommonUIPlugin;
 import org.apache.directory.studio.ldapbrowser.core.model.schema.SchemaUtils;
 import org.eclipse.osgi.util.NLS;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Composite;
@@ -353,38 +355,38 @@
         // set flags
         if ( ( atd != null ) && ( atd.isSingleValued() ) )
         {
-            singleValuedLabel.setForeground( CommonUIConstants.BLACK_COLOR );
+            singleValuedLabel.setForeground( getColor( CommonUIConstants.DEFAULT_COLOR ) );
         }
         else
         {
-            singleValuedLabel.setForeground( CommonUIConstants.ML_GREY_COLOR );
+            singleValuedLabel.setForeground( getColor( CommonUIConstants.DISABLED_COLOR ) );
         }
 
         if ( atd != null && atd.isObsolete() )
         {
-            isObsoleteLabel.setForeground( CommonUIConstants.BLACK_COLOR );
+            isObsoleteLabel.setForeground( getColor( CommonUIConstants.DEFAULT_COLOR ) );
         }
         else
         {
-            isObsoleteLabel.setForeground( CommonUIConstants.ML_GREY_COLOR );
+            isObsoleteLabel.setForeground( getColor( CommonUIConstants.DISABLED_COLOR ) );
         }
 
         if ( atd != null && atd.isCollective() )
         {
-            collectiveLabel.setForeground( CommonUIConstants.BLACK_COLOR );
+            collectiveLabel.setForeground( getColor( CommonUIConstants.DEFAULT_COLOR ) );
         }
         else
         {
-            collectiveLabel.setForeground( CommonUIConstants.ML_GREY_COLOR );
+            collectiveLabel.setForeground( getColor( CommonUIConstants.DISABLED_COLOR ) );
         }
 
         if ( atd != null && !atd.isUserModifiable() )
         {
-            noUserModificationLabel.setForeground( CommonUIConstants.BLACK_COLOR );
+            noUserModificationLabel.setForeground( getColor( CommonUIConstants.DEFAULT_COLOR ) );
         }
         else
         {
-            noUserModificationLabel.setForeground( CommonUIConstants.ML_GREY_COLOR );
+            noUserModificationLabel.setForeground( getColor( CommonUIConstants.DISABLED_COLOR ) );
         }
 
         flagSection.layout();
@@ -482,6 +484,12 @@
     }
 
 
+    private Color getColor( String color )
+    {
+        return CommonUIPlugin.getDefault().getColor( color );
+    }
+
+
     /**
      * Creates the content of the main section. It is newly created
      * on every input change to ensure a proper layout of 
diff --git a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/editors/schemabrowser/BrowserConnectionWidgetContributionItem.java b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/editors/schemabrowser/BrowserConnectionWidgetContributionItem.java
index 8f4febf..d286270 100644
--- a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/editors/schemabrowser/BrowserConnectionWidgetContributionItem.java
+++ b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/editors/schemabrowser/BrowserConnectionWidgetContributionItem.java
@@ -31,7 +31,6 @@
 import org.apache.directory.studio.ldapbrowser.common.widgets.search.BrowserConnectionWidget;
 import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection;
 import org.eclipse.jface.action.ContributionItem;
-import org.eclipse.jface.util.Assert;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
@@ -141,7 +140,7 @@
      */
     public final void fill( Menu parent, int index )
     {
-        Assert.isTrue( false, Messages.getString( "BrowserConnectionWidgetContributionItem.CantAddControl" ) );//$NON-NLS-1$
+        throw new UnsupportedOperationException( Messages.getString( "BrowserConnectionWidgetContributionItem.CantAddControl" ) ); //$NON-NLS-1$
     }
 
 
diff --git a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/browser/BrowserViewUniversalListener.java b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/browser/BrowserViewUniversalListener.java
index 8c5159f..f00e941 100644
--- a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/browser/BrowserViewUniversalListener.java
+++ b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/browser/BrowserViewUniversalListener.java
@@ -550,9 +550,9 @@
 
         if ( ( search instanceof IQuickSearch ) && ( searchUpdateEvent.getDetail() == EventDetail.SEARCH_REMOVED ) )
         {
-            if ( widget.getQuickSearch() == search )
+            if ( search.getBrowserConnection().getQuickSearch() == search )
             {
-                widget.setQuickSearch( null );
+                search.getBrowserConnection().setQuickSearch( null );
             }
         }
 
@@ -568,7 +568,7 @@
         }
         else if ( ( search instanceof IQuickSearch ) && ( searchUpdateEvent.getDetail() != EventDetail.SEARCH_REMOVED ) )
         {
-            if ( widget.getQuickSearch() == search )
+            if ( search.getBrowserConnection().getQuickSearch() == search )
             {
                 viewer.setSelection( new StructuredSelection( search ), true );
             }
diff --git a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/modificationlogs/ClearAction.java b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/modificationlogs/ClearAction.java
index ba18ada..f6086c5 100644
--- a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/modificationlogs/ClearAction.java
+++ b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/modificationlogs/ClearAction.java
@@ -96,8 +96,8 @@
             Messages.getString( "ClearAction.Delete" ), Messages.getString( "ClearAction.DeleteAllLogFiles" ) ) ) //$NON-NLS-1$ //$NON-NLS-2$

         {

             view.getUniversalListener().clearInput();

+            new RefreshAction( view ).run();

         }

-

     }

 

 

diff --git a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/modificationlogs/EnableModificationLogsAction.java b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/modificationlogs/EnableModificationLogsAction.java
index 3d53069..b36dfb0 100644
--- a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/modificationlogs/EnableModificationLogsAction.java
+++ b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/modificationlogs/EnableModificationLogsAction.java
@@ -23,6 +23,7 @@
 
 import org.apache.directory.studio.connection.core.ConnectionCoreConstants;
 import org.apache.directory.studio.connection.core.ConnectionCorePlugin;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
 import org.eclipse.jface.action.Action;
 
 
@@ -42,8 +43,7 @@
         super( Messages.getString( "EnableModificationLogsAction.EnableModificationLogs" ), AS_CHECK_BOX ); //$NON-NLS-1$
         setToolTipText( getText() );
         setEnabled( true );
-        setChecked( ConnectionCorePlugin.getDefault().getPluginPreferences().getBoolean(
-            ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_ENABLE ) );
+        setChecked( ConnectionCorePlugin.getDefault().isModificationLogsEnabled() );
     }
 
 
@@ -52,9 +52,10 @@
      */
     public void run()
     {
-        ConnectionCorePlugin.getDefault().getPluginPreferences().setValue(
-            ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_ENABLE, super.isChecked() );
-        ConnectionCorePlugin.getDefault().savePluginPreferences();
+        IEclipsePreferences instancePreferences = ConnectionCorePlugin.getDefault().getInstanceScopePreferences();
+        instancePreferences.putBoolean( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_ENABLE,
+            super.isChecked() );
+        ConnectionCorePlugin.getDefault().flushInstanceScopePreferences();
     }
 
 }
diff --git a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/modificationlogs/ModificationLogsViewActionGroup.java b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/modificationlogs/ModificationLogsViewActionGroup.java
index 35a1f95..1497a5d 100644
--- a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/modificationlogs/ModificationLogsViewActionGroup.java
+++ b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/modificationlogs/ModificationLogsViewActionGroup.java
@@ -24,7 +24,6 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.directory.studio.connection.core.ConnectionCoreConstants;
 import org.apache.directory.studio.connection.core.ConnectionCorePlugin;
 import org.apache.directory.studio.ldapbrowser.common.actions.proxy.ActionHandlerManager;
 import org.apache.directory.studio.ldapbrowser.ui.actions.proxy.ModificationLogsViewActionProxy;
@@ -144,8 +143,8 @@
         {
             public void menuAboutToShow( IMenuManager manager )
             {
-                enableModificationLogsAction.setChecked( ConnectionCorePlugin.getDefault().getPluginPreferences()
-                    .getBoolean( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_ENABLE ) );
+                enableModificationLogsAction
+                    .setChecked( ConnectionCorePlugin.getDefault().isModificationLogsEnabled() );
             }
         } );
     }
diff --git a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/modificationlogs/ModificationLogsViewUniversalListener.java b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/modificationlogs/ModificationLogsViewUniversalListener.java
index 3fb1341..4866157 100644
--- a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/modificationlogs/ModificationLogsViewUniversalListener.java
+++ b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/modificationlogs/ModificationLogsViewUniversalListener.java
@@ -23,7 +23,6 @@
 
 import java.io.File;
 import java.io.FileReader;
-import java.io.FileWriter;
 
 import org.apache.directory.studio.connection.core.Connection;
 import org.apache.directory.studio.connection.core.ConnectionCorePlugin;
@@ -153,9 +152,8 @@
                 int i = input.getIndex();
                 if ( 0 <= i && i < files.length && files[i] != null && files[i].exists() && files[i].canRead() )
                 {
-                    try
+                    try ( FileReader fr = new FileReader( files[i] ) )
                     {
-                        FileReader fr = new FileReader( files[i] );
                         char[] cbuf = new char[4096];
                         for ( int length = fr.read( cbuf ); length > 0; length = fr.read( cbuf ) )
                         {
@@ -227,29 +225,10 @@
     {
         if ( input.getBrowserConnection().getConnection() != null )
         {
-            StringBuffer sb = new StringBuffer( "" ); //$NON-NLS-1$
-            FileWriter fw = null;
             LdifModificationLogger modificationLogger = ConnectionCorePlugin.getDefault().getLdifModificationLogger();
-            File[] files = modificationLogger.getFiles( input.getBrowserConnection().getConnection() );
             modificationLogger.dispose( input.getBrowserConnection().getConnection() );
-            for ( int i = 0; i < files.length; i++ )
-            {
-                try
-                {
-                    if ( files[i] != null && files[i].exists() && !files[i].delete() )
-                    {
-                        fw = new FileWriter( files[i] );
-                        fw.write( "" ); //$NON-NLS-1$
-                    }
-
-                }
-                catch ( Exception e )
-                {
-                    sb.append( e.getMessage() );
-                }
-            }
             view.getMainWidget().getSourceViewer().setTopIndex( 0 );
-            view.getMainWidget().getSourceViewer().getDocument().set( sb.toString() );
+            view.getMainWidget().getSourceViewer().getDocument().set( "" );
         }
     }
 
diff --git a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/searchlogs/ClearAction.java b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/searchlogs/ClearAction.java
index bac29d7..296acb4 100644
--- a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/searchlogs/ClearAction.java
+++ b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/searchlogs/ClearAction.java
@@ -97,8 +97,8 @@
             Messages.getString( "ClearAction.Delete" ), Messages.getString( "ClearAction.DeleteAllLogFiles" ) ) ) //$NON-NLS-1$ //$NON-NLS-2$

         {

             view.getUniversalListener().clearInput();

+            new RefreshAction( view ).run();

         }

-

     }

 

 

diff --git a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/searchlogs/EnableSearchRequestLogsAction.java b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/searchlogs/EnableSearchRequestLogsAction.java
index 3a8b42e..5557b01 100644
--- a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/searchlogs/EnableSearchRequestLogsAction.java
+++ b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/searchlogs/EnableSearchRequestLogsAction.java
@@ -23,6 +23,7 @@
 
 import org.apache.directory.studio.connection.core.ConnectionCoreConstants;
 import org.apache.directory.studio.connection.core.ConnectionCorePlugin;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
 import org.eclipse.jface.action.Action;
 
 
@@ -42,8 +43,7 @@
         super( Messages.getString( "EnableSearchRequestLogsAction.EnableSearchRequestLogs" ), AS_CHECK_BOX ); //$NON-NLS-1$
         setToolTipText( getText() );
         setEnabled( true );
-        setChecked( ConnectionCorePlugin.getDefault().getPluginPreferences().getBoolean(
-            ConnectionCoreConstants.PREFERENCE_SEARCHREQUESTLOGS_ENABLE ) );
+        setChecked( ConnectionCorePlugin.getDefault().isSearchRequestLogsEnabled() );
     }
 
 
@@ -52,9 +52,10 @@
      */
     public void run()
     {
-        ConnectionCorePlugin.getDefault().getPluginPreferences().setValue(
-            ConnectionCoreConstants.PREFERENCE_SEARCHREQUESTLOGS_ENABLE, super.isChecked() );
-        ConnectionCorePlugin.getDefault().savePluginPreferences();
+        IEclipsePreferences instancePreferences = ConnectionCorePlugin.getDefault().getInstanceScopePreferences();
+        instancePreferences.putBoolean( ConnectionCoreConstants.PREFERENCE_SEARCHREQUESTLOGS_ENABLE,
+            super.isChecked() );
+        ConnectionCorePlugin.getDefault().flushInstanceScopePreferences();
     }
 
 }
diff --git a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/searchlogs/EnableSearchResultEntryLogsAction.java b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/searchlogs/EnableSearchResultEntryLogsAction.java
index 8cb55dd..74afd1c 100644
--- a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/searchlogs/EnableSearchResultEntryLogsAction.java
+++ b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/searchlogs/EnableSearchResultEntryLogsAction.java
@@ -23,6 +23,7 @@
 
 import org.apache.directory.studio.connection.core.ConnectionCoreConstants;
 import org.apache.directory.studio.connection.core.ConnectionCorePlugin;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
 import org.eclipse.jface.action.Action;
 
 
@@ -42,8 +43,7 @@
         super( Messages.getString( "EnableSearchResultEntryLogsAction.EnableSearchResultLogs" ), AS_CHECK_BOX ); //$NON-NLS-1$
         setToolTipText( getText() );
         setEnabled( true );
-        setChecked( ConnectionCorePlugin.getDefault().getPluginPreferences().getBoolean(
-            ConnectionCoreConstants.PREFERENCE_SEARCHRESULTENTRYLOGS_ENABLE ) );
+        setChecked( ConnectionCorePlugin.getDefault().isSearchResultEntryLogsEnabled() );
     }
 
 
@@ -52,9 +52,10 @@
      */
     public void run()
     {
-        ConnectionCorePlugin.getDefault().getPluginPreferences().setValue(
-            ConnectionCoreConstants.PREFERENCE_SEARCHRESULTENTRYLOGS_ENABLE, super.isChecked() );
-        ConnectionCorePlugin.getDefault().savePluginPreferences();
+        IEclipsePreferences instancePreferences = ConnectionCorePlugin.getDefault().getInstanceScopePreferences();
+        instancePreferences.putBoolean( ConnectionCoreConstants.PREFERENCE_SEARCHRESULTENTRYLOGS_ENABLE,
+            super.isChecked() );
+        ConnectionCorePlugin.getDefault().flushInstanceScopePreferences();
     }
 
 }
diff --git a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/searchlogs/SearchLogsViewActionGroup.java b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/searchlogs/SearchLogsViewActionGroup.java
index 2038596..49293fb 100644
--- a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/searchlogs/SearchLogsViewActionGroup.java
+++ b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/searchlogs/SearchLogsViewActionGroup.java
@@ -24,7 +24,6 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.directory.studio.connection.core.ConnectionCoreConstants;
 import org.apache.directory.studio.connection.core.ConnectionCorePlugin;
 import org.apache.directory.studio.ldapbrowser.common.actions.proxy.ActionHandlerManager;
 import org.apache.directory.studio.ldapbrowser.ui.actions.proxy.SearchLogsViewActionProxy;
@@ -145,10 +144,10 @@
         {
             public void menuAboutToShow( IMenuManager manager )
             {
-                enableSearchRequestLogsAction.setChecked( ConnectionCorePlugin.getDefault().getPluginPreferences()
-                    .getBoolean( ConnectionCoreConstants.PREFERENCE_SEARCHREQUESTLOGS_ENABLE ) );
-                enableSearchResultEntryLogsAction.setChecked( ConnectionCorePlugin.getDefault().getPluginPreferences()
-                    .getBoolean( ConnectionCoreConstants.PREFERENCE_SEARCHRESULTENTRYLOGS_ENABLE ) );
+                enableSearchRequestLogsAction
+                    .setChecked( ConnectionCorePlugin.getDefault().isSearchRequestLogsEnabled() );
+                enableSearchResultEntryLogsAction
+                    .setChecked( ConnectionCorePlugin.getDefault().isSearchResultEntryLogsEnabled() );
             }
         } );
     }
diff --git a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/searchlogs/SearchLogsViewUniversalListener.java b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/searchlogs/SearchLogsViewUniversalListener.java
index cd7c177..45e334a 100644
--- a/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/searchlogs/SearchLogsViewUniversalListener.java
+++ b/plugins/ldapbrowser.ui/src/main/java/org/apache/directory/studio/ldapbrowser/ui/views/searchlogs/SearchLogsViewUniversalListener.java
@@ -23,7 +23,6 @@
 
 import java.io.File;
 import java.io.FileReader;
-import java.io.FileWriter;
 
 import org.apache.directory.studio.connection.core.Connection;
 import org.apache.directory.studio.connection.core.ConnectionCorePlugin;
@@ -165,9 +164,8 @@
                 int i = input.getIndex();
                 if ( 0 <= i && i < files.length && files[i] != null && files[i].exists() && files[i].canRead() )
                 {
-                    try
+                    try ( FileReader fr = new FileReader( files[i] ) )
                     {
-                        FileReader fr = new FileReader( files[i] );
                         char[] cbuf = new char[4096];
                         for ( int length = fr.read( cbuf ); length > 0; length = fr.read( cbuf ) )
                         {
@@ -280,29 +278,10 @@
     {
         if ( input.getBrowserConnection().getConnection() != null )
         {
-            StringBuffer sb = new StringBuffer( "" ); //$NON-NLS-1$
-            FileWriter fw = null;
             LdifSearchLogger searchLogger = ConnectionCorePlugin.getDefault().getLdifSearchLogger();
-            File[] files = searchLogger.getFiles( input.getBrowserConnection().getConnection() );
             searchLogger.dispose( input.getBrowserConnection().getConnection() );
-            for ( int i = 0; i < files.length; i++ )
-            {
-                try
-                {
-                    if ( files[i] != null && files[i].exists() && !files[i].delete() )
-                    {
-                        fw = new FileWriter( files[i] );
-                        fw.write( "" ); //$NON-NLS-1$
-                    }
-
-                }
-                catch ( Exception e )
-                {
-                    sb.append( e.getMessage() );
-                }
-            }
             view.getMainWidget().getSourceViewer().setTopIndex( 0 );
-            view.getMainWidget().getSourceViewer().getDocument().set( sb.toString() );
+            view.getMainWidget().getSourceViewer().getDocument().set( "" );
         }
     }
 
diff --git a/plugins/ldapservers.apacheds/plugin_fr.properties b/plugins/ldapservers.apacheds/plugin_fr.properties
index 8e6d375..40724d1 100644
--- a/plugins/ldapservers.apacheds/plugin_fr.properties
+++ b/plugins/ldapservers.apacheds/plugin_fr.properties
@@ -15,4 +15,4 @@
 # specific language governing permissions and limitations
 # under the License.
 
-ActionCreateConnection_label=Créer une connexion
\ No newline at end of file
+ActionCreateConnection_label=Cr\u00E9er une connexion
\ No newline at end of file
diff --git a/plugins/ldifeditor/about.ini b/plugins/ldifeditor/about.ini
index 80df2c3..c7730e7 100644
--- a/plugins/ldifeditor/about.ini
+++ b/plugins/ldifeditor/about.ini
@@ -1,2 +1,2 @@
 featureImage=studio.png
-aboutText=Apache Directory Studio LDIF Editor - Editor for LDIF (LDAP Data Interchange Format) files.\n\nVersion: ${unqualifiedVersion}.${buildQualifier}\n\nCopyright \u00A9 2006-2020 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.\nVisit http://directory.apache.org/studio
+aboutText=Apache Directory Studio LDIF Editor - Editor for LDIF (LDAP Data Interchange Format) files.\n\nVersion: ${unqualifiedVersion}.${buildQualifier}\n\nCopyright \u00A9 2006-2021 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.\nVisit http://directory.apache.org/studio
diff --git a/plugins/ldifeditor/src/main/java/org/apache/directory/studio/ldifeditor/LdifEditorPreferencesInitializer.java b/plugins/ldifeditor/src/main/java/org/apache/directory/studio/ldifeditor/LdifEditorPreferencesInitializer.java
index 9d53c5c..fe75187 100644
--- a/plugins/ldifeditor/src/main/java/org/apache/directory/studio/ldifeditor/LdifEditorPreferencesInitializer.java
+++ b/plugins/ldifeditor/src/main/java/org/apache/directory/studio/ldifeditor/LdifEditorPreferencesInitializer.java
@@ -22,11 +22,12 @@
 
 
 import org.apache.directory.studio.common.ui.CommonUIConstants;
+import org.apache.directory.studio.common.ui.CommonUIPlugin;
 import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
 import org.eclipse.jface.preference.IPreferenceStore;
 import org.eclipse.jface.preference.PreferenceConverter;
 import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Color;
 
 
 /**
@@ -41,7 +42,6 @@
      */
     public void initializeDefaultPreferences()
     {
-
         IPreferenceStore store = LdifEditorActivator.getDefault().getPreferenceStore();
 
         // LDIF Editor
@@ -58,47 +58,70 @@
         store.setDefault( LdifEditorConstants.PREFERENCE_LDIFEDITOR_OPTIONS_UPDATEIFENTRYEXISTS, false );
         store.setDefault( LdifEditorConstants.PREFERENCE_LDIFEDITOR_OPTIONS_CONTINUEONERROR, true );
 
-        PreferenceConverter.setDefault( store, LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_COMMENT
-            + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX, new RGB( 63, 127, 95 ) );// green
+        setDefaultColor( store, LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_COMMENT
+            + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX,
+            CommonUIConstants.COMMENT_COLOR );
         store.setDefault( LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_COMMENT
             + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_STYLE_SUFFIX, SWT.NORMAL );
-        PreferenceConverter.setDefault( store, LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_KEYWORD
-            + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX, CommonUIConstants.M_GREY );
+        setDefaultColor( store, LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_KEYWORD
+            + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX,
+            CommonUIConstants.KEYWORD_1_COLOR );
         store.setDefault( LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_KEYWORD
             + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_STYLE_SUFFIX, SWT.BOLD );
-        PreferenceConverter.setDefault( store, LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_DN
-            + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX, CommonUIConstants.BLACK );
+        setDefaultColor( store, LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_DN
+            + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX,
+            CommonUIConstants.DEFAULT_COLOR );
         store.setDefault( LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_DN
             + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_STYLE_SUFFIX, SWT.BOLD );
-        PreferenceConverter.setDefault( store, LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_ATTRIBUTE
-            + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX, CommonUIConstants.M_PURPLE );// violet
+        setDefaultColor( store, LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_ATTRIBUTE
+            + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX,
+            CommonUIConstants.ATTRIBUTE_TYPE_COLOR );
         store.setDefault( LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_ATTRIBUTE
             + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_STYLE_SUFFIX, SWT.BOLD );
-        PreferenceConverter.setDefault( store, LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_VALUETYPE
-            + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX, CommonUIConstants.RED );
+        setDefaultColor( store, LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_VALUETYPE
+            + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX,
+            CommonUIConstants.SEPARATOR_COLOR );
         store.setDefault( LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_VALUETYPE
             + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_STYLE_SUFFIX, SWT.BOLD );
-        PreferenceConverter.setDefault( store, LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_VALUE
-            + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX, CommonUIConstants.L_BLUE );// blue
+        setDefaultColor( store, LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_VALUE
+            + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX,
+            CommonUIConstants.VALUE_COLOR );
         store.setDefault( LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_VALUE
             + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_STYLE_SUFFIX, SWT.NORMAL );
-        PreferenceConverter.setDefault( store, LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_CHANGETYPEADD
-            + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX, new RGB( 127, 159, 95 ) );// green
+        setDefaultColor( store, LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_CHANGETYPEADD
+            + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX,
+            CommonUIConstants.ADD_COLOR );
         store.setDefault( LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_CHANGETYPEADD
             + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_STYLE_SUFFIX, SWT.BOLD );
-        PreferenceConverter.setDefault( store, LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_CHANGETYPEMODIFY
-            + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX, new RGB( 223, 159, 95 ) );// yellow
+        setDefaultColor( store, LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_CHANGETYPEMODIFY
+            + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX,
+            CommonUIConstants.MODIFY_COLOR );
         store.setDefault( LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_CHANGETYPEMODIFY
             + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_STYLE_SUFFIX, SWT.BOLD );
-        PreferenceConverter.setDefault( store, LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_CHANGETYPEDELETE
-            + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX, new RGB( 255, 63, 95 ) );// red
+        setDefaultColor( store, LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_CHANGETYPEDELETE
+            + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX,
+            CommonUIConstants.DELETE_COLOR );
         store.setDefault( LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_CHANGETYPEDELETE
             + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_STYLE_SUFFIX, SWT.BOLD );
-        PreferenceConverter.setDefault( store, LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_CHANGETYPEMODDN
-            + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX, new RGB( 127, 159, 191 ) );// bright
-        // blue
+        setDefaultColor( store, LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_CHANGETYPEMODDN
+            + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX,
+            CommonUIConstants.RENAME_COLOR );
         store.setDefault( LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_CHANGETYPEMODDN
             + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_STYLE_SUFFIX, SWT.BOLD );
     }
 
+
+    private void setDefaultColor( IPreferenceStore store, String preferenceName, String colorName )
+    {
+        Color color = CommonUIPlugin.getDefault().getColor( colorName );
+        if ( color == null )
+        {
+            store.setDefault( preferenceName, IPreferenceStore.STRING_DEFAULT_DEFAULT );
+        }
+        else
+        {
+            PreferenceConverter.setDefault( store, preferenceName, color.getRGB() );
+        }
+    }
+
 }
diff --git a/plugins/ldifeditor/src/main/java/org/apache/directory/studio/ldifeditor/dialogs/preferences/LdifEditorSyntaxColoringPreferencePage.java b/plugins/ldifeditor/src/main/java/org/apache/directory/studio/ldifeditor/dialogs/preferences/LdifEditorSyntaxColoringPreferencePage.java
index 716a443..a816bf7 100644
--- a/plugins/ldifeditor/src/main/java/org/apache/directory/studio/ldifeditor/dialogs/preferences/LdifEditorSyntaxColoringPreferencePage.java
+++ b/plugins/ldifeditor/src/main/java/org/apache/directory/studio/ldifeditor/dialogs/preferences/LdifEditorSyntaxColoringPreferencePage.java
@@ -156,7 +156,7 @@
 
         void loadPreferences()
         {
-            IPreferenceStore store = LdifEditorActivator.getDefault().getPreferenceStore();
+            IPreferenceStore store = getPreferenceStore();
             this.rgb = PreferenceConverter.getColor( store, key
                 + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX );
             int style = store.getInt( key + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_STYLE_SUFFIX );
@@ -166,7 +166,7 @@
 
         void savePreferences()
         {
-            IPreferenceStore store = LdifEditorActivator.getDefault().getPreferenceStore();
+            IPreferenceStore store = getPreferenceStore();
             PreferenceConverter
                 .setValue( store, key + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX, rgb );
             store.setValue( key + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_STYLE_SUFFIX, getStyle() );
@@ -175,10 +175,13 @@
 
         void loadDefaultPreferences()
         {
-            IPreferenceStore store = LdifEditorActivator.getDefault().getPreferenceStore();
-            this.rgb = PreferenceConverter.getDefaultColor( store, key
-                + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX );
-            int style = store.getDefaultInt( key + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_STYLE_SUFFIX );
+            IPreferenceStore store = getPreferenceStore();
+            String colorKey = key + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX;
+            store.setToDefault( colorKey);
+            String styleKey = key + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_STYLE_SUFFIX;
+            store.setToDefault( styleKey);
+            this.rgb = PreferenceConverter.getDefaultColor( store, colorKey );
+            int style = store.getDefaultInt( styleKey );
             setStyle( style );
         }
 
diff --git a/plugins/ldifeditor/src/main/java/org/apache/directory/studio/ldifeditor/editor/text/LdifDamagerRepairer.java b/plugins/ldifeditor/src/main/java/org/apache/directory/studio/ldifeditor/editor/text/LdifDamagerRepairer.java
index d736455..8cba4d2 100644
--- a/plugins/ldifeditor/src/main/java/org/apache/directory/studio/ldifeditor/editor/text/LdifDamagerRepairer.java
+++ b/plugins/ldifeditor/src/main/java/org/apache/directory/studio/ldifeditor/editor/text/LdifDamagerRepairer.java
@@ -75,20 +75,15 @@
 
     private Map<String, Object> textAttributeKeyToValueMap;
 
-
-    // private IDocument document;
-
     public LdifDamagerRepairer( ILdifEditor editor )
     {
         super();
         this.editor = editor;
-        // this.document = null;
     }
 
 
     public void setDocument( IDocument document )
     {
-        // this.document = document;
     }
 
 
@@ -104,47 +99,51 @@
         LdifFile ldifModel = this.editor.getLdifModel();
         List<LdifContainer> allContainers = ldifModel.getContainers();
         List<LdifContainer> containerList = new ArrayList<LdifContainer>();
-        
+
         for ( LdifContainer ldifContainer : allContainers )
         {
             Region containerRegion = new Region( ldifContainer.getOffset(), ldifContainer.getLength() );
-            
+
             if ( TextUtilities.overlaps( containerRegion, damage ) )
             {
                 containerList.add( ldifContainer );
             }
         }
-        
+
         LdifContainer[] containers = ( LdifContainer[] ) containerList
             .toArray( new LdifContainer[containerList.size()] );
         this.highlight( containers, presentation, damage );
     }
 
-    private TextAttribute geTextAttribute( String key )
+
+    private TextAttribute getTextAttribute( String key )
     {
         IPreferenceStore store = LdifEditorActivator.getDefault().getPreferenceStore();
 
-        RGB rgb = PreferenceConverter.getColor( store, key
-            + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX );
-        int style = store.getInt( key + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_STYLE_SUFFIX );
+        String colorKey = key + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX;
+        String styleKey = key + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_STYLE_SUFFIX;
+
+        RGB rgb = PreferenceConverter.getColor( store, colorKey );
+        int style = store.getInt( styleKey );
 
         if ( textAttributeKeyToValueMap != null )
         {
-            if ( textAttributeKeyToValueMap.containsKey( key
-                + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX ) )
+            if ( textAttributeKeyToValueMap.containsKey( colorKey ) )
             {
-                rgb = ( RGB ) textAttributeKeyToValueMap.get( key
-                    + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_RGB_SUFFIX );
+                rgb = ( RGB ) textAttributeKeyToValueMap.get( colorKey );
             }
-            if ( textAttributeKeyToValueMap.containsKey( key
-                + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_STYLE_SUFFIX ) )
+            if ( textAttributeKeyToValueMap.containsKey( styleKey ) )
             {
-                style = ( ( Integer ) textAttributeKeyToValueMap.get( key
-                    + LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_STYLE_SUFFIX ) ).intValue();
+                style = ( ( Integer ) textAttributeKeyToValueMap.get( styleKey ) ).intValue();
             }
         }
 
-        Color color = LdifEditorActivator.getDefault().getColor( rgb );
+        /*
+         * Use color <code>null</code> if the default is the default string, This is important
+         * to not override the system color when a high-contrast theme is used.
+         */
+        boolean isDefaultDefaultKey = IPreferenceStore.STRING_DEFAULT_DEFAULT.equals( store.getString( colorKey ) );
+        Color color = isDefaultDefaultKey ? null : LdifEditorActivator.getDefault().getColor( rgb );
         TextAttribute textAttribute = new TextAttribute( color, null, style );
         return textAttribute;
     }
@@ -176,20 +175,24 @@
 
     private void highlight( LdifContainer[] containers, TextPresentation presentation, ITypedRegion damage )
     {
-
-        // TextAttribute DEFAULT_TEXT_ATTRIBUTE = new
-        // TextAttribute(Activator.getDefault().getColor(CommonUIConstants.COLOR_BLACK));
-
-        TextAttribute COMMENT_TEXT_ATTRIBUTE = geTextAttribute( LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_COMMENT );
-        TextAttribute KEYWORD_TEXT_ATTRIBUTE = geTextAttribute( LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_KEYWORD );
-        TextAttribute DN_TEXT_ATTRIBUTE = geTextAttribute( LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_DN );
-        TextAttribute ATTRIBUTE_TEXT_ATTRIBUTE = geTextAttribute( LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_ATTRIBUTE );
-        TextAttribute VALUETYPE_TEXT_ATTRIBUTE = geTextAttribute( LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_VALUETYPE );
-        TextAttribute VALUE_TEXT_ATTRIBUTE = geTextAttribute( LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_VALUE );
-        TextAttribute ADD_TEXT_ATTRIBUTE = geTextAttribute( LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_CHANGETYPEADD );
-        TextAttribute MODIFY_TEXT_ATTRIBUTE = geTextAttribute( LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_CHANGETYPEMODIFY );
-        TextAttribute DELETE_TEXT_ATTRIBUTE = geTextAttribute( LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_CHANGETYPEDELETE );
-        TextAttribute MODDN_TEXT_ATTRIBUTE = geTextAttribute( LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_CHANGETYPEMODDN );
+        TextAttribute COMMENT_TEXT_ATTRIBUTE = getTextAttribute(
+            LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_COMMENT );
+        TextAttribute KEYWORD_TEXT_ATTRIBUTE = getTextAttribute(
+            LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_KEYWORD );
+        TextAttribute DN_TEXT_ATTRIBUTE = getTextAttribute( LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_DN );
+        TextAttribute ATTRIBUTE_TEXT_ATTRIBUTE = getTextAttribute(
+            LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_ATTRIBUTE );
+        TextAttribute VALUETYPE_TEXT_ATTRIBUTE = getTextAttribute(
+            LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_VALUETYPE );
+        TextAttribute VALUE_TEXT_ATTRIBUTE = getTextAttribute( LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_VALUE );
+        TextAttribute ADD_TEXT_ATTRIBUTE = getTextAttribute(
+            LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_CHANGETYPEADD );
+        TextAttribute MODIFY_TEXT_ATTRIBUTE = getTextAttribute(
+            LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_CHANGETYPEMODIFY );
+        TextAttribute DELETE_TEXT_ATTRIBUTE = getTextAttribute(
+            LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_CHANGETYPEDELETE );
+        TextAttribute MODDN_TEXT_ATTRIBUTE = getTextAttribute(
+            LdifEditorConstants.PREFERENCE_LDIFEDITOR_SYNTAX_CHANGETYPEMODDN );
 
         for ( int z = 0; z < containers.length; z++ )
         {
diff --git a/plugins/ldifparser/pom-first.xml b/plugins/ldifparser/pom-first.xml
index 5e1885b..70e0ed5 100644
--- a/plugins/ldifparser/pom-first.xml
+++ b/plugins/ldifparser/pom-first.xml
@@ -32,15 +32,6 @@
   <description/>
   <packaging>bundle</packaging>
 
-  <dependencies>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>${junit.version}</version>
-      <scope>test</scope>
-    </dependency>
-  </dependencies>
-
   <build>
      <!-- MANIFEST.MF Generation -->
     <plugins>
diff --git a/plugins/ldifparser/src/test/java/org/apache/directory/studio/ldifparser/model/lines/LdifAttrValLineTest.java b/plugins/ldifparser/src/test/java/org/apache/directory/studio/ldifparser/model/lines/LdifAttrValLineTest.java
index 2cedf49..06b229f 100644
--- a/plugins/ldifparser/src/test/java/org/apache/directory/studio/ldifparser/model/lines/LdifAttrValLineTest.java
+++ b/plugins/ldifparser/src/test/java/org/apache/directory/studio/ldifparser/model/lines/LdifAttrValLineTest.java
@@ -21,14 +21,17 @@
 package org.apache.directory.studio.ldifparser.model.lines;
 
 
-import junit.framework.TestCase;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import org.apache.directory.studio.ldifparser.LdifFormatParameters;
 
+import org.junit.jupiter.api.Test;
 
-public class LdifAttrValLineTest extends TestCase
+
+public class LdifAttrValLineTest
 {
 
+    @Test
     public void testToFormattedStringSimple()
     {
         LdifAttrValLine line = LdifAttrValLine.create( "cn", "abc" ); //$NON-NLS-1$ //$NON-NLS-2$
@@ -38,6 +41,7 @@
     }
 
 
+    @Test
     public void testToFormattedStringLineWrap()
     {
         LdifAttrValLine line = LdifAttrValLine.create( "cn", //$NON-NLS-1$
@@ -49,6 +53,7 @@
     }
 
 
+    @Test
     public void testToFormattedStringNoSpaceAfterColon()
     {
         LdifAttrValLine line = LdifAttrValLine.create( "cn", "abc" ); //$NON-NLS-1$ //$NON-NLS-2$
@@ -58,6 +63,7 @@
     }
 
 
+    @Test
     public void testToFormattedStringBase64()
     {
         LdifAttrValLine line = LdifAttrValLine.create( "cn", "\u00e4\u00f6\u00fc" ); //$NON-NLS-1$ //$NON-NLS-2$
@@ -67,6 +73,7 @@
     }
 
 
+    @Test
     public void testToFormattedString_DIRSERVER_285()
     {
         LdifAttrValLine line = LdifAttrValLine.create( "cn", "abc::def:<ghi" ); //$NON-NLS-1$ //$NON-NLS-2$
diff --git a/plugins/ldifparser/src/test/java/org/apache/directory/studio/ldifparser/model/lines/LdifDnLineTest.java b/plugins/ldifparser/src/test/java/org/apache/directory/studio/ldifparser/model/lines/LdifDnLineTest.java
index 47c4ec8..eaa19bf 100644
--- a/plugins/ldifparser/src/test/java/org/apache/directory/studio/ldifparser/model/lines/LdifDnLineTest.java
+++ b/plugins/ldifparser/src/test/java/org/apache/directory/studio/ldifparser/model/lines/LdifDnLineTest.java
@@ -21,14 +21,18 @@
 package org.apache.directory.studio.ldifparser.model.lines;
 
 
-import junit.framework.TestCase;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import org.apache.directory.studio.ldifparser.LdifFormatParameters;
 
+import org.junit.jupiter.api.Test;
 
-public class LdifDnLineTest extends TestCase
+
+public class LdifDnLineTest
 {
 
+    @Test
     public void testToFormattedStringSimple()
     {
         LdifDnLine dnLine = LdifDnLine.create( "cn=abc,ou=department,o=org,dc=example,dc=com" ); //$NON-NLS-1$
@@ -38,6 +42,7 @@
     }
 
 
+    @Test
     public void testToFormattedStringNewline()
     {
         LdifDnLine dnLine = LdifDnLine.create( "cn=abc,ou=department,o=org,dc=example,dc=com" ); //$NON-NLS-1$
@@ -47,6 +52,7 @@
     }
 
 
+    @Test
     public void testToFormattedStringLineWrap()
     {
         LdifDnLine dnLine = LdifDnLine
@@ -58,6 +64,7 @@
     }
 
 
+    @Test
     public void testToFormattedStringNoSpaceAfterColon()
     {
         LdifDnLine dnLine = LdifDnLine.create( "cn=abc,ou=department,o=org,dc=example,dc=com" ); //$NON-NLS-1$
@@ -67,6 +74,7 @@
     }
 
 
+    @Test
     public void testToFormattedStringBase64()
     {
         LdifDnLine dnLine = LdifDnLine.create( "cn=\u00e4\u00f6\u00fc,ou=department,o=org,dc=example,dc=com" ); //$NON-NLS-1$
@@ -80,6 +88,7 @@
      * Test for DIRSTUDIO-598
      * (Base64 encoded Dn marked as invalid in LDIF editor)
      */
+    @Test
     public void testIsValid()
     {
         LdifDnLine dnLine = LdifDnLine.create( "cn=\\#\\\\\\+\\, \\\"\u00f6\u00e9\\\",ou=users,ou=system" ); //$NON-NLS-1$
diff --git a/plugins/ldifparser/src/test/java/org/apache/directory/studio/ldifparser/parser/LdifParserTest.java b/plugins/ldifparser/src/test/java/org/apache/directory/studio/ldifparser/parser/LdifParserTest.java
index 7f29000..f1c80ac 100644
--- a/plugins/ldifparser/src/test/java/org/apache/directory/studio/ldifparser/parser/LdifParserTest.java
+++ b/plugins/ldifparser/src/test/java/org/apache/directory/studio/ldifparser/parser/LdifParserTest.java
@@ -21,15 +21,18 @@
 package org.apache.directory.studio.ldifparser.parser;
 
 
-import junit.framework.TestCase;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import org.apache.directory.studio.ldifparser.LdifFormatParameters;
 import org.apache.directory.studio.ldifparser.model.LdifFile;
 
+import org.junit.jupiter.api.Test;
 
-public class LdifParserTest extends TestCase
+
+public class LdifParserTest
 {
 
+    @Test
     public void testLdifNull()
     {
         String ldif = null;
@@ -41,6 +44,7 @@
     }
 
 
+    @Test
     public void testParseAndFormatWithLdifWindowsLineBreak()
     {
         String ldif = ""
@@ -62,6 +66,7 @@
     }
 
 
+    @Test
     public void testParseAndFormatWithLdifUnixLineBreak()
     {
         String ldif = ""
diff --git a/plugins/openldap.acl.editor/src/main/java/org/apache/directory/studio/openldap/config/acl/dialogs/AclAttributeDialog.java b/plugins/openldap.acl.editor/src/main/java/org/apache/directory/studio/openldap/config/acl/dialogs/AclAttributeDialog.java
index a934a68..19c6620 100644
--- a/plugins/openldap.acl.editor/src/main/java/org/apache/directory/studio/openldap/config/acl/dialogs/AclAttributeDialog.java
+++ b/plugins/openldap.acl.editor/src/main/java/org/apache/directory/studio/openldap/config/acl/dialogs/AclAttributeDialog.java
@@ -23,6 +23,7 @@
 import org.apache.directory.api.util.Strings;
 import org.apache.directory.studio.common.ui.AddEditDialog;
 import org.apache.directory.studio.common.ui.CommonUIConstants;
+import org.apache.directory.studio.common.ui.CommonUIPlugin;
 import org.apache.directory.studio.common.ui.CommonUIUtils;
 import org.apache.directory.studio.common.ui.widgets.BaseWidgetUtils;
 import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection;
@@ -274,12 +275,12 @@
             // Check that the element does not already exist
             if ( getElements().contains( getEditedElement() ) )
             {
-                attributevalueText.setForeground( CommonUIConstants.RED_COLOR );
+                attributevalueText.setForeground( CommonUIPlugin.getDefault().getColor( CommonUIConstants.ERROR_COLOR ) );
                 okButton.setEnabled( false );
             }
             else
             {
-                attributevalueText.setForeground( CommonUIConstants.BLACK_COLOR );
+                attributevalueText.setForeground( CommonUIPlugin.getDefault().getColor( CommonUIConstants.DEFAULT_COLOR ) );
                 okButton.setEnabled( true );
             }
         }
diff --git a/plugins/openldap.acl.editor/src/main/java/org/apache/directory/studio/openldap/config/acl/sourceeditor/OpenLdapAclTextAttributeProvider.java b/plugins/openldap.acl.editor/src/main/java/org/apache/directory/studio/openldap/config/acl/sourceeditor/OpenLdapAclTextAttributeProvider.java
index 2c77f6a..db1a5fc 100644
--- a/plugins/openldap.acl.editor/src/main/java/org/apache/directory/studio/openldap/config/acl/sourceeditor/OpenLdapAclTextAttributeProvider.java
+++ b/plugins/openldap.acl.editor/src/main/java/org/apache/directory/studio/openldap/config/acl/sourceeditor/OpenLdapAclTextAttributeProvider.java
@@ -24,6 +24,7 @@
 import java.util.Map;
 
 import org.apache.directory.studio.common.ui.CommonUIConstants;
+import org.apache.directory.studio.common.ui.CommonUIPlugin;
 import org.eclipse.jface.text.TextAttribute;
 import org.eclipse.swt.SWT;
 
@@ -47,11 +48,11 @@
      */
     public OpenLdapAclTextAttributeProvider()
     {
-        attributes.put( DEFAULT_ATTRIBUTE, new TextAttribute( CommonUIConstants.BLACK_COLOR ) );
-
-        attributes.put( KEYWORD_ATTRIBUTE, new TextAttribute( CommonUIConstants.M_PURPLE_COLOR, null, SWT.BOLD ) );
-
-        attributes.put( STRING_ATTRIBUTE, new TextAttribute( CommonUIConstants.BLUE_COLOR ) );
+        CommonUIPlugin plugin = CommonUIPlugin.getDefault();
+        attributes.put( DEFAULT_ATTRIBUTE, new TextAttribute( plugin.getColor( CommonUIConstants.DEFAULT_COLOR ) ) );
+        attributes.put( KEYWORD_ATTRIBUTE,
+            new TextAttribute( plugin.getColor( CommonUIConstants.ATTRIBUTE_TYPE_COLOR ), null, SWT.BOLD ) );
+        attributes.put( STRING_ATTRIBUTE, new TextAttribute( plugin.getColor( CommonUIConstants.VALUE_COLOR ) ) );
     }
 
 
diff --git a/plugins/openldap.acl.editor/src/test/java/org/apache/directory/studio/openldap/config/acl/model/OpenLdapAclParserTest.java b/plugins/openldap.acl.editor/src/test/java/org/apache/directory/studio/openldap/config/acl/model/OpenLdapAclParserTest.java
index 2a96427..ed7aa25 100644
--- a/plugins/openldap.acl.editor/src/test/java/org/apache/directory/studio/openldap/config/acl/model/OpenLdapAclParserTest.java
+++ b/plugins/openldap.acl.editor/src/test/java/org/apache/directory/studio/openldap/config/acl/model/OpenLdapAclParserTest.java
@@ -20,13 +20,13 @@
 package org.apache.directory.studio.openldap.config.acl.model;
 
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
 import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.List;
@@ -34,23 +34,22 @@
 import antlr.RecognitionException;
 
 import org.apache.directory.studio.openldap.config.acl.model.AclAttribute;
-import org.junit.Ignore;
-import org.junit.Test;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
 
+//assertThrows(ParseException.class, () -> parser.parse( "" ));
 
 /**
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
 public class OpenLdapAclParserTest
 {
-    @Test( expected = ParseException.class )
+    @Test
     public void testEmpty() throws Exception
     {
         System.out.println( "\n--> testEmpty" );
         OpenLdapAclParser parser = new OpenLdapAclParser();
-        parser.parse( "" );
-
-        fail();
+        assertThrows(ParseException.class, () -> parser.parse( "" ));
     }
 
 
@@ -134,14 +133,12 @@
     }
 
 
-    @Test( expected = ParseException.class )
+    @Test
     public void testWhatTwoStars() throws Exception
     {
         System.out.println( "\n--> testWhatTwoStars" );
         OpenLdapAclParser parser = new OpenLdapAclParser();
-        parser.parse( "to * * by *" );
-
-        fail();
+        assertThrows(ParseException.class, () -> parser.parse( "to * * by *" ));
     }
 
     
@@ -172,7 +169,7 @@
     }
 
     
-    @Test( expected = ParseException.class )
+    @Test
     public void testWhatDnStar() throws Exception
     {
         System.out.println( "\n--> testWhatDnStar" );
@@ -180,13 +177,11 @@
         OpenLdapAclParser parser = new OpenLdapAclParser();
 
         // Testing the ACL item
-        parser.parse( "access to dn=* by *" );
-        
-        fail();
+        assertThrows(ParseException.class, () -> parser.parse( "access to dn=* by *" ));
     }
 
     
-    @Test( expected=ParseException.class)
+    @Test
     public void testWhatDnValidDnNoQuote() throws Exception
     {
         System.out.println( "\n--> testWhatDnValidDnNoQuote" );
@@ -196,13 +191,11 @@
         OpenLdapAclParser parser = new OpenLdapAclParser();
 
         // Testing the ACL item
-        parser.parse( "access to dn=" + dnPattern + "\n by *" );
-        
-        fail();
+        assertThrows(ParseException.class, () -> parser.parse( "access to dn=" + dnPattern + "\n by *" ));
     }
 
-    @Ignore
-    @Test ( expected=ParseException.class)
+    @Disabled
+    @Test
     public void testWhatDnBadDn() throws Exception
     {
         System.out.println( "\n--> testWhatDnBadDn" );
@@ -212,9 +205,7 @@
         OpenLdapAclParser parser = new OpenLdapAclParser();
 
         // Testing the ACL item
-        parser.parse( "access to dn=\"" + dnPattern + "\"\n by *" );
-        
-        fail();
+        assertThrows(ParseException.class, () -> parser.parse( "access to dn=\"" + dnPattern + "\"\n by *" ));
     }
 
     
@@ -248,7 +239,7 @@
     }
     
     
-    @Test ( expected=ParseException.class)
+    @Test
     public void testWhatDnBasicDnExactNoQuote() throws Exception
     {
         System.out.println( "\n--> testWhatDnBasicDnExactNoQuote" );
@@ -258,13 +249,11 @@
         OpenLdapAclParser parser = new OpenLdapAclParser();
 
         // Testing the ACL item
-        parser.parse( "access to dn.exact=" + dnPattern + " by *" );
-        
-        fail();
+        assertThrows(ParseException.class, () -> parser.parse( "access to dn.exact=" + dnPattern + " by *" ));
     }
     
     
-    @Test ( expected=ParseException.class)
+    @Test
     public void testWhatDnBasicDnExactBadDn() throws Exception
     {
         System.out.println( "\n--> testWhatDnBasicDnExactBadDn" );
@@ -274,9 +263,7 @@
         OpenLdapAclParser parser = new OpenLdapAclParser();
 
         // Testing the ACL item
-        parser.parse( "access to dn.exact=" + dnPattern + " by *" );
-        
-        fail();
+        assertThrows(ParseException.class, () -> parser.parse( "access to dn.exact=" + dnPattern + " by *" ));
     }
     
     
@@ -310,7 +297,7 @@
     }
     
     
-    @Test( expected=ParseException.class)
+    @Test
     public void testWhatDnBasicDnRegexNoQuote() throws Exception
     {
         System.out.println( "\n--> testWhatDnBasicDnRegexNoQuote" );
@@ -320,9 +307,7 @@
         OpenLdapAclParser parser = new OpenLdapAclParser();
 
         // Testing the ACL item
-        AclItem aclItem = parser.parse( "access to dn.regex=" + dnPattern + " by *" );
-        
-        fail();
+        assertThrows(ParseException.class, () -> parser.parse( "access to dn.regex=" + dnPattern + " by *" ));
     }
     
     
@@ -544,7 +529,7 @@
     }
 
     
-    @Test( expected=ParseException.class)
+    @Test
     public void testWhatDnScopeOneNoQuotedDn() throws Exception
     {
         System.out.println( "\n--> testWhatDnScopeOneNoQuotedDn" );
@@ -554,11 +539,11 @@
         OpenLdapAclParser parser = new OpenLdapAclParser();
 
         // Testing the ACL item
-        parser.parse( "access to dn.one=" + dnPattern + " by *" );
+        assertThrows(ParseException.class, () -> parser.parse( "access to dn.one=" + dnPattern + " by *" ));
     }
 
     
-    @Test( expected=ParseException.class)
+    @Test
     public void testWhatDnScopeOneNoDn() throws Exception
     {
         System.out.println( "\n--> testWhatDnScopeOneNoDn" );
@@ -567,11 +552,11 @@
         OpenLdapAclParser parser = new OpenLdapAclParser();
 
         // Testing the ACL item
-        parser.parse( "access to dn.one= by *" );
+        assertThrows(ParseException.class, () -> parser.parse( "access to dn.one= by *" ));
     }
 
     
-    @Test( expected=ParseException.class)
+    @Test
     public void testWhatDnScopeOneStar() throws Exception
     {
         System.out.println( "\n--> testWhatDnScopeOneStar" );
@@ -580,7 +565,7 @@
         OpenLdapAclParser parser = new OpenLdapAclParser();
 
         // Testing the ACL item
-        parser.parse( "access to dn.one=* by *" );
+        assertThrows(ParseException.class, () -> parser.parse( "access to dn.one=* by *" ));
     }
     
     
@@ -641,7 +626,7 @@
     }
 
 
-    @Test( expected=ParseException.class)
+    @Test
     public void testWhatFilterWrongSimple() throws Exception
     {
         System.out.println( "\n--> testWhatFilterWrongSimple" );
@@ -651,15 +636,13 @@
         OpenLdapAclParser parser = new OpenLdapAclParser();
 
         // Testing the ACL item
-        parser.parse( "access to filter=" + filter + " by *" );
-        
-        fail();
+        assertThrows(ParseException.class, () -> parser.parse( "access to filter=" + filter + " by *" ));
     }
  
 
     
 
-    @Ignore
+    @Disabled
     @Test
     public void testFail() throws Exception
     {
@@ -3853,7 +3836,7 @@
 
 
     @Test
-    @Ignore
+    @Disabled
     public void testWhoAccessLevelSelfPrivMinusMWRSCX() throws Exception
     {
         // Create parser
diff --git a/plugins/openldap.common.ui/src/test/java/org/apache/directory/studio/openldap/common/ui/dialogs/UnixPermissionsTest.java b/plugins/openldap.common.ui/src/test/java/org/apache/directory/studio/openldap/common/ui/dialogs/UnixPermissionsTest.java
index d0fe1ff..c1cc039 100644
--- a/plugins/openldap.common.ui/src/test/java/org/apache/directory/studio/openldap/common/ui/dialogs/UnixPermissionsTest.java
+++ b/plugins/openldap.common.ui/src/test/java/org/apache/directory/studio/openldap/common/ui/dialogs/UnixPermissionsTest.java
@@ -20,12 +20,13 @@
 package org.apache.directory.studio.openldap.common.ui.dialogs;
 
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
 import org.apache.directory.studio.openldap.common.ui.model.UnixPermissions;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 
 public class UnixPermissionsTest
diff --git a/plugins/openldap.config.editor/src/main/java/org/apache/directory/studio/openldap/config/editor/databases/MdbDatabaseSpecificDetailsBlock.java b/plugins/openldap.config.editor/src/main/java/org/apache/directory/studio/openldap/config/editor/databases/MdbDatabaseSpecificDetailsBlock.java
index 0bead2b..afe5906 100644
--- a/plugins/openldap.config.editor/src/main/java/org/apache/directory/studio/openldap/config/editor/databases/MdbDatabaseSpecificDetailsBlock.java
+++ b/plugins/openldap.config.editor/src/main/java/org/apache/directory/studio/openldap/config/editor/databases/MdbDatabaseSpecificDetailsBlock.java
@@ -25,6 +25,7 @@
 
 import org.apache.directory.api.util.Strings;
 import org.apache.directory.studio.common.ui.CommonUIConstants;
+import org.apache.directory.studio.common.ui.CommonUIPlugin;
 import org.apache.directory.studio.common.ui.widgets.BaseWidgetUtils;
 import org.apache.directory.studio.common.ui.widgets.TableWidget;
 import org.apache.directory.studio.common.ui.widgets.WidgetModifyListener;
@@ -207,7 +208,7 @@
 
         // Directory Text. This is a MUST attribute (it will be red and bold)
         Label olcDirectory = toolkit.createLabel( databaseConfigurationComposite, Messages.getString( "OpenLDAPMDBConfiguration.Directory" ) );
-        olcDirectory.setForeground( CommonUIConstants.RED_COLOR );
+        olcDirectory.setForeground( CommonUIPlugin.getDefault().getColor( CommonUIConstants.ERROR_COLOR ) );
         FontDescriptor boldDescriptor = FontDescriptor.createFrom( olcDirectory.getFont() ).setStyle( SWT.BOLD );
         Font boldFont = boldDescriptor.createFont( olcDirectory.getDisplay() );
         olcDirectory.setFont( boldFont );
diff --git a/plugins/openldap.config.editor/src/main/java/org/apache/directory/studio/openldap/config/editor/dialogs/SizeTimeLimitDialog.java b/plugins/openldap.config.editor/src/main/java/org/apache/directory/studio/openldap/config/editor/dialogs/SizeTimeLimitDialog.java
index 9360d9d..bb50286 100644
--- a/plugins/openldap.config.editor/src/main/java/org/apache/directory/studio/openldap/config/editor/dialogs/SizeTimeLimitDialog.java
+++ b/plugins/openldap.config.editor/src/main/java/org/apache/directory/studio/openldap/config/editor/dialogs/SizeTimeLimitDialog.java
@@ -22,6 +22,7 @@
 
 import org.apache.directory.studio.common.ui.AddEditDialog;
 import org.apache.directory.studio.common.ui.CommonUIConstants;
+import org.apache.directory.studio.common.ui.CommonUIPlugin;
 import org.apache.directory.studio.common.ui.widgets.BaseWidgetUtils;
 import org.eclipse.jface.dialogs.IDialogConstants;
 import org.eclipse.swt.SWT;
@@ -235,13 +236,13 @@
             
             if ( sizeLimitWrapper.isValid() )
             {
-                sizeLimitText.setForeground( CommonUIConstants.BLACK_COLOR );
+                sizeLimitText.setForeground( CommonUIPlugin.getDefault().getColor( CommonUIConstants.DEFAULT_COLOR ) );
                 setEditedElement( sizeLimitWrapper );
                 okButton.setEnabled( true );
             }
             else
             {
-                sizeLimitText.setForeground( CommonUIConstants.RED_COLOR );
+                sizeLimitText.setForeground( CommonUIPlugin.getDefault().getColor( CommonUIConstants.ERROR_COLOR ) );
                 okButton.setEnabled( false );
             }
         };
@@ -264,13 +265,13 @@
             
             if ( timeLimitWrapper.isValid() )
             {
-                timeLimitText.setForeground( CommonUIConstants.BLACK_COLOR );
+                timeLimitText.setForeground( CommonUIPlugin.getDefault().getColor( CommonUIConstants.DEFAULT_COLOR ) );
                 setEditedElement( timeLimitWrapper );
                 okButton.setEnabled( true );
             }
             else
             {
-                timeLimitText.setForeground( CommonUIConstants.RED_COLOR );
+                timeLimitText.setForeground( CommonUIPlugin.getDefault().getColor( CommonUIConstants.ERROR_COLOR ) );
                 okButton.setEnabled( false );
             }
         };
diff --git a/plugins/openldap.config.editor/src/main/java/org/apache/directory/studio/openldap/config/editor/pages/OpenLDAPServerConfigurationEditorPage.java b/plugins/openldap.config.editor/src/main/java/org/apache/directory/studio/openldap/config/editor/pages/OpenLDAPServerConfigurationEditorPage.java
index 837600e..edde476 100644
--- a/plugins/openldap.config.editor/src/main/java/org/apache/directory/studio/openldap/config/editor/pages/OpenLDAPServerConfigurationEditorPage.java
+++ b/plugins/openldap.config.editor/src/main/java/org/apache/directory/studio/openldap/config/editor/pages/OpenLDAPServerConfigurationEditorPage.java
@@ -21,6 +21,7 @@
 
 
 import org.apache.directory.studio.common.ui.CommonUIConstants;
+import org.apache.directory.studio.common.ui.CommonUIPlugin;
 import org.apache.directory.studio.common.ui.widgets.TableWidget;
 import org.apache.directory.studio.common.ui.widgets.WidgetModifyListener;
 import org.apache.directory.studio.openldap.config.actions.EditorExportConfigurationAction;
@@ -259,7 +260,7 @@
     protected Label createDefaultValueLabel( FormToolkit toolkit, Composite parent, String text )
     {
         Label label = toolkit.createLabel( parent, NLS.bind( "(Default: {0})", text ) );
-        label.setForeground( CommonUIConstants.M_GREY_COLOR );
+        label.setForeground( CommonUIPlugin.getDefault().getColor( CommonUIConstants.KEYWORD_1_COLOR ) );
 
         return label;
     }
diff --git a/plugins/openldap.config.editor/src/main/java/org/apache/directory/studio/openldap/config/editor/wrappers/DatabaseWrapperLabelProvider.java b/plugins/openldap.config.editor/src/main/java/org/apache/directory/studio/openldap/config/editor/wrappers/DatabaseWrapperLabelProvider.java
index fecb06e..bc4e9f1 100644
--- a/plugins/openldap.config.editor/src/main/java/org/apache/directory/studio/openldap/config/editor/wrappers/DatabaseWrapperLabelProvider.java
+++ b/plugins/openldap.config.editor/src/main/java/org/apache/directory/studio/openldap/config/editor/wrappers/DatabaseWrapperLabelProvider.java
@@ -23,6 +23,7 @@
 
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.studio.common.ui.CommonUIConstants;
+import org.apache.directory.studio.common.ui.CommonUIPlugin;
 import org.apache.directory.studio.openldap.common.ui.model.DatabaseTypeEnum;
 import org.apache.directory.studio.openldap.config.OpenLdapConfigurationPlugin;
 import org.apache.directory.studio.openldap.config.OpenLdapConfigurationPluginConstants;
@@ -49,7 +50,7 @@
         @Override
         public void applyStyles( TextStyle textStyle ) 
         {
-            textStyle.foreground = CommonUIConstants.L_GREY_COLOR;
+            textStyle.foreground = CommonUIPlugin.getDefault().getColor( CommonUIConstants.DISABLED_COLOR );
         }
     };
     
diff --git a/plugins/openldap.config.editor/src/main/java/org/apache/directory/studio/openldap/config/editor/wrappers/TcpBufferWrapper.java b/plugins/openldap.config.editor/src/main/java/org/apache/directory/studio/openldap/config/editor/wrappers/TcpBufferWrapper.java
index 1366f51..afd2174 100644
--- a/plugins/openldap.config.editor/src/main/java/org/apache/directory/studio/openldap/config/editor/wrappers/TcpBufferWrapper.java
+++ b/plugins/openldap.config.editor/src/main/java/org/apache/directory/studio/openldap/config/editor/wrappers/TcpBufferWrapper.java
@@ -334,7 +334,7 @@
     {
         int h = 37;
         
-        h += h*17 + size;
+        h += h*17 + Long.hashCode( size );
         h += h*17 + tcpType.hashCode();
         h += h*17 + listener.hashCode();
         
diff --git a/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/editor/dialogs/PurgeTimeSpanTest.java b/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/editor/dialogs/PurgeTimeSpanTest.java
index 4363d0a..a14ac79 100644
--- a/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/editor/dialogs/PurgeTimeSpanTest.java
+++ b/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/editor/dialogs/PurgeTimeSpanTest.java
@@ -20,12 +20,12 @@
 package org.apache.directory.studio.openldap.config.editor.dialogs;
 
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
 
 import java.text.ParseException;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 
 /**
diff --git a/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/model/overlay/OlcValSortValueParserTest.java b/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/model/overlay/OlcValSortValueParserTest.java
index 515e6ed..45f3685 100644
--- a/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/model/overlay/OlcValSortValueParserTest.java
+++ b/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/model/overlay/OlcValSortValueParserTest.java
@@ -20,14 +20,14 @@
 package org.apache.directory.studio.openldap.config.model.overlay;
 
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import org.apache.directory.api.ldap.model.name.Dn;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 
 /**
diff --git a/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/wrappers/DbIndexWrapperTest.java b/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/wrappers/DbIndexWrapperTest.java
index 125269b..beb4a0e 100644
--- a/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/wrappers/DbIndexWrapperTest.java
+++ b/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/wrappers/DbIndexWrapperTest.java
@@ -19,13 +19,13 @@
  */
 package org.apache.directory.studio.openldap.config.wrappers;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import org.apache.directory.studio.openldap.config.editor.wrappers.DbIndexWrapper;
 import org.apache.directory.studio.openldap.common.ui.model.DbIndexTypeEnum;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 /**
  * A test for the DbIndexWrapper class
diff --git a/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/wrappers/LimitsWrapperTest.java b/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/wrappers/LimitsWrapperTest.java
index c871cbb..8edbaaf 100644
--- a/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/wrappers/LimitsWrapperTest.java
+++ b/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/wrappers/LimitsWrapperTest.java
@@ -19,10 +19,10 @@
  */
 package org.apache.directory.studio.openldap.config.wrappers;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import org.apache.directory.studio.openldap.common.ui.model.DnSpecStyleEnum;
 import org.apache.directory.studio.openldap.common.ui.model.DnSpecTypeEnum;
@@ -31,7 +31,7 @@
 import org.apache.directory.studio.openldap.config.editor.wrappers.LimitsWrapper;
 import org.apache.directory.studio.openldap.config.editor.wrappers.TimeLimitWrapper;
 import org.apache.directory.studio.openldap.config.editor.wrappers.SizeLimitWrapper;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 import java.util.List;
 
 /**
diff --git a/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/wrappers/SaslSecPropsWrapperTest.java b/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/wrappers/SaslSecPropsWrapperTest.java
index 2162759..55c4a5e 100644
--- a/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/wrappers/SaslSecPropsWrapperTest.java
+++ b/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/wrappers/SaslSecPropsWrapperTest.java
@@ -19,14 +19,14 @@
  */
 package org.apache.directory.studio.openldap.config.wrappers;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import org.apache.directory.studio.openldap.common.ui.model.SaslSecPropEnum;
 import org.apache.directory.studio.openldap.config.editor.wrappers.SaslSecPropsWrapper;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 /**
  * A test for the SaslSecPropsWrapper class
diff --git a/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/wrappers/SizeLimitWrapperTest.java b/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/wrappers/SizeLimitWrapperTest.java
index 67fa599..de51e80 100644
--- a/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/wrappers/SizeLimitWrapperTest.java
+++ b/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/wrappers/SizeLimitWrapperTest.java
@@ -19,12 +19,12 @@
  */
 package org.apache.directory.studio.openldap.config.wrappers;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import org.apache.directory.studio.openldap.config.editor.wrappers.SizeLimitWrapper;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 /**
  * A test for the SizeLimitWrapper class
diff --git a/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/wrappers/SsfWrapperTest.java b/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/wrappers/SsfWrapperTest.java
index 64333ab..85689d7 100644
--- a/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/wrappers/SsfWrapperTest.java
+++ b/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/wrappers/SsfWrapperTest.java
@@ -19,13 +19,13 @@
  */
 package org.apache.directory.studio.openldap.config.wrappers;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import org.apache.directory.studio.openldap.common.ui.model.SsfFeatureEnum;
 import org.apache.directory.studio.openldap.config.editor.wrappers.SsfWrapper;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 /**
  * A test for the SsfWrapper class
diff --git a/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/wrappers/TimeLimitWrapperTest.java b/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/wrappers/TimeLimitWrapperTest.java
index 1910ec3..ce0e2df 100644
--- a/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/wrappers/TimeLimitWrapperTest.java
+++ b/plugins/openldap.config.editor/src/test/java/org/apache/directory/studio/openldap/config/wrappers/TimeLimitWrapperTest.java
@@ -19,11 +19,11 @@
  */
 package org.apache.directory.studio.openldap.config.wrappers;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import org.apache.directory.studio.openldap.config.editor.wrappers.TimeLimitWrapper;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 /**
  * A test for the TimeLimitWrapper class
diff --git a/plugins/openldap.syncrepl/src/test/java/com/iktek/studio/openldap/syncrepl/IntervalTest.java b/plugins/openldap.syncrepl/src/test/java/com/iktek/studio/openldap/syncrepl/IntervalTest.java
index 90c16de..4da9d45 100644
--- a/plugins/openldap.syncrepl/src/test/java/com/iktek/studio/openldap/syncrepl/IntervalTest.java
+++ b/plugins/openldap.syncrepl/src/test/java/com/iktek/studio/openldap/syncrepl/IntervalTest.java
@@ -20,10 +20,10 @@
 package org.apache.directory.studio.openldap.syncrepl;
 
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 
 /**
diff --git a/plugins/openldap.syncrepl/src/test/java/com/iktek/studio/openldap/syncrepl/KeepAliveTest.java b/plugins/openldap.syncrepl/src/test/java/com/iktek/studio/openldap/syncrepl/KeepAliveTest.java
index 69d78d6..b0e0115 100644
--- a/plugins/openldap.syncrepl/src/test/java/com/iktek/studio/openldap/syncrepl/KeepAliveTest.java
+++ b/plugins/openldap.syncrepl/src/test/java/com/iktek/studio/openldap/syncrepl/KeepAliveTest.java
@@ -20,10 +20,10 @@
 package org.apache.directory.studio.openldap.syncrepl;
 
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 
 /**
diff --git a/plugins/openldap.syncrepl/src/test/java/com/iktek/studio/openldap/syncrepl/ProviderTest.java b/plugins/openldap.syncrepl/src/test/java/com/iktek/studio/openldap/syncrepl/ProviderTest.java
index 220f732..c2e6cde 100644
--- a/plugins/openldap.syncrepl/src/test/java/com/iktek/studio/openldap/syncrepl/ProviderTest.java
+++ b/plugins/openldap.syncrepl/src/test/java/com/iktek/studio/openldap/syncrepl/ProviderTest.java
@@ -20,10 +20,10 @@
 package org.apache.directory.studio.openldap.syncrepl;
 
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 
 /**
diff --git a/plugins/openldap.syncrepl/src/test/java/com/iktek/studio/openldap/syncrepl/RetryPairTest.java b/plugins/openldap.syncrepl/src/test/java/com/iktek/studio/openldap/syncrepl/RetryPairTest.java
index 7ab7135..4ab030f 100644
--- a/plugins/openldap.syncrepl/src/test/java/com/iktek/studio/openldap/syncrepl/RetryPairTest.java
+++ b/plugins/openldap.syncrepl/src/test/java/com/iktek/studio/openldap/syncrepl/RetryPairTest.java
@@ -20,10 +20,10 @@
 package org.apache.directory.studio.openldap.syncrepl;
 
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 
 /**
diff --git a/plugins/openldap.syncrepl/src/test/java/com/iktek/studio/openldap/syncrepl/RetryTest.java b/plugins/openldap.syncrepl/src/test/java/com/iktek/studio/openldap/syncrepl/RetryTest.java
index 8cf9c91..ebbf110 100644
--- a/plugins/openldap.syncrepl/src/test/java/com/iktek/studio/openldap/syncrepl/RetryTest.java
+++ b/plugins/openldap.syncrepl/src/test/java/com/iktek/studio/openldap/syncrepl/RetryTest.java
@@ -20,11 +20,11 @@
 package org.apache.directory.studio.openldap.syncrepl;
 
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.fail;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 
 /**
diff --git a/plugins/openldap.syncrepl/src/test/java/com/iktek/studio/openldap/syncrepl/SyncReplParserTest.java b/plugins/openldap.syncrepl/src/test/java/com/iktek/studio/openldap/syncrepl/SyncReplParserTest.java
index 36c1ebb..ac99ff3 100644
--- a/plugins/openldap.syncrepl/src/test/java/com/iktek/studio/openldap/syncrepl/SyncReplParserTest.java
+++ b/plugins/openldap.syncrepl/src/test/java/com/iktek/studio/openldap/syncrepl/SyncReplParserTest.java
@@ -20,13 +20,13 @@
 package org.apache.directory.studio.openldap.syncrepl;
 
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 
 /**
diff --git a/plugins/pom.xml b/plugins/pom.xml
index 2eee716..575f929 100644
--- a/plugins/pom.xml
+++ b/plugins/pom.xml
@@ -144,11 +144,34 @@
 
   <dependencies>
     <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>${junit.version}</version>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <version>${junit.jupiter.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter</artifactId>
+      <version>${junit.jupiter.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <version>${junit.jupiter.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.platform</groupId>
+      <artifactId>junit-platform-runner</artifactId>
+      <version>${junit.platform.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-params</artifactId>
+      <version>${junit.jupiter.version}</version>
       <scope>test</scope>
     </dependency>
   </dependencies>
-
 </project>
diff --git a/plugins/rcp/about.ini b/plugins/rcp/about.ini
index ce83258..cf5c6f2 100644
--- a/plugins/rcp/about.ini
+++ b/plugins/rcp/about.ini
@@ -1,2 +1,2 @@
 featureImage=studio.png
-aboutText=Apache Directory Studio - The Eclipse-based LDAP browser and directory client.\n\nVersion: ${unqualifiedVersion}.${buildQualifier}\n\nCopyright \u00A9 2006-2020 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.\nVisit http://directory.apache.org/studio
+aboutText=Apache Directory Studio - The Eclipse-based LDAP browser and directory client.\n\nVersion: ${unqualifiedVersion}.${buildQualifier}\n\nCopyright \u00A9 2006-2021 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.\nVisit http://directory.apache.org/studio
diff --git a/plugins/rcp/plugin.properties b/plugins/rcp/plugin.properties
index dd88f2e..1f228dd 100644
--- a/plugins/rcp/plugin.properties
+++ b/plugins/rcp/plugin.properties
@@ -22,6 +22,6 @@
 #---------------------------------------------------------------------------------------------------
 # The I18n Strings
 #---------------------------------------------------------------------------------------------------
-aboutText=Apache Directory Studio\n\nVersion: ${unqualifiedVersion}.${buildQualifier}\n\nCopyright \u00A9 2006-2020 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.\nVisit http://directory.apache.org/studio\n\nSome icons from FAMFAMFAM http://www.famfamfam.com/lab/icons/silk
+aboutText=Apache Directory Studio\n\nVersion: ${unqualifiedVersion}.${buildQualifier}\n\nCopyright \u00A9 2006-2021 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.\nVisit http://directory.apache.org/studio\n\nSome icons from FAMFAMFAM http://www.famfamfam.com/lab/icons/silk
 
 PrefPage_ShutdownPreferencesPage_name=Shutdown
diff --git a/plugins/rcp/plugin.xml b/plugins/rcp/plugin.xml
index c7950c8..5f14094 100644
--- a/plugins/rcp/plugin.xml
+++ b/plugins/rcp/plugin.xml
@@ -107,6 +107,21 @@
         class="org.apache.directory.studio.preferences.ShutdownPreferencesPage"
         id="org.apache.directory.studio.preferences.ShutdownPreferencesPage"
         name="%PrefPage_ShutdownPreferencesPage_name"/>
+    <page
+        category="org.eclipse.ui.preferencePages.Workbench"
+        class="org.eclipse.ui.ExtensionFactory:appearancePreferencePage"
+        id="org.eclipse.ui.preferencePages.Appearance"
+        name="Appearance"/>
+    <page
+        category="org.eclipse.ui.preferencePages.Appearance"
+        class="org.eclipse.ui.ExtensionFactory:colorsAndFontsPreferencePage"
+        id="org.eclipse.ui.preferencePages.ColorsAndFonts"
+        name="Colors and Fonts"/>
+    <page
+        category="org.eclipse.ui.preferencePages.Appearance"
+        class="org.eclipse.ui.internal.editors.text.TextEditorDefaultsPreferencePage"
+        id="org.eclipse.ui.preferencePages.GeneralTextEditor"
+        name="Text Editors"/>
   </extension>
    
   <extension
@@ -134,6 +149,11 @@
     <activityPatternBinding
         activityId="%RCP_Hide_id"
         isEqualityPattern="false"
+        pattern="org.eclipse.ui.net.*"/>
+
+    <activityPatternBinding
+        activityId="%RCP_Hide_id"
+        isEqualityPattern="false"
         pattern="org.eclipse.ui.ide.application.*"/>
 
     <activityPatternBinding
@@ -380,6 +400,11 @@
         activityId="%RCP_Hide_id"
         isEqualityPattern="true"
         pattern="org.eclipse.ui.ide/org.eclipse.e4.ui.importer.openDirectory.menu"/>
+
+    <activityPatternBinding
+        activityId="%RCP_Hide_id"
+        isEqualityPattern="true"
+        pattern="org.eclipse.text.quicksearch/org.eclipse.text.quicksearch.PreferencesPage"/>
   </extension>
 
   <extension
diff --git a/plugins/rcp/plugin_de.properties b/plugins/rcp/plugin_de.properties
index db943c1..5787396 100644
--- a/plugins/rcp/plugin_de.properties
+++ b/plugins/rcp/plugin_de.properties
@@ -14,5 +14,5 @@
 #  KIND, either express or implied.  See the License for the
 #  specific language governing permissions and limitations
 #  under the License.
-aboutText=Apache Directory Studio\n\nVersion: ${unqualifiedVersion}.${buildQualifier}\n\nCopyright \u00A9 2006-2020 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.\nBesuchen Sie http://directory.apache.org/studio\n\nEinige Symbole stammen von FAMFAMFAM http://www.famfamfam.com/lab/icons/silk
+aboutText=Apache Directory Studio\n\nVersion: ${unqualifiedVersion}.${buildQualifier}\n\nCopyright \u00A9 2006-2021 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.\nBesuchen Sie http://directory.apache.org/studio\n\nEinige Symbole stammen von FAMFAMFAM http://www.famfamfam.com/lab/icons/silk
 PrefPage_ShutdownPreferencesPage_name=Beenden
diff --git a/plugins/rcp/plugin_fr.properties b/plugins/rcp/plugin_fr.properties
index 9025757..878e977 100644
--- a/plugins/rcp/plugin_fr.properties
+++ b/plugins/rcp/plugin_fr.properties
@@ -14,5 +14,5 @@
 #  KIND, either express or implied.  See the License for the
 #  specific language governing permissions and limitations
 #  under the License.
-aboutText=Apache Directory Studio\n\nVersion: ${unqualifiedVersion}.${buildQualifier}\n\nCopyright \u00A9 2006-2020 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.\nVisit http://directory.apache.org/studio\n\nCertaines icones sont de FAMFAMFAM http://www.famfamfam.com/lab/icons/silk
+aboutText=Apache Directory Studio\n\nVersion: ${unqualifiedVersion}.${buildQualifier}\n\nCopyright \u00A9 2006-2021 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.\nVisit http://directory.apache.org/studio\n\nCertaines icones sont de FAMFAMFAM http://www.famfamfam.com/lab/icons/silk
 PrefPage_ShutdownPreferencesPage_name=Extinction
diff --git a/plugins/rcp/pom-first.xml b/plugins/rcp/pom-first.xml
index 723059f..8c2ad2b 100644
--- a/plugins/rcp/pom-first.xml
+++ b/plugins/rcp/pom-first.xml
@@ -51,10 +51,11 @@
             
             <Require-Bundle>
  org.eclipse.core.filesystem,
- org.eclipse.core.net,
  org.eclipse.core.resources,
  org.eclipse.core.runtime,
+ org.eclipse.e4.ui.css.swt.theme,
  org.eclipse.ui,
+ org.eclipse.ui.editors,
  org.eclipse.ui.ide,
  org.eclipse.ui.intro
             </Require-Bundle>
diff --git a/plugins/rcp/src/main/java/org/apache/directory/studio/ApplicationWorkbenchAdvisor.java b/plugins/rcp/src/main/java/org/apache/directory/studio/ApplicationWorkbenchAdvisor.java
index 05e0b52..8e40805 100644
--- a/plugins/rcp/src/main/java/org/apache/directory/studio/ApplicationWorkbenchAdvisor.java
+++ b/plugins/rcp/src/main/java/org/apache/directory/studio/ApplicationWorkbenchAdvisor.java
@@ -22,8 +22,6 @@
 
 
 import org.apache.directory.studio.preferences.ShutdownPreferencesPage;
-import org.eclipse.core.net.proxy.IProxyService;
-import org.eclipse.core.runtime.Platform;
 import org.eclipse.core.runtime.preferences.IEclipsePreferences;
 import org.eclipse.core.runtime.preferences.InstanceScope;
 import org.eclipse.jface.dialogs.Dialog;
@@ -37,8 +35,6 @@
 import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
 import org.eclipse.ui.application.WorkbenchAdvisor;
 import org.eclipse.ui.application.WorkbenchWindowAdvisor;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.ServiceReference;
 
 
 /**
@@ -131,31 +127,11 @@
     public void postStartup()
     {
         super.postStartup();
-        activateProxyService();
         removeDefaultJvmSetting();
     }
 
 
     /**
-     * Activate the proxy service, this sets the relevant system properties.
-     */
-    private void activateProxyService()
-    {
-        Bundle bundle = Platform.getBundle( "org.eclipse.ui.ide" ); //$NON-NLS-1$
-        
-        if ( bundle != null )
-        {
-            ServiceReference<?> ref = bundle.getBundleContext().getServiceReference( IProxyService.class.getName() );
-        
-            if ( ref != null )
-            {
-                bundle.getBundleContext().getService( ref );
-            }
-        }
-    }
-
-
-    /**
      * DIRSTUDIO-1188: When launching ApacheDS the first time the same Studio JVM is used and stored in the preferences
      * (~/.ApacheDirectoryStudio/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.launching.prefs).
      * Afterwards that JVM is always used when starting ApacheDS, even if the Studio JVM changes. As there is no
diff --git a/plugins/rcp/src/main/resources/about.ini b/plugins/rcp/src/main/resources/about.ini
index ce83258..cf5c6f2 100644
--- a/plugins/rcp/src/main/resources/about.ini
+++ b/plugins/rcp/src/main/resources/about.ini
@@ -1,2 +1,2 @@
 featureImage=studio.png
-aboutText=Apache Directory Studio - The Eclipse-based LDAP browser and directory client.\n\nVersion: ${unqualifiedVersion}.${buildQualifier}\n\nCopyright \u00A9 2006-2020 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.\nVisit http://directory.apache.org/studio
+aboutText=Apache Directory Studio - The Eclipse-based LDAP browser and directory client.\n\nVersion: ${unqualifiedVersion}.${buildQualifier}\n\nCopyright \u00A9 2006-2021 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.\nVisit http://directory.apache.org/studio
diff --git a/plugins/rcp/src/main/resources/splash.bmp b/plugins/rcp/src/main/resources/splash.bmp
index 02f6ec7..c5f2447 100644
--- a/plugins/rcp/src/main/resources/splash.bmp
+++ b/plugins/rcp/src/main/resources/splash.bmp
Binary files differ
diff --git a/plugins/schemaeditor/about.ini b/plugins/schemaeditor/about.ini
index 8be1d71..303a73d 100644
--- a/plugins/schemaeditor/about.ini
+++ b/plugins/schemaeditor/about.ini
@@ -1,2 +1,2 @@
 featureImage=studio.png
-aboutText=Apache Directory Studio Schema Editor - Editors for LDAP schema, supports ApacheDS and OpenLDAP format.\n\nVersion: ${unqualifiedVersion}.${buildQualifier}\n\nCopyright \u00A9 2006-2020 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.\nVisit http://directory.apache.org/studio
+aboutText=Apache Directory Studio Schema Editor - Editors for LDAP schema, supports ApacheDS and OpenLDAP format.\n\nVersion: ${unqualifiedVersion}.${buildQualifier}\n\nCopyright \u00A9 2006-2021 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.\nVisit http://directory.apache.org/studio
diff --git a/plugins/schemaeditor/plugin_de.properties b/plugins/schemaeditor/plugin_de.properties
index 863e77f..5ff16c2 100644
--- a/plugins/schemaeditor/plugin_de.properties
+++ b/plugins/schemaeditor/plugin_de.properties
@@ -77,8 +77,8 @@
 Cmd_RenameProject_name=Project umbenennen
 Cmd_RenameProject_description=Benennt ein Projekt um
 
-Cmd_DeleteProject_name=Projekt löschen
-Cmd_DeleteProject_description=Löscht das ausgewählte Projekt
+Cmd_DeleteProject_name=Projekt l\u00F6schen
+Cmd_DeleteProject_description=L\u00F6scht das ausgew\u00E4hlte Projekt
 
 Cmd_NewSchema_name=Neues Schema
 Cmd_NewSchema_description=Erstellt ein neues Schema
@@ -99,7 +99,7 @@
 Cmd_DeleteSchemaElement_description=L\u00F6scht das ausgew\u00E4hlte Schema Element
 
 Cmd_RenameProject_name=Schema Element umbenennen
-Cmd_RenameProject_description=Benennt das ausgewählte Schema-Element um
+Cmd_RenameProject_description=Benennt das ausgew\u00E4hlte Schema-Element um
 
 SchemaConnector_ApacheDS_name=ApacheDS Schema Konnektor
 SchemaConnector_ApacheDS_description=Der ApacheDS Schema Konnektor ist kompatibel mit ApacheDS (Version 1.5 oder h\u00F6her)
diff --git a/plugins/schemaeditor/pom-first.xml b/plugins/schemaeditor/pom-first.xml
index d32627b..c4170c3 100644
--- a/plugins/schemaeditor/pom-first.xml
+++ b/plugins/schemaeditor/pom-first.xml
@@ -32,15 +32,6 @@
   <description/>
   <packaging>bundle</packaging>
 
-  <dependencies>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>${junit.version}</version>
-      <scope>test</scope>
-    </dependency>
-  </dependencies>
-
   <build>
      <!-- MANIFEST.MF Generation -->
     <plugins>
diff --git a/plugins/schemaeditor/src/main/java/org/apache/directory/studio/schemaeditor/view/widget/SchemaTextAttributeProvider.java b/plugins/schemaeditor/src/main/java/org/apache/directory/studio/schemaeditor/view/widget/SchemaTextAttributeProvider.java
index 171f896..eb9cd80 100644
--- a/plugins/schemaeditor/src/main/java/org/apache/directory/studio/schemaeditor/view/widget/SchemaTextAttributeProvider.java
+++ b/plugins/schemaeditor/src/main/java/org/apache/directory/studio/schemaeditor/view/widget/SchemaTextAttributeProvider.java
@@ -24,6 +24,7 @@
 import java.util.Map;
 
 import org.apache.directory.studio.common.ui.CommonUIConstants;
+import org.apache.directory.studio.common.ui.CommonUIPlugin;
 import org.eclipse.jface.text.TextAttribute;
 import org.eclipse.swt.SWT;
 
@@ -51,12 +52,13 @@
      */
     public SchemaTextAttributeProvider()
     {
-        attributes.put( DEFAULT_ATTRIBUTE, new TextAttribute( CommonUIConstants.BLACK_COLOR ) );
-        attributes.put( KEYWORD_ATTRIBUTE, new TextAttribute( CommonUIConstants.M_PURPLE_COLOR, null, SWT.BOLD ) );
-        attributes.put( STRING_ATTRIBUTE, new TextAttribute( CommonUIConstants.BLUE_COLOR ) );
-        attributes.put( ATTRIBUTETYPE_ATTRIBUTE, new TextAttribute( CommonUIConstants.R95_G63_B159_COLOR, null, SWT.BOLD ) );
-        attributes.put( OBJECTCLASS_ATTRIBUTE, new TextAttribute( CommonUIConstants.R63_G127_B63_COLOR, null, SWT.BOLD ) );
-        attributes.put( OID_ATTRIBUTE, new TextAttribute( CommonUIConstants.RED_COLOR ) );
+        CommonUIPlugin plugin = CommonUIPlugin.getDefault();
+        attributes.put( DEFAULT_ATTRIBUTE, new TextAttribute( plugin.getColor( CommonUIConstants.DEFAULT_COLOR ) ) );
+        attributes.put( KEYWORD_ATTRIBUTE, new TextAttribute( plugin.getColor( CommonUIConstants.KEYWORD_2_COLOR ), null, SWT.BOLD ) );
+        attributes.put( STRING_ATTRIBUTE, new TextAttribute( plugin.getColor( CommonUIConstants.VALUE_COLOR ) ) );
+        attributes.put( ATTRIBUTETYPE_ATTRIBUTE, new TextAttribute( plugin.getColor( CommonUIConstants.ATTRIBUTE_TYPE_COLOR ), null, SWT.BOLD ) );
+        attributes.put( OBJECTCLASS_ATTRIBUTE, new TextAttribute( plugin.getColor( CommonUIConstants.OBJECT_CLASS_COLOR ), null, SWT.BOLD ) );
+        attributes.put( OID_ATTRIBUTE, new TextAttribute( plugin.getColor( CommonUIConstants.OID_COLOR ) ) );
     }
 
 
diff --git a/plugins/schemaeditor/src/test/java/org/apache/directory/studio/schemaeditor/model/alias/AliasesStringParserTest.java b/plugins/schemaeditor/src/test/java/org/apache/directory/studio/schemaeditor/model/alias/AliasesStringParserTest.java
index f79cc93..69066fa 100644
--- a/plugins/schemaeditor/src/test/java/org/apache/directory/studio/schemaeditor/model/alias/AliasesStringParserTest.java
+++ b/plugins/schemaeditor/src/test/java/org/apache/directory/studio/schemaeditor/model/alias/AliasesStringParserTest.java
@@ -20,9 +20,11 @@
 package org.apache.directory.studio.schemaeditor.model.alias;
 
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
 import java.util.List;
 
-import junit.framework.TestCase;
+import org.junit.jupiter.api.Test;
 
 
 /**
@@ -30,8 +32,9 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class AliasesStringParserTest extends TestCase
+public class AliasesStringParserTest
 {
+    @Test
     public void testNoAlias() throws Exception
     {
         AliasesStringParser parser = new AliasesStringParser();
@@ -42,6 +45,7 @@
     }
 
 
+    @Test
     public void testOneAlias() throws Exception
     {
         AliasesStringParser parser = new AliasesStringParser();
@@ -53,6 +57,7 @@
     }
 
 
+    @Test
     public void testTwoAliases() throws Exception
     {
         AliasesStringParser parser = new AliasesStringParser();
@@ -65,6 +70,7 @@
     }
 
 
+    @Test
     public void testThreeAliases() throws Exception
     {
         AliasesStringParser parser = new AliasesStringParser();
@@ -78,6 +84,7 @@
     }
 
 
+    @Test
     public void testMultipleCommasNoAlias() throws Exception
     {
         AliasesStringParser parser = new AliasesStringParser();
@@ -88,6 +95,7 @@
     }
 
 
+    @Test
     public void testMultipleCommasAndWhiteSpacesNoAlias() throws Exception
     {
         AliasesStringParser parser = new AliasesStringParser();
@@ -98,6 +106,7 @@
     }
 
 
+    @Test
     public void testTwoAliasesMultipleCommas() throws Exception
     {
         AliasesStringParser parser = new AliasesStringParser();
@@ -110,6 +119,7 @@
     }
 
 
+    @Test
     public void testOneAliasWithStartError() throws Exception
     {
         AliasesStringParser parser = new AliasesStringParser();
@@ -122,6 +132,7 @@
     }
 
 
+    @Test
     public void testOneAliasWithStartError2() throws Exception
     {
         AliasesStringParser parser = new AliasesStringParser();
@@ -134,6 +145,7 @@
     }
 
 
+    @Test
     public void testOneAliasWithPartError() throws Exception
     {
         AliasesStringParser parser = new AliasesStringParser();
@@ -146,6 +158,7 @@
     }
 
 
+    @Test
     public void testOneAliasWithPartError2() throws Exception
     {
         AliasesStringParser parser = new AliasesStringParser();
@@ -158,6 +171,7 @@
     }
 
 
+    @Test
     public void testOneAliasWithPartErrorAndOneAliasWithStartError() throws Exception
     {
         AliasesStringParser parser = new AliasesStringParser();
@@ -172,6 +186,7 @@
     }
 
 
+    @Test
     public void testOneAliasWithPartErrorAndOneAliasWithStartError2() throws Exception
     {
         AliasesStringParser parser = new AliasesStringParser();
diff --git a/plugins/schemaeditor/src/test/java/org/apache/directory/studio/schemaeditor/model/difference/DifferenceEngineTest.java b/plugins/schemaeditor/src/test/java/org/apache/directory/studio/schemaeditor/model/difference/DifferenceEngineTest.java
index 1988468..d4365c1 100644
--- a/plugins/schemaeditor/src/test/java/org/apache/directory/studio/schemaeditor/model/difference/DifferenceEngineTest.java
+++ b/plugins/schemaeditor/src/test/java/org/apache/directory/studio/schemaeditor/model/difference/DifferenceEngineTest.java
@@ -20,29 +20,34 @@
 package org.apache.directory.studio.schemaeditor.model.difference;
 
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.fail;
+
 import java.util.Arrays;
 import java.util.List;
 
-import junit.framework.TestCase;
-
 import org.apache.directory.api.ldap.model.schema.AttributeType;
 import org.apache.directory.api.ldap.model.schema.ObjectClass;
 import org.apache.directory.api.ldap.model.schema.ObjectClassTypeEnum;
 import org.apache.directory.api.ldap.model.schema.UsageEnum;
 
+import org.junit.jupiter.api.Test;
+
 
 /**
  * This class tests the DifferenceEngine class.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class DifferenceEngineTest extends TestCase
+public class DifferenceEngineTest
 {
     /**
      * Tests the AddAliasDifference.
      *
      * @throws Exception
      */
+    @Test
     public void testAddAliasDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -70,6 +75,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testAddDescriptionDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -97,6 +103,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testAddEqualityDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -123,6 +130,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testAddMandatoryATDifference() throws Exception
     {
         ObjectClass o1 = new ObjectClass( "1.2.3.4" ); //$NON-NLS-1$
@@ -151,6 +159,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testAddOptionalATDifference() throws Exception
     {
         ObjectClass o1 = new ObjectClass( "1.2.3.4" ); //$NON-NLS-1$
@@ -164,7 +173,8 @@
 
         Difference difference = differences.get( 0 );
 
-        if ( !( difference instanceof OptionalATDifference ) || ( !difference.getType().equals( DifferenceType.ADDED ) ) )
+        if ( !( difference instanceof OptionalATDifference )
+            || ( !difference.getType().equals( DifferenceType.ADDED ) ) )
         {
             fail();
         }
@@ -178,6 +188,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testAddOrderingDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -204,6 +215,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testAddSubstringDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -216,7 +228,8 @@
 
         Difference difference = differences.get( 0 );
 
-        if ( !( difference instanceof SubstringDifference ) || ( !difference.getType().equals( DifferenceType.ADDED ) ) )
+        if ( !( difference instanceof SubstringDifference )
+            || ( !difference.getType().equals( DifferenceType.ADDED ) ) )
         {
             fail();
         }
@@ -230,6 +243,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testAddSuperiorATDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -242,7 +256,8 @@
 
         Difference difference = differences.get( 0 );
 
-        if ( !( difference instanceof SuperiorATDifference ) || ( !difference.getType().equals( DifferenceType.ADDED ) ) )
+        if ( !( difference instanceof SuperiorATDifference )
+            || ( !difference.getType().equals( DifferenceType.ADDED ) ) )
         {
             fail();
         }
@@ -256,6 +271,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testAddSuperiorOCDifference() throws Exception
     {
         ObjectClass o1 = new ObjectClass( "1.2.3.4" ); //$NON-NLS-1$
@@ -269,7 +285,8 @@
 
         Difference difference = differences.get( 0 );
 
-        if ( !( difference instanceof SuperiorOCDifference ) || ( !difference.getType().equals( DifferenceType.ADDED ) ) )
+        if ( !( difference instanceof SuperiorOCDifference )
+            || ( !difference.getType().equals( DifferenceType.ADDED ) ) )
         {
             fail();
         }
@@ -283,6 +300,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testAddSyntaxDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -309,6 +327,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testAddSyntaxLengthDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -336,6 +355,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testModifyClassTypeDifference() throws Exception
     {
         ObjectClass o1 = new ObjectClass( "1.2.3.4" ); //$NON-NLS-1$
@@ -365,6 +385,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testModifyCollectiveDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -394,6 +415,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testModifyDescriptionDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -423,6 +445,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testModifyEqualityDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -452,6 +475,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testModifyNoUserModificationDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -481,6 +505,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testModifyObsoleteDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -510,6 +535,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testModifyOrderingDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -539,6 +565,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testModifySingleValueDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -568,6 +595,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testModifySubstringDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -597,6 +625,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testModifySuperiorATDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -626,6 +655,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testModifySyntaxDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -639,7 +669,8 @@
 
         Difference difference = differences.get( 0 );
 
-        if ( !( difference instanceof SyntaxDifference ) || ( !difference.getType().equals( DifferenceType.MODIFIED ) ) )
+        if ( !( difference instanceof SyntaxDifference )
+            || ( !difference.getType().equals( DifferenceType.MODIFIED ) ) )
         {
             fail();
         }
@@ -654,6 +685,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testModifySyntaxLengthDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -683,6 +715,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testModifyUsageDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -711,6 +744,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testRemoveAliasDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -741,6 +775,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testRemoveDescriptionDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -769,6 +804,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testRemoveEqualityDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -781,7 +817,8 @@
 
         Difference difference = differences.get( 0 );
 
-        if ( !( difference instanceof EqualityDifference ) || ( !difference.getType().equals( DifferenceType.REMOVED ) ) )
+        if ( !( difference instanceof EqualityDifference )
+            || ( !difference.getType().equals( DifferenceType.REMOVED ) ) )
         {
             fail();
         }
@@ -796,6 +833,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testRemoveMandatoryATDifference() throws Exception
     {
         ObjectClass o1 = new ObjectClass( "1.2.3.4" ); //$NON-NLS-1$
@@ -827,6 +865,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testRemoveOptionalATDifference() throws Exception
     {
         ObjectClass o1 = new ObjectClass( "1.2.3.4" ); //$NON-NLS-1$
@@ -858,6 +897,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testRemoveOrderingDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -870,7 +910,8 @@
 
         Difference difference = differences.get( 0 );
 
-        if ( !( difference instanceof OrderingDifference ) || ( !difference.getType().equals( DifferenceType.REMOVED ) ) )
+        if ( !( difference instanceof OrderingDifference )
+            || ( !difference.getType().equals( DifferenceType.REMOVED ) ) )
         {
             fail();
         }
@@ -885,6 +926,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testRemoveSubstringDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -913,6 +955,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testRemoveSuperiorATDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -941,6 +984,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testRemoveSuperiorOCDifference() throws Exception
     {
         ObjectClass o1 = new ObjectClass( "1.2.3.4" ); //$NON-NLS-1$
@@ -972,6 +1016,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testRemoveSyntaxDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
@@ -999,6 +1044,7 @@
      *
      * @throws Exception
      */
+    @Test
     public void testRemoveSyntaxLengthDifference() throws Exception
     {
         AttributeType o1 = new AttributeType( "1.2.3.4" ); //$NON-NLS-1$
diff --git a/plugins/schemaeditor/src/test/java/org/apache/directory/studio/schemaeditor/model/io/OpenLdapSchemaFileExporterTest.java b/plugins/schemaeditor/src/test/java/org/apache/directory/studio/schemaeditor/model/io/OpenLdapSchemaFileExporterTest.java
index 8495a0b..bd8cc1f 100644
--- a/plugins/schemaeditor/src/test/java/org/apache/directory/studio/schemaeditor/model/io/OpenLdapSchemaFileExporterTest.java
+++ b/plugins/schemaeditor/src/test/java/org/apache/directory/studio/schemaeditor/model/io/OpenLdapSchemaFileExporterTest.java
@@ -20,7 +20,7 @@
 package org.apache.directory.studio.schemaeditor.model.io;
 
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import java.util.Arrays;
 import java.util.Collections;
@@ -29,9 +29,8 @@
 import org.apache.directory.api.ldap.model.schema.ObjectClass;
 import org.apache.directory.api.ldap.model.schema.ObjectClassTypeEnum;
 import org.apache.directory.api.ldap.model.schema.UsageEnum;
-import org.junit.Before;
-import org.junit.Test;
-
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 /**
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
@@ -45,7 +44,7 @@
     private AttributeType attributeTypeSimple;
     private AttributeType attributeTypeComplex;
 
-    @Before
+    @BeforeEach
     public void setUp()
     {
         objectClassSimple = new ObjectClass( "1.2.3.4" );
diff --git a/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/view/preferences/TemplatesLabelProvider.java b/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/view/preferences/TemplatesLabelProvider.java
index f3bea07..0456cd3 100644
--- a/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/view/preferences/TemplatesLabelProvider.java
+++ b/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/view/preferences/TemplatesLabelProvider.java
@@ -32,7 +32,6 @@
 import org.eclipse.swt.graphics.Color;
 import org.eclipse.swt.graphics.Font;
 import org.eclipse.swt.graphics.Image;
-import org.apache.directory.studio.common.ui.CommonUIConstants;
 import org.apache.directory.studio.templateeditor.EntryTemplatePlugin;
 import org.apache.directory.studio.templateeditor.EntryTemplatePluginConstants;
 import org.apache.directory.studio.templateeditor.EntryTemplatePluginUtils;
@@ -48,9 +47,6 @@
  */
 public class TemplatesLabelProvider extends ColumnsLabelProvider implements ITableFontProvider, ITableColorProvider
 {
-    /** The Grey color constant */
-    private static final Color GREY_COLOR = CommonUIConstants.ML_GREY_COLOR;
-
     /** The templates manager */
     private PreferencesTemplatesManager manager;
 
@@ -315,7 +311,8 @@
         {
             if ( !manager.isEnabled( ( Template ) element ) )
             {
-                return GREY_COLOR;
+                // TODO: get disabled color
+                return null;
             }
         }
 
diff --git a/plugins/templateeditor/src/test/java/org/apache/directory/studio/templateeditor/model/parser/TemplateIOTest.java b/plugins/templateeditor/src/test/java/org/apache/directory/studio/templateeditor/model/parser/TemplateIOTest.java
index fd284ce..04f1e04 100644
--- a/plugins/templateeditor/src/test/java/org/apache/directory/studio/templateeditor/model/parser/TemplateIOTest.java
+++ b/plugins/templateeditor/src/test/java/org/apache/directory/studio/templateeditor/model/parser/TemplateIOTest.java
@@ -20,7 +20,14 @@
 package org.apache.directory.studio.templateeditor.model.parser;
 
 
-import junit.framework.TestCase;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import org.junit.jupiter.api.Test;
 
 import org.apache.directory.studio.templateeditor.model.FileTemplate;
 import org.apache.directory.studio.templateeditor.model.parser.TemplateIO;
@@ -47,11 +54,12 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class TemplateIOTest extends TestCase
+public class TemplateIOTest
 {
     /**
      * Tests the parser with a minimal template file.
      */
+    @Test
     public void testReadTemplateMinimalTest()
     {
         FileTemplate template = null;
@@ -92,6 +100,7 @@
     /**
      * Tests the parser with a minimal template file.
      */
+    @Test
     public void testReadTemplateMinimalWithCompositeTest()
     {
         FileTemplate template = null;
@@ -135,6 +144,7 @@
      * Tests the parser with a template file containing a section with a 
      * 'columns' attribute.
      */
+    @Test
     public void testReadTemplateSectionColumnsAttributeTest()
     {
         FileTemplate template = null;
@@ -167,6 +177,7 @@
      * Tests the parser with a template file containing a section with a 
      * 'columns' attribute.
      */
+    @Test
     public void testReadTemplateSectionDescriptionAttributeTest()
     {
         FileTemplate template = null;
@@ -199,6 +210,7 @@
      * Tests the parser with a template file containing a section with a 
      * 'columns' attribute.
      */
+    @Test
     public void testReadTemplateSectionTitleAttributeTest()
     {
         FileTemplate template = null;
@@ -231,6 +243,7 @@
      * Tests the parser with a template file containing a section with a wrong
      * 'columns' attribute.
      */
+    @Test
     public void testReadTemplateSectionWrongColumnsAttributeTest() throws Exception
     {
         testParsingFail( "template_section_with_wrong_columns_attribute.xml" ); //$NON-NLS-1$
@@ -241,6 +254,7 @@
      * Tests the parser with a template file containing a checkbox with a 
      * value for the 'attributeType' attribute.
      */
+    @Test
     public void testReadTemplateCheckboxAttributetypeValueTest()
     {
         FileTemplate template = null;
@@ -282,6 +296,7 @@
      * Tests the parser with a template file containing a checkbox with a 
      * value for the 'checkedValue' attribute.
      */
+    @Test
     public void testReadTemplateCheckboxCheckedValueTest()
     {
         FileTemplate template = null;
@@ -323,6 +338,7 @@
      * Tests the parser with a template file containing a checkbox with a 
      * value for the 'uncheckedValue' attribute.
      */
+    @Test
     public void testReadTemplateCheckboxUncheckedValueTest()
     {
         FileTemplate template = null;
@@ -364,6 +380,7 @@
      * Tests the parser with a template file containing a checkbox with a 
      * value for the 'uncheckedValue' attribute.
      */
+    @Test
     public void testReadTemplateCheckboxCheckedAndUnheckedValuesTest()
     {
         FileTemplate template = null;
@@ -405,6 +422,7 @@
      * Tests the parser with a template file containing a file chooser with 
      * only value for the 'attributeType' attribute.
      */
+    @Test
     public void testReadTemplateFileChooserAttributeTypeValueTest()
     {
         FileTemplate template = null;
@@ -448,6 +466,7 @@
      * Tests the parser with a template file containing a file chooser with all 
      * values.
      */
+    @Test
     public void testReadTemplateFileChooserAllValuesTest()
     {
         FileTemplate template = null;
@@ -491,6 +510,7 @@
      * Tests the parser with a template file containing an image with only the
      * value for the 'attributeType' attribute.
      */
+    @Test
     public void testReadTemplateImageAttributeTypeValueTest()
     {
         FileTemplate template = null;
@@ -535,6 +555,7 @@
      * Tests the parser with a template file containing an image with all
      * values.
      */
+    @Test
     public void testReadTemplateImageAllValuesTest()
     {
         FileTemplate template = null;
@@ -579,6 +600,7 @@
      * Tests the parser with a template file containing a label with only the
      * value for the 'attributeType' attribute.
      */
+    @Test
     public void testReadTemplateLabelAttributeTypeValueTest()
     {
         FileTemplate template = null;
@@ -618,6 +640,7 @@
      * Tests the parser with a template file containing a label with a value
      * for the 'value' attribute.
      */
+    @Test
     public void testReadTemplateLabelValueValueTest()
     {
         FileTemplate template = null;
@@ -657,6 +680,7 @@
      * Tests the parser with a template file containing a link with only the
      * value for the 'attributeType' attribute.
      */
+    @Test
     public void testReadTemplateLinkAttributeTypeValueTest()
     {
         FileTemplate template = null;
@@ -696,6 +720,7 @@
      * Tests the parser with a template file containing a link with a value
      * for the 'value' attribute.
      */
+    @Test
     public void testReadTemplateLinkValueValueTest()
     {
         FileTemplate template = null;
@@ -735,6 +760,7 @@
      * Tests the parser with a template file containing a listbox with the 
      * minimal set of elements and attributes.
      */
+    @Test
     public void testReadTemplateListboxMinimalTest()
     {
         FileTemplate template = null;
@@ -777,6 +803,7 @@
      * Tests the parser with a template file containing a listbox with the 
      * minimal set of elements and attributes.
      */
+    @Test
     public void testReadTemplateListboxSingleSelectionTest()
     {
         FileTemplate template = null;
@@ -819,6 +846,7 @@
      * Tests the parser with a template file containing a listbox with 
      * multiple items.
      */
+    @Test
     public void testReadTemplateListboxMultipleItemsTest()
     {
         FileTemplate template = null;
@@ -863,6 +891,7 @@
      * Tests the parser with a template file containing a password with the 
      * minimal set of elements and attributes.
      */
+    @Test
     public void testReadTemplatePasswordMinimalTest()
     {
         FileTemplate template = null;
@@ -903,6 +932,7 @@
      * Tests the parser with a template file containing a password with the 
      * minimal set of elements and attributes.
      */
+    @Test
     public void testReadTemplatePasswordNotHiddenTest()
     {
         FileTemplate template = null;
@@ -943,6 +973,7 @@
      * Tests the parser with a template file containing a password with the 
      * minimal set of elements and attributes.
      */
+    @Test
     public void testReadTemplatePasswordNotShowChangeButtonTest()
     {
         FileTemplate template = null;
@@ -983,6 +1014,7 @@
      * Tests the parser with a template file containing a radio buttons with 
      * the minimal set of elements and attributes.
      */
+    @Test
     public void testReadTemplateRadioButtonsMinimalTest()
     {
         FileTemplate template = null;
@@ -1024,6 +1056,7 @@
      * Tests the parser with a template file containing a radio buttons with 
      * multiple buttons.
      */
+    @Test
     public void testReadTemplateRadioButtonsMultipleButtonsTest()
     {
         FileTemplate template = null;
@@ -1067,6 +1100,7 @@
      * Tests the parser with a template file containing a spinner with the 
      * minimal set of elements and attributes.
      */
+    @Test
     public void testReadTemplateSpinnerMinimalTest()
     {
         FileTemplate template = null;
@@ -1110,6 +1144,7 @@
      * Tests the parser with a template file containing a spinner with all the
      * values for its attributes.
      */
+    @Test
     public void testReadTemplateSpinnerAllValuesTest()
     {
         FileTemplate template = null;
@@ -1152,6 +1187,7 @@
     /**
      * Tests the parser with a template file containing a table.
      */
+    @Test
     public void testReadTemplateTableTest()
     {
         FileTemplate template = null;
@@ -1189,6 +1225,7 @@
      * Tests the parser with a template file containing a text field with the
      * minimal set of elements and attributes.
      */
+    @Test
     public void testReadTemplateTextFieldMinimalTest()
     {
         FileTemplate template = null;
@@ -1229,6 +1266,7 @@
      * Tests the parser with a template file containing a text field with the
      * minimal set of elements and attributes.
      */
+    @Test
     public void testReadTemplateTextFieldAllValuesTest()
     {
         FileTemplate template = null;
@@ -1268,6 +1306,7 @@
     /**
      * Tests the parser with a template containing a wrong root element.
      */
+    @Test
     public void testReadTemplateWrongRootElementTest() throws Exception
     {
         testParsingFail( "template_wrong_root_element.xml" ); //$NON-NLS-1$
@@ -1277,6 +1316,7 @@
     /**
      * Tests the parser with a template containing no 'id' attribute.
      */
+    @Test
     public void testReadTemplateNoIdAttributeTest() throws Exception
     {
         testParsingFail( "template_no_id_attribute.xml" ); //$NON-NLS-1$
@@ -1286,6 +1326,7 @@
     /**
      * Tests the parser with a template containing no 'title' attribute.
      */
+    @Test
     public void testReadTemplateNoTitleAttributeTest() throws Exception
     {
         testParsingFail( "template_no_title_attribute.xml" ); //$NON-NLS-1$
@@ -1295,6 +1336,7 @@
     /**
      * Tests the parser with a template containing no 'objectClasses' element.
      */
+    @Test
     public void testReadTemplateNoObjectClassesElementTest() throws Exception
     {
         testParsingFail( "template_no_objectClasses_element.xml" ); //$NON-NLS-1$
@@ -1304,6 +1346,7 @@
     /**
      * Tests the parser with a template containing no 'structural' element.
      */
+    @Test
     public void testReadTemplateNoObjectClassElementTest() throws Exception
     {
         testParsingFail( "template_no_structural_element.xml" ); //$NON-NLS-1$
@@ -1313,6 +1356,7 @@
     /**
      * Tests the parser with a template containing no 'form' element.
      */
+    @Test
     public void testReadTemplateNoFormElementTest() throws Exception
     {
         testParsingFail( "template_no_form_element.xml" ); //$NON-NLS-1$
@@ -1322,6 +1366,7 @@
     /**
      * Tests the parser with a template containing no 'section' element.
      */
+    @Test
     public void testReadTemplateNoSectionElementTest() throws Exception
     {
         testParsingFail( "template_no_section_element.xml" ); //$NON-NLS-1$
@@ -1344,7 +1389,7 @@
         }
         catch ( TemplateIOException e )
         {
-            assertTrue( e.getMessage(), true );
+            assertTrue( true, e.getMessage() );
             return;
         }
         fail();
@@ -1355,6 +1400,7 @@
      * Tests the parser with a template file containing a section with a 
      * 'columns' attribute.
      */
+    @Test
     public void testReadTemplateCompositeColumnsAttributeTest()
     {
         FileTemplate template = null;
diff --git a/plugins/valueeditors/src/main/java/org/apache/directory/studio/valueeditors/certificate/CertificateDialog.java b/plugins/valueeditors/src/main/java/org/apache/directory/studio/valueeditors/certificate/CertificateDialog.java
index 99c501d..c139d8a 100644
--- a/plugins/valueeditors/src/main/java/org/apache/directory/studio/valueeditors/certificate/CertificateDialog.java
+++ b/plugins/valueeditors/src/main/java/org/apache/directory/studio/valueeditors/certificate/CertificateDialog.java
@@ -41,11 +41,15 @@
 import org.eclipse.jface.dialogs.IDialogConstants;
 import org.eclipse.osgi.util.NLS;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
 import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.FileDialog;
 import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
 
 
 /**
@@ -57,6 +61,8 @@
 public class CertificateDialog extends Dialog
 {
 
+    public static final String LOAD_FILE_NAME_TOOLTIP = "LoadFileName";
+
     /** The default title. */
     private static final String DIALOG_TITLE = Messages.getString( "CertificateDialog.CertificateDialog" ); //$NON-NLS-1$
 
@@ -66,6 +72,9 @@
     /** The button ID for the save button. */
     private static final int SAVE_BUTTON_ID = 9999;
 
+    /** Hidden text to set the filename, used for UI tests. */
+    private Text loadFilenameText;
+
     /** The current certificate binary data. */
     private byte[] currentData;
 
@@ -130,18 +139,7 @@
             String returnedFileName = fileDialog.open();
             if ( returnedFileName != null )
             {
-                try
-                {
-                    File file = new File( returnedFileName );
-                    currentData = FileUtils.readFileToByteArray( file );
-                    updateInput();
-                }
-                catch ( IOException e )
-                {
-                    ConnectionUIPlugin.getDefault().getExceptionHandler().handleException(
-                        new Status( IStatus.ERROR, ValueEditorsConstants.PLUGIN_ID, IStatus.ERROR, Messages
-                            .getString( "CertificateDialog.CantReadFile" ), e ) ); //$NON-NLS-1$
-                }
+                loadFile( returnedFileName );
             }
         }
         else
@@ -153,6 +151,23 @@
     }
 
 
+    private void loadFile( String fileName )
+    {
+        try
+        {
+            File file = new File( fileName );
+            currentData = FileUtils.readFileToByteArray( file );
+            updateInput();
+        }
+        catch ( IOException e )
+        {
+            ConnectionUIPlugin.getDefault().getExceptionHandler().handleException(
+                new Status( IStatus.ERROR, ValueEditorsConstants.PLUGIN_ID, IStatus.ERROR, Messages
+                    .getString( "CertificateDialog.CantReadFile" ), e ) ); //$NON-NLS-1$
+        }
+    }
+
+
     /**
      * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
      */
@@ -169,6 +184,18 @@
      */
     protected void createButtonsForButtonBar( Composite parent )
     {
+        ((GridLayout) parent.getLayout()).numColumns++;
+        loadFilenameText = new Text( parent, SWT.NONE );
+        loadFilenameText.setToolTipText( LOAD_FILE_NAME_TOOLTIP );
+        loadFilenameText.setBackground( parent.getBackground() );
+        loadFilenameText.addModifyListener( new ModifyListener()
+        {
+            public void modifyText( ModifyEvent e )
+            {
+                loadFile( loadFilenameText.getText() );
+            }
+        } );
+
         createButton( parent, LOAD_BUTTON_ID, Messages.getString( "CertificateDialog.LoadCertificateButton" ), false ); //$NON-NLS-1$
         createButton( parent, SAVE_BUTTON_ID, Messages.getString( "CertificateDialog.SaveCertificateButton" ), false ); //$NON-NLS-1$
         createButton( parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, false );
diff --git a/plugins/valueeditors/src/main/java/org/apache/directory/studio/valueeditors/oid/InPlaceOidValueEditor.java b/plugins/valueeditors/src/main/java/org/apache/directory/studio/valueeditors/oid/InPlaceOidValueEditor.java
index 733127b..0a15acd 100644
--- a/plugins/valueeditors/src/main/java/org/apache/directory/studio/valueeditors/oid/InPlaceOidValueEditor.java
+++ b/plugins/valueeditors/src/main/java/org/apache/directory/studio/valueeditors/oid/InPlaceOidValueEditor.java
@@ -64,7 +64,9 @@
     {
         Object rawValue = super.getRawValue( value );
 
-        if ( rawValue instanceof String && OidSyntaxChecker.INSTANCE.isValidSyntax( rawValue ) )
+        // DIRSTUDIO-1216: allows relaxed OID syntax with underscore, e.g. for Oracle or DirX
+        if ( rawValue instanceof String
+            && OidSyntaxChecker.INSTANCE.isValidSyntax( ( ( String ) rawValue ).replace( "_", "-" ) ) )
         {
             return rawValue;
         }
diff --git a/plugins/valueeditors/src/test/java/org/apache/directory/studio/valueeditors/msad/InPlaceMsAdObjectGuidValueEditorTest.java b/plugins/valueeditors/src/test/java/org/apache/directory/studio/valueeditors/msad/InPlaceMsAdObjectGuidValueEditorTest.java
index 7bd20c7..d6764a9 100644
--- a/plugins/valueeditors/src/test/java/org/apache/directory/studio/valueeditors/msad/InPlaceMsAdObjectGuidValueEditorTest.java
+++ b/plugins/valueeditors/src/test/java/org/apache/directory/studio/valueeditors/msad/InPlaceMsAdObjectGuidValueEditorTest.java
@@ -21,10 +21,11 @@
 package org.apache.directory.studio.valueeditors.msad;
 
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import org.apache.directory.api.util.Strings;
-import org.junit.Test;
+
+import org.junit.jupiter.api.Test;
 
 
 public class InPlaceMsAdObjectGuidValueEditorTest
diff --git a/plugins/valueeditors/src/test/java/org/apache/directory/studio/valueeditors/msad/InPlaceMsAdObjectSidValueEditorTest.java b/plugins/valueeditors/src/test/java/org/apache/directory/studio/valueeditors/msad/InPlaceMsAdObjectSidValueEditorTest.java
index 78f4f81..e86c5dd 100644
--- a/plugins/valueeditors/src/test/java/org/apache/directory/studio/valueeditors/msad/InPlaceMsAdObjectSidValueEditorTest.java
+++ b/plugins/valueeditors/src/test/java/org/apache/directory/studio/valueeditors/msad/InPlaceMsAdObjectSidValueEditorTest.java
@@ -21,9 +21,9 @@
 package org.apache.directory.studio.valueeditors.msad;
 
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 
 public class InPlaceMsAdObjectSidValueEditorTest
@@ -48,7 +48,7 @@
                 ( byte ) 0x00,
                 ( byte ) 0x00,
                 ( byte ) 0x00 //
-        };
+            };
         String displayValue = editor.convertToString( bytes );
         assertEquals( "S-1-5-4", displayValue ); //$NON-NLS-1$
     }
@@ -77,7 +77,7 @@
                 ( byte ) 0x02,
                 ( byte ) 0x00,
                 ( byte ) 0x00 //
-        };
+            };
         String displayValue = editor.convertToString( bytes );
         assertEquals( "S-1-5-32-549", displayValue ); //$NON-NLS-1$
     }
@@ -119,7 +119,7 @@
                 ( byte ) 0x01,
                 ( byte ) 0x00,
                 ( byte ) 0x00 //
-        };
+            };
         String displayValue = editor.convertToString( bytes );
         assertEquals( "S-1-5-21-666267311-2692216076-1860112551-500", displayValue ); //$NON-NLS-1$
     }
@@ -206,7 +206,7 @@
                 ( byte ) 0x00,
                 ( byte ) 0x00,
                 ( byte ) 0x00 //
-        };
+            };
         String displayValue3 = editor.convertToString( bytes3 );
         assertEquals( Messages.getString( "InPlaceMsAdObjectSidValueEditor.InvalidSid" ), displayValue3 ); //$NON-NLS-1$
     }
diff --git a/plugins/valueeditors/src/test/java/org/apache/directory/studio/valueeditors/uuid/InPlaceUuidValueEditorTest.java b/plugins/valueeditors/src/test/java/org/apache/directory/studio/valueeditors/uuid/InPlaceUuidValueEditorTest.java
index a31ac1d..a5ac129 100644
--- a/plugins/valueeditors/src/test/java/org/apache/directory/studio/valueeditors/uuid/InPlaceUuidValueEditorTest.java
+++ b/plugins/valueeditors/src/test/java/org/apache/directory/studio/valueeditors/uuid/InPlaceUuidValueEditorTest.java
@@ -21,10 +21,11 @@
 package org.apache.directory.studio.valueeditors.uuid;
 
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import org.apache.directory.api.util.Strings;
-import org.junit.Test;
+
+import org.junit.jupiter.api.Test;
 
 
 public class InPlaceUuidValueEditorTest
@@ -99,9 +100,26 @@
 
         // test too long
         byte[] bytes2 = new byte[]
-            { ( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00,
-                ( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00,
-                ( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00,
+            {
+                ( byte ) 0x00,
+                ( byte ) 0x00,
+                ( byte ) 0x00,
+                ( byte ) 0x00,
+                ( byte ) 0x00,
+                ( byte ) 0x00,
+                ( byte ) 0x00,
+                ( byte ) 0x00,
+                ( byte ) 0x00,
+                ( byte ) 0x00,
+                ( byte ) 0x00,
+                ( byte ) 0x00,
+                ( byte ) 0x00,
+                ( byte ) 0x00,
+                ( byte ) 0x00,
+                ( byte ) 0x00,
+                ( byte ) 0x00,
+                ( byte ) 0x00,
+                ( byte ) 0x00,
                 ( byte ) 0x00, };
         String displayValue2 = editor.convertToString( bytes2 );
         assertEquals( Messages.getString( "InPlaceUuidValueEditor.InvalidUuid" ), displayValue2 ); //$NON-NLS-1$
diff --git a/pom.xml b/pom.xml
index cfa3722..6f5fd4e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,7 +23,7 @@
   <parent>
     <groupId>org.apache.directory.project</groupId>
     <artifactId>project</artifactId>
-    <version>42</version>
+    <version>45</version>
     <relativePath />
   </parent>
 
@@ -69,12 +69,13 @@
     <maven.compiler.source>1.8</maven.compiler.source>
     <maven.compiler.target>1.8</maven.compiler.target>
 
-    <tycho.version>1.6.0</tycho.version>
+    <tycho.version>2.3.0</tycho.version>
 
     <!-- Set versions for dependencies -->
     <antlr.version>2.7.7</antlr.version>
     <antlr.bundleversion>2.7.7</antlr.bundleversion>
-    <junit.version>4.11</junit.version>
+    <junit.platform.version>1.7.1</junit.platform.version>
+    <junit.jupiter.version>5.7.1</junit.jupiter.version>
     <log4j.log4j.version>1.2.17</log4j.log4j.version>
     <log4j.log4j.bundleversion>1.2.17</log4j.log4j.bundleversion>
     <com.github.ben-manes.caffeine.version>2.7.0</com.github.ben-manes.caffeine.version>
@@ -83,24 +84,25 @@
     <org.apache.httpcomponents.httpclient.bundleversion>4.5.12</org.apache.httpcomponents.httpclient.bundleversion>
     <org.apache.httpcomponents.httpcore.version>4.4.13</org.apache.httpcomponents.httpcore.version>
     <org.apache.httpcomponents.httpcore.bundleversion>4.4.13</org.apache.httpcomponents.httpcore.bundleversion>
-    <org.apache.commons.codec.version>1.14</org.apache.commons.codec.version>
-    <org.apache.commons.codec.bundleversion>1.14.0</org.apache.commons.codec.bundleversion>
+    <org.apache.commons.codec.version>1.15</org.apache.commons.codec.version>
+    <org.apache.commons.codec.bundleversion>1.15.0</org.apache.commons.codec.bundleversion>
     <org.apache.commons.collections4.version>4.4</org.apache.commons.collections4.version>
     <org.apache.commons.collections4.bundleversion>4.4.0</org.apache.commons.collections4.bundleversion>
     <org.apache.commons.io.version>2.6</org.apache.commons.io.version>
     <org.apache.commons.io.bundleversion>2.6.0</org.apache.commons.io.bundleversion>
-    <org.apache.commons.lang3.version>3.9</org.apache.commons.lang3.version>
-    <org.apache.commons.lang3.bundleversion>3.9</org.apache.commons.lang3.bundleversion>
-    <org.apache.commons.pool.version>2.8.0</org.apache.commons.pool.version>
-    <org.apache.commons.pool.bundleversion>2.8.0</org.apache.commons.pool.bundleversion>
-    <org.apache.directory.api.version>2.0.1</org.apache.directory.api.version>
-    <org.apache.directory.api.bundleversion>2.0.1</org.apache.directory.api.bundleversion>
+    <org.apache.commons.lang3.version>3.12.0</org.apache.commons.lang3.version>
+    <org.apache.commons.lang3.bundleversion>3.12.0</org.apache.commons.lang3.bundleversion>
+    <org.apache.commons.pool.version>2.9.0</org.apache.commons.pool.version>
+    <org.apache.commons.pool.bundleversion>2.9.0</org.apache.commons.pool.bundleversion>
+    <org.apache.directory.api.version>2.1.0</org.apache.directory.api.version>
+    <org.apache.directory.api.bundleversion>2.1.0</org.apache.directory.api.bundleversion>
     <org.apache.directory.server.version>2.0.0.AM26</org.apache.directory.server.version>
     <org.apache.mina.version>2.1.3</org.apache.mina.version>
     <org.apache.mina.bundleversion>2.1.3</org.apache.mina.bundleversion>
     <org.apache.poi.version>3.9</org.apache.poi.version>
     <org.apache.poi.bundleversion>3.9.0</org.apache.poi.bundleversion>
     <org.apache.xmlgraphics.fop.version>1.0</org.apache.xmlgraphics.fop.version>
+    <org.bouncycastle.version>1.62</org.bouncycastle.version>
     <org.slf4j.version>1.7.25</org.slf4j.version>
     <org.slf4j.bundleversion>1.7.25</org.slf4j.bundleversion>
     <org.xpp3.version>1.1.4.c</org.xpp3.version>
@@ -291,6 +293,8 @@
               <exclude>**/rfc*/rfc*.txt</exclude>
               <exclude>tools/**/*</exclude>
               <exclude>**/p2.index</exclude>
+              <!-- exclude GitHub files (codeql-analysis.yml) -->
+              <exclude>.github/**</exclude>
             </excludes>
           </configuration>
          </plugin>
diff --git a/product/NOTICE b/product/NOTICE
index d0d47b2..d2bed13 100644
--- a/product/NOTICE
+++ b/product/NOTICE
@@ -1,5 +1,5 @@
 Apache Directory Studio
-Copyright 2006-2020 The Apache Software Foundation
+Copyright 2006-2021 The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
diff --git a/product/org.apache.directory.studio.product b/product/org.apache.directory.studio.product
index 787a489..18bf10b 100644
--- a/product/org.apache.directory.studio.product
+++ b/product/org.apache.directory.studio.product
@@ -15,8 +15,23 @@
 
    <launcherArgs>
       <programArgs>/studio-rcp/resources/icons/linux/studio.xpm
+###
+#Uncomment_to_configure_the_language
+#https://directory.apache.org/studio/faqs.html#how-to-set-the-language-of-studio
+#-nl
+#en
+###
+#Uncomment_to_configure_Java_version_to_use
+#https://directory.apache.org/studio/faqs.html#how-to-set-the-java-vm-to-use
+#-vm
+#/usr/lib/jvm/java-11-openjdk/bin/java
       </programArgs>
-      <vmArgs>-Dosgi.requiredJavaVersion=1.8
+      <vmArgs>-Dosgi.requiredJavaVersion=11
+###
+#Uncomment_to_configure_heap_memory
+#https://directory.apache.org/studio/faqs.html#how-to-increase-the-heap-memory
+#-Xms1g
+#-Xmx2g
       </vmArgs>
       <vmArgsMac>-XstartOnFirstThread -Dorg.eclipse.swt.internal.carbon.smallFonts
       </vmArgsMac>
@@ -256,8 +271,8 @@
       <plugin id="org.eclipse.equinox.common" autoStart="true" startLevel="2" />
       <plugin id="org.eclipse.equinox.event" autoStart="true" startLevel="2" />
       <plugin id="org.eclipse.equinox.simpleconfigurator" autoStart="true" startLevel="1" />
-      <property name="org.eclipse.update.reconcile" value="false" />
       <property name="osgi.instance.area.default" value="@user.home/.ApacheDirectoryStudio" />
+      <property name="org.eclipse.update.reconcile" value="false" />
    </configurations>
 
    <preferencesInfo>
diff --git a/tests/test.integration.core/pom-first.xml b/tests/test.integration.core/pom-first.xml
index 70a38f9..271d18e 100644
--- a/tests/test.integration.core/pom-first.xml
+++ b/tests/test.integration.core/pom-first.xml
@@ -47,22 +47,35 @@
             <Eclipse-LazyStart>true</Eclipse-LazyStart>
             <Bundle-Activator>org.apache.directory.studio.test.integration.core.Activator</Bundle-Activator>
             
-            <Require-Bundle>org.junit;bundle-version="4.11.0",
+            <Export-Package>org.apache.directory.studio.test.integration.junit5</Export-Package>
+            
+            <Require-Bundle>org.hamcrest.library;bundle-version="1.3.0",
+ org.junit.jupiter.api;bundle-version="5.7.0",
+ org.junit.jupiter.params;bundle-version="5.7.0",
+ org.opentest4j;bundle-version="1.2.0",
+
  org.apache.directory.server.apacheds-test-framework;bundle-version="${org.apache.directory.server.version}",
  org.apache.directory.server.annotations;bundle-version="${org.apache.directory.server.version}",
- org.apache.directory.server.xdbm.partition;bundle-version="${org.apache.directory.server.version}",
- org.apache.directory.server.jdbm.partition;bundle-version="${org.apache.directory.server.version}",
  org.apache.directory.server.core.annotations;bundle-version="${org.apache.directory.server.version}",
  org.apache.directory.server.core.api;bundle-version="${org.apache.directory.server.version}",
+ org.apache.directory.server.core;bundle-version="${org.apache.directory.server.version}",
  org.apache.directory.server.protocol.ldap;bundle-version="${org.apache.directory.server.version}",
+ org.apache.directory.server.protocol.shared;bundle-version="${org.apache.directory.server.version}",
+ org.apache.directory.server.jdbm.partition;bundle-version="${org.apache.directory.server.version}",
+ org.apache.directory.server.xdbm.partition;bundle-version="${org.apache.directory.server.version}",
+
  org.apache.directory.api.asn1.api;bundle-version="${org.apache.directory.api.bundleversion}",
  org.apache.directory.api.ldap.client.api;bundle-version="${org.apache.directory.api.bundleversion}",
  org.apache.directory.api.ldap.codec.core;bundle-version="${org.apache.directory.api.bundleversion}",
+ org.apache.directory.api.ldap.extras.codec;bundle-version="${org.apache.directory.api.bundleversion}",
  org.apache.directory.api.ldap.extras.codec.api;bundle-version="${org.apache.directory.api.bundleversion}",
  org.apache.directory.api.ldap.model;bundle-version="${org.apache.directory.api.bundleversion}",
  org.apache.directory.api.ldap.net.mina;bundle-version="${org.apache.directory.api.bundleversion}",
+ org.apache.directory.api.ldap.schema;bundle-version="${org.apache.directory.api.bundleversion}",
+ org.apache.directory.api.ldap.schema.converter;bundle-version="${org.apache.directory.api.bundleversion}",
  org.apache.directory.api.util;bundle-version="${org.apache.directory.api.bundleversion}",
  org.apache.mina.core;bundle-version="${org.apache.mina.bundleversion}",
+
  org.apache.directory.studio.connection.core,
  org.apache.directory.studio.common.core,
  org.apache.directory.studio.ldapbrowser.core,
@@ -72,7 +85,16 @@
  javax.annotation</Require-Bundle>
             
             <Import-Package>org.apache.commons.codec.digest,
+ org.apache.commons.lang3,
  org.apache.http.conn.ssl,
+ org.bouncycastle.asn1,
+ org.bouncycastle.asn1.x509,
+ org.bouncycastle.cert,
+ org.bouncycastle.cert.jcajce,
+ org.bouncycastle.jce.provider,
+ org.bouncycastle.operator,
+ org.bouncycastle.operator.jcajce,
+ org.bouncycastle.x509,
  org.dom4j,
  org.dom4j.io</Import-Package>
           
diff --git a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/core/ComputeDiffTest.java b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/core/ComputeDiffTest.java
new file mode 100644
index 0000000..99f032d
--- /dev/null
+++ b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/core/ComputeDiffTest.java
@@ -0,0 +1,308 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.studio.test.integration.core;
+
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.nullValue;
+
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.studio.connection.core.event.ConnectionEventRegistry;
+import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection;
+import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection.ModifyMode;
+import org.apache.directory.studio.ldapbrowser.core.model.IEntry;
+import org.apache.directory.studio.ldapbrowser.core.model.impl.Attribute;
+import org.apache.directory.studio.ldapbrowser.core.model.impl.DummyConnection;
+import org.apache.directory.studio.ldapbrowser.core.model.impl.DummyEntry;
+import org.apache.directory.studio.ldapbrowser.core.model.impl.Value;
+import org.apache.directory.studio.ldapbrowser.core.model.schema.Schema;
+import org.apache.directory.studio.ldapbrowser.core.utils.Utils;
+import org.apache.directory.studio.ldifparser.LdifParserConstants;
+import org.apache.directory.studio.ldifparser.model.LdifFile;
+import org.apache.directory.studio.ldifparser.model.container.LdifChangeModifyRecord;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+
+public class ComputeDiffTest
+{
+    private IBrowserConnection connection;
+
+    private IEntry oldEntry;
+    private IEntry newEntry;
+
+    static class TestConnection extends DummyConnection
+    {
+        private static final long serialVersionUID = 1L;
+
+        private ModifyMode modifyMode = ModifyMode.DEFAULT;
+        private ModifyMode modifyModeNoEMR = ModifyMode.DEFAULT;
+
+        public TestConnection()
+        {
+            super( Schema.DEFAULT_SCHEMA );
+        }
+
+
+        public ModifyMode getModifyMode()
+        {
+            return modifyMode;
+        }
+
+
+        public void setModifyMode( ModifyMode mode )
+        {
+            this.modifyMode = mode;
+        }
+
+
+        public ModifyMode getModifyModeNoEMR()
+        {
+            return modifyModeNoEMR;
+        }
+
+
+        public void setModifyModeNoEMR( ModifyMode mode )
+        {
+            this.modifyModeNoEMR = mode;
+        }
+
+    }
+
+    @BeforeEach
+    public void setup() throws Exception
+    {
+        ConnectionEventRegistry.suspendEventFiringInCurrentThread();
+        connection = new TestConnection();
+        oldEntry = new DummyEntry( new Dn( "cn=foo" ), connection );
+        newEntry = new DummyEntry( new Dn( "cn=foo" ), connection );
+    }
+
+
+    @Test
+    public void shouldReturnNullForEqualEntries()
+    {
+        // entries without attribute
+        assertThat( Utils.computeDiff( oldEntry, newEntry ), nullValue() );
+        assertThat( Utils.computeDiff( oldEntry, oldEntry ), nullValue() );
+        assertThat( Utils.computeDiff( newEntry, newEntry ), nullValue() );
+
+        // entries with attributes
+        addAttribute( oldEntry, "cn", "1" );
+        addAttribute( oldEntry, "member", "cn=1", "cn=2", "cn=3" );
+        addAttribute( newEntry, "cn", "1" );
+        addAttribute( newEntry, "member", "cn=1", "cn=2", "cn=3" );
+        assertThat( Utils.computeDiff( oldEntry, newEntry ), nullValue() );
+        assertThat( Utils.computeDiff( oldEntry, oldEntry ), nullValue() );
+        assertThat( Utils.computeDiff( newEntry, newEntry ), nullValue() );
+    }
+
+
+    @Test
+    public void shouldAddOneAttributeWithOneValue()
+    {
+        addAttribute( newEntry, "cn", "1" );
+
+        connection.setModifyMode( ModifyMode.DEFAULT );
+        assertChangeModify( Utils.computeDiff( oldEntry, newEntry ), "add:cn", "cn:1" );
+
+        connection.setModifyMode( ModifyMode.REPLACE );
+        assertChangeModify( Utils.computeDiff( oldEntry, newEntry ), "replace:cn", "cn:1" );
+    }
+
+
+    @Test
+    public void shouldAddMultipleAttributeWithMultipleValues()
+    {
+        addAttribute( newEntry, "cn", "1", "2" );
+        addAttribute( newEntry, "member", "cn=1", "cn=2", "cn=3" );
+
+        connection.setModifyMode( ModifyMode.DEFAULT );
+        assertChangeModify( Utils.computeDiff( oldEntry, newEntry ),
+            "add:cn", "cn:1", "cn:2", "-", "add:member", "member:cn=1", "member:cn=2", "member:cn=3" );
+
+        connection.setModifyMode( ModifyMode.REPLACE );
+        assertChangeModify( Utils.computeDiff( oldEntry, newEntry ),
+            "replace:cn", "cn:1", "cn:2", "-", "replace:member", "member:cn=1", "member:cn=2", "member:cn=3" );
+    }
+
+
+    @Test
+    public void shouldAddOneValueToOneExistingAttribute()
+    {
+        addAttribute( oldEntry, "cn", "1" );
+        addAttribute( newEntry, "cn", "1", "2" );
+
+        connection.setModifyMode( ModifyMode.DEFAULT );
+        assertChangeModify( Utils.computeDiff( oldEntry, newEntry ), "add:cn", "cn:2" );
+
+        connection.setModifyMode( ModifyMode.REPLACE );
+        assertChangeModify( Utils.computeDiff( oldEntry, newEntry ), "replace:cn", "cn:1", "cn:2" );
+    }
+
+
+    @Test
+    public void shouldAddMultipleValuesToMultipleExistingAttributes()
+    {
+        addAttribute( oldEntry, "cn", "1" );
+        addAttribute( newEntry, "cn", "1", "2", "3" );
+        addAttribute( oldEntry, "member", "cn=1", "cn=2", "cn=3" );
+        addAttribute( newEntry, "member", "cn=1", "cn=2", "cn=3", "cn=4", "cn=5" );
+
+        connection.setModifyMode( ModifyMode.DEFAULT );
+        assertChangeModify( Utils.computeDiff( oldEntry, newEntry ),
+            "add:cn", "cn:2", "cn:3", "-", "add:member", "member:cn=4", "member:cn=5" );
+
+        connection.setModifyMode( ModifyMode.REPLACE );
+        assertChangeModify( Utils.computeDiff( oldEntry, newEntry ),
+            "replace:cn", "cn:1", "cn:2", "cn:3", "-",
+            "replace:member", "member:cn=1", "member:cn=2", "member:cn=3", "member:cn=4", "member:cn=5" );
+    }
+
+
+    @Test
+    public void shouldDeleteAllOneValue()
+    {
+        addAttribute( oldEntry, "cn", "1" );
+
+        connection.setModifyMode( ModifyMode.DEFAULT );
+        assertChangeModify( Utils.computeDiff( oldEntry, newEntry ), "delete:cn", "cn:1" );
+
+        connection.setModifyMode( ModifyMode.REPLACE );
+        assertChangeModify( Utils.computeDiff( oldEntry, newEntry ), "replace:cn" );
+    }
+
+
+    @Test
+    public void shouldDeleteAllMultipleValues()
+    {
+        addAttribute( oldEntry, "cn", "1", "2" );
+        addAttribute( oldEntry, "member", "cn=1", "cn=2", "cn=3" );
+
+        connection.setModifyMode( ModifyMode.DEFAULT );
+        assertChangeModify( Utils.computeDiff( oldEntry, newEntry ),
+            "delete:cn", "cn:1", "cn:2", "-",
+            "delete:member", "member:cn=1", "member:cn=2", "member:cn=3" );
+
+        connection.setModifyMode( ModifyMode.REPLACE );
+        assertChangeModify( Utils.computeDiff( oldEntry, newEntry ), "replace:cn", "-", "replace:member" );
+    }
+
+
+    @Test
+    public void shouldDeleteOneValue()
+    {
+        addAttribute( oldEntry, "cn", "1", "2", "3" );
+        addAttribute( newEntry, "cn", "1", "2" );
+
+        connection.setModifyMode( ModifyMode.DEFAULT );
+        assertChangeModify( Utils.computeDiff( oldEntry, newEntry ), "delete:cn", "cn:3" );
+
+        connection.setModifyMode( ModifyMode.REPLACE );
+        assertChangeModify( Utils.computeDiff( oldEntry, newEntry ), "replace:cn", "cn:1", "cn:2" );
+    }
+
+
+    @Test
+    public void shouldDeleteMultipleValues()
+    {
+        addAttribute( oldEntry, "cn", "1", "2", "3" );
+        addAttribute( newEntry, "cn", "1" );
+        addAttribute( oldEntry, "member", "cn=1", "cn=2", "cn=3", "cn=4", "cn=5" );
+        addAttribute( newEntry, "member", "cn=1" );
+
+        connection.setModifyMode( ModifyMode.DEFAULT );
+        assertChangeModify( Utils.computeDiff( oldEntry, newEntry ),
+            "delete:cn", "cn:2", "cn:3", "-",
+            "delete:member", "member:cn=2", "member:cn=3", "member:cn=4", "member:cn=5" );
+
+        connection.setModifyMode( ModifyMode.REPLACE );
+        assertChangeModify( Utils.computeDiff( oldEntry, newEntry ),
+            "replace:cn", "cn:1", "-", "replace:member", "member:cn=1" );
+    }
+
+
+    @Test
+    public void shouldReplaceOneValue()
+    {
+        addAttribute( oldEntry, "cn", "1" );
+        addAttribute( newEntry, "cn", "2" );
+
+        connection.setModifyMode( ModifyMode.DEFAULT );
+        assertChangeModify( Utils.computeDiff( oldEntry, newEntry ), "delete:cn", "cn:1", "-", "add:cn", "cn:2" );
+
+        connection.setModifyMode( ModifyMode.REPLACE );
+        assertChangeModify( Utils.computeDiff( oldEntry, newEntry ), "replace:cn", "cn:2" );
+    }
+
+
+    @Test
+    public void shouldReplaceMultipleValues()
+    {
+        addAttribute( oldEntry, "cn", "1", "2", "3" );
+        addAttribute( newEntry, "cn", "4" );
+        addAttribute( oldEntry, "member", "cn=1", "cn=2", "cn=3" );
+        addAttribute( newEntry, "member", "cn=1", "cn=4", "cn=5" );
+
+        connection.setModifyMode( ModifyMode.DEFAULT );
+        assertChangeModify( Utils.computeDiff( oldEntry, newEntry ),
+            "delete:cn", "cn:1", "cn:2", "cn:3", "-", "add:cn", "cn:4", "-",
+            "delete:member", "member:cn=2", "member:cn=3", "-", "add:member", "member:cn=4", "member:cn=5" );
+
+        connection.setModifyMode( ModifyMode.REPLACE );
+        assertChangeModify( Utils.computeDiff( oldEntry, newEntry ),
+            "replace:cn", "cn:4", "-",
+            "replace:member", "member:cn=1", "member:cn=4", "member:cn=5" );
+    }
+
+
+    private static void addAttribute( IEntry entry, String attributeName, Object... rawValues )
+    {
+        Attribute attribute = new Attribute( entry, attributeName );
+        entry.addAttribute( attribute );
+        for ( Object rawValue : rawValues )
+        {
+            Value value = new Value( attribute, rawValue );
+            attribute.addValue( value );
+        }
+    }
+
+
+    private void assertChangeModify( LdifFile diff, String... lines )
+    {
+        assertThat( diff.isChangeType(), equalTo( true ) );
+        assertThat( diff.getContainers(), hasSize( 1 ) );
+        assertThat( diff.getLastContainer(), instanceOf( LdifChangeModifyRecord.class ) );
+
+        String s = "changetype:modify" + LdifParserConstants.LINE_SEPARATOR;
+        for ( String line : lines )
+        {
+            assertThat( diff.toRawString(), containsString( line ) );
+            s += line + LdifParserConstants.LINE_SEPARATOR;
+        }
+        s += "-" + LdifParserConstants.LINE_SEPARATOR;
+        assertThat( diff.toRawString(), containsString( s ) );
+    }
+
+}
diff --git a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/core/DirectoryApiConnectionWrapperTest.java b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/core/DirectoryApiConnectionWrapperTest.java
index b17eb59..730e49d 100644
--- a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/core/DirectoryApiConnectionWrapperTest.java
+++ b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/core/DirectoryApiConnectionWrapperTest.java
@@ -21,19 +21,33 @@
 package org.apache.directory.studio.test.integration.core;
 
 
-import static org.apache.directory.studio.test.integration.core.Constants.LOCALHOST;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.CONTEXT_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.MISC111_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.MISC_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.REFERRALS_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.REFERRAL_LOOP_1_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.REFERRAL_LOOP_2_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.REFERRAL_TO_REFERRALS_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.REFERRAL_TO_REFERRAL_TO_USERS_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.REFERRAL_TO_USERS_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USER1_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USER8_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USERS_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.dn;
 import static org.hamcrest.CoreMatchers.hasItems;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.net.ConnectException;
 import java.nio.channels.UnresolvedAddressException;
-import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.Callable;
@@ -45,7 +59,10 @@
 import java.util.function.Function;
 
 import javax.naming.directory.SearchControls;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
 
+import org.apache.commons.lang3.RandomStringUtils;
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
 import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
 //import org.apache.directory.api.ldap.extras.extended.endTransaction.EndTransactionRequest;
@@ -55,6 +72,9 @@
 //import org.apache.directory.api.ldap.extras.extended.startTransaction.StartTransactionResponse;
 import org.apache.directory.api.ldap.extras.extended.whoAmI.WhoAmIRequest;
 import org.apache.directory.api.ldap.extras.extended.whoAmI.WhoAmIResponse;
+import org.apache.directory.api.ldap.model.constants.SaslQoP;
+import org.apache.directory.api.ldap.model.constants.SaslSecurityStrength;
+import org.apache.directory.api.ldap.model.constants.SchemaConstants;
 import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
 import org.apache.directory.api.ldap.model.entry.DefaultEntry;
 import org.apache.directory.api.ldap.model.entry.DefaultModification;
@@ -62,6 +82,7 @@
 import org.apache.directory.api.ldap.model.entry.Modification;
 import org.apache.directory.api.ldap.model.entry.ModificationOperation;
 import org.apache.directory.api.ldap.model.exception.LdapAuthenticationException;
+import org.apache.directory.api.ldap.model.exception.LdapAuthenticationNotSupportedException;
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.exception.LdapLoopDetectedException;
 import org.apache.directory.api.ldap.model.message.ExtendedResponse;
@@ -69,38 +90,40 @@
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.util.Strings;
 import org.apache.directory.ldap.client.api.exception.InvalidConnectionException;
-import org.apache.directory.server.annotations.CreateLdapServer;
-import org.apache.directory.server.annotations.CreateTransport;
-import org.apache.directory.server.core.annotations.ApplyLdifFiles;
-import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
-import org.apache.directory.server.core.integ.FrameworkRunner;
-//import org.apache.directory.server.ldap.handlers.extended.EndTransactionHandler;
-import org.apache.directory.server.ldap.handlers.extended.PwdModifyHandler;
-//import org.apache.directory.server.ldap.handlers.extended.StartTransactionHandler;
-import org.apache.directory.server.ldap.handlers.extended.WhoAmIHandler;
 import org.apache.directory.studio.common.core.jobs.StudioProgressMonitor;
 import org.apache.directory.studio.connection.core.Connection;
-import org.apache.directory.studio.connection.core.ConnectionCorePlugin;
 import org.apache.directory.studio.connection.core.Connection.AliasDereferencingMethod;
 import org.apache.directory.studio.connection.core.Connection.ReferralHandlingMethod;
+import org.apache.directory.studio.connection.core.ConnectionCorePlugin;
 import org.apache.directory.studio.connection.core.ConnectionParameter;
-import org.apache.directory.studio.connection.core.IReferralHandler;
 import org.apache.directory.studio.connection.core.ConnectionParameter.AuthenticationMethod;
 import org.apache.directory.studio.connection.core.ConnectionParameter.EncryptionMethod;
+import org.apache.directory.studio.connection.core.ConnectionParameter.Krb5CredentialConfiguration;
+import org.apache.directory.studio.connection.core.ICertificateHandler.TrustLevel;
+import org.apache.directory.studio.connection.core.IReferralHandler;
 import org.apache.directory.studio.connection.core.event.ConnectionEventRegistry;
 import org.apache.directory.studio.connection.core.io.ConnectionWrapper;
+import org.apache.directory.studio.connection.core.io.StudioLdapException;
 import org.apache.directory.studio.connection.core.io.api.DirectoryApiConnectionWrapper;
 import org.apache.directory.studio.connection.core.io.api.StudioSearchResult;
 import org.apache.directory.studio.connection.core.io.api.StudioSearchResultEnumeration;
 import org.apache.directory.studio.ldapbrowser.core.jobs.InitializeRootDSERunnable;
 import org.apache.directory.studio.ldapbrowser.core.model.impl.BrowserConnection;
+import org.apache.directory.studio.test.integration.junit5.LdapServerType;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource.Mode;
+import org.apache.directory.studio.test.integration.junit5.SkipTestIfLdapServerIsNotAvailableInterceptor;
+import org.apache.directory.studio.test.integration.junit5.TestData;
+import org.apache.directory.studio.test.integration.junit5.TestFixture;
+import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
 import org.apache.mina.util.AvailablePortFinder;
 import org.eclipse.core.runtime.NullProgressMonitor;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
 
 
 /**
@@ -109,68 +132,28 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-@RunWith(FrameworkRunner.class)
-@CreateLdapServer(transports =
-    { @CreateTransport(protocol = "LDAP"), @CreateTransport(protocol = "LDAPS") }, extendedOpHandlers =
-    { PwdModifyHandler.class, WhoAmIHandler.class })
-@ApplyLdifFiles(clazz = DirectoryApiConnectionWrapperTest.class, value = "org/apache/directory/studio/test/integration/core/TestData.ldif")
-public class DirectoryApiConnectionWrapperTest extends AbstractLdapTestUnit
+@ExtendWith(SkipTestIfLdapServerIsNotAvailableInterceptor.class)
+public class DirectoryApiConnectionWrapperTest
 {
 
     protected ConnectionWrapper connectionWrapper;
 
-
-    @Before
-    public void setUp() throws Exception
+    @BeforeAll
+    public static void suspendEventFiringInCurrentThread()
     {
-        // create referral entries
-        Entry referralsOu = new DefaultEntry( getService().getSchemaManager() );
-        referralsOu.setDn( new Dn( "ou=referrals,ou=system" ) );
-        referralsOu.add( "objectClass", "top", "organizationalUnit" );
-        referralsOu.add( "ou", "referrals" );
-        service.getAdminSession().add( referralsOu );
-
-        // direct referral
-        Entry r1 = new DefaultEntry( getService().getSchemaManager() );
-        r1.setDn( new Dn( "cn=referral1,ou=referrals,ou=system" ) );
-        r1.add( "objectClass", "top", "referral", "extensibleObject" );
-        r1.add( "cn", "referral1" );
-        r1.add( "ref", "ldap://" + LOCALHOST + ":" + ldapServer.getPort() + "/ou=users,ou=system" );
-        service.getAdminSession().add( r1 );
-
-        // referral via another immediate referral
-        Entry r2 = new DefaultEntry( getService().getSchemaManager() );
-        r2.setDn( new Dn( "cn=referral2,ou=referrals,ou=system" ) );
-        r2.add( "objectClass", "top", "referral", "extensibleObject" );
-        r2.add( "cn", "referral2" );
-        r2.add( "ref", "ldap://" + LOCALHOST + ":" + ldapServer.getPort() + "/cn=referral1,ou=referrals,ou=system" );
-        service.getAdminSession().add( r2 );
-
-        // referral to parent which contains this referral
-        Entry r3 = new DefaultEntry( getService().getSchemaManager() );
-        r3.setDn( new Dn( "cn=referral3,ou=referrals,ou=system" ) );
-        r3.add( "objectClass", "top", "referral", "extensibleObject" );
-        r3.add( "cn", "referral3" );
-        r3.add( "ref", "ldap://" + LOCALHOST + ":" + ldapServer.getPort() + "/ou=referrals,ou=system" );
-        service.getAdminSession().add( r3 );
-
-        // referrals pointing to each other (loop)
-        Entry r4a = new DefaultEntry( getService().getSchemaManager() );
-        r4a.setDn( new Dn( "cn=referral4a,ou=referrals,ou=system" ) );
-        r4a.add( "objectClass", "top", "referral", "extensibleObject" );
-        r4a.add( "cn", "referral4a" );
-        r4a.add( "ref", "ldap://" + LOCALHOST + ":" + ldapServer.getPort() + "/cn=referral4b,ou=referrals,ou=system" );
-        service.getAdminSession().add( r4a );
-        Entry r4b = new DefaultEntry( getService().getSchemaManager() );
-        r4b.setDn( new Dn( "cn=referral4b,ou=referrals,ou=system" ) );
-        r4b.add( "objectClass", "top", "referral", "extensibleObject" );
-        r4b.add( "cn", "referral4b" );
-        r4b.add( "ref", "ldap://" + LOCALHOST + ":" + ldapServer.getPort() + "/cn=referral4a,ou=referrals,ou=system" );
-        service.getAdminSession().add( r4b );
+        ConnectionEventRegistry.suspendEventFiringInCurrentThread();
+        ConnectionCorePlugin.getDefault().setCertificateHandler( null );
     }
 
 
-    @After
+    @AfterAll
+    public static void resumeEventFiringInCurrentThread()
+    {
+        ConnectionEventRegistry.resumeEventFiringInCurrentThread();
+    }
+
+
+    @AfterEach
     public void tearDown() throws Exception
     {
         if ( connectionWrapper != null )
@@ -181,89 +164,637 @@
 
 
     /**
-     * Tests connecting to the server.
+     * Tests connecting to the server without encryption.
      */
-    @Test
-    public void testConnect()
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testConnectPlain( TestLdapServer ldapServer )
     {
         StudioProgressMonitor monitor = getProgressMonitor();
-        ConnectionParameter connectionParameter = new ConnectionParameter( null, LOCALHOST, ldapServer.getPort(),
-            EncryptionMethod.NONE, AuthenticationMethod.NONE, null, null, null, true, null, 30000L );
-        Connection connection = new Connection( connectionParameter );
-        ConnectionWrapper connectionWrapper = connection.getConnectionWrapper();
+        getConnection( monitor, ldapServer, null, null );
 
         assertFalse( connectionWrapper.isConnected() );
 
         connectionWrapper.connect( monitor );
         assertTrue( connectionWrapper.isConnected() );
+        assertFalse( connectionWrapper.isSecured() );
+        assertNull( connectionWrapper.getSslSession() );
         assertNull( monitor.getException() );
 
         connectionWrapper.disconnect();
         assertFalse( connectionWrapper.isConnected() );
+    }
 
-        // TODO: SSL, StartTLS
+
+    /**
+     * Tests connecting to the server using ldaps:// encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testConnectLdaps( TestLdapServer ldapServer )
+    {
+        StudioProgressMonitor monitor = getProgressMonitor();
+        Connection connection = getConnection( monitor, ldapServer, null, null );
+        connection.setPort( ldapServer.getPortSSL() );
+        connection.setEncryptionMethod( EncryptionMethod.LDAPS );
+        acceptAllCertificates();
+
+        assertFalse( connectionWrapper.isConnected() );
+
+        connectionWrapper.connect( monitor );
+        assertTrue( connectionWrapper.isConnected() );
+        assertTrue( connectionWrapper.isSecured() );
+        assertSslSession( ldapServer );
+        assertNull( monitor.getException() );
+
+        connectionWrapper.disconnect();
+        assertFalse( connectionWrapper.isConnected() );
+    }
+
+
+    /**
+     * Tests connecting to the server using StartTLS encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testConnectStartTls( TestLdapServer ldapServer )
+    {
+        StudioProgressMonitor monitor = getProgressMonitor();
+        Connection connection = getConnection( monitor, ldapServer, null, null );
+        connection.setEncryptionMethod( EncryptionMethod.START_TLS );
+        acceptAllCertificates();
+
+        assertFalse( connectionWrapper.isConnected() );
+
+        connectionWrapper.connect( monitor );
+        assertTrue( connectionWrapper.isConnected() );
+        assertTrue( connectionWrapper.isSecured() );
+        assertSslSession( ldapServer );
+        assertNull( monitor.getException() );
+
+        connectionWrapper.disconnect();
+        assertFalse( connectionWrapper.isConnected() );
     }
 
 
     /**
      * Test failed connections to the server.
      */
-    @Test
-    public void testConnectFailures()
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testConnectFailures( TestLdapServer ldapServer )
     {
         StudioProgressMonitor monitor = null;
-        ConnectionParameter connectionParameter = null;
         Connection connection = null;
-        ConnectionWrapper connectionWrapper = null;
 
         // invalid port
         monitor = getProgressMonitor();
-        connectionParameter = new ConnectionParameter( null, LOCALHOST, AvailablePortFinder.getNextAvailable(),
-            EncryptionMethod.NONE, AuthenticationMethod.NONE, null, null, null, true, null, 30000L );
-        connection = new Connection( connectionParameter );
-        connectionWrapper = connection.getConnectionWrapper();
+        connection = getConnection( monitor, ldapServer, null, null );
+        connection.setPort( AvailablePortFinder.getNextAvailable() );
         connectionWrapper.connect( monitor );
         assertFalse( connectionWrapper.isConnected() );
         assertNotNull( monitor.getException() );
-        assertTrue( monitor.getException() instanceof InvalidConnectionException );
+        assertTrue( monitor.getException() instanceof StudioLdapException );
         assertNotNull( monitor.getException().getCause() );
-        assertTrue( monitor.getException().getCause() instanceof ConnectException );
+        assertTrue( monitor.getException().getCause() instanceof InvalidConnectionException );
+        assertNotNull( monitor.getException().getCause().getCause() );
+        assertTrue( monitor.getException().getCause().getCause() instanceof ConnectException );
 
         // unknown host
         monitor = getProgressMonitor();
-        connectionParameter = new ConnectionParameter( null, "555.555.555.555", ldapServer.getPort(),
-            EncryptionMethod.NONE, AuthenticationMethod.NONE, null, null, null, true, null, 30000L );
-        connection = new Connection( connectionParameter );
-        connectionWrapper = connection.getConnectionWrapper();
+        connection = getConnection( monitor, ldapServer, null, null );
+        connection.setHost( "555.555.555.555" );
         connectionWrapper.connect( monitor );
         assertFalse( connectionWrapper.isConnected() );
         assertNotNull( monitor.getException() );
-        assertTrue( monitor.getException() instanceof InvalidConnectionException );
+        assertTrue( monitor.getException() instanceof StudioLdapException );
         assertNotNull( monitor.getException().getCause() );
-        assertTrue( monitor.getException().getCause() instanceof UnresolvedAddressException );
+        assertTrue( monitor.getException().getCause() instanceof InvalidConnectionException );
+        assertNotNull( monitor.getException().getCause().getCause() );
+        assertTrue( monitor.getException().getCause().getCause() instanceof UnresolvedAddressException );
+    }
 
-        // TODO: SSL, StartTLS
+
+    private void assertSslSession( TestLdapServer ldapServer )
+    {
+        try
+        {
+            SSLSession sslSession = connectionWrapper.getSslSession();
+            assertNotNull( sslSession );
+            assertNotNull( sslSession.getProtocol() );
+            assertNotNull( sslSession.getCipherSuite() );
+            assertNotNull( sslSession.getPeerCertificates() );
+            if ( ldapServer.getType() == LdapServerType.ApacheDS )
+            {
+                assertEquals( "TLSv1.2", sslSession.getProtocol() );
+            }
+            else
+            {
+                assertEquals( "TLSv1.3", sslSession.getProtocol() );
+            }
+        }
+        catch ( SSLPeerUnverifiedException e )
+        {
+            throw new RuntimeException( e );
+        }
     }
 
 
     /**
-     * Test binding to the server.
+     * Test binding to the server using simple auth and no encryption.
      */
-    @Test
-    public void testBind()
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testSimpleBindPlain( TestLdapServer ldapServer )
     {
+        ldapServer.setConfidentialityRequired( false );
         StudioProgressMonitor monitor = getProgressMonitor();
-        ConnectionParameter connectionParameter = new ConnectionParameter( null, LOCALHOST, ldapServer.getPort(),
-            EncryptionMethod.NONE, AuthenticationMethod.SIMPLE, "uid=admin,ou=system", "secret", null, true,
-            null, 30000L );
-        Connection connection = new Connection( connectionParameter );
-        ConnectionWrapper connectionWrapper = connection.getConnectionWrapper();
+        getConnection( monitor, ldapServer, ldapServer.getAdminDn(), ldapServer.getAdminPassword() );
 
         assertFalse( connectionWrapper.isConnected() );
 
         connectionWrapper.connect( monitor );
         connectionWrapper.bind( monitor );
         assertTrue( connectionWrapper.isConnected() );
+        assertFalse( connectionWrapper.isSecured() );
+        assertNull( monitor.getException() );
+
+        connectionWrapper.unbind();
+        connectionWrapper.disconnect();
+        assertFalse( connectionWrapper.isConnected() );
+    }
+
+
+    /**
+     * Test binding to the server using simple auth and no encryption should fail if the server requires confidentially.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testSimpleBindPlainConfidentiallyRequired( TestLdapServer ldapServer )
+    {
+        ldapServer.setConfidentialityRequired( true );
+        StudioProgressMonitor monitor = getProgressMonitor();
+        getConnection( monitor, ldapServer, ldapServer.getAdminDn(), ldapServer.getAdminPassword() );
+
+        assertFalse( connectionWrapper.isConnected() );
+
+        connectionWrapper.connect( monitor );
+        connectionWrapper.bind( monitor );
+
+        assertFalse( connectionWrapper.isConnected() );
+        assertFalse( connectionWrapper.isSecured() );
+        assertNotNull( monitor.getException() );
+        assertTrue( monitor.getException() instanceof StudioLdapException );
+        assertTrue( monitor.getException().getMessage().contains( "[LDAP result code 13 - confidentialityRequired]" ) );
+        assertNotNull( monitor.getException().getCause() );
+        assertTrue( monitor.getException().getCause() instanceof LdapAuthenticationNotSupportedException );
+    }
+
+
+    /**
+     * Test binding to the server using simple auth and ldaps:// encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testSimpleBindLdaps( TestLdapServer ldapServer )
+    {
+        ldapServer.setConfidentialityRequired( true );
+        StudioProgressMonitor monitor = getProgressMonitor();
+        Connection connection = getConnection( monitor, ldapServer, ldapServer.getAdminDn(),
+            ldapServer.getAdminPassword() );
+        connection.setPort( ldapServer.getPortSSL() );
+        connection.setEncryptionMethod( EncryptionMethod.LDAPS );
+        acceptAllCertificates();
+
+        assertFalse( connectionWrapper.isConnected() );
+
+        connectionWrapper.connect( monitor );
+        connectionWrapper.bind( monitor );
+        assertTrue( connectionWrapper.isConnected() );
+        assertTrue( connectionWrapper.isSecured() );
+        assertSslSession( ldapServer );
+        assertNull( monitor.getException() );
+
+        connectionWrapper.unbind();
+        connectionWrapper.disconnect();
+        assertFalse( connectionWrapper.isConnected() );
+    }
+
+
+    /**
+     * Test binding to the server using simple auth and StartTLS encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testSimpleBindStartTls( TestLdapServer ldapServer )
+    {
+        ldapServer.setConfidentialityRequired( true );
+        StudioProgressMonitor monitor = getProgressMonitor();
+        Connection connection = getConnection( monitor, ldapServer, ldapServer.getAdminDn(),
+            ldapServer.getAdminPassword() );
+        connection.setEncryptionMethod( EncryptionMethod.START_TLS );
+        acceptAllCertificates();
+
+        assertFalse( connectionWrapper.isConnected() );
+
+        connectionWrapper.connect( monitor );
+        connectionWrapper.bind( monitor );
+        assertTrue( connectionWrapper.isConnected() );
+        assertTrue( connectionWrapper.isSecured() );
+        assertSslSession( ldapServer );
+        assertNull( monitor.getException() );
+
+        connectionWrapper.unbind();
+        connectionWrapper.disconnect();
+        assertFalse( connectionWrapper.isConnected() );
+    }
+
+
+    /**
+     * Test binding to the server using SASL auth and no encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testSaslDigestMd5BindAuthPlain( TestLdapServer ldapServer )
+    {
+        testSaslDigestMd5BindPlain( ldapServer, SaslQoP.AUTH );
+    }
+
+
+    /**
+     * Test binding to the server using SASL auth-int and no encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.Fedora389ds)
+    public void testSaslDigestMd5BindAuthIntPlain( TestLdapServer ldapServer )
+    {
+        testSaslDigestMd5BindPlain( ldapServer, SaslQoP.AUTH_INT );
+    }
+
+
+    /**
+     * Test binding to the server using SASL auth-conf and no encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.Fedora389ds)
+    public void testSaslDigestMd5BindAuthConfPlain( TestLdapServer ldapServer )
+    {
+        testSaslDigestMd5BindPlain( ldapServer, SaslQoP.AUTH_CONF );
+    }
+
+
+    private void testSaslDigestMd5BindPlain( TestLdapServer ldapServer, SaslQoP saslQoP )
+    {
+        ldapServer.setConfidentialityRequired( false );
+        StudioProgressMonitor monitor = getProgressMonitor();
+        Connection connection = getConnection( monitor, ldapServer, "user.1", "password" );
+        connection.setAuthMethod( AuthenticationMethod.SASL_DIGEST_MD5 );
+        connection.getConnectionParameter().setSaslQop( SaslQoP.AUTH_CONF );
+
+        assertFalse( connectionWrapper.isConnected() );
+
+        connectionWrapper.connect( monitor );
+        connectionWrapper.bind( monitor );
+
+        assertTrue( connectionWrapper.isConnected() );
+        assertFalse( connectionWrapper.isSecured() );
+        assertNull( monitor.getException() );
+
+        connectionWrapper.unbind();
+        connectionWrapper.disconnect();
+        assertFalse( connectionWrapper.isConnected() );
+    }
+
+
+    /**
+     * Test binding to the server using SASL and no encryption should fail if the server requires confidentially.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.Fedora389ds)
+    public void testSaslBindPlainConfidentiallyRequired( TestLdapServer ldapServer )
+    {
+        ldapServer.setConfidentialityRequired( true );
+        StudioProgressMonitor monitor = getProgressMonitor();
+        Connection connection = getConnection( monitor, ldapServer, "user.1", "password" );
+        connection.setAuthMethod( AuthenticationMethod.SASL_DIGEST_MD5 );
+
+        assertFalse( connectionWrapper.isConnected() );
+
+        connectionWrapper.connect( monitor );
+        connectionWrapper.bind( monitor );
+
+        assertFalse( connectionWrapper.isConnected() );
+        assertFalse( connectionWrapper.isSecured() );
+        assertNotNull( monitor.getException() );
+        assertTrue( monitor.getException() instanceof StudioLdapException );
+        assertTrue( monitor.getException().getMessage().contains( "[LDAP result code 13 - confidentialityRequired]" ) );
+        assertNotNull( monitor.getException().getCause() );
+        assertTrue( monitor.getException().getCause() instanceof LdapAuthenticationNotSupportedException );
+    }
+
+
+    /**
+     * Test binding to the server using SASL auth and ldaps:// encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.Fedora389ds)
+    public void testSaslDigestMd5BindAuthLdaps( TestLdapServer ldapServer )
+    {
+        testSaslDigestMd5BindLdaps( ldapServer, SaslQoP.AUTH );
+    }
+
+
+    /**
+     * Test binding to the server using SASL auth-int and ldaps:// encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.Fedora389ds)
+    public void testSaslDigestMd5BindAuthIntLdaps( TestLdapServer ldapServer )
+    {
+        testSaslDigestMd5BindLdaps( ldapServer, SaslQoP.AUTH_INT );
+    }
+
+
+    /**
+     * Test binding to the server using SASL auth-conf and ldaps:// encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testSaslDigestMd5BindAuthConfLdaps( TestLdapServer ldapServer )
+    {
+        testSaslDigestMd5BindLdaps( ldapServer, SaslQoP.AUTH_CONF );
+    }
+
+
+    private void testSaslDigestMd5BindLdaps( TestLdapServer ldapServer, SaslQoP saslQoP )
+    {
+        ldapServer.setConfidentialityRequired( true );
+        StudioProgressMonitor monitor = getProgressMonitor();
+        Connection connection = getConnection( monitor, ldapServer, "user.1", "password" );
+        connection.setPort( ldapServer.getPortSSL() );
+        connection.setEncryptionMethod( EncryptionMethod.LDAPS );
+        connection.setAuthMethod( AuthenticationMethod.SASL_DIGEST_MD5 );
+        connection.getConnectionParameter().setSaslQop( saslQoP );
+        acceptAllCertificates();
+
+        assertFalse( connectionWrapper.isConnected() );
+
+        connectionWrapper.connect( monitor );
+        connectionWrapper.bind( monitor );
+
+        assertTrue( connectionWrapper.isConnected() );
+        assertTrue( connectionWrapper.isSecured() );
+        assertSslSession( ldapServer );
+        assertNull( monitor.getException() );
+
+        connectionWrapper.unbind();
+        connectionWrapper.disconnect();
+        assertFalse( connectionWrapper.isConnected() );
+    }
+
+
+    /**
+     * Test binding to the server using SASL auth and StartTLS encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.Fedora389ds)
+    public void testSaslDigestMd5BindAuthStartTls( TestLdapServer ldapServer )
+    {
+        testSaslDigestMd5BindStartTls( ldapServer, SaslQoP.AUTH );
+    }
+
+
+    /**
+     * Test binding to the server using SASL auth-int and StartTLS encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.Fedora389ds)
+    public void testSaslDigestMd5BindAuthIntStartTls( TestLdapServer ldapServer )
+    {
+        testSaslDigestMd5BindStartTls( ldapServer, SaslQoP.AUTH_INT );
+    }
+
+
+    /**
+     * Test binding to the server using SASL auth-conf and StartTLS encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testSaslDigestMd5BindAuthConfStartTls( TestLdapServer ldapServer )
+    {
+        testSaslDigestMd5BindStartTls( ldapServer, SaslQoP.AUTH_CONF );
+    }
+
+
+    private void testSaslDigestMd5BindStartTls( TestLdapServer ldapServer, SaslQoP saslQoP )
+    {
+        ldapServer.setConfidentialityRequired( true );
+        StudioProgressMonitor monitor = getProgressMonitor();
+        Connection connection = getConnection( monitor, ldapServer, "user.1", "password" );
+        connection.setEncryptionMethod( EncryptionMethod.START_TLS );
+        connection.setAuthMethod( AuthenticationMethod.SASL_DIGEST_MD5 );
+        connection.getConnectionParameter().setSaslQop( saslQoP );
+        acceptAllCertificates();
+
+        assertFalse( connectionWrapper.isConnected() );
+
+        connectionWrapper.connect( monitor );
+        connectionWrapper.bind( monitor );
+
+        assertTrue( connectionWrapper.isConnected() );
+        assertTrue( connectionWrapper.isSecured() );
+        assertSslSession( ldapServer );
+        assertNull( monitor.getException() );
+
+        connectionWrapper.unbind();
+        connectionWrapper.disconnect();
+        assertFalse( connectionWrapper.isConnected() );
+    }
+
+
+    /**
+     * Test binding to the server using GSSAPI auth and no encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.ApacheDS, reason = "Missing OSGi import: org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntryModifier cannot be found by org.apache.directory.server.protocol.shared_2.0.0.AM26")
+    public void testSaslGssapiBindAuthPlain( TestLdapServer ldapServer )
+    {
+        testSaslGssapiBindPlain( ldapServer, SaslQoP.AUTH );
+    }
+
+
+    /**
+     * Test binding to the server using GSSAPI auth-int and no encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.ApacheDS, reason = "Missing OSGi import: org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntryModifier cannot be found by org.apache.directory.server.protocol.shared_2.0.0.AM26")
+    public void testSaslGssapiBindAuthIntPlain( TestLdapServer ldapServer )
+    {
+        testSaslGssapiBindPlain( ldapServer, SaslQoP.AUTH_INT );
+    }
+
+
+    /**
+     * Test binding to the server using GSSAPI auth-conf and no encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.ApacheDS, reason = "Missing OSGi import: org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntryModifier cannot be found by org.apache.directory.server.protocol.shared_2.0.0.AM26")
+    public void testSaslGssapiBindAuthConfPlain( TestLdapServer ldapServer )
+    {
+        testSaslGssapiBindPlain( ldapServer, SaslQoP.AUTH_CONF );
+    }
+
+
+    private void testSaslGssapiBindPlain( TestLdapServer ldapServer, SaslQoP saslQoP )
+    {
+        TestFixture.skipIfKdcServerIsNotAvailable();
+
+        ldapServer.setConfidentialityRequired( false );
+        StudioProgressMonitor monitor = getProgressMonitor();
+        Connection connection = getConnection( monitor, ldapServer, "hnelson", "secret" );
+        connection.setAuthMethod( AuthenticationMethod.SASL_GSSAPI );
+        connection.getConnectionParameter().setKrb5CredentialConfiguration( Krb5CredentialConfiguration.OBTAIN_TGT );
+        connection.getConnectionParameter().setSaslQop( saslQoP );
+
+        assertFalse( connectionWrapper.isConnected() );
+
+        connectionWrapper.connect( monitor );
+        connectionWrapper.bind( monitor );
+
+        assertTrue( connectionWrapper.isConnected() );
+        assertFalse( connectionWrapper.isSecured() );
+        assertNull( monitor.getException() );
+
+        connectionWrapper.unbind();
+        connectionWrapper.disconnect();
+        assertFalse( connectionWrapper.isConnected() );
+    }
+
+
+    /**
+     * Test binding to the server using GSSAPI auth and ldaps:// encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.ApacheDS, reason = "Missing OSGi import: org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntryModifier cannot be found by org.apache.directory.server.protocol.shared_2.0.0.AM26")
+    public void testSaslGssapiBindAuthLdaps( TestLdapServer ldapServer ) throws Exception
+    {
+        testSaslGssapiBindLdaps( ldapServer, SaslQoP.AUTH );
+    }
+
+
+    /**
+     * Test binding to the server using GSSAPI auth-int and ldaps:// encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.ApacheDS, reason = "Missing OSGi import: org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntryModifier cannot be found by org.apache.directory.server.protocol.shared_2.0.0.AM26")
+    public void testSaslGssapiBindAuthIntLdaps( TestLdapServer ldapServer ) throws Exception
+    {
+        testSaslGssapiBindLdaps( ldapServer, SaslQoP.AUTH_INT );
+    }
+
+
+    /**
+     * Test binding to the server using GSSAPI auth-conf and ldaps:// encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.ApacheDS, reason = "Missing OSGi import: org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntryModifier cannot be found by org.apache.directory.server.protocol.shared_2.0.0.AM26")
+    public void testSaslGssapiBindAuthConfLdaps( TestLdapServer ldapServer ) throws Exception
+    {
+        testSaslGssapiBindLdaps( ldapServer, SaslQoP.AUTH_CONF );
+    }
+
+
+    private void testSaslGssapiBindLdaps( TestLdapServer ldapServer, SaslQoP saslQoP ) throws Exception
+    {
+        TestFixture.skipIfKdcServerIsNotAvailable();
+
+        // obtain native TGT
+        String[] cmd =
+            { "/bin/sh", "-c", "echo secret | /usr/bin/kinit hnelson" };
+        Process process = Runtime.getRuntime().exec( cmd );
+        int exitCode = process.waitFor();
+        assertEquals( 0, exitCode );
+
+        ldapServer.setConfidentialityRequired( true );
+        StudioProgressMonitor monitor = getProgressMonitor();
+        Connection connection = getConnection( monitor, ldapServer, "hnelson", "secret" );
+        connection.setPort( ldapServer.getPortSSL() );
+        connection.setEncryptionMethod( EncryptionMethod.LDAPS );
+        connection.setAuthMethod( AuthenticationMethod.SASL_GSSAPI );
+        connection.getConnectionParameter().setKrb5CredentialConfiguration( Krb5CredentialConfiguration.USE_NATIVE );
+        connection.getConnectionParameter().setSaslQop( saslQoP );
+        acceptAllCertificates();
+
+        assertFalse( connectionWrapper.isConnected() );
+
+        connectionWrapper.connect( monitor );
+        connectionWrapper.bind( monitor );
+
+        assertTrue( connectionWrapper.isConnected() );
+        assertTrue( connectionWrapper.isSecured() );
+        assertSslSession( ldapServer );
+        assertNull( monitor.getException() );
+
+        connectionWrapper.unbind();
+        connectionWrapper.disconnect();
+        assertFalse( connectionWrapper.isConnected() );
+    }
+
+
+    /**
+     * Test binding to the server using GSSAPI auth and StartTLS encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.ApacheDS, reason = "Missing OSGi import: org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntryModifier cannot be found by org.apache.directory.server.protocol.shared_2.0.0.AM26")
+    public void testSaslGssapiBindAuthStartTls( TestLdapServer ldapServer )
+    {
+        testSaslGssapiBindStartTls( ldapServer, SaslQoP.AUTH );
+    }
+
+
+    /**
+     * Test binding to the server using GSSAPI auth-int and StartTLS encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.ApacheDS, reason = "Missing OSGi import: org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntryModifier cannot be found by org.apache.directory.server.protocol.shared_2.0.0.AM26")
+    public void testSaslGssapiBindAuthIntStartTls( TestLdapServer ldapServer )
+    {
+        testSaslGssapiBindStartTls( ldapServer, SaslQoP.AUTH_INT );
+    }
+
+
+    /**
+     * Test binding to the server using GSSAPI auth-conf and StartTLS encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.ApacheDS, reason = "Missing OSGi import: org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntryModifier cannot be found by org.apache.directory.server.protocol.shared_2.0.0.AM26")
+    public void testSaslGssapiBindAuthConfStartTls( TestLdapServer ldapServer )
+    {
+        testSaslGssapiBindStartTls( ldapServer, SaslQoP.AUTH_CONF );
+    }
+
+
+    private void testSaslGssapiBindStartTls( TestLdapServer ldapServer, SaslQoP saslQoP )
+    {
+        TestFixture.skipIfKdcServerIsNotAvailable();
+
+        ldapServer.setConfidentialityRequired( true );
+        StudioProgressMonitor monitor = getProgressMonitor();
+        Connection connection = getConnection( monitor, ldapServer, "hnelson", "secret" );
+        connection.setEncryptionMethod( EncryptionMethod.START_TLS );
+        connection.setAuthMethod( AuthenticationMethod.SASL_GSSAPI );
+        connection.getConnectionParameter().setKrb5CredentialConfiguration( Krb5CredentialConfiguration.OBTAIN_TGT );
+        connection.getConnectionParameter().setSaslQop( saslQoP );
+        acceptAllCertificates();
+
+        assertFalse( connectionWrapper.isConnected() );
+
+        connectionWrapper.connect( monitor );
+        connectionWrapper.bind( monitor );
+
+        assertTrue( connectionWrapper.isConnected() );
+        assertTrue( connectionWrapper.isSecured() );
+        assertSslSession( ldapServer );
         assertNull( monitor.getException() );
 
         connectionWrapper.unbind();
@@ -275,52 +806,219 @@
     /**
      * Test failed binds to the server.
      */
-    @Test
-    public void testBindFailures()
+    @ParameterizedTest
+    @LdapServersSource
+    public void testBindFailures( TestLdapServer ldapServer )
     {
         StudioProgressMonitor monitor = null;
-        ConnectionParameter connectionParameter = null;
-        Connection connection = null;
-        ConnectionWrapper connectionWrapper = null;
 
-        // simple auth without principal and credential
+        // simple auth with invalid user
         monitor = getProgressMonitor();
-        connectionParameter = new ConnectionParameter( null, LOCALHOST, ldapServer.getPort(), EncryptionMethod.NONE,
-            AuthenticationMethod.SIMPLE, "uid=admin", "invalid", null, true, null, 30000L );
-        connection = new Connection( connectionParameter );
-        connectionWrapper = connection.getConnectionWrapper();
+        getConnection( monitor, ldapServer, "cn=invalid," + USERS_DN, "invalid" );
         connectionWrapper.connect( monitor );
         connectionWrapper.bind( monitor );
         assertFalse( connectionWrapper.isConnected() );
         assertNotNull( monitor.getException() );
-        assertTrue( monitor.getException() instanceof LdapAuthenticationException );
-        assertTrue( monitor.getException().getMessage().contains( "INVALID_CREDENTIALS" ) );
+        assertTrue( monitor.getException() instanceof StudioLdapException );
+        assertTrue( monitor.getException().getMessage().contains( "[LDAP result code 49 - invalidCredentials]" ) );
+        assertTrue( monitor.getException().getCause() instanceof LdapAuthenticationException );
+        if ( ldapServer.getType() == LdapServerType.ApacheDS )
+        {
+            assertTrue( monitor.getException().getMessage().contains( "INVALID_CREDENTIALS" ) );
+            assertTrue( monitor.getException().getCause().getMessage().contains( "INVALID_CREDENTIALS" ) );
+        }
 
-        // simple auth with invalid principal and credential
+        // simple auth with invalid password
         monitor = getProgressMonitor();
-        connectionParameter = new ConnectionParameter( null, LOCALHOST, ldapServer.getPort(), EncryptionMethod.NONE,
-            AuthenticationMethod.SIMPLE, "uid=admin,ou=system", "bar", null, true, null, 30000L );
-        connection = new Connection( connectionParameter );
-        connectionWrapper = connection.getConnectionWrapper();
+        getConnection( monitor, ldapServer, ldapServer.getAdminDn(), "invalid" );
         connectionWrapper.connect( monitor );
         connectionWrapper.bind( monitor );
         assertFalse( connectionWrapper.isConnected() );
         assertNotNull( monitor.getException() );
-        assertTrue( monitor.getException() instanceof LdapAuthenticationException );
-        assertTrue( monitor.getException().getMessage().contains( "INVALID_CREDENTIALS" ) );
+        assertTrue( monitor.getException() instanceof StudioLdapException );
+        assertTrue( monitor.getException().getMessage().contains( "[LDAP result code 49 - invalidCredentials]" ) );
+        assertTrue( monitor.getException().getCause() instanceof LdapAuthenticationException );
+        if ( ldapServer.getType() == LdapServerType.ApacheDS )
+        {
+            assertTrue( monitor.getException().getMessage().contains( "INVALID_CREDENTIALS" ) );
+            assertTrue( monitor.getException().getCause().getMessage().contains( "INVALID_CREDENTIALS" ) );
+        }
+    }
+
+
+    /**
+     * Executes load tests without encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.ApacheDS, reason = "JDBM JAR defines wrong OSGi imports")
+    public void loadTestPlain( TestLdapServer ldapServer ) throws Exception
+    {
+        ldapServer.setConfidentialityRequired( false );
+        StudioProgressMonitor monitor = getProgressMonitor();
+        getConnection( monitor, ldapServer, ldapServer.getAdminDn(), ldapServer.getAdminPassword() );
+
+        loadTest( ldapServer );
+    }
+
+
+    /**
+     * Executes load test with ldaps:// encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.ApacheDS, reason = "JDBM JAR defines wrong OSGi imports")
+    public void loadTestLdaps( TestLdapServer ldapServer ) throws Exception
+    {
+        ldapServer.setConfidentialityRequired( true );
+        StudioProgressMonitor monitor = getProgressMonitor();
+        Connection connection = getConnection( monitor, ldapServer, ldapServer.getAdminDn(),
+            ldapServer.getAdminPassword() );
+        connection.setPort( ldapServer.getPortSSL() );
+        connection.setEncryptionMethod( EncryptionMethod.LDAPS );
+        acceptAllCertificates();
+
+        loadTest( ldapServer );
+        loadTest( ldapServer );
+
+        assertEquals( "TLSv1.3", connectionWrapper.getSslSession().getProtocol() );
+    }
+
+
+    /**
+     * Executes load test with StartTLS encryption.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.ApacheDS, reason = "JDBM JAR defines wrong OSGi imports")
+    public void loadTestStartTls( TestLdapServer ldapServer ) throws Exception
+    {
+        ldapServer.setConfidentialityRequired( true );
+        StudioProgressMonitor monitor = getProgressMonitor();
+        Connection connection = getConnection( monitor, ldapServer, ldapServer.getAdminDn(),
+            ldapServer.getAdminPassword() );
+        connection.setEncryptionMethod( EncryptionMethod.START_TLS );
+        acceptAllCertificates();
+
+        loadTest( ldapServer );
+        loadTest( ldapServer );
+
+        assertEquals( "TLSv1.3", connectionWrapper.getSslSession().getProtocol() );
+    }
+
+
+    /**
+     * Executes various search and modify operations with small and large payloads.
+     */
+    private void loadTest( TestLdapServer ldapServer ) throws LdapException
+    {
+        int num = 500;
+
+        StudioProgressMonitor monitor = getProgressMonitor();
+
+        // connect and bind
+        for ( int i = 1; i <= 20; i++ )
+        {
+            connectionWrapper.connect( monitor );
+            connectionWrapper.bind( monitor );
+            connectionWrapper.unbind();
+            assertNull( monitor.getException() );
+        }
+        connectionWrapper.connect( monitor );
+        connectionWrapper.bind( monitor );
+        assertNull( monitor.getException() );
+
+        // lookup Root DSE
+        Entry rootDSE = lookup( "", monitor );
+        assertNull( monitor.getException() );
+        assertTrue( rootDSE.containsAttribute( "namingContexts", "subschemaSubentry" ) );
+        String subschemaSubentryDn = rootDSE.get( "subschemaSubentry" ).getString();
+
+        // lookup schema
+        Entry schema = lookup( subschemaSubentryDn, monitor );
+        assertNull( monitor.getException() );
+        assertTrue( schema.containsAttribute( "objectClasses", "attributeTypes" ) );
+
+        // create entries with some large attributes
+        for ( int i = 1; i <= num; i++ )
+        {
+            String dn = "uid=user." + i + "," + MISC111_DN;
+            Entry entry = new DefaultEntry( dn, "objectClass: inetOrgPerson", "sn: " + i, "cn: " + i,
+                "uid: user." + i );
+            if ( i % 50 == 0 )
+            {
+                entry.add( "description", RandomStringUtils.randomAscii( 10000 ) );
+                entry.add( "jpegPhoto", TestData.jpegImage( 100000 ) );
+            }
+            connectionWrapper.createEntry( entry, null, monitor, null );
+            assertNull( monitor.getException() );
+        }
+
+        // modify entries
+        for ( int i = 1; i <= num; i++ )
+        {
+            Dn dn = new Dn( "uid=user." + i + "," + MISC111_DN );
+            Collection<Modification> modifications = Arrays.asList(
+                new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE, "description",
+                    RandomStringUtils.randomAscii( 20 ) ),
+                new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE, "userPassword",
+                    RandomStringUtils.randomAscii( 20 ) ) );
+            connectionWrapper.modifyEntry( dn, modifications, null, monitor, null );
+            assertNull( monitor.getException() );
+        }
+
+        try
+        {
+            Thread.sleep( 5000L );
+        }
+        catch ( InterruptedException e )
+        {
+        }
+
+        // search entries
+        StudioSearchResultEnumeration result = connectionWrapper.search( MISC111_DN.getName(),
+            TestFixture.OBJECT_CLASS_ALL_FILTER, new SearchControls(), AliasDereferencingMethod.NEVER,
+            ReferralHandlingMethod.IGNORE, null, monitor, null );
+        List<Dn> dns = consume( result, sr -> sr.getDn() );
+        assertEquals( num, dns.size() );
+        assertNull( monitor.getException() );
+
+        // delete entries
+        for ( int i = 1; i <= num; i++ )
+        {
+            Dn dn = new Dn( "uid=user." + i + "," + MISC111_DN );
+            connectionWrapper.deleteEntry( dn, null, monitor, null );
+            assertNull( monitor.getException() );
+        }
+
+        assertNull( monitor.getException() );
+    }
+
+
+    private Entry lookup( String dn, StudioProgressMonitor monitor ) throws LdapException
+    {
+        SearchControls searchControls = new SearchControls();
+        searchControls.setSearchScope( SearchControls.OBJECT_SCOPE );
+        searchControls.setReturningAttributes( SchemaConstants.ALL_ATTRIBUTES_ARRAY );
+        StudioSearchResultEnumeration result = connectionWrapper.search( dn,
+            TestFixture.OBJECT_CLASS_ALL_FILTER, searchControls, AliasDereferencingMethod.NEVER,
+            ReferralHandlingMethod.IGNORE, null,
+            monitor, null );
+        List<Entry> entries = consume( result, sr -> sr.getEntry() );
+        assertEquals( 1, entries.size() );
+        return entries.get( 0 );
     }
 
 
     /**
      * Test searching.
      */
-    @Test
-    public void testSearch() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testSearch( TestLdapServer ldapServer ) throws Exception
     {
         StudioProgressMonitor monitor = getProgressMonitor();
         SearchControls searchControls = new SearchControls();
-        StudioSearchResultEnumeration result = getConnectionWrapper( monitor ).search( "ou=system", "(objectClass=*)",
-            searchControls, AliasDereferencingMethod.NEVER, ReferralHandlingMethod.IGNORE, null, monitor, null );
+        StudioSearchResultEnumeration result = getConnectionWrapper( monitor, ldapServer ).search( CONTEXT_DN.getName(),
+            "(objectClass=*)", searchControls, AliasDereferencingMethod.NEVER, ReferralHandlingMethod.IGNORE, null,
+            monitor, null );
 
         assertFalse( monitor.isCanceled() );
         assertFalse( monitor.errorsReported() );
@@ -333,15 +1031,16 @@
     /**
      * Test binary attributes.
      */
-    @Test
-    public void testSearchBinaryAttributes() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testSearchBinaryAttributes( TestLdapServer ldapServer ) throws Exception
     {
         StudioProgressMonitor monitor = getProgressMonitor();
         SearchControls searchControls = new SearchControls();
         searchControls.setSearchScope( SearchControls.OBJECT_SCOPE );
-        StudioSearchResultEnumeration result = getConnectionWrapper( monitor ).search( "uid=admin,ou=system",
-            "(objectClass=*)",
-            searchControls, AliasDereferencingMethod.NEVER, ReferralHandlingMethod.IGNORE, null, monitor, null );
+        StudioSearchResultEnumeration result = getConnectionWrapper( monitor, ldapServer ).search(
+            "uid=user.1,ou=users,dc=example,dc=org", "(objectClass=*)", searchControls, AliasDereferencingMethod.NEVER,
+            ReferralHandlingMethod.IGNORE, null, monitor, null );
 
         assertNotNull( result );
         assertTrue( result.hasMore() );
@@ -350,77 +1049,94 @@
 
         Object userPasswordValue = entry.getEntry().get( "userPassword" ).getBytes();
         assertEquals( byte[].class, userPasswordValue.getClass() );
-        assertEquals( "secret", new String( ( byte[] ) userPasswordValue, StandardCharsets.UTF_8 ) );
     }
 
 
-    @Test
-    public void testSearchContinuation_Follow_DirectReferral() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testSearchContinuation_Follow_DirectReferral( TestLdapServer ldapServer ) throws Exception
     {
         StudioProgressMonitor monitor = getProgressMonitor();
         SearchControls searchControls = new SearchControls();
-        StudioSearchResultEnumeration result = getConnectionWrapper( monitor ).search(
-            "cn=referral1,ou=referrals,ou=system", "(objectClass=*)", searchControls, AliasDereferencingMethod.NEVER,
+        StudioSearchResultEnumeration result = getConnectionWrapper( monitor, ldapServer ).search(
+            REFERRAL_TO_USERS_DN.getName(), "(objectClass=*)", searchControls,
+            AliasDereferencingMethod.NEVER,
             ReferralHandlingMethod.FOLLOW, null, monitor, null );
 
         assertFalse( monitor.isCanceled() );
         assertFalse( monitor.errorsReported() );
         assertNotNull( result );
 
-        List<String> dns = consume( result, sr -> sr.getDn().getName() );
-        assertEquals( 1, dns.size() );
-        assertEquals( "uid=user.1,ou=users,ou=system", dns.get( 0 ) );
+        List<Dn> dns = consume( result, sr -> sr.getDn() );
+        if ( ldapServer.getType() != LdapServerType.Fedora389ds )
+        {
+            // TODO: check why 389ds returns ou=users
+            assertEquals( 8, dns.size() );
+            assertThat( dns, hasItems( USER1_DN, USER8_DN ) );
+        }
     }
 
 
-    @Test
-    public void testSearchContinuation_Follow_IntermediateReferral() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testSearchContinuation_Follow_IntermediateReferral( TestLdapServer ldapServer ) throws Exception
     {
         StudioProgressMonitor monitor = getProgressMonitor();
         SearchControls searchControls = new SearchControls();
         searchControls.setSearchScope( SearchControls.SUBTREE_SCOPE );
-        StudioSearchResultEnumeration result = getConnectionWrapper( monitor ).search(
-            "cn=referral2,ou=referrals,ou=system", "(objectClass=*)", searchControls, AliasDereferencingMethod.NEVER,
+        StudioSearchResultEnumeration result = getConnectionWrapper( monitor, ldapServer ).search(
+            REFERRAL_TO_REFERRAL_TO_USERS_DN.getName(), "(objectClass=*)", searchControls,
+            AliasDereferencingMethod.NEVER,
             ReferralHandlingMethod.FOLLOW, null, monitor, null );
 
         assertFalse( monitor.isCanceled() );
         assertFalse( monitor.errorsReported() );
         assertNotNull( result );
 
-        List<String> dns = consume( result, sr -> sr.getDn().getName() );
-        assertEquals( 2, dns.size() );
-        assertThat( dns, hasItems( "ou=users,ou=system", "uid=user.1,ou=users,ou=system" ) );
+        List<Dn> dns = consume( result, sr -> sr.getDn() );
+        if ( ldapServer.getType() != LdapServerType.Fedora389ds )
+        {
+            // TODO: check why 389ds returns ou=users only
+            assertEquals( 9, dns.size() );
+            assertThat( dns, hasItems( USERS_DN, USER1_DN, USER8_DN ) );
+        }
     }
 
 
-    @Test
-    public void testSearchContinuation_Follow_ReferralToParent() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testSearchContinuation_Follow_ReferralToParent( TestLdapServer ldapServer ) throws Exception
     {
         StudioProgressMonitor monitor = getProgressMonitor();
         SearchControls searchControls = new SearchControls();
-        searchControls.setSearchScope( SearchControls.SUBTREE_SCOPE );
-        StudioSearchResultEnumeration result = getConnectionWrapper( monitor ).search(
-            "cn=referral3,ou=referrals,ou=system", "(objectClass=*)", searchControls, AliasDereferencingMethod.NEVER,
+        searchControls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
+        StudioSearchResultEnumeration result = getConnectionWrapper( monitor, ldapServer ).search(
+            REFERRAL_TO_REFERRALS_DN.getName(), "(objectClass=*)", searchControls, AliasDereferencingMethod.NEVER,
             ReferralHandlingMethod.FOLLOW, null, monitor, null );
 
         assertFalse( monitor.isCanceled() );
         assertFalse( monitor.errorsReported() );
         assertNotNull( result );
 
-        List<String> dns = consume( result, sr -> sr.getDn().getName() );
-        assertEquals( 3, dns.size() );
-        assertThat( dns, hasItems( "ou=referrals,ou=system", "ou=users,ou=system", "uid=user.1,ou=users,ou=system" ) );
+        List<Dn> dns = consume( result, sr -> sr.getDn() );
+        if ( ldapServer.getType() != LdapServerType.Fedora389ds )
+        {
+            // TODO: check why 389ds returns nothing
+            assertEquals( 5, dns.size() );
+            assertThat( dns, hasItems( REFERRALS_DN, USERS_DN, USER1_DN, MISC_DN ) );
+        }
     }
 
 
-    @Test
-    public void testSearchContinuation_Follow_ReferralLoop() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testSearchContinuation_Follow_ReferralLoop( TestLdapServer ldapServer ) throws Exception
     {
         StudioProgressMonitor monitor = getProgressMonitor();
         SearchControls searchControls = new SearchControls();
         searchControls.setSearchScope( SearchControls.SUBTREE_SCOPE );
-        StudioSearchResultEnumeration result = getConnectionWrapper( monitor ).search(
-            "cn=referral4a,ou=referrals,ou=system", "(objectClass=*)", searchControls, AliasDereferencingMethod.NEVER,
+        StudioSearchResultEnumeration result = getConnectionWrapper( monitor, ldapServer ).search(
+            REFERRAL_LOOP_1_DN.getName(), "(objectClass=*)", searchControls, AliasDereferencingMethod.NEVER,
             ReferralHandlingMethod.FOLLOW, null, monitor, null );
 
         assertFalse( monitor.isCanceled() );
@@ -432,15 +1148,16 @@
     }
 
 
-    @Test
-    public void testSearchContinuationFollowManually() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testSearchContinuationFollowManually( TestLdapServer ldapServer ) throws Exception
     {
         StudioProgressMonitor monitor = getProgressMonitor();
         SearchControls searchControls = new SearchControls();
         searchControls.setSearchScope( SearchControls.SUBTREE_SCOPE );
-        ConnectionWrapper connectionWrapper = getConnectionWrapper( monitor );
+        ConnectionWrapper connectionWrapper = getConnectionWrapper( monitor, ldapServer );
         ConnectionCorePlugin.getDefault().setReferralHandler( null );
-        StudioSearchResultEnumeration result = connectionWrapper.search( "ou=referrals,ou=system", "(objectClass=*)",
+        StudioSearchResultEnumeration result = connectionWrapper.search( REFERRALS_DN.getName(), "(objectClass=*)",
             searchControls, AliasDereferencingMethod.NEVER, ReferralHandlingMethod.FOLLOW_MANUALLY, null, monitor,
             null );
 
@@ -448,37 +1165,59 @@
         assertFalse( monitor.errorsReported() );
         assertNotNull( result );
 
-        List<String> dns = consume( result, sr -> sr.getDn().getName() );
-        assertEquals( 6, dns.size() );
-        assertThat( dns,
-            hasItems( "ou=referrals,ou=system", "ou=users,ou=system", "cn=referral1,ou=referrals,ou=system",
-                "cn=referral4a,ou=referrals,ou=system", "cn=referral4b,ou=referrals,ou=system" ) );
+        List<Dn> dns = consume( result, sr -> sr.getDn() );
+        assertEquals( 8, dns.size() );
+        assertThat( dns, hasItems( REFERRALS_DN, USER1_DN, USERS_DN, REFERRAL_TO_USERS_DN, REFERRAL_LOOP_1_DN,
+            REFERRAL_LOOP_2_DN, MISC_DN ) );
     }
 
 
-    @Test
-    public void testSearchContinuationIgnore() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testSearchContinuationIgnore( TestLdapServer ldapServer ) throws Exception
     {
         StudioProgressMonitor monitor = getProgressMonitor();
         SearchControls searchControls = new SearchControls();
         searchControls.setSearchScope( SearchControls.SUBTREE_SCOPE );
-        StudioSearchResultEnumeration result = getConnectionWrapper( monitor ).search( "ou=referrals,ou=system",
-            "(objectClass=*)", searchControls, AliasDereferencingMethod.NEVER, ReferralHandlingMethod.IGNORE, null,
-            monitor, null );
+        StudioSearchResultEnumeration result = getConnectionWrapper( monitor, ldapServer ).search(
+            REFERRALS_DN.getName(), "(objectClass=*)", searchControls, AliasDereferencingMethod.NEVER,
+            ReferralHandlingMethod.IGNORE, null, monitor, null );
 
         assertFalse( monitor.isCanceled() );
         assertFalse( monitor.errorsReported() );
         assertNotNull( result );
 
-        List<String> dns = consume( result, sr -> sr.getDn().getName() );
+        List<Dn> dns = consume( result, sr -> sr.getDn() );
         assertEquals( 1, dns.size() );
-        assertThat( dns, hasItems( "ou=referrals,ou=system" ) );
+        assertThat( dns, hasItems( REFERRALS_DN ) );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testSearchContinuationFollowParent( TestLdapServer ldapServer ) throws Exception
+    {
+        StudioProgressMonitor monitor = getProgressMonitor();
+        SearchControls searchControls = new SearchControls();
+        searchControls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
+        StudioSearchResultEnumeration result = getConnectionWrapper( monitor, ldapServer ).search(
+            REFERRALS_DN.getName(), "(objectClass=*)", searchControls, AliasDereferencingMethod.NEVER,
+            ReferralHandlingMethod.FOLLOW, null, monitor, null );
+
+        assertFalse( monitor.isCanceled() );
+        assertFalse( monitor.errorsReported() );
+        assertNotNull( result );
+
+        List<Dn> dns = consume( result, sr -> sr.getDn() );
+        assertEquals( 5, dns.size() );
+        assertThat( dns, hasItems( REFERRALS_DN, USERS_DN, USER1_DN, MISC_DN ) );
     }
 
 
     protected <T> List<T> consume( StudioSearchResultEnumeration result, Function<StudioSearchResult, T> fn )
         throws LdapException
     {
+        assertNotNull( result );
         List<T> list = new ArrayList<>();
         while ( result.hasMore() )
         {
@@ -489,291 +1228,295 @@
     }
 
 
-    @Test
-    public void testAdd() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testAdd( TestLdapServer ldapServer ) throws Exception
     {
-        String dn = "uid=user.X,ou=users,ou=system";
+        String dn = "uid=user.X," + USERS_DN;
 
         StudioProgressMonitor monitor = getProgressMonitor();
         Entry entry = new DefaultEntry( dn, "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: user.X" );
-        getConnectionWrapper( monitor ).createEntry( entry, null, monitor, null );
+        getConnectionWrapper( monitor, ldapServer ).createEntry( entry, null, monitor, null );
 
         // should have created entry
         assertFalse( monitor.isCanceled() );
         assertFalse( monitor.errorsReported() );
-        assertTrue( service.getAdminSession().exists( dn ) );
+        assertTrue( ldapServer.withAdminConnectionAndGet( connection -> connection.exists( dn ) ) );
     }
 
 
-    @Test
-    public void testAddFollowsReferral_DirectReferral() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testAddFollowsReferral_DirectReferral( TestLdapServer ldapServer ) throws Exception
     {
-        String targetDn = "uid=user.X,ou=users,ou=system";
-        String referralDn = "uid=user.X,cn=referral1,ou=referrals,ou=system";
+        Dn targetDn = dn( "uid=user.X", USERS_DN );
+        Dn referralDn = dn( "uid=user.X", REFERRAL_TO_USERS_DN );
 
         // create entry under referral
         StudioProgressMonitor monitor = getProgressMonitor();
         Entry entry = new DefaultEntry( referralDn, "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: user.X" );
-        getConnectionWrapper( monitor ).createEntry( entry, null, monitor, null );
+        getConnectionWrapper( monitor, ldapServer ).createEntry( entry, null, monitor, null );
 
         // should have created target entry
         assertFalse( monitor.isCanceled() );
         assertFalse( monitor.errorsReported() );
-        assertTrue( service.getAdminSession().exists( targetDn ) );
+        assertTrue( ldapServer.withAdminConnectionAndGet( connection -> connection.exists( targetDn ) ) );
     }
 
 
-    @Test
-    public void testAddFollowsReferral_IntermediateReferral() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testAddFollowsReferral_IntermediateReferral( TestLdapServer ldapServer ) throws Exception
     {
-        String targetDn = "uid=user.X,ou=users,ou=system";
-        String referralDn = "uid=user.X,cn=referral2,ou=referrals,ou=system";
+        Dn targetDn = dn( "uid=user.X", USERS_DN );
+        Dn referralDn = dn( "uid=user.X", REFERRAL_TO_REFERRAL_TO_USERS_DN );
 
         // create entry under referral
         StudioProgressMonitor monitor = getProgressMonitor();
         Entry entry = new DefaultEntry( referralDn, "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: user.X" );
-        getConnectionWrapper( monitor ).createEntry( entry, null, monitor, null );
+        getConnectionWrapper( monitor, ldapServer ).createEntry( entry, null, monitor, null );
 
         // should have created target entry
         assertFalse( monitor.isCanceled() );
         assertFalse( monitor.errorsReported() );
-        assertTrue( service.getAdminSession().exists( targetDn ) );
+        assertTrue( ldapServer.withAdminConnectionAndGet( connection -> connection.exists( targetDn ) ) );
     }
 
 
-    @Test
-    public void testAddFollowsReferral_ReferralLoop() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testAddFollowsReferral_ReferralLoop( TestLdapServer ldapServer ) throws Exception
     {
-        String referralDn = "uid=user.X,cn=referral4a,ou=referrals,ou=system";
+        Dn referralDn = dn( "uid=user.X", REFERRAL_LOOP_1_DN );
 
         // create entry under referral
         StudioProgressMonitor monitor = getProgressMonitor();
         Entry entry = new DefaultEntry( referralDn, "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: user.X" );
-        getConnectionWrapper( monitor ).createEntry( entry, null, monitor, null );
+        getConnectionWrapper( monitor, ldapServer ).createEntry( entry, null, monitor, null );
 
         // should not have created target entry
         assertFalse( monitor.isCanceled() );
         assertTrue( monitor.errorsReported() );
         assertNotNull( monitor.getException() );
-        assertTrue( monitor.getException() instanceof LdapLoopDetectedException );
+        assertTrue( monitor.getException() instanceof StudioLdapException );
+        assertTrue( monitor.getException().getMessage().contains( "[LDAP result code 54 - loopDetect]" ) );
+        assertTrue( monitor.getException().getMessage().contains( "already processed" ) );
+        assertTrue( monitor.getException().getCause() instanceof LdapLoopDetectedException );
     }
 
 
-    @Test
-    public void testModify() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testModify( TestLdapServer ldapServer ) throws Exception
     {
-        String dn = "uid=user.X,ou=users,ou=system";
+        String dn = "uid=user.X," + USERS_DN;
 
         // create entry
-        service.getAdminSession().add( new DefaultEntry( service.getSchemaManager(), dn,
-            "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: user.X" ) );
+        ldapServer.withAdminConnection( connection -> connection.add( new DefaultEntry( dn,
+            "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: user.X" ) ) );
 
         // modify entry
         StudioProgressMonitor monitor = getProgressMonitor();
         List<Modification> modifications = Collections.singletonList(
             new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE,
                 new DefaultAttribute( "sn", "modified" ) ) );
-        getConnectionWrapper( monitor ).modifyEntry( new Dn( dn ), modifications, null, monitor, null );
+        getConnectionWrapper( monitor, ldapServer ).modifyEntry( new Dn( dn ), modifications, null, monitor, null );
 
         // should have modified the entry
         assertFalse( monitor.isCanceled() );
         assertFalse( monitor.errorsReported() );
-        Entry entry = service.getAdminSession().lookup( new Dn( dn ) );
+        Entry entry = ldapServer.withAdminConnectionAndGet( connection -> connection.lookup( new Dn( dn ) ) );
         assertEquals( "modified", entry.get( "sn" ).getString() );
     }
 
 
-    @Test
-    public void testModifyFollowsReferral_DirectReferral() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testModifyFollowsReferral_DirectReferral( TestLdapServer ldapServer ) throws Exception
     {
-        String targetDn = "uid=user.X,ou=users,ou=system";
-        String referralDn = "uid=user.X,cn=referral1,ou=referrals,ou=system";
+        Dn targetDn = dn( "uid=user.X", USERS_DN );
+        Dn referralDn = dn( "uid=user.X", REFERRAL_TO_USERS_DN );
 
         // create target entry
-        service.getAdminSession().add( new DefaultEntry( service.getSchemaManager(), targetDn,
-            "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: user.X" ) );
+        ldapServer.withAdminConnection( connection -> connection.add( new DefaultEntry( targetDn,
+            "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: user.X" ) ) );
 
         // modify referral entry 
         StudioProgressMonitor monitor = getProgressMonitor();
         List<Modification> modifications = Collections.singletonList(
             new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE,
                 new DefaultAttribute( "sn", "modified" ) ) );
-        getConnectionWrapper( monitor ).modifyEntry( new Dn( referralDn ), modifications, null, monitor, null );
+        getConnectionWrapper( monitor, ldapServer ).modifyEntry( referralDn, modifications, null, monitor,
+            null );
 
         // should have modified the target entry
         assertFalse( monitor.isCanceled() );
         assertFalse( monitor.errorsReported() );
-        Entry entry = service.getAdminSession().lookup( new Dn( targetDn ) );
+        Entry entry = ldapServer.withAdminConnectionAndGet( connection -> connection.lookup( targetDn ) );
         assertEquals( "modified", entry.get( "sn" ).getString() );
     }
 
 
-    @Test
-    public void testModifyFollowsReferral_IntermediateReferral() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testModifyFollowsReferral_IntermediateReferral( TestLdapServer ldapServer ) throws Exception
     {
-        String targetDn = "uid=user.X,ou=users,ou=system";
-        String referralDn = "uid=user.X,cn=referral2,ou=referrals,ou=system";
+        Dn targetDn = dn( "uid=user.X", USERS_DN );
+        Dn referralDn = dn( "uid=user.X", REFERRAL_TO_REFERRAL_TO_USERS_DN );
 
         // create target entry
-        service.getAdminSession().add( new DefaultEntry( service.getSchemaManager(), targetDn,
-            "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: user.X" ) );
+        ldapServer.withAdminConnection( connection -> connection.add( new DefaultEntry( targetDn,
+            "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: user.X" ) ) );
 
         // modify referral entry 
         StudioProgressMonitor monitor = getProgressMonitor();
         List<Modification> modifications = Collections.singletonList(
             new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE,
                 new DefaultAttribute( "sn", "modified" ) ) );
-        getConnectionWrapper( monitor ).modifyEntry( new Dn( referralDn ), modifications, null, monitor, null );
+        getConnectionWrapper( monitor, ldapServer ).modifyEntry( referralDn, modifications, null, monitor,
+            null );
 
         // should have modified the target entry
         assertFalse( monitor.isCanceled() );
         assertFalse( monitor.errorsReported() );
-        Entry entry = service.getAdminSession().lookup( new Dn( targetDn ) );
+        Entry entry = ldapServer.withAdminConnectionAndGet( connection -> connection.lookup( targetDn ) );
         assertEquals( "modified", entry.get( "sn" ).getString() );
     }
 
 
-    @Test
-    public void testModifyFollowsReferral_ReferralLoop() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testModifyFollowsReferral_ReferralLoop( TestLdapServer ldapServer ) throws Exception
     {
-        String targetDn = "uid=user.X,ou=users,ou=system";
-        String referralDn = "uid=user.X,cn=referral4a,ou=referrals,ou=system";
+        Dn targetDn = dn( "uid=user.X", USERS_DN );
+        Dn referralDn = dn( "uid=user.X", REFERRAL_LOOP_1_DN );
 
         // create target entry
-        service.getAdminSession().add( new DefaultEntry( service.getSchemaManager(), targetDn,
-            "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: user.X" ) );
+        ldapServer.withAdminConnection( connection -> connection.add( new DefaultEntry( targetDn,
+            "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: user.X" ) ) );
 
         // modify referral entry 
         StudioProgressMonitor monitor = getProgressMonitor();
         List<Modification> modifications = Collections.singletonList(
             new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE,
                 new DefaultAttribute( "sn", "modified" ) ) );
-        getConnectionWrapper( monitor ).modifyEntry( new Dn( referralDn ), modifications, null, monitor, null );
+        getConnectionWrapper( monitor, ldapServer ).modifyEntry( referralDn, modifications, null, monitor,
+            null );
 
         // should not have modified the target entry
         assertFalse( monitor.isCanceled() );
         assertTrue( monitor.errorsReported() );
         assertNotNull( monitor.getException() );
-        assertTrue( monitor.getException() instanceof LdapLoopDetectedException );
+        assertTrue( monitor.getException() instanceof StudioLdapException );
+        assertTrue( monitor.getException().getMessage().contains( "[LDAP result code 54 - loopDetect]" ) );
+        assertTrue( monitor.getException().getMessage().contains( "already processed" ) );
+        assertTrue( monitor.getException().getCause() instanceof LdapLoopDetectedException );
     }
 
 
-    @Test
-    public void testDelete() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testDelete( TestLdapServer ldapServer ) throws Exception
     {
-        String dn = "uid=user.X,ou=users,ou=system";
+        String dn = "uid=user.X," + USERS_DN;
 
         // create entry
-        service.getAdminSession().add( new DefaultEntry( service.getSchemaManager(), dn,
-            "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: user.X" ) );
+        ldapServer.withAdminConnection( connection -> connection.add( new DefaultEntry( dn,
+            "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: user.X" ) ) );
 
         // delete entry
         StudioProgressMonitor monitor = getProgressMonitor();
-        getConnectionWrapper( monitor ).deleteEntry( new Dn( dn ), null, monitor, null );
+        getConnectionWrapper( monitor, ldapServer ).deleteEntry( new Dn( dn ), null, monitor, null );
 
         // should have deleted the entry
         assertFalse( monitor.isCanceled() );
         assertFalse( monitor.errorsReported() );
-        assertFalse( service.getAdminSession().exists( dn ) );
+        assertFalse( ldapServer.withAdminConnectionAndGet( connection -> connection.exists( dn ) ) );
     }
 
 
-    @Test
-    public void testDeleteFollowsReferral_DirectReferral() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testDeleteFollowsReferral_DirectReferral( TestLdapServer ldapServer ) throws Exception
     {
-        String targetDn = "uid=user.X,ou=users,ou=system";
-        String referralDn = "uid=user.X,cn=referral1,ou=referrals,ou=system";
+        Dn targetDn = dn( "uid=user.X", USERS_DN );
+        Dn referralDn = dn( "uid=user.X", REFERRAL_TO_USERS_DN );
 
         // create target entry
-        service.getAdminSession().add( new DefaultEntry( service.getSchemaManager(), targetDn,
-            "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: user.X" ) );
+        ldapServer.withAdminConnection( connection -> connection.add( new DefaultEntry( targetDn,
+            "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: user.X" ) ) );
 
         // delete referral entry 
         StudioProgressMonitor monitor = getProgressMonitor();
-        getConnectionWrapper( monitor ).deleteEntry( new Dn( referralDn ), null, monitor, null );
+        getConnectionWrapper( monitor, ldapServer ).deleteEntry( referralDn, null, monitor, null );
 
         // should have deleted the target entry
         assertFalse( monitor.isCanceled() );
         assertFalse( monitor.errorsReported() );
-        assertFalse( service.getAdminSession().exists( targetDn ) );
+        assertFalse( ldapServer.withAdminConnectionAndGet( connection -> connection.exists( targetDn ) ) );
     }
 
 
-    @Test
-    public void testDeleteFollowsReferral_IntermediateReferral() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testDeleteFollowsReferral_IntermediateReferral( TestLdapServer ldapServer ) throws Exception
     {
-        String targetDn = "uid=user.X,ou=users,ou=system";
-        String referralDn = "uid=user.X,cn=referral2,ou=referrals,ou=system";
+        Dn targetDn = dn( "uid=user.X", USERS_DN );
+        Dn referralDn = dn( "uid=user.X", REFERRAL_TO_REFERRAL_TO_USERS_DN );
 
         // create target entry
-        service.getAdminSession().add( new DefaultEntry( service.getSchemaManager(), targetDn,
-            "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: user.X" ) );
+        ldapServer.withAdminConnection( connection -> connection.add( new DefaultEntry( targetDn,
+            "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: user.X" ) ) );
 
         // delete referral entry 
         StudioProgressMonitor monitor = getProgressMonitor();
-        getConnectionWrapper( monitor ).deleteEntry( new Dn( referralDn ), null, monitor, null );
+        getConnectionWrapper( monitor, ldapServer ).deleteEntry( referralDn, null, monitor, null );
 
         // should have deleted the target entry
         assertFalse( monitor.isCanceled() );
         assertFalse( monitor.errorsReported() );
-        assertFalse( service.getAdminSession().exists( targetDn ) );
+        assertFalse( ldapServer.withAdminConnectionAndGet( connection -> connection.exists( targetDn ) ) );
     }
 
 
-    @Test
-    public void testDeleteFollowsReferral_ReferralLoop() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testDeleteFollowsReferral_ReferralLoop( TestLdapServer ldapServer ) throws Exception
     {
-        String targetDn = "uid=user.X,ou=users,ou=system";
-        String referralDn = "uid=user.X,cn=referral4a,ou=referrals,ou=system";
+        Dn targetDn = dn( "uid=user.X", USERS_DN );
+        Dn referralDn = dn( "uid=user.X", REFERRAL_LOOP_1_DN );
 
         // create target entry
-        service.getAdminSession().add( new DefaultEntry( service.getSchemaManager(), targetDn,
-            "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: user.X" ) );
+        ldapServer.withAdminConnection( connection -> connection.add( new DefaultEntry( targetDn,
+            "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: user.X" ) ) );
 
         // delete referral entry 
         StudioProgressMonitor monitor = getProgressMonitor();
-        getConnectionWrapper( monitor ).deleteEntry( new Dn( referralDn ), null, monitor, null );
+        getConnectionWrapper( monitor, ldapServer ).deleteEntry( referralDn, null, monitor, null );
 
         // should not have deleted the target entry
         assertFalse( monitor.isCanceled() );
         assertTrue( monitor.errorsReported() );
         assertNotNull( monitor.getException() );
-        assertTrue( monitor.getException() instanceof LdapLoopDetectedException );
-        assertTrue( service.getAdminSession().exists( targetDn ) );
-    }
-
-
-    @Test
-    public void testSearchContinuationFollowParent() throws Exception
-    {
-        StudioProgressMonitor monitor = getProgressMonitor();
-        SearchControls searchControls = new SearchControls();
-        searchControls.setSearchScope( SearchControls.SUBTREE_SCOPE );
-        StudioSearchResultEnumeration result = getConnectionWrapper( monitor ).search( "ou=referrals,ou=system",
-            "(objectClass=*)", searchControls, AliasDereferencingMethod.NEVER, ReferralHandlingMethod.FOLLOW, null,
-            monitor, null );
-
-        assertFalse( monitor.isCanceled() );
-        assertFalse( monitor.errorsReported() );
-        assertNotNull( result );
-
-        List<String> dns = consume( result, sr -> sr.getDn().getName() );
-        assertEquals( 4, dns.size() );
-        assertThat( dns, hasItems( "ou=referrals,ou=system", "ou=referrals,ou=system", "ou=users,ou=system",
-            "uid=user.1,ou=users,ou=system" ) );
+        assertTrue( monitor.getException() instanceof StudioLdapException );
+        assertTrue( monitor.getException().getMessage().contains( "[LDAP result code 54 - loopDetect]" ) );
+        assertTrue( monitor.getException().getMessage().contains( "already processed" ) );
+        assertTrue( monitor.getException().getCause() instanceof LdapLoopDetectedException );
+        assertTrue( ldapServer.withAdminConnectionAndGet( connection -> connection.exists( targetDn ) ) );
     }
 
 
     /**
      * Test initializing of Root DSE.
      */
-    @Test
-    public void testInitializeAttributesRunnable() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testInitializeAttributesRunnable( TestLdapServer ldapServer ) throws Exception
     {
         StudioProgressMonitor monitor = getProgressMonitor();
-        ConnectionParameter connectionParameter = new ConnectionParameter( null, LOCALHOST, ldapServer.getPort(),
-            EncryptionMethod.NONE, AuthenticationMethod.SIMPLE,
-            "uid=admin,ou=system", "secret", null, true, null, 30000L );
+        ConnectionParameter connectionParameter = new ConnectionParameter( null, ldapServer.getHost(),
+            ldapServer.getPort(), EncryptionMethod.NONE, AuthenticationMethod.SIMPLE,
+            ldapServer.getAdminDn(), ldapServer.getAdminPassword(), null, true, null, 30000L );
         Connection connection = new Connection( connectionParameter );
         BrowserConnection browserConnection = new BrowserConnection( connection );
 
@@ -788,14 +1531,16 @@
     /**
      * DIRSTUDIO-1039
      */
-    @Ignore
-    @Test
-    public void testConcurrentUseAndCloseOfConnection() throws Exception
+    @Disabled("Flaky test")
+    @ParameterizedTest
+    @LdapServersSource
+    public void testConcurrentUseAndCloseOfConnection( TestLdapServer ldapServer ) throws Exception
     {
         final StudioProgressMonitor monitor = getProgressMonitor();
-        final ConnectionParameter connectionParameter = new ConnectionParameter( null, LOCALHOST, ldapServer.getPort(),
+        final ConnectionParameter connectionParameter = new ConnectionParameter( null, ldapServer.getHost(),
+            ldapServer.getPort(),
             EncryptionMethod.NONE, AuthenticationMethod.SIMPLE,
-            "uid=admin,ou=system", "secret", null, true, null, 30000L );
+            ldapServer.getAdminDn(), ldapServer.getAdminPassword(), null, true, null, 30000L );
         final Connection connection = new Connection( connectionParameter );
         final BrowserConnection browserConnection = new BrowserConnection( connection );
 
@@ -857,14 +1602,20 @@
     }
 
 
-    @Test
-    public void testPasswordModifyRequestExtendedOperation_AdminChangesUserPassword() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testPasswordModifyRequestExtendedOperation_AdminChangesUserPassword( TestLdapServer ldapServer )
+        throws Exception
     {
-        String dn = "uid=user.X,ou=users,ou=system";
+        String dn = "uid=user.X," + USERS_DN;
 
         // create target entry
-        service.getAdminSession().add( new DefaultEntry( service.getSchemaManager(), dn,
-            "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: user.X", "userPassword:  secret" ) );
+        String password0 = "{SSHA}VHg6ewDaPUmVWw3efXL5NF6bVuRHGWhrCRH1xA==";
+        ldapServer.withAdminConnection( connection -> connection.add( new DefaultEntry( dn,
+            "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: user.X",
+            "userPassword: " + password0 ) ) );
+        Entry entry0 = ldapServer.withAdminConnectionAndGet( connection -> connection.lookup( new Dn( dn ) ) );
+        assertEquals( password0, Strings.utf8ToString( entry0.get( "userPassword" ).getBytes() ) );
 
         // modify password
         LdapApiService ldapApiService = LdapApiServiceFactory.getSingleton();
@@ -873,42 +1624,65 @@
         request.setUserIdentity( Strings.getBytesUtf8( dn ) );
         request.setNewPassword( Strings.getBytesUtf8( "s3cre3t" ) );
         StudioProgressMonitor monitor = getProgressMonitor();
-        ExtendedResponse response = getConnectionWrapper( monitor ).extended( request, monitor );
+        ExtendedResponse response = getConnectionWrapper( monitor, ldapServer ).extended( request, monitor );
 
-        // should have modified password of the target entry
-        assertEquals( ResultCodeEnum.SUCCESS, response.getLdapResult().getResultCode() );
-        assertFalse( monitor.isCanceled() );
-        assertFalse( monitor.errorsReported() );
-        Entry entry = service.getAdminSession().lookup( new Dn( dn ) );
-        assertEquals( "s3cre3t", Strings.utf8ToString( entry.get( "userPassword" ).getBytes() ) );
+        if ( ldapServer.getType() == LdapServerType.Fedora389ds )
+        {
+            assertEquals( ResultCodeEnum.CONFIDENTIALITY_REQUIRED, response.getLdapResult().getResultCode() );
+            assertFalse( monitor.isCanceled() );
+            assertTrue( monitor.errorsReported() );
+        }
+        else
+        {
+            // should have modified password of the target entry
+            assertEquals( ResultCodeEnum.SUCCESS, response.getLdapResult().getResultCode() );
+            assertFalse( monitor.isCanceled() );
+            assertFalse( monitor.errorsReported() );
+            Entry entry = ldapServer.withAdminConnectionAndGet( connection -> connection.lookup( new Dn( dn ) ) );
+            assertNotEquals( password0, Strings.utf8ToString( entry.get( "userPassword" ).getBytes() ) );
+        }
     }
 
 
-    @Test
-    public void testPasswordModifyRequestExtendedOperation_UserChangesOwnPassword() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.Fedora389ds, reason = "389ds requires secure connection")
+    public void testPasswordModifyRequestExtendedOperation_UserChangesOwnPassword( TestLdapServer ldapServer )
+        throws Exception
     {
-        LdapApiService ldapApiService = LdapApiServiceFactory.getSingleton();
-        String dn = "uid=user.X,ou=users,ou=system";
+        String dn = "uid=user.X," + USERS_DN;
 
         // create target entry
-        service.getAdminSession().add( new DefaultEntry( service.getSchemaManager(), dn,
-            "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: user.X", "userPassword:  secret" ) );
+        String password0 = "{SSHA}VHg6ewDaPUmVWw3efXL5NF6bVuRHGWhrCRH1xA==";
+        ldapServer.withAdminConnection( connection -> connection.add( new DefaultEntry( dn,
+            "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: user.X",
+            "userPassword: " + password0 ) ) );
+        Entry entry0 = ldapServer.withAdminConnectionAndGet( connection -> connection.lookup( new Dn( dn ) ) );
+        assertEquals( password0, Strings.utf8ToString( entry0.get( "userPassword" ).getBytes() ) );
 
         // modify password with wrong old password
+        LdapApiService ldapApiService = LdapApiServiceFactory.getSingleton();
         PasswordModifyRequest request1 = ( PasswordModifyRequest ) ldapApiService.getExtendedRequestFactories()
             .get( PasswordModifyRequest.EXTENSION_OID ).newRequest();
         request1.setUserIdentity( Strings.getBytesUtf8( dn ) );
         request1.setOldPassword( Strings.getBytesUtf8( "wrong" ) );
         request1.setNewPassword( Strings.getBytesUtf8( "s3cre3t" ) );
         StudioProgressMonitor monitor1 = getProgressMonitor();
-        ExtendedResponse response1 = getConnectionWrapper( monitor1, dn, "secret" ).extended( request1, monitor1 );
+        ExtendedResponse response1 = getConnectionWrapper( monitor1, ldapServer, dn, "secret" ).extended( request1,
+            monitor1 );
 
         // should not have modified password of the target entry
-        assertEquals( ResultCodeEnum.INVALID_CREDENTIALS, response1.getLdapResult().getResultCode() );
+        if ( ldapServer.getType() == LdapServerType.OpenLdap )
+        {
+            assertEquals( ResultCodeEnum.UNWILLING_TO_PERFORM, response1.getLdapResult().getResultCode() );
+        }
+        else
+        {
+            assertEquals( ResultCodeEnum.INVALID_CREDENTIALS, response1.getLdapResult().getResultCode() );
+        }
         assertFalse( monitor1.isCanceled() );
         assertTrue( monitor1.errorsReported() );
-        Entry entry1 = service.getAdminSession().lookup( new Dn( dn ) );
-        assertEquals( "secret", Strings.utf8ToString( entry1.get( "userPassword" ).getBytes() ) );
+        Entry entry1 = ldapServer.withAdminConnectionAndGet( connection -> connection.lookup( new Dn( dn ) ) );
+        assertEquals( password0, Strings.utf8ToString( entry1.get( "userPassword" ).getBytes() ) );
 
         // modify password with correct old password
         PasswordModifyRequest request2 = ( PasswordModifyRequest ) ldapApiService.getExtendedRequestFactories()
@@ -917,52 +1691,53 @@
         request2.setOldPassword( Strings.getBytesUtf8( "secret" ) );
         request2.setNewPassword( Strings.getBytesUtf8( "s3cre3t" ) );
         StudioProgressMonitor monitor2 = getProgressMonitor();
-        ExtendedResponse response2 = getConnectionWrapper( monitor2, dn, "secret" ).extended( request2, monitor2 );
+        ExtendedResponse response2 = getConnectionWrapper( monitor2, ldapServer, dn, "secret" ).extended( request2,
+            monitor2 );
 
         // should have modified password of the target entry
         assertEquals( ResultCodeEnum.SUCCESS, response2.getLdapResult().getResultCode() );
         assertFalse( monitor2.isCanceled() );
         assertFalse( monitor2.errorsReported() );
-        Entry entry2 = service.getAdminSession().lookup( new Dn( dn ) );
-        assertEquals( "s3cre3t", Strings.utf8ToString( entry2.get( "userPassword" ).getBytes() ) );
+        Entry entry2 = ldapServer.withAdminConnectionAndGet( connection -> connection.lookup( new Dn( dn ) ) );
+        assertNotEquals( password0, Strings.utf8ToString( entry2.get( "userPassword" ).getBytes() ) );
     }
 
 
-    @Ignore
-    @Test
-    public void testWhoAmIExtendedOperation() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(except = LdapServerType.ApacheDS, reason = "OSGi issue when using WhoAmI extended operation in ApacheDS")
+    public void testWhoAmIExtendedOperation( TestLdapServer ldapServer ) throws Exception
     {
         LdapApiService ldapApiService = LdapApiServiceFactory.getSingleton();
         WhoAmIRequest request = ( WhoAmIRequest ) ldapApiService.getExtendedRequestFactories()
             .get( WhoAmIRequest.EXTENSION_OID ).newRequest();
         StudioProgressMonitor monitor = getProgressMonitor();
-        WhoAmIResponse response = ( WhoAmIResponse ) getConnectionWrapper( monitor ).extended( request, monitor );
+        WhoAmIResponse response = ( WhoAmIResponse ) getConnectionWrapper( monitor, ldapServer ).extended( request,
+            monitor );
 
         assertEquals( ResultCodeEnum.SUCCESS, response.getLdapResult().getResultCode() );
         assertFalse( monitor.isCanceled() );
         assertFalse( monitor.errorsReported() );
         assertTrue( response.isDnAuthzId() );
-        assertEquals( "uid=admin,ou=system", response.getDn().toString() );
+        assertEquals( ldapServer.getAdminDn().toLowerCase(), response.getDn().toString().toLowerCase().trim() );
     }
 
-
     /*
     @Ignore
     @Test
-    public void testStartEndTransactionExtendedOperation() throws Exception
+    public void testStartEndTransactionExtendedOperation( TestLdapServer ldapServer ) throws Exception
     {
         LdapApiService ldapApiService = LdapApiServiceFactory.getSingleton();
-
+    
         StartTransactionRequest request1 = ( StartTransactionRequest ) ldapApiService.getExtendedRequestFactories()
             .get( StartTransactionRequest.EXTENSION_OID ).newRequest();
         StudioProgressMonitor monitor1 = getProgressMonitor();
         StartTransactionResponse response1 = ( StartTransactionResponse ) getConnectionWrapper( monitor1 )
             .extended( request1, monitor1 );
-
+    
         assertEquals( ResultCodeEnum.SUCCESS, response1.getLdapResult().getResultCode() );
         assertFalse( monitor1.isCanceled() );
         assertFalse( monitor1.errorsReported() );
-
+    
         EndTransactionRequest request2 = ( EndTransactionRequest ) ldapApiService.getExtendedRequestFactories()
             .get( EndTransactionRequest.EXTENSION_OID ).newRequest();
         request2.setTransactionId( response1.getTransactionId() );
@@ -970,7 +1745,7 @@
         StudioProgressMonitor monitor2 = getProgressMonitor();
         EndTransactionResponse response2 = ( EndTransactionResponse ) getConnectionWrapper( monitor2 )
             .extended( request2, monitor2 );
-
+    
         assertEquals( ResultCodeEnum.SUCCESS, response2.getLdapResult().getResultCode() );
         assertFalse( monitor2.isCanceled() );
         assertFalse( monitor2.errorsReported() );
@@ -985,35 +1760,57 @@
     }
 
 
-    protected ConnectionWrapper getConnectionWrapper( StudioProgressMonitor monitor )
+    protected void acceptAllCertificates()
     {
-        return getConnectionWrapper( monitor, "uid=admin,ou=system", "secret" );
+        ConnectionCorePlugin.getDefault().setCertificateHandler( ( host, certChain, failCauses ) -> {
+            return TrustLevel.Permanent;
+        } );
     }
 
 
-    protected ConnectionWrapper getConnectionWrapper( StudioProgressMonitor monitor, String dn, String password )
+    protected ConnectionWrapper getConnectionWrapper( StudioProgressMonitor monitor, TestLdapServer ldapServer )
     {
-        // simple auth without principal and credential
-        ConnectionParameter connectionParameter = new ConnectionParameter( null, LOCALHOST, ldapServer.getPort(),
-            EncryptionMethod.NONE, AuthenticationMethod.SIMPLE, dn, password, null, false, null, 30000L );
+        return getConnectionWrapper( monitor, ldapServer, ldapServer.getAdminDn(),
+            ldapServer.getAdminPassword() );
+    }
 
-        Connection connection = new Connection( connectionParameter );
 
-        connectionWrapper = connection.getConnectionWrapper();
+    protected ConnectionWrapper getConnectionWrapper( StudioProgressMonitor monitor, TestLdapServer ldapServer,
+        String dn, String password )
+    {
+        getConnection( monitor, ldapServer, dn, password );
+
         connectionWrapper.connect( monitor );
         connectionWrapper.bind( monitor );
-
         assertTrue( connectionWrapper.isConnected() );
+        assertNull( monitor.getException() );
+
+        return connectionWrapper;
+
+    }
+
+
+    protected Connection getConnection( StudioProgressMonitor monitor, TestLdapServer ldapServer,
+        String dn, String password )
+    {
+        // simple auth without principal and credential
+        ConnectionParameter connectionParameter = new ConnectionParameter( null, ldapServer.getHost(),
+            ldapServer.getPort(), EncryptionMethod.NONE, AuthenticationMethod.SIMPLE, dn, password, null, false, null,
+            30000L );
+        connectionParameter.setSaslQop( SaslQoP.AUTH_CONF );
+        connectionParameter.setSaslSecurityStrength( SaslSecurityStrength.HIGH );
+        connectionParameter.setSaslMutualAuthentication( true );
+
+        Connection connection = new Connection( connectionParameter );
 
         IReferralHandler referralHandler = referralUrls -> {
             return connection;
         };
         ConnectionCorePlugin.getDefault().setReferralHandler( referralHandler );
 
-        assertTrue( connectionWrapper.isConnected() );
-        assertNull( monitor.getException() );
+        connectionWrapper = connection.getConnectionWrapper();
 
-        return connectionWrapper;
+        return connection;
     }
 
 }
diff --git a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/core/SchemaTest.java b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/core/SchemaTest.java
index a779804..ed2c872 100644
--- a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/core/SchemaTest.java
+++ b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/core/SchemaTest.java
@@ -21,20 +21,15 @@
 package org.apache.directory.studio.test.integration.core;
 
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
 
 import java.util.Collection;
 
 import org.apache.directory.api.ldap.model.schema.AttributeType;
 import org.apache.directory.api.ldap.model.schema.ObjectClass;
-import org.apache.directory.server.annotations.CreateLdapServer;
-import org.apache.directory.server.annotations.CreateTransport;
-import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
-import org.apache.directory.server.core.integ.FrameworkRunner;
 import org.apache.directory.studio.ldapbrowser.core.model.schema.Schema;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.api.Test;
 
 
 /**
@@ -42,10 +37,7 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-@RunWith(FrameworkRunner.class)
-@CreateLdapServer(transports =
-    { @CreateTransport(protocol = "LDAP"), @CreateTransport(protocol = "LDAPS") })
-public class SchemaTest extends AbstractLdapTestUnit
+public class SchemaTest
 {
 
     /**
diff --git a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/ApacheDirectoryServer.java b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/ApacheDirectoryServer.java
new file mode 100644
index 0000000..c93a945
--- /dev/null
+++ b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/ApacheDirectoryServer.java
@@ -0,0 +1,169 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.studio.test.integration.junit5;
+
+
+import static org.apache.directory.studio.test.integration.junit5.Constants.LOCALHOST;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.stream.Collectors;
+
+import org.apache.directory.server.core.api.DirectoryService;
+import org.apache.directory.server.core.api.partition.Partition;
+import org.apache.directory.server.core.factory.DefaultDirectoryServiceFactory;
+import org.apache.directory.server.ldap.LdapServer;
+import org.apache.directory.server.ldap.handlers.extended.PwdModifyHandler;
+import org.apache.directory.server.ldap.handlers.extended.StartTlsHandler;
+import org.apache.directory.server.ldap.handlers.extended.WhoAmIHandler;
+import org.apache.directory.server.ldap.handlers.sasl.SimpleMechanismHandler;
+import org.apache.directory.server.ldap.handlers.sasl.cramMD5.CramMd5MechanismHandler;
+import org.apache.directory.server.ldap.handlers.sasl.digestMD5.DigestMd5MechanismHandler;
+import org.apache.directory.server.protocol.shared.transport.TcpTransport;
+import org.apache.directory.server.protocol.shared.transport.Transport;
+import org.apache.mina.util.AvailablePortFinder;
+
+
+/**
+ * An ApacheDS implementation of a test LDAP server.
+ * 
+ * This implementation starts an embedded ApacheDS and adds a partition dc=example,dc=org.
+ */
+public class ApacheDirectoryServer extends TestLdapServer
+{
+
+    private static ApacheDirectoryServer instance;
+
+    private DirectoryService service;
+    private LdapServer server;
+    private String defaultKeyStoreFile;
+
+    public static synchronized ApacheDirectoryServer getInstance()
+    {
+        if ( instance == null )
+        {
+            int port = AvailablePortFinder.getNextAvailable( 1024 );
+            int portSSL = AvailablePortFinder.getNextAvailable( port + 1 );
+            instance = new ApacheDirectoryServer( port, portSSL );
+            instance.startServer();
+        }
+        return instance;
+    }
+
+
+    private void startServer()
+    {
+        try
+        {
+            DefaultDirectoryServiceFactory factory = new DefaultDirectoryServiceFactory();
+            factory.init( "test" );
+            service = factory.getDirectoryService();
+            Partition partition = factory.getPartitionFactory().createPartition( service.getSchemaManager(),
+                service.getDnFactory(), "example.org", "dc=example,dc=org", 1024,
+                new File( service.getInstanceLayout().getPartitionsDirectory(), "example.org" ) );
+            partition.initialize();
+            service.addPartition( partition );
+            service.getSchemaManager().enable( "nis", "krb5kdc" );
+            service.getInterceptor( "passwordHashingInterceptor" );
+            service.setInterceptors( service.getInterceptors().stream()
+                .filter( i -> !i.getName().equals( "ConfigurableHashingInterceptor" ) )
+                .collect( Collectors.toList() ) );
+            service.setAllowAnonymousAccess( true );
+
+            server = new LdapServer();
+            server.setDirectoryService( service );
+            Transport ldap = new TcpTransport( port );
+            server.addTransports( ldap );
+            Transport ldaps = new TcpTransport( portSSL );
+            ldaps.setEnableSSL( true );
+            server.addTransports( ldaps );
+
+            server.addSaslMechanismHandler( "SIMPLE", new SimpleMechanismHandler() );
+            server.addSaslMechanismHandler( "CRAM-MD5", new CramMd5MechanismHandler() );
+            server.addSaslMechanismHandler( "DIGEST-MD5", new DigestMd5MechanismHandler() );
+            server.setSaslRealms( Collections.singletonList( "EXAMPLE.ORG" ) );
+            server.setSaslHost( getHost() );
+            server.setSearchBaseDn( TestFixture.CONTEXT_DN.getName() );
+
+            server.addExtendedOperationHandler( new StartTlsHandler() );
+            server.addExtendedOperationHandler( new PwdModifyHandler() );
+            server.addExtendedOperationHandler( new WhoAmIHandler() );
+
+            defaultKeyStoreFile = CertificateUtil.createTempKeyStore( "testStore", "changeit".toCharArray() )
+                .getAbsolutePath();
+            server.setKeystoreFile( defaultKeyStoreFile );
+            server.setCertificatePassword( "changeit" );
+
+            server.start();
+        }
+        catch ( Exception e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
+
+
+    @Override
+    public void prepare()
+    {
+        super.prepare();
+
+        try
+        {
+            if ( !defaultKeyStoreFile.equals( server.getKeystoreFile() ) )
+            {
+                server.setKeystoreFile( defaultKeyStoreFile );
+                server.reloadSslContext();
+            }
+        }
+        catch ( Exception e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
+
+
+    public void setKeystore( String keystorePath ) throws Exception
+    {
+        server.setKeystoreFile( keystorePath );
+        server.reloadSslContext();
+    }
+
+
+    public DirectoryService getService()
+    {
+        return service;
+    }
+
+
+    @Override
+    public void setConfidentialityRequired( boolean confidentialityRequired )
+    {
+        server.setConfidentialityRequired( confidentialityRequired );
+    }
+
+
+    private ApacheDirectoryServer( int port, int portSSL )
+    {
+        super( LdapServerType.ApacheDS, LOCALHOST, port, portSSL, "uid=admin,ou=system", "secret" );
+    }
+
+}
diff --git a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/CertificateUtil.java b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/CertificateUtil.java
new file mode 100644
index 0000000..8aa8197
--- /dev/null
+++ b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/CertificateUtil.java
@@ -0,0 +1,270 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.apache.directory.studio.test.integration.junit5;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.SecureRandom;
+import java.security.Security;
+import java.security.SignatureException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.Date;
+import java.util.Enumeration;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.security.auth.x500.X500Principal;
+
+import org.apache.directory.api.util.Strings;
+import org.bouncycastle.asn1.x509.BasicConstraints;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.asn1.x509.GeneralName;
+import org.bouncycastle.asn1.x509.GeneralNames;
+import org.bouncycastle.cert.CertIOException;
+import org.bouncycastle.cert.X509v3CertificateBuilder;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
+import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.operator.ContentSigner;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+
+/**
+ * Helper class used to generate self-signed certificates, and load a KeyStore
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public final class CertificateUtil
+{
+    private static final boolean SELF_SIGNED = true;
+    private static final boolean CA_SIGNED = false;
+    private static final boolean CRITICAL = true;
+        
+    private CertificateUtil()
+    {
+        // Nothing to do
+    }
+    
+    public static X509Certificate generateX509Certificate( X500Principal subjectDn, X500Principal issuerDn, KeyPair keyPair,
+            long daysValidity, String sigAlgorithm, boolean isCa )
+                    throws CertificateException
+    {
+        Instant from = Instant.now();
+        Instant to = from.plus( Duration.ofDays( daysValidity ) );
+        BigInteger serialNumber = new BigInteger( 64, new SecureRandom() );
+        try
+        {
+            ContentSigner signer = new JcaContentSignerBuilder( sigAlgorithm ).build( keyPair.getPrivate() );
+            InetAddress localHost = InetAddress.getLocalHost();
+            GeneralName[] sanLocalHost = new GeneralName[] {
+                    new GeneralName( GeneralName.dNSName,
+                            localHost.getHostName() ),
+                    new GeneralName( GeneralName.iPAddress, localHost.getHostAddress() )
+            };
+            X509v3CertificateBuilder certificateBuilder = new JcaX509v3CertificateBuilder( issuerDn,
+                    serialNumber,
+                    Date.from( from ),
+                    Date.from( to ),
+                    subjectDn,
+                    keyPair.getPublic() )
+                .addExtension( Extension.basicConstraints, CRITICAL, new BasicConstraints( isCa ) )
+                .addExtension( Extension.subjectAlternativeName, false, new GeneralNames( sanLocalHost ) );
+
+            return new JcaX509CertificateConverter().setProvider( new BouncyCastleProvider() )
+                    .getCertificate( certificateBuilder.build( signer ) );
+        }
+        catch ( OperatorCreationException | CertIOException | UnknownHostException e )
+        {
+            throw new CertificateException( "BouncyCastle failed to generate the X509 certificate.", e );
+        }
+    }
+    
+    /**
+     * Create a self signed certificate
+     * 
+     * @param issuer The Issuer (which is the same as the subject
+     * @param keyPair The asymmetric keyPair
+     * @param days Validity number of days
+     * @param algoStr Algorithm
+     * @return A self signed CA certificate
+     * @throws CertificateException If the info store din the certificate is invalid
+     * @throws IOException If we can't store some info in the certificate
+     * @throws NoSuchAlgorithmException If the algorithm does not exist
+     * @throws SignatureException If the certificate cannot be signed
+     * @throws NoSuchProviderException  If we don't have a security provider
+     * @throws InvalidKeyException  If the KeyPair is invalid
+     */
+    public static X509Certificate generateSelfSignedCertificate( X500Principal issuer, KeyPair keyPair,  int days, String algoStr ) 
+        throws CertificateException, IOException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException
+    {
+        return generateX509Certificate( issuer, issuer, keyPair, days, algoStr, SELF_SIGNED );
+    }
+    
+    /**
+     * Generate a Certificate signed by a CA certificate
+     * 
+     * @param issuer The Issuer (which is the same as the subject
+     * @param keyPair The asymmetric keyPair
+     * @param days Validity number of days
+     * @param algoStr Algorithm
+     * @return A self signed CA certificate
+     * @throws CertificateException If the info store din the certificate is invalid
+     * @throws IOException If we can't store some info in the certificate
+     * @throws NoSuchAlgorithmException If the algorithm does not exist
+     * @throws SignatureException If the certificate cannot be signed
+     * @throws NoSuchProviderException  If we don't have a security provider
+     * @throws InvalidKeyException  If the KeyPair is invalid
+     */
+    public static X509Certificate generateCertificate( X500Principal subject, X500Principal issuer, KeyPair keyPair,  int days, String algoStr ) 
+        throws CertificateException, IOException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException
+    {
+        return generateX509Certificate( subject, issuer, keyPair, days, algoStr, CA_SIGNED );
+    }
+    
+    
+    /**
+     * Loads the digital certificate from a keystore file
+     *
+     * @param keyStoreFile The KeyStore file to load
+     * @param keyStorePasswordStr The KeyStore password
+     * @return The KeyManager factory it created 
+     * @throws Exception If the KeyStore can't be loaded
+     */
+    public static KeyManagerFactory loadKeyStore( String keyStoreFile, String keyStorePasswordStr ) throws Exception
+    {
+        char[] keyStorePassword = Strings.isEmpty( keyStorePasswordStr ) ? null : keyStorePasswordStr.toCharArray();
+
+        if ( !Strings.isEmpty( keyStoreFile ) )
+        {
+            // We have a provided KeyStore file: read it
+            KeyStore keyStore = KeyStore.getInstance( KeyStore.getDefaultType() );
+
+            try ( InputStream is = Files.newInputStream( Paths.get( keyStoreFile ) ) )
+            {
+                keyStore.load( is, keyStorePassword );
+            }
+    
+            /*
+             * Verify key store:
+             * * Must only contain one entry which must be a key entry
+             * * Must contain a certificate chain
+             * * The private key must be recoverable by the key store password
+             */
+            Enumeration<String> aliases = keyStore.aliases();
+            
+            if ( !aliases.hasMoreElements() )
+            {
+                throw new KeyStoreException( "Key store is empty" );
+            }
+            
+            String alias = aliases.nextElement();
+            
+            if ( aliases.hasMoreElements() )
+            {
+                throw new KeyStoreException( "Key store contains more than one entry" );
+            }
+            
+            if ( !keyStore.isKeyEntry( alias ) )
+            {
+                throw new KeyStoreException( "Key store must contain a key entry" );
+            }
+            
+            if ( keyStore.getCertificateChain( alias ) == null )
+            {
+                throw new KeyStoreException( "Key store must contain a certificate chain" );
+            }
+            
+            if ( keyStore.getKey( alias, keyStorePassword ) == null )
+            {
+                throw new KeyStoreException( "Private key must be recoverable by the key store password" );
+            }
+    
+            // Set up key manager factory to use our key store
+            String algorithm = Security.getProperty( "ssl.KeyManagerFactory.algorithm" );
+    
+            if ( algorithm == null )
+            {
+                algorithm = KeyManagerFactory.getDefaultAlgorithm();
+            }
+    
+            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance( algorithm );
+    
+            keyManagerFactory.init( keyStore, keyStorePassword );
+            
+            return keyManagerFactory;
+        }
+        else
+        {
+            return null;
+        }
+    }
+    
+    
+    public static File createTempKeyStore( String keyStoreName, char[] keyStorePassword ) throws IOException, KeyStoreException,
+        NoSuchAlgorithmException, CertificateException, InvalidKeyException, NoSuchProviderException, SignatureException
+    {
+        // Create a temporary keystore, be sure to remove it when exiting the test
+        File keyStoreFile = Files.createTempFile( keyStoreName, "ks" ).toFile();
+        keyStoreFile.deleteOnExit();
+        
+        KeyStore keyStore = KeyStore.getInstance( KeyStore.getDefaultType() );
+        
+        try ( InputStream keyStoreData = new FileInputStream( keyStoreFile ) )
+        {
+            keyStore.load( null, keyStorePassword );
+        }
+
+        // Generate the asymmetric keys, using EC algorithm
+        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance( "EC" );
+        KeyPair keyPair = keyPairGenerator.generateKeyPair();
+        
+        // Generate the subject's name
+        X500Principal owner = new X500Principal( "CN=apacheds,OU=directory,O=apache,C=US" );
+
+        // Create the self-signed certificate
+        X509Certificate certificate = CertificateUtil.generateSelfSignedCertificate( owner, keyPair, 365, "SHA256WithECDSA" );
+        
+        keyStore.setKeyEntry( "apachedsKey", keyPair.getPrivate(), keyStorePassword, new X509Certificate[] { certificate } );
+        
+        try ( FileOutputStream out = new FileOutputStream( keyStoreFile ) )
+        {
+            keyStore.store( out, keyStorePassword );
+        }
+        
+        return keyStoreFile;
+    }
+}
diff --git a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/core/Constants.java b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/Constants.java
similarity index 93%
rename from tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/core/Constants.java
rename to tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/Constants.java
index d7b4332..6c7e879 100644
--- a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/core/Constants.java
+++ b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/Constants.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.studio.test.integration.core;
+package org.apache.directory.studio.test.integration.junit5;
 
 
 import org.apache.directory.api.util.Network;
diff --git a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/Fedora389dsLdapServer.java b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/Fedora389dsLdapServer.java
new file mode 100644
index 0000000..c65e4ba
--- /dev/null
+++ b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/Fedora389dsLdapServer.java
@@ -0,0 +1,67 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.studio.test.integration.junit5;
+
+
+import org.apache.directory.api.ldap.model.entry.DefaultModification;
+import org.apache.directory.api.ldap.model.entry.Modification;
+import org.apache.directory.api.ldap.model.entry.ModificationOperation;
+
+
+/**
+ * An 389ds implementation of a test LDAP server.
+ * 
+ * This implementation expects that an existing 389ds server is running
+ * and connection parameters are provided via environment variables.
+ */
+public class Fedora389dsLdapServer extends TestLdapServer
+{
+    private static final String FEDORA_389DS_HOST = getEnvOrDefault( "FEDORA_389DS_HOST", "fedora389ds.example.com" );
+    private static final int FEDORA_389DS_PORT = Integer.parseInt( getEnvOrDefault( "FEDORA_389DS_PORT", "21389" ) );
+    private static final int FEDORA_389DS_PORT_SSL = Integer
+        .parseInt( getEnvOrDefault( "FEDORA_389DS_PORT_SSL", "21636" ) );
+    private static final String FEDORA_389DS_ADMIN_DN = getEnvOrDefault( "FEDORA_389DS_ADMIN_DN",
+        "cn=Directory Manager" );
+    private static final String FEDORA_389DS_ADMIN_PASSWORD = getEnvOrDefault( "FEDORA_389DS_ADMIN_PASSWORD", "admin" );
+
+    public static Fedora389dsLdapServer getInstance()
+    {
+        return new Fedora389dsLdapServer();
+    }
+
+
+    private Fedora389dsLdapServer()
+    {
+        super( LdapServerType.Fedora389ds, FEDORA_389DS_HOST, FEDORA_389DS_PORT, FEDORA_389DS_PORT_SSL,
+            FEDORA_389DS_ADMIN_DN, FEDORA_389DS_ADMIN_PASSWORD );
+    }
+
+
+    @Override
+    public void setConfidentialityRequired( boolean confidentialityRequired )
+    {
+        withAdminConnection( connection -> {
+            Modification modification = new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE,
+                "nsslapd-require-secure-binds", confidentialityRequired ? "on" : "off" );
+            connection.modify( "cn=config", modification );
+        } );
+    }
+}
diff --git a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/LdapServerType.java b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/LdapServerType.java
new file mode 100644
index 0000000..0ffe045
--- /dev/null
+++ b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/LdapServerType.java
@@ -0,0 +1,45 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.studio.test.integration.junit5;
+
+
+public enum LdapServerType
+{
+    ApacheDS,
+    OpenLdap,
+    Fedora389ds,
+    ;
+
+    public TestLdapServer getLdapServer()
+    {
+        switch ( this )
+        {
+            case ApacheDS:
+                return ApacheDirectoryServer.getInstance();
+            case OpenLdap:
+                return OpenLdapServer.getInstance();
+            case Fedora389ds:
+                return Fedora389dsLdapServer.getInstance();
+            default:
+                throw new IllegalArgumentException( "Unknown LDAP server type " + this );
+        }
+    }
+}
diff --git a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/LdapServersArgumentsProvider.java b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/LdapServersArgumentsProvider.java
new file mode 100644
index 0000000..2ffb5cd
--- /dev/null
+++ b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/LdapServersArgumentsProvider.java
@@ -0,0 +1,90 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.studio.test.integration.junit5;
+
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource.Mode;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.ArgumentsProvider;
+
+
+public class LdapServersArgumentsProvider implements ArgumentsProvider
+{
+
+    @Override
+    public Stream<Arguments> provideArguments( ExtensionContext context ) throws Exception
+    {
+        // Determine possible server types by checking only/except annotation attributes
+        LdapServersSource annotation = context.getTestMethod().get().getAnnotation( LdapServersSource.class );
+        List<LdapServerType> types = new ArrayList<>();
+        types.addAll( Arrays.asList( annotation.only() ) );
+        if ( types.isEmpty() )
+        {
+            types.addAll( Arrays.asList( LdapServerType.values() ) );
+        }
+        types.removeAll( Arrays.asList( annotation.except() ) );
+
+        // Filter available server types
+        List<LdapServerType> available = types.stream().filter( type -> type.getLdapServer().isAvailable() )
+            .collect( Collectors.toList() );
+
+        if ( !available.isEmpty() )
+        {
+            // Pick a random one
+            if ( annotation.mode() == Mode.One )
+            {
+                available = Collections.singletonList( available.get( new Random().nextInt( available.size() ) ) );
+            }
+
+            // Prepare the available servers
+            for ( LdapServerType type : available )
+            {
+                try
+                {
+                    type.getLdapServer().prepare();
+                }
+                catch ( Exception e )
+                {
+                    throw new RuntimeException( "Prepare failed for LDAP server type " + type, e );
+                }
+            }
+
+            // Return the available/picked servers
+            return available.stream().map( LdapServerType::getLdapServer ).map( Arguments::of );
+        }
+        else
+        {
+            // Return all types even if not available, will be skipped in SkipTestIfLdapServerIsNotAvailableInterceptor
+            return types.stream().map( LdapServerType::getLdapServer ).map( Arguments::of );
+        }
+
+    }
+
+}
diff --git a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/LdapServersSource.java b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/LdapServersSource.java
new file mode 100644
index 0000000..1261137
--- /dev/null
+++ b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/LdapServersSource.java
@@ -0,0 +1,56 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.studio.test.integration.junit5;
+
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.junit.jupiter.params.provider.ArgumentsSource;
+
+
+@Documented
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@ArgumentsSource(LdapServersArgumentsProvider.class)
+public @interface LdapServersSource
+{
+    Mode mode() default Mode.One;
+
+
+    LdapServerType[] only() default
+        {};
+
+
+    LdapServerType[] except() default
+        {};
+
+
+    String reason() default "";
+
+    enum Mode
+    {
+        One, All;
+    }
+}
diff --git a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/OpenLdapServer.java b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/OpenLdapServer.java
new file mode 100644
index 0000000..929cfc0
--- /dev/null
+++ b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/OpenLdapServer.java
@@ -0,0 +1,122 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.studio.test.integration.junit5;
+
+
+import org.apache.directory.api.ldap.model.entry.DefaultModification;
+import org.apache.directory.api.ldap.model.entry.Modification;
+import org.apache.directory.api.ldap.model.entry.ModificationOperation;
+import org.apache.directory.api.ldap.model.exception.LdapNoSuchAttributeException;
+import org.apache.directory.api.ldap.model.ldif.LdifEntry;
+import org.apache.directory.api.ldap.model.ldif.LdifReader;
+import org.apache.directory.ldap.client.api.LdapConnection;
+
+
+/**
+ * An OpenLDAP implementation of a test LDAP server.
+ * 
+ * This implementation expects that an existing OpenLDAP server is running
+ * and connection parameters are provided via environment variables.
+ */
+public class OpenLdapServer extends TestLdapServer
+{
+    private static final String OPENLDAP_HOST = getEnvOrDefault( "OPENLDAP_HOST", "openldap.example.com" );
+    private static final int OPENLDAP_PORT = Integer.parseInt( getEnvOrDefault( "OPENLDAP_PORT", "20389" ) );
+    private static final int OPENLDAP_PORT_SSL = Integer.parseInt( getEnvOrDefault( "OPENLDAP_PORT_SSL", "20636" ) );
+    private static final String OPENLDAP_ADMIN_DN = getEnvOrDefault( "OPENLDAP_ADMIN_DN",
+        "cn=admin,dc=example,dc=org" );
+    private static final String OPENLDAP_ADMIN_PASSWORD = getEnvOrDefault( "OPENLDAP_ADMIN_PASSWORD", "admin" );
+    private static final String OPENLDAP_CONFIG_DN = getEnvOrDefault( "OPENLDAP_CONFIG_DN", "cn=admin,cn=config" );
+    private static final String OPENLDAP_CONFIG_PASSWORD = getEnvOrDefault( "OPENLDAP_CONFIG_PASSWORD", "config" );
+
+    public static OpenLdapServer getInstance()
+    {
+        return new OpenLdapServer();
+    }
+
+
+    private OpenLdapServer()
+    {
+        super( LdapServerType.OpenLdap, OPENLDAP_HOST, OPENLDAP_PORT, OPENLDAP_PORT_SSL, OPENLDAP_ADMIN_DN,
+            OPENLDAP_ADMIN_PASSWORD );
+    }
+
+
+    public void prepare()
+    {
+        super.prepare();
+
+        try ( LdapConnection connection = openConnection();
+            LdifReader ldifReader = new LdifReader( TestFixture.class.getResourceAsStream( "OpenLdapConfig.ldif" ) ) )
+        {
+            connection.bind( OPENLDAP_CONFIG_DN, OPENLDAP_CONFIG_PASSWORD );
+            for ( LdifEntry entry : ldifReader )
+            {
+                for ( Modification modification : entry.getModifications() )
+                {
+                    connection.modify( entry.getDn(), modification );
+                }
+            }
+        }
+        catch ( Exception e )
+        {
+            throw new RuntimeException( "Unexpected exception: " + e, e );
+        }
+    }
+
+
+    @Override
+    public void setConfidentialityRequired( boolean confidentialityRequired )
+    {
+        if ( confidentialityRequired )
+        {
+            setSecurityProps( 128, 128 );
+        }
+        else
+        {
+            setSecurityProps( 0, 0 );
+        }
+    }
+
+
+    public void setSecurityProps( int ssf, int tls )
+    {
+
+        try ( LdapConnection connection = openConnection() )
+        {
+            connection.bind( OPENLDAP_CONFIG_DN, OPENLDAP_CONFIG_PASSWORD );
+            Modification modification1 = new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE,
+                "olcSecurity", "ssf=" + ssf + " tls=" + tls );
+            Modification modification2 = new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE,
+                "olcSaslSecProps", "noplain,noanonymous,minssf=" + ssf );
+            connection.modify( "cn=config", modification1, modification2 );
+        }
+        catch ( LdapNoSuchAttributeException e )
+        {
+            // ignore
+        }
+        catch ( Exception e )
+        {
+            throw new RuntimeException( "Unexpected exception: " + e, e );
+        }
+    }
+
+}
diff --git a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/SkipTestIfLdapServerIsNotAvailableInterceptor.java b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/SkipTestIfLdapServerIsNotAvailableInterceptor.java
new file mode 100644
index 0000000..95fe2f9
--- /dev/null
+++ b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/SkipTestIfLdapServerIsNotAvailableInterceptor.java
@@ -0,0 +1,53 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.studio.test.integration.junit5;
+
+
+import java.lang.reflect.Method;
+
+import org.junit.jupiter.api.Assumptions;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.api.extension.InvocationInterceptor;
+import org.junit.jupiter.api.extension.ReflectiveInvocationContext;
+
+
+public class SkipTestIfLdapServerIsNotAvailableInterceptor implements InvocationInterceptor
+{
+
+    @Override
+    public void interceptTestTemplateMethod( Invocation<Void> invocation,
+        ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext ) throws Throwable
+    {
+        invocationContext.getArguments().stream()
+            .filter( TestLdapServer.class::isInstance )
+            .map( TestLdapServer.class::cast )
+            .forEach( server -> {
+                if ( !server.isAvailable() )
+                {
+                    invocation.skip();
+                    Assumptions.assumeTrue( false,
+                        "Skip test because server " + server.getType() + " is not available" );
+                }
+            } );
+        invocation.proceed();
+    }
+
+}
diff --git a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/TestData.java b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/TestData.java
new file mode 100644
index 0000000..29829f0
--- /dev/null
+++ b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/TestData.java
@@ -0,0 +1,55 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.studio.test.integration.junit5;
+
+
+import java.nio.charset.StandardCharsets;
+
+import org.apache.commons.lang3.RandomStringUtils;
+
+
+/**
+ * Utility to generate test data.
+ */
+public class TestData
+{
+
+    public static byte[] jpegImage( int size )
+    {
+        byte[] jpegImage = RandomStringUtils.randomAscii( size ).getBytes( StandardCharsets.UTF_8 );
+        System.arraycopy( new byte[]
+            {
+                ( byte ) 0xFF,
+                ( byte ) 0xD8,
+                ( byte ) 0XFF,
+                ( byte ) 0XE0,
+                ( byte ) 0X00,
+                ( byte ) 0X00,
+                'J',
+                'F',
+                'I',
+                'F',
+                ( byte ) 0X00 },
+            0, jpegImage, 0, 11 );
+        return jpegImage;
+    }
+
+}
diff --git a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/TestFixture.java b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/TestFixture.java
new file mode 100644
index 0000000..6b04ad8
--- /dev/null
+++ b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/TestFixture.java
@@ -0,0 +1,274 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.studio.test.integration.junit5;
+
+
+import java.net.InetAddress;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+import org.apache.directory.api.ldap.model.cursor.EntryCursor;
+import org.apache.directory.api.ldap.model.cursor.SearchCursor;
+import org.apache.directory.api.ldap.model.entry.Attribute;
+import org.apache.directory.api.ldap.model.entry.DefaultEntry;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
+import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
+import org.apache.directory.api.ldap.model.ldif.LdifEntry;
+import org.apache.directory.api.ldap.model.ldif.LdifReader;
+import org.apache.directory.api.ldap.model.message.AliasDerefMode;
+import org.apache.directory.api.ldap.model.message.Control;
+import org.apache.directory.api.ldap.model.message.DeleteRequest;
+import org.apache.directory.api.ldap.model.message.DeleteRequestImpl;
+import org.apache.directory.api.ldap.model.message.SearchRequest;
+import org.apache.directory.api.ldap.model.message.SearchRequestImpl;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.api.ldap.model.name.Rdn;
+import org.apache.directory.api.ldap.model.schema.comparators.DnComparator;
+import org.apache.directory.ldap.client.api.EntryCursorImpl;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.studio.connection.core.Controls;
+import org.junit.jupiter.api.Assumptions;
+
+
+/**
+ * A unified test fixture that defines the DIT structure for all tests and for all test LDAP servers.
+ */
+public class TestFixture
+{
+
+    public static Dn dn( String dn )
+    {
+        try
+        {
+            return new Dn( dn );
+        }
+        catch ( LdapInvalidDnException e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
+
+
+    public static Dn dn( Rdn rdn, Dn dn )
+    {
+        try
+        {
+            return dn.add( rdn );
+        }
+        catch ( LdapInvalidDnException e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
+
+
+    public static Dn dn( String rdn, Dn dn )
+    {
+        try
+        {
+            return dn.add( rdn );
+        }
+        catch ( LdapInvalidDnException e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
+
+    public static final String KRB5_REALM = "EXAMPLE>COM";
+    public static final String KDC_HOST = "kerby.example.com";
+    public static final int KDC_PORT = 60088;
+
+    public static void skipIfKdcServerIsNotAvailable()
+    {
+        boolean available = false;
+        try(Socket s = new Socket(KDC_HOST, KDC_PORT))
+        {
+            available = true;
+        }
+        catch ( Exception e )
+        {
+            available = false;
+        }
+
+        if ( !available )
+        {
+            Assumptions.assumeTrue( false,
+                "Skip test because KDC server " + KDC_HOST + " is not available" );
+        }
+    }
+
+    public static final String OBJECT_CLASS_ALL_FILTER = "(objectClass=*)";
+
+    public static final String TEST_FIXTURE_LDIF = "TestFixture.ldif";
+
+    public static final Dn CONTEXT_DN = dn( "dc=example,dc=org" );
+
+    public static final Dn MISC_DN = dn( "ou=misc", CONTEXT_DN );
+    public static final Dn MISC1_DN = dn( "ou=misc.1", MISC_DN );
+    public static final Dn MISC11_DN = dn( "ou=misc.1.1", MISC1_DN );
+    public static final Dn MISC111_DN = dn( "ou=misc.1.1.1", MISC11_DN );
+    public static final Dn BJENSEN_DN = dn( "cn=Barbara Jensen", MISC_DN );
+    public static final Dn HNELSON_DN = dn( "uid=hnelson", MISC_DN );
+    public static final Dn GERMAN_UMLAUT_DN = dn( "cn=Wolfgang K\u00f6lbel", MISC_DN );
+    public static final Dn MULTI_VALUED_RDN_DN = dn( "cn=Barbara Jensen+uid=bjensen", MISC_DN );
+    public static final Dn DN_WITH_LEADING_SHARP_BACKSLASH_PREFIXED = dn( "cn=\\#123456", MISC_DN );
+    public static final Dn DN_WITH_LEADING_SHARP_HEX_PAIR_ESCAPED = dn( "cn=\\23123456", MISC_DN );
+    public static final Dn DN_WITH_ESCAPED_CHARACTERS_BACKSLASH_PREFIXED = dn( "cn=\\\"\\+\\,\\;\\<\\>\\\\", MISC_DN );
+    public static final Dn DN_WITH_ESCAPED_CHARACTERS_HEX_PAIR_ESCAPED = dn( "cn=\\22\\2B\\2C\\3B\\3C\\3E\\5C",
+        MISC_DN );
+    public static final Dn DN_WITH_TRAILING_EQUALS_CHARACTER = dn( "cn=trailing=", MISC_DN );
+    public static final Dn DN_WITH_TRAILING_EQUALS_CHARACTER_HEX_PAIR_ESCAPED = dn( "cn=trailing\\3D", MISC_DN );
+    public static final Dn DN_WITH_IP_HOST_NUMBER = dn( "cn=loopback+ipHostNumber=127.0.0.1", MISC_DN );
+    public static final Dn ALIAS_DN = dn( "cn=alias", MISC_DN );
+    public static final Dn SUBENTRY_DN = dn( "cn=subentry", MISC_DN );
+
+    public static final Dn USERS_DN = dn( "ou=users", CONTEXT_DN );
+    public static final Dn USER1_DN = dn( "uid=user.1", USERS_DN );
+    public static final Dn USER2_DN = dn( "uid=user.2", USERS_DN );
+    public static final Dn USER3_DN = dn( "uid=user.3", USERS_DN );
+    public static final Dn USER4_DN = dn( "uid=user.4", USERS_DN );
+    public static final Dn USER5_DN = dn( "uid=user.5", USERS_DN );
+    public static final Dn USER8_DN = dn( "uid=user.8", USERS_DN );
+
+    public static final Dn GROUPS_DN = dn( "ou=groups", CONTEXT_DN );
+    public static final Dn GROUP1_DN = dn( "cn=group.1", GROUPS_DN );
+
+    public static final Dn TARGET_DN = dn( "ou=target", CONTEXT_DN );
+
+    public static final Dn REFERRALS_DN = dn( "ou=referrals", CONTEXT_DN );
+    public static final Dn REFERRAL_TO_USERS_DN = dn( "cn=referral-to-users", REFERRALS_DN );
+    public static final Dn REFERRAL_TO_USER1_DN = dn( "cn=referral-to-user.1", REFERRALS_DN );
+    public static final Dn REFERRAL_TO_REFERRAL_TO_USERS_DN = dn( "cn=referral-to-referral-to-users", REFERRALS_DN );
+    public static final Dn REFERRAL_TO_REFERRALS_DN = dn( "cn=referral-to-referrals", REFERRALS_DN );
+    public static final Dn REFERRAL_LOOP_1_DN = dn( "cn=referral-loop-1", REFERRALS_DN );
+    public static final Dn REFERRAL_LOOP_2_DN = dn( "cn=referral-loop-2", REFERRALS_DN );
+    public static final Dn REFERRAL_TO_MISC_DN = dn( "cn=referral-to-misc", REFERRALS_DN );
+
+    /**
+     * Creates the context entry "dc=example,dc=org" if it doesn't exist yet.
+     */
+    public static void createContextEntry( TestLdapServer ldapServer )
+    {
+        ldapServer.withAdminConnection( connection -> {
+            if ( !connection.exists( CONTEXT_DN ) )
+            {
+                connection.add(
+                    new DefaultEntry( CONTEXT_DN, "objectClass", "top", "objectClass", "domain", "dc", "example" ) );
+            }
+        } );
+    }
+
+
+    public static void importData( TestLdapServer ldapServer )
+    {
+        ldapServer.withAdminConnection( connection -> {
+            try ( LdifReader ldifReader = new LdifReader( TestFixture.class.getResourceAsStream( TEST_FIXTURE_LDIF ) ) )
+            {
+                ldifReader.setSchemaManager( connection.getSchemaManager() );
+                for ( LdifEntry entry : ldifReader )
+                {
+                    replaceRefLdapUrl( ldapServer, entry );
+                    connection.add( entry.getEntry() );
+                }
+            }
+        } );
+    }
+
+
+    private static void replaceRefLdapUrl( TestLdapServer ldapServer, LdifEntry entry )
+        throws LdapInvalidAttributeValueException
+    {
+        Attribute ref = entry.get( "ref" );
+        if ( ref != null )
+        {
+            String oldRefLdapUrl = ref.getString();
+            String newRefLdapUrl = oldRefLdapUrl.replace( "replace-with-host-port",
+                ldapServer.getHost() + ":" + ldapServer.getPort() );
+            ref.remove( oldRefLdapUrl );
+            ref.add( newRefLdapUrl );
+        }
+    }
+
+
+    /**
+     * Cleans all test data.
+     */
+    public static void cleanup( TestLdapServer ldapServer )
+    {
+        ldapServer.withAdminConnection( connection -> {
+            // skip cleanup if context entry doesn't exist yet
+            if ( !connection.exists( CONTEXT_DN ) )
+            {
+                return;
+            }
+
+            // delete ou=referrals
+            deleteTree( connection, REFERRALS_DN, Optional.empty() );
+            // delete ou=groups
+            deleteTree( connection, GROUPS_DN, Optional.empty() );
+            // delete ou=users
+            deleteTree( connection, USERS_DN, Optional.empty() );
+            // delete ou=misc
+            deleteTree( connection, MISC_DN, Optional.of( Controls.SUBENTRIES_CONTROL ) );
+            deleteTree( connection, MISC_DN, Optional.empty() );
+            // delete ou=target
+            deleteTree( connection, TARGET_DN, Optional.of( Controls.SUBENTRIES_CONTROL ) );
+            deleteTree( connection, TARGET_DN, Optional.empty() );
+        } );
+    }
+
+
+    private static void deleteTree( LdapConnection connection, Dn baseDn, Optional<Control> control )
+        throws Exception
+    {
+        SearchRequest searchRequest = new SearchRequestImpl();
+        searchRequest.setBase( baseDn );
+        searchRequest.setFilter( OBJECT_CLASS_ALL_FILTER );
+        searchRequest.setScope( SearchScope.SUBTREE );
+        searchRequest.setDerefAliases( AliasDerefMode.NEVER_DEREF_ALIASES );
+        searchRequest.addControl( Controls.MANAGEDSAIT_CONTROL );
+        control.ifPresent( c -> searchRequest.addControl( c ) );
+
+        try ( SearchCursor searchCursor = connection.search( searchRequest );
+            EntryCursor entryCursor = new EntryCursorImpl( searchCursor ) )
+        {
+            List<Dn> dns = new ArrayList<>();
+            for ( Entry entry : entryCursor )
+            {
+                dns.add( entry.getDn() );
+            }
+            dns.sort( new DnComparator( "1.1" ) );
+            for ( Dn dn : dns )
+            {
+                DeleteRequest deleteRequest = new DeleteRequestImpl();
+                deleteRequest.setName( dn );
+                deleteRequest.addControl( Controls.MANAGEDSAIT_CONTROL );
+                control.ifPresent( c -> deleteRequest.addControl( c ) );
+                connection.delete( deleteRequest );
+            }
+        }
+    }
+
+}
diff --git a/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/TestLdapServer.java b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/TestLdapServer.java
new file mode 100644
index 0000000..bf3290c
--- /dev/null
+++ b/tests/test.integration.core/src/main/java/org/apache/directory/studio/test/integration/junit5/TestLdapServer.java
@@ -0,0 +1,226 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.studio.test.integration.junit5;
+
+
+import org.apache.directory.api.ldap.model.exception.LdapAuthenticationException;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.ldif.LdifEntry;
+import org.apache.directory.api.ldap.model.ldif.LdifReader;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.ldap.client.api.LdapConnectionConfig;
+import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+import org.apache.directory.ldap.client.api.NoVerificationTrustManager;
+import org.apache.directory.ldap.client.api.exception.InvalidConnectionException;
+
+
+/**
+ * An abstraction around an LDAP server that can be used for testing.
+ * Provides the LDAP server type and connection parameters.
+ */
+public abstract class TestLdapServer
+{
+    public static String getEnvOrDefault( String key, String defaultValue )
+    {
+        return System.getenv().getOrDefault( key, defaultValue );
+    }
+
+    protected final LdapServerType type;
+    protected final String host;
+    protected final int port;
+    protected final int portSSL;
+    protected final String adminDn;
+    protected final String adminPassword;
+
+    protected TestLdapServer( LdapServerType type, String host, int port, int portSSL, String adminDn,
+        String adminPassword )
+    {
+        this.type = type;
+        this.host = host;
+        this.port = port;
+        this.portSSL = portSSL;
+        this.adminDn = adminDn;
+        this.adminPassword = adminPassword;
+    }
+
+
+    public boolean isAvailable()
+    {
+        try ( LdapConnection connection = openAdminConnection() )
+        {
+        }
+        catch ( InvalidConnectionException e )
+        {
+            return false;
+        }
+        catch ( LdapAuthenticationException e )
+        {
+            return false;
+        }
+        catch ( Exception e )
+        {
+            throw new RuntimeException( "Unexpected exception: " + e, e );
+        }
+        return true;
+    }
+
+
+    public LdapConnection openAdminConnection() throws LdapException
+    {
+        LdapConnection connection = openConnection();
+        connection.bind( adminDn, adminPassword );
+        return connection;
+    }
+
+
+    public LdapNetworkConnection openConnection() throws LdapException
+    {
+        LdapConnectionConfig config = new LdapConnectionConfig();
+        config.setLdapHost( host );
+        config.setLdapPort( port );
+        config.setUseTls( true );
+        config.setTrustManagers( new NoVerificationTrustManager() );
+        LdapNetworkConnection connection = new LdapNetworkConnection( config );
+        connection.connect();
+        return connection;
+    }
+
+
+    public void withAdminConnection( LdapConnectionConsumer consumer )
+    {
+        try ( LdapConnection connection = openAdminConnection() )
+        {
+            consumer.accept( connection );
+        }
+        catch ( Exception e )
+        {
+            throw new RuntimeException( "Unexpected exception: " + e, e );
+        }
+    }
+
+    public static interface LdapConnectionConsumer
+    {
+        void accept( LdapConnection connection ) throws Exception;
+    }
+
+    public <T> T withAdminConnectionAndGet( LdapConnectionFunction<T> function )
+    {
+        try ( LdapConnection connection = openAdminConnection() )
+        {
+            return function.apply( connection );
+        }
+        catch ( Exception e )
+        {
+            throw new RuntimeException( "Unexpected exception: " + e, e );
+        }
+    }
+
+    public static interface LdapConnectionFunction<T>
+    {
+        T apply( LdapConnection connection ) throws Exception;
+    }
+
+    public void prepare()
+    {
+        TestFixture.createContextEntry( this );
+        TestFixture.cleanup( this );
+        TestFixture.importData( this );
+        setConfidentialityRequired( false );
+
+        String serverSpecificLdif = getType().name() + ".ldif";
+        if ( TestFixture.class.getResource( serverSpecificLdif ) != null )
+        {
+            withAdminConnection( connection -> {
+                try ( LdifReader ldifReader = new LdifReader(
+                    TestFixture.class.getResourceAsStream( serverSpecificLdif ) ) )
+                {
+                    for ( LdifEntry entry : ldifReader )
+                    {
+                        if ( entry.isChangeModify() )
+                        {
+                            connection.modify( entry.getDn(), entry.getModificationArray() );
+                        }
+                        if ( entry.isChangeAdd() )
+                        {
+                            connection.add( entry.getEntry() );
+                        }
+                    }
+                }
+                catch ( Exception e )
+                {
+                    throw new RuntimeException( "Unexpected exception: " + e, e );
+                }
+            } );
+        }
+    }
+
+
+    public LdapServerType getType()
+    {
+        return type;
+    }
+
+
+    public String getHost()
+    {
+        return host;
+    }
+
+
+    public int getPort()
+    {
+        return port;
+    }
+
+
+    public int getPortSSL()
+    {
+        return portSSL;
+    }
+
+
+    public String getLdapUrl()
+    {
+        return "ldap://" + host + ":" + port;
+    }
+
+
+    public String getAdminDn()
+    {
+        return adminDn;
+    }
+
+
+    public String getAdminPassword()
+    {
+        return adminPassword;
+    }
+
+
+    public abstract void setConfidentialityRequired( boolean confidentialityRequired );
+
+
+    @Override
+    public String toString()
+    {
+        return type.name();
+    }
+}
diff --git a/tests/test.integration.core/src/main/resources/org/apache/directory/studio/test/integration/core/TestData.ldif b/tests/test.integration.core/src/main/resources/org/apache/directory/studio/test/integration/core/TestData.ldif
deleted file mode 100644
index a33bc9e..0000000
--- a/tests/test.integration.core/src/main/resources/org/apache/directory/studio/test/integration/core/TestData.ldif
+++ /dev/null
@@ -1,42 +0,0 @@
-#  Licensed to the Apache Software Foundation (ASF) under one
-#  or more contributor license agreements.  See the NOTICE file
-#  distributed with this work for additional information
-#  regarding copyright ownership.  The ASF licenses this file
-#  to you 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.
-#
-dn: uid=user.1,ou=users,ou=system
-objectClass: top
-objectClass: person
-objectClass: organizationalPerson
-objectClass: inetOrgPerson
-givenName: Aaccf
-sn: Amar
-cn: Aaccf Amar
-initials: AA
-uid: user.1
-mail: user.1@null
-userPassword: password
-telephoneNumber: 976-893-3312
-homePhone: 337-310-0727
-pager: 185-156-4071
-mobile: 626-188-0934
-employeeNumber: 1
-street: 27919 Broadway Street
-l: Tallahassee
-st: DE
-postalCode: 67698
-postalAddress: Aaccf Amar$27919 Broadway Street$Tallahassee, DE  67698
-description: This is the description for Aaccf Amar.
-roomNumber: 1388
-
diff --git a/tests/test.integration.core/src/main/resources/org/apache/directory/studio/test/integration/junit5/ApacheDS.ldif b/tests/test.integration.core/src/main/resources/org/apache/directory/studio/test/integration/junit5/ApacheDS.ldif
new file mode 100644
index 0000000..e96163d
--- /dev/null
+++ b/tests/test.integration.core/src/main/resources/org/apache/directory/studio/test/integration/junit5/ApacheDS.ldif
@@ -0,0 +1,61 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you 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.
+#
+
+dn: ou=misc,dc=example,dc=org
+changetype: modify
+add: administrativeRole
+administrativeRole: accessControlSpecificArea
+-
+
+dn: ou=target,dc=example,dc=org
+changetype: modify
+add: administrativeRole
+administrativeRole: accessControlSpecificArea
+-
+
+dn: cn=subentry,ou=misc,dc=example,dc=org
+changetype: add
+objectClass: top
+objectClass: subentry
+cn: subentry
+subtreeSpecification: {}
+
+dn: uid=hnelson,ou=misc,dc=example,dc=org
+changetype: modify
+add: subtreeSpecification
+subtreeSpecification: {}
+-
+add: entryACI
+entryACI: { identificationTag "test", precedence 1, authenticationLevel none, 
+ itemOrUserFirst userFirst: { userClasses { subtree { { base "dc=example,dc=co
+ m", minimum 1, maximum 2, specificExclusions { chopBefore: "dc=example,dc=com
+ " } } }, allUsers, userGroup { "dc=example,dc=com" } }, userPermissions { { p
+ recedence 2, protectedItems { allUserAttributeTypes, attributeValue {userpass
+ word=*  }, maxImmSub 2, entry, maxValueCount {{ type userPassword, maxCount 2
+ }} }, grantsAndDenials { denyRemove, grantReturnDN, denyModify, denyAdd, deny
+ Rename, grantFilterMatch, grantBrowse, grantRead, grantCompare } } } } }
+-
+add: prescriptiveACI
+prescriptiveACI: { identificationTag "allUsersACI", precedence 10, authenticat
+ ionLevel simple, itemOrUserFirst userFirst: { userClasses { allUsers }, userP
+ ermissions { { protectedItems { allUserAttributeTypesAndValues, entry }, gran
+ tsAndDenials { grantReturnDN, grantCompare, grantRead, grantDiscloseOnError, 
+ grantFilterMatch, grantBrowse } }, { protectedItems { attributeType { userPas
+ sword } }, grantsAndDenials { denyCompare, denyRead, denyFilterMatch } } } } 
+ }
+-
diff --git a/tests/test.integration.core/src/main/resources/org/apache/directory/studio/test/integration/junit5/Fedora389ds.ldif b/tests/test.integration.core/src/main/resources/org/apache/directory/studio/test/integration/junit5/Fedora389ds.ldif
new file mode 100644
index 0000000..d8d5bd0
--- /dev/null
+++ b/tests/test.integration.core/src/main/resources/org/apache/directory/studio/test/integration/junit5/Fedora389ds.ldif
@@ -0,0 +1,50 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you 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.
+#
+
+dn: ou=misc,dc=example,dc=org
+changetype: modify
+add: aci
+aci: (targetattr="*")(version 3.0; aci "allow hnelson all access"; allow(all) userdn="ldap:///uid=hnelson,ou=misc,dc=example,dc=org";)
+-
+
+dn: cn=config
+changetype: modify
+replace: passwordStorageScheme
+passwordStorageScheme: CLEAR
+-
+replace: nsslapd-enable-upgrade-hash
+nsslapd-enable-upgrade-hash: off
+-
+
+dn: cn=Kerberos uid mapping,cn=mapping,cn=sasl,cn=config
+changetype: modify
+replace: nsSaslMapRegexString
+nsSaslMapRegexString: \(.*\)
+-
+
+dn: cn=Kerberos uid mapping,cn=mapping,cn=sasl,cn=config
+changetype: modify
+replace: nsSaslMapBaseDNTemplate
+nsSaslMapBaseDNTemplate: dc=example,dc=org
+-
+
+dn: cn=Kerberos uid mapping,cn=mapping,cn=sasl,cn=config
+changetype: modify
+replace: nsSaslMapFilterTemplate
+nsSaslMapFilterTemplate: (uid=\1)
+-
diff --git a/tests/test.integration.core/src/main/resources/org/apache/directory/studio/test/integration/junit5/OpenLdapConfig.ldif b/tests/test.integration.core/src/main/resources/org/apache/directory/studio/test/integration/junit5/OpenLdapConfig.ldif
new file mode 100644
index 0000000..a2eb4da
--- /dev/null
+++ b/tests/test.integration.core/src/main/resources/org/apache/directory/studio/test/integration/junit5/OpenLdapConfig.ldif
@@ -0,0 +1,50 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you 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.
+#
+dn: olcDatabase={-1}frontend,cn=config
+changetype: modify
+replace: olcAccess
+olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by * break
+olcAccess: {1}to dn.exact="" by * read
+# Forbid user.8 to read the schema, used in SchemaBrowserTest
+olcAccess: {2}to dn.base="cn=Subschema" by dn.exact="uid=user.8,ou=users,dc=example,dc=org" none by * read
+-
+replace: olcSizeLimit
+olcSizeLimit: 2000
+-
+
+dn: olcDatabase={1}mdb,cn=config
+changetype: modify
+replace: olcAccess
+olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by * break
+olcAccess: {1}to attrs=userPassword,shadowLastChange by self write by dn="cn=admin,dc=example,dc=org" write by dn="uid=hnelson,cn=gssapi,cn=auth" write by anonymous auth by * none
+olcAccess: {2}to * by self read by dn="cn=admin,dc=example,dc=org" write by dn="uid=hnelson,cn=gssapi,cn=auth" write by anonymous auth by * none
+-
+
+dn: cn=config
+changetype: modify
+replace: olcAuthzRegexp
+olcAuthzRegexp: uid=([^,]*),cn=digest-md5,cn=auth uid=$1,ou=users,dc=example,dc=org
+olcAuthzRegexp: uid=([^,]*),cn=cram-md5,cn=auth uid=$1,ou=users,dc=example,dc=org
+-
+replace: olcSaslSecProps
+olcSaslSecProps: noplain,noanonymous,minssf=0
+-
+replace: olcTLSCipherSuite
+olcTLSCipherSuite: SECURE256:+SECURE128:-VERS-TLS-ALL:+VERS-TLS1.3:+VERS-TLS1.2:-RSA:-DHE-DSS:-CAMELLIA-128-CBC:-CAMELLIA-256-CBC
+-
+
diff --git a/tests/test.integration.core/src/main/resources/org/apache/directory/studio/test/integration/junit5/TestFixture.ldif b/tests/test.integration.core/src/main/resources/org/apache/directory/studio/test/integration/junit5/TestFixture.ldif
new file mode 100644
index 0000000..8b18c6d
--- /dev/null
+++ b/tests/test.integration.core/src/main/resources/org/apache/directory/studio/test/integration/junit5/TestFixture.ldif
@@ -0,0 +1,460 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you 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.
+#
+
+#
+# ou=misc
+# Entries for specific test scenarios. Other tests should not rely on the number or structure of this ou.
+# Add here new specific entries for specific test scenarios.
+#
+
+dn: ou=misc,dc=example,dc=org
+objectClass: top
+objectClass: organizationalUnit
+ou: misc
+
+dn: cn=Barbara Jensen,ou=misc,dc=example,dc=org
+objectClass: inetOrgPerson
+objectClass: organizationalPerson
+objectClass: person
+objectClass: top
+cn: Barbara Jensen
+sn: Jensen
+givenName: Barbara
+uid: bjensen
+
+dn: uid=hnelson,ou=misc,dc=example,dc=org
+objectClass: inetOrgPerson
+objectClass: organizationalPerson
+objectClass: person
+objectClass: top
+objectClass: extensibleObject
+cn: Horatio Nelson
+sn: Nelson
+uid: hnelson
+description:: QSDDqSDigqwg0K8gzrsg16kg2Lkg4ruhIA==
+userPassword:: e1NTSEE1MTJ9aUlyTG1uR0MxdTNaTGFPWmRvSjZUMjBKdG9XQ05wWjArWGFLRnN
+ 5bEVEdFpYK3I3bUZrcjRwYTNKMXE3VWpSZ3ZFV2lCd1FNUjZadjBoYnRsYnRqSTQ2TmR6WVRDdG9G
+jpegPhoto:: /9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw
+ 8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRw
+ hMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAAB
+ AAEDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEA
+ wUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKS
+ o0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqK
+ jpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QA
+ HwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEB
+ SExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSE
+ lKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba
+ 3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3+iii
+ gD//2Q==
+userSMIMECertificate:: AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJyg
+ pKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFi
+ Y2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbn
+ J2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1d
+ bX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==
+userSMIMECertificate:: AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJyg
+ pKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFi
+ Y2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbn
+ J2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1d
+ bX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/wA=
+userSMIMECertificate:: AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJyg
+ pKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFi
+ Y2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbn
+ J2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1d
+ bX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+
+
+dn:: Y249V29sZmdhbmcgS8O2bGJlbCxvdT1taXNjLGRjPWV4YW1wbGUsZGM9b3Jn
+objectClass: person
+objectClass: organizationalPerson
+objectClass: inetOrgPerson
+objectClass: top
+cn:: V29sZmdhbmcgS8O2bGJlbA==
+sn:: S8O2bGJlbA==
+description: =1+1
+
+# Multi-valued RDN
+dn: cn=Barbara Jensen+uid=bjensen,ou=misc,dc=example,dc=org
+objectClass: inetOrgPerson
+objectClass: organizationalPerson
+objectClass: person
+objectClass: top
+cn: Barbara Jensen
+sn: Jensen
+givenName: Barbara
+uid: bjensen
+
+# DN with escaped characters: '"', '+', ',', ';', '<', '>',  or '\'
+dn: cn=\"\+\,\;\<\>\\,ou=misc,dc=example,dc=org
+objectClass: inetOrgPerson
+objectClass: organizationalPerson
+objectClass: person
+objectClass: top
+cn: "+,;<>\
+sn: "+,;<>\
+
+# DN with leading sharp/hash/pound/number sign
+dn: cn=\#123456,ou=misc,dc=example,dc=org
+objectClass: inetOrgPerson
+objectClass: organizationalPerson
+objectClass: person
+objectClass: top
+cn: #123456
+sn: #123456
+givenName: #123456
+uid: #123456
+
+# DN with trailing equals character =
+dn: cn=trailing=,ou=misc,dc=example,dc=org
+objectClass: top
+objectClass: person
+cn: trailing=
+sn: trailing=
+
+# Multi-valued RDN with IP address
+dn: cn=loopback+ipHostNumber=127.0.0.1,ou=misc,dc=example,dc=org
+objectClass: top
+objectClass: device
+objectClass: ipHost
+cn: loopback
+ipHostNumber: 127.0.0.1
+
+dn: ou=misc.1,ou=misc,dc=example,dc=org
+objectClass: top
+objectClass: organizationalUnit
+ou: misc.1
+
+dn: cn=alias,ou=misc,dc=example,dc=org
+objectClass: alias
+objectClass: top
+objectClass: extensibleObject
+cn: alias
+aliasedObjectName: ou=misc,dc=example,dc=org
+
+dn: ou=misc.1.1,ou=misc.1,ou=misc,dc=example,dc=org
+objectClass: top
+objectClass: organizationalUnit
+ou: misc.1.1
+
+dn: ou=misc.1.1.1,ou=misc.1.1,ou=misc.1,ou=misc,dc=example,dc=org
+objectClass: top
+objectClass: organizationalUnit
+ou: misc.1.1.1
+
+
+#
+# ou=users
+# Fixed number of users used by severals search tests that expect a fixed entry set.
+# Avoid add or modify those entries if not required as many tests need to be adjusted otherwise.
+#
+
+dn: ou=users,dc=example,dc=org
+objectClass: top
+objectClass: organizationalUnit
+ou: users
+
+dn: uid=user.1,ou=users,dc=example,dc=org
+objectClass: top
+objectClass: person
+objectClass: organizationalPerson
+objectClass: inetOrgPerson
+givenName: Aaccf
+sn: Amar
+cn: Aaccf Amar
+initials: AA
+uid: user.1
+mail: user.1@null
+userPassword: password
+telephoneNumber: 976-893-3312
+homePhone: 337-310-0727
+pager: 185-156-4071
+mobile: 626-188-0934
+employeeNumber: 1
+street: 27919 Broadway Street
+l: Tallahassee
+st: DE
+postalCode: 67698
+postalAddress: Aaccf Amar$27919 Broadway Street$Tallahassee, DE  67698
+description: This is the description for Aaccf Amar.
+roomNumber: 1388
+
+dn: uid=user.2,ou=users,dc=example,dc=org
+objectClass: top
+objectClass: person
+objectClass: organizationalPerson
+objectClass: inetOrgPerson
+givenName: Aaren
+sn: Atp
+cn: Aaren Atp
+initials: AA
+uid: user.2
+mail: user.2@null
+userPassword: password
+telephoneNumber: 147-953-0396
+homePhone: 174-439-5329
+pager: 617-443-8449
+mobile: 045-464-2512
+employeeNumber: 2
+street: 36109 Center Street
+l: Harlingen
+st: CO
+postalCode: 21733
+postalAddress: Aaren Atp$36109 Center Street$Harlingen, CO  21733
+description: This is the description for Aaren Atp.
+roomNumber: 1198
+
+dn: uid=user.3,ou=users,dc=example,dc=org
+objectClass: top
+objectClass: person
+objectClass: organizationalPerson
+objectClass: inetOrgPerson
+givenName: Aarika
+sn: Atpco
+cn: Aarika Atpco
+initials: AA
+uid: user.3
+mail: user.3@null
+userPassword: password
+telephoneNumber: 925-356-4943
+homePhone: 099-983-0308
+pager: 806-672-7363
+mobile: 425-493-8009
+employeeNumber: 3
+street: 14730 Fourteenth Street
+l: Evansville
+st: ND
+postalCode: 95526
+postalAddress: Aarika Atpco$14730 Fourteenth Street$Evansville, ND  95526
+description: This is the description for Aarika Atpco.
+roomNumber: 1135
+
+dn: uid=user.4,ou=users,dc=example,dc=org
+objectClass: top
+objectClass: person
+objectClass: organizationalPerson
+objectClass: inetOrgPerson
+givenName: Aaron
+sn: Atrc
+cn: Aaron Atrc
+initials: AA
+uid: user.4
+mail: user.4@null
+userPassword: password
+telephoneNumber: 696-981-0488
+homePhone: 854-401-1330
+pager: 389-028-9518
+mobile: 117-882-4912
+employeeNumber: 4
+street: 98495 Fifteenth Street
+l: Miami
+st: PA
+postalCode: 16887
+postalAddress: Aaron Atrc$98495 Fifteenth Street$Miami, PA  16887
+description: This is the description for Aaron Atrc.
+roomNumber: 1311
+
+dn: uid=user.5,ou=users,dc=example,dc=org
+objectClass: top
+objectClass: person
+objectClass: organizationalPerson
+objectClass: inetOrgPerson
+givenName: Aartjan
+sn: Aalders
+cn: Aartjan Aalders
+initials: AA
+uid: user.5
+mail: user.5@null
+userPassword: password
+telephoneNumber: 657-627-9753
+homePhone: 109-158-4533
+pager: 801-392-0010
+mobile: 763-973-0947
+employeeNumber: 5
+street: 52408 Ridge Street
+l: Omaha
+st: AR
+postalCode: 08015
+postalAddress: Aartjan Aalders$52408 Ridge Street$Omaha, AR  08015
+description: This is the description for Aartjan Aalders.
+roomNumber: 1090
+
+dn: uid=user.6,ou=users,dc=example,dc=org
+objectClass: top
+objectClass: person
+objectClass: organizationalPerson
+objectClass: inetOrgPerson
+givenName: Abagael
+sn: Aasen
+cn: Abagael Aasen
+initials: AA
+uid: user.6
+mail: user.6@null
+userPassword: password
+telephoneNumber: 600-556-9017
+homePhone: 543-731-7797
+pager: 349-743-6572
+mobile: 042-921-9717
+employeeNumber: 6
+street: 87514 Dogwood Street
+l: Bloomington
+st: ID
+postalCode: 56762
+postalAddress: Abagael Aasen$87514 Dogwood Street$Bloomington, ID  56762
+description: This is the description for Abagael Aasen.
+roomNumber: 1449
+
+dn: uid=user.7,ou=users,dc=example,dc=org
+objectClass: top
+objectClass: person
+objectClass: organizationalPerson
+objectClass: inetOrgPerson
+givenName: Abagail
+sn: Abadines
+cn: Abagail Abadines
+initials: AA
+uid: user.7
+mail: user.7@null
+userPassword: password
+telephoneNumber: 628-294-0713
+homePhone: 313-764-3970
+pager: 118-541-2978
+mobile: 111-360-9243
+employeeNumber: 7
+street: 60751 Main Street
+l: Macon
+st: MI
+postalCode: 38755
+postalAddress: Abagail Abadines$60751 Main Street$Macon, MI  38755
+description: This is the description for Abagail Abadines.
+roomNumber: 1312
+
+dn: uid=user.8,ou=users,dc=example,dc=org
+objectClass: top
+objectClass: person
+objectClass: organizationalPerson
+objectClass: inetOrgPerson
+givenName: Abahri
+sn: Abazari
+cn: Abahri Abazari
+initials: AA
+uid: user.8
+mail: user.8@null
+userPassword: password
+telephoneNumber: 760-373-5805
+homePhone: 856-861-3648
+pager: 271-218-0027
+mobile: 957-465-6928
+employeeNumber: 8
+street: 81023 River Street
+l: Monroe
+st: SD
+postalCode: 51865
+postalAddress: Abahri Abazari$81023 River Street$Monroe, SD  51865
+description: This is the description for Abahri Abazari.
+roomNumber: 1963
+
+#
+# ou=groups
+# Group entries
+#
+
+dn: ou=groups,dc=example,dc=org
+objectClass: organizationalUnit
+objectClass: top
+ou: groups
+
+dn: cn=group.1,ou=groups,dc=example,dc=org
+objectClass: groupOfNames
+objectClass: top
+cn: group.1
+member: uid=user.1,ou=users,dc=example,dc=org
+member: uid=user.2,ou=users,dc=example,dc=org
+member: uid=user.3,ou=users,dc=example,dc=org
+member: uid=user.4,ou=users,dc=example,dc=org
+member: uid=user.5,ou=users,dc=example,dc=org
+member: uid=user.6,ou=users,dc=example,dc=org
+member: uid=user.7,ou=users,dc=example,dc=org
+member: uid=user.8,ou=users,dc=example,dc=org
+member: cn=\#123456,ou=misc,dc=example,dc=org
+
+#
+# ou=target
+#
+
+dn: ou=target,dc=example,dc=org
+objectClass: organizationalUnit
+objectClass: top
+ou: target
+
+#
+# ou=referrals
+# Entries for referral specific test scenarios.
+#
+
+dn: ou=referrals,dc=example,dc=org
+objectClass: organizationalUnit
+objectClass: top
+ou: referrals
+
+dn: cn=referral-to-user.1,ou=referrals,dc=example,dc=org
+objectClass: top
+objectClass: referral
+objectClass: extensibleObject
+cn: referral-to-user.1
+ref: ldap://replace-with-host-port/uid=user.1,ou=users,dc=example,dc=org
+
+dn: cn=referral-to-users,ou=referrals,dc=example,dc=org
+objectClass: top
+objectClass: referral
+objectClass: extensibleObject
+cn: referral-to-users
+ref: ldap://replace-with-host-port/ou=users,dc=example,dc=org
+
+dn: cn=referral-to-referral-to-users,ou=referrals,dc=example,dc=org
+objectClass: top
+objectClass: referral
+objectClass: extensibleObject
+cn: referral-to-referral-to-users
+ref: ldap://replace-with-host-port/cn=referral-to-users,ou=referrals,dc=example,dc=org
+
+dn: cn=referral-to-referrals,ou=referrals,dc=example,dc=org
+objectClass: top
+objectClass: referral
+objectClass: extensibleObject
+cn: referral-to-referrals
+ref: ldap://replace-with-host-port/ou=referrals,dc=example,dc=org
+
+dn: cn=referral-loop-1,ou=referrals,dc=example,dc=org
+objectClass: top
+objectClass: referral
+objectClass: extensibleObject
+cn: referral-loop-1
+ref: ldap://replace-with-host-port/cn=referral-loop-2,ou=referrals,dc=example,dc=org
+
+dn: cn=referral-loop-2,ou=referrals,dc=example,dc=org
+objectClass: top
+objectClass: referral
+objectClass: extensibleObject
+cn: referral-loop-2
+ref: ldap://replace-with-host-port/cn=referral-loop-1,ou=referrals,dc=example,dc=org
+
+dn: cn=referral-to-misc,ou=referrals,dc=example,dc=org
+objectClass: top
+objectClass: referral
+objectClass: extensibleObject
+cn: referral-to-misc
+ref: ldap://replace-with-host-port/ou=misc,dc=example,dc=org
+
diff --git a/tests/test.integration.ui/pom-first.xml b/tests/test.integration.ui/pom-first.xml
index a02a02d..9e91593 100644
--- a/tests/test.integration.ui/pom-first.xml
+++ b/tests/test.integration.ui/pom-first.xml
@@ -47,12 +47,14 @@
             <Eclipse-LazyStart>true</Eclipse-LazyStart>
             <Bundle-Activator>org.apache.directory.studio.test.integration.ui.Activator</Bundle-Activator>
             
-            <Require-Bundle>org.junit;bundle-version="4.11.0",
+            <Require-Bundle>org.junit.jupiter.api;bundle-version="5.7.0",
+ org.junit.jupiter.params;bundle-version="5.7.0",
+ org.opentest4j;bundle-version="1.2.0",
  org.hamcrest.library;bundle-version="1.3.0",
- org.eclipse.swtbot.eclipse.finder;bundle-version="2.2.1",
- org.eclipse.swtbot.eclipse.core;bundle-version="2.2.1",
- org.eclipse.swtbot.forms.finder;bundle-version="2.2.1",
- org.eclipse.swtbot.junit4_x;bundle-version="2.2.1",
+ org.eclipse.swtbot.eclipse.finder;bundle-version="3.0.0",
+ org.eclipse.swtbot.eclipse.core;bundle-version="3.0.0",
+ org.eclipse.swtbot.forms.finder;bundle-version="3.0.0",
+ org.eclipse.swtbot.junit5_x;bundle-version="3.0.0",
  
  org.apache.directory.server.apacheds-test-framework;bundle-version="${org.apache.directory.server.version}",
  org.apache.directory.server.annotations;bundle-version="${org.apache.directory.server.version}",
@@ -69,6 +71,8 @@
  org.apache.directory.api.ldap.codec.core;bundle-version="${org.apache.directory.api.bundleversion}",
  org.apache.directory.api.ldap.model;bundle-version="${org.apache.directory.api.bundleversion}",
  org.apache.directory.api.ldap.net.mina;bundle-version="${org.apache.directory.api.bundleversion}",
+ org.apache.directory.api.ldap.schema;bundle-version="${org.apache.directory.api.bundleversion}",
+ org.apache.directory.api.ldap.schema.converter;bundle-version="${org.apache.directory.api.bundleversion}",
  org.apache.directory.api.util;bundle-version="${org.apache.directory.api.bundleversion}",
  org.apache.mina.core;bundle-version="${org.apache.mina.bundleversion}",
  
@@ -98,7 +102,9 @@
  org.apache.directory.studio.schemaeditor,
  org.apache.directory.studio.schemaeditor.help,
  org.apache.directory.studio.valueeditors,
+ org.apache.directory.studio.test.integration.core,
  org.eclipse.core.runtime,
+ org.eclipse.e4.ui.css.swt.theme,
  org.eclipse.ui</Require-Bundle>
             
             <Import-Package>org.apache.commons.lang3,
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/AbstractTestBase.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/AbstractTestBase.java
new file mode 100644
index 0000000..0fc7497
--- /dev/null
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/AbstractTestBase.java
@@ -0,0 +1,163 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.studio.test.integration.ui;
+
+
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.CONTEXT_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.REFERRALS_DN;
+
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.api.ldap.model.name.Rdn;
+import org.apache.directory.studio.connection.core.ConnectionCorePlugin;
+import org.apache.directory.studio.ldapbrowser.core.BrowserCoreConstants;
+import org.apache.directory.studio.ldapbrowser.core.BrowserCorePlugin;
+import org.apache.directory.studio.test.integration.junit5.SkipTestIfLdapServerIsNotAvailableInterceptor;
+import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
+import org.apache.directory.studio.test.integration.ui.bots.ApacheDSServersViewBot;
+import org.apache.directory.studio.test.integration.ui.bots.BrowserViewBot;
+import org.apache.directory.studio.test.integration.ui.bots.ConnectionsViewBot;
+import org.apache.directory.studio.test.integration.ui.bots.ModificationLogsViewBot;
+import org.apache.directory.studio.test.integration.ui.bots.SearchLogsViewBot;
+import org.apache.directory.studio.test.integration.ui.bots.StudioBot;
+import org.apache.directory.studio.test.integration.ui.utils.Assertions;
+import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
+import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable;
+import org.eclipse.swtbot.swt.finder.junit5.SWTBotJunit5Extension;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+
+@ExtendWith(
+    { SWTBotJunit5Extension.class, SkipTestIfLdapServerIsNotAvailableInterceptor.class })
+public class AbstractTestBase
+{
+
+    protected SWTWorkbenchBot bot;
+    protected StudioBot studioBot;
+    protected ConnectionsViewBot connectionsViewBot;
+    protected BrowserViewBot browserViewBot;
+    protected SearchLogsViewBot searchLogsViewBot;
+    protected ModificationLogsViewBot modificationLogsViewBot;
+    protected ApacheDSServersViewBot serversViewBot;
+
+    @BeforeEach
+    final void setUpBase() throws Exception
+    {
+        bot = new SWTWorkbenchBot();
+        studioBot = new StudioBot();
+        studioBot.resetLdapPerspective();
+        connectionsViewBot = studioBot.getConnectionView();
+        browserViewBot = studioBot.getBrowserView();
+        searchLogsViewBot = studioBot.getSearchLogsViewBot();
+        modificationLogsViewBot = studioBot.getModificationLogsViewBot();
+        serversViewBot = studioBot.getApacheDSServersViewBot();
+        UIThreadRunnable.syncExec( () -> {
+            BrowserCorePlugin.getDefault()
+                .getPluginPreferences().setValue( BrowserCoreConstants.PREFERENCE_LDIF_LINE_WIDTH, 1000 );
+        } );
+    }
+
+
+    @AfterEach
+    final void tearDownBase() throws Exception
+    {
+        // clear custom trust stores
+        X509Certificate[] permanentCertificates = ConnectionCorePlugin.getDefault().getPermanentTrustStoreManager()
+            .getCertificates();
+        for ( X509Certificate certificate : permanentCertificates )
+        {
+            ConnectionCorePlugin.getDefault().getPermanentTrustStoreManager().removeCertificate( certificate );
+        }
+        X509Certificate[] temporaryCertificates = ConnectionCorePlugin.getDefault().getSessionTrustStoreManager()
+            .getCertificates();
+        for ( X509Certificate certificate : temporaryCertificates )
+        {
+            ConnectionCorePlugin.getDefault().getSessionTrustStoreManager().removeCertificate( certificate );
+        }
+
+        connectionsViewBot.deleteTestConnections();
+        serversViewBot.deleteTestServers();
+        Assertions.genericTearDownAssertions();
+    }
+
+    public static final String[] ROOT_DSE_PATH =
+        { "DIT", "Root DSE" };
+    public static final String[] CONTEXT_PATH = path( ROOT_DSE_PATH, CONTEXT_DN.getName() );
+
+    public static String[] path( String[] parents, String leaf )
+    {
+        return ArrayUtils.addAll( parents, leaf );
+    }
+
+
+    /**
+     * Gets the path to the DN in the LDAP browser tree.
+     * The path starts with "DIT", "Root DSE", and the context entry.
+     */
+    public static String[] path( Dn dn )
+    {
+        List<String> l = new ArrayList<>();
+
+        l.addAll( Arrays.asList( CONTEXT_PATH ) );
+
+        List<Rdn> rdns = dn.getRdns();
+        for ( int i = rdns.size() - 3; i >= 0; i-- )
+        {
+            l.add( rdns.get( i ).getName() );
+        }
+
+        return l.toArray( new String[0] );
+    }
+
+
+    /**
+     * Gets the path to the RDN  below the DN in the LDAP browser tree.
+     * The path starts with "DIT", "Root DSE", and the context entry.
+     */
+    public static String[] path( Dn dn, Rdn rdn )
+    {
+        return path( dn, rdn.getName() );
+    }
+
+
+    /**
+     * Gets the path to the leaf  below the DN in the LDAP browser tree.
+     * The path starts with "DIT", "Root DSE", and the context entry.
+     */
+    public static String[] path( Dn dn, String... leaf )
+    {
+        return ArrayUtils.addAll( path( dn ), leaf );
+    }
+
+
+    public static String[] pathWithRefLdapUrl( TestLdapServer ldapServer, Dn dn )
+    {
+        String leaf = ldapServer.getLdapUrl() + "/" + dn.getName();
+        return path( REFERRALS_DN, leaf );
+    }
+
+}
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ApacheDSPluginTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ApacheDSPluginTest.java
index e6c30c6..00f419a 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ApacheDSPluginTest.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ApacheDSPluginTest.java
@@ -23,9 +23,9 @@
 
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import org.apache.directory.studio.connection.core.Connection;
 import org.apache.directory.studio.connection.core.ConnectionCorePlugin;
@@ -34,22 +34,17 @@
 import org.apache.directory.studio.connection.core.ConnectionManager;
 import org.apache.directory.studio.ldapservers.LdapServersManager;
 import org.apache.directory.studio.test.integration.ui.bots.ApacheDSConfigurationEditorBot;
-import org.apache.directory.studio.test.integration.ui.bots.ApacheDSServersViewBot;
 import org.apache.directory.studio.test.integration.ui.bots.BotUtils;
 import org.apache.directory.studio.test.integration.ui.bots.ConnectionFromServerDialogBot;
-import org.apache.directory.studio.test.integration.ui.bots.ConnectionsViewBot;
 import org.apache.directory.studio.test.integration.ui.bots.ConsoleViewBot;
 import org.apache.directory.studio.test.integration.ui.bots.DeleteDialogBot;
 import org.apache.directory.studio.test.integration.ui.bots.ModificationLogsViewBot;
 import org.apache.directory.studio.test.integration.ui.bots.NewApacheDSServerWizardBot;
-import org.apache.directory.studio.test.integration.ui.bots.StudioBot;
-import org.apache.directory.studio.test.integration.ui.bots.utils.Assertions;
-import org.apache.directory.studio.test.integration.ui.bots.utils.FrameworkRunnerWithScreenshotCaptureListener;
 import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledForJreRange;
+import org.junit.jupiter.api.condition.JRE;
 
 
 /**
@@ -58,35 +53,18 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-@RunWith(FrameworkRunnerWithScreenshotCaptureListener.class)
-public class ApacheDSPluginTest
+@DisabledForJreRange(min = JRE.JAVA_16)
+public class ApacheDSPluginTest extends AbstractTestBase
 {
-    private StudioBot studioBot;
-    private ApacheDSServersViewBot serversViewBot;
-    private ConnectionsViewBot connectionsViewBot;
-    private ConsoleViewBot consoleViewBot;
+    protected ConsoleViewBot consoleViewBot;
 
-
-    @Before
-    public void setUp() throws Exception
+    @BeforeEach
+    void setUp() throws Exception
     {
-        studioBot = new StudioBot();
-        studioBot.resetLdapPerspective();
-        serversViewBot = studioBot.getApacheDSServersViewBot();
-        connectionsViewBot = studioBot.getConnectionView();
         consoleViewBot = studioBot.getConsoleView();
     }
 
 
-    @After
-    public void tearDown() throws Exception
-    {
-        connectionsViewBot.deleteTestConnections();
-        serversViewBot.deleteTestServers();
-        Assertions.genericTearDownAssertions();
-    }
-
-
     /**
      * Run the following tests:
      * <ul>
@@ -124,7 +102,7 @@
         assertEquals( 1, getBrowserConnectionsCount() );
 
         // Opening the connection
-        connectionsViewBot.selectConnection( serverName );
+        connectionsViewBot.select( serverName );
         connectionsViewBot.openSelectedConnection();
 
         // Getting the associated connection object
@@ -134,7 +112,7 @@
         assertTrue( connection.getConnectionWrapper().isConnected() );
 
         // Closing the connection
-        connectionsViewBot.selectConnection( serverName );
+        connectionsViewBot.select( serverName );
         connectionsViewBot.closeSelectedConnections();
 
         // Checking if the connection is closed
@@ -350,7 +328,7 @@
         connectionFromServerDialogBot.clickOkButton();
 
         // Open the connection
-        connectionsViewBot.selectConnection( serverName );
+        connectionsViewBot.select( serverName );
         connectionsViewBot.openSelectedConnection();
 
         // Open the config editor and load remote config
@@ -389,7 +367,7 @@
         localEditorBot.close();
 
         // Close the connection
-        connectionsViewBot.selectConnection( serverName );
+        connectionsViewBot.select( serverName );
         connectionsViewBot.closeSelectedConnections();
 
         // Delete the connection
@@ -417,7 +395,7 @@
 
         // Repair the server
         serversViewBot.repairServer( serverName );
-        consoleViewBot.waitForConsoleText("Database repaired");
+        consoleViewBot.waitForConsoleText( "Database repaired" );
         serversViewBot.waitForServerStop( serverName );
 
         // Wait a bit more after repair, another weird race condition...
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/AutomatedSuite.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/AutomatedSuite.java
deleted file mode 100644
index b92f34b..0000000
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/AutomatedSuite.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you 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.apache.directory.studio.test.integration.ui;
-
-
-import org.eclipse.jface.dialogs.ErrorDialog;
-import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences;
-import org.junit.runner.RunWith;
-import org.junit.runners.Suite;
-
-
-/**
- * Test suite.
- *
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- * @version $Rev$, $Date$
- */
-@RunWith(Suite.class)
-@Suite.SuiteClasses(
-    { BrowserTest.class, EntryEditorTest.class, ImportExportTest.class, NewConnectionWizardTest.class,
-        NewEntryWizardTest.class, PreferencesTest.class, ReferralDialogTest.class, RenameEntryTest.class,
-        SearchTest.class })
-public class AutomatedSuite
-{
-    static
-    {
-        ErrorDialog.AUTOMATED_MODE = false;
-        SWTBotPreferences.PLAYBACK_DELAY = 50;
-    }
-
-}
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/BrowserTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/BrowserTest.java
index 44234b0..615173f 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/BrowserTest.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/BrowserTest.java
@@ -21,11 +21,26 @@
 package org.apache.directory.studio.test.integration.ui;
 
 
-import static org.apache.directory.studio.test.integration.ui.Constants.LOCALHOST;
-import static org.apache.directory.studio.test.integration.ui.Constants.LOCALHOST_ADDRESS;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.ALIAS_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.CONTEXT_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.DN_WITH_ESCAPED_CHARACTERS_BACKSLASH_PREFIXED;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.DN_WITH_ESCAPED_CHARACTERS_HEX_PAIR_ESCAPED;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.DN_WITH_IP_HOST_NUMBER;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.DN_WITH_LEADING_SHARP_BACKSLASH_PREFIXED;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.DN_WITH_LEADING_SHARP_HEX_PAIR_ESCAPED;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.DN_WITH_TRAILING_EQUALS_CHARACTER;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.DN_WITH_TRAILING_EQUALS_CHARACTER_HEX_PAIR_ESCAPED;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.MISC_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.MULTI_VALUED_RDN_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.REFERRAL_TO_USERS_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USER1_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USER2_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USER3_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USERS_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.dn;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.util.List;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -34,10 +49,6 @@
 import org.apache.directory.api.ldap.model.entry.DefaultEntry;
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.name.Dn;
-import org.apache.directory.server.annotations.CreateLdapServer;
-import org.apache.directory.server.annotations.CreateTransport;
-import org.apache.directory.server.core.annotations.ApplyLdifFiles;
-import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
 import org.apache.directory.studio.connection.core.Connection;
 import org.apache.directory.studio.connection.core.Connection.AliasDereferencingMethod;
 import org.apache.directory.studio.connection.core.Connection.ReferralHandlingMethod;
@@ -49,29 +60,21 @@
 import org.apache.directory.studio.ldapbrowser.ui.BrowserUIConstants;
 import org.apache.directory.studio.ldapbrowser.ui.BrowserUIPlugin;
 import org.apache.directory.studio.ldapbrowser.ui.editors.entry.EntryEditor;
-import org.apache.directory.studio.test.integration.ui.bots.BrowserViewBot;
-import org.apache.directory.studio.test.integration.ui.bots.ConnectionsViewBot;
+import org.apache.directory.studio.test.integration.junit5.LdapServerType;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource.Mode;
+import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
 import org.apache.directory.studio.test.integration.ui.bots.DeleteDialogBot;
 import org.apache.directory.studio.test.integration.ui.bots.EntryEditorBot;
-import org.apache.directory.studio.test.integration.ui.bots.ModificationLogsViewBot;
 import org.apache.directory.studio.test.integration.ui.bots.ReferralDialogBot;
-import org.apache.directory.studio.test.integration.ui.bots.SearchLogsViewBot;
-import org.apache.directory.studio.test.integration.ui.bots.StudioBot;
-import org.apache.directory.studio.test.integration.ui.bots.utils.Assertions;
-import org.apache.directory.studio.test.integration.ui.bots.utils.FrameworkRunnerWithScreenshotCaptureListener;
-import org.apache.directory.studio.test.integration.ui.bots.utils.JobWatcher;
-import org.apache.directory.studio.test.integration.ui.bots.utils.StudioSystemUtils;
+import org.apache.directory.studio.test.integration.ui.utils.JobWatcher;
 import org.eclipse.jface.dialogs.ErrorDialog;
 import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable;
 import org.eclipse.swtbot.swt.finder.results.VoidResult;
 import org.eclipse.ui.IEditorPart;
 import org.eclipse.ui.IPropertyListener;
 import org.eclipse.ui.PlatformUI;
-import org.junit.After;
-import org.junit.Assume;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.params.ParameterizedTest;
 
 
 /**
@@ -80,70 +83,37 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-@RunWith(FrameworkRunnerWithScreenshotCaptureListener.class)
-@CreateLdapServer(transports =
-    { @CreateTransport(protocol = "LDAP") })
-@ApplyLdifFiles(clazz = BrowserTest.class, value = "org/apache/directory/studio/test/integration/ui/BrowserTest.ldif")
-public class BrowserTest extends AbstractLdapTestUnit
+public class BrowserTest extends AbstractTestBase
 {
-    private StudioBot studioBot;
-    private ConnectionsViewBot connectionsViewBot;
-    private BrowserViewBot browserViewBot;
-    private SearchLogsViewBot searchLogsViewBot;
-    private ModificationLogsViewBot modificationLogsViewBot;
-
-    private Connection connection;
-
-
-    @Before
-    public void setUp() throws Exception
-    {
-        studioBot = new StudioBot();
-        studioBot.resetLdapPerspective();
-        connectionsViewBot = studioBot.getConnectionView();
-        connection = connectionsViewBot.createTestConnection( "BrowserTest", ldapServer.getPort() );
-        browserViewBot = studioBot.getBrowserView();
-        searchLogsViewBot = studioBot.getSearchLogsViewBot();
-        modificationLogsViewBot = studioBot.getModificationLogsViewBot();
-    }
-
-
-    @After
-    public void tearDown() throws Exception
-    {
-        connectionsViewBot.deleteTestConnections();
-        Assertions.genericTearDownAssertions();
-    }
-
 
     /**
      * Test for DIRSTUDIO-463.
      *
      * When expanding an entry in the browser only one search request
      * should be send to the server
-     *
-     * @throws Exception
      */
-    @Test
-    public void testOnlyOneSearchRequestWhenExpandingEntry() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testOnlyOneSearchRequestWhenExpandingEntry( TestLdapServer server ) throws Exception
     {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system" );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( CONTEXT_DN ) );
 
         // get number of search requests before expanding the entry
         String text = searchLogsViewBot.getSearchLogsText();
         int countMatchesBefore = StringUtils.countMatches( text, "#!SEARCH REQUEST" );
 
         // expand
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system" );
-        browserViewBot.waitForEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
+        browserViewBot.expandEntry( path( CONTEXT_DN ) );
+        browserViewBot.waitForEntry( path( USERS_DN ) );
 
         // get number of search requests after expanding the entry
         text = searchLogsViewBot.getSearchLogsText();
         int countMatchesAfter = StringUtils.countMatches( text, "#!SEARCH REQUEST" );
 
-        assertEquals( "Expected exactly 1 search request", 1, countMatchesAfter - countMatchesBefore );
+        assertEquals( 1, countMatchesAfter - countMatchesBefore, "Expected exactly 1 search request" );
 
-        assertEquals( "No modification expected", "", modificationLogsViewBot.getModificationLogsText() );
+        assertEquals( "", modificationLogsViewBot.getModificationLogsText(), "No modification expected" );
     }
 
 
@@ -151,14 +121,14 @@
      * Test for DIRSTUDIO-512.
      *
      * Verify minimum UI updates when deleting multiple entries.
-     *
-     * @throws Exception
      */
-    @Test
-    public void testDeleteDontUpdateUI() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testDeleteDoesNotUpdateUI( TestLdapServer server ) throws Exception
     {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( USERS_DN ) );
+        browserViewBot.expandEntry( path( USERS_DN ) );
 
         long fireCount0 = EventRegistry.getFireCount();
 
@@ -173,16 +143,16 @@
                 "uid=user.6",
                 "uid=user.7",
                 "uid=user.8" };
-        browserViewBot.selectChildrenOfEntry( children, "DIT", "Root DSE", "ou=system", "ou=users" );
+        browserViewBot.selectChildrenOfEntry( children, path( USERS_DN ) );
         DeleteDialogBot deleteDialog = browserViewBot.openDeleteDialog();
         deleteDialog.clickOkButton();
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
+        browserViewBot.selectEntry( path( USERS_DN ) );
 
         long fireCount1 = EventRegistry.getFireCount();
 
         // verify that only two events were fired during deletion
         long fireCount = fireCount1 - fireCount0;
-        assertEquals( "Only 2 event firings expected when deleting multiple entries.", 2, fireCount );
+        assertEquals( 2, fireCount, "Only 2 event firings expected when deleting multiple entries." );
     }
 
 
@@ -191,30 +161,30 @@
      *
      * When opening a bookmark the entry editor should be opened and the
      * bookmark entry's attributes should be displayed.
-     *
-     * @throws Exception
      */
-    @Test
-    public void testBookmark() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testBookmark( TestLdapServer server ) throws Exception
     {
         // create a bookmark
+        Connection connection = connectionsViewBot.createTestConnection( server );
         IBrowserConnection browserConnection = BrowserCorePlugin.getDefault().getConnectionManager()
             .getBrowserConnection( connection );
         browserConnection.getBookmarkManager().addBookmark(
-            new Bookmark( browserConnection, new Dn( "uid=user.1,ou=users,ou=system" ), "Existing Bookmark" ) );
+            new Bookmark( browserConnection, USER1_DN, "Existing Bookmark" ) );
 
         // select the bookmark
         browserViewBot.selectEntry( "Bookmarks", "Existing Bookmark" );
 
         // check that entry editor was opened and attributes are visible
-        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( "uid=user.1,ou=users,ou=system" );
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( USER1_DN.getName() );
         String dn = entryEditorBot.getDnText();
-        assertEquals( "DN: uid=user.1,ou=users,ou=system", dn );
+        assertEquals( "DN: " + USER1_DN.getName(), dn );
         List<String> attributeValues = entryEditorBot.getAttributeValues();
         assertEquals( 23, attributeValues.size() );
         assertTrue( attributeValues.contains( "uid: user.1" ) );
 
-        assertEquals( "No modification expected", "", modificationLogsViewBot.getModificationLogsText() );
+        assertEquals( "", modificationLogsViewBot.getModificationLogsText(), "No modification expected" );
     }
 
 
@@ -222,49 +192,54 @@
      * Test for DIRSTUDIO-481.
      *
      * Check proper operation of refresh action.
-     *
-     * @throws Exception
      */
-    @Test
-    public void testRefreshParent() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testRefreshParent( TestLdapServer server ) throws Exception
     {
         // check the entry doesn't exist yet
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=refresh" ) );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.expandEntry( path( MISC_DN ) );
+        Dn refreshDn = dn( "cn=refresh", MISC_DN );
+        assertFalse( browserViewBot.existsEntry( path( refreshDn ) ) );
 
         // add the entry directly in the server
-        Entry entry = new DefaultEntry( service.getSchemaManager() );
-        entry.setDn( new Dn( "cn=refresh,ou=users,ou=system" ) );
-        entry.add( "objectClass", "top", "person" );
-        entry.add( "cn", "refresh" );
-        entry.add( "sn", "refresh" );
-        ldapServer.getDirectoryService().getAdminSession().add( entry );
+        server.withAdminConnection( conn -> {
+            Entry entry = new DefaultEntry( conn.getSchemaManager() );
+            entry.setDn( refreshDn );
+            entry.add( "objectClass", "top", "person" );
+            entry.add( "cn", "refresh" );
+            entry.add( "sn", "refresh" );
+            conn.add( entry );
+        } );
 
         // check the entry still isn't visible in the tree
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=refresh" ) );
+        assertFalse( browserViewBot.existsEntry( path( refreshDn ) ) );
 
         // refresh parent
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
+        browserViewBot.selectEntry( path( MISC_DN ) );
         browserViewBot.refresh();
 
         // check the entry exists now
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=refresh" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=refresh" );
+        browserViewBot.expandEntry( path( MISC_DN ) );
+        assertTrue( browserViewBot.existsEntry( path( refreshDn ) ) );
+        browserViewBot.selectEntry( path( refreshDn ) );
 
         // delete the entry directly in the server
-        ldapServer.getDirectoryService().getAdminSession().delete( new Dn( "cn=refresh,ou=users,ou=system" ) );
+        server.withAdminConnection( conn -> {
+            conn.delete( refreshDn );
+        } );
 
-        // check the entry still is now visible in the tree
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=refresh" ) );
+        // check the entry still is visible in the tree
+        assertTrue( browserViewBot.existsEntry( path( refreshDn ) ) );
 
         // refresh parent
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
+        browserViewBot.selectEntry( path( MISC_DN ) );
         browserViewBot.refresh();
 
         // check the entry doesn't exist now
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=refresh" ) );
+        browserViewBot.expandEntry( path( MISC_DN ) );
+        assertFalse( browserViewBot.existsEntry( path( refreshDn ) ) );
     }
 
 
@@ -275,46 +250,53 @@
      *
      * @throws Exception
      */
-    @Test
-    public void testRefreshContextEntry() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testRefreshContextEntry( TestLdapServer server ) throws Exception
     {
         // check the entry doesn't exist yet
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=refresh" ) );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.expandEntry( path( MISC_DN ) );
+        Dn refreshDn = dn( "cn=refresh", MISC_DN );
+        assertFalse( browserViewBot.existsEntry( path( refreshDn ) ) );
 
         // add the entry directly in the server
-        Entry entry = new DefaultEntry( service.getSchemaManager() );
-        entry.setDn( new Dn( "cn=refresh,ou=users,ou=system" ) );
-        entry.add( "objectClass", "top", "person" );
-        entry.add( "cn", "refresh" );
-        entry.add( "sn", "refresh" );
-        ldapServer.getDirectoryService().getAdminSession().add( entry );
+        server.withAdminConnection( conn -> {
+            Entry entry = new DefaultEntry( conn.getSchemaManager() );
+            entry.setDn( refreshDn );
+            entry.add( "objectClass", "top", "person" );
+            entry.add( "cn", "refresh" );
+            entry.add( "sn", "refresh" );
+            conn.add( entry );
+        } );
 
         // check the entry still isn't visible in the tree
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=refresh" ) );
+        assertFalse( browserViewBot.existsEntry( path( refreshDn ) ) );
 
         // refresh context entry
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system" );
+        browserViewBot.selectEntry( path( CONTEXT_DN ) );
         browserViewBot.refresh();
 
         // check the entry exists now
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=refresh" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=refresh" );
+        browserViewBot.expandEntry( path( MISC_DN ) );
+        assertTrue( browserViewBot.existsEntry( path( refreshDn ) ) );
+        browserViewBot.selectEntry( path( refreshDn ) );
 
         // delete the entry directly in the server
-        ldapServer.getDirectoryService().getAdminSession().delete( new Dn( "cn=refresh,ou=users,ou=system" ) );
+        server.withAdminConnection( connection -> {
+            connection.delete( refreshDn );
+        } );
 
-        // check the entry still is now visible in the tree
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=refresh" ) );
+        // check the entry still is visible in the tree
+        assertTrue( browserViewBot.existsEntry( path( refreshDn ) ) );
 
         // refresh context entry
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system" );
+        browserViewBot.selectEntry( path( CONTEXT_DN ) );
         browserViewBot.refresh();
 
         // check the entry doesn't exist now
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=refresh" ) );
+        browserViewBot.expandEntry( path( MISC_DN ) );
+        assertFalse( browserViewBot.existsEntry( path( refreshDn ) ) );
     }
 
 
@@ -322,49 +304,54 @@
      * Test for DIRSTUDIO-481.
      *
      * Check proper operation of refresh action.
-     *
-     * @throws Exception
      */
-    @Test
-    public void testRefreshRootDSE() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testRefreshRootDSE( TestLdapServer server ) throws Exception
     {
         // check the entry doesn't exist yet
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=refresh" ) );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.expandEntry( path( MISC_DN ) );
+        Dn refreshDn = dn( "cn=refresh", MISC_DN );
+        assertFalse( browserViewBot.existsEntry( path( refreshDn ) ) );
 
         // add the entry directly in the server
-        Entry entry = new DefaultEntry( service.getSchemaManager() );
-        entry.setDn( new Dn( "cn=refresh,ou=users,ou=system" ) );
-        entry.add( "objectClass", "top", "person" );
-        entry.add( "cn", "refresh" );
-        entry.add( "sn", "refresh" );
-        ldapServer.getDirectoryService().getAdminSession().add( entry );
+        server.withAdminConnection( connection -> {
+            Entry entry = new DefaultEntry( connection.getSchemaManager() );
+            entry.setDn( refreshDn );
+            entry.add( "objectClass", "top", "person" );
+            entry.add( "cn", "refresh" );
+            entry.add( "sn", "refresh" );
+            connection.add( entry );
+        } );
 
         // check the entry still isn't visible in the tree
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=refresh" ) );
+        assertFalse( browserViewBot.existsEntry( path( refreshDn ) ) );
 
         // refresh Root DSE
-        browserViewBot.selectEntry( "DIT", "Root DSE" );
+        browserViewBot.selectEntry( ROOT_DSE_PATH );
         browserViewBot.refresh();
 
         // check the entry exists now
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=refresh" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=refresh" );
+        browserViewBot.expandEntry( path( MISC_DN ) );
+        assertTrue( browserViewBot.existsEntry( path( refreshDn ) ) );
+        browserViewBot.selectEntry( path( refreshDn ) );
 
         // delete the entry directly in the server
-        ldapServer.getDirectoryService().getAdminSession().delete( new Dn( "cn=refresh,ou=users,ou=system" ) );
+        server.withAdminConnection( connection -> {
+            connection.delete( refreshDn );
+        } );
 
         // check the entry still is now visible in the tree
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=refresh" ) );
+        assertTrue( browserViewBot.existsEntry( path( refreshDn ) ) );
 
         // refresh Root DSE
-        browserViewBot.selectEntry( "DIT", "Root DSE" );
+        browserViewBot.selectEntry( ROOT_DSE_PATH );
         browserViewBot.refresh();
 
         // check the entry doesn't exist now
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=refresh" ) );
+        browserViewBot.expandEntry( path( MISC_DN ) );
+        assertFalse( browserViewBot.existsEntry( path( refreshDn ) ) );
     }
 
 
@@ -372,116 +359,162 @@
      * Test for DIRSTUDIO-481.
      *
      * Check proper operation of refresh action.
-     *
-     * @throws Exception
      */
-    @Test
-    public void testRefreshSearchContinuation() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testRefreshSearchContinuation( TestLdapServer server ) throws Exception
     {
-        // preparation: add referral entry and set referral handling
-        String url = "ldap://" + LOCALHOST + ":" + ldapServer.getPort() + "/ou=users,ou=system";
-        Entry refEntry = new DefaultEntry( service.getSchemaManager() );
-        refEntry.setDn( new Dn( "cn=referral,ou=system" ) );
-        refEntry.add( "objectClass", "top", "referral", "extensibleObject" );
-        refEntry.add( "cn", "referral" );
-        refEntry.add( "ref", url );
-        ldapServer.getDirectoryService().getAdminSession().add( refEntry );
+        Connection connection = connectionsViewBot.createTestConnection( server );
+        Dn refreshDn = dn( "cn=refresh", MISC_DN );
+        String[] pathToReferral = pathWithRefLdapUrl( server, MISC_DN );
+        String[] pathToRefreshViaReferral = path( pathToReferral, "cn=refresh" );
         connection.getConnectionParameter().setExtendedIntProperty(
             IBrowserConnection.CONNECTION_PARAMETER_REFERRALS_HANDLING_METHOD,
             ReferralHandlingMethod.FOLLOW_MANUALLY.ordinal() );
-        browserViewBot.selectEntry( "DIT", "Root DSE" );
+        browserViewBot.selectEntry( ROOT_DSE_PATH );
         browserViewBot.refresh();
 
         // check the entry doesn't exist yet
-        ReferralDialogBot refDialog = browserViewBot.expandEntryExpectingReferralDialog( "DIT", "Root DSE",
-            "ou=system", url );
+        ReferralDialogBot refDialog = browserViewBot.expandEntryExpectingReferralDialog( pathToReferral );
         refDialog.clickOkButton();
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", url, "cn=refresh" ) );
+        assertFalse( browserViewBot.existsEntry( pathToRefreshViaReferral ) );
 
         // add the entry directly in the server
-        Entry entry = new DefaultEntry( service.getSchemaManager() );
-        entry.setDn( new Dn( "cn=refresh,ou=users,ou=system" ) );
-        entry.add( "objectClass", "top", "person" );
-        entry.add( "cn", "refresh" );
-        entry.add( "sn", "refresh" );
-        ldapServer.getDirectoryService().getAdminSession().add( entry );
+        server.withAdminConnection( conn -> {
+            Entry entry = new DefaultEntry( conn.getSchemaManager() );
+            entry.setDn( refreshDn );
+            entry.add( "objectClass", "top", "person" );
+            entry.add( "cn", "refresh" );
+            entry.add( "sn", "refresh" );
+            conn.add( entry );
+        } );
 
         // check the entry still isn't visible in the tree
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", url, "cn=refresh" ) );
+        assertFalse( browserViewBot.existsEntry( pathToRefreshViaReferral ) );
 
         // refresh search continuation
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", url );
+        browserViewBot.selectEntry( pathToReferral );
         browserViewBot.refresh();
 
         // check the entry exists now
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", url );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", url, "cn=refresh" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", url, "cn=refresh" );
+        browserViewBot.expandEntry( pathToReferral );
+        assertTrue( browserViewBot.existsEntry( pathToRefreshViaReferral ) );
+        browserViewBot.selectEntry( pathToRefreshViaReferral );
 
         // delete the entry directly in the server
-        ldapServer.getDirectoryService().getAdminSession().delete( new Dn( "cn=refresh,ou=users,ou=system" ) );
+        server.withAdminConnection( conn -> {
+            conn.delete( refreshDn );
+        } );
 
-        // check the entry still is now visible in the tree
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", url, "cn=refresh" ) );
+        // check the entry still is visible in the tree
+        assertTrue( browserViewBot.existsEntry( pathToRefreshViaReferral ) );
 
         // refresh search continuation
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", url );
+        browserViewBot.selectEntry( pathToReferral );
         browserViewBot.refresh();
 
         // check the entry doesn't exist now
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", url );
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", url, "cn=refresh" ) );
+        browserViewBot.expandEntry( pathToReferral );
+        assertFalse( browserViewBot.existsEntry( pathToRefreshViaReferral ) );
     }
 
 
     /**
      * Test for DIRSTUDIO-591.
      * (Error reading objects with # in DN)
-     *
-     * @throws Exception
      */
-    @Test
-    public void testBrowseDnWithSharpAndHexSequence() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testBrowseDnWithSharpAndHexSequence( TestLdapServer server ) throws Exception
     {
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "cn=\\#ACL_AD-Projects_Author" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=\\#ACL_AD-Projects_Author" );
+        Dn dn = DN_WITH_LEADING_SHARP_BACKSLASH_PREFIXED;
+        if ( server.getType() == LdapServerType.OpenLdap || server.getType() == LdapServerType.Fedora389ds )
+        {
+            dn = DN_WITH_LEADING_SHARP_HEX_PAIR_ESCAPED;
+        }
 
-        assertEquals( "No modification expected", "", modificationLogsViewBot.getModificationLogsText() );
+        connectionsViewBot.createTestConnection( server );
+        assertTrue( browserViewBot.existsEntry( path( dn ) ) );
+        browserViewBot.selectEntry( path( dn ) );
+
+        assertEquals( "", modificationLogsViewBot.getModificationLogsText(), "No modification expected" );
     }
 
 
     /**
      * Test for DIRSTUDIO-1172: Studio doesn't display entries with trailing =.
      */
-    @Test
-    public void testBrowseDnWithTrailingEqualsCharacter() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testBrowseDnWithTrailingEqualsCharacter( TestLdapServer server ) throws Exception
     {
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "cn=nghZwwtHgxgyvVbTQCYyeY\\+O4cc=" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=nghZwwtHgxgyvVbTQCYyeY\\+O4cc=" );
+        Dn dn = DN_WITH_TRAILING_EQUALS_CHARACTER;
+        if ( server.getType() == LdapServerType.OpenLdap )
+        {
+            dn = DN_WITH_TRAILING_EQUALS_CHARACTER_HEX_PAIR_ESCAPED;
+        }
 
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "cn=nghZwwtHgxgyvVbTQCYyeY+email=" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=nghZwwtHgxgyvVbTQCYyeY+email=" );
+        connectionsViewBot.createTestConnection( server );
+
+        assertTrue( browserViewBot.existsEntry( path( dn ) ) );
+        browserViewBot.selectEntry( path( dn ) );
+    }
+
+
+    /**
+     * Test for DIRSTUDIO-1172: Studio doesn't display entries with trailing =.
+     */
+    @ParameterizedTest
+    @LdapServersSource(except =
+        {
+            LdapServerType.OpenLdap,
+            LdapServerType.Fedora389ds }, reason = "Empty RDN value is not supported by OpenLDAP and 389ds")
+    public void testBrowseDnWithEmptyRdnValue( TestLdapServer server ) throws Exception
+    {
+
+        Dn dn = dn( "cn=nghZwwtHgxgyvVbTQCYyeY+email=", MISC_DN );
+
+        server.withAdminConnection( connection -> {
+            Entry entry = new DefaultEntry( connection.getSchemaManager() );
+            entry.setDn( dn );
+            entry.add( "objectClass", "top", "person", "extensibleObject" );
+            entry.add( "cn", "nghZwwtHgxgyvVbTQCYyeY" );
+            entry.add( "sn", "nghZwwtHgxgyvVbTQCYyeY" );
+            entry.add( "email", "" );
+            connection.add( entry );
+        } );
+
+        connectionsViewBot.createTestConnection( server );
+
+        assertTrue( browserViewBot.existsEntry( path( dn ) ) );
+        browserViewBot.selectEntry( path( dn ) );
     }
 
 
     /**
      * Test for DIRSTUDIO-1151: DN with backslash not displayed
      */
-    @Test
-    public void testBrowseDnWithBackslash() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testBrowseDnWithBackslash( TestLdapServer server ) throws Exception
     {
+        Dn dn = DN_WITH_ESCAPED_CHARACTERS_BACKSLASH_PREFIXED;
+        if ( server.getType() == LdapServerType.OpenLdap || server.getType() == LdapServerType.Fedora389ds )
+        {
+            dn = DN_WITH_ESCAPED_CHARACTERS_HEX_PAIR_ESCAPED;
+        }
+
+        connectionsViewBot.createTestConnection( server );
+
         // expand parent and verify entry is visible
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.0\\,foo" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.0\\,foo" );
+        browserViewBot.expandEntry( path( dn.getParent() ) );
+        assertTrue( browserViewBot.existsEntry( path( dn ) ) );
+        browserViewBot.selectEntry( path( dn ) );
 
         // refresh entry and verify child is still visible
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
+        browserViewBot.selectEntry( path( dn.getParent() ) );
         browserViewBot.refresh();
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.0\\,foo" ) );
+        assertTrue( browserViewBot.existsEntry( path( dn ) ) );
     }
 
 
@@ -491,9 +524,12 @@
      *
      * @throws Exception
      */
-    @Test
-    public void testNoModificationWhileBrowsingAndRefreshing() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testNoModificationWhileBrowsingAndRefreshing( TestLdapServer server ) throws Exception
     {
+        connectionsViewBot.createTestConnection( server );
+
         boolean errorDialogAutomatedMode = ErrorDialog.AUTOMATED_MODE;
         ErrorDialog.AUTOMATED_MODE = false;
 
@@ -502,18 +538,16 @@
 
         try
         {
-            assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-                "cn=\\#ACL_AD-Projects_Author" ) );
+            assertTrue( browserViewBot.existsEntry( path( MULTI_VALUED_RDN_DN ) ) );
 
             for ( int i = 0; i < 5; i++ )
             {
                 // select entry and refresh
-                browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-                    "cn=\\#ACL_AD-Projects_Author" );
+                browserViewBot.selectEntry( path( MULTI_VALUED_RDN_DN ) );
                 browserViewBot.refresh();
 
                 // select parent and refresh
-                browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
+                browserViewBot.selectEntry( path( MULTI_VALUED_RDN_DN.getParent() ) );
                 browserViewBot.refresh();
             }
         }
@@ -525,7 +559,7 @@
 
         // check that modification logs is still empty
         // to ensure that no modification was sent to the server
-        assertEquals( "No modification expected", "", modificationLogsViewBot.getModificationLogsText() );
+        assertEquals( "", modificationLogsViewBot.getModificationLogsText(), "No modification expected" );
     }
 
 
@@ -533,53 +567,43 @@
      * Test for DIRSTUDIO-603, DIRSHARED-41.
      * (Error browsing/entering rfc2307 compliant host entry.)
      */
-    @Test
-    public void testBrowseDnWithIpHostNumber() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testBrowseDnWithIpHostNumber( TestLdapServer server ) throws Exception
     {
-        ApacheDsUtils.enableSchema( ldapServer, "nis" );
+        connectionsViewBot.createTestConnection( server );
 
-        // create entry with multi-valued RDN containing an IP address value
-        Entry entry = new DefaultEntry( service.getSchemaManager() );
-        entry.setDn( new Dn( "cn=loopback+ipHostNumber=" + LOCALHOST_ADDRESS + ",ou=users,ou=system" ) );
-        entry.add( "objectClass", "top", "device", "ipHost" );
-        entry.add( "cn", "loopback" );
-        entry.add( "ipHostNumber", LOCALHOST_ADDRESS );
-        ldapServer.getDirectoryService().getAdminSession().add( entry );
-
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "cn=loopback+ipHostNumber=" + LOCALHOST_ADDRESS ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "cn=loopback+ipHostNumber=" + LOCALHOST_ADDRESS );
+        assertTrue( browserViewBot.existsEntry( path( DN_WITH_IP_HOST_NUMBER ) ) );
+        browserViewBot.selectEntry( path( DN_WITH_IP_HOST_NUMBER ) );
     }
 
 
     /**
      * DIRSTUDIO-637: copy/paste of attributes no longer works.
      * Test copy/paste of a value to a bookmark.
-     *
-     * @throws Exception
-     *             the exception
      */
-    @Test
-    public void testCopyPasteValueToBookmark() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCopyPasteValueToBookmark( TestLdapServer server ) throws Exception
     {
         // create a bookmark
+        Connection connection = connectionsViewBot.createTestConnection( server );
         IBrowserConnection browserConnection = BrowserCorePlugin.getDefault().getConnectionManager()
             .getBrowserConnection( connection );
         browserConnection.getBookmarkManager().addBookmark(
-            new Bookmark( browserConnection, new Dn( "uid=user.2,ou=users,ou=system" ), "My Bookmark" ) );
+            new Bookmark( browserConnection, MULTI_VALUED_RDN_DN, "My Bookmark" ) );
 
         // copy a value
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.1" );
-        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( "uid=user.1,ou=users,ou=system" );
+        browserViewBot.selectEntry( path( USER1_DN ) );
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( USER1_DN.getName() );
         entryEditorBot.activate();
         entryEditorBot.copyValue( "uid", "user.1" );
 
         // select the bookmark
         browserViewBot.selectEntry( "Bookmarks", "My Bookmark" );
-        entryEditorBot = studioBot.getEntryEditorBot( "uid=user.2,ou=users,ou=system" );
+        entryEditorBot = studioBot.getEntryEditorBot( MULTI_VALUED_RDN_DN.getName() );
         entryEditorBot.activate();
-        assertEquals( 23, entryEditorBot.getAttributeValues().size() );
+        assertEquals( 8, entryEditorBot.getAttributeValues().size() );
 
         // paste the value
         JobWatcher watcher = new JobWatcher( BrowserCoreMessages.jobs__execute_ldif_name );
@@ -587,13 +611,14 @@
         watcher.waitUntilDone();
 
         // assert pasted value visible in editor
-        assertEquals( 24, entryEditorBot.getAttributeValues().size() );
+        assertEquals( 9, entryEditorBot.getAttributeValues().size() );
         entryEditorBot.getAttributeValues().contains( "uid: user.1" );
 
         // assert pasted value was written to directory
-        Entry entry = ldapServer.getDirectoryService().getAdminSession().lookup(
-            new Dn( "uid=user.2,ou=users,ou=system" ) );
-        assertTrue( entry.contains( "uid", "user.1" ) );
+        server.withAdminConnection( conn -> {
+            Entry entry = conn.lookup( MULTI_VALUED_RDN_DN );
+            assertTrue( entry.contains( "uid", "user.1" ) );
+        } );
     }
 
 
@@ -602,16 +627,18 @@
      *
      * Verify input is set only once when entry is selected.
      */
-    @Test
-    public void testSetInputOnlyOnce() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testSetInputOnlyOnce( TestLdapServer server ) throws Exception
     {
         /*
          * This test fails on Jenkins Windows Server, to be investigated...
          */
         // Assume.assumeFalse( StudioSystemUtils.IS_OS_WINDOWS_SERVER );
+        connectionsViewBot.createTestConnection( server );
 
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
+        browserViewBot.selectEntry( path( USERS_DN ) );
+        browserViewBot.expandEntry( path( USERS_DN ) );
 
         // verify link-with-editor is enabled
         assertTrue( BrowserUIPlugin.getDefault().getPreferenceStore()
@@ -647,31 +674,31 @@
         } );
 
         // select 3 different entries, select one twice should not set the input again
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.1" );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.1" );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.2" );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.2" );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.3" );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.3" );
+        browserViewBot.selectEntry( path( USER1_DN ) );
+        browserViewBot.selectEntry( path( USER1_DN ) );
+        browserViewBot.selectEntry( path( USER2_DN ) );
+        browserViewBot.selectEntry( path( USER2_DN ) );
+        browserViewBot.selectEntry( path( USER3_DN ) );
+        browserViewBot.selectEntry( path( USER3_DN ) );
 
         // verify that input was only set 3 times.
-        assertEquals( "Only 3 input changes expected.", 3, counter.get() );
+        assertEquals( 3, counter.get(), "Only 3 input changes expected." );
 
         // reset counter
         counter.set( 0 );
 
         // use navigation history to go back and forth, each step should set input only once
         studioBot.navigationHistoryBack();
-        browserViewBot.waitUntilEntryIsSelected( "uid=user.2" );
+        browserViewBot.waitUntilEntryIsSelected( USER2_DN.getRdn().getName() );
         studioBot.navigationHistoryBack();
-        browserViewBot.waitUntilEntryIsSelected( "uid=user.1" );
+        browserViewBot.waitUntilEntryIsSelected( USER1_DN.getRdn().getName() );
         studioBot.navigationHistoryForward();
-        browserViewBot.waitUntilEntryIsSelected( "uid=user.2" );
+        browserViewBot.waitUntilEntryIsSelected( USER2_DN.getRdn().getName() );
         studioBot.navigationHistoryForward();
-        browserViewBot.waitUntilEntryIsSelected( "uid=user.3" );
+        browserViewBot.waitUntilEntryIsSelected( USER3_DN.getRdn().getName() );
 
         // verify that input was only set 4 times.
-        assertEquals( "Only 4 input changes expected.", 4, counter.get() );
+        assertEquals( 4, counter.get(), "Only 4 input changes expected." );
     }
 
 
@@ -679,140 +706,212 @@
      * Test for DIRSTUDIO-987, DIRSTUDIO-271.
      *
      * Browse and refresh entry with multi-valued RDN with same attribute type.
-     *
-     * @throws Exception
      */
-    @Test
-    public void testBrowseAndRefreshEntryWithMvRdn() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(except = LdapServerType.OpenLdap, reason = "Multi-valued RDN with same attribute is not supported by OpenLDAP")
+    public void testBrowseAndRefreshEntryWithMvRdn( TestLdapServer server ) throws Exception
     {
+        Dn entryDn = dn( "l=Berlin+l=Brandenburger Tor+l=de+l=eu", MISC_DN );
+        Dn childDn = dn( "cn=A", entryDn );
+
+        server.withAdminConnection( connection -> {
+            Entry entry1 = new DefaultEntry( connection.getSchemaManager() );
+            entry1.setDn( entryDn );
+            entry1.add( "objectClass", "top", "locality" );
+            entry1.add( "l", "eu", "de", "Berlin", "Brandenburger Tor" );
+            connection.add( entry1 );
+
+            Entry entry2 = new DefaultEntry( connection.getSchemaManager() );
+            entry2.setDn( childDn );
+            entry2.add( "objectClass", "top", "person" );
+            entry2.add( "cn", "A" );
+            entry2.add( "sn", "A" );
+            connection.add( entry2 );
+        } );
+
+        String[] pathToParent = path( entryDn.getParent() );
+        String[] pathToEntry = path( entryDn );
+        String[] pathToChild = path( childDn );
+
+        connectionsViewBot.createTestConnection( server );
+
         // expand parent and verify entry is visible
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "l=eu + l=de + l=Berlin + l=Brandenburger Tor" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "l=eu + l=de + l=Berlin + l=Brandenburger Tor" );
+        browserViewBot.expandEntry( pathToParent );
+        assertTrue( browserViewBot.existsEntry( pathToEntry ) );
+        browserViewBot.selectEntry( pathToEntry );
 
         // expand entry and verify child is visible
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "l=eu + l=de + l=Berlin + l=Brandenburger Tor" );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "l=eu + l=de + l=Berlin + l=Brandenburger Tor", "cn=A" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "l=eu + l=de + l=Berlin + l=Brandenburger Tor", "cn=A" );
+        browserViewBot.expandEntry( pathToEntry );
+        assertTrue( browserViewBot.existsEntry( pathToChild ) );
+        browserViewBot.selectEntry( pathToChild );
 
         // refresh entry and verify child is still visible
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "l=eu + l=de + l=Berlin + l=Brandenburger Tor" );
+        browserViewBot.selectEntry( pathToEntry );
         browserViewBot.refresh();
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "l=eu + l=de + l=Berlin + l=Brandenburger Tor", "cn=A" ) );
+        assertTrue( browserViewBot.existsEntry( pathToChild ) );
 
         // refresh parent and verify entry is still visible
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
+        browserViewBot.selectEntry( pathToParent );
         browserViewBot.refresh();
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "l=eu + l=de + l=Berlin + l=Brandenburger Tor" ) );
+        assertTrue( browserViewBot.existsEntry( pathToEntry ) );
 
         // expand entry and verify child is visible
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "l=eu + l=de + l=Berlin + l=Brandenburger Tor" );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "l=eu + l=de + l=Berlin + l=Brandenburger Tor", "cn=A" ) );
+        browserViewBot.expandEntry( pathToEntry );
+        assertTrue( browserViewBot.existsEntry( pathToChild ) );
     }
 
 
-    @Test
-    public void testBrowseAliasEntry()
+    @ParameterizedTest
+    @LdapServersSource
+    public void testBrowseAliasEntry( TestLdapServer server ) throws Exception
     {
         // disable alias dereferencing
+        Connection connection = connectionsViewBot.createTestConnection( server );
         connection.getConnectionParameter().setExtendedIntProperty(
             IBrowserConnection.CONNECTION_PARAMETER_ALIASES_DEREFERENCING_METHOD,
             AliasDereferencingMethod.NEVER.ordinal() );
 
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=special", "cn=alias" );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=special", "cn=alias" ) );
+        browserViewBot.expandEntry( path( ALIAS_DN.getParent() ) );
+        assertTrue( browserViewBot.existsEntry( path( ALIAS_DN ) ) );
+        browserViewBot.selectEntry( path( ALIAS_DN ) );
     }
 
 
-    @Test
-    public void testBrowseReferralEntry()
+    @ParameterizedTest
+    @LdapServersSource
+    public void testBrowseReferralEntry( TestLdapServer server ) throws Exception
     {
         // enable ManageDsaIT control
+        Connection connection = connectionsViewBot.createTestConnection( server );
         connection.getConnectionParameter().setExtendedBoolProperty(
             IBrowserConnection.CONNECTION_PARAMETER_MANAGE_DSA_IT, true );
 
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=special", "cn=referral" );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=special", "cn=referral" ) );
+        browserViewBot.expandEntry( path( REFERRAL_TO_USERS_DN.getParent() ) );
+        assertTrue( browserViewBot.existsEntry( path( REFERRAL_TO_USERS_DN ) ) );
+        browserViewBot.selectEntry( path( REFERRAL_TO_USERS_DN ) );
     }
 
 
-    @Test
-    public void testBrowseSubEntry()
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.ApacheDS, reason = "ApacheDS specific test")
+    public void testBrowseSubEntry( TestLdapServer server ) throws Exception
     {
+        Dn subentryDn = dn( "cn=subentry", MISC_DN );
+
         // enable Subentries control
+        Connection connection = connectionsViewBot.createTestConnection( server );
         connection.getConnectionParameter().setExtendedBoolProperty(
             IBrowserConnection.CONNECTION_PARAMETER_FETCH_SUBENTRIES, true );
 
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=special", "cn=subentry" );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=special", "cn=subentry" ) );
+        browserViewBot.expandEntry( path( subentryDn.getParent() ) );
+        assertTrue( browserViewBot.existsEntry( path( subentryDn ) ) );
+        browserViewBot.selectEntry( path( subentryDn ) );
     }
 
 
-    @Test
-    public void testBrowseWithPagingWithScrollMode()
+    @ParameterizedTest
+    @LdapServersSource
+    public void testBrowseWithPagingWithScrollMode( TestLdapServer server ) throws Exception
     {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
+        Connection connection = connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( USERS_DN ) );
 
         // enable Simple Paged Results control
         connection.getConnectionParameter().setExtendedBoolProperty(
             IBrowserConnection.CONNECTION_PARAMETER_PAGED_SEARCH, true );
         connection.getConnectionParameter().setExtendedIntProperty(
-            IBrowserConnection.CONNECTION_PARAMETER_PAGED_SEARCH_SIZE, 5 );
+            IBrowserConnection.CONNECTION_PARAMETER_PAGED_SEARCH_SIZE, 3 );
         connection.getConnectionParameter().setExtendedBoolProperty(
             IBrowserConnection.CONNECTION_PARAMETER_PAGED_SEARCH_SCROLL_MODE, true );
 
         // 1st page
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "--- Top Page ---" ) );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "--- Next Page ---" ) );
+        browserViewBot.expandEntry( path( USERS_DN ) );
+        assertFalse( browserViewBot.existsEntry( path( USERS_DN, "--- Top Page ---" ) ) );
+        assertTrue( browserViewBot.existsEntry( path( USERS_DN, "--- Next Page ---" ) ) );
 
         // next page
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "--- Next Page ---" );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "--- Top Page ---" ) );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "--- Next Page ---" ) );
+        browserViewBot.selectEntry( path( USERS_DN, "--- Next Page ---" ) );
+        assertTrue( browserViewBot.existsEntry( path( USERS_DN, "--- Top Page ---" ) ) );
+        assertTrue( browserViewBot.existsEntry( path( USERS_DN, "--- Next Page ---" ) ) );
 
         // last page
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "--- Next Page ---" );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "--- Top Page ---" ) );
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "--- Next Page ---" ) );
+        browserViewBot.selectEntry( path( USERS_DN, "--- Next Page ---" ) );
+        assertTrue( browserViewBot.existsEntry( path( USERS_DN, "--- Top Page ---" ) ) );
+        assertFalse( browserViewBot.existsEntry( path( USERS_DN, "--- Next Page ---" ) ) );
 
         // back to top
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "--- Top Page ---" );
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "--- Top Page ---" ) );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "--- Next Page ---" ) );
+        browserViewBot.selectEntry( path( USERS_DN, "--- Top Page ---" ) );
+        assertFalse( browserViewBot.existsEntry( path( USERS_DN, "--- Top Page ---" ) ) );
+        assertTrue( browserViewBot.existsEntry( path( USERS_DN, "--- Next Page ---" ) ) );
     }
 
 
-    @Test
-    public void testBrowseWithPagingWithoutScrollMode()
+    @ParameterizedTest
+    @LdapServersSource
+    public void testBrowseWithPagingWithoutScrollMode( TestLdapServer server ) throws Exception
     {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
+        Connection connection = connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( USERS_DN ) );
 
         // enable Simple Paged Results control
         connection.getConnectionParameter().setExtendedBoolProperty(
             IBrowserConnection.CONNECTION_PARAMETER_PAGED_SEARCH, true );
         connection.getConnectionParameter().setExtendedIntProperty(
-            IBrowserConnection.CONNECTION_PARAMETER_PAGED_SEARCH_SIZE, 5 );
+            IBrowserConnection.CONNECTION_PARAMETER_PAGED_SEARCH_SIZE, 3 );
         connection.getConnectionParameter().setExtendedBoolProperty(
             IBrowserConnection.CONNECTION_PARAMETER_PAGED_SEARCH_SCROLL_MODE, false );
 
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "--- Top Page ---" ) );
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "--- Next Page ---" ) );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users (13)" ) );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.1" ) );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.8" ) );
+        browserViewBot.expandEntry( path( USERS_DN ) );
+        assertFalse( browserViewBot.existsEntry( path( USERS_DN, "--- Top Page ---" ) ) );
+        assertFalse( browserViewBot.existsEntry( path( USERS_DN, "--- Next Page ---" ) ) );
+        assertTrue( browserViewBot.existsEntry( path( USERS_DN ) ) );
+        assertTrue( browserViewBot.existsEntry( path( USERS_DN, "uid=user.1" ) ) );
+        assertTrue( browserViewBot.existsEntry( path( USERS_DN, "uid=user.8" ) ) );
+    }
 
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void x( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+
+        browserViewBot.selectEntry( path( USERS_DN ) );
+        browserViewBot.expandEntry( path( USERS_DN ) );
+
+        browserViewBot.selectEntry( path( USER1_DN ) );
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( USER1_DN.getName() );
+        List<String> attributeValues = entryEditorBot.getAttributeValues();
+        assertEquals( 23, attributeValues.size() );
+        assertTrue( attributeValues.contains( "uid: user.1" ) );
+        assertTrue( entryEditorBot.getAttributeValues().contains( "initials: AA" ) );
+
+        DeleteDialogBot deleteDialog = browserViewBot.openDeleteDialog();
+        deleteDialog.clickOkButton();
+        browserViewBot.selectEntry( path( USERS_DN ) );
+        assertFalse( browserViewBot.existsEntry( path( USER1_DN ) ) );
+
+        server.withAdminConnection( conn -> {
+            Entry entry = new DefaultEntry( conn.getSchemaManager() );
+            entry.setDn( USER1_DN );
+            entry.add( "objectClass", "top", "person", "organizationalPerson", "inetOrgPerson" );
+            entry.add( "uid", "user.1" );
+            entry.add( "givenName", "Foo" );
+            entry.add( "sn", "Bar" );
+            entry.add( "cn", "Foo Bar" );
+            entry.add( "initials", "FB" );
+            conn.add( entry );
+        } );
+
+        browserViewBot.refresh();
+        assertTrue( browserViewBot.existsEntry( path( USER1_DN ) ) );
+
+        browserViewBot.selectEntry( path( USER1_DN ) );
+        entryEditorBot = studioBot.getEntryEditorBot( USER1_DN.getName() );
+        attributeValues = entryEditorBot.getAttributeValues();
+        assertEquals( 9, attributeValues.size() );
+        assertTrue( attributeValues.contains( "uid: user.1" ) );
+        assertTrue( entryEditorBot.getAttributeValues().contains( "initials: FB" ) );
     }
 
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/CertificateValidationTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/CertificateValidationTest.java
index 305f4ad..094e25f 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/CertificateValidationTest.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/CertificateValidationTest.java
@@ -21,16 +21,17 @@
 package org.apache.directory.studio.test.integration.ui;
 
 
-import static org.apache.directory.studio.test.integration.ui.Constants.LOCALHOST;
+import static org.apache.directory.studio.test.integration.ui.utils.Constants.LOCALHOST;
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.File;
 import java.io.FileOutputStream;
+import java.lang.reflect.Method;
 import java.math.BigInteger;
 import java.security.KeyPair;
 import java.security.KeyPairGenerator;
@@ -50,35 +51,31 @@
 import org.apache.directory.api.ldap.model.entry.DefaultEntry;
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.server.annotations.CreateLdapServer;
-import org.apache.directory.server.annotations.CreateTransport;
-import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
 import org.apache.directory.server.core.security.TlsKeyGenerator;
-import org.apache.directory.server.ldap.handlers.extended.StartTlsHandler;
 import org.apache.directory.studio.connection.core.ConnectionCorePlugin;
+import org.apache.directory.studio.test.integration.junit5.ApacheDirectoryServer;
+import org.apache.directory.studio.test.integration.junit5.LdapServerType;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource;
+import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
 import org.apache.directory.studio.test.integration.ui.bots.CertificateTrustDialogBot;
 import org.apache.directory.studio.test.integration.ui.bots.CertificateValidationPreferencePageBot;
+import org.apache.directory.studio.test.integration.ui.bots.CertificateViewerDialogBot;
 import org.apache.directory.studio.test.integration.ui.bots.CheckAuthenticationDialogBot;
-import org.apache.directory.studio.test.integration.ui.bots.ConnectionsViewBot;
+import org.apache.directory.studio.test.integration.ui.bots.DialogBot.CheckResponse;
 import org.apache.directory.studio.test.integration.ui.bots.ErrorDialogBot;
 import org.apache.directory.studio.test.integration.ui.bots.NewConnectionWizardBot;
 import org.apache.directory.studio.test.integration.ui.bots.PreferencesBot;
-import org.apache.directory.studio.test.integration.ui.bots.StudioBot;
-import org.apache.directory.studio.test.integration.ui.bots.utils.Assertions;
-import org.apache.directory.studio.test.integration.ui.bots.utils.FrameworkRunnerWithScreenshotCaptureListener;
 import org.bouncycastle.asn1.x509.BasicConstraints;
 import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
 import org.bouncycastle.asn1.x509.Extension;
 import org.bouncycastle.asn1.x509.KeyPurposeId;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.bouncycastle.x509.X509V3CertificateGenerator;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TestName;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.params.ParameterizedTest;
 
 
 /**
@@ -87,34 +84,18 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-@RunWith(FrameworkRunnerWithScreenshotCaptureListener.class)
-//@CreateDS(allowAnonAccess = true, name = "KeyStoreIT-class")
-public class CertificateValidationTest extends AbstractLdapTestUnit
+public class CertificateValidationTest extends AbstractTestBase
 {
     static final long YEAR_MILLIS = 365L * 24L * 3600L * 1000L;
 
-    @Rule
-    public TestName name = new TestName();
+    private TestInfo testInfo;
 
-    private static StudioBot studioBot;
-    private static ConnectionsViewBot connectionsViewBot;
     private static NewConnectionWizardBot wizardBot;
 
-
-    @BeforeClass
-    public static void setUpClass() throws Exception
+    @BeforeEach
+    public void setUp( TestInfo testInfo ) throws Exception
     {
-        studioBot = new StudioBot();
-        studioBot.resetLdapPerspective();
-        connectionsViewBot = studioBot.getConnectionView();
-        // ErrorDialog.AUTOMATED_MODE = false;
-    }
-
-
-    @Before
-    public void setUp() throws Exception
-    {
-        studioBot.resetLdapPerspective();
+        this.testInfo = testInfo;
 
         // let Java use the key store
         System.setProperty( "javax.net.ssl.trustStore", ROOT_CA_KEYSTORE_PATH );
@@ -124,32 +105,14 @@
     }
 
 
-    @After
+    @AfterEach
     public void tearDown() throws Exception
     {
-        connectionsViewBot.deleteTestConnections();
-
-        // delete custom trust stores
-        X509Certificate[] permanentCertificates = ConnectionCorePlugin.getDefault().getPermanentTrustStoreManager()
-            .getCertificates();
-        for ( X509Certificate certificate : permanentCertificates )
-        {
-            ConnectionCorePlugin.getDefault().getPermanentTrustStoreManager().removeCertificate( certificate );
-        }
-        X509Certificate[] temporaryCertificates = ConnectionCorePlugin.getDefault().getSessionTrustStoreManager()
-            .getCertificates();
-        for ( X509Certificate certificate : temporaryCertificates )
-        {
-            ConnectionCorePlugin.getDefault().getSessionTrustStoreManager().removeCertificate( certificate );
-        }
-
         // delete custom Java key store settings
         System.clearProperty( "javax.net.ssl.trustStore" );
         System.clearProperty( "javax.net.ssl.trustStorePassword" );
         System.clearProperty( "javax.net.ssl.keyStore" );
         System.clearProperty( "javax.net.ssl.keyStorePassword" );
-
-        Assertions.genericTearDownAssertions();
     }
 
     private static final String KEYSTORE_PW = "changeit";
@@ -175,8 +138,7 @@
 
     private static final String MULTIPLE_ISSUES_KEYSTORE_PATH = "target/classes/multiple-issues-keystore.ks";
 
-
-    @BeforeClass
+    @BeforeAll
     public static void installKeyStoreWithCertificate() throws Exception
     {
         String issuerDn = "CN=trusted-root-ca";
@@ -227,7 +189,8 @@
             UNTRUSTED_ROOT_CA_KEYSTORE_PATH );
         PrivateKey untrustedRootCaPrivateKey = ( PrivateKey ) ROOT_CA_KEYSTORE.getKey( "apacheds",
             KEYSTORE_PW.toCharArray() );
-        createKeyStore( subjectDn, untrustedRootCaIssuerDn, startDate, expiryDate, keyAlgo, keySize, untrustedRootCaPrivateKey,
+        createKeyStore( subjectDn, untrustedRootCaIssuerDn, startDate, expiryDate, keyAlgo, keySize,
+            untrustedRootCaPrivateKey,
             UNTRUSTED_KEYSTORE_PATH );
 
         // generate a certificate with multiple issues: expired, wrong hostname, self-signed
@@ -345,22 +308,37 @@
 
     private String getConnectionName()
     {
-        return "NewConnectionWizardTest." + name.getMethodName();
+        return testInfo.getTestMethod().map( Method::getName ).orElse( "null" ) + " "
+            + testInfo.getDisplayName();
     }
 
 
     /**
      * Tests ldaps:// with a valid certificate.
      */
-    @CreateLdapServer(keyStore = VALID_KEYSTORE_PATH, certificatePassword = KEYSTORE_PW)
-    @Test
-    public void testLdapsCertificateValidationOK() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.ApacheDS, reason = "Update of keystore only implemented for ApacheDS")
+    public void testLdapsCertificateValidationOK( ApacheDirectoryServer server ) throws Exception
     {
-        wizardBotWithLdaps();
+        server.setKeystore( VALID_KEYSTORE_PATH );
+        wizardBotWithLdaps( server, false );
 
         // check the certificate, should be OK
-        String result = wizardBot.clickCheckAuthenticationButton();
-        assertNull( "Expected OK, valid and trusted certificate", result );
+        CheckResponse checkResponse = wizardBot.clickCheckNetworkParameterButton();
+        assertFalse( checkResponse.isError(), "Expected OK, valid and trusted certificate" );
+
+        // view the certificate
+        CertificateViewerDialogBot certificateViewerBot = wizardBot.clickViewCertificateButton();
+        certificateViewerBot.clickCloseButton();
+
+        // enter correct authentication parameter
+        wizardBot.clickNextButton();
+        wizardBot.typeUser( "uid=admin,ou=system" );
+        wizardBot.typePassword( "secret" );
+
+        // check the certificate again, should be OK
+        String result2 = wizardBot.clickCheckAuthenticationButton();
+        assertNull( result2, "Expected OK, valid and trusted certificate" );
 
         wizardBot.clickCancelButton();
     }
@@ -369,15 +347,16 @@
     /**
      * Tests ldaps:// with an expired certificate.
      */
-    @CreateLdapServer(keyStore = EXPIRED_KEYSTORE_PATH, certificatePassword = KEYSTORE_PW)
-    @Test
-    public void testLdapsCertificateValidationExpired() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.ApacheDS, reason = "Update of keystore only implemented for ApacheDS")
+    public void testLdapsCertificateValidationExpired( ApacheDirectoryServer server ) throws Exception
     {
-        wizardBotWithLdaps();
+        server.setKeystore( EXPIRED_KEYSTORE_PATH );
+        wizardBotWithLdaps( server, false );
 
         // check the certificate, expecting the trust dialog
         CertificateTrustDialogBot trustDialogBot = wizardBot
-            .clickCheckAuthenticationButtonExpectingCertificateTrustDialog();
+            .clickCheckNetworkParameterButtonExpectingCertificateTrustDialog();
         assertTrue( trustDialogBot.isExpired() );
         assertFalse( trustDialogBot.isSelfSigned() );
         assertFalse( trustDialogBot.isNotYetValid() );
@@ -396,11 +375,11 @@
      * Tests that when selecting "Don't trust" the certificate is not trusted
      * and not added to any key store.
      */
-    @CreateLdapServer(keyStore = EXPIRED_KEYSTORE_PATH, certificatePassword = KEYSTORE_PW)
-    @Test
-    public void testLdapsCertificateDoNotTrust() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testLdapsCertificateDoNotTrust( TestLdapServer server ) throws Exception
     {
-        wizardBotWithLdaps();
+        wizardBotWithLdaps( server, true );
 
         // check trust, expect trust dialog, select don't trust
         CertificateTrustDialogBot trustDialogBot = wizardBot
@@ -441,11 +420,11 @@
      * Tests that when selecting "Trust temporary" the certificate is trusted
      * and added to the session key store.
      */
-    @CreateLdapServer(keyStore = EXPIRED_KEYSTORE_PATH, certificatePassword = KEYSTORE_PW)
-    @Test
-    public void testLdapsCertificateTrustTemporary() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testLdapsCertificateTrustTemporary( TestLdapServer server ) throws Exception
     {
-        wizardBotWithLdaps();
+        wizardBotWithLdaps( server, true );
 
         // check trust, expect trust dialog, select trust temporary
         CertificateTrustDialogBot trustDialogBot = wizardBot
@@ -464,7 +443,7 @@
         // check trust again, now the certificate is already trusted
         wizardBot.activate();
         String result = wizardBot.clickCheckAuthenticationButton();
-        assertNull( "Expected OK, valid and trusted certificate", result );
+        assertNull( result, "Expected OK, valid and trusted certificate" );
 
         wizardBot.clickCancelButton();
     }
@@ -474,11 +453,11 @@
      * Tests that when selecting "Trust permanent" the certificate is trusted
      * and added to the permanent key store.
      */
-    @CreateLdapServer(keyStore = EXPIRED_KEYSTORE_PATH, certificatePassword = KEYSTORE_PW)
-    @Test
-    public void testLdapsCertificateTrustPermanent() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testLdapsCertificateTrustPermanent( TestLdapServer server ) throws Exception
     {
-        wizardBotWithLdaps();
+        wizardBotWithLdaps( server, true );
 
         // check trust, expect trust dialog, select trust temporary
         CertificateTrustDialogBot trustDialogBot = wizardBot
@@ -497,7 +476,7 @@
         // check trust again, now the certificate is already trusted
         wizardBot.activate();
         String result = wizardBot.clickCheckAuthenticationButton();
-        assertNull( "Expected OK, valid and trusted certificate", result );
+        assertNull( result, "Expected OK, valid and trusted certificate" );
 
         wizardBot.clickCancelButton();
     }
@@ -507,20 +486,26 @@
      * Tests StartTLS with an valid certificate. This is simulated
      * by putting the root certificate into a temporary key store.
      */
-    @Test
-    @CreateLdapServer(keyStore = VALID_KEYSTORE_PATH, certificatePassword = KEYSTORE_PW, extendedOpHandlers = StartTlsHandler.class)
-    public void testStartTlsCertificateValidationOK() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.ApacheDS, reason = "Update of keystore only implemented for ApacheDS")
+    public void testStartTlsCertificateValidationOK( ApacheDirectoryServer server ) throws Exception
     {
+        server.setKeystore( VALID_KEYSTORE_PATH );
+
         // enter connection parameter
         wizardBot = connectionsViewBot.openNewConnectionWizard();
         wizardBot.typeConnectionName( getConnectionName() );
         wizardBot.typeHost( LOCALHOST );
-        wizardBot.typePort( ldapServer.getPort() );
+        wizardBot.typePort( server.getPort() );
         wizardBot.selectStartTlsEncryption();
 
         // check the certificate, should be OK
-        String result = wizardBot.clickCheckNetworkParameterButton();
-        assertNull( "Expected OK, valid and trusted certificate", result );
+        CheckResponse checkResponse = wizardBot.clickCheckNetworkParameterButton();
+        assertFalse( checkResponse.isError(), "Expected OK, valid and trusted certificate" );
+
+        // view the certificate
+        CertificateViewerDialogBot certificateViewerBot = wizardBot.clickViewCertificateButton();
+        certificateViewerBot.clickCloseButton();
 
         // enter correct authentication parameter
         wizardBot.clickNextButton();
@@ -529,7 +514,7 @@
 
         // check the certificate again, should be OK
         String result2 = wizardBot.clickCheckAuthenticationButton();
-        assertNull( "Expected OK, valid and trusted certificate", result2 );
+        assertNull( result2, "Expected OK, valid and trusted certificate" );
 
         wizardBot.clickCancelButton();
     }
@@ -538,15 +523,16 @@
     /**
      * DIRSTUDIO-1205: SSL/TLS with small key size is not working.
      */
-    @CreateLdapServer(keyStore = SMALL_KEYSIZE_KEYSTORE_PATH, certificatePassword = KEYSTORE_PW, extendedOpHandlers = StartTlsHandler.class)
-    @Test
-    public void testStartTlsCertificateValidationSmallKeysizeError() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.ApacheDS, reason = "Update of keystore only implemented for ApacheDS")
+    public void testStartTlsCertificateValidationSmallKeysizeError( ApacheDirectoryServer server ) throws Exception
     {
-        wizardBotWithStartTls();
+        server.setKeystore( SMALL_KEYSIZE_KEYSTORE_PATH );
+        wizardBotWithStartTls( server, false );
 
         // check the certificate, expecting the trust dialog
         CertificateTrustDialogBot trustDialogBot = wizardBot
-            .clickCheckAuthenticationButtonExpectingCertificateTrustDialog();
+            .clickCheckNetworkParameterButtonExpectingCertificateTrustDialog();
         assertFalse( trustDialogBot.isExpired() );
         assertFalse( trustDialogBot.isSelfSigned() );
         assertFalse( trustDialogBot.isNotYetValid() );
@@ -556,7 +542,7 @@
 
         trustDialogBot.selectDontTrust();
         clickOkButtonExpectingCertficateErrorDialog( trustDialogBot, "Failed to verify certification path",
-            "Algorithm constraints check failed on keysize limits", "RSA 512bit key used" );
+            "Algorithm constraints check failed on keysize limits", "RSA 512", "bit key used" );
         wizardBot.clickCancelButton();
     }
 
@@ -564,15 +550,16 @@
     /**
      * Tests StartTLS with an expired certificate.
      */
-    @CreateLdapServer(keyStore = EXPIRED_KEYSTORE_PATH, certificatePassword = KEYSTORE_PW, extendedOpHandlers = StartTlsHandler.class)
-    @Test
-    public void testStartTlsCertificateValidationExpired() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.ApacheDS, reason = "Update of keystore only implemented for ApacheDS")
+    public void testStartTlsCertificateValidationExpired( ApacheDirectoryServer server ) throws Exception
     {
-        wizardBotWithStartTls();
+        server.setKeystore( EXPIRED_KEYSTORE_PATH );
+        wizardBotWithStartTls( server, false );
 
         // check the certificate, expecting the trust dialog
         CertificateTrustDialogBot trustDialogBot = wizardBot
-            .clickCheckAuthenticationButtonExpectingCertificateTrustDialog();
+            .clickCheckNetworkParameterButtonExpectingCertificateTrustDialog();
         assertTrue( trustDialogBot.isExpired() );
         assertFalse( trustDialogBot.isSelfSigned() );
         assertFalse( trustDialogBot.isNotYetValid() );
@@ -588,11 +575,12 @@
     /**
      * Tests StartTLS with an not yet valid certificate.
      */
-    @CreateLdapServer(keyStore = NOT_YET_VALID_KEYSTORE_PATH, certificatePassword = KEYSTORE_PW, extendedOpHandlers = StartTlsHandler.class)
-    @Test
-    public void testStartTlsCertificateValidationNotYetValid() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.ApacheDS, reason = "Update of keystore only implemented for ApacheDS")
+    public void testStartTlsCertificateValidationNotYetValid( ApacheDirectoryServer server ) throws Exception
     {
-        wizardBotWithStartTls();
+        server.setKeystore( NOT_YET_VALID_KEYSTORE_PATH );
+        wizardBotWithStartTls( server, true );
 
         // check the certificate, expecting the trust dialog
         CertificateTrustDialogBot trustDialogBot = wizardBot
@@ -613,11 +601,12 @@
      * Tests StartTLS with a certificate where the certificate's host name
      * doesn't match the server's host name (localhost)
      */
-    @CreateLdapServer(keyStore = WRONG_HOSTNAME_KEYSTORE_PATH, certificatePassword = KEYSTORE_PW, extendedOpHandlers = StartTlsHandler.class)
-    @Test
-    public void testStartTlsCertificateValidationHostnameMismatch() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.ApacheDS, reason = "Update of keystore only implemented for ApacheDS")
+    public void testStartTlsCertificateValidationHostnameMismatch( ApacheDirectoryServer server ) throws Exception
     {
-        wizardBotWithStartTls();
+        server.setKeystore( WRONG_HOSTNAME_KEYSTORE_PATH );
+        wizardBotWithStartTls( server, true );
 
         // check the certificate, expecting the trust dialog
         CertificateTrustDialogBot trustDialogBot = wizardBot
@@ -637,11 +626,13 @@
     /**
      * Tests StartTLS with a certificate without valid certification path.
      */
-    @CreateLdapServer(keyStore = UNTRUSTED_KEYSTORE_PATH, certificatePassword = KEYSTORE_PW, extendedOpHandlers = StartTlsHandler.class)
-    @Test
-    public void testStartTlsCertificateValidationNoValidCertificationPath() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.ApacheDS, reason = "Update of keystore only implemented for ApacheDS")
+    public void testStartTlsCertificateValidationNoValidCertificationPath( ApacheDirectoryServer server )
+        throws Exception
     {
-        wizardBotWithStartTls();
+        server.setKeystore( UNTRUSTED_KEYSTORE_PATH );
+        wizardBotWithStartTls( server, true );
 
         // check the certificate, expecting the trust dialog
         CertificateTrustDialogBot trustDialogBot = wizardBot
@@ -662,11 +653,12 @@
     /**
      * Tests StartTLS with a self-signed certificate.
      */
-    @CreateLdapServer(extendedOpHandlers = StartTlsHandler.class, keyStore = SELF_SIGNED_KEYSTORE_PATH, certificatePassword = KEYSTORE_PW)
-    @Test
-    public void testStartTlsCertificateValidationSelfSigned() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.ApacheDS, reason = "Update of keystore only implemented for ApacheDS")
+    public void testStartTlsCertificateValidationSelfSigned( ApacheDirectoryServer server ) throws Exception
     {
-        wizardBotWithStartTls();
+        server.setKeystore( SELF_SIGNED_KEYSTORE_PATH );
+        wizardBotWithStartTls( server, true );
 
         // check the certificate, expecting the trust dialog
         CertificateTrustDialogBot trustDialogBot = wizardBot
@@ -687,11 +679,13 @@
     /**
      * Tests StartTLS with a certificate with multiple issues.
      */
-    @CreateLdapServer(extendedOpHandlers = StartTlsHandler.class, keyStore = MULTIPLE_ISSUES_KEYSTORE_PATH, certificatePassword = KEYSTORE_PW)
-    @Test
-    public void testStartTlsCertificateValidationExpiredAndWrongHostnameAndSelfSigned() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.ApacheDS, reason = "Update of keystore only implemented for ApacheDS")
+    public void testStartTlsCertificateValidationExpiredAndWrongHostnameAndSelfSigned( ApacheDirectoryServer server )
+        throws Exception
     {
-        wizardBotWithStartTls();
+        server.setKeystore( MULTIPLE_ISSUES_KEYSTORE_PATH );
+        wizardBotWithStartTls( server, true );
 
         // check the certificate, expecting the trust dialog
         CertificateTrustDialogBot trustDialogBot = wizardBot
@@ -712,11 +706,11 @@
      * Tests that when selecting "Don't trust" the certificate is not trusted
      * and not added to any key store.
      */
-    @CreateLdapServer(transports = @CreateTransport(protocol = "LDAP"), extendedOpHandlers = StartTlsHandler.class, keyStore = EXPIRED_KEYSTORE_PATH, certificatePassword = KEYSTORE_PW)
-    @Test
-    public void testStartTlsCertificateDoNotTrust() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testStartTlsCertificateDoNotTrust( TestLdapServer server ) throws Exception
     {
-        wizardBotWithStartTls();
+        wizardBotWithStartTls( server, true );
 
         // check trust, expect trust dialog, select don't trust
         CertificateTrustDialogBot trustDialogBot = wizardBot
@@ -767,11 +761,11 @@
      * Tests that when selecting "Trust temporary" the certificate is trusted
      * and added to the session key store.
      */
-    @CreateLdapServer(transports = @CreateTransport(protocol = "LDAP"), extendedOpHandlers = StartTlsHandler.class, keyStore = EXPIRED_KEYSTORE_PATH, certificatePassword = KEYSTORE_PW)
-    @Test
-    public void testStartTlsCertificateTrustTemporary() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testStartTlsCertificateTrustTemporary( TestLdapServer server ) throws Exception
     {
-        wizardBotWithStartTls();
+        wizardBotWithStartTls( server, true );
 
         // check trust, expect trust dialog, select trust temporary
         CertificateTrustDialogBot trustDialogBot = wizardBot
@@ -790,7 +784,7 @@
         // check trust again, now the certificate is already trusted
         wizardBot.activate();
         String result = wizardBot.clickCheckAuthenticationButton();
-        assertNull( "Expected OK, valid and trusted certificate", result );
+        assertNull( result, "Expected OK, valid and trusted certificate" );
 
         wizardBot.clickCancelButton();
 
@@ -809,11 +803,11 @@
      * Tests that when selecting "Trust permanent" the certificate is trusted
      * and added to the permanent key store.
      */
-    @CreateLdapServer(transports = @CreateTransport(protocol = "LDAP"), extendedOpHandlers = StartTlsHandler.class, keyStore = EXPIRED_KEYSTORE_PATH, certificatePassword = KEYSTORE_PW)
-    @Test
-    public void testStartTlsCertificateTrustPermanent() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testStartTlsCertificateTrustPermanent( TestLdapServer server ) throws Exception
     {
-        wizardBotWithStartTls();
+        wizardBotWithStartTls( server, true );
 
         // check trust, expect trust dialog, select trust temporary
         CertificateTrustDialogBot trustDialogBot = wizardBot
@@ -832,7 +826,7 @@
         // check trust again, now the certificate is already trusted
         wizardBot.activate();
         String result = wizardBot.clickCheckAuthenticationButton();
-        assertNull( "Expected OK, valid and trusted certificate", result );
+        assertNull( result, "Expected OK, valid and trusted certificate" );
 
         wizardBot.clickCancelButton();
 
@@ -847,31 +841,37 @@
     }
 
 
-    private void wizardBotWithLdaps()
+    private void wizardBotWithLdaps( TestLdapServer server, boolean continueToAuthenticationPage )
     {
         // enter connection parameter and authentication parameter
         wizardBot = connectionsViewBot.openNewConnectionWizard();
         wizardBot.typeConnectionName( getConnectionName() );
-        wizardBot.typeHost( LOCALHOST );
-        wizardBot.typePort( ldapServer.getPortSSL() );
+        wizardBot.typeHost( server.getHost() );
+        wizardBot.typePort( server.getPortSSL() );
         wizardBot.selectLdapsEncryption();
-        wizardBot.clickNextButton();
-        wizardBot.typeUser( "uid=admin,ou=system" );
-        wizardBot.typePassword( "secret" );
+        if ( continueToAuthenticationPage )
+        {
+            wizardBot.clickNextButton();
+            wizardBot.typeUser( server.getAdminDn() );
+            wizardBot.typePassword( server.getAdminPassword() );
+        }
     }
 
 
-    private void wizardBotWithStartTls()
+    private void wizardBotWithStartTls( TestLdapServer server, boolean continueToAuthenticationPage )
     {
         // enter connection parameter and authentication parameter
         wizardBot = connectionsViewBot.openNewConnectionWizard();
         wizardBot.typeConnectionName( getConnectionName() );
-        wizardBot.typeHost( LOCALHOST );
-        wizardBot.typePort( ldapServer.getPort() );
+        wizardBot.typeHost( server.getHost() );
+        wizardBot.typePort( server.getPort() );
         wizardBot.selectStartTlsEncryption();
-        wizardBot.clickNextButton();
-        wizardBot.typeUser( "uid=admin,ou=system" );
-        wizardBot.typePassword( "secret" );
+        if ( continueToAuthenticationPage )
+        {
+            wizardBot.clickNextButton();
+            wizardBot.typeUser( server.getAdminDn() );
+            wizardBot.typePassword( server.getAdminPassword() );
+        }
     }
 
 
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ConnectionViewTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ConnectionViewTest.java
new file mode 100644
index 0000000..af91b22
--- /dev/null
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ConnectionViewTest.java
@@ -0,0 +1,192 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.studio.test.integration.ui;
+
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.net.URL;
+
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource;
+import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
+import org.apache.directory.studio.test.integration.ui.bots.ExportConnectionsWizardBot;
+import org.apache.directory.studio.test.integration.ui.bots.ImportConnectionsWizardBot;
+import org.apache.directory.studio.test.integration.ui.bots.NewConnectionFolderDialogBot;
+import org.apache.directory.studio.test.integration.ui.bots.NewConnectionWizardBot;
+import org.eclipse.core.runtime.Platform;
+import org.junit.jupiter.params.ParameterizedTest;
+
+
+/**
+ * Tests the LDAP browser.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class ConnectionViewTest extends AbstractTestBase
+{
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCreateAndDeleteConnections( TestLdapServer server )
+    {
+        String connectionName = "Test connection 1";
+        createConnection( connectionName, server );
+
+        // ensure connection is visible in Connections view
+        assertEquals( 1, connectionsViewBot.getCount() );
+
+        // delete connection
+        connectionsViewBot.select( connectionName );
+        connectionsViewBot.openDeleteConnectionDialog().clickOkButton();
+
+        // ensure connection is no longer visible in Connections view
+        assertEquals( 0, connectionsViewBot.getCount() );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCreateAndDeleteConnectionFolders( TestLdapServer server )
+    {
+        String folderName = "Connection folder 1";
+        String subFolder1Name = "Connection folder 2";
+        String subFolder2Name = "Connection folder 3";
+
+        // create one folder
+        createConnectionFolder( folderName );
+
+        // ensure folder is visible
+        assertEquals( 1, connectionsViewBot.getCount() );
+
+        // create two sub folders
+        connectionsViewBot.select( folderName );
+        createConnectionFolder( subFolder1Name );
+        connectionsViewBot.select( folderName );
+        createConnectionFolder( subFolder2Name );
+
+        // ensure connection folders are visible
+        assertEquals( 3, connectionsViewBot.getCount() );
+
+        // delete one sub folder
+        connectionsViewBot.select( folderName, subFolder1Name );
+        connectionsViewBot.openDeleteConnectionFolderDialog().clickOkButton();
+
+        // ensure connection folders are visible
+        assertEquals( 2, connectionsViewBot.getCount() );
+
+        // delete connection folder
+        connectionsViewBot.select( folderName );
+        connectionsViewBot.openDeleteConnectionFolderDialog().clickOkButton();
+
+        // ensure folders no longer exist
+        assertEquals( 0, connectionsViewBot.getCount() );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testExportImportConnections( TestLdapServer server ) throws Exception
+    {
+        String connection1Name = "Test connection 1";
+        String connection2Name = "Test connection 2";
+        String connection3Name = "Test connection 3";
+        String folderName = "Connection folder 1";
+        String subFolder1Name = "Connection folder 2";
+        String subFolder2Name = "Connection folder 3";
+
+        // create connections and folders
+        createConnection( connection1Name, server );
+        createConnectionFolder( folderName );
+        connectionsViewBot.select( folderName );
+        createConnection( connection2Name, server );
+        connectionsViewBot.select( folderName );
+        createConnectionFolder( subFolder1Name );
+        connectionsViewBot.select( folderName, subFolder1Name );
+        createConnection( connection3Name, server );
+        connectionsViewBot.select( folderName );
+        createConnectionFolder( subFolder2Name );
+
+        // verify connections and folders exist
+        assertEquals( 6, connectionsViewBot.getCount() );
+        connectionsViewBot.select( folderName );
+        connectionsViewBot.select( folderName, subFolder1Name );
+        connectionsViewBot.select( folderName, subFolder2Name );
+        connectionsViewBot.select( connection1Name );
+        connectionsViewBot.select( folderName, connection2Name );
+        connectionsViewBot.select( folderName, subFolder1Name, connection3Name );
+
+        // export connections and folders
+        URL url = Platform.getInstanceLocation().getURL();
+        final String file = url.getFile() + "ImportExportConnections" + server.getType() + ".zip";
+        ExportConnectionsWizardBot exportConnectionsWizardBot = connectionsViewBot.openExportConnectionsWizard();
+        exportConnectionsWizardBot.typeFile( file );
+        exportConnectionsWizardBot.clickFinishButton();
+
+        // delete connections and folders
+        connectionsViewBot.deleteTestConnections();
+        assertEquals( 0, connectionsViewBot.getCount() );
+
+        // import connections and folders
+        ImportConnectionsWizardBot importConnectionsWizardBot = connectionsViewBot.openImportConnectionsWizard();
+        importConnectionsWizardBot.typeFile( file );
+        importConnectionsWizardBot.clickFinishButton();
+
+        // verify connections and folders exist
+        assertEquals( 6, connectionsViewBot.getCount() );
+        connectionsViewBot.select( folderName );
+        connectionsViewBot.select( folderName, subFolder1Name );
+        connectionsViewBot.select( folderName, subFolder2Name );
+        connectionsViewBot.select( connection1Name );
+        connectionsViewBot.select( folderName, connection2Name );
+        connectionsViewBot.select( folderName, subFolder1Name, connection3Name );
+    }
+
+
+    private void createConnection( String connectionName, TestLdapServer server )
+    {
+        NewConnectionWizardBot wizardBot = connectionsViewBot.openNewConnectionWizard();
+
+        // enter connection parameter
+        wizardBot.typeConnectionName( connectionName );
+        wizardBot.typeHost( server.getHost() );
+        wizardBot.typePort( server.getPort() );
+
+        // jump to auth page
+        wizardBot.clickNextButton();
+
+        // enter authentication parameters
+        wizardBot.typeUser( server.getAdminDn() );
+        wizardBot.typePassword( server.getAdminPassword() );
+
+        // finish dialog
+        wizardBot.clickFinishButton( true );
+    }
+
+
+    private void createConnectionFolder( String folderName )
+    {
+        NewConnectionFolderDialogBot newConnectionFolderDialog = connectionsViewBot.openNewConnectionFolderDialog();
+        newConnectionFolderDialog.setConnectionFoldername( folderName );
+        newConnectionFolderDialog.clickOkButton();
+    }
+
+}
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/CopyEntryTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/CopyEntryTest.java
index cafe850..5b2763a 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/CopyEntryTest.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/CopyEntryTest.java
@@ -21,31 +21,33 @@
 package org.apache.directory.studio.test.integration.ui;
 
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.ALIAS_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.CONTEXT_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.TARGET_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.REFERRAL_TO_USER1_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.SUBENTRY_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USER1_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USERS_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.dn;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import org.apache.directory.server.annotations.CreateLdapServer;
-import org.apache.directory.server.annotations.CreateTransport;
-import org.apache.directory.server.core.annotations.ApplyLdifFiles;
-import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
+import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.studio.connection.core.Connection;
 import org.apache.directory.studio.connection.core.Connection.AliasDereferencingMethod;
 import org.apache.directory.studio.ldapbrowser.core.BrowserCoreConstants;
 import org.apache.directory.studio.ldapbrowser.core.BrowserCorePlugin;
 import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection;
 import org.apache.directory.studio.ldifparser.LdifParserConstants;
-import org.apache.directory.studio.test.integration.ui.bots.BrowserViewBot;
-import org.apache.directory.studio.test.integration.ui.bots.ConnectionsViewBot;
-import org.apache.directory.studio.test.integration.ui.bots.ModificationLogsViewBot;
+import org.apache.directory.studio.test.integration.junit5.LdapServerType;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource;
+import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
 import org.apache.directory.studio.test.integration.ui.bots.SelectCopyDepthDialogBot;
 import org.apache.directory.studio.test.integration.ui.bots.SelectCopyStrategyBot;
-import org.apache.directory.studio.test.integration.ui.bots.StudioBot;
-import org.apache.directory.studio.test.integration.ui.bots.utils.Assertions;
-import org.apache.directory.studio.test.integration.ui.bots.utils.FrameworkRunnerWithScreenshotCaptureListener;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable;
+import org.eclipse.swtbot.swt.finder.results.VoidResult;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.params.ParameterizedTest;
 
 
 /**
@@ -54,92 +56,71 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-@RunWith(FrameworkRunnerWithScreenshotCaptureListener.class)
-@CreateLdapServer(transports =
-    { @CreateTransport(protocol = "LDAP") })
-@ApplyLdifFiles(clazz = CopyEntryTest.class, value = "org/apache/directory/studio/test/integration/ui/BrowserTest.ldif")
-public class CopyEntryTest extends AbstractLdapTestUnit
+public class CopyEntryTest extends AbstractTestBase
 {
-    private StudioBot studioBot;
-    private ConnectionsViewBot connectionsViewBot;
-    private BrowserViewBot browserViewBot;
-    private ModificationLogsViewBot modificationLogsViewBot;
-    private Connection connection;
 
-
-    @Before
-    public void setUp() throws Exception
+    @AfterEach
+    public void resetPreferences()
     {
-        studioBot = new StudioBot();
-        studioBot.resetLdapPerspective();
-        connectionsViewBot = studioBot.getConnectionView();
-        connection = connectionsViewBot.createTestConnection( "CopyEntryTest", ldapServer.getPort() );
-        browserViewBot = studioBot.getBrowserView();
-        modificationLogsViewBot = studioBot.getModificationLogsViewBot();
-    }
-
-
-    @After
-    public void tearDown() throws Exception
-    {
-        connectionsViewBot.deleteTestConnections();
-        Assertions.genericTearDownAssertions();
         // DIRSERVER-2133: reset check for children preference
-        BrowserCorePlugin.getDefault()
-            .getPluginPreferences().setValue( BrowserCoreConstants.PREFERENCE_CHECK_FOR_CHILDREN, true );
+        UIThreadRunnable.syncExec( () -> {
+            BrowserCorePlugin.getDefault()
+                .getPluginPreferences().setValue( BrowserCoreConstants.PREFERENCE_CHECK_FOR_CHILDREN, true );
+        } );
     }
 
 
-    @Test
-    public void testCopyPasteSingleEntryWithoutCopyDepthDialog() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCopyPasteSingleEntryWithoutCopyDepthDialog( TestLdapServer server ) throws Exception
     {
+        Dn newDn = dn( USER1_DN.getRdn(), TARGET_DN );
+
         // expand the entry to avoid copy depth dialog
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.1" );
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.1" );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( USER1_DN ) );
+        browserViewBot.expandEntry( path( USER1_DN ) );
 
         // copy an entry
         browserViewBot.copy();
 
         // select the parent entry where the copied entry should be pasted to
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "l=eu + l=de + l=Berlin + l=Brandenburger Tor" );
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "l=eu + l=de + l=Berlin + l=Brandenburger Tor", "uid=user.1" ) );
+        browserViewBot.selectEntry( path( TARGET_DN ) );
+        assertFalse( browserViewBot.existsEntry( path( newDn ) ) );
 
         // paste the entry
         browserViewBot.pasteEntry();
 
         // verify the entry was copied
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "l=eu + l=de + l=Berlin + l=Brandenburger Tor", "uid=user.1" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "l=eu + l=de + l=Berlin + l=Brandenburger Tor", "uid=user.1" );
+        assertTrue( browserViewBot.existsEntry( path( newDn ) ) );
+        browserViewBot.selectEntry( path( newDn ) );
 
         // verify in modification logs
-        modificationLogsViewBot.assertContainsOk(
-            "dn: uid=user.1,l=eu + l=de + l=Berlin + l=Brandenburger Tor,ou=users,ou=system", "changetype: add" );
+        modificationLogsViewBot.assertContainsOk( "dn: " + newDn.getName(), "changetype: add" );
     }
 
 
-    @Test
-    public void testCopyPasteMultipleEntriesWithCopyDepthDialogObjectOnly() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCopyPasteMultipleEntriesWithCopyDepthDialogObjectOnly( TestLdapServer server ) throws Exception
     {
         // DIRSERVER-2133: disable check for children for this test
-        BrowserCorePlugin.getDefault()
-            .getPluginPreferences().setValue( BrowserCoreConstants.PREFERENCE_CHECK_FOR_CHILDREN, false );
+        UIThreadRunnable.syncExec( () -> {
+            BrowserCorePlugin.getDefault()
+                .getPluginPreferences().setValue( BrowserCoreConstants.PREFERENCE_CHECK_FOR_CHILDREN, false );
+        } );
 
         // select and copy multiple entries
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.expandEntry( path( USERS_DN ) );
         String[] children =
             { "uid=user.1", "uid=user.2", "uid=user.3", "uid=user.4" };
-        browserViewBot.selectChildrenOfEntry( children, "DIT", "Root DSE", "ou=system", "ou=users" );
+        browserViewBot.selectChildrenOfEntry( children, path( USERS_DN ) );
         browserViewBot.copy();
 
         // select the parent entry where the copied entries should be pasted to
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "l=eu + l=de + l=Berlin + l=Brandenburger Tor" );
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "l=eu + l=de + l=Berlin + l=Brandenburger Tor", "uid=user.1" ) );
+        browserViewBot.selectEntry( path( TARGET_DN ) );
+        assertFalse( browserViewBot.existsEntry( path( TARGET_DN, "uid=user.1" ) ) );
 
         // paste the entry
         SelectCopyDepthDialogBot dialog = browserViewBot.pasteEntriesExpectingSelectCopyDepthDialog( 4 );
@@ -147,41 +128,35 @@
         dialog.clickOkButton();
 
         // verify the entries were copied
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "l=eu + l=de + l=Berlin + l=Brandenburger Tor", "uid=user.1" ) );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "l=eu + l=de + l=Berlin + l=Brandenburger Tor", "uid=user.2" ) );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "l=eu + l=de + l=Berlin + l=Brandenburger Tor", "uid=user.3" ) );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "l=eu + l=de + l=Berlin + l=Brandenburger Tor", "uid=user.4" ) );
+        assertTrue( browserViewBot.existsEntry( path( TARGET_DN, "uid=user.1" ) ) );
+        assertTrue( browserViewBot.existsEntry( path( TARGET_DN, "uid=user.2" ) ) );
+        assertTrue( browserViewBot.existsEntry( path( TARGET_DN, "uid=user.3" ) ) );
+        assertTrue( browserViewBot.existsEntry( path( TARGET_DN, "uid=user.4" ) ) );
 
         // verify in modification logs
-        modificationLogsViewBot.assertContainsOk(
-            "dn: uid=user.1,l=eu + l=de + l=Berlin + l=Brandenburger Tor,ou=users,ou=system", "changetype: add" );
-        modificationLogsViewBot.assertContainsOk(
-            "dn: uid=user.2,l=eu + l=de + l=Berlin + l=Brandenburger Tor,ou=users,ou=system", "changetype: add" );
-        modificationLogsViewBot.assertContainsOk(
-            "dn: uid=user.3,l=eu + l=de + l=Berlin + l=Brandenburger Tor,ou=users,ou=system", "changetype: add" );
-        modificationLogsViewBot.assertContainsOk(
-            "dn: uid=user.4,l=eu + l=de + l=Berlin + l=Brandenburger Tor,ou=users,ou=system", "changetype: add" );
+        modificationLogsViewBot.assertContainsOk( "dn: " + dn( "uid=user.1", TARGET_DN ), "changetype: add" );
+        modificationLogsViewBot.assertContainsOk( "dn: " + dn( "uid=user.2", TARGET_DN ), "changetype: add" );
+        modificationLogsViewBot.assertContainsOk( "dn: " + dn( "uid=user.3", TARGET_DN ), "changetype: add" );
+        modificationLogsViewBot.assertContainsOk( "dn: " + dn( "uid=user.4", TARGET_DN ), "changetype: add" );
     }
 
 
-    @Test
-    public void testCopyPasteMultipleEntriesWithCopyDepthDialogSubtree() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCopyPasteMultipleEntriesWithCopyDepthDialogSubtree( TestLdapServer server ) throws Exception
     {
         // select and copy multiple entries
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system" );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.expandEntry( path( CONTEXT_DN ) );
         String[] children =
             { "ou=users", "ou=groups" };
-        browserViewBot.selectChildrenOfEntry( children, "DIT", "Root DSE", "ou=system" );
+        browserViewBot.selectChildrenOfEntry( children, path( CONTEXT_DN ) );
         browserViewBot.copy();
 
         // select the parent entry where the copied entries should be pasted to
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=target" );
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=target", "ou=users" ) );
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=target", "ou=groups" ) );
+        browserViewBot.selectEntry( path( TARGET_DN ) );
+        assertFalse( browserViewBot.existsEntry( path( TARGET_DN, "ou=users" ) ) );
+        assertFalse( browserViewBot.existsEntry( path( TARGET_DN, "ou=groups" ) ) );
 
         // paste the entry
         SelectCopyDepthDialogBot dialog = browserViewBot.pasteEntriesExpectingSelectCopyDepthDialog( 2 );
@@ -189,40 +164,32 @@
         dialog.clickOkButton();
 
         // verify the entries were copied
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=target", "ou=users" ) );
-        assertTrue(
-            browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=target", "ou=users", "uid=user.1" ) );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=target", "ou=users",
-            "cn=\\#ACL_AD-Projects_Author" ) );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=target", "ou=users",
-            "l=eu + l=de + l=Berlin + l=Brandenburger Tor", "cn=A" ) );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=target", "ou=groups" ) );
-        assertTrue(
-            browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=target", "ou=groups",
-                "cn=Administrators" ) );
+        assertTrue( browserViewBot.existsEntry( path( TARGET_DN, "ou=users" ) ) );
+        assertTrue( browserViewBot.existsEntry( path( TARGET_DN, "ou=users", "uid=user.1" ) ) );
+        assertTrue( browserViewBot.existsEntry( path( TARGET_DN, "ou=users", "uid=user.8" ) ) );
+        assertTrue( browserViewBot.existsEntry( path( TARGET_DN, "ou=groups" ) ) );
+        assertTrue( browserViewBot.existsEntry( path( TARGET_DN, "ou=groups", "cn=group.1" ) ) );
 
         // verify in modification logs
-        modificationLogsViewBot.assertContainsOk( "dn: ou=users,ou=target,ou=system", "changetype: add" );
-        modificationLogsViewBot.assertContainsOk(
-            "dn: cn=A,l=eu + l=de + l=Berlin + l=Brandenburger Tor,ou=users,ou=target,ou=system", "changetype: add" );
-        modificationLogsViewBot.assertContainsOk( "dn: ou=groups,ou=target,ou=system", "changetype: add" );
-        modificationLogsViewBot.assertContainsOk( "dn: cn=Administrators,ou=groups,ou=target,ou=system",
-            "changetype: add" );
+        modificationLogsViewBot.assertContainsOk( "dn: " + dn( "ou=users", TARGET_DN ), "changetype: add" );
+        modificationLogsViewBot.assertContainsOk( "dn: " + dn( "ou=groups", TARGET_DN ), "changetype: add" );
     }
 
 
-    @Test
-    public void testCopyPasteSingleEntryOverwrite() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCopyPasteSingleEntryOverwrite( TestLdapServer server ) throws Exception
     {
         // expand the entry to avoid copy depth dialog
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.1" );
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.1" );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( USER1_DN ) );
+        browserViewBot.expandEntry( path( USER1_DN ) );
 
         // copy an entry
         browserViewBot.copy();
 
         // select the parent entry where the copied entry should be pasted to
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
+        browserViewBot.selectEntry( path( USERS_DN ) );
 
         // paste the entry
         SelectCopyStrategyBot dialog = browserViewBot.pasteEntriesExpectingSelectCopyStrategy();
@@ -230,91 +197,134 @@
         dialog.clickOkButton();
 
         // verify in modification logs
-        modificationLogsViewBot.assertContainsError( "ENTRY_ALREADY_EXISTS", "dn: uid=user.1,ou=users,ou=system",
-            "changetype: add", "uid: user.1" );
-        modificationLogsViewBot.assertContainsOk( "dn: uid=user.1,ou=users,ou=system", "changetype: modify",
-            "replace: uid" + LdifParserConstants.LINE_SEPARATOR + "uid: user.1" + LdifParserConstants.LINE_SEPARATOR
-                + "-",
-            "replace: objectclass" );
+        modificationLogsViewBot.assertContainsError( "[LDAP result code 68 - entryAlreadyExists]",
+            "dn: " + USER1_DN.getName(), "changetype: add", "uid: user.1" );
+        modificationLogsViewBot.assertContainsOk( "dn: " + USER1_DN.getName(), "changetype: modify", "replace: uid"
+            + LdifParserConstants.LINE_SEPARATOR + "uid: user.1" + LdifParserConstants.LINE_SEPARATOR + "-",
+            "replace: objectClass" );
     }
 
 
-    @Test
-    public void testCopyPasteSingleEntryRename() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCopyPasteSingleEntryRename( TestLdapServer server ) throws Exception
     {
         // expand the entry to avoid copy depth dialog
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.1" );
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.1" );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( USER1_DN ) );
+        browserViewBot.expandEntry( path( USER1_DN ) );
 
         // copy an entry
         browserViewBot.copy();
 
         // select the parent entry where the copied entry should be pasted to
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
+        browserViewBot.selectEntry( path( USERS_DN ) );
 
         // paste the entry
+        Dn renamedDn = dn( "uid=user.renamed", USERS_DN );
         SelectCopyStrategyBot dialog = browserViewBot.pasteEntriesExpectingSelectCopyStrategy();
         dialog.selectRenameEntryAndContinue();
         dialog.setRdnValue( 1, "user.renamed" );
         dialog.clickOkButton();
 
         // verify the entry was copied
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.renamed" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.renamed" );
+        assertTrue( browserViewBot.existsEntry( path( renamedDn ) ) );
+        browserViewBot.selectEntry( path( renamedDn ) );
 
         // verify in modification logs
-        modificationLogsViewBot.assertContainsError( "ENTRY_ALREADY_EXISTS", "dn: uid=user.1,ou=users,ou=system",
-            "changetype: add", "uid: user.1" );
-        modificationLogsViewBot.assertContainsOk( "dn: uid=user.renamed,ou=users,ou=system", "changetype: add",
+        modificationLogsViewBot.assertContainsError( "[LDAP result code 68 - entryAlreadyExists]",
+            "dn: " + USER1_DN.getName(), "changetype: add", "uid: user.1" );
+        modificationLogsViewBot.assertContainsOk( "dn: " + renamedDn.getName(), "changetype: add",
             "uid: user.renamed" );
     }
 
 
-    @Test
-    public void testCopyPasteSpecialEntries() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCopyPasteAliasEntry( TestLdapServer server ) throws Exception
     {
         // disable alias dereferencing
+        Connection connection = connectionsViewBot.createTestConnection( server );
         connection.getConnectionParameter().setExtendedIntProperty(
             IBrowserConnection.CONNECTION_PARAMETER_ALIASES_DEREFERENCING_METHOD,
             AliasDereferencingMethod.NEVER.ordinal() );
+
+        // expand the entry to avoid copy depth dialog
+        browserViewBot.expandEntry( path( ALIAS_DN ) );
+        browserViewBot.selectEntry( path( ALIAS_DN ) );
+        browserViewBot.copy();
+
+        // select the parent entry where the copied entry should be pasted to
+        browserViewBot.selectEntry( path( TARGET_DN ) );
+        assertFalse( browserViewBot.existsEntry( path( TARGET_DN, ALIAS_DN.getRdn() ) ) );
+
+        // paste the entry
+        browserViewBot.pasteEntries( 1 );
+
+        // verify the entyr was copied
+        assertTrue( browserViewBot.existsEntry( path( TARGET_DN, ALIAS_DN.getRdn() ) ) );
+
+        // verify in modification logs
+        modificationLogsViewBot.assertContainsOk( "dn: " + dn( ALIAS_DN.getRdn(), TARGET_DN ), "changetype: add" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCopyPasteReferralEntry( TestLdapServer server ) throws Exception
+    {
         // enable ManageDsaIT control
+        Connection connection = connectionsViewBot.createTestConnection( server );
         connection.getConnectionParameter().setExtendedBoolProperty(
             IBrowserConnection.CONNECTION_PARAMETER_MANAGE_DSA_IT, true );
+
+        // expand the entry to avoid copy depth dialog
+        browserViewBot.expandEntry( path( REFERRAL_TO_USER1_DN ) );
+        browserViewBot.selectEntry( path( REFERRAL_TO_USER1_DN ) );
+        browserViewBot.copy();
+
+        // select the parent entry where the copied entry should be pasted to
+        browserViewBot.selectEntry( path( TARGET_DN ) );
+        assertFalse( browserViewBot.existsEntry( path( TARGET_DN, REFERRAL_TO_USER1_DN.getRdn() ) ) );
+
+        // paste the entry
+        browserViewBot.pasteEntries( 1 );
+
+        // verify the entry was copied
+        assertTrue( browserViewBot.existsEntry( path( TARGET_DN, REFERRAL_TO_USER1_DN.getRdn() ) ) );
+
+        // verify in modification logs
+        modificationLogsViewBot.assertContainsOk( "dn: " + dn( REFERRAL_TO_USER1_DN.getRdn(), TARGET_DN ),
+            "changetype: add" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.ApacheDS, reason = "ApacheDS specific test")
+    public void testCopyPasteSubentry( TestLdapServer server ) throws Exception
+    {
         // enable Subentries control
+        Connection connection = connectionsViewBot.createTestConnection( server );
         connection.getConnectionParameter().setExtendedBoolProperty(
             IBrowserConnection.CONNECTION_PARAMETER_FETCH_SUBENTRIES, true );
 
-        // expand the entries to avoid copy depth dialog
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=special", "cn=alias" );
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=special", "cn=referral" );
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=special", "cn=subentry" );
-
-        // select and copy the entries
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=special" );
-        String[] children =
-            { "cn=alias", "cn=referral", "cn=subentry" };
-        browserViewBot.selectChildrenOfEntry( children, "DIT", "Root DSE", "ou=system", "ou=special" );
+        // expand the entry to avoid copy depth dialog
+        browserViewBot.expandEntry( path( SUBENTRY_DN ) );
+        browserViewBot.selectEntry( path( SUBENTRY_DN ) );
         browserViewBot.copy();
 
-        // select the parent entry where the copied entries should be pasted to
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=target" );
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=target", "cn=alias" ) );
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=target", "cn=referral" ) );
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=target", "cn=subentry" ) );
+        // select the parent entry where the copied entry should be pasted to
+        browserViewBot.selectEntry( path( TARGET_DN ) );
+        assertFalse( browserViewBot.existsEntry( path( TARGET_DN, SUBENTRY_DN.getRdn() ) ) );
 
-        // paste the entries
-        browserViewBot.pasteEntries( 3 );
+        // paste the entry
+        browserViewBot.pasteEntries( 1 );
 
-        // verify the entries was copied
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=target", "cn=alias" ) );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=target", "cn=referral" ) );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=target", "cn=subentry" ) );
+        // verify the entry was copied
+        assertTrue( browserViewBot.existsEntry( path( TARGET_DN, SUBENTRY_DN.getRdn() ) ) );
 
         // verify in modification logs
-        modificationLogsViewBot.assertContainsOk( "dn: cn=alias,ou=target,ou=system", "changetype: add" );
-        modificationLogsViewBot.assertContainsOk( "dn: cn=referral,ou=target,ou=system",
-            "control: 2.16.840.1.113730.3.4.2 false", "changetype: add" );
-        modificationLogsViewBot.assertContainsOk( "dn: cn=subentry,ou=target,ou=system", "changetype: add" );
+        modificationLogsViewBot.assertContainsOk( "dn: " + dn( SUBENTRY_DN.getRdn(), TARGET_DN ), "changetype: add" );
     }
 
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/EntryEditorTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/EntryEditorTest.java
index e3ed3aa..220dc20 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/EntryEditorTest.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/EntryEditorTest.java
@@ -21,64 +21,55 @@
 package org.apache.directory.studio.test.integration.ui;
 
 
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.BJENSEN_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.GROUP1_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.HNELSON_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.MULTI_VALUED_RDN_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USER1_DN;
 import static org.hamcrest.CoreMatchers.startsWith;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import java.io.File;
-import java.io.InputStream;
-import java.net.URL;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.cert.X509Certificate;
-
+import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.directory.api.ldap.model.constants.AuthenticationLevel;
 import org.apache.directory.api.ldap.model.constants.LdapSecurityConstants;
-import org.apache.directory.api.ldap.model.entry.DefaultModification;
 import org.apache.directory.api.ldap.model.entry.Entry;
-import org.apache.directory.api.ldap.model.entry.ModificationOperation;
-import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.password.PasswordUtil;
-import org.apache.directory.api.util.FileUtils;
-import org.apache.directory.api.util.IOUtils;
 import org.apache.directory.api.util.Strings;
-import org.apache.directory.server.annotations.CreateLdapServer;
-import org.apache.directory.server.annotations.CreateTransport;
-import org.apache.directory.server.core.annotations.ApplyLdifFiles;
-import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
-import org.apache.directory.server.core.security.CertificateUtil;
+import org.apache.directory.studio.connection.core.Connection;
 import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
+import org.apache.directory.studio.ldapbrowser.core.BrowserCorePlugin;
+import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection;
+import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection.ModifyMode;
 import org.apache.directory.studio.ldifparser.LdifFormatParameters;
 import org.apache.directory.studio.ldifparser.LdifParserConstants;
 import org.apache.directory.studio.ldifparser.model.lines.LdifAttrValLine;
-import org.apache.directory.studio.test.integration.ui.bots.BotUtils;
-import org.apache.directory.studio.test.integration.ui.bots.BrowserViewBot;
-import org.apache.directory.studio.test.integration.ui.bots.ConnectionsViewBot;
+import org.apache.directory.studio.test.integration.junit5.LdapServerType;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource;
+import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource.Mode;
+import org.apache.directory.studio.test.integration.ui.bots.AciItemEditorDialogBot;
+import org.apache.directory.studio.test.integration.ui.bots.CertificateEditorDialogBot;
 import org.apache.directory.studio.test.integration.ui.bots.DnEditorDialogBot;
+import org.apache.directory.studio.test.integration.ui.bots.EditAttributeWizardBot;
 import org.apache.directory.studio.test.integration.ui.bots.EntryEditorBot;
+import org.apache.directory.studio.test.integration.ui.bots.HexEditorDialogBot;
 import org.apache.directory.studio.test.integration.ui.bots.ImageEditorDialogBot;
-import org.apache.directory.studio.test.integration.ui.bots.ModificationLogsViewBot;
 import org.apache.directory.studio.test.integration.ui.bots.NewAttributeWizardBot;
 import org.apache.directory.studio.test.integration.ui.bots.PasswordEditorDialogBot;
 import org.apache.directory.studio.test.integration.ui.bots.SelectDnDialogBot;
-import org.apache.directory.studio.test.integration.ui.bots.StudioBot;
+import org.apache.directory.studio.test.integration.ui.bots.SubtreeSpecificationEditorDialogBot;
 import org.apache.directory.studio.test.integration.ui.bots.TextEditorDialogBot;
-import org.apache.directory.studio.test.integration.ui.bots.utils.Assertions;
-import org.apache.directory.studio.test.integration.ui.bots.utils.Characters;
-import org.apache.directory.studio.test.integration.ui.bots.utils.FrameworkRunnerWithScreenshotCaptureListener;
-import org.apache.directory.studio.test.integration.ui.bots.utils.JobWatcher;
-import org.eclipse.core.runtime.Platform;
+import org.apache.directory.studio.test.integration.ui.utils.Characters;
+import org.apache.directory.studio.test.integration.ui.utils.JobWatcher;
+import org.apache.directory.studio.test.integration.ui.utils.ResourceUtils;
 import org.eclipse.swtbot.swt.finder.utils.SWTUtils;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import sun.security.x509.X500Name;
+import org.junit.jupiter.params.ParameterizedTest;
 
 
 /**
@@ -87,54 +78,23 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-@RunWith(FrameworkRunnerWithScreenshotCaptureListener.class)
-@CreateLdapServer(transports =
-    { @CreateTransport(protocol = "LDAP") })
-@ApplyLdifFiles(clazz = EntryEditorTest.class, value =
-    { "org/apache/directory/studio/test/integration/ui/EntryEditorTest.ldif" })
-public class EntryEditorTest extends AbstractLdapTestUnit
+public class EntryEditorTest extends AbstractTestBase
 {
-    private StudioBot studioBot;
-    private ConnectionsViewBot connectionsViewBot;
-    private BrowserViewBot browserViewBot;
-    private ModificationLogsViewBot modificationLogsViewBot;
-
-
-    @Before
-    public void setUp() throws Exception
-    {
-        studioBot = new StudioBot();
-        studioBot.resetLdapPerspective();
-        connectionsViewBot = studioBot.getConnectionView();
-        connectionsViewBot.createTestConnection( "EntryEditorTest", ldapServer.getPort() );
-        browserViewBot = studioBot.getBrowserView();
-        modificationLogsViewBot = studioBot.getModificationLogsViewBot();
-    }
-
-
-    @After
-    public void tearDown() throws Exception
-    {
-        connectionsViewBot.deleteTestConnections();
-        Assertions.genericTearDownAssertions();
-    }
-
 
     /**
      * Test adding, editing and deleting of attributes in the entry editor.
-     *
-     * @throws Exception
-     *             the exception
      */
-    @Test
-    public void testAddEditDeleteAttribute() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testAddEditDeleteAttribute( TestLdapServer server ) throws Exception
     {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=Barbara Jensen" );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( BJENSEN_DN ) );
 
-        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( "cn=Barbara Jensen,ou=users,ou=system" );
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( BJENSEN_DN.getName() );
         entryEditorBot.activate();
         String dn = entryEditorBot.getDnText();
-        assertEquals( "DN: cn=Barbara Jensen,ou=users,ou=system", dn );
+        assertEquals( "DN: " + BJENSEN_DN.getName(), dn );
         assertEquals( 8, entryEditorBot.getAttributeValues().size() );
         assertEquals( "", modificationLogsViewBot.getModificationLogsText() );
 
@@ -162,7 +122,6 @@
         entryEditorBot.editValue( "description", "This is the 2nd description." );
         entryEditorBot.typeValueAndFinish( "This is the 3rd description." );
         assertEquals( 10, entryEditorBot.getAttributeValues().size() );
-        assertEquals( 10, entryEditorBot.getAttributeValues().size() );
         assertTrue( entryEditorBot.getAttributeValues().contains( "description: This is the 1st description." ) );
         assertFalse( entryEditorBot.getAttributeValues().contains( "description: This is the 2nd description." ) );
         assertTrue( entryEditorBot.getAttributeValues().contains( "description: This is the 3rd description." ) );
@@ -182,35 +141,172 @@
         assertEquals( 9, entryEditorBot.getAttributeValues().size() );
         assertFalse( entryEditorBot.getAttributeValues().contains( "description: This is the 1st description." ) );
         assertTrue( entryEditorBot.getAttributeValues().contains( "description: This is the final description." ) );
-        modificationLogsViewBot.waitForText( "replace: description\ndescription: This is the final description." );
+        modificationLogsViewBot.waitForText( "delete: description\ndescription: This is the 1st description." );
+        modificationLogsViewBot.waitForText( "add: description\ndescription: This is the final description." );
 
         // delete 1st value/attribute
         entryEditorBot.deleteValue( "description", "This is the final description." );
         assertEquals( 8, entryEditorBot.getAttributeValues().size() );
         assertFalse( entryEditorBot.getAttributeValues().contains( "description: This is the final description." ) );
-        modificationLogsViewBot.waitForText( "delete: description\n-" );
+        modificationLogsViewBot.waitForText( "delete: description\ndescription: This is the final description.\n-" );
 
-        assertEquals( "Expected 6 modifications.", 6,
-            StringUtils.countMatches( modificationLogsViewBot.getModificationLogsText(), "#!RESULT OK" ) );
+        assertEquals( 6, StringUtils.countMatches( modificationLogsViewBot.getModificationLogsText(), "#!RESULT OK" ),
+            "Expected 6 modifications." );
+    }
+
+
+    /**
+     * Test adding, editing and deleting of attributes without equality matching rule in the entry editor.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testAddEditDeleteAttributeWithoutEqualityMatchingRule( TestLdapServer server ) throws Exception
+    {
+        Connection connection = connectionsViewBot.createTestConnection( server );
+
+        if ( server.getType() == LdapServerType.OpenLdap )
+        {
+            IBrowserConnection browserConnection = BrowserCorePlugin.getDefault().getConnectionManager()
+                .getBrowserConnection( connection );
+            browserConnection.setModifyModeNoEMR( ModifyMode.REPLACE );
+        }
+
+        browserViewBot.selectEntry( path( BJENSEN_DN ) );
+
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( BJENSEN_DN.getName() );
+        entryEditorBot.activate();
+        String dn = entryEditorBot.getDnText();
+        assertEquals( "DN: " + BJENSEN_DN.getName(), dn );
+        assertEquals( 8, entryEditorBot.getAttributeValues().size() );
+        assertEquals( "", modificationLogsViewBot.getModificationLogsText() );
+
+        // add facsimileTelephoneNumber attribute
+        entryEditorBot.activate();
+        NewAttributeWizardBot wizardBot = entryEditorBot.openNewAttributeWizard();
+        assertTrue( wizardBot.isVisible() );
+        wizardBot.typeAttributeType( "facsimileTelephoneNumber" );
+        wizardBot.clickFinishButton();
+        entryEditorBot.typeValueAndFinish( "+1 234 567 890" );
+        assertEquals( 9, entryEditorBot.getAttributeValues().size() );
+        assertTrue( entryEditorBot.getAttributeValues().contains( "facsimileTelephoneNumber: +1 234 567 890" ) );
+        if ( server.getType() == LdapServerType.OpenLdap )
+        {
+            modificationLogsViewBot
+                .waitForText( "replace: facsimileTelephoneNumber\nfacsimileTelephoneNumber: +1 234 567 890" );
+
+        }
+        else
+        {
+            modificationLogsViewBot
+                .waitForText( "add: facsimileTelephoneNumber\nfacsimileTelephoneNumber: +1 234 567 890" );
+
+        }
+
+        // edit value
+        entryEditorBot.editValue( "facsimileTelephoneNumber", "+1 234 567 890" );
+        entryEditorBot.typeValueAndFinish( "000000000000" );
+        assertEquals( 9, entryEditorBot.getAttributeValues().size() );
+        assertFalse( entryEditorBot.getAttributeValues().contains( "facsimileTelephoneNumber: +1 234 567 890" ) );
+        assertTrue( entryEditorBot.getAttributeValues().contains( "facsimileTelephoneNumber: 000000000000" ) );
+        if ( server.getType() == LdapServerType.OpenLdap )
+        {
+            modificationLogsViewBot
+                .waitForText( "replace: facsimileTelephoneNumber\nfacsimileTelephoneNumber: 000000000000" );
+
+        }
+        else
+        {
+            modificationLogsViewBot
+                .waitForText( "delete: facsimileTelephoneNumber\nfacsimileTelephoneNumber: +1 234 567 890" );
+            modificationLogsViewBot
+                .waitForText( "add: facsimileTelephoneNumber\nfacsimileTelephoneNumber: 000000000000" );
+        }
+
+        // delete 1st value/attribute
+        entryEditorBot.deleteValue( "facsimileTelephoneNumber", "000000000000" );
+        assertEquals( 8, entryEditorBot.getAttributeValues().size() );
+        assertFalse( entryEditorBot.getAttributeValues().contains( "facsimileTelephoneNumber: 000000000000" ) );
+        if ( server.getType() == LdapServerType.OpenLdap )
+        {
+            modificationLogsViewBot.waitForText( "replace: facsimileTelephoneNumber\n-" );
+
+        }
+        else
+        {
+            modificationLogsViewBot
+                .waitForText( "delete: facsimileTelephoneNumber\nfacsimileTelephoneNumber: 000000000000\n-" );
+        }
+
+        assertEquals( 3, StringUtils.countMatches( modificationLogsViewBot.getModificationLogsText(), "#!RESULT OK" ),
+            "Expected 3 modifications." );
+    }
+
+
+    /**
+     * DIRSTUDIO-1267:Test adding, editing and deleting of attributes with language tag in the entry editor.
+     */
+    @ParameterizedTest
+    @LdapServersSource(except = LdapServerType.ApacheDS, reason = "Language tags not yet supported by ApacheDS")
+    public void testAddEditDeleteAttributeWithLanguageTag( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( USER1_DN ) );
+
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( USER1_DN.getName() );
+        entryEditorBot.activate();
+
+        // add attribute description;lang-en
+        entryEditorBot.activate();
+        NewAttributeWizardBot wizardBot = entryEditorBot.openNewAttributeWizard();
+        assertTrue( wizardBot.isVisible() );
+        wizardBot.typeAttributeType( "description" );
+        wizardBot.clickNextButton();
+        wizardBot.setLanguageTag( "en", "" );
+        wizardBot.clickFinishButton();
+        entryEditorBot.typeValueAndFinish( "English" );
+        modificationLogsViewBot.waitForText( "add: description;lang-en\ndescription;lang-en: English\n-" );
+        assertTrue( entryEditorBot.getAttributeValues().contains( "description;lang-en: English" ) );
+
+        // edit the attribute to description;lang-en
+        EditAttributeWizardBot editWizardBot = entryEditorBot.editAttribute( "description;lang-en", "English" );
+        editWizardBot.clickNextButton();
+        editWizardBot.setLanguageTag( "en", "us" );
+        editWizardBot.clickFinishButton();
+        modificationLogsViewBot.waitForText( "delete: description;lang-en\ndescription;lang-en: English\n-" );
+        modificationLogsViewBot.waitForText( "add: description;lang-en-us\ndescription;lang-en-us: English\n-" );
+        assertFalse( entryEditorBot.getAttributeValues().contains( "description;lang-en: English" ) );
+        assertTrue( entryEditorBot.getAttributeValues().contains( "description;lang-en-us: English" ) );
+
+        // edit the value
+        entryEditorBot.editValue( "description;lang-en-us", "English" );
+        entryEditorBot.typeValueAndFinish( "English US" );
+        modificationLogsViewBot.waitForText( "delete: description;lang-en-us\ndescription;lang-en-us: English\n-" );
+        modificationLogsViewBot.waitForText( "add: description;lang-en-us\ndescription;lang-en-us: English US\n-" );
+        assertFalse( entryEditorBot.getAttributeValues().contains( "description;lang-en-us: English" ) );
+        assertTrue( entryEditorBot.getAttributeValues().contains( "description;lang-en-us: English US" ) );
+
+        // delete the attribute
+        entryEditorBot.deleteValue( "description;lang-en-us", "English US" );
+        modificationLogsViewBot.waitForText( "delete: description;lang-en-us\ndescription;lang-en-us: English US\n-" );
+        assertFalse( entryEditorBot.getAttributeValues().contains( "description;lang-en-us: English US" ) );
     }
 
 
     /**
      * DIRSTUDIO-483: DN Editor escapes all non-ascii characters
-     *
-     * @throws Exception
-     *             the exception
      */
-    @Test
-    public void testDnValueEditor() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testDnValueEditor( TestLdapServer server ) throws Exception
     {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=groups", "cn=My Group" );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( GROUP1_DN ) );
 
-        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( "cn=My Group,ou=groups,ou=system" );
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( GROUP1_DN.getName() );
         entryEditorBot.activate();
         String dn = entryEditorBot.getDnText();
-        assertEquals( "DN: cn=My Group,ou=groups,ou=system", dn );
-        assertEquals( 4, entryEditorBot.getAttributeValues().size() );
+        assertEquals( "DN: " + GROUP1_DN.getName(), dn );
+        assertEquals( 12, entryEditorBot.getAttributeValues().size() );
 
         // add member attribute
         NewAttributeWizardBot wizardBot = entryEditorBot.openNewAttributeWizard();
@@ -220,50 +316,45 @@
         assertTrue( dnEditorBot.isVisible() );
         SelectDnDialogBot selectDnBot = dnEditorBot.clickBrowseButtonExpectingSelectDnDialog();
         assertTrue( selectDnBot.isVisible() );
-        selectDnBot.selectEntry( "Root DSE", "ou=system", "ou=users", "cn=\\#\\\\\\+\\, \\\"\u00F6\u00E9\\\"" );
+        selectDnBot.selectEntry( ArrayUtils.remove( path( MULTI_VALUED_RDN_DN ), 0 ) );
         selectDnBot.clickOkButton();
-        assertEquals( "cn=\\#\\\\\\+\\, \\\"\u00F6\u00E9\\\",ou=users,ou=system", dnEditorBot.getDnText() );
+        assertEquals( MULTI_VALUED_RDN_DN.getName(), dnEditorBot.getDnText() );
         dnEditorBot.clickOkButton();
 
         // assert value after saved and reloaded from server
-        SWTUtils.sleep( 1000 );
-        assertEquals( 5, entryEditorBot.getAttributeValues().size() );
-        assertTrue( entryEditorBot.getAttributeValues().contains(
-            "member: cn=\\#\\\\\\+\\, \\\"\u00F6\u00E9\\\",ou=users,ou=system" ) );
-        dnEditorBot = entryEditorBot.editValueExpectingDnEditor( "member",
-            "cn=\\#\\\\\\+\\, \\\"\u00F6\u00E9\\\",ou=users,ou=system" );
-        assertEquals( "cn=\\#\\\\\\+\\, \\\"\u00F6\u00E9\\\",ou=users,ou=system", dnEditorBot.getDnText() );
+        assertEquals( 13, entryEditorBot.getAttributeValues().size() );
+        assertTrue( entryEditorBot.getAttributeValues().contains( "member: " + MULTI_VALUED_RDN_DN.getName() ) );
+        dnEditorBot = entryEditorBot.editValueExpectingDnEditor( "member", MULTI_VALUED_RDN_DN.getName() );
+        assertEquals( MULTI_VALUED_RDN_DN.getName(), dnEditorBot.getDnText() );
         dnEditorBot.clickCancelButton();
 
         modificationLogsViewBot.waitForText( "#!RESULT OK" );
-        assertEquals( "Expected 1 modification.", 1,
-            StringUtils.countMatches( modificationLogsViewBot.getModificationLogsText(), "#!RESULT OK" ) );
+        assertEquals( 1, StringUtils.countMatches( modificationLogsViewBot.getModificationLogsText(), "#!RESULT OK" ),
+            "Expected 1 modification." );
     }
 
 
     /**
      * DIRSTUDIO-637: copy/paste of attributes no longer works.
      * Test copy/paste within entry editor.
-     *
-     * @throws Exception
-     *             the exception
      */
-    @Test
-    public void testCopyPasteStringValue() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCopyPasteStringValue( TestLdapServer server ) throws Exception
     {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=Barbara Jensen" );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( BJENSEN_DN ) );
 
         // copy a value
-        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( "cn=Barbara Jensen,ou=users,ou=system" );
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( BJENSEN_DN.getName() );
         entryEditorBot.activate();
         entryEditorBot.copyValue( "uid", "bjensen" );
 
         // go to another entry
-        browserViewBot
-            .selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=\\#\\\\\\+\\, \\\"\u00F6\u00E9\\\"" );
-        entryEditorBot = studioBot.getEntryEditorBot( "cn=\\#\\\\\\+\\, \\\"\u00F6\u00E9\\\",ou=users,ou=system" );
+        browserViewBot.selectEntry( path( USER1_DN ) );
+        entryEditorBot = studioBot.getEntryEditorBot( USER1_DN.getName() );
         entryEditorBot.activate();
-        assertEquals( 8, entryEditorBot.getAttributeValues().size() );
+        assertEquals( 23, entryEditorBot.getAttributeValues().size() );
 
         // paste value, wait till job is done
         JobWatcher watcher = new JobWatcher( BrowserCoreMessages.jobs__execute_ldif_name );
@@ -271,33 +362,36 @@
         watcher.waitUntilDone();
 
         // assert pasted value visible in editor
-        assertEquals( 9, entryEditorBot.getAttributeValues().size() );
-        assertTrue( "Should contain uid=bjensen: " + entryEditorBot.getAttributeValues(),
-            entryEditorBot.getAttributeValues().contains( "uid: bjensen" ) );
+        assertEquals( 24, entryEditorBot.getAttributeValues().size() );
+        assertTrue( entryEditorBot.getAttributeValues().contains( "uid: bjensen" ),
+            "Should contain uid=bjensen: " + entryEditorBot.getAttributeValues() );
 
         // assert pasted value was written to directory
-        Entry entry = service.getAdminSession()
-            .lookup( new Dn( "cn=\\#\\\\\\+\\, \\\"\u00F6\u00E9\\\",ou=users,ou=system" ) );
-        assertTrue( "Should contain uid=bjensen: " + entry, entry.contains( "uid", "bjensen" ) );
+        server.withAdminConnection( conn -> {
+            Entry entry = conn.lookup( USER1_DN );
+            assertTrue( entry.contains( "uid", "bjensen" ), "Should contain uid=bjensen: " + entry );
+
+        } );
     }
 
 
-    @Test
-    public void testCopyPasteMultipleStringAndBinaryValues() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCopyPasteMultipleStringAndBinaryValues( TestLdapServer server ) throws Exception
     {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=hnelson" );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( HNELSON_DN ) );
 
         // copy the values
-        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( "uid=hnelson,ou=users,ou=system" );
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( HNELSON_DN.getName() );
         entryEditorBot.activate();
-        entryEditorBot.copyValues( "userpassword", "uid", "description", "jpegphoto" );
+        entryEditorBot.copyValues( "userPassword", "uid", "description", "jpegPhoto" );
 
         // go to another entry
-        browserViewBot
-            .selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=\\#\\\\\\+\\, \\\"\u00F6\u00E9\\\"" );
-        entryEditorBot = studioBot.getEntryEditorBot( "cn=\\#\\\\\\+\\, \\\"\u00F6\u00E9\\\",ou=users,ou=system" );
+        browserViewBot.selectEntry( path( USER1_DN ) );
+        entryEditorBot = studioBot.getEntryEditorBot( USER1_DN.getName() );
         entryEditorBot.activate();
-        assertEquals( 8, entryEditorBot.getAttributeValues().size() );
+        assertEquals( 23, entryEditorBot.getAttributeValues().size() );
 
         // paste values, wait till job is done
         JobWatcher watcher = new JobWatcher( BrowserCoreMessages.jobs__execute_ldif_name );
@@ -305,35 +399,37 @@
         watcher.waitUntilDone();
 
         // assert pasted values are visible in editor
-        SWTUtils.sleep( 1000 );
-        assertEquals( 12, entryEditorBot.getAttributeValues().size() );
+        assertEquals( 27, entryEditorBot.getAttributeValues().size() );
         assertTrue( entryEditorBot.getAttributeValues().contains( "uid: hnelson" ) );
         assertTrue( entryEditorBot.getAttributeValues().contains( "description: " + Characters.ALL ) );
         assertTrue( entryEditorBot.getAttributeValues().contains( "jpegPhoto: JPEG-Image (1x1 Pixel, 631 Bytes)" ) );
         assertTrue( entryEditorBot.getAttributeValues().contains( "userPassword: SSHA-512 hashed password" ) );
 
         // assert pasted values were written to directory
-        Entry entry = service.getAdminSession()
-            .lookup( new Dn( "cn=\\#\\\\\\+\\, \\\"\u00F6\u00E9\\\",ou=users,ou=system" ) );
-        assertTrue( "Should contain uid=hnelson: " + entry, entry.contains( "uid", "hnelson" ) );
-        assertTrue( "Should contain description: " + entry, entry.contains( "description", Characters.ALL ) );
-        assertTrue( "Should contain userPassword: " + entry, entry.containsAttribute( "userPassword" ) );
-        assertTrue( "Should contain jpegPhoto: " + entry, entry.containsAttribute( "jpegPhoto" ) );
+        server.withAdminConnection( conn -> {
+            Entry entry = conn.lookup( USER1_DN );
+            assertTrue( entry.contains( "uid", "hnelson" ), "Should contain uid=hnelson: " + entry );
+            assertTrue( entry.contains( "description", Characters.ALL ), "Should contain description: " + entry );
+            assertTrue( entry.containsAttribute( "userPassword" ), "Should contain userPassword: " + entry );
+            assertTrue( entry.containsAttribute( "jpegPhoto" ), "Should contain jpegPhoto: " + entry );
+        } );
     }
 
 
     /**
      * DIRSTUDIO-738: Add support for modular crypt format password
      */
-    @Test
-    public void testPasswordValueEditor() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(mode=Mode.All)
+    public void testPasswordValueEditor( TestLdapServer server ) throws Exception
     {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=Barbara Jensen" );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( BJENSEN_DN ) );
 
-        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( "cn=Barbara Jensen,ou=users,ou=system" );
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( BJENSEN_DN.getName() );
         entryEditorBot.activate();
         String dn = entryEditorBot.getDnText();
-        assertEquals( "DN: cn=Barbara Jensen,ou=users,ou=system", dn );
+        assertEquals( "DN: " + BJENSEN_DN.getName(), dn );
         assertEquals( 8, entryEditorBot.getAttributeValues().size() );
         assertEquals( "", modificationLogsViewBot.getModificationLogsText() );
 
@@ -371,7 +467,6 @@
         pwdEditorBot.clickOkButton();
 
         // assert value after saved and reloaded from server
-        SWTUtils.sleep( 1000 );
         assertTrue( entryEditorBot.getAttributeValues().contains( "userPassword: CRYPT-SHA-512 hashed password" ) );
 
         // verify and bind with the correct password
@@ -400,11 +495,8 @@
         pwdEditorBot.setShowNewPasswordDetails( true );
         assertHashMethod( pwdEditorBot, LdapSecurityConstants.HASH_METHOD_SSHA256, PasswordUtil.SHA256_LENGTH, 8 );
         pwdEditorBot.clickOkButton();
-        SWTUtils.sleep( 1000 );
         assertTrue( entryEditorBot.getAttributeValues().contains( "userPassword: SSHA-256 hashed password" ) );
     }
-
-
     private void assertHashMethod( PasswordEditorDialogBot passwordEditorBot, LdapSecurityConstants hashMethod,
         int passwordLength, int saltLength ) throws Exception
     {
@@ -433,15 +525,17 @@
     /**
      * DIRSTUDIO-1157: Values cannot be modified by text editor
      */
-    @Test
-    public void testTextValueEditor() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testTextValueEditor( TestLdapServer server ) throws Exception
     {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=Barbara Jensen" );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( BJENSEN_DN ) );
 
-        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( "cn=Barbara Jensen,ou=users,ou=system" );
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( BJENSEN_DN.getName() );
         entryEditorBot.activate();
         String dn = entryEditorBot.getDnText();
-        assertEquals( "DN: cn=Barbara Jensen,ou=users,ou=system", dn );
+        assertEquals( "DN: " + BJENSEN_DN.getName(), dn );
         assertEquals( 8, entryEditorBot.getAttributeValues().size() );
         assertEquals( "", modificationLogsViewBot.getModificationLogsText() );
 
@@ -468,52 +562,116 @@
         assertTrue( entryEditorBot.getAttributeValues().contains( "description: " + newValue ) );
         String description2Ldif = LdifAttrValLine.create( "description", newValue )
             .toFormattedString( LdifFormatParameters.DEFAULT ).replace( LdifParserConstants.LINE_SEPARATOR, "\n" );
-        modificationLogsViewBot.waitForText( "replace: description\n" + description2Ldif );
+        modificationLogsViewBot.waitForText( "delete: description\ndescription: testTextValueEditor 1" );
+        modificationLogsViewBot.waitForText( "add: description\n" + description2Ldif );
     }
 
 
     /**
-     * DIRSTUDIO-1199, DIRSTUDIO-1204: Binary attributes
+     * DIRSTUDIO-1199, DIRSTUDIO-1204, DIRSTUDIO-1267: Binary attributes.
+     * Test adding, editing and deleting of attributes with binary option in the entry editor.
      */
-    @Test
-    public void testCertificateValueEditor() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testCertificateValueEditor( TestLdapServer server ) throws Exception
     {
-        X500Name issuer = new X500Name( "Foo", "Bar", "Baz", "US" );
-        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance( "EC" );
-        keyPairGenerator.initialize( 256 );
-        KeyPair keyPair = keyPairGenerator.generateKeyPair();
-        X509Certificate certificate = CertificateUtil.generateSelfSignedCertificate( issuer, keyPair, 365,
-            "SHA256WithECDSA" );
-        getService().getAdminSession().modify( new Dn( "cn=Barbara Jensen,ou=users,ou=system" ),
-            new DefaultModification( ModificationOperation.ADD_ATTRIBUTE, "userCertificate",
-                certificate.getEncoded() ) );
+        connectionsViewBot.createTestConnection( server );
+        String certFile = ResourceUtils.prepareInputFile( "rfc5280_cert2.cer" );
+        String cert3File = ResourceUtils.prepareInputFile( "rfc5280_cert3.cer" );
 
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=Barbara Jensen" );
+        browserViewBot.selectEntry( path( BJENSEN_DN ) );
 
-        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( "cn=Barbara Jensen,ou=users,ou=system" );
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( BJENSEN_DN.getName() );
         entryEditorBot.activate();
 
-        BotUtils.sleep( 1000 );
-        assertTrue( entryEditorBot.getAttributeValues()
-            .contains( "userCertificate: X.509v3: CN=Foo,OU=Bar,O=Baz,C=US" ) );
+        // add userCertificate;binary
+        NewAttributeWizardBot wizardBot = entryEditorBot.openNewAttributeWizard();
+        assertTrue( wizardBot.isVisible() );
+        wizardBot.typeAttributeType( "userCertificate" );
+        wizardBot.clickNextButton();
+        wizardBot.selectBinaryOption();
+        CertificateEditorDialogBot certEditorBot = wizardBot.clickFinishButtonExpectingCertificateEditor();
+        assertTrue( certEditorBot.isVisible() );
+        certEditorBot.typeFile( certFile );
+        certEditorBot.clickOkButton();
+        modificationLogsViewBot.waitForText( "add: userCertificate;binary\nuserCertificate;binary:: " );
+        if ( server.getType() == LdapServerType.OpenLdap || server.getType() == LdapServerType.Fedora389ds )
+        {
+            assertTrue( entryEditorBot.getAttributeValues()
+                .contains( "userCertificate;binary: X.509v3: CN=End Entity,DC=example,DC=com" ) );
+        }
+        else
+        {
+            assertTrue( entryEditorBot.getAttributeValues()
+                .contains( "userCertificate: X.509v3: CN=End Entity,DC=example,DC=com" ) );
+        }
+
+        // edit userCertificate;binary
+        if ( server.getType() == LdapServerType.OpenLdap || server.getType() == LdapServerType.Fedora389ds )
+        {
+            certEditorBot = entryEditorBot.editValueExpectingCertificateEditor( "userCertificate;binary",
+                "X.509v3: CN=End Entity,DC=example,DC=com" );
+        }
+        else
+        {
+            certEditorBot = entryEditorBot.editValueExpectingCertificateEditor( "userCertificate",
+                "X.509v3: CN=End Entity,DC=example,DC=com" );
+        }
+        assertTrue( certEditorBot.isVisible() );
+        certEditorBot.typeFile( cert3File );
+        certEditorBot.clickOkButton();
+        if ( server.getType() == LdapServerType.OpenLdap || server.getType() == LdapServerType.Fedora389ds )
+        {
+            modificationLogsViewBot
+                .waitForText( "delete: userCertificate;binary\nuserCertificate;binary:: MIICcTCCAdqg" );
+            modificationLogsViewBot.waitForText( "add: userCertificate;binary\nuserCertificate;binary:: MIIDjjCCA06g" );
+            assertFalse( entryEditorBot.getAttributeValues()
+                .contains( "userCertificate;binary: X.509v3: CN=End Entity,DC=example,DC=com" ) );
+            assertTrue( entryEditorBot.getAttributeValues()
+                .contains( "userCertificate;binary: X.509v3: CN=DSA End Entity,DC=example,DC=com" ) );
+        }
+        else
+        {
+            modificationLogsViewBot.waitForText( "delete: userCertificate\nuserCertificate:: MIICcTCCAdqg" );
+            modificationLogsViewBot.waitForText( "add: userCertificate\nuserCertificate:: MIIDjjCCA06g" );
+            assertFalse( entryEditorBot.getAttributeValues()
+                .contains( "userCertificate: X.509v3: CN=End Entity,DC=example,DC=com" ) );
+            assertTrue( entryEditorBot.getAttributeValues()
+                .contains( "userCertificate: X.509v3: CN=DSA End Entity,DC=example,DC=com" ) );
+        }
+
+        // delete userCertificate;binary
+        if ( server.getType() == LdapServerType.OpenLdap || server.getType() == LdapServerType.Fedora389ds )
+        {
+            entryEditorBot.deleteValue( "userCertificate;binary", "X.509v3: CN=DSA End Entity,DC=example,DC=com" );
+            modificationLogsViewBot
+                .waitForText( "delete: userCertificate;binary\nuserCertificate;binary:: MIIDjjCCA06g" );
+            assertFalse( entryEditorBot.getAttributeValues()
+                .contains( "userCertificate;binary: X.509v3: CN=DSA End Entity,DC=example,DC=com" ) );
+        }
+        else
+        {
+            entryEditorBot.deleteValue( "userCertificate", "X.509v3: CN=DSA End Entity,DC=example,DC=com" );
+            modificationLogsViewBot.waitForText( "delete: userCertificate\nuserCertificate:: MIIDjjCCA06g" );
+            assertFalse( entryEditorBot.getAttributeValues()
+                .contains( "userCertificate: X.509v3: CN=DSA End Entity,DC=example,DC=com" ) );
+        }
     }
 
 
     /**
      * DIRSTUDIO-1199, DIRSTUDIO-1204: Binary attributes
      */
-    @Test
-    public void testImageValueEditor() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testImageValueEditor( TestLdapServer server ) throws Exception
     {
-        URL url = Platform.getInstanceLocation().getURL();
-        String destFile = url.getFile() + "studio_64x64.jpg";
-        InputStream is = getClass().getResourceAsStream( "studio_64x64.jpg" );
-        byte[] data = IOUtils.toByteArray( is, 2014 );
-        FileUtils.writeByteArrayToFile( new File( destFile ), data );
+        connectionsViewBot.createTestConnection( server );
+        String imgFile = ResourceUtils.prepareInputFile( "studio_64x64.jpg" );
 
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=Barbara Jensen" );
+        browserViewBot.selectEntry( path( BJENSEN_DN ) );
 
-        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( "cn=Barbara Jensen,ou=users,ou=system" );
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( BJENSEN_DN.getName() );
         entryEditorBot.activate();
 
         // add image
@@ -522,12 +680,290 @@
         wizardBot.typeAttributeType( "jpegPhoto" );
         ImageEditorDialogBot imageEditorBot = wizardBot.clickFinishButtonExpectingImageEditor();
         assertTrue( imageEditorBot.isVisible() );
-        imageEditorBot.typeFile( destFile );
+        imageEditorBot.typeFile( imgFile );
         imageEditorBot.clickOkButton();
 
         // assert value after saved and reloaded from server
-        SWTUtils.sleep( 1000 );
+        modificationLogsViewBot.waitForText( "add: jpegPhoto\njpegPhoto:: " );
         assertTrue( entryEditorBot.getAttributeValues().contains( "jpegPhoto: JPEG-Image (64x64 Pixel, 2014 Bytes)" ) );
     }
 
+
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.ApacheDS, reason = "ApacheDS specific test")
+    public void testAciItemEditorAllOptions( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( HNELSON_DN ) );
+
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( HNELSON_DN.getName() );
+        entryEditorBot.activate();
+        entryEditorBot.fetchOperationalAttributes();
+        SWTUtils.sleep( 1000 );
+
+        entryEditorBot.activate();
+        AciItemEditorDialogBot aciItemEditor = entryEditorBot.editValueExpectingAciItemEditor( "entryACI", null );
+
+        aciItemEditor.activateSourceTab();
+        aciItemEditor.activateVisualEditorTab();
+
+        aciItemEditor.setIdentificationTag( "Test 1234" );
+
+        aciItemEditor.setPrecedence( 1 );
+        aciItemEditor.setPrecedence( 10 );
+        aciItemEditor.setPrecedence( 100 );
+
+        aciItemEditor.setAuthenticationLevel( AuthenticationLevel.NONE );
+        aciItemEditor.setAuthenticationLevel( AuthenticationLevel.SIMPLE );
+        aciItemEditor.setAuthenticationLevel( AuthenticationLevel.STRONG );
+
+        aciItemEditor.setUserFirst();
+
+        aciItemEditor.enableUserClassAllUsers();
+        aciItemEditor.disableUserClassAllUsers();
+        aciItemEditor.enableUserClassThisEntry();
+        aciItemEditor.disableUserClassThisEntry();
+        aciItemEditor.enableUserClassParentOfEntry();
+        aciItemEditor.disableUserClassParentOfEntry();
+        aciItemEditor.enableUserClassName();
+        aciItemEditor.disableUserClassName();
+        aciItemEditor.enableUserClassUserGroup();
+        aciItemEditor.disableUserClassUserGroup();
+        aciItemEditor.enableUserClassSubtree();
+        aciItemEditor.disableUserClassSubtree();
+
+        aciItemEditor.setItemFirst();
+
+        aciItemEditor.enableProtectedItemEntry();
+        aciItemEditor.disableProtectedItemEntry();
+        aciItemEditor.enableProtectedItemAllUserAttributeTypes();
+        aciItemEditor.disableProtectedItemAllUserAttributeTypes();
+        aciItemEditor.enableProtectedItemAttributeType();
+        aciItemEditor.disableProtectedItemAttributeType();
+        aciItemEditor.enableProtectedItemAllAttributeValues();
+        aciItemEditor.disableProtectedItemAllAttributeValues();
+        aciItemEditor.enableProtectedItemAllUserAttributeTypesAndValues();
+        aciItemEditor.disableProtectedItemAllUserAttributeTypesAndValues();
+        aciItemEditor.enableProtectedItemAttributeValues();
+        aciItemEditor.disableProtectedItemAttributeValues();
+        aciItemEditor.enableProtectedItemSelfValue();
+        aciItemEditor.disableProtectedItemSelfValue();
+        aciItemEditor.enableProtectedItemRangeOfValues();
+        aciItemEditor.disableProtectedItemRangeOfValues();
+        aciItemEditor.enableProtectedItemMaxValueCount();
+        aciItemEditor.disableProtectedItemMaxValueCount();
+        aciItemEditor.enableProtectedItemMaxNumberOfImmediateSubordinates();
+        aciItemEditor.disableProtectedItemMaxNumberOfImmediateSubordinates();
+        aciItemEditor.enableProtectedItemRestrictedBy();
+        aciItemEditor.disableProtectedItemRestrictedBy();
+        aciItemEditor.enableProtectedItemClasses();
+        aciItemEditor.disableProtectedItemClasses();
+
+        aciItemEditor.clickCancelButton();
+    }
+
+
+    /**
+     * Test for DIRSTUDIO-1135
+     */
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.ApacheDS, reason = "ApacheDS specific test")
+    public void testAciItemEditorAllAttributesValuesParser( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( HNELSON_DN ) );
+
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( HNELSON_DN.getName() );
+        entryEditorBot.activate();
+        entryEditorBot.fetchOperationalAttributes();
+        SWTUtils.sleep( 1000 );
+
+        entryEditorBot.activate();
+        AciItemEditorDialogBot aciItemEditor = entryEditorBot.editValueExpectingAciItemEditor( "entryACI", null );
+
+        aciItemEditor.activateSourceTab();
+        aciItemEditor.setSource(
+            "{ identificationTag \"Test\", precedence 0, authenticationLevel none, itemOrUserFirst itemFirst: { protectedItems { allAttributeValues { cn } }, itemPermissions { } } }" );
+        aciItemEditor.clickCheckSyntaxButtonOk();
+
+        aciItemEditor.activateVisualEditorTab();
+        aciItemEditor.clickCheckSyntaxButtonOk();
+
+        aciItemEditor.activateSourceTab();
+        aciItemEditor.clickCheckSyntaxButtonOk();
+
+        aciItemEditor.activateVisualEditorTab();
+        aciItemEditor.clickCheckSyntaxButtonOk();
+
+        aciItemEditor.clickOkButton();
+
+        modificationLogsViewBot.waitForText( "delete: entryACI\n" );
+        modificationLogsViewBot.waitForText( "add: entryACI\n" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.ApacheDS, reason = "ApacheDS specific test")
+    public void testAciItemEditorEntryAci( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( HNELSON_DN ) );
+
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( HNELSON_DN.getName() );
+        entryEditorBot.activate();
+        entryEditorBot.fetchOperationalAttributes();
+        SWTUtils.sleep( 1000 );
+
+        entryEditorBot.activate();
+        AciItemEditorDialogBot aciItemEditor = entryEditorBot.editValueExpectingAciItemEditor( "entryACI", null );
+
+        aciItemEditor.activateSourceTab();
+        aciItemEditor.clickCheckSyntaxButtonOk();
+
+        aciItemEditor.activateVisualEditorTab();
+        aciItemEditor.clickCheckSyntaxButtonOk();
+
+        aciItemEditor.activateSourceTab();
+        aciItemEditor.clickFormatButton();
+        aciItemEditor.clickCheckSyntaxButtonOk();
+
+        String source = aciItemEditor.getSource();
+        source = source.replace( "grantFilterMatch,", "" );
+
+        aciItemEditor.setSource( "invalid" );
+        aciItemEditor.clickCheckSyntaxButtonError();
+
+        aciItemEditor.setSource( source );
+        aciItemEditor.clickCheckSyntaxButtonOk();
+
+        aciItemEditor.clickOkButton();
+
+        modificationLogsViewBot.waitForText( "delete: entryACI\n" );
+        modificationLogsViewBot.waitForText( "add: entryACI\n" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.ApacheDS, reason = "ApacheDS specific test")
+    public void testAciItemEditorPrescriptiveAci( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( HNELSON_DN ) );
+
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( HNELSON_DN.getName() );
+        entryEditorBot.activate();
+        entryEditorBot.fetchOperationalAttributes();
+        SWTUtils.sleep( 1000 );
+
+        entryEditorBot.activate();
+        AciItemEditorDialogBot aciItemEditor = entryEditorBot.editValueExpectingAciItemEditor( "prescriptiveACI",
+            null );
+
+        aciItemEditor.activateSourceTab();
+        aciItemEditor.clickFormatButton();
+        aciItemEditor.clickCheckSyntaxButtonOk();
+
+        aciItemEditor.activateVisualEditorTab();
+        aciItemEditor.clickCheckSyntaxButtonOk();
+
+        aciItemEditor.clickOkButton();
+
+        modificationLogsViewBot.waitForText( "delete: prescriptiveACI\n" );
+        modificationLogsViewBot.waitForText( "add: prescriptiveACI\n" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.ApacheDS, reason = "ApacheDS specific test")
+    public void testSubtreeSpecificationEditor( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( HNELSON_DN ) );
+
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( HNELSON_DN.getName() );
+        entryEditorBot.activate();
+        entryEditorBot.fetchOperationalAttributes();
+        SWTUtils.sleep( 1000 );
+
+        entryEditorBot.activate();
+        SubtreeSpecificationEditorDialogBot subtreeEditorBot = entryEditorBot
+            .editValueExpectingSubtreeSpecificationEditor( "subtreeSpecification",
+                null );
+
+        subtreeEditorBot.clickOkButton();
+    }
+
+
+    /**
+     * Test for DIRSTUDIO-1249, DIRSTUDIO-1267: userSMIMECertificate is a binary attribute.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testHexEditor( TestLdapServer server ) throws Exception
+    {
+        Connection connection = connectionsViewBot.createTestConnection( server );
+        if ( server.getType() == LdapServerType.OpenLdap )
+        {
+            IBrowserConnection browserConnection = BrowserCorePlugin.getDefault().getConnectionManager()
+                .getBrowserConnection( connection );
+            browserConnection.setModifyModeNoEMR( ModifyMode.REPLACE );
+        }
+
+        browserViewBot.selectEntry( path( HNELSON_DN ) );
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( HNELSON_DN.getName() );
+        entryEditorBot.activate();
+        assertTrue( entryEditorBot.getAttributeValues().contains( "userSMIMECertificate: Binary Data (255 Bytes)" ) );
+        assertTrue( entryEditorBot.getAttributeValues().contains( "userSMIMECertificate: Binary Data (256 Bytes)" ) );
+        assertTrue( entryEditorBot.getAttributeValues().contains( "userSMIMECertificate: Binary Data (257 Bytes)" ) );
+
+        HexEditorDialogBot hexEditorDialogBot = entryEditorBot.editValueExpectingHexEditor( "userSMIMECertificate",
+            "Binary Data (256 Bytes)" );
+        String hexText = hexEditorDialogBot.getHexText();
+        assertTrue( hexText.contains( "00 01 02 03 04 05 06 07  08 09 0a 0b 0c 0d 0e 0f     ........ ........" ) );
+        assertTrue( hexText.contains( "70 71 72 73 74 75 76 77  78 79 7a 7b 7c 7d 7e 7f     pqrstuvw xyz{|}~." ) );
+        assertTrue( hexText.contains( "80 81 82 83 84 85 86 87  88 89 8a 8b 8c 8d 8e 8f     ........ ........" ) );
+        assertTrue( hexText.contains( "f0 f1 f2 f3 f4 f5 f6 f7  f8 f9 fa fb fc fd fe ff     ........ ........" ) );
+        hexEditorDialogBot.clickCancelButton();
+
+        hexEditorDialogBot = entryEditorBot.editValueExpectingHexEditor( "userSMIMECertificate",
+            "Binary Data (255 Bytes)" );
+        hexText = hexEditorDialogBot.getHexText();
+        assertTrue( hexText.contains( "f0 f1 f2 f3 f4 f5 f6 f7  f8 f9 fa fb fc fd fe        ........ ......." ) );
+        hexEditorDialogBot.clickCancelButton();
+
+        hexEditorDialogBot = entryEditorBot.editValueExpectingHexEditor( "userSMIMECertificate",
+            "Binary Data (257 Bytes)" );
+        hexText = hexEditorDialogBot.getHexText();
+        assertTrue( hexText.contains( "f0 f1 f2 f3 f4 f5 f6 f7  f8 f9 fa fb fc fd fe ff     ........ ........" ) );
+        assertTrue( hexText.contains( "00                                                   ." ) );
+        hexEditorDialogBot.clickCancelButton();
+
+        String crtFile = ResourceUtils.prepareInputFile( "rfc5280_cert2.cer" );
+
+        entryEditorBot.activate();
+        NewAttributeWizardBot wizardBot = entryEditorBot.openNewAttributeWizard();
+        assertTrue( wizardBot.isVisible() );
+        wizardBot.typeAttributeType( "userSMIMECertificate" );
+        wizardBot.clickNextButton();
+        HexEditorDialogBot hexEditorBot = wizardBot.clickFinishButtonExpectingHexEditor();
+
+        assertTrue( hexEditorBot.isVisible() );
+        hexEditorBot.typeFile( crtFile );
+
+        hexEditorBot.clickOkButton();
+
+        if ( server.getType() == LdapServerType.OpenLdap )
+        {
+            modificationLogsViewBot.waitForText( "replace: userSMIMECertificate\nuserSMIMECertificate:: " );
+            assertTrue( entryEditorBot.getAttributeValues()
+                .contains( "userSMIMECertificate: Binary Data (629 Bytes)" ) );
+        }
+        else
+        {
+            modificationLogsViewBot.waitForText( "add: userSMIMECertificate\nuserSMIMECertificate:: " );
+            assertTrue( entryEditorBot.getAttributeValues()
+                .contains( "userSMIMECertificate: Binary Data (629 Bytes)" ) );
+        }
+    }
+
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ErrorHandlingTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ErrorHandlingTest.java
new file mode 100644
index 0000000..29a8a64
--- /dev/null
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ErrorHandlingTest.java
@@ -0,0 +1,212 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.studio.test.integration.ui;
+
+
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USER1_DN;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import org.apache.directory.studio.test.integration.junit5.LdapServerType;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource;
+import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource.Mode;
+import org.apache.directory.studio.test.integration.ui.bots.DeleteDialogBot;
+import org.apache.directory.studio.test.integration.ui.bots.EntryEditorBot;
+import org.apache.directory.studio.test.integration.ui.bots.ErrorDialogBot;
+import org.eclipse.swtbot.swt.finder.utils.SWTUtils;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.params.ParameterizedTest;
+
+
+/**
+ * Tests error handling
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class ErrorHandlingTest extends AbstractTestBase
+{
+
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.ApacheDS, reason = "ApacheDS specific test")
+    public void testDeleteObjectClassTopSchemaEntryShouldFail( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=schema", "cn=system", "ou=objectClasses", "m-oid=2.5.6.0" );
+        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=schema", "cn=system", "ou=objectClasses", "m-oid=2.5.6.0" );
+        DeleteDialogBot deleteDialog = browserViewBot.openDeleteDialog();
+        ErrorDialogBot errorDialog = deleteDialog.clickOkButtonExpectingErrorDialog();
+
+        // verify message in error dialog
+        assertThat( errorDialog.getErrorDetails(), containsString( "[LDAP result code 53 - unwillingToPerform]" ) );
+        errorDialog.clickOkButton();
+
+        // verify in modification logs
+        modificationLogsViewBot.assertContainsError( "[LDAP result code 53 - unwillingToPerform]",
+            "dn: m-oid=2.5.6.0,ou=objectClasses,cn=system,ou=schema", "changetype: delete" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testDeleteObjectClassAttributeShouldFail( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( ( USER1_DN ) ) );
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( USER1_DN.getName() );
+        entryEditorBot.activate();
+        ErrorDialogBot errorDialog = entryEditorBot.deleteValueExpectingErrorDialog( "objectClass",
+            "inetOrgPerson (structural)" );
+
+        String expectedError = "65 - objectClassViolation";
+        if ( server.getType() == LdapServerType.OpenLdap )
+        {
+            expectedError = "69 - objectClassModsProhibited";
+        }
+
+        // verify message in error dialog
+        assertThat( errorDialog.getErrorMessage(), containsString( "[LDAP result code " + expectedError + "]" ) );
+        errorDialog.clickOkButton();
+
+        modificationLogsViewBot.assertContainsError( "[LDAP result code " + expectedError + "]",
+            "dn: " + USER1_DN.getName(), "changetype: modify" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testDeleteRdnAttributeShouldFail( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( ( USER1_DN ) ) );
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( USER1_DN.getName() );
+        entryEditorBot.activate();
+        ErrorDialogBot errorDialog = entryEditorBot.deleteValueExpectingErrorDialog( "uid", "user.1" );
+
+        String expectedError = "67 - notAllowedOnRDN";
+        if ( server.getType() == LdapServerType.OpenLdap )
+        {
+            expectedError = "64 - namingViolation";
+        }
+
+        // verify message in error dialog
+        assertThat( errorDialog.getErrorMessage(), containsString( "[LDAP result code " + expectedError + "]" ) );
+        errorDialog.clickOkButton();
+
+        // verify in modification logs
+        modificationLogsViewBot.assertContainsError( "[LDAP result code " + expectedError + "]",
+            "dn: " + USER1_DN.getName(), "changetype: modify", "delete: uid" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testDeleteMustAttributeShouldFail( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( ( USER1_DN ) ) );
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( USER1_DN.getName() );
+        entryEditorBot.activate();
+        ErrorDialogBot errorDialog = entryEditorBot.deleteValueExpectingErrorDialog( "sn", "Amar" );
+
+        // verify message in error dialog
+        assertThat( errorDialog.getErrorMessage(), containsString( "[LDAP result code 65 - objectClassViolation]" ) );
+        errorDialog.clickOkButton();
+
+        // verify in modification logs
+        modificationLogsViewBot.assertContainsError( "[LDAP result code 65 - objectClassViolation]",
+            "dn: " + USER1_DN.getName(), "changetype: modify", "delete: sn" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testDeleteOperationalAttributeShouldFail( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( ( USER1_DN ) ) );
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( USER1_DN.getName() );
+        entryEditorBot.activate();
+        entryEditorBot.fetchOperationalAttributes();
+        SWTUtils.sleep( 1000 );
+        entryEditorBot.activate();
+        ErrorDialogBot errorDialog = entryEditorBot.deleteValueExpectingErrorDialog( "creatorsName", null );
+
+        String expectedError = "50 - insufficientAccessRights";
+        if ( server.getType() == LdapServerType.OpenLdap )
+        {
+            expectedError = "19 - constraintViolation";
+        }
+        if ( server.getType() == LdapServerType.Fedora389ds )
+        {
+            expectedError = "53 - unwillingToPerform";
+        }
+
+        // verify message in error dialog
+        assertThat( errorDialog.getErrorMessage(),
+            containsString( "[LDAP result code " + expectedError + "]" ) );
+        errorDialog.clickOkButton();
+
+        // verify in modification logs
+        modificationLogsViewBot.assertContainsError( "[LDAP result code " + expectedError + "]",
+            "dn: " + USER1_DN.getName(), "changetype: modify", "delete: creatorsName" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testModifyInvalidSyntaxShouldFail( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( ( USER1_DN ) ) );
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( USER1_DN.getName() );
+        entryEditorBot.activate();
+        entryEditorBot.editValue( "mail", null );
+        ErrorDialogBot errorDialog = entryEditorBot.typeValueAndFinishAndExpectErrorDialog( "äöüß" );
+
+        // verify message in error dialog
+        assertThat( errorDialog.getErrorMessage(),
+            containsString( "[LDAP result code 21 - invalidAttributeSyntax]" ) );
+        errorDialog.clickOkButton();
+
+        // verify in modification logs
+        modificationLogsViewBot.assertContainsError( "[LDAP result code 21 - invalidAttributeSyntax]",
+            "dn: " + USER1_DN.getName(), "changetype: modify", "delete: mail" );
+    }
+
+
+    @Disabled("Until DIRSERVER-2308 is fixed")
+    @ParameterizedTest
+    @LdapServersSource
+    public void testRenameAlreadyExistingEntry( TestLdapServer server ) throws Exception
+    {
+    }
+
+
+    @Disabled("Until DIRSERVER-2308 is fixed")
+    @ParameterizedTest
+    @LdapServersSource
+    public void testMoveAlreadyExistingEntry( TestLdapServer server ) throws Exception
+    {
+    }
+
+}
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ExtendedOperationsTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ExtendedOperationsTest.java
index ea9e09b..9268450 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ExtendedOperationsTest.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ExtendedOperationsTest.java
@@ -21,31 +21,25 @@
 package org.apache.directory.studio.test.integration.ui;
 
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USER1_DN;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import org.apache.commons.lang3.RandomStringUtils;
-import org.apache.directory.server.annotations.CreateLdapServer;
-import org.apache.directory.server.annotations.CreateTransport;
-import org.apache.directory.server.core.annotations.ApplyLdifFiles;
-import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
-import org.apache.directory.server.ldap.handlers.extended.PwdModifyHandler;
-import org.apache.directory.studio.test.integration.ui.bots.BotUtils;
-import org.apache.directory.studio.test.integration.ui.bots.BrowserViewBot;
-import org.apache.directory.studio.test.integration.ui.bots.ConnectionsViewBot;
+import org.apache.directory.studio.test.integration.junit5.LdapServerType;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource.Mode;
+import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
 import org.apache.directory.studio.test.integration.ui.bots.EntryEditorBot;
 import org.apache.directory.studio.test.integration.ui.bots.ErrorDialogBot;
+import org.apache.directory.studio.test.integration.ui.bots.GeneratedPasswordDialogBot;
 import org.apache.directory.studio.test.integration.ui.bots.PasswordEditorDialogBot;
 import org.apache.directory.studio.test.integration.ui.bots.PasswordModifyExtendedOperationDialogBot;
-import org.apache.directory.studio.test.integration.ui.bots.StudioBot;
-import org.apache.directory.studio.test.integration.ui.bots.utils.Assertions;
-import org.apache.directory.studio.test.integration.ui.bots.utils.FrameworkRunnerWithScreenshotCaptureListener;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.params.ParameterizedTest;
 
 
 /**
@@ -54,48 +48,22 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-@RunWith(FrameworkRunnerWithScreenshotCaptureListener.class)
-@CreateLdapServer(transports =
-    { @CreateTransport(protocol = "LDAP") }, extendedOpHandlers =
-    { PwdModifyHandler.class })
-@ApplyLdifFiles(clazz = ExtendedOperationsTest.class, value = "org/apache/directory/studio/test/integration/ui/BrowserTest.ldif")
-public class ExtendedOperationsTest extends AbstractLdapTestUnit
+public class ExtendedOperationsTest extends AbstractTestBase
 {
-    private StudioBot studioBot;
-    private ConnectionsViewBot connectionsViewBot;
-    private BrowserViewBot browserViewBot;
 
-
-    @Before
-    public void setUp() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testPasswordModifyExtendedOperationDialogValidation( TestLdapServer server ) throws Exception
     {
-        studioBot = new StudioBot();
-        studioBot.resetLdapPerspective();
-        connectionsViewBot = studioBot.getConnectionView();
-        connectionsViewBot.createTestConnection( "BrowserTest", ldapServer.getPort() );
-        browserViewBot = studioBot.getBrowserView();
-    }
-
-
-    @After
-    public void tearDown() throws Exception
-    {
-        connectionsViewBot.deleteTestConnections();
-        Assertions.genericTearDownAssertions();
-    }
-
-
-    @Test
-    public void testPasswordModifyExtendedOperationDialogValidation()
-    {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.1" );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( USER1_DN ) );
 
         // Open dialog
         PasswordModifyExtendedOperationDialogBot dialogBot = browserViewBot.openPasswordModifyExtendedOperationDialog();
         assertTrue( dialogBot.isVisible() );
 
         // Verify default UI state
-        assertEquals( "uid=user.1,ou=users,ou=system", dialogBot.getUserIdentity() );
+        assertEquals( USER1_DN.getName(), dialogBot.getUserIdentity() );
         assertFalse( dialogBot.useBindUserIdentity() );
         assertEquals( "", dialogBot.getOldPassword() );
         assertFalse( dialogBot.noOldPassword() );
@@ -151,17 +119,18 @@
     }
 
 
-    @Test
-    public void testPasswordModifyExtendedOperationDialogOk()
+    @ParameterizedTest
+    @LdapServersSource(mode=Mode.All, except = LdapServerType.Fedora389ds, reason = "389ds requires secure connection")
+    public void testPasswordModifyExtendedOperationDialogSetNewPassword( TestLdapServer server ) throws Exception
     {
+        connectionsViewBot.createTestConnection( server );
         String random = RandomStringUtils.random( 20 );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.1" );
-        String dn = "uid=user.1,ou=users,ou=system";
+        browserViewBot.selectEntry( path( USER1_DN ) );
 
         // Open dialog
         PasswordModifyExtendedOperationDialogBot dialogBot = browserViewBot.openPasswordModifyExtendedOperationDialog();
         assertTrue( dialogBot.isVisible() );
-        assertEquals( dn, dialogBot.getUserIdentity() );
+        assertEquals( USER1_DN.getName(), dialogBot.getUserIdentity() );
 
         // Change password
         dialogBot.noOldPassword( true );
@@ -170,25 +139,98 @@
 
         // Verify and bind with the correct password
         browserViewBot.refresh();
-        BotUtils.sleep( 1000L );
-        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( dn );
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( USER1_DN.getName() );
         entryEditorBot.activate();
-        PasswordEditorDialogBot pwdEditorBot = entryEditorBot.editValueExpectingPasswordEditor( "userPassword",
-            "Plain text password" );
+        PasswordEditorDialogBot pwdEditorBot = entryEditorBot.editValueExpectingPasswordEditor( "userPassword", null );
         pwdEditorBot.activateCurrentPasswordTab();
         pwdEditorBot.setVerifyPassword( random );
         assertNull( pwdEditorBot.clickVerifyButton() );
         assertNull( pwdEditorBot.clickBindButton() );
+
         pwdEditorBot.clickCancelButton();
     }
 
-
-    @Test
-    public void testPasswordModifyExtendedOperationDialogError()
+    @ParameterizedTest
+    @LdapServersSource(mode=Mode.All, except = LdapServerType.Fedora389ds, reason = "389ds requires secure connection")
+    public void testPasswordModifyExtendedOperationDialogGenerateNewPassword( TestLdapServer server ) throws Exception
     {
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( USER1_DN ) );
+
+        // Open dialog
+        PasswordModifyExtendedOperationDialogBot dialogBot = browserViewBot.openPasswordModifyExtendedOperationDialog();
+        assertTrue( dialogBot.isVisible() );
+        assertEquals( USER1_DN.getName(), dialogBot.getUserIdentity() );
+
+        // Generate password
+        dialogBot.noOldPassword( true );
+        dialogBot.generateNewPassword( true );
+
+        // ApacheDS does not support password generation
+        if ( server.getType() == LdapServerType.ApacheDS )
+        {
+            ErrorDialogBot errorBot = dialogBot.clickOkButtonExpectingErrorDialog();
+            assertThat( errorBot.getErrorMessage(), containsString( "null new password" ) );
+            errorBot.clickOkButton();
+            dialogBot.activate();
+            dialogBot.clickCancelButton();
+        }
+        else
+        {
+            dialogBot.clickOkButton();
+            GeneratedPasswordDialogBot generatedPasswordDialogBot = new GeneratedPasswordDialogBot();
+            String generatedPassword = generatedPasswordDialogBot.getGeneratedPassword();
+            generatedPasswordDialogBot.clickOkButton();
+
+            // Verify and bind with the correct password
+            browserViewBot.refresh();
+            EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( USER1_DN.getName() );
+            entryEditorBot.activate();
+            PasswordEditorDialogBot pwdEditorBot = entryEditorBot.editValueExpectingPasswordEditor( "userPassword",
+                null );
+            pwdEditorBot.activateCurrentPasswordTab();
+            pwdEditorBot.setVerifyPassword( generatedPassword );
+            assertNull( pwdEditorBot.clickVerifyButton() );
+            assertNull( pwdEditorBot.clickBindButton() );
+            pwdEditorBot.clickCancelButton();
+        }
+
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.Fedora389ds, reason = "389ds requires secure connection")
+    public void testPasswordModifyExtendedOperationRequiresSecureConnection( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
         String random = RandomStringUtils.random( 20 );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.1" );
-        String dn = "uid=user.1,ou=users,ou=system";
+        browserViewBot.selectEntry( path( USER1_DN ) );
+
+        // Open dialog
+        PasswordModifyExtendedOperationDialogBot dialogBot = browserViewBot.openPasswordModifyExtendedOperationDialog();
+        assertTrue( dialogBot.isVisible() );
+        assertEquals( USER1_DN.getName(), dialogBot.getUserIdentity() );
+
+        // Change password
+        dialogBot.noOldPassword( true );
+        dialogBot.setNewPassword( random );
+        ErrorDialogBot errorBot = dialogBot.clickOkButtonExpectingErrorDialog();
+        assertThat( errorBot.getErrorMessage(), containsString( "Operation requires a secure connection" ) );
+        errorBot.clickOkButton();
+
+        dialogBot.activate();
+        dialogBot.clickCancelButton();
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode=Mode.All)
+    public void testPasswordModifyExtendedOperationDialogError( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+        String random = RandomStringUtils.random( 20 );
+        browserViewBot.selectEntry( path( USER1_DN ) );
+        String dn = USER1_DN.getName();
 
         // Open dialog
         PasswordModifyExtendedOperationDialogBot dialogBot = browserViewBot.openPasswordModifyExtendedOperationDialog();
@@ -201,7 +243,18 @@
         dialogBot.setOldPassword( "wrong password" );
         dialogBot.setNewPassword( random );
         ErrorDialogBot errorBot = dialogBot.clickOkButtonExpectingErrorDialog();
-        assertTrue( errorBot.getErrorMessage().contains( "invalid credentials" ) );
+        if ( server.getType() == LdapServerType.OpenLdap )
+        {
+            assertThat( errorBot.getErrorMessage(), containsString( "unwilling to verify old password" ) );
+        }
+        else if ( server.getType() == LdapServerType.Fedora389ds )
+        {
+            assertThat( errorBot.getErrorMessage(), containsString( "Operation requires a secure connection" ) );
+        }
+        else
+        {
+            assertThat( errorBot.getErrorMessage(), containsString( "invalid credentials" ) );
+        }
         errorBot.clickOkButton();
 
         // Not existing entry
@@ -210,17 +263,31 @@
         dialogBot.noOldPassword( true );
         dialogBot.setNewPassword( random );
         errorBot = dialogBot.clickOkButtonExpectingErrorDialog();
-        assertTrue( errorBot.getErrorMessage().contains( "The entry does not exist" ) );
+        if ( server.getType() == LdapServerType.OpenLdap )
+        {
+            assertThat( errorBot.getErrorMessage(), containsString( "unable to retrieve SASL username" ) );
+        }
+        else if ( server.getType() == LdapServerType.Fedora389ds )
+        {
+            assertThat( errorBot.getErrorMessage(), containsString( "Operation requires a secure connection" ) );
+        }
+        else
+        {
+            assertThat( errorBot.getErrorMessage(), containsString( "The entry does not exist" ) );
+        }
         errorBot.clickOkButton();
 
         // ApacheDS does not support password generation
-        dialogBot.activate();
-        dialogBot.setUserIdentity( dn );
-        dialogBot.noOldPassword( true );
-        dialogBot.generateNewPassword( true );
-        errorBot = dialogBot.clickOkButtonExpectingErrorDialog();
-        assertTrue( errorBot.getErrorMessage().contains( "null new password" ) );
-        errorBot.clickOkButton();
+        if ( server.getType() == LdapServerType.ApacheDS )
+        {
+            dialogBot.activate();
+            dialogBot.setUserIdentity( dn );
+            dialogBot.noOldPassword( true );
+            dialogBot.generateNewPassword( true );
+            errorBot = dialogBot.clickOkButtonExpectingErrorDialog();
+            assertThat( errorBot.getErrorMessage(), containsString( "null new password" ) );
+            errorBot.clickOkButton();
+        }
 
         dialogBot.activate();
         dialogBot.clickCancelButton();
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/GssApiTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/GssApiTest.java
index 149176b..72dab5d 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/GssApiTest.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/GssApiTest.java
@@ -21,13 +21,13 @@
 package org.apache.directory.studio.test.integration.ui;
 
 
-import static org.apache.directory.studio.test.integration.ui.Constants.LOCALHOST;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
+import static org.apache.directory.studio.test.integration.ui.utils.Constants.LOCALHOST;
+import static org.junit.jupiter.api.Assertions.assertNull;
 
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.reflect.Method;
 import java.net.URL;
 import java.nio.charset.StandardCharsets;
 
@@ -36,25 +36,20 @@
 import org.apache.directory.api.util.FileUtils;
 import org.apache.directory.api.util.IOUtils;
 import org.apache.directory.studio.test.integration.ui.bots.ApacheDSConfigurationEditorBot;
-import org.apache.directory.studio.test.integration.ui.bots.ApacheDSServersViewBot;
 import org.apache.directory.studio.test.integration.ui.bots.BrowserViewBot;
-import org.apache.directory.studio.test.integration.ui.bots.ConnectionsViewBot;
-import org.apache.directory.studio.test.integration.ui.bots.DeleteDialogBot;
 import org.apache.directory.studio.test.integration.ui.bots.ImportWizardBot;
 import org.apache.directory.studio.test.integration.ui.bots.NewApacheDSServerWizardBot;
 import org.apache.directory.studio.test.integration.ui.bots.NewConnectionWizardBot;
-import org.apache.directory.studio.test.integration.ui.bots.StudioBot;
-import org.apache.directory.studio.test.integration.ui.bots.utils.Assertions;
-import org.apache.directory.studio.test.integration.ui.bots.utils.FrameworkRunnerWithScreenshotCaptureListener;
+import org.apache.directory.studio.test.integration.ui.utils.Constants;
 import org.eclipse.core.runtime.Platform;
-import org.junit.After;
-import org.junit.Assume;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TestName;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assumptions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.condition.DisabledForJreRange;
+import org.junit.jupiter.api.condition.JRE;
 
 
 /**
@@ -63,42 +58,16 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-@RunWith(FrameworkRunnerWithScreenshotCaptureListener.class)
-public class GssApiTest
+@DisabledForJreRange(min = JRE.JAVA_16)
+public class GssApiTest extends AbstractTestBase
 {
     private static final String serverName = "GssApiTest";
 
-    @Rule
-    public TestName name = new TestName();
-
     private static int ldapPort;
     private static int kdcPort;
+    private TestInfo testInfo;
 
-    private static StudioBot studioBot;
-    private static ApacheDSServersViewBot serversViewBot;
-    private static ConnectionsViewBot connectionsViewBot;
-
-
-    @BeforeClass
-    public static void setUpClass() throws Exception
-    {
-        studioBot = new StudioBot();
-        studioBot.resetLdapPerspective();
-        serversViewBot = studioBot.getApacheDSServersViewBot();
-        connectionsViewBot = studioBot.getConnectionView();
-
-        // ErrorDialog.AUTOMATED_MODE = false;
-    }
-
-
-    @Before
-    public void setUp() throws Exception
-    {
-        studioBot.resetLdapPerspective();
-    }
-
-
-    @BeforeClass
+    @BeforeAll
     public static void skipGssApiTestIfNoDefaultRealmIsConfigured()
     {
         try
@@ -112,31 +81,31 @@
         }
         catch ( IllegalArgumentException e )
         {
-            Assume.assumeNoException( "Skipping tests as no default realm (/etc/krb5.conf) is configured", e );
+            Assumptions.assumeTrue( false, "Skipping tests as no default realm (/etc/krb5.conf) is configured" );
         }
     }
 
 
-    @After
-    public void tearDown() throws Exception
+    @BeforeEach
+    public void beforeEach( TestInfo testInfo )
     {
-        connectionsViewBot.deleteTestConnections();
+        this.testInfo = testInfo;
+    }
 
+
+    @AfterEach
+    public void afterEach() throws Exception
+    {
         // stop ApacheDS
         serversViewBot.stopServer( serverName );
         serversViewBot.waitForServerStop( serverName );
-
-        // delete ApacheDS
-        DeleteDialogBot deleteDialogBot = serversViewBot.openDeleteServerDialog();
-        deleteDialogBot.clickOkButton();
-
-        Assertions.genericTearDownAssertions();
     }
 
 
     private String getConnectionName()
     {
-        return "GssApiTest." + name.getMethodName();
+        return testInfo.getTestMethod().map( Method::getName ).orElse( "null" ) + " "
+            + testInfo.getDisplayName();
     }
 
 
@@ -174,55 +143,13 @@
 
         // check the connection
         String result = wizardBot.clickCheckAuthenticationButton();
-        assertNull( "Expected OK", result );
+        assertNull( result, "Expected OK" );
 
         wizardBot.clickCancelButton();
     }
 
 
-    @Test
-    public void testGssApiUseNativeTgtAndNativeConfigurationAndObtainServiceTicket() throws Exception
-    {
-        // create the server
-        createServer( serverName );
-
-        // configure ApacheDS and KDC server
-        configureApacheDS( serverName );
-
-        // start ApacheDS
-        serversViewBot.runServer( serverName );
-        serversViewBot.waitForServerStart( serverName );
-
-        // import KDC data
-        connectionsViewBot.createTestConnection( "GssApiTest", ldapPort );
-        importData();
-
-        // obtain native TGT
-        String[] cmd =
-            { "/bin/sh", "-c", "echo secret | /usr/bin/kinit hnelson" };
-        Process process = Runtime.getRuntime().exec( cmd );
-        int exitCode = process.waitFor();
-        assertEquals( 0, exitCode );
-
-        // connect with GSSAPI authentication
-        NewConnectionWizardBot wizardBot = connectionsViewBot.openNewConnectionWizard();
-        wizardBot.typeConnectionName( getConnectionName() );
-        wizardBot.typeHost( LOCALHOST );
-        wizardBot.typePort( ldapPort );
-        wizardBot.clickNextButton();
-        wizardBot.selectGssApiAuthentication();
-        wizardBot.selectUseNativeTgt();
-        wizardBot.selectUseNativeSystemConfiguration();
-
-        // check the connection
-        String result = wizardBot.clickCheckAuthenticationButton();
-        assertNull( "Expected OK", result );
-
-        wizardBot.clickCancelButton();
-    }
-
-
-    private static void createServer( String serverName )
+    private void createServer( String serverName )
     {
         // Showing view
         serversViewBot.show();
@@ -240,14 +167,13 @@
     }
 
 
-    private static void configureApacheDS( String serverName ) throws Exception
+    private void configureApacheDS( String serverName ) throws Exception
     {
         ApacheDSConfigurationEditorBot editorBot = serversViewBot.openConfigurationEditor( serverName );
 
         editorBot.enableKerberosServer();
 
         editorBot.setAvailablePorts();
-        editorBot.setKerberosPort( 60088 );
         ldapPort = editorBot.getLdapPort();
         kdcPort = editorBot.getKerberosPort();
 
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ImportExportTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ImportExportTest.java
index a395207..fcf5291 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ImportExportTest.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ImportExportTest.java
@@ -21,26 +21,36 @@
 package org.apache.directory.studio.test.integration.ui;
 
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.ALIAS_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.GERMAN_UMLAUT_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.MISC111_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.MISC_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.REFERRAL_TO_USER1_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.SUBENTRY_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USER1_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USER2_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USERS_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.dn;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.File;
-import java.io.InputStream;
+import java.io.IOException;
 import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.util.List;
 import java.util.function.Supplier;
 
+import org.apache.directory.api.ldap.model.entry.DefaultEntry;
 import org.apache.directory.api.ldap.model.message.SearchScope;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.util.FileUtils;
-import org.apache.directory.api.util.IOUtils;
-import org.apache.directory.server.annotations.CreateLdapServer;
-import org.apache.directory.server.annotations.CreateTransport;
-import org.apache.directory.server.core.annotations.ApplyLdifFiles;
+import org.apache.directory.server.core.api.DirectoryService;
 import org.apache.directory.server.core.api.partition.Partition;
-import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
 import org.apache.directory.server.core.partition.impl.avl.AvlPartition;
 import org.apache.directory.studio.connection.core.Connection;
 import org.apache.directory.studio.connection.core.Connection.AliasDereferencingMethod;
@@ -48,24 +58,21 @@
 import org.apache.directory.studio.ldapbrowser.core.BrowserCorePlugin;
 import org.apache.directory.studio.ldapbrowser.core.events.EventRegistry;
 import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection;
+import org.apache.directory.studio.test.integration.junit5.ApacheDirectoryServer;
+import org.apache.directory.studio.test.integration.junit5.LdapServerType;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource;
+import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource.Mode;
 import org.apache.directory.studio.test.integration.ui.bots.BotUtils;
-import org.apache.directory.studio.test.integration.ui.bots.BrowserViewBot;
-import org.apache.directory.studio.test.integration.ui.bots.ConnectionsViewBot;
 import org.apache.directory.studio.test.integration.ui.bots.DeleteDialogBot;
 import org.apache.directory.studio.test.integration.ui.bots.EntryEditorBot;
 import org.apache.directory.studio.test.integration.ui.bots.ExportWizardBot;
 import org.apache.directory.studio.test.integration.ui.bots.ImportWizardBot;
-import org.apache.directory.studio.test.integration.ui.bots.SearchLogsViewBot;
-import org.apache.directory.studio.test.integration.ui.bots.StudioBot;
-import org.apache.directory.studio.test.integration.ui.bots.utils.Assertions;
-import org.apache.directory.studio.test.integration.ui.bots.utils.Characters;
-import org.apache.directory.studio.test.integration.ui.bots.utils.FrameworkRunnerWithScreenshotCaptureListener;
+import org.apache.directory.studio.test.integration.ui.utils.Characters;
+import org.apache.directory.studio.test.integration.ui.utils.ResourceUtils;
 import org.eclipse.core.runtime.Platform;
 import org.eclipse.core.runtime.Preferences;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.params.ParameterizedTest;
 
 
 /**
@@ -74,38 +81,8 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-@RunWith(FrameworkRunnerWithScreenshotCaptureListener.class)
-@CreateLdapServer(transports =
-    { @CreateTransport(protocol = "LDAP") })
-@ApplyLdifFiles(clazz = ImportExportTest.class, value = "org/apache/directory/studio/test/integration/ui/ImportExportTest.ldif")
-public class ImportExportTest extends AbstractLdapTestUnit
+public class ImportExportTest extends AbstractTestBase
 {
-    private StudioBot studioBot;
-    private ConnectionsViewBot connectionsViewBot;
-    private BrowserViewBot browserViewBot;
-    private Connection connection;
-    private SearchLogsViewBot searchLogsViewBot;
-
-
-    @Before
-    public void setUp() throws Exception
-    {
-        studioBot = new StudioBot();
-        studioBot.resetLdapPerspective();
-        connectionsViewBot = studioBot.getConnectionView();
-        connection = connectionsViewBot.createTestConnection( "ImportExportTest", ldapServer.getPort() );
-        browserViewBot = studioBot.getBrowserView();
-        searchLogsViewBot = studioBot.getSearchLogsViewBot();
-    }
-
-
-    @After
-    public void tearDown() throws Exception
-    {
-        connectionsViewBot.deleteTestConnections();
-        Assertions.genericTearDownAssertions();
-    }
-
 
     /**
      * Test for DIRSTUDIO-395.
@@ -118,13 +95,15 @@
      * @throws Exception
      *             the exception
      */
-    @Test
-    public void testExportImportLdifWithGermanUmlautInDN() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testExportImportLdifWithGermanUmlautInDN( TestLdapServer server ) throws Exception
     {
+        connectionsViewBot.createTestConnection( server );
         URL url = Platform.getInstanceLocation().getURL();
-        final String file = url.getFile() + "ImportExportWithGermanUmlautInDnTest.ldif";
+        final String file = url.getFile() + "ImportExportWithGermanUmlautInDnTest" + server.getType().name() + ".ldif";
 
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=Wolfgang K\u00f6lbel" );
+        browserViewBot.selectEntry( path( GERMAN_UMLAUT_DN ) );
 
         // export LDIF
         ExportWizardBot wizardBot = browserViewBot.openExportLdifWizard();
@@ -136,17 +115,16 @@
 
         List<String> lines = FileUtils.readLines( new File( file ), StandardCharsets.UTF_8 );
         // verify that the first line of exported LDIF is "version: 1"
-        assertEquals( "LDIF must start with version: 1", lines.get( 0 ), "version: 1" );
+        assertEquals( lines.get( 0 ), "version: 1", "LDIF must start with version: 1" );
         // verify that the third line of exported LDIF is the Base64 encoded DN
-        assertEquals( "Expected Base64 encoded DN", lines.get( 2 ),
-            "dn:: Y249V29sZmdhbmcgS8O2bGJlbCxvdT11c2VycyxvdT1zeXN0ZW0=" );
+        assertEquals( lines.get( 2 ), "dn:: Y249V29sZmdhbmcgS8O2bGJlbCxvdT1taXNjLGRjPWV4YW1wbGUsZGM9b3Jn",
+            "Expected Base64 encoded DN" );
 
         // delete entry
         DeleteDialogBot dialogBot = browserViewBot.openDeleteDialog();
         assertTrue( dialogBot.isVisible() );
         dialogBot.clickOkButton();
-        assertFalse(
-            browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=Wolfgang K\u00f6lbel" ) );
+        assertFalse( browserViewBot.existsEntry( path( GERMAN_UMLAUT_DN ) ) );
 
         // import LDIF
         ImportWizardBot importWizardBot = browserViewBot.openImportLdifWizard();
@@ -154,9 +132,8 @@
         importWizardBot.clickFinishButton();
 
         // verify that entry with umlaut exists
-        assertTrue(
-            browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=Wolfgang K\u00f6lbel" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=Wolfgang K\u00f6lbel" );
+        assertTrue( browserViewBot.existsEntry( path( GERMAN_UMLAUT_DN ) ) );
+        browserViewBot.selectEntry( path( GERMAN_UMLAUT_DN ) );
     }
 
 
@@ -171,13 +148,15 @@
      * @throws Exception
      *             the exception
      */
-    @Test
-    public void testExportImportDsmlWithGermanUmlautInDN() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testExportImportDsmlWithGermanUmlautInDN( TestLdapServer server ) throws Exception
     {
+        connectionsViewBot.createTestConnection( server );
         URL url = Platform.getInstanceLocation().getURL();
-        final String file = url.getFile() + "ImportExportWithGermanUmlautInDnTest.dsml";
+        final String file = url.getFile() + "ImportExportWithGermanUmlautInDnTest" + server.getType().name() + ".dsml";
 
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=Wolfgang K\u00f6lbel" );
+        browserViewBot.selectEntry( path( GERMAN_UMLAUT_DN ) );
 
         // export DSML
         ExportWizardBot wizardBot = browserViewBot.openExportDsmlWizard();
@@ -190,15 +169,14 @@
 
         // verify that exported DSML contains the Base64 encoded DN
         String content = FileUtils.readFileToString( new File( file ), StandardCharsets.UTF_8 );
-        assertTrue( "DSML must contain DN with umlaut.",
-            content.contains( "dn=\"cn=Wolfgang K\u00f6lbel,ou=users,ou=system\"" ) );
+        assertTrue( content.contains( "dn=\"" + GERMAN_UMLAUT_DN.getName() + "\"" ),
+            "DSML must contain DN with umlaut." );
 
         // delete entry
         DeleteDialogBot dialogBot = browserViewBot.openDeleteDialog();
         assertTrue( dialogBot.isVisible() );
         dialogBot.clickOkButton();
-        assertFalse(
-            browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=Wolfgang K\u00f6lbel" ) );
+        assertFalse( browserViewBot.existsEntry( path( GERMAN_UMLAUT_DN ) ) );
 
         // import DSML
         ImportWizardBot importWizardBot = browserViewBot.openImportDsmlWizard();
@@ -206,181 +184,305 @@
         importWizardBot.clickFinishButton();
 
         // verify that entry with umlaut exists
-        assertTrue(
-            browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=Wolfgang K\u00f6lbel" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=Wolfgang K\u00f6lbel" );
+        assertTrue( browserViewBot.existsEntry( path( GERMAN_UMLAUT_DN ) ) );
+        browserViewBot.selectEntry( path( GERMAN_UMLAUT_DN ) );
     }
 
 
-    @Test
-    public void testExportImportLdifSpecialEntries() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testExportImportLdifAlias( TestLdapServer server ) throws Exception
     {
+        Connection connection = connectionsViewBot.createTestConnection( server );
         // disable alias dereferencing
         connection.getConnectionParameter().setExtendedIntProperty(
             IBrowserConnection.CONNECTION_PARAMETER_ALIASES_DEREFERENCING_METHOD,
             AliasDereferencingMethod.NEVER.ordinal() );
-        // enable ManageDsaIT control
-        connection.getConnectionParameter().setExtendedBoolProperty(
-            IBrowserConnection.CONNECTION_PARAMETER_MANAGE_DSA_IT, true );
-        // enable Subentries control
-        connection.getConnectionParameter().setExtendedBoolProperty(
-            IBrowserConnection.CONNECTION_PARAMETER_FETCH_SUBENTRIES, true );
 
         URL url = Platform.getInstanceLocation().getURL();
-        final String file1 = url.getFile() + "ImportExportSpecialEntries1Test.ldif";
-        final String file2 = url.getFile() + "ImportExportSpecialEntries2Test.ldif";
+        final String file = url.getFile() + "ImportExportAlias" + server.getType().name() + ".ldif";
 
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=special" );
+        browserViewBot.selectEntry( path( ALIAS_DN.getParent() ) );
 
-        // export first LDIF (alias and referral)
+        // export to LDIF
         ExportWizardBot wizardBot = browserViewBot.openExportLdifWizard();
         assertTrue( wizardBot.isVisible() );
-        wizardBot.setReturningAttributes( "ref" );
+        wizardBot.setFilter( "(objectClass=alias)" );
         wizardBot.setScope( SearchScope.ONELEVEL );
-        wizardBot.setControlManageDsaIT( true );
         wizardBot.setAliasDereferencingMode( AliasDereferencingMethod.NEVER );
         wizardBot.clickNextButton();
-        wizardBot.typeFile( file1 );
+        wizardBot.typeFile( file );
         wizardBot.clickFinishButton();
-        wizardBot.waitTillExportFinished( file1, 200 );
+        wizardBot.waitTillExportFinished( file, 50 );
 
-        List<String> lines1 = FileUtils.readLines( new File( file1 ), StandardCharsets.UTF_8 );
-        assertEquals( "LDIF must start with version: 1", lines1.get( 0 ), "version: 1" );
-        assertTrue( lines1.contains( "dn: cn=referral,ou=special,ou=system" ) );
-        assertTrue( lines1.contains( "ref: ldap://foo.example.com/ou=system" ) );
-        assertTrue( lines1.contains( "dn: cn=alias,ou=special,ou=system" ) );
+        List<String> lines = FileUtils.readLines( new File( file ), StandardCharsets.UTF_8 );
+        assertEquals( lines.get( 0 ), "version: 1", "LDIF must start with version: 1" );
+        assertTrue( lines.contains( "dn: " + ALIAS_DN.getName() ) );
 
-        // export second LDIF (subentry)
-        wizardBot = browserViewBot.openExportLdifWizard();
-        assertTrue( wizardBot.isVisible() );
-        wizardBot.setReturningAttributes( "subtreeSpecification" );
-        wizardBot.setScope( SearchScope.ONELEVEL );
-        wizardBot.setControlSubentries( true );
-        wizardBot.clickNextButton();
-        wizardBot.typeFile( file2 );
-        wizardBot.clickFinishButton();
-        wizardBot.waitTillExportFinished( file2, 100 );
-
-        List<String> lines2 = FileUtils.readLines( new File( file2 ), StandardCharsets.UTF_8 );
-        assertEquals( "LDIF must start with version: 1", lines2.get( 0 ), "version: 1" );
-        assertTrue( lines2.contains( "dn: cn=subentry,ou=special,ou=system" ) );
-        assertTrue( lines2.contains( "subtreespecification: { }" ) );
-
-        // delete entries
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=special" );
-        String[] children =
-            { "cn=alias", "cn=referral", "cn=subentry" };
-        // select entries twice, sometimes one gets unselected, reason unknown
-        browserViewBot.selectChildrenOfEntry( children, "DIT", "Root DSE", "ou=system", "ou=special" );
-        browserViewBot.selectChildrenOfEntry( children, "DIT", "Root DSE", "ou=system", "ou=special" );
+        // delete entry
+        browserViewBot.selectEntry( path( ALIAS_DN ) );
         DeleteDialogBot dialogBot = browserViewBot.openDeleteDialog();
         assertTrue( dialogBot.isVisible() );
         dialogBot.clickOkButton();
-        waitAndAssert(false, () -> browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=special", "cn=alias" ));
-        waitAndAssert(false, () -> browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=special", "cn=referral" ));
-        waitAndAssert(false, () -> browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=special", "cn=subentry" ));
+        waitAndAssert( false,
+            () -> browserViewBot.existsEntry( path( ALIAS_DN ) ) );
 
-        // import LDIFs
+        // import LDIF
         ImportWizardBot importWizardBot = browserViewBot.openImportLdifWizard();
-        importWizardBot.typeFile( file1 );
-        importWizardBot.clickFinishButton();
-        importWizardBot = browserViewBot.openImportLdifWizard();
-        importWizardBot.typeFile( file2 );
+        importWizardBot.typeFile( file );
         importWizardBot.clickFinishButton();
 
-        // verify that entries exist
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=special" ) );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=special", "cn=alias" ) );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=special", "cn=referral" ) );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=special", "cn=subentry" ) );
+        // verify that entry exist
+        assertTrue( browserViewBot.existsEntry( path( ALIAS_DN ) ) );
     }
 
 
-    @Test
-    public void testExportImportDsmlSpecialEntries() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testExportImportLdifReferral( TestLdapServer server ) throws Exception
     {
-        // disable alias dereferencing
-        connection.getConnectionParameter().setExtendedIntProperty(
-            IBrowserConnection.CONNECTION_PARAMETER_ALIASES_DEREFERENCING_METHOD,
-            AliasDereferencingMethod.NEVER.ordinal() );
+        Connection connection = connectionsViewBot.createTestConnection( server );
         // enable ManageDsaIT control
         connection.getConnectionParameter().setExtendedBoolProperty(
             IBrowserConnection.CONNECTION_PARAMETER_MANAGE_DSA_IT, true );
+
+        URL url = Platform.getInstanceLocation().getURL();
+        final String file = url.getFile() + "ImportExportReferral" + server.getType().name() + ".ldif";
+
+        browserViewBot.selectEntry( path( REFERRAL_TO_USER1_DN.getParent() ) );
+
+        // export to LDIF
+        ExportWizardBot wizardBot = browserViewBot.openExportLdifWizard();
+        assertTrue( wizardBot.isVisible() );
+        wizardBot.setFilter( "(" + REFERRAL_TO_USER1_DN.getRdn().getName() + ")" );
+        wizardBot.setReturningAttributes( "ref" );
+        wizardBot.setScope( SearchScope.ONELEVEL );
+        wizardBot.setControlManageDsaIT( true );
+        wizardBot.clickNextButton();
+        wizardBot.typeFile( file );
+        wizardBot.clickFinishButton();
+        wizardBot.waitTillExportFinished( file, 20 );
+
+        List<String> lines = FileUtils.readLines( new File( file ), StandardCharsets.UTF_8 );
+        assertEquals( lines.get( 0 ), "version: 1", "LDIF must start with version: 1" );
+        assertTrue( lines.contains( "dn: " + REFERRAL_TO_USER1_DN.getName() ) );
+        assertTrue( lines.contains( "ref: " + server.getLdapUrl() + "/" + USER1_DN.getName() ) );
+
+        // delete entry
+        browserViewBot.selectEntry( path( REFERRAL_TO_USER1_DN ) );
+        DeleteDialogBot dialogBot = browserViewBot.openDeleteDialog();
+        assertTrue( dialogBot.isVisible() );
+        dialogBot.clickOkButton();
+        waitAndAssert( false,
+            () -> browserViewBot.existsEntry( path( REFERRAL_TO_USER1_DN ) ) );
+
+        // import LDIF
+        ImportWizardBot importWizardBot = browserViewBot.openImportLdifWizard();
+        importWizardBot.typeFile( file );
+        importWizardBot.clickFinishButton();
+
+        // verify that entry exist
+        assertTrue( browserViewBot.existsEntry( path( REFERRAL_TO_USER1_DN ) ) );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.ApacheDS, reason = "ApacheDS specific test")
+    public void testExportImportLdifSubentry( TestLdapServer server ) throws Exception
+    {
+        Connection connection = connectionsViewBot.createTestConnection( server );
         // enable Subentries control
         connection.getConnectionParameter().setExtendedBoolProperty(
             IBrowserConnection.CONNECTION_PARAMETER_FETCH_SUBENTRIES, true );
 
         URL url = Platform.getInstanceLocation().getURL();
-        final String file1 = url.getFile() + "ImportExportSpecialEntries1Test.dsml";
-        final String file2 = url.getFile() + "ImportExportSpecialEntries2Test.dsml";
+        final String file = url.getFile() + "ImportExportSubentry" + server.getType().name() + ".ldif";
 
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=special" );
+        browserViewBot.selectEntry( path( SUBENTRY_DN.getParent() ) );
 
-        // export first DSML (alias and referral)
-        ExportWizardBot wizardBot = browserViewBot.openExportDsmlWizard();
+        // export to LDIF
+        ExportWizardBot wizardBot = browserViewBot.openExportLdifWizard();
         assertTrue( wizardBot.isVisible() );
-        wizardBot.setReturningAttributes( "ref" );
-        wizardBot.setScope( SearchScope.ONELEVEL );
-        wizardBot.setControlManageDsaIT( true );
-        wizardBot.setAliasDereferencingMode( AliasDereferencingMethod.NEVER );
-        wizardBot.clickNextButton();
-        wizardBot.typeFile( file1 );
-        wizardBot.selectDsmlRequest();
-        wizardBot.clickFinishButton();
-        wizardBot.waitTillExportFinished( file1, 800 );
-
-        // verify that exported DSML contains the entries
-        String content1 = FileUtils.readFileToString( new File( file1 ), StandardCharsets.UTF_8 );
-        assertTrue( content1.contains( "dn=\"cn=referral,ou=special,ou=system\"" ) );
-        assertTrue( content1.contains( "<attr name=\"ref\">" ) );
-        assertTrue( content1.contains( "<value>ldap://foo.example.com/ou=system</value>" ) );
-        assertTrue( content1.contains( "dn=\"cn=alias,ou=special,ou=system\"" ) );
-
-        // export second DSML (subentry)
-        wizardBot = browserViewBot.openExportDsmlWizard();
-        assertTrue( wizardBot.isVisible() );
+        wizardBot.setFilter( "(objectClass=subentry)" );
         wizardBot.setReturningAttributes( "subtreeSpecification" );
         wizardBot.setScope( SearchScope.ONELEVEL );
         wizardBot.setControlSubentries( true );
         wizardBot.clickNextButton();
-        wizardBot.typeFile( file2 );
-        wizardBot.selectDsmlRequest();
+        wizardBot.typeFile( file );
         wizardBot.clickFinishButton();
-        wizardBot.waitTillExportFinished( file2, 300 );
+        wizardBot.waitTillExportFinished( file, 20 );
 
-        // verify that exported DSML contains the entries
-        String content2 = FileUtils.readFileToString( new File( file2 ), StandardCharsets.UTF_8 );
-        assertTrue( content2.contains( "dn=\"cn=subentry,ou=special,ou=system\"" ) );
-        assertTrue( content2.contains( "<attr name=\"subtreespecification\">" ) );
-        assertTrue( content2.contains( "<value>{ }</value>" ) );
+        List<String> lines = FileUtils.readLines( new File( file ), StandardCharsets.UTF_8 );
+        assertEquals( lines.get( 0 ), "version: 1", "LDIF must start with version: 1" );
+        assertTrue( lines.contains( "dn: " + SUBENTRY_DN.getName() ) );
+        assertTrue( lines.contains( "subtreeSpecification: {}" ) );
 
-        // delete entries
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=special" );
-        String[] children =
-            { "cn=alias", "cn=referral", "cn=subentry" };
-        // select entries twice, sometimes one gets unselected, reason unknown
-        browserViewBot.selectChildrenOfEntry( children, "DIT", "Root DSE", "ou=system", "ou=special" );
-        browserViewBot.selectChildrenOfEntry( children, "DIT", "Root DSE", "ou=system", "ou=special" );
+        // delete entry
+        browserViewBot.selectEntry( path( SUBENTRY_DN ) );
         DeleteDialogBot dialogBot = browserViewBot.openDeleteDialog();
         assertTrue( dialogBot.isVisible() );
         dialogBot.clickOkButton();
-        waitAndAssert(false, () -> browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=special", "cn=alias" ));
-        waitAndAssert(false, () -> browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=special", "cn=referral" ));
-        waitAndAssert(false, () -> browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=special", "cn=subentry" ));
+        waitAndAssert( false,
+            () -> browserViewBot.existsEntry( path( SUBENTRY_DN ) ) );
+
+        // import LDIF
+        ImportWizardBot importWizardBot = browserViewBot.openImportLdifWizard();
+        importWizardBot.typeFile( file );
+        importWizardBot.clickFinishButton();
+
+        // verify that entry exist
+        assertTrue( browserViewBot.existsEntry( path( SUBENTRY_DN ) ) );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testExportImportDsmlAlias( TestLdapServer server ) throws Exception
+    {
+        Connection connection = connectionsViewBot.createTestConnection( server );
+        // disable alias dereferencing
+        connection.getConnectionParameter().setExtendedIntProperty(
+            IBrowserConnection.CONNECTION_PARAMETER_ALIASES_DEREFERENCING_METHOD,
+            AliasDereferencingMethod.NEVER.ordinal() );
+
+        URL url = Platform.getInstanceLocation().getURL();
+        final String file = url.getFile() + "ImportExportAlias" + server.getType().name() + ".dsml";
+
+        browserViewBot.selectEntry( path( ALIAS_DN.getParent() ) );
+
+        // export to DSML
+        ExportWizardBot wizardBot = browserViewBot.openExportDsmlWizard();
+        assertTrue( wizardBot.isVisible() );
+        wizardBot.setFilter( "(objectClass=alias)" );
+        wizardBot.setScope( SearchScope.ONELEVEL );
+        wizardBot.setAliasDereferencingMode( AliasDereferencingMethod.NEVER );
+        wizardBot.clickNextButton();
+        wizardBot.typeFile( file );
+        wizardBot.selectDsmlRequest();
+        wizardBot.clickFinishButton();
+        wizardBot.waitTillExportFinished( file, 50 );
+
+        // verify that exported DSML contains the entry
+        String content = FileUtils.readFileToString( new File( file ), StandardCharsets.UTF_8 );
+        assertTrue( content.contains( "dn=\"" + ALIAS_DN.getName() + "\"" ) );
+
+        // delete entry
+        browserViewBot.selectEntry( path( ALIAS_DN ) );
+        DeleteDialogBot dialogBot = browserViewBot.openDeleteDialog();
+        assertTrue( dialogBot.isVisible() );
+        dialogBot.clickOkButton();
+        waitAndAssert( false,
+            () -> browserViewBot.existsEntry( path( ALIAS_DN ) ) );
 
         // import DSML
         ImportWizardBot importWizardBot = browserViewBot.openImportDsmlWizard();
-        importWizardBot.typeFile( file1 );
-        importWizardBot.clickFinishButton();
-        importWizardBot = browserViewBot.openImportDsmlWizard();
-        importWizardBot.typeFile( file2 );
+        importWizardBot.typeFile( file );
         importWizardBot.clickFinishButton();
 
-        // verify that entries exist
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=special" ) );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=special", "cn=alias" ) );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=special", "cn=referral" ) );
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=special", "cn=subentry" ) );
+        // verify that entry exist
+        assertTrue( browserViewBot.existsEntry( path( ALIAS_DN ) ) );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testExportImportDsmlReferral( TestLdapServer server ) throws Exception
+    {
+        Connection connection = connectionsViewBot.createTestConnection( server );
+        // enable ManageDsaIT control
+        connection.getConnectionParameter().setExtendedBoolProperty(
+            IBrowserConnection.CONNECTION_PARAMETER_MANAGE_DSA_IT, true );
+
+        URL url = Platform.getInstanceLocation().getURL();
+        final String file = url.getFile() + "ImportExportReferral" + server.getType().name() + ".dsml";
+
+        browserViewBot.selectEntry( path( REFERRAL_TO_USER1_DN.getParent() ) );
+
+        // export to DSML
+        ExportWizardBot wizardBot = browserViewBot.openExportDsmlWizard();
+        assertTrue( wizardBot.isVisible() );
+        wizardBot.setFilter( "(" + REFERRAL_TO_USER1_DN.getRdn().getName() + ")" );
+        wizardBot.setReturningAttributes( "ref" );
+        wizardBot.setScope( SearchScope.ONELEVEL );
+        wizardBot.setControlManageDsaIT( true );
+        wizardBot.clickNextButton();
+        wizardBot.typeFile( file );
+        wizardBot.selectDsmlRequest();
+        wizardBot.clickFinishButton();
+        wizardBot.waitTillExportFinished( file, 50 );
+
+        // verify that exported DSML contains the entry
+        String content = FileUtils.readFileToString( new File( file ), StandardCharsets.UTF_8 );
+        assertTrue( content.contains( "dn=\"" + REFERRAL_TO_USER1_DN.getName() + "\"" ) );
+        assertTrue( content.contains( "<attr name=\"ref\">" ) );
+        assertTrue( content.contains( "<value>" + server.getLdapUrl() + "/" + USER1_DN.getName() + "</value>" ) );
+
+        // delete entry
+        browserViewBot.selectEntry( path( REFERRAL_TO_USER1_DN ) );
+        DeleteDialogBot dialogBot = browserViewBot.openDeleteDialog();
+        assertTrue( dialogBot.isVisible() );
+        dialogBot.clickOkButton();
+        waitAndAssert( false,
+            () -> browserViewBot.existsEntry( path( REFERRAL_TO_USER1_DN ) ) );
+
+        // import DSML
+        ImportWizardBot importWizardBot = browserViewBot.openImportDsmlWizard();
+        importWizardBot.typeFile( file );
+        importWizardBot.clickFinishButton();
+
+        // verify that entry exist
+        assertTrue( browserViewBot.existsEntry( path( REFERRAL_TO_USER1_DN ) ) );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.ApacheDS, reason = "ApacheDS specific test")
+    public void testExportImportDsmlSubentry( TestLdapServer server ) throws Exception
+    {
+        Connection connection = connectionsViewBot.createTestConnection( server );
+        // enable Subentries control
+        connection.getConnectionParameter().setExtendedBoolProperty(
+            IBrowserConnection.CONNECTION_PARAMETER_FETCH_SUBENTRIES, true );
+
+        URL url = Platform.getInstanceLocation().getURL();
+        final String file = url.getFile() + "ImportExportSubentry" + server.getType().name() + ".dsml";
+
+        browserViewBot.selectEntry( path( SUBENTRY_DN.getParent() ) );
+
+        // export to DSML
+        ExportWizardBot wizardBot = browserViewBot.openExportDsmlWizard();
+        assertTrue( wizardBot.isVisible() );
+        wizardBot.setFilter( "(objectClass=subentry)" );
+        wizardBot.setReturningAttributes( "subtreeSpecification" );
+        wizardBot.setScope( SearchScope.ONELEVEL );
+        wizardBot.setControlSubentries( true );
+        wizardBot.clickNextButton();
+        wizardBot.typeFile( file );
+        wizardBot.selectDsmlRequest();
+        wizardBot.clickFinishButton();
+        wizardBot.waitTillExportFinished( file, 50 );
+
+        // verify that exported DSML
+        String content = FileUtils.readFileToString( new File( file ), StandardCharsets.UTF_8 );
+        assertTrue( content.contains( "dn=\"" + SUBENTRY_DN.getName() + "\"" ) );
+        assertTrue( content.contains( "<attr name=\"subtreespecification\">" ) );
+        assertTrue( content.contains( "<value>{}</value>" ) );
+
+        // delete entry
+        browserViewBot.selectEntry( path( SUBENTRY_DN ) );
+        DeleteDialogBot dialogBot = browserViewBot.openDeleteDialog();
+        assertTrue( dialogBot.isVisible() );
+        dialogBot.clickOkButton();
+        waitAndAssert( false,
+            () -> browserViewBot.existsEntry( path( SUBENTRY_DN ) ) );
+
+        // import DSML
+        ImportWizardBot importWizardBot = browserViewBot.openImportDsmlWizard();
+        importWizardBot.typeFile( file );
+        importWizardBot.clickFinishButton();
+
+        // verify that entry exist
+        assertTrue( browserViewBot.existsEntry( path( SUBENTRY_DN ) ) );
     }
 
 
@@ -405,9 +507,11 @@
     }
 
 
-    @Test
-    public void testExportWithPagedResultControl() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.ApacheDS, reason = "ApacheDS specific test")
+    public void testExportWithPagedResultControl( TestLdapServer server ) throws Exception
     {
+        connectionsViewBot.createTestConnection( server );
         URL url = Platform.getInstanceLocation().getURL();
         final String file = url.getFile() + "ExportWithPagedResultControl.ldif";
 
@@ -424,7 +528,7 @@
         wizardBot.waitTillExportFinished( file, 2500 );
 
         List<String> lines = FileUtils.readLines( new File( file ), StandardCharsets.UTF_8 );
-        assertEquals( "LDIF must start with version: 1", lines.get( 0 ), "version: 1" );
+        assertEquals( lines.get( 0 ), "version: 1", "LDIF must start with version: 1" );
         assertTrue( lines.contains( "dn: cn=adsconfig,ou=schema" ) );
         assertTrue( lines.contains( "dn: cn=apachemeta,ou=schema" ) );
         assertTrue( lines.contains( "dn: cn=core,ou=schema" ) );
@@ -440,14 +544,16 @@
      *
      * Import a new context entry must refresh the root DSE and
      * show the new context entry in the LDAP Browser view.
-     *
-     * @throws Exception
-     *             the exception
      */
-    @Test
-    public void testImportContextEntryRefreshesRootDSE() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.ApacheDS, reason = "ApacheDS specific test")
+    public void testImportContextEntryRefreshesRootDSE( TestLdapServer server ) throws Exception
     {
+        connectionsViewBot.createTestConnection( server );
+
         // add a new partition
+        ApacheDirectoryServer apacheds = ( ApacheDirectoryServer ) server;
+        DirectoryService service = apacheds.getService();
         Partition partition = new AvlPartition( service.getSchemaManager(), service.getDnFactory() );
         partition.setId( "example" );
         partition.setSuffixDn( new Dn( "dc=example,dc=com" ) );
@@ -479,52 +585,49 @@
      * Test for DIRSTUDIO-489.
      *
      * Verify that there are no UI updates when importing an LDIF.
-     *
-     * @throws Exception
      */
-    @Test
-    public void testImportDoesNotUpdateUI() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testImportDoesNotUpdateUI( TestLdapServer server ) throws Exception
     {
-        URL url = Platform.getInstanceLocation().getURL();
-        String destFile = url.getFile() + "ImportDontUpdateUiTest.ldif";
-        InputStream is = getClass().getResourceAsStream( "ImportExportTest_ImportDontUpdateUI.ldif" );
-        String ldifContent = IOUtils.toString( is, StandardCharsets.UTF_8 );
-        FileUtils.writeStringToFile( new File( destFile ), ldifContent, StandardCharsets.UTF_8, false );
-
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( MISC111_DN ) );
+        browserViewBot.expandEntry( path( MISC111_DN ) );
 
         long fireCount0 = EventRegistry.getFireCount();
 
         // import the LDIF
+        String file = prepareInputFile( "ImportExportTest_User1to8.ldif" );
         ImportWizardBot importWizardBot = browserViewBot.openImportLdifWizard();
-        importWizardBot.typeFile( destFile );
+        importWizardBot.typeFile( file );
         importWizardBot.clickFinishButton();
-        browserViewBot.waitForEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=User.1" );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=User.1" );
+        browserViewBot.waitForEntry( path( MISC111_DN, "uid=User.1" ) );
+        browserViewBot.selectEntry( path( MISC111_DN, "uid=User.1" ) );
 
         long fireCount1 = EventRegistry.getFireCount();
 
         // verify that only three two events were fired between Import
         long fireCount = fireCount1 - fireCount0;
-        assertEquals( "Only 2 event firings expected when importing LDIF.", 2, fireCount );
+        assertEquals( 2, fireCount, "Only 2 event firings expected when importing LDIF." );
     }
 
 
     /**
      * Export to CSV and checks that spreadsheet formulas are prefixed with an apostrophe.
      */
-    @Test
-    public void testExportCsvShouldPrefixFormulaWithApostrophe() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testExportCsvShouldPrefixFormulaWithApostrophe( TestLdapServer server ) throws Exception
     {
+        connectionsViewBot.createTestConnection( server );
         // set CSV encoding explicit to UTF-8, otherwise platform default encoding would be used
         Preferences store = BrowserCorePlugin.getDefault().getPluginPreferences();
         store.setDefault( BrowserCoreConstants.PREFERENCE_FORMAT_CSV_ENCODING, "UTF-8" );
 
         URL url = Platform.getInstanceLocation().getURL();
-        final String file = url.getFile() + "ImportExportTest.csv";
+        final String file = url.getFile() + "ImportExportTest" + server.getType().name() + ".csv";
 
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=Wolfgang K\u00f6lbel" );
+        browserViewBot.selectEntry( path( GERMAN_UMLAUT_DN ) );
 
         // export CSV
         ExportWizardBot wizardBot = browserViewBot.openExportCsvWizard();
@@ -539,8 +642,7 @@
         // verify that the first line is header
         assertEquals( "dn,cn,description", lines.get( 0 ) );
         // verify that the second line is actual content and the formula is prefixed with an apostrophe
-        assertEquals( "\"cn=Wolfgang K\u00f6lbel,ou=users,ou=system\",\"Wolfgang K\u00f6lbel\",\"'=1+1\"",
-            lines.get( 1 ) );
+        assertEquals( "\"" + GERMAN_UMLAUT_DN.getName() + "\",\"Wolfgang K\u00f6lbel\",\"'=1+1\"", lines.get( 1 ) );
     }
 
 
@@ -548,27 +650,24 @@
      * Test for DIRSTUDIO-1160.
      *
      * Attributes silently dropped and not imported when import LDIF and provider is Apache Directory LDAP API.
-     *
-     * @throws Exception
      */
-    @Test
-    public void testDIRSTUDIO_1160() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testDIRSTUDIO_1160( TestLdapServer server ) throws Exception
     {
-        URL url = Platform.getInstanceLocation().getURL();
-        String destFile = url.getFile() + "DIRSTUDIO-1160.ldif";
-        InputStream is = getClass().getResourceAsStream( "DIRSTUDIO-1160.ldif" );
-        String ldifContent = IOUtils.toString( is, StandardCharsets.UTF_8 );
-        FileUtils.writeStringToFile( new File( destFile ), ldifContent, StandardCharsets.UTF_8, false );
+        connectionsViewBot.createTestConnection( server );
+        Dn dn = dn( "cn=U0034692", MISC_DN );
 
         // import the LDIF
+        String file = prepareInputFile( "DIRSTUDIO-1160.ldif" );
         ImportWizardBot importWizardBot = browserViewBot.openImportLdifWizard();
-        importWizardBot.typeFile( destFile );
+        importWizardBot.typeFile( file );
         importWizardBot.clickFinishButton();
 
-        browserViewBot.waitForEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=U0034692" );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=U0034692" );
+        browserViewBot.waitForEntry( path( dn ) );
+        browserViewBot.selectEntry( path( dn ) );
 
-        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( "cn=U0034692,ou=users,ou=system" );
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( dn.getName() );
         entryEditorBot.activate();
         assertTrue( entryEditorBot.getAttributeValues().contains( "description: Initial import" ) );
         assertTrue( entryEditorBot.getAttributeValues().contains( "description: Good#Stuff" ) );
@@ -582,37 +681,132 @@
     /**
      * Test LDIF with several modifications.
      */
-    @Test
-    public void testLdifModification() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testLdifModification( TestLdapServer server ) throws Exception
     {
-        URL url = Platform.getInstanceLocation().getURL();
-        String destFile = url.getFile() + "ImportExportTest_Modifications.ldif";
-        InputStream is = getClass().getResourceAsStream( "ImportExportTest_Modifications.ldif" );
-        String ldifContent = IOUtils.toString( is, StandardCharsets.UTF_8 );
-        FileUtils.writeStringToFile( new File( destFile ), ldifContent, StandardCharsets.UTF_8, false );
-
+        connectionsViewBot.createTestConnection( server );
         // import the LDIF
+        String file = prepareInputFile( "ImportExportTest_Modifications.ldif" );
         ImportWizardBot importWizardBot = browserViewBot.openImportLdifWizard();
-        importWizardBot.typeFile( destFile );
+        importWizardBot.typeFile( file );
         importWizardBot.clickFinishButton();
 
-        browserViewBot.waitForEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.1" );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.1" );
-        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( "uid=user.1,ou=users,ou=system" );
+        browserViewBot.waitForEntry( path( USER1_DN ) );
+        browserViewBot.selectEntry( path( USER1_DN ) );
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( USER1_DN.getName() );
         entryEditorBot.activate();
         assertTrue( entryEditorBot.getAttributeValues().contains( "description: " + Characters.ALL ) );
-        assertTrue( entryEditorBot.getAttributeValues().contains( "roomNumber: 0000" ) );
+        assertTrue( entryEditorBot.getAttributeValues().contains( "roomNumber: 1388" ) );
         assertTrue( entryEditorBot.getAttributeValues().contains( "roomNumber: 1234" ) );
         assertTrue( entryEditorBot.getAttributeValues().contains( "roomNumber: 2345" ) );
         assertTrue( entryEditorBot.getAttributeValues().contains( "roomNumber: 3456" ) );
+        if ( server.getType() == LdapServerType.ApacheDS )
+        {
+            assertTrue( entryEditorBot.getAttributeValues()
+                .contains( "userCertificate: X.509v3: CN=End Entity,DC=example,DC=com" ) );
+            assertTrue( entryEditorBot.getAttributeValues().contains( "description: Deutsch" ) );
+            assertTrue( entryEditorBot.getAttributeValues().contains( "description: English" ) );
+        }
+        else
+        {
+            assertTrue( entryEditorBot.getAttributeValues()
+                .contains( "userCertificate;binary: X.509v3: CN=End Entity,DC=example,DC=com" ) );
+            assertTrue( entryEditorBot.getAttributeValues().contains( "description;lang-de: Deutsch" ) );
+            assertTrue( entryEditorBot.getAttributeValues().contains( "description;lang-en: English" ) );
+        }
+        modificationLogsViewBot.waitForText( "add: userCertificate;binary\nuserCertificate;binary:: " );
+        modificationLogsViewBot.waitForText( "add: description;lang-en\ndescription;lang-en: " );
+        modificationLogsViewBot.waitForText( "add: description;lang-de\ndescription;lang-de: " );
 
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.2" ) );
+        assertFalse( browserViewBot.existsEntry( path( USER2_DN ) ) );
 
-        browserViewBot.waitForEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.33" );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "uid=user.33" );
+        browserViewBot.waitForEntry( path( USERS_DN, "uid=user.33" ) );
+        browserViewBot.selectEntry( path( USERS_DN, "uid=user.33" ) );
         entryEditorBot.activate();
         assertTrue( entryEditorBot.getAttributeValues().contains( "uid: user.33" ) );
         assertFalse( entryEditorBot.getAttributeValues().contains( "uid: user.3" ) );
     }
 
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testImportUpdateExistingEntriesFalse( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+        Dn dn = dn( "uid=User.1", MISC111_DN );
+        server.withAdminConnection( conn -> {
+            conn.add( new DefaultEntry( conn.getSchemaManager(), dn,
+                "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: User.1" ) );
+        } );
+
+        // import the LDIF
+        String file = prepareInputFile( "ImportExportTest_User1to8.ldif" );
+        ImportWizardBot importWizardBot = browserViewBot.openImportLdifWizard();
+        importWizardBot.typeFile( file );
+        importWizardBot.setUpdateExistingEntries( false );
+        importWizardBot.setContinueOnError( false );
+        importWizardBot.clickFinishButton();
+
+        // check entry was not updated
+        browserViewBot.waitForEntry( path( dn ) );
+        browserViewBot.selectEntry( path( dn ) );
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( dn.getName() );
+        entryEditorBot.activate();
+        assertTrue( entryEditorBot.getAttributeValues().contains( "sn: X" ) );
+        assertFalse( entryEditorBot.getAttributeValues().contains( "sn: Amar" ) );
+        assertFalse( entryEditorBot.getAttributeValues().contains( "roomNumber: 1388" ) );
+
+        // check error in modifications logs view
+        modificationLogsViewBot.assertContainsError( "[LDAP result code 68 - entryAlreadyExists]",
+            "dn: " + dn.getName(), "changetype: add" );
+        // check error in LDIF log file
+        String logContent = FileUtils.readFileToString( new File( file + ".log" ), StandardCharsets.UTF_8 );
+        assertThat( logContent, containsString( "[LDAP result code 68 - entryAlreadyExists]" ) );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testImportUpdateExistingEntriesTrue( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+        Dn dn = dn( "uid=User.1", MISC111_DN );
+        server.withAdminConnection( conn -> {
+            conn.add( new DefaultEntry( conn.getSchemaManager(), dn,
+                "objectClass: inetOrgPerson", "sn: X", "cn: X", "uid: User.1" ) );
+        } );
+
+        // import the LDIF
+        String file = prepareInputFile( "ImportExportTest_User1to8.ldif" );
+        ImportWizardBot importWizardBot = browserViewBot.openImportLdifWizard();
+        importWizardBot.typeFile( file );
+        importWizardBot.setUpdateExistingEntries( true );
+        importWizardBot.setContinueOnError( false );
+        importWizardBot.clickFinishButton();
+
+        // check entry was updated
+        browserViewBot.waitForEntry( path( dn ) );
+        browserViewBot.selectEntry( path( dn ) );
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( dn.getName() );
+        entryEditorBot.activate();
+        assertFalse( entryEditorBot.getAttributeValues().contains( "sn: X" ) );
+        assertTrue( entryEditorBot.getAttributeValues().contains( "sn: Amar" ) );
+        assertTrue( entryEditorBot.getAttributeValues().contains( "roomNumber: 1388" ) );
+
+        // check error and update in modifications logs view
+        modificationLogsViewBot.assertContainsError( "[LDAP result code 68 - entryAlreadyExists]",
+            "dn: " + dn.getName(), "changetype: add" );
+        modificationLogsViewBot.assertContainsOk( "dn: " + dn.getName(), "changetype: modify" );
+        // check no error but update in LDIF log file
+        String logContent = FileUtils.readFileToString( new File( file + ".log" ), StandardCharsets.UTF_8 );
+        assertThat( logContent, not( containsString( "[LDAP result code 68 - entryAlreadyExists]" ) ) );
+    }
+
+
+    private String prepareInputFile( String inputFileName ) throws IOException
+    {
+        return ResourceUtils.prepareInputFile( inputFileName );
+    }
+
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/LdifEditorTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/LdifEditorTest.java
index d591c0d..5f69391 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/LdifEditorTest.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/LdifEditorTest.java
@@ -21,20 +21,11 @@
 package org.apache.directory.studio.test.integration.ui;
 
 
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
 import org.apache.directory.studio.test.integration.ui.bots.LdifEditorBot;
 import org.apache.directory.studio.test.integration.ui.bots.NewWizardBot;
-import org.apache.directory.studio.test.integration.ui.bots.StudioBot;
-import org.apache.directory.studio.test.integration.ui.bots.utils.Assertions;
-import org.apache.directory.studio.test.integration.ui.bots.utils.FrameworkRunnerWithScreenshotCaptureListener;
-import org.apache.directory.studio.test.integration.ui.bots.utils.StudioSystemUtils;
-import org.junit.After;
-import org.junit.Assume;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.api.Test;
 
 
 /**
@@ -42,30 +33,8 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-@RunWith(FrameworkRunnerWithScreenshotCaptureListener.class)
-public class LdifEditorTest extends AbstractLdapTestUnit
+public class LdifEditorTest extends AbstractTestBase
 {
-    private StudioBot studioBot;
-
-
-    @Before
-    public void setUp() throws Exception
-    {
-        studioBot = new StudioBot();
-        studioBot.resetLdapPerspective();
-
-        // activate search and modifications logs, they also include an LDIF editor and increment the counter
-        studioBot.getSearchLogsViewBot().getSearchLogsText();
-        studioBot.getModificationLogsViewBot().getModificationLogsText();
-    }
-
-
-    @After
-    public void tearDown() throws Exception
-    {
-        Assertions.genericTearDownAssertions();
-    }
-
 
     /**
      * Test for DIRSTUDIO-1043 (First open of LDIF editor fails)
@@ -73,22 +42,29 @@
     @Test
     public void testNewLdifEditor() throws Exception
     {
-        /*
-         * This test fails on Jenkins Windows Server, to be investigated...
-         */
-        // Assume.assumeFalse( StudioSystemUtils.IS_OS_WINDOWS_SERVER );
-
+        // Open first LDIF editor
         NewWizardBot newWizard = studioBot.openNewWizard();
         newWizard.selectLdifFile();
         assertTrue( newWizard.isFinishButtonEnabled() );
         newWizard.clickFinishButton();
 
-        // TODO: use matcher instead of hard code editor number
-        LdifEditorBot ldifEditorBot = new LdifEditorBot( "LDIF 3" );
+        LdifEditorBot ldifEditorBot = new LdifEditorBot( "LDIF" );
         ldifEditorBot.activate();
         ldifEditorBot.typeText( "dn: dc=test\nobjectClass: domain\n\n" );
         assertTrue( ldifEditorBot.isDirty() );
         ldifEditorBot.close();
+
+        // Open second LDIF editor
+        NewWizardBot newWizard2 = studioBot.openNewWizard();
+        newWizard2.selectLdifFile();
+        assertTrue( newWizard2.isFinishButtonEnabled() );
+        newWizard2.clickFinishButton();
+
+        LdifEditorBot ldifEditorBot2 = new LdifEditorBot( "LDIF" );
+        ldifEditorBot2.activate();
+        ldifEditorBot2.typeText( "dn: dc=test\nobjectClass: domain\n\n" );
+        assertTrue( ldifEditorBot2.isDirty() );
+        ldifEditorBot2.close();
     }
 
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/LogsViewsTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/LogsViewsTest.java
new file mode 100644
index 0000000..65eac80
--- /dev/null
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/LogsViewsTest.java
@@ -0,0 +1,446 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.studio.test.integration.ui;
+
+
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.GROUPS_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.TARGET_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USER1_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USER2_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USER3_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USER4_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USER5_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USERS_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.dn;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.ArrayList;
+import java.util.IntSummaryStatistics;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.directory.studio.connection.core.ConnectionCoreConstants;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource.Mode;
+import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
+import org.apache.directory.studio.test.integration.ui.bots.SelectCopyDepthDialogBot;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.params.ParameterizedTest;
+
+
+/**
+ * Tests the modification and search logs views.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class LogsViewsTest extends AbstractTestBase
+{
+
+    @AfterEach
+    public void reset() throws Exception
+    {
+        IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode( ConnectionCoreConstants.PLUGIN_ID );
+        prefs.remove( ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_COUNT );
+        prefs.remove( ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_SIZE );
+        prefs.remove( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_COUNT );
+        prefs.remove( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_SIZE );
+        prefs.remove( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_MASKED_ATTRIBUTES );
+        searchLogsViewBot.enableSearchRequestLogs( true );
+        searchLogsViewBot.enableSearchResultEntryLogs( false );
+        modificationLogsViewBot.enableModificationLogs( true );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testSearchLogsViewDefault( TestLdapServer server ) throws Exception
+    {
+        // create and open connection
+        connectionsViewBot.createTestConnection( server );
+        searchLogsViewBot.clear();
+
+        // select groups entry
+        browserViewBot.selectAndExpandEntry( path( USERS_DN ) );
+
+        // assert content (ou=users)
+        String text = searchLogsViewBot.getSearchLogsText();
+
+        assertThat( text, containsString( "#!SEARCH REQUEST " ) );
+        assertThat( text, containsString( "#!CONNECTION " + server.getLdapUrl() ) );
+        assertThat( text, containsString( "#!DATE " ) );
+        assertThat( text, containsString( "# LDAP URL     : " + server.getLdapUrl()
+            + "/ou=users,dc=example,dc=org?hasSubordinates,objectClass?one?(objectClass=*)" ) );
+        assertThat( text, containsString( "# command line : ldapsearch -H " + server.getLdapUrl() + " -x -D \""
+            + server.getAdminDn()
+            + "\" -W -b \"ou=users,dc=example,dc=org\" -s one -a always -z 1000 \"(objectClass=*)\" \"hasSubordinates\" \"objectClass\"" ) );
+        assertThat( text, containsString( "# baseObject   : ou=users,dc=example,dc=org" ) );
+        assertThat( text, containsString( "# scope        : singleLevel (1)" ) );
+        assertThat( text, containsString( "# derefAliases : derefAlways (3)" ) );
+        assertThat( text, containsString( "# sizeLimit    : 1000" ) );
+        assertThat( text, containsString( "# timeLimit    : 0" ) );
+        assertThat( text, containsString( "# typesOnly    : False" ) );
+        assertThat( text, containsString( "# filter       : (objectClass=*)" ) );
+        assertThat( text, containsString( "# attributes   : hasSubordinates objectClass" ) );
+
+        assertThat( text, not( containsString( "#!SEARCH RESULT ENTRY" ) ) );
+
+        assertThat( text, containsString( "#!SEARCH RESULT DONE " ) );
+        assertThat( text, containsString( "# numEntries : 8" ) );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testSearchLogsViewWithSearchResultEntryLogsEnabled( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+        searchLogsViewBot.clear();
+
+        // enable search result entry logs
+        searchLogsViewBot.enableSearchResultEntryLogs( true );
+
+        // select entry (ou=groups)
+        browserViewBot.selectEntry( path( GROUPS_DN ) );
+
+        // assert content
+        String text = searchLogsViewBot.getSearchLogsText();
+
+        assertThat( text, containsString( "#!SEARCH REQUEST " ) );
+        assertThat( text, containsString( "#!CONNECTION " + server.getLdapUrl() ) );
+        assertThat( text, containsString( "#!DATE " ) );
+        assertThat( text, containsString(
+            "# LDAP URL     : " + server.getLdapUrl() + "/ou=groups,dc=example,dc=org?*??(objectClass=*)" ) );
+        assertThat( text, containsString( "# command line : ldapsearch -H " + server.getLdapUrl() + " -x -D \""
+            + server.getAdminDn()
+            + "\" -W -b \"ou=groups,dc=example,dc=org\" -s base -a always \"(objectClass=*)\" \"*\"" ) );
+        assertThat( text, containsString( "# baseObject   : ou=groups,dc=example,dc=org" ) );
+        assertThat( text, containsString( "# scope        : baseObject (0)" ) );
+        assertThat( text, containsString( "# derefAliases : derefAlways (3)" ) );
+        assertThat( text, containsString( "# sizeLimit    : 0" ) );
+        assertThat( text, containsString( "# timeLimit    : 0" ) );
+        assertThat( text, containsString( "# typesOnly    : False" ) );
+        assertThat( text, containsString( "# filter       : (objectClass=*)" ) );
+        assertThat( text, containsString( "# attributes   : *" ) );
+
+        assertThat( text, containsString( "#!SEARCH RESULT ENTRY" ) );
+        assertThat( text, containsString( "dn: ou=groups,dc=example,dc=org" ) );
+        assertThat( text, containsString( "objectClass: top" ) );
+        assertThat( text, containsString( "objectClass: organizationalUnit" ) );
+        assertThat( text, containsString( "ou: groups" ) );
+
+        assertThat( text, containsString( "#!SEARCH RESULT DONE " ) );
+        assertThat( text, containsString( "# numEntries : 1" ) );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testSearchLogsViewWithSearchResultLogsDisabled( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+        searchLogsViewBot.clear();
+
+        // disable search request logs
+        searchLogsViewBot.enableSearchRequestLogs( false );
+
+        // select entry (ou=groups)
+        browserViewBot.selectEntry( path( GROUPS_DN ) );
+
+        // assert content
+        assertTrue( searchLogsViewBot.getSearchLogsText().isEmpty() );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testSearchLogsViewClear( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+
+        assertFalse( searchLogsViewBot.getSearchLogsText().isEmpty() );
+
+        searchLogsViewBot.clear();
+
+        assertTrue( searchLogsViewBot.getSearchLogsText().isEmpty() );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testSearchLogsViewLogFileRotationAndNavigation( TestLdapServer server ) throws Exception
+    {
+        IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode( ConnectionCoreConstants.PLUGIN_ID );
+        prefs.putInt( ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_COUNT, 4 );
+        prefs.putInt( ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_SIZE, 1 );
+        searchLogsViewBot.enableSearchResultEntryLogs( true );
+
+        connectionsViewBot.createTestConnection( server );
+        searchLogsViewBot.clear();
+
+        // initial state: empty log view and older/newer buttons are disabled
+        assertTrue( searchLogsViewBot.getSearchLogsText().isEmpty() );
+        assertFalse( searchLogsViewBot.isOlderButtonEnabled() );
+        assertFalse( searchLogsViewBot.isNewerButtonEnabled() );
+
+        // make some searches
+        browserViewBot.selectEntry( path( USER1_DN ) );
+        browserViewBot.selectEntry( path( USER2_DN ) );
+        browserViewBot.selectEntry( path( USER3_DN ) );
+        browserViewBot.selectEntry( path( USER4_DN ) );
+        browserViewBot.selectEntry( path( USER5_DN ) );
+
+        // assert status of newest page (1)
+        assertTrue( searchLogsViewBot.isOlderButtonEnabled() );
+        assertFalse( searchLogsViewBot.isNewerButtonEnabled() );
+        IntSummaryStatistics requestNumbers1 = getRequestStats( searchLogsViewBot.getSearchLogsText() );
+
+        // go to older page (2) and assert status
+        searchLogsViewBot.clickOlderButton();
+
+        assertTrue( searchLogsViewBot.isOlderButtonEnabled() );
+        assertTrue( searchLogsViewBot.isNewerButtonEnabled() );
+        IntSummaryStatistics requestNumbers2 = getRequestStats( searchLogsViewBot.getSearchLogsText() );
+        assertTrue( requestNumbers1.getMin() >= requestNumbers2.getMin() );
+        assertTrue( requestNumbers1.getMax() >= requestNumbers2.getMax() );
+
+        // go to older page (3) and assert status
+        searchLogsViewBot.clickOlderButton();
+
+        assertTrue( searchLogsViewBot.isOlderButtonEnabled() );
+        assertTrue( searchLogsViewBot.isNewerButtonEnabled() );
+        IntSummaryStatistics requestNumbers3 = getRequestStats( searchLogsViewBot.getSearchLogsText() );
+        assertTrue( requestNumbers2.getMin() >= requestNumbers3.getMin() );
+        assertTrue( requestNumbers2.getMax() >= requestNumbers3.getMax() );
+
+        // go to older page (4) and assert status
+        searchLogsViewBot.clickOlderButton();
+
+        assertFalse( searchLogsViewBot.isOlderButtonEnabled() );
+        assertTrue( searchLogsViewBot.isNewerButtonEnabled() );
+        IntSummaryStatistics requestNumbers4 = getRequestStats( searchLogsViewBot.getSearchLogsText() );
+        assertTrue( requestNumbers3.getMin() >= requestNumbers4.getMin() );
+        assertTrue( requestNumbers3.getMax() >= requestNumbers4.getMax() );
+
+        // go back to newest page (1) and assert status
+        searchLogsViewBot.clickNewerButton();
+        searchLogsViewBot.clickNewerButton();
+        searchLogsViewBot.clickNewerButton();
+
+        assertTrue( searchLogsViewBot.isOlderButtonEnabled() );
+        assertFalse( searchLogsViewBot.isNewerButtonEnabled() );
+
+        // reduce file count and assert extra files were deleted
+        prefs.putInt( ConnectionCoreConstants.PREFERENCE_SEARCHLOGS_FILE_COUNT, 2 );
+
+        assertTrue( searchLogsViewBot.isOlderButtonEnabled() );
+        assertFalse( searchLogsViewBot.isNewerButtonEnabled() );
+        searchLogsViewBot.clickOlderButton();
+        assertFalse( searchLogsViewBot.isOlderButtonEnabled() );
+        assertTrue( searchLogsViewBot.isNewerButtonEnabled() );
+        searchLogsViewBot.clickNewerButton();
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testSearchLogsViewLogMaskAttributes( TestLdapServer server ) throws Exception
+    {
+        IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode( ConnectionCoreConstants.PLUGIN_ID );
+        prefs.put( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_MASKED_ATTRIBUTES,
+            "userPassword,employeeNumber" );
+        searchLogsViewBot.enableSearchResultEntryLogs( true );
+
+        connectionsViewBot.createTestConnection( server );
+        searchLogsViewBot.clear();
+
+        browserViewBot.selectEntry( path( USER1_DN ) );
+
+        String text = searchLogsViewBot.getSearchLogsText();
+
+        assertThat( text, containsString( "userPassword: **********" ) );
+        assertThat( text, not( containsString( "userPassword:: " ) ) );
+        assertThat( text, containsString( "employeeNumber: **********" ) );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testModificationLogsViewModificationLogsDisabled( TestLdapServer server ) throws Exception
+    {
+        // create and open connection
+        connectionsViewBot.createTestConnection( server );
+        modificationLogsViewBot.clear();
+
+        // disable modification logs
+        modificationLogsViewBot.enableModificationLogs( false );
+
+        makeModifications();
+
+        // assert content
+        assertTrue( modificationLogsViewBot.getModificationLogsText().isEmpty() );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testModificationLogsViewDefault( TestLdapServer server ) throws Exception
+    {
+        // create and open connection
+        connectionsViewBot.createTestConnection( server );
+        modificationLogsViewBot.clear();
+
+        makeModifications();
+
+        // assert content (ou=users)
+        String text = modificationLogsViewBot.getModificationLogsText();
+
+        assertThat( text, containsString( "#!RESULT OK" ) );
+        assertThat( text, containsString( "#!CONNECTION " + server.getLdapUrl() ) );
+        assertThat( text, containsString( "#!DATE " ) );
+        modificationLogsViewBot.assertContainsOk( "dn: " + dn( USERS_DN.getRdn(), TARGET_DN ), "changetype: add" );
+        modificationLogsViewBot.assertContainsOk( "dn: " + dn( USERS_DN.getRdn(), TARGET_DN ), "changetype: delete" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testModificationLogsViewClear( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+
+        assertTrue( modificationLogsViewBot.getModificationLogsText().isEmpty() );
+
+        makeModifications();
+
+        assertFalse( modificationLogsViewBot.getModificationLogsText().isEmpty() );
+
+        modificationLogsViewBot.clear();
+
+        assertTrue( modificationLogsViewBot.getModificationLogsText().isEmpty() );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testModificationLogsViewLogFileRotationAndNavigation( TestLdapServer server ) throws Exception
+    {
+        IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode( ConnectionCoreConstants.PLUGIN_ID );
+        prefs.putInt( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_COUNT, 3 );
+        prefs.putInt( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_FILE_SIZE, 2 );
+
+        connectionsViewBot.createTestConnection( server );
+        modificationLogsViewBot.clear();
+
+        // initial state: empty log view and older/newer buttons are disabled
+        assertTrue( modificationLogsViewBot.getModificationLogsText().isEmpty() );
+        assertFalse( modificationLogsViewBot.isOlderButtonEnabled() );
+        assertFalse( modificationLogsViewBot.isNewerButtonEnabled() );
+
+        makeModifications();
+
+        // assert status of newest page (1)
+        assertTrue( modificationLogsViewBot.isOlderButtonEnabled() );
+        assertFalse( modificationLogsViewBot.isNewerButtonEnabled() );
+        IntSummaryStatistics requestNumbers1 = getRequestStats( modificationLogsViewBot.getModificationLogsText() );
+
+        // go to older page (2) and assert status
+        modificationLogsViewBot.clickOlderButton();
+
+        assertTrue( modificationLogsViewBot.isOlderButtonEnabled() );
+        assertTrue( modificationLogsViewBot.isNewerButtonEnabled() );
+        IntSummaryStatistics requestNumbers2 = getRequestStats( modificationLogsViewBot.getModificationLogsText() );
+        assertTrue( requestNumbers1.getMin() >= requestNumbers2.getMin() );
+        assertTrue( requestNumbers1.getMax() >= requestNumbers2.getMax() );
+
+        // go to older page (3) and assert status
+        modificationLogsViewBot.clickOlderButton();
+
+        assertFalse( modificationLogsViewBot.isOlderButtonEnabled() );
+        assertTrue( modificationLogsViewBot.isNewerButtonEnabled() );
+        IntSummaryStatistics requestNumbers3 = getRequestStats( modificationLogsViewBot.getModificationLogsText() );
+        assertTrue( requestNumbers2.getMin() >= requestNumbers3.getMin() );
+        assertTrue( requestNumbers2.getMax() >= requestNumbers3.getMax() );
+
+        // go back to newest page (1) and assert status
+        modificationLogsViewBot.clickNewerButton();
+        modificationLogsViewBot.clickNewerButton();
+
+        assertTrue( modificationLogsViewBot.isOlderButtonEnabled() );
+        assertFalse( modificationLogsViewBot.isNewerButtonEnabled() );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testModificationLogsViewMaskAttributes( TestLdapServer server ) throws Exception
+    {
+        IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode( ConnectionCoreConstants.PLUGIN_ID );
+        prefs.put( ConnectionCoreConstants.PREFERENCE_MODIFICATIONLOGS_MASKED_ATTRIBUTES,
+            "userPassword,employeeNumber" );
+        searchLogsViewBot.enableSearchResultEntryLogs( true );
+
+        connectionsViewBot.createTestConnection( server );
+        modificationLogsViewBot.clear();
+
+        makeModifications();
+
+        String text = modificationLogsViewBot.getModificationLogsText();
+
+        assertThat( text, containsString( "userPassword: **********" ) );
+        assertThat( text, not( containsString( "userPassword:: " ) ) );
+        assertThat( text, containsString( "employeeNumber: **********" ) );
+    }
+
+
+    private void makeModifications()
+    {
+        browserViewBot.selectEntry( path( USERS_DN ) );
+        browserViewBot.copy();
+        browserViewBot.selectEntry( path( TARGET_DN ) );
+        SelectCopyDepthDialogBot dialog = browserViewBot.pasteEntriesExpectingSelectCopyDepthDialog( 1 );
+        dialog.selectSubTree();
+        dialog.clickOkButton();
+        browserViewBot.selectEntry( path( TARGET_DN, USERS_DN.getRdn() ) );
+        browserViewBot.openDeleteDialog().clickOkButton();
+    }
+
+
+    private static IntSummaryStatistics getRequestStats( String text )
+    {
+        Pattern requestNumberPattern = Pattern.compile( "^#!.+\\((\\d+)\\) OK$", Pattern.MULTILINE );
+        Matcher matcher = requestNumberPattern.matcher( text );
+        List<String> matches = new ArrayList<>();
+        while ( matcher.find() )
+        {
+            matches.add( matcher.group( 1 ) );
+        }
+
+        return matches.stream().mapToInt( Integer::parseInt ).summaryStatistics();
+    }
+}
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/MoveEntryTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/MoveEntryTest.java
index 9057c84..d1d55ad 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/MoveEntryTest.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/MoveEntryTest.java
@@ -21,25 +21,25 @@
 package org.apache.directory.studio.test.integration.ui;
 
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.DN_WITH_LEADING_SHARP_BACKSLASH_PREFIXED;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.DN_WITH_LEADING_SHARP_HEX_PAIR_ESCAPED;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.MISC111_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.MISC_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.DN_WITH_ESCAPED_CHARACTERS_BACKSLASH_PREFIXED;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.DN_WITH_ESCAPED_CHARACTERS_HEX_PAIR_ESCAPED;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import org.apache.directory.server.annotations.CreateLdapServer;
-import org.apache.directory.server.annotations.CreateTransport;
-import org.apache.directory.server.core.annotations.ApplyLdifFiles;
-import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
-import org.apache.directory.studio.test.integration.ui.bots.BrowserViewBot;
-import org.apache.directory.studio.test.integration.ui.bots.ConnectionsViewBot;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.studio.test.integration.junit5.LdapServerType;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource;
+import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource.Mode;
 import org.apache.directory.studio.test.integration.ui.bots.MoveEntriesDialogBot;
 import org.apache.directory.studio.test.integration.ui.bots.SelectDnDialogBot;
-import org.apache.directory.studio.test.integration.ui.bots.StudioBot;
-import org.apache.directory.studio.test.integration.ui.bots.utils.Assertions;
-import org.apache.directory.studio.test.integration.ui.bots.utils.FrameworkRunnerWithScreenshotCaptureListener;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.params.ParameterizedTest;
 
 
 /**
@@ -48,72 +48,58 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-@RunWith(FrameworkRunnerWithScreenshotCaptureListener.class)
-@CreateLdapServer(transports =
-    { @CreateTransport(protocol = "LDAP") })
-@ApplyLdifFiles(clazz = MoveEntryTest.class, value = "org/apache/directory/studio/test/integration/ui/RenameEntryDialogTest.ldif")
-public class MoveEntryTest extends AbstractLdapTestUnit
+public class MoveEntryTest extends AbstractTestBase
 {
-    private StudioBot studioBot;
-    private ConnectionsViewBot connectionsViewBot;
-    private BrowserViewBot browserViewBot;
 
-
-    @Before
-    public void setUp() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testMoveUp( TestLdapServer server ) throws Exception
     {
-        studioBot = new StudioBot();
-        studioBot.resetLdapPerspective();
-        connectionsViewBot = studioBot.getConnectionView();
-        connectionsViewBot.createTestConnection( "MoveEntryTest", ldapServer.getPort() );
-        browserViewBot = studioBot.getBrowserView();
-    }
+        Dn dnToMove = MISC111_DN;
+        Dn newParentDn = MISC_DN;
 
-
-    @After
-    public void tearDown() throws Exception
-    {
-        connectionsViewBot.deleteTestConnections();
-        Assertions.genericTearDownAssertions();
-    }
-
-
-    @Test
-    public void testMoveUp() throws Exception
-    {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=Barbara Jensen+uid=bjensen" );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( dnToMove ) );
 
         MoveEntriesDialogBot moveEntryDialog = browserViewBot.openMoveEntryDialog();
         assertTrue( moveEntryDialog.isVisible() );
-        moveEntryDialog.setParentText( "ou=system" );
+        moveEntryDialog.setParentText( newParentDn.getName() );
         moveEntryDialog.clickOkButton();
 
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "cn=Barbara Jensen+uid=bjensen" ) );
-        assertFalse(
-            browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=Barbara Jensen+uid=bjensen" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "cn=Barbara Jensen+uid=bjensen" );
+        assertTrue( browserViewBot.existsEntry( path( newParentDn, dnToMove.getRdn() ) ) );
+        browserViewBot.selectEntry( path( newParentDn, dnToMove.getRdn() ) );
+        assertFalse( browserViewBot.existsEntry( path( dnToMove ) ) );
     }
 
 
-    @Test
-    public void testMoveDown() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testMoveDown( TestLdapServer server ) throws Exception
     {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=\\#123456" );
+        Dn dnToMove = DN_WITH_ESCAPED_CHARACTERS_BACKSLASH_PREFIXED;
+        Dn newParentDn = DN_WITH_LEADING_SHARP_BACKSLASH_PREFIXED;
+        if ( server.getType() == LdapServerType.OpenLdap || server.getType() == LdapServerType.Fedora389ds )
+        {
+            // OpenLDAP and 389ds escape all characters with hex digits 
+            dnToMove = DN_WITH_ESCAPED_CHARACTERS_HEX_PAIR_ESCAPED;
+            newParentDn = DN_WITH_LEADING_SHARP_HEX_PAIR_ESCAPED;
+        }
+
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( dnToMove ) );
 
         MoveEntriesDialogBot moveEntryDialog = browserViewBot.openMoveEntryDialog();
         assertTrue( moveEntryDialog.isVisible() );
         SelectDnDialogBot selectDnBot = moveEntryDialog.clickBrowseButtonExpectingSelectDnDialog();
         assertTrue( selectDnBot.isVisible() );
-        selectDnBot.selectEntry( "Root DSE", "ou=system", "ou=users", "cn=\\#\\\\\\+\\, \\\"\u00F6\u00E9\\\"" );
+        selectDnBot.selectEntry( ArrayUtils.remove( path( newParentDn ), 0 ) );
         selectDnBot.clickOkButton();
         moveEntryDialog.activate();
-        assertEquals( "cn=\\#\\\\\\+\\, \\\"\u00F6\u00E9\\\",ou=users,ou=system", moveEntryDialog.getParentText() );
+        assertEquals( newParentDn.getName(), moveEntryDialog.getParentText() );
         moveEntryDialog.clickOkButton();
 
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "cn=\\#\\\\\\+\\, \\\"\u00F6\u00E9\\\"", "cn=\\#123456" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "cn=\\#\\\\\\+\\, \\\"\u00F6\u00E9\\\"", "cn=\\#123456" );
+        assertTrue( browserViewBot.existsEntry( path( newParentDn, dnToMove.getRdn() ) ) );
+        browserViewBot.selectEntry( path( newParentDn, dnToMove.getRdn() ) );
     }
 
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/NewConnectionWizardTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/NewConnectionWizardTest.java
index 4cc19a9..24bb67d 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/NewConnectionWizardTest.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/NewConnectionWizardTest.java
@@ -21,37 +21,46 @@
 package org.apache.directory.studio.test.integration.ui;
 
 
-import static org.apache.directory.studio.test.integration.ui.Constants.LOCALHOST;
-import static org.apache.directory.studio.test.integration.ui.Constants.LOCALHOST_ADDRESS;
 import static org.hamcrest.CoreMatchers.containsString;
-import static org.hamcrest.CoreMatchers.anyOf;
+import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
+import java.lang.reflect.Method;
+import java.net.InetAddress;
 import java.net.UnknownHostException;
+import java.util.Arrays;
 
-import org.apache.directory.server.annotations.CreateLdapServer;
-import org.apache.directory.server.annotations.CreateTransport;
-import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
+import org.apache.directory.api.ldap.model.constants.SaslQoP;
+import org.apache.directory.api.ldap.model.constants.SaslSecurityStrength;
 import org.apache.directory.studio.connection.core.Connection;
 import org.apache.directory.studio.connection.core.ConnectionCorePlugin;
 import org.apache.directory.studio.connection.core.ConnectionManager;
 import org.apache.directory.studio.connection.core.ConnectionParameter.AuthenticationMethod;
-import org.apache.directory.studio.test.integration.ui.bots.ConnectionsViewBot;
+import org.apache.directory.studio.connection.core.ConnectionParameter.EncryptionMethod;
+import org.apache.directory.studio.ldapbrowser.core.BrowserConnectionManager;
+import org.apache.directory.studio.ldapbrowser.core.BrowserCorePlugin;
+import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection;
+import org.apache.directory.studio.ldapbrowser.core.model.IRootDSE;
+import org.apache.directory.studio.test.integration.junit5.LdapServerType;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource.Mode;
+import org.apache.directory.studio.test.integration.junit5.OpenLdapServer;
+import org.apache.directory.studio.test.integration.junit5.TestFixture;
+import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
+import org.apache.directory.studio.test.integration.ui.bots.CertificateTrustDialogBot;
+import org.apache.directory.studio.test.integration.ui.bots.DialogBot.CheckResponse;
+import org.apache.directory.studio.test.integration.ui.bots.ErrorDialogBot;
 import org.apache.directory.studio.test.integration.ui.bots.NewConnectionWizardBot;
-import org.apache.directory.studio.test.integration.ui.bots.StudioBot;
-import org.apache.directory.studio.test.integration.ui.bots.utils.Assertions;
-import org.apache.directory.studio.test.integration.ui.bots.utils.FrameworkRunnerWithScreenshotCaptureListener;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TestName;
-import org.junit.runner.RunWith;
+import org.apache.mina.util.AvailablePortFinder;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.params.ParameterizedTest;
 
 
 /**
@@ -60,47 +69,23 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-@RunWith(FrameworkRunnerWithScreenshotCaptureListener.class)
-@CreateLdapServer(transports =
-    { @CreateTransport(protocol = "LDAP") })
-public class NewConnectionWizardTest extends AbstractLdapTestUnit
+public class NewConnectionWizardTest extends AbstractTestBase
 {
-    @Rule
-    public TestName name = new TestName();
-
-    private StudioBot studioBot;
-    private ConnectionsViewBot connectionsViewBot;
     private NewConnectionWizardBot wizardBot;
+    private TestInfo testInfo;
 
-
-    @Before
-    public void setUp() throws Exception
+    @BeforeEach
+    public void beforeEach( TestInfo testInfo )
     {
-        studioBot = new StudioBot();
-        studioBot.resetLdapPerspective();
-        connectionsViewBot = studioBot.getConnectionView();
-
-        // open the new connection wizard
-        wizardBot = connectionsViewBot.openNewConnectionWizard();
-
-        //ErrorDialog.AUTOMATED_MODE = false;
-    }
-
-
-    @After
-    public void tearDown() throws Exception
-    {
-        connectionsViewBot.deleteTestConnections();
-        studioBot = null;
-        connectionsViewBot = null;
-        wizardBot = null;
-        Assertions.genericTearDownAssertions();
+        this.wizardBot = connectionsViewBot.openNewConnectionWizard();
+        this.testInfo = testInfo;
     }
 
 
     private String getConnectionName()
     {
-        return "NewConnectionWizardTest." + name.getMethodName();
+        return testInfo.getTestMethod().map( Method::getName ).orElse( "null" ) + " "
+            + testInfo.getDisplayName();
     }
 
 
@@ -112,6 +97,9 @@
     {
         assertTrue( wizardBot.isVisible() );
 
+        // check network parameter buttons
+        assertFalse( wizardBot.isViewCertificateButtonEnabled() );
+        assertFalse( wizardBot.isCheckNetworkParameterButtonEnabled() );
         // ensure "Next >" and "Finish" buttons are disabled
         assertFalse( wizardBot.isBackButtonEnabled() );
         assertFalse( wizardBot.isNextButtonEnabled() );
@@ -120,8 +108,11 @@
 
         // enter connection parameter
         wizardBot.typeConnectionName( getConnectionName() );
-        wizardBot.typeHost( LOCALHOST );
-        wizardBot.typePort( ldapServer.getPort() );
+        wizardBot.typeHost( "test.example.com" );
+        wizardBot.typePort( 389 );
+        // check network parameter buttons
+        assertFalse( wizardBot.isViewCertificateButtonEnabled() );
+        assertTrue( wizardBot.isCheckNetworkParameterButtonEnabled() );
         // ensure "Next >" button is enabled
         assertFalse( wizardBot.isBackButtonEnabled() );
         assertTrue( wizardBot.isNextButtonEnabled() );
@@ -130,6 +121,9 @@
 
         // clear host
         wizardBot.typeHost( "" );
+        // check network parameter buttons
+        assertFalse( wizardBot.isViewCertificateButtonEnabled() );
+        assertFalse( wizardBot.isCheckNetworkParameterButtonEnabled() );
         // ensure "Next >" is disabled
         assertFalse( wizardBot.isBackButtonEnabled() );
         assertFalse( wizardBot.isNextButtonEnabled() );
@@ -137,13 +131,49 @@
         assertTrue( wizardBot.isCancelButtonEnabled() );
 
         // enter host again
-        wizardBot.typeHost( LOCALHOST );
+        wizardBot.typeHost( "test.example.com" );
+        // check network parameter buttons
+        assertFalse( wizardBot.isViewCertificateButtonEnabled() );
+        assertTrue( wizardBot.isCheckNetworkParameterButtonEnabled() );
         // ensure "Next >" button is enabled
         assertFalse( wizardBot.isBackButtonEnabled() );
         assertTrue( wizardBot.isNextButtonEnabled() );
         assertFalse( wizardBot.isFinishButtonEnabled() );
         assertTrue( wizardBot.isCancelButtonEnabled() );
 
+        // set StartTLS encryption
+        wizardBot.selectStartTlsEncryption();
+        // check network parameter buttons
+        assertTrue( wizardBot.isViewCertificateButtonEnabled() );
+        assertTrue( wizardBot.isCheckNetworkParameterButtonEnabled() );
+        // check wizard buttons
+        assertFalse( wizardBot.isBackButtonEnabled() );
+        assertTrue( wizardBot.isNextButtonEnabled() );
+        assertFalse( wizardBot.isFinishButtonEnabled() );
+        assertTrue( wizardBot.isCancelButtonEnabled() );
+
+        // set SSL encryption
+        wizardBot.selectLdapsEncryption();
+        // check network parameter buttons
+        assertTrue( wizardBot.isViewCertificateButtonEnabled() );
+        assertTrue( wizardBot.isCheckNetworkParameterButtonEnabled() );
+        // check wizard buttons
+        assertFalse( wizardBot.isBackButtonEnabled() );
+        assertTrue( wizardBot.isNextButtonEnabled() );
+        assertFalse( wizardBot.isFinishButtonEnabled() );
+        assertTrue( wizardBot.isCancelButtonEnabled() );
+
+        // set no encryption
+        wizardBot.selectNoEncryption();
+        // check network parameter buttons
+        assertFalse( wizardBot.isViewCertificateButtonEnabled() );
+        assertTrue( wizardBot.isCheckNetworkParameterButtonEnabled() );
+        // check wizard buttons
+        assertFalse( wizardBot.isBackButtonEnabled() );
+        assertTrue( wizardBot.isNextButtonEnabled() );
+        assertFalse( wizardBot.isFinishButtonEnabled() );
+        assertTrue( wizardBot.isCancelButtonEnabled() );
+
         wizardBot.clickNextButton();
 
         // check default settings
@@ -322,26 +352,842 @@
     }
 
 
-    /**
-     * Creates a new connection using the new connection wizard.
-     */
-    @Test
-    public void testCreateConnection()
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testCreateConnectionNoEncryptionNoAuthOK( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.NONE );
+
+        wizardBot.selectNoAuthentication();
+
+        finishAndAssertConnection( server, EncryptionMethod.NONE, AuthenticationMethod.NONE, "", "" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCreateConnectionNoEncryptionNoAuthInvalidHostname( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.NONE );
+
+        wizardBot.clickBackButton();
+        String hostname = getInvalidHostName();
+        wizardBot.typeHost( hostname );
+        wizardBot.clickNextButton();
+        wizardBot.selectNoAuthentication();
+
+        finishAndAssertConnectionError( hostname );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCreateConnectionNoEncryptionSimpleAuthOK( TestLdapServer server ) throws UnknownHostException
     {
         // enter connection parameter
         wizardBot.typeConnectionName( getConnectionName() );
-        wizardBot.typeHost( LOCALHOST );
-        wizardBot.typePort( ldapServer.getPort() );
+        wizardBot.typeHost( server.getHost() );
+        wizardBot.typePort( server.getPort() );
+
+        // click "Check Network Parameter" button
+        CheckResponse checkResponse = wizardBot.clickCheckNetworkParameterButton();
+        assertFalse( checkResponse.isError(), "Expected OK" );
+        assertThat( checkResponse.getMessage(), not( containsString( "Protocol" ) ) );
+        assertThat( checkResponse.getMessage(), not( containsString( "Cipher Suite" ) ) );
+
+        // enter IPv4 address as host
+        wizardBot.typeHost( InetAddress.getByName( server.getHost() ).getHostAddress() );
+
+        // click "Check Network Parameter" button
+        checkResponse = wizardBot.clickCheckNetworkParameterButton();
+        assertFalse( checkResponse.isError(), "Expected OK" );
+        assertThat( checkResponse.getMessage(), not( containsString( "Protocol" ) ) );
+        assertThat( checkResponse.getMessage(), not( containsString( "Cipher Suite" ) ) );
+
+        // enter hostname as host again
+        wizardBot.typeHost( server.getHost() );
 
         // jump to auth page
         wizardBot.clickNextButton();
 
         // enter authentication parameters
-        wizardBot.typeUser( "uid=admin,ou=system" );
-        wizardBot.typePassword( "secret" );
+        wizardBot.typeUser( server.getAdminDn() );
+        wizardBot.typePassword( server.getAdminPassword() );
 
-        // finish dialog
+        // click "Check Network Parameter" button
+        String result = wizardBot.clickCheckAuthenticationButton();
+        assertNull( result, "Expected OK" );
+
+        finishAndAssertConnection( server, EncryptionMethod.NONE, AuthenticationMethod.SIMPLE,
+            server.getAdminDn(), server.getAdminPassword() );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testCreateConnectionNoEncryptionSimpleAuthConfidentialityRequired( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.NONE );
+
+        wizardBot.selectSimpleAuthentication();
+        wizardBot.typeUser( server.getAdminDn() );
+        wizardBot.typePassword( server.getAdminPassword() );
+
+        server.setConfidentialityRequired( true );
+
+        String result = wizardBot.clickCheckAuthenticationButton();
+        assertThat( result, containsString( "[LDAP result code 13 - confidentialityRequired]" ) );
+
+        finishAndAssertConnectionError( "[LDAP result code 13 - confidentialityRequired]" );
+
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCreateConnectionNoEncryptionSaslCramMd5OK( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.NONE );
+
+        wizardBot.selectCramMD5Authentication();
+        wizardBot.typeUser( "user.1" );
+        wizardBot.typePassword( "password" );
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
+
+        String result = wizardBot.clickCheckAuthenticationButton();
+        assertNull( result, "Expected OK" );
+
+        finishAndAssertConnection( server, EncryptionMethod.NONE, AuthenticationMethod.SASL_CRAM_MD5,
+            "user.1", "password" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCreateConnectionNoEncryptionSaslDigestMd5AuthOK( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.NONE );
+
+        wizardBot.selectDigestMD5Authentication();
+        wizardBot.typeUser( "user.1" );
+        wizardBot.typePassword( "password" );
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
+
+        String result = wizardBot.clickCheckAuthenticationButton();
+        assertNull( result, "Expected OK" );
+
+        finishAndAssertConnection( server, EncryptionMethod.NONE, AuthenticationMethod.SASL_DIGEST_MD5,
+            "user.1", "password" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(except = LdapServerType.ApacheDS, reason = "Bug in SASL filter in ApacheDS 2.0.0.M26")
+    public void testCreateConnectionNoEncryptionSaslDigestMd5AuthIntOK( TestLdapServer server )
+    {
+        // Configure OpenLDAP with ssf=1 (1 implies integrity protection only)
+        if ( server instanceof OpenLdapServer )
+        {
+            OpenLdapServer openLdapServer = ( OpenLdapServer ) server;
+            openLdapServer.setSecurityProps( 1, 0 );
+        }
+
+        setConnectionParameters( server, EncryptionMethod.NONE );
+
+        wizardBot.selectDigestMD5Authentication();
+        wizardBot.typeUser( "user.1" );
+        wizardBot.typePassword( "password" );
+        if ( server.getType() == LdapServerType.ApacheDS )
+        {
+            wizardBot.typeRealm( "EXAMPLE.ORG" );
+        }
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH_INT );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
+
+        String result = wizardBot.clickCheckAuthenticationButton();
+        assertNull( result, "Expected OK" );
+
+        finishAndAssertConnection( server, EncryptionMethod.NONE, AuthenticationMethod.SASL_DIGEST_MD5,
+            "user.1", "password" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(except = LdapServerType.ApacheDS, reason = "Bug in SASL filter in ApacheDS 2.0.0.M26.")
+    public void testCreateConnectionNoEncryptionSaslDigestMd5AuthConfOK( TestLdapServer server )
+    {
+        // Configure OpenLDAP with ssf=128 (128 allows RC4, Blowfish and other modern strong ciphers)
+        if ( server instanceof OpenLdapServer )
+        {
+            OpenLdapServer openLdapServer = ( OpenLdapServer ) server;
+            openLdapServer.setSecurityProps( 128, 0 );
+        }
+
+        setConnectionParameters( server, EncryptionMethod.NONE );
+
+        wizardBot.selectDigestMD5Authentication();
+        wizardBot.typeUser( "user.1" );
+        wizardBot.typePassword( "password" );
+        if ( server.getType() == LdapServerType.ApacheDS )
+        {
+            wizardBot.typeRealm( "EXAMPLE.ORG" );
+        }
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH_CONF );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
+
+        String result = wizardBot.clickCheckAuthenticationButton();
+        assertNull( result, "Expected OK" );
+
+        finishAndAssertConnection( server, EncryptionMethod.NONE, AuthenticationMethod.SASL_DIGEST_MD5,
+            "user.1", "password" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(except = LdapServerType.Fedora389ds, reason = "Only secure binds configured for 389ds")
+    public void testCreateConnectionNoEncryptionSaslDigestMd5ConfidentialityRequired( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.NONE );
+
+        wizardBot.selectDigestMD5Authentication();
+        wizardBot.typeUser( "user.1" );
+        wizardBot.typePassword( "password" );
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
+
+        server.setConfidentialityRequired( true );
+
+        finishAndAssertConnectionError( "[LDAP result code 13 - confidentialityRequired]" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(except = LdapServerType.ApacheDS, reason = "Missing OSGi import: org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntryModifier cannot be found by org.apache.directory.server.protocol.shared_2.0.0.AM26")
+    public void testCreateConnectionNoEncryptionSaslGssapiNativeTgtAuthOK( TestLdapServer server ) throws Exception
+    {
+        TestFixture.skipIfKdcServerIsNotAvailable();
+
+        // obtain native TGT
+        String[] cmd =
+            { "/bin/sh", "-c", "echo secret | /usr/bin/kinit hnelson" };
+        Process process = Runtime.getRuntime().exec( cmd );
+        int exitCode = process.waitFor();
+        assertEquals( 0, exitCode );
+
+        setConnectionParameters( server, EncryptionMethod.NONE );
+
+        wizardBot.selectGssApiAuthentication();
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
+        wizardBot.selectUseNativeTgt();
+        wizardBot.selectUseNativeSystemConfiguration();
+
+        String result = wizardBot.clickCheckAuthenticationButton();
+        assertNull( result, "Expected OK" );
+
+        finishAndAssertConnection( server, EncryptionMethod.NONE, AuthenticationMethod.SASL_GSSAPI,
+            "", "" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(except = LdapServerType.ApacheDS, reason = "Missing OSGi import: org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntryModifier cannot be found by org.apache.directory.server.protocol.shared_2.0.0.AM26")
+    public void testCreateConnectionNoEncryptionSaslGssapiNativeTgtAuthConfOK( TestLdapServer server ) throws Exception
+    {
+        TestFixture.skipIfKdcServerIsNotAvailable();
+
+        // Configure OpenLDAP with ssf=128 (128 allows RC4, Blowfish and other modern strong ciphers)
+        if ( server instanceof OpenLdapServer )
+        {
+            OpenLdapServer openLdapServer = ( OpenLdapServer ) server;
+            openLdapServer.setSecurityProps( 128, 0 );
+        }
+
+        // obtain native TGT
+        String[] cmd =
+            { "/bin/sh", "-c", "echo secret | /usr/bin/kinit hnelson" };
+        Process process = Runtime.getRuntime().exec( cmd );
+        int exitCode = process.waitFor();
+        assertEquals( 0, exitCode );
+
+        setConnectionParameters( server, EncryptionMethod.NONE );
+
+        wizardBot.selectGssApiAuthentication();
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH_CONF );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
+        wizardBot.selectUseNativeTgt();
+        wizardBot.selectUseNativeSystemConfiguration();
+
+        String result = wizardBot.clickCheckAuthenticationButton();
+        assertNull( result, "Expected OK" );
+
+        finishAndAssertConnection( server, EncryptionMethod.NONE, AuthenticationMethod.SASL_GSSAPI,
+            "", "" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(except = LdapServerType.ApacheDS, reason = "Missing OSGi import: org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntryModifier cannot be found by org.apache.directory.server.protocol.shared_2.0.0.AM26")
+    public void testCreateConnectionNoEncryptionSaslGssapiObtainAuthOK( TestLdapServer server )
+    {
+        TestFixture.skipIfKdcServerIsNotAvailable();
+
+        setConnectionParameters( server, EncryptionMethod.NONE );
+
+        wizardBot.selectGssApiAuthentication();
+        wizardBot.selectObtainTgtFromKdc();
+        wizardBot.typeUser( "hnelson" );
+        wizardBot.typePassword( "secret" );
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
+
+        String result = wizardBot.clickCheckAuthenticationButton();
+        assertNull( result, "Expected OK" );
+
+        finishAndAssertConnection( server, EncryptionMethod.NONE, AuthenticationMethod.SASL_GSSAPI,
+            "hnelson", "secret" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(except = LdapServerType.ApacheDS, reason = "Missing OSGi import: org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntryModifier cannot be found by org.apache.directory.server.protocol.shared_2.0.0.AM26")
+    public void testCreateConnectionNoEncryptionSaslGssapiObtainAuthConfOK( TestLdapServer server )
+    {
+        TestFixture.skipIfKdcServerIsNotAvailable();
+
+        // Configure OpenLDAP with ssf=128 (128 allows RC4, Blowfish and other modern strong ciphers)
+        if ( server instanceof OpenLdapServer )
+        {
+            OpenLdapServer openLdapServer = ( OpenLdapServer ) server;
+            openLdapServer.setSecurityProps( 128, 0 );
+        }
+
+        setConnectionParameters( server, EncryptionMethod.NONE );
+
+        wizardBot.selectGssApiAuthentication();
+        wizardBot.selectObtainTgtFromKdc();
+        wizardBot.typeUser( "hnelson" );
+        wizardBot.typePassword( "secret" );
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH_CONF );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
+
+        String result = wizardBot.clickCheckAuthenticationButton();
+        assertNull( result, "Expected OK" );
+
+        finishAndAssertConnection( server, EncryptionMethod.NONE, AuthenticationMethod.SASL_GSSAPI,
+            "hnelson", "secret" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCreateConnectionLdapsEncryptionNoAuthOK( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.LDAPS );
+
+        wizardBot.selectNoAuthentication();
+
+        finishAndAssertConnection( server, EncryptionMethod.LDAPS, AuthenticationMethod.NONE, "", "" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCreateConnectionLdapsEncryptionSimpleAuthOK( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.LDAPS );
+
+        wizardBot.typeUser( server.getAdminDn() );
+        wizardBot.typePassword( server.getAdminPassword() );
+
+        finishAndAssertConnection( server, EncryptionMethod.LDAPS, AuthenticationMethod.SIMPLE,
+            server.getAdminDn(), server.getAdminPassword() );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testCreateConnectionLdapsEncryptionSimpleAuthInvalidCredentials( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.LDAPS );
+
+        wizardBot.selectSimpleAuthentication();
+        wizardBot.typeUser( "cn=invalid" );
+        wizardBot.typePassword( "invalid" );
+
+        String result = wizardBot.clickCheckAuthenticationButton();
+        assertThat( result, containsString( "[LDAP result code 49 - invalidCredentials]" ) );
+
+        finishAndAssertConnectionError( "[LDAP result code 49 - invalidCredentials]" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCreateConnectionLdapsEncryptionSaslDigestMd5AuthOk( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.LDAPS );
+
+        wizardBot.selectDigestMD5Authentication();
+        wizardBot.typeUser( "user.1" );
+        wizardBot.typePassword( "password" );
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
+
+        finishAndAssertConnection( server, EncryptionMethod.LDAPS, AuthenticationMethod.SASL_DIGEST_MD5,
+            "user.1", "password" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(except = LdapServerType.ApacheDS, reason = "Bug in SASL filter in ApacheDS 2.0.0.M26.")
+    public void testCreateConnectionLdapsEncryptionSaslDigestMd5AuthIntOk( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.LDAPS );
+
+        wizardBot.selectDigestMD5Authentication();
+        wizardBot.typeUser( "user.1" );
+        wizardBot.typePassword( "password" );
+        if ( server.getType() == LdapServerType.ApacheDS )
+        {
+            wizardBot.typeRealm( "EXAMPLE.ORG" );
+        }
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH_INT );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
+
+        finishAndAssertConnection( server, EncryptionMethod.LDAPS, AuthenticationMethod.SASL_DIGEST_MD5,
+            "user.1", "password" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(except = LdapServerType.ApacheDS, reason = "Bug in SASL filter in ApacheDS 2.0.0.M26.")
+    public void testCreateConnectionLdapsEncryptionSaslDigestMd5AuthConfOk( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.LDAPS );
+
+        wizardBot.selectDigestMD5Authentication();
+        wizardBot.typeUser( "user.1" );
+        wizardBot.typePassword( "password" );
+        if ( server.getType() == LdapServerType.ApacheDS )
+        {
+            wizardBot.typeRealm( "EXAMPLE.ORG" );
+        }
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH_CONF );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
+
+        finishAndAssertConnection( server, EncryptionMethod.LDAPS, AuthenticationMethod.SASL_DIGEST_MD5,
+            "user.1", "password" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testCreateConnectionLdapsEncryptionSaslDigestMd5InvalidCredentials( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.LDAPS );
+
+        wizardBot.selectDigestMD5Authentication();
+        wizardBot.typeUser( "user.1" );
+        wizardBot.typePassword( "invalid" );
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
+
+        String result = wizardBot.clickCheckAuthenticationButton();
+        assertThat( result, containsString( "[LDAP result code 49 - invalidCredentials]" ) );
+
+        finishAndAssertConnectionError( "[LDAP result code 49 - invalidCredentials]" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testCreateConnectionLdapsEncryptionSaslDigestMd5InvalidRealm( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.LDAPS );
+
+        wizardBot.selectDigestMD5Authentication();
+        wizardBot.typeUser( "user.1" );
+        wizardBot.typePassword( "password" );
+        wizardBot.typeRealm( "APACHE.ORG" );
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
+
+        String result = wizardBot.clickCheckAuthenticationButton();
+        assertThat( result, containsString( "[LDAP result code" ) );
+
+        finishAndAssertConnectionError( "[LDAP result code" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCreateConnectionStartTlsEncryptionNoAuthOK( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.START_TLS );
+
+        wizardBot.selectNoAuthentication();
+
+        finishAndAssertConnection( server, EncryptionMethod.START_TLS, AuthenticationMethod.NONE, "", "" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCreateConnectionStartTlsEncryptionSimpleAuthOK( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.START_TLS );
+
+        wizardBot.typeUser( server.getAdminDn() );
+        wizardBot.typePassword( server.getAdminPassword() );
+
+        finishAndAssertConnection( server, EncryptionMethod.START_TLS, AuthenticationMethod.SIMPLE,
+            server.getAdminDn(), server.getAdminPassword() );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testCreateConnectionStartTlsEncryptionSimpleAuthInvalidCredentials( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.START_TLS );
+
+        wizardBot.selectSimpleAuthentication();
+        wizardBot.typeUser( "cn=invalid" );
+        wizardBot.typePassword( "invalid" );
+
+        String result = wizardBot.clickCheckAuthenticationButton();
+        assertThat( result, containsString( "[LDAP result code 49 - invalidCredentials]" ) );
+
+        finishAndAssertConnectionError( "[LDAP result code 49 - invalidCredentials]" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCreateConnectionStartTlsEncryptionSaslDigestMd5OK( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.START_TLS );
+
+        wizardBot.selectDigestMD5Authentication();
+        wizardBot.typeUser( "user.1" );
+        wizardBot.typePassword( "password" );
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
+
+        finishAndAssertConnection( server, EncryptionMethod.START_TLS, AuthenticationMethod.SASL_DIGEST_MD5,
+            "user.1", "password" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testCreateConnectionStartTlsEncryptionSaslDigestMd5InvalidCredentials( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.START_TLS );
+
+        wizardBot.selectDigestMD5Authentication();
+        wizardBot.typeUser( "user.1" );
+        wizardBot.typePassword( "invalid" );
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
+
+        String result = wizardBot.clickCheckAuthenticationButton();
+        assertThat( result, containsString( "[LDAP result code 49 - invalidCredentials]" ) );
+
+        finishAndAssertConnectionError( "[LDAP result code 49 - invalidCredentials]" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(except = LdapServerType.ApacheDS, reason = "Missing OSGi import: org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntryModifier cannot be found by org.apache.directory.server.protocol.shared_2.0.0.AM26")
+    public void testCreateConnectionStartTlsEncryptionSaslGssapiNativeTgtAuthOK( TestLdapServer server )
+        throws Exception
+    {
+        TestFixture.skipIfKdcServerIsNotAvailable();
+
+        // obtain native TGT
+        String[] cmd =
+            { "/bin/sh", "-c", "echo secret | /usr/bin/kinit hnelson" };
+        Process process = Runtime.getRuntime().exec( cmd );
+        int exitCode = process.waitFor();
+        assertEquals( 0, exitCode );
+
+        setConnectionParameters( server, EncryptionMethod.START_TLS );
+
+        wizardBot.selectGssApiAuthentication();
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
+        wizardBot.selectUseNativeTgt();
+        wizardBot.selectUseNativeSystemConfiguration();
+
+        String result = wizardBot.clickCheckAuthenticationButton();
+        assertNull( result, "Expected OK" );
+
+        finishAndAssertConnection( server, EncryptionMethod.START_TLS, AuthenticationMethod.SASL_GSSAPI,
+            "", "" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(except = LdapServerType.ApacheDS, reason = "Missing OSGi import: org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntryModifier cannot be found by org.apache.directory.server.protocol.shared_2.0.0.AM26")
+    public void testCreateConnectionStartTlsEncryptionSaslGssapiNativeTgtAuthConfOK( TestLdapServer server )
+        throws Exception
+    {
+        TestFixture.skipIfKdcServerIsNotAvailable();
+
+        // obtain native TGT
+        String[] cmd =
+            { "/bin/sh", "-c", "echo secret | /usr/bin/kinit hnelson" };
+        Process process = Runtime.getRuntime().exec( cmd );
+        int exitCode = process.waitFor();
+        assertEquals( 0, exitCode );
+
+        setConnectionParameters( server, EncryptionMethod.START_TLS );
+
+        wizardBot.selectGssApiAuthentication();
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH_CONF );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
+        wizardBot.selectUseNativeTgt();
+        wizardBot.selectUseNativeSystemConfiguration();
+
+        String result = wizardBot.clickCheckAuthenticationButton();
+        assertNull( result, "Expected OK" );
+
+        finishAndAssertConnection( server, EncryptionMethod.START_TLS, AuthenticationMethod.SASL_GSSAPI,
+            "", "" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(except = LdapServerType.ApacheDS, reason = "Missing OSGi import: org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntryModifier cannot be found by org.apache.directory.server.protocol.shared_2.0.0.AM26")
+    public void testCreateConnectionStartTlsEncryptionSaslGssapiNativeTgtAuthConfInvalidCredentials(
+        TestLdapServer server ) throws Exception
+    {
+        TestFixture.skipIfKdcServerIsNotAvailable();
+
+        // obtain native TGT
+        String[] cmd =
+            { "/bin/sh", "-c", "echo secret | /usr/bin/kdestroy -A" };
+        Process process = Runtime.getRuntime().exec( cmd );
+        int exitCode = process.waitFor();
+        assertEquals( 0, exitCode );
+
+        setConnectionParameters( server, EncryptionMethod.START_TLS );
+
+        wizardBot.selectGssApiAuthentication();
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH_CONF );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
+        wizardBot.selectUseNativeTgt();
+        wizardBot.selectUseNativeSystemConfiguration();
+
+        String result = wizardBot.clickCheckAuthenticationButton();
+        assertThat( result, containsString( "Unable to obtain Principal Name for authentication" ) );
+
+        finishAndAssertConnectionError( "Unable to obtain Principal Name for authentication" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(except = LdapServerType.ApacheDS, reason = "Missing OSGi import: org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntryModifier cannot be found by org.apache.directory.server.protocol.shared_2.0.0.AM26")
+    public void testCreateConnectionStartTlsEncryptionSaslGssapiObtainAuthOK( TestLdapServer server )
+    {
+        TestFixture.skipIfKdcServerIsNotAvailable();
+
+        setConnectionParameters( server, EncryptionMethod.START_TLS );
+
+        wizardBot.selectGssApiAuthentication();
+        wizardBot.selectObtainTgtFromKdc();
+        wizardBot.typeUser( "hnelson" );
+        wizardBot.typePassword( "secret" );
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
+
+        String result = wizardBot.clickCheckAuthenticationButton();
+        assertNull( result, "Expected OK" );
+
+        finishAndAssertConnection( server, EncryptionMethod.START_TLS, AuthenticationMethod.SASL_GSSAPI,
+            "hnelson", "secret" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(except = LdapServerType.ApacheDS, reason = "Missing OSGi import: org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntryModifier cannot be found by org.apache.directory.server.protocol.shared_2.0.0.AM26")
+    public void testCreateConnectionStartTlsEncryptionSaslGssapiObtainAuthConfOK( TestLdapServer server )
+    {
+        TestFixture.skipIfKdcServerIsNotAvailable();
+
+        setConnectionParameters( server, EncryptionMethod.START_TLS );
+
+        wizardBot.selectGssApiAuthentication();
+        wizardBot.selectObtainTgtFromKdc();
+        wizardBot.typeUser( "hnelson" );
+        wizardBot.typePassword( "secret" );
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH_CONF );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
+
+        String result = wizardBot.clickCheckAuthenticationButton();
+        assertNull( result, "Expected OK" );
+
+        finishAndAssertConnection( server, EncryptionMethod.START_TLS, AuthenticationMethod.SASL_GSSAPI,
+            "hnelson", "secret" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.ApacheDS, reason = "Missing OSGi import: org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntryModifier cannot be found by org.apache.directory.server.protocol.shared_2.0.0.AM26")
+    public void testCreateConnectionStartTlsEncryptionSaslGssapiObtainAuthConfInvalidCredentials(
+        TestLdapServer server )
+    {
+        TestFixture.skipIfKdcServerIsNotAvailable();
+
+        setConnectionParameters( server, EncryptionMethod.START_TLS );
+
+        wizardBot.selectGssApiAuthentication();
+        wizardBot.selectObtainTgtFromKdc();
+        wizardBot.typeUser( "hnelson" );
+        wizardBot.typePassword( "invalid" );
+        wizardBot.selectQualityOfProtection( SaslQoP.AUTH_CONF );
+        wizardBot.selectProtectionStrength( SaslSecurityStrength.HIGH );
+
+        String result = wizardBot.clickCheckAuthenticationButton();
+        assertThat( result, containsString( "Integrity check on decrypted field failed (31) - PREAUTH_FAILED" ) );
+
+        finishAndAssertConnectionError( "Integrity check on decrypted field failed (31) - PREAUTH_FAILED" );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCheckNetworkParameterButtonNoEncryptionNotOk( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.NONE );
+        wizardBot.clickBackButton();
+
+        // Invalid port
+        wizardBot.typePort( getInvalidPort() );
+        CheckResponse checkResponse = wizardBot.clickCheckNetworkParameterButton();
+        assertTrue( checkResponse.isError() );
+        assertThat( checkResponse.getMessage(), containsString( "The connection failed" ) );
+
+        // Invalid host
+        String hostname = getInvalidHostName();
+        wizardBot.typeHost( hostname );
+        checkResponse = wizardBot.clickCheckNetworkParameterButton();
+        assertTrue( checkResponse.isError() );
+        assertThat( checkResponse.getMessage(), containsString( "The connection failed" ) );
+        assertThat( "Unknown host name must occur in error message", checkResponse.getMessage(),
+            containsString( hostname ) );
+
+        wizardBot.clickCancelButton();
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCheckNetworkParameterButtonLdapsEncryptionNotOk( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.LDAPS );
+        wizardBot.clickBackButton();
+
+        // Invalid port
+        wizardBot.typePort( getInvalidPort() );
+        CheckResponse checkResponse = wizardBot.clickCheckNetworkParameterButton();
+        assertTrue( checkResponse.isError() );
+        assertThat( checkResponse.getMessage(), containsString( "The connection failed" ) );
+
+        // Non ldaps port
+        wizardBot.typePort( server.getPort() );
+        checkResponse = wizardBot.clickCheckNetworkParameterButton();
+        assertTrue( checkResponse.isError() );
+        assertThat( checkResponse.getMessage(), containsString( "The connection failed" ) );
+
+        // Invalid host
+        String hostname = getInvalidHostName();
+        wizardBot.typeHost( hostname );
+        checkResponse = wizardBot.clickCheckNetworkParameterButton();
+        assertTrue( checkResponse.isError() );
+        assertThat( checkResponse.getMessage(), containsString( "The connection failed" ) );
+        assertThat( "Unknown host name must occur in error message", checkResponse.getMessage(),
+            containsString( hostname ) );
+
+        wizardBot.clickCancelButton();
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCheckNetworkParameterButtonStartTlsEncryptionNotOk( TestLdapServer server )
+    {
+        setConnectionParameters( server, EncryptionMethod.START_TLS );
+        wizardBot.clickBackButton();
+
+        // Invalid port
+        wizardBot.typePort( getInvalidPort() );
+        CheckResponse checkResponse = wizardBot.clickCheckNetworkParameterButton();
+        assertTrue( checkResponse.isError() );
+        assertThat( checkResponse.getMessage(), containsString( "The connection failed" ) );
+
+        // Ldaps port
+        wizardBot.typePort( server.getPortSSL() );
+        assertTrue( checkResponse.isError() );
+        checkResponse = wizardBot.clickCheckNetworkParameterButton();
+        assertThat( checkResponse.getMessage(), containsString( "The connection failed" ) );
+
+        // Invalid host
+        String hostname = getInvalidHostName();
+        wizardBot.typeHost( hostname );
+        checkResponse = wizardBot.clickCheckNetworkParameterButton();
+        assertTrue( checkResponse.isError() );
+        assertThat( checkResponse.getMessage(), containsString( "The connection failed" ) );
+        assertThat( "Unknown host name must occur in error message", checkResponse.getMessage(),
+            containsString( hostname ) );
+
+        wizardBot.clickCancelButton();
+    }
+
+
+    private void setConnectionParameters( TestLdapServer server, EncryptionMethod encryptionMethod )
+    {
+        wizardBot.typeConnectionName( getConnectionName() );
+        wizardBot.typeHost( server.getHost() );
+        wizardBot.typePort( encryptionMethod == EncryptionMethod.LDAPS ? server.getPortSSL() : server.getPort() );
+
+        if ( encryptionMethod == EncryptionMethod.LDAPS )
+        {
+            wizardBot.selectLdapsEncryption();
+        }
+        if ( encryptionMethod == EncryptionMethod.START_TLS )
+        {
+            wizardBot.selectStartTlsEncryption();
+        }
+
+        if ( encryptionMethod != EncryptionMethod.NONE )
+        {
+            server.setConfidentialityRequired( true );
+            CertificateTrustDialogBot trustDialog = wizardBot
+                .clickCheckNetworkParameterButtonExpectingCertificateTrustDialog();
+            trustDialog.selectTrustPermanent();
+            trustDialog.clickOkButton();
+            bot.button( "OK" ).click();
+
+            CheckResponse checkResponse = wizardBot.clickCheckNetworkParameterButton();
+            assertFalse( checkResponse.isError() );
+            assertThat( checkResponse.getMessage(), containsString( "Protocol" ) );
+            assertThat( checkResponse.getMessage(), containsString( "Cipher Suite" ) );
+        }
+
+        wizardBot.clickNextButton();
+    }
+
+
+    private void finishAndAssertConnection( TestLdapServer server, EncryptionMethod encryptionMethod,
+        AuthenticationMethod authenticationMethod, String user, String password )
+    {
         wizardBot.clickFinishButton( true );
+
         connectionsViewBot.waitForConnection( getConnectionName() );
 
         // ensure connection was created
@@ -350,157 +1196,73 @@
         assertEquals( 1, connectionManager.getConnections().length );
         Connection connection = connectionManager.getConnections()[0];
         assertEquals( getConnectionName(), connection.getName() );
-        assertEquals( LOCALHOST, connection.getHost() );
-        assertEquals( ldapServer.getPort(), connection.getPort() );
-        assertEquals( AuthenticationMethod.SIMPLE, connection.getAuthMethod() );
-        assertEquals( "uid=admin,ou=system", connection.getBindPrincipal() );
-        assertEquals( "secret", connection.getBindPassword() );
+        assertEquals( server.getHost(), connection.getHost() );
+        assertEquals( encryptionMethod == EncryptionMethod.LDAPS ? server.getPortSSL() : server.getPort(),
+            connection.getPort() );
+        assertEquals( user, connection.getBindPrincipal() );
+        assertEquals( password, connection.getBindPassword() );
+        assertEquals( authenticationMethod, connection.getAuthMethod() );
+        assertTrue( connection.getConnectionWrapper().isConnected() );
+        if ( encryptionMethod == EncryptionMethod.NONE )
+        {
+            assertFalse( connection.getConnectionWrapper().isSecured() );
+        }
+        else
+        {
+            assertTrue( connection.getConnectionWrapper().isSecured() );
+        }
 
         // ensure connection is visible in Connections view
-        assertEquals( 1, connectionsViewBot.getConnectionCount() );
+        assertEquals( 1, connectionsViewBot.getCount() );
+
+        // assert Root DSE and schema was read
+        BrowserConnectionManager browserConnectionManager = BrowserCorePlugin.getDefault().getConnectionManager();
+        IBrowserConnection browserConnection = browserConnectionManager.getBrowserConnection( connection );
+        IRootDSE rootDSE = browserConnection.getRootDSE();
+        assertTrue( Arrays.asList( rootDSE.getAttribute( "namingContexts" ).getStringValues() )
+            .contains( TestFixture.CONTEXT_DN.getName() ) );
+        assertFalse( browserConnection.getSchema().isDefault() );
+        assertTrue( browserConnection.getSchema().getObjectClassDescriptions().size() > 50 );
+        assertTrue( browserConnection.getSchema().getAttributeTypeDescriptions().size() > 100 );
 
         // close connection
         connectionsViewBot.closeSelectedConnections();
     }
 
 
-    /**
-     * Tests the "Check Network Parameter" button.
-     */
-    @Test
-    public void testCheckNetworkParameterButtonOK() throws UnknownHostException
+    private void finishAndAssertConnectionError( String errorText )
     {
-        // enter connection parameter with host name
-        wizardBot.typeConnectionName( getConnectionName() );
-        wizardBot.typeHost( LOCALHOST );
-        wizardBot.typePort( ldapServer.getPort() );
+        ErrorDialogBot errorBot = wizardBot.clickFinishButtonExpectingError();
 
-        // click "Check Network Parameter" button
-        String result1 = wizardBot.clickCheckNetworkParameterButton();
-        assertNull( "Expected OK", result1 );
+        String errorMessage = errorBot.getErrorMessage();
+        String errorDetails = errorBot.getErrorDetails();
+        assertNotNull( errorMessage );
+        assertNotNull( errorDetails );
+        assertThat( errorDetails, containsString( errorText ) );
+        errorBot.clickOkButton();
 
-        // enter connection parameter with IPv4 address
-        wizardBot.typeHost( LOCALHOST_ADDRESS );
-        wizardBot.typePort( ldapServer.getPort() );
+        ConnectionManager connectionManager = ConnectionCorePlugin.getDefault().getConnectionManager();
+        assertNotNull( connectionManager.getConnections() );
+        assertEquals( 1, connectionManager.getConnections().length );
+        Connection connection = connectionManager.getConnections()[0];
+        assertEquals( getConnectionName(), connection.getName() );
+        assertFalse( connection.getConnectionWrapper().isConnected() );
+        assertFalse( connection.getConnectionWrapper().isSecured() );
 
-        // click "Check Network Parameter" button
-        String result2 = wizardBot.clickCheckNetworkParameterButton();
-        assertNull( "Expected OK", result2 );
-
-        //
-        // Don't know why this doesn't work with SWTBot.
-        // When testing manually it works.
-        //
-        // // enter connection parameter with IPv6 address
-        // wizardBot.typeHost( "[::1]" );
-        // wizardBot.typePort( ldapService.getPort() );
-        //
-        // // click "Check Network Parameter" button
-        // String result3 = wizardBot.clickCheckNetworkParameterButton();
-        // assertNull( "Expected OK", result3 );
-
-        wizardBot.clickCancelButton();
+        // ensure connection is visible in Connections view
+        assertEquals( 1, connectionsViewBot.getCount() );
     }
 
 
-    /**
-     * Tests the "Check Network Parameter" button.
-     */
-    @Test
-    public void testCheckNetworkParameterButtonNotOK()
+    private int getInvalidPort()
     {
-        // enter connection parameter with invalid port
-        wizardBot.typeConnectionName( getConnectionName() );
-        int port = ldapServer.getPort() + 1;
-        wizardBot.typeHost( LOCALHOST );
-        wizardBot.typePort( port );
-
-        // click "Check Network Parameter" button and get the result
-        String result1 = wizardBot.clickCheckNetworkParameterButton();
-        assertNotNull( "Expected Error", result1 );
-        // LDAP API: Connection refused
-        // JNDI: The connection failed
-        assertThat( result1,
-            anyOf( containsString( "Connection refused" ), containsString( "The connection failed" ) ) );
-
-        // enter connection parameter with invalid host name
-        String hostname = "qwertzuiop.asdfghjkl.yxcvbnm";
-        wizardBot.typeHost( hostname );
-        wizardBot.typePort( ldapServer.getPort() );
-
-        // click "Check Network Parameter" button and get the result
-        String result2 = wizardBot.clickCheckNetworkParameterButton();
-        assertNotNull( "Expected Error", result2 );
-        // LDAP API: could not be resolved
-        // JNDI: The connection failed
-        assertThat( result2,
-            anyOf( containsString( "could not be resolved" ), containsString( "The connection failed" ) ) );
-        assertThat( "Unknown host name must occur in error message", result2, containsString( hostname ) );
-
-        // disabled this test because it does not work properly
-        // as it depends from the network connection settings.
-        //        // enter connection parameter with non-routed IP address
-        //        String ipAddress = "10.11.12.13";
-        //        wizardBot.typeHost( ipAddress );
-        //        wizardBot.typePort( ldapServer.getPort() );
-        //
-        //        // click "Check Network Parameter" button and get the result
-        //        String result3 = wizardBot.clickCheckNetworkParameterButton();
-        //        assertNotNull( "Expected Error", result3 );
-        //        assertTrue( "'No route to host' or 'Network is unreachable' message must occur in error message", //
-        //            result3.contains( "No route to host" ) || result3.contains( "Network is unreachable" ) );
-        //        assertTrue( "IP address must occur in error message", result3.contains( ipAddress ) );
-
-        wizardBot.clickCancelButton();
+        return AvailablePortFinder.getNextAvailable( 1025 );
     }
 
 
-    /**
-     * Tests the "Check Network Parameter" button.
-     */
-    @Test
-    public void testCheckAuthenticationButtonOK()
+    private static String getInvalidHostName()
     {
-        // enter connection parameter
-        wizardBot.typeConnectionName( getConnectionName() );
-        wizardBot.typeHost( LOCALHOST );
-        wizardBot.typePort( ldapServer.getPort() );
-        wizardBot.clickNextButton();
-
-        // enter correct authentication parameter
-        wizardBot.typeUser( "uid=admin,ou=system" );
-        wizardBot.typePassword( "secret" );
-
-        // click "Check Network Parameter" button
-        String result = wizardBot.clickCheckAuthenticationButton();
-        assertNull( "Expected OK", result );
-
-        wizardBot.clickCancelButton();
-    }
-
-
-    /**
-     * Tests the "Check Authentication" button.
-     */
-    @Test
-    public void testCheckAuthenticationButtonNotOK()
-    {
-        // enter connection parameter
-        wizardBot.typeConnectionName( getConnectionName() );
-        wizardBot.typeHost( LOCALHOST );
-        wizardBot.typePort( ldapServer.getPort() );
-        wizardBot.clickNextButton();
-
-        // enter incorrect authentication parameter
-        wizardBot.typeUser( "uid=admin,ou=system" );
-        wizardBot.typePassword( "secret45" );
-
-        // click "Check Network Parameter" button
-        String result = wizardBot.clickCheckAuthenticationButton();
-        assertNotNull( "Expected Error", result );
-        assertTrue( "'INVALID_CREDENTIALS' message must occur in error message", result.contains( "INVALID_CREDENTIALS" ) );
-
-        wizardBot.clickCancelButton();
+        return "qwertzuiop.asdfghjkl.yxcvbnm";
     }
 
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/NewEntryWizardTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/NewEntryWizardTest.java
index 434aa59..742601e 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/NewEntryWizardTest.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/NewEntryWizardTest.java
@@ -21,40 +21,36 @@
 package org.apache.directory.studio.test.integration.ui;
 
 
-import static org.apache.directory.studio.test.integration.ui.Constants.LOCALHOST;
-import static org.apache.directory.studio.test.integration.ui.Constants.LOCALHOST_ADDRESS;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.MISC_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.REFERRAL_TO_MISC_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.TARGET_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USER1_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.dn;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
-import org.apache.directory.api.ldap.model.entry.DefaultEntry;
-import org.apache.directory.api.ldap.model.entry.DefaultModification;
-import org.apache.directory.api.ldap.model.entry.Entry;
-import org.apache.directory.api.ldap.model.entry.Modification;
-import org.apache.directory.api.ldap.model.entry.ModificationOperation;
-import org.apache.directory.api.ldap.model.name.Dn;
-import org.apache.directory.server.annotations.CreateLdapServer;
-import org.apache.directory.server.annotations.CreateTransport;
-import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
 import org.apache.directory.studio.connection.core.Connection;
 import org.apache.directory.studio.connection.core.Connection.AliasDereferencingMethod;
 import org.apache.directory.studio.connection.core.Connection.ReferralHandlingMethod;
 import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection;
-import org.apache.directory.studio.test.integration.ui.bots.BrowserViewBot;
-import org.apache.directory.studio.test.integration.ui.bots.ConnectionsViewBot;
+import org.apache.directory.studio.test.integration.junit5.LdapServerType;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource;
+import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource.Mode;
+import org.apache.directory.studio.test.integration.ui.bots.CertificateEditorDialogBot;
 import org.apache.directory.studio.test.integration.ui.bots.DnEditorDialogBot;
+import org.apache.directory.studio.test.integration.ui.bots.EditAttributeWizardBot;
+import org.apache.directory.studio.test.integration.ui.bots.EntryEditorBot;
+import org.apache.directory.studio.test.integration.ui.bots.HexEditorDialogBot;
+import org.apache.directory.studio.test.integration.ui.bots.NewAttributeWizardBot;
 import org.apache.directory.studio.test.integration.ui.bots.NewEntryWizardBot;
 import org.apache.directory.studio.test.integration.ui.bots.ReferralDialogBot;
-import org.apache.directory.studio.test.integration.ui.bots.StudioBot;
 import org.apache.directory.studio.test.integration.ui.bots.SubtreeSpecificationEditorDialogBot;
-import org.apache.directory.studio.test.integration.ui.bots.utils.Assertions;
-import org.apache.directory.studio.test.integration.ui.bots.utils.FrameworkRunnerWithScreenshotCaptureListener;
+import org.apache.directory.studio.test.integration.ui.utils.ResourceUtils;
+import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException;
 import org.eclipse.swtbot.swt.finder.utils.SWTUtils;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.params.ParameterizedTest;
 
 
 /**
@@ -63,56 +59,18 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-@RunWith(FrameworkRunnerWithScreenshotCaptureListener.class)
-@CreateLdapServer(transports =
-    { @CreateTransport(protocol = "LDAP") })
-public class NewEntryWizardTest extends AbstractLdapTestUnit
+public class NewEntryWizardTest extends AbstractTestBase
 {
-    private StudioBot studioBot;
-    private ConnectionsViewBot connectionsViewBot;
-    private BrowserViewBot browserViewBot;
-
-    private Connection connection;
-
-
-    @Before
-    public void setUp() throws Exception
-    {
-        // enable krb5kdc and nis schemas
-        ApacheDsUtils.enableSchema( ldapServer, "krb5kdc" );
-        ApacheDsUtils.enableSchema( ldapServer, "nis" );
-
-        // create referral entry
-        Entry entry = new DefaultEntry( service.getSchemaManager() );
-        entry.setDn( new Dn( "cn=referral,ou=system" ) );
-        entry.add( "objectClass", "top", "referral", "extensibleObject" );
-        entry.add( "cn", "referral" );
-        entry.add( "ref", "ldap://" + LOCALHOST + ":" + ldapServer.getPort() + "/ou=users,ou=system" );
-        service.getAdminSession().add( entry );
-
-        studioBot = new StudioBot();
-        studioBot.resetLdapPerspective();
-        connectionsViewBot = studioBot.getConnectionView();
-        connection = connectionsViewBot.createTestConnection( "NewEntryWizardTest", ldapServer.getPort() );
-        browserViewBot = studioBot.getBrowserView();
-    }
-
-
-    @After
-    public void tearDown() throws Exception
-    {
-        connectionsViewBot.deleteTestConnections();
-        Assertions.genericTearDownAssertions();
-    }
-
 
     /**
      * Test to create a single organization entry.
      */
-    @Test
-    public void testCreateOrganizationEntry()
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCreateOrganizationEntry( TestLdapServer server ) throws Exception
     {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system" );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( TARGET_DN ) );
 
         NewEntryWizardBot wizardBot = browserViewBot.openNewEntryWizard();
         assertTrue( wizardBot.isVisible() );
@@ -159,18 +117,20 @@
 
         wizardBot.clickFinishButton();
 
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "o=testCreateOrganizationEntry" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "o=testCreateOrganizationEntry" );
+        assertTrue( browserViewBot.existsEntry( path( TARGET_DN, "o=testCreateOrganizationEntry" ) ) );
+        browserViewBot.selectEntry( path( TARGET_DN, "o=testCreateOrganizationEntry" ) );
     }
 
 
     /**
      * Test to create a single person entry.
      */
-    @Test
-    public void testCreatePersonEntry()
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCreatePersonEntry( TestLdapServer server ) throws Exception
     {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system" );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( TARGET_DN ) );
 
         NewEntryWizardBot wizardBot = browserViewBot.openNewEntryWizard();
 
@@ -187,8 +147,8 @@
         wizardBot.typeValueAndFinish( "test" );
         wizardBot.clickFinishButton();
 
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "cn=testCreatePersonEntry" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "cn=testCreatePersonEntry" );
+        assertTrue( browserViewBot.existsEntry( path( TARGET_DN, "cn=testCreatePersonEntry" ) ) );
+        browserViewBot.selectEntry( path( TARGET_DN, "cn=testCreatePersonEntry" ) );
     }
 
 
@@ -198,10 +158,12 @@
      * Create entries with upper case attribute types and ensures that the
      * retrieved entries still are in upper case.
      */
-    @Test
-    public void testCreateUpperCaseOrganizationEntries()
+    @ParameterizedTest
+    @LdapServersSource(except = LdapServerType.OpenLdap, reason = "Attributes type is not case sensitive in OpenLDAP")
+    public void testCreateUpperCaseOrganizationEntries( TestLdapServer server ) throws Exception
     {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system" );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( TARGET_DN ) );
 
         NewEntryWizardBot wizardBot = browserViewBot.openNewEntryWizard();
 
@@ -217,8 +179,8 @@
 
         wizardBot.clickFinishButton();
 
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "O=testCreateOrganizationEntry" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "O=testCreateOrganizationEntry" );
+        assertTrue( browserViewBot.existsEntry( path( TARGET_DN, "O=testCreateOrganizationEntry" ) ) );
+        browserViewBot.selectEntry( path( TARGET_DN, "O=testCreateOrganizationEntry" ) );
 
         // Now create a second entry under the previously created entry
         // to ensure that the selected parent is also upper case.
@@ -233,16 +195,16 @@
 
         wizardBot.setRdnType( 1, "O" );
         wizardBot.setRdnValue( 1, "testCreateOrganizationEntry2" );
-        assertEquals( "O=testCreateOrganizationEntry2,O=testCreateOrganizationEntry,ou=system",
+        assertEquals( "O=testCreateOrganizationEntry2,O=testCreateOrganizationEntry," + TARGET_DN.getName(),
             wizardBot.getDnPreview() );
         wizardBot.clickNextButton();
 
         wizardBot.clickFinishButton();
 
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "O=testCreateOrganizationEntry",
-            "O=testCreateOrganizationEntry2" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "O=testCreateOrganizationEntry",
-            "O=testCreateOrganizationEntry2" );
+        assertTrue( browserViewBot
+            .existsEntry( path( TARGET_DN, "O=testCreateOrganizationEntry", "O=testCreateOrganizationEntry2" ) ) );
+        browserViewBot
+            .selectEntry( path( TARGET_DN, "O=testCreateOrganizationEntry", "O=testCreateOrganizationEntry2" ) );
     }
 
 
@@ -251,44 +213,45 @@
      *
      * Create entries with a slash '/' in the RDN value.
      */
-    @Test
-    public void testCreateEntryWithSlash()
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCreateEntryWithSlash( TestLdapServer server ) throws Exception
     {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system" );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( TARGET_DN ) );
 
         NewEntryWizardBot wizardBot = browserViewBot.openNewEntryWizard();
 
         wizardBot.selectCreateEntryFromScratch();
         wizardBot.clickNextButton();
 
-        wizardBot.addObjectClasses( "krb5Principal", "person" );
+        wizardBot.addObjectClasses( "person" );
         wizardBot.clickNextButton();
 
-        wizardBot.setRdnType( 1, "krb5PrincipalName" );
+        wizardBot.setRdnType( 1, "cn" );
         wizardBot.setRdnValue( 1, "kadmin/changepw@DOMAIN" );
         wizardBot.clickNextButton();
 
-        wizardBot.editValue( "cn", "" );
-        wizardBot.typeValueAndFinish( "test" );
         wizardBot.editValue( "sn", "" );
         wizardBot.typeValueAndFinish( "test" );
         wizardBot.clickFinishButton();
 
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system",
-            "krb5PrincipalName=kadmin/changepw@DOMAIN" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "krb5PrincipalName=kadmin/changepw@DOMAIN" );
+        assertTrue( browserViewBot.existsEntry( path( TARGET_DN, "cn=kadmin/changepw@DOMAIN" ) ) );
+        browserViewBot.selectEntry( path( TARGET_DN, "cn=kadmin/changepw@DOMAIN" ) );
     }
 
 
-    @Test
-    public void testCreateAliasEntry()
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCreateAliasEntry( TestLdapServer server ) throws Exception
     {
         // disable alias dereferencing
+        Connection connection = connectionsViewBot.createTestConnection( server );
         connection.getConnectionParameter().setExtendedIntProperty(
             IBrowserConnection.CONNECTION_PARAMETER_ALIASES_DEREFERENCING_METHOD,
             AliasDereferencingMethod.NEVER.ordinal() );
 
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system" );
+        browserViewBot.selectEntry( path( TARGET_DN ) );
 
         NewEntryWizardBot wizardBot = browserViewBot.openNewEntryWizard();
 
@@ -299,32 +262,30 @@
         wizardBot.clickNextButton();
 
         wizardBot.setRdnType( 1, "cn" );
-        wizardBot.setRdnValue( 1, "alias2" );
+        wizardBot.setRdnValue( 1, "alias" );
         wizardBot.clickNextButton();
 
         DnEditorDialogBot dnEditorBot = new DnEditorDialogBot();
-        dnEditorBot.setDnText( "ou=system" );
+        dnEditorBot.setWaitAfterClickOkButton( false );
+        dnEditorBot.setDnText( USER1_DN.getName() );
         dnEditorBot.clickOkButton();
         wizardBot.clickFinishButton();
 
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "cn=alias2" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "cn=alias2" );
+        assertTrue( browserViewBot.existsEntry( path( TARGET_DN, "cn=alias" ) ) );
+        browserViewBot.selectEntry( path( TARGET_DN, "cn=alias" ) );
     }
 
 
-    @Test
-    public void testCreateSubEntry() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.ApacheDS, reason = "ApacheDS specific test")
+    public void testCreateSubEntry( TestLdapServer server ) throws Exception
     {
         // set Subentries control
+        Connection connection = connectionsViewBot.createTestConnection( server );
         connection.getConnectionParameter().setExtendedBoolProperty(
             IBrowserConnection.CONNECTION_PARAMETER_FETCH_SUBENTRIES, true );
 
-        // create accessControlSpecificArea
-        Modification modification = new DefaultModification( ModificationOperation.ADD_ATTRIBUTE,
-            new DefaultAttribute( "administrativeRole", "accessControlSpecificArea" ) );
-        service.getAdminSession().modify( new Dn( "ou=system" ), modification );
-
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system" );
+        browserViewBot.selectEntry( path( TARGET_DN ) );
 
         NewEntryWizardBot wizardBot = browserViewBot.openNewEntryWizard();
 
@@ -335,29 +296,32 @@
         wizardBot.clickNextButton();
 
         wizardBot.setRdnType( 1, "cn" );
-        wizardBot.setRdnValue( 1, "subentry2" );
+        wizardBot.setRdnValue( 1, "subentry" );
         wizardBot.clickNextButton();
 
         SubtreeSpecificationEditorDialogBot subtreeEditorBot = new SubtreeSpecificationEditorDialogBot();
+        subtreeEditorBot.setWaitAfterClickOkButton( false );
         subtreeEditorBot.clickOkButton();
         wizardBot.clickFinishButton();
 
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "cn=subentry2" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "cn=subentry2" );
+        assertTrue( browserViewBot.existsEntry( path( TARGET_DN, "cn=subentry" ) ) );
+        browserViewBot.selectEntry( path( TARGET_DN, "cn=subentry" ) );
     }
 
 
-    @Test
-    public void testCreateReferralEntry()
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testCreateReferralEntry( TestLdapServer server ) throws Exception
     {
         // set ManageDsaIT control
+        Connection connection = connectionsViewBot.createTestConnection( server );
         connection.getConnectionParameter().setExtendedIntProperty(
             IBrowserConnection.CONNECTION_PARAMETER_REFERRALS_HANDLING_METHOD,
             ReferralHandlingMethod.IGNORE.ordinal() );
         connection.getConnectionParameter().setExtendedBoolProperty(
             IBrowserConnection.CONNECTION_PARAMETER_MANAGE_DSA_IT, true );
 
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system" );
+        browserViewBot.selectEntry( path( TARGET_DN ) );
 
         NewEntryWizardBot wizardBot = browserViewBot.openNewEntryWizard();
 
@@ -368,15 +332,26 @@
         wizardBot.clickNextButton();
 
         wizardBot.setRdnType( 1, "cn" );
-        wizardBot.setRdnValue( 1, "referral2" );
+        wizardBot.setRdnValue( 1, "referral" );
         wizardBot.clickNextButton();
 
+        // 389ds doesn't define ref as mandatory attribute
+        if ( server.getType() == LdapServerType.Fedora389ds )
+        {
+            NewAttributeWizardBot newAttributeWizardBot = wizardBot.openNewAttributeWizard();
+            assertTrue( newAttributeWizardBot.isVisible() );
+            newAttributeWizardBot.typeAttributeType( "ref" );
+            newAttributeWizardBot.clickFinishButton();
+            wizardBot.cancelEditValue();
+            wizardBot.activate();
+        }
         wizardBot.editValue( "ref", "" );
-        wizardBot.typeValueAndFinish( "ldap://" + LOCALHOST + ":" + ldapServer.getPort() + "/ou=users,ou=system" );
+
+        wizardBot.typeValueAndFinish( server.getLdapUrl() + "/" + USER1_DN.getName() );
         wizardBot.clickFinishButton();
 
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "cn=referral2" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "cn=referral2" );
+        assertTrue( browserViewBot.existsEntry( path( TARGET_DN, "cn=referral" ) ) );
+        browserViewBot.selectEntry( path( TARGET_DN, "cn=referral" ) );
     }
 
 
@@ -387,17 +362,19 @@
      * The connection selection dialog pops up and we cancel the selection.
      * No error should occur and the wizard is not closed.
      */
-    @Test
-    public void testCreateEntryBelowReferralObjectCancel()
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCreateEntryBelowReferralObjectCancel( TestLdapServer server ) throws Exception
     {
         // set ManageDsaIT control
+        Connection connection = connectionsViewBot.createTestConnection( server );
         connection.getConnectionParameter().setExtendedIntProperty(
             IBrowserConnection.CONNECTION_PARAMETER_REFERRALS_HANDLING_METHOD,
             ReferralHandlingMethod.IGNORE.ordinal() );
         connection.getConnectionParameter().setExtendedBoolProperty(
             IBrowserConnection.CONNECTION_PARAMETER_MANAGE_DSA_IT, true );
 
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "cn=referral" );
+        browserViewBot.selectEntry( path( REFERRAL_TO_MISC_DN ) );
 
         NewEntryWizardBot wizardBot = browserViewBot.openNewEntryWizard();
 
@@ -423,7 +400,7 @@
 
         wizardBot.clickCancelButton();
 
-        assertFalse( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "o=orgBelowReferral" ) );
+        assertFalse( browserViewBot.existsEntry( path( MISC_DN, "o=orgBelowReferral" ) ) );
     }
 
 
@@ -434,17 +411,19 @@
      * The connection selection dialog pops up and we select a connection.
      * The entry is created under the target entry.
      */
-    @Test
-    public void testCreateEntryBelowReferralObjectFollow()
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCreateEntryBelowReferralObjectFollow( TestLdapServer server ) throws Exception
     {
         // set ManageDsaIT control
+        Connection connection = connectionsViewBot.createTestConnection( server );
         connection.getConnectionParameter().setExtendedIntProperty(
             IBrowserConnection.CONNECTION_PARAMETER_REFERRALS_HANDLING_METHOD,
             ReferralHandlingMethod.IGNORE.ordinal() );
         connection.getConnectionParameter().setExtendedBoolProperty(
             IBrowserConnection.CONNECTION_PARAMETER_MANAGE_DSA_IT, true );
 
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "cn=referral" );
+        browserViewBot.selectEntry( path( REFERRAL_TO_MISC_DN ) );
 
         NewEntryWizardBot wizardBot = browserViewBot.openNewEntryWizard();
 
@@ -466,8 +445,8 @@
         referralDialogBot.clickOkButton();
 
         // check entry was created under referral target entry
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "o=orgBelowReferral" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "o=orgBelowReferral" );
+        assertTrue( browserViewBot.existsEntry( path( MISC_DN, "o=orgBelowReferral" ) ) );
+        browserViewBot.selectEntry( path( MISC_DN, "o=orgBelowReferral" ) );
     }
 
 
@@ -476,10 +455,12 @@
      *
      * Create an entry with sharp in DN: cn=\#123456.
      */
-    @Test
-    public void testCreateEntryWithSharp()
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testCreateEntryWithSharp( TestLdapServer server ) throws Exception
     {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system" );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( TARGET_DN ) );
 
         NewEntryWizardBot wizardBot = browserViewBot.openNewEntryWizard();
 
@@ -496,8 +477,16 @@
         wizardBot.typeValueAndFinish( "#123456" );
         wizardBot.clickFinishButton();
 
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "cn=\\#123456" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "cn=\\#123456" );
+        if ( server.getType() == LdapServerType.ApacheDS )
+        {
+            assertTrue( browserViewBot.existsEntry( path( TARGET_DN, "cn=\\#123456" ) ) );
+            browserViewBot.selectEntry( path( TARGET_DN, "cn=\\#123456" ) );
+        }
+        else
+        {
+            assertTrue( browserViewBot.existsEntry( path( TARGET_DN, "cn=\\23123456" ) ) );
+            browserViewBot.selectEntry( path( TARGET_DN, "cn=\\23123456" ) );
+        }
     }
 
 
@@ -506,10 +495,12 @@
      *
      * Create an entry with multi-valued RDN and numeric OID (IP address) in RDN value.
      */
-    @Test
-    public void testCreateMvRdnWithNumericOid()
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCreateMvRdnWithNumericOid( TestLdapServer server ) throws Exception
     {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system" );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( TARGET_DN ) );
 
         NewEntryWizardBot wizardBot = browserViewBot.openNewEntryWizard();
 
@@ -524,14 +515,13 @@
         wizardBot.setRdnType( 1, "cn" );
         wizardBot.setRdnValue( 1, "loopback" );
         wizardBot.setRdnType( 2, "ipHostNumber" );
-        wizardBot.setRdnValue( 2, LOCALHOST_ADDRESS );
+        wizardBot.setRdnValue( 2, "127.0.0.1" );
         wizardBot.clickNextButton();
 
         wizardBot.clickFinishButton();
 
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system",
-            "cn=loopback+ipHostNumber=" + LOCALHOST_ADDRESS ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "cn=loopback+ipHostNumber=" + LOCALHOST_ADDRESS );
+        assertTrue( browserViewBot.existsEntry( path( TARGET_DN, "cn=loopback+ipHostNumber=127.0.0.1" ) ) );
+        browserViewBot.selectEntry( path( TARGET_DN, "cn=loopback+ipHostNumber=127.0.0.1" ) );
     }
 
 
@@ -540,10 +530,12 @@
      *
      * Create and browse entry with multi-valued RDN with same attribute type.
      */
-    @Test
-    public void testCreateMvRdnWithSameAttribute()
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.OpenLdap, reason = "Multi-valued RDN with same attribute is not supported by OpenLDAP")
+    public void testCreateMvRdnWithSameAttribute( TestLdapServer server ) throws Exception
     {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system" );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( TARGET_DN ) );
 
         NewEntryWizardBot wizardBot = browserViewBot.openNewEntryWizard();
 
@@ -565,9 +557,137 @@
 
         wizardBot.clickFinishButton();
 
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system",
-            "l=eu+l=de+l=Berlin" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "l=eu+l=de+l=Berlin" );
+        if ( server.getType() == LdapServerType.Fedora389ds )
+        {
+            // 389ds sorts the RDN
+            assertTrue( browserViewBot.existsEntry( path( TARGET_DN, "l=Berlin+l=de+l=eu" ) ) );
+            browserViewBot.selectEntry( path( TARGET_DN, "l=Berlin+l=de+l=eu" ) );
+        }
+        else
+        {
+            assertTrue( browserViewBot.existsEntry( path( TARGET_DN, "l=eu+l=de+l=Berlin" ) ) );
+            browserViewBot.selectEntry( path( TARGET_DN, "l=eu+l=de+l=Berlin" ) );
+        }
     }
 
+
+    /**
+     * DIRSTUDIO-1267: Test creation of new entry with binary option and language tags.
+     */
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCreateEntryWithBinaryOptionAndLanguageTags( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+        String certFile = ResourceUtils.prepareInputFile( "rfc5280_cert1.cer" );
+        String crlFile = ResourceUtils.prepareInputFile( "rfc5280_crl.crl" );
+
+        browserViewBot.selectEntry( path( TARGET_DN ) );
+
+        NewEntryWizardBot wizardBot = browserViewBot.openNewEntryWizard();
+
+        wizardBot.selectCreateEntryFromScratch();
+        wizardBot.clickNextButton();
+        wizardBot.addObjectClasses( "organizationalRole" );
+        wizardBot.addObjectClasses( "certificationAuthority" );
+        wizardBot.clickNextButton();
+
+        wizardBot.setRdnType( 1, "cn" );
+        wizardBot.setRdnValue( 1, "asdf" );
+        wizardBot.clickNextButton();
+
+        // by default the hex or certificate editor is opened, close it
+        try
+        {
+            new HexEditorDialogBot().clickCancelButton();
+        }
+        catch ( WidgetNotFoundException e )
+        {
+        }
+        try
+        {
+            new CertificateEditorDialogBot().clickCancelButton();
+        }
+        catch ( WidgetNotFoundException e )
+        {
+        }
+
+        wizardBot.activate();
+        NewAttributeWizardBot newAttributeWizardBot = wizardBot.openNewAttributeWizard();
+        assertTrue( newAttributeWizardBot.isVisible() );
+        newAttributeWizardBot.typeAttributeType( "description" );
+        newAttributeWizardBot.clickNextButton();
+        newAttributeWizardBot.setLanguageTag( "en", "us" );
+        newAttributeWizardBot.clickFinishButton();
+        wizardBot.cancelEditValue();
+        wizardBot.activate();
+        wizardBot.editValue( "description;lang-en-us", null );
+        SWTUtils.sleep( 1000 );
+        wizardBot.typeValueAndFinish( "English description" );
+
+        wizardBot.activate();
+        EditAttributeWizardBot editAttributeBot = wizardBot.editAttribute( "cACertificate", null );
+        editAttributeBot.clickNextButton();
+        editAttributeBot.selectBinaryOption();
+        editAttributeBot.clickFinishButton();
+
+        wizardBot.activate();
+        wizardBot.editValue( "cACertificate;binary", null );
+        CertificateEditorDialogBot certEditorBot = new CertificateEditorDialogBot();
+        certEditorBot.setWaitAfterClickOkButton( false );
+        assertTrue( certEditorBot.isVisible() );
+        certEditorBot.typeFile( certFile );
+        certEditorBot.clickOkButton();
+
+        wizardBot.activate();
+        editAttributeBot = wizardBot.editAttribute( "certificateRevocationList", null );
+        editAttributeBot.clickNextButton();
+        editAttributeBot.selectBinaryOption();
+        editAttributeBot.clickFinishButton();
+
+        wizardBot.activate();
+        wizardBot.editValue( "certificateRevocationList;binary", null );
+        HexEditorDialogBot hexEditorBot = new HexEditorDialogBot();
+        hexEditorBot.setWaitAfterClickOkButton( false );
+        assertTrue( hexEditorBot.isVisible() );
+        hexEditorBot.typeFile( crlFile );
+        hexEditorBot.clickOkButton();
+
+        wizardBot.activate();
+        editAttributeBot = wizardBot.editAttribute( "authorityRevocationList", null );
+        editAttributeBot.clickNextButton();
+        editAttributeBot.selectBinaryOption();
+        editAttributeBot.clickFinishButton();
+
+        wizardBot.activate();
+        wizardBot.editValue( "authorityRevocationList;binary", null );
+        assertTrue( hexEditorBot.isVisible() );
+        hexEditorBot.typeFile( crlFile );
+        hexEditorBot.clickOkButton();
+
+        wizardBot.activate();
+        wizardBot.clickFinishButton();
+
+        assertTrue( browserViewBot.existsEntry( path( TARGET_DN, "cn=asdf" ) ) );
+        browserViewBot.selectEntry( path( TARGET_DN, "cn=asdf" ) );
+
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( dn( "cn=asdf", TARGET_DN ).getName() );
+        entryEditorBot.activate();
+
+        modificationLogsViewBot.waitForText( "cACertificate;binary:: MIICPjCCAaeg" );
+        assertTrue( entryEditorBot.getAttributeValues()
+            .contains( "cACertificate;binary: X.509v3: CN=Example CA,DC=example,DC=com" ) );
+
+        modificationLogsViewBot.waitForText( "certificateRevocationList;binary:: MIIBYDCBygIB" );
+        assertTrue( entryEditorBot.getAttributeValues()
+            .contains( "certificateRevocationList;binary: Binary Data (356 Bytes)" ) );
+
+        modificationLogsViewBot.waitForText( "authorityRevocationList;binary:: MIIBYDCBygIB" );
+        assertTrue( entryEditorBot.getAttributeValues()
+            .contains( "authorityRevocationList;binary: Binary Data (356 Bytes)" ) );
+
+        modificationLogsViewBot.waitForText( "description;lang-en-us: English description" );
+        assertTrue( entryEditorBot.getAttributeValues()
+            .contains( "description;lang-en-us: English description" ) );
+    }
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/PerformanceTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/PerformanceTest.java
new file mode 100644
index 0000000..240282b
--- /dev/null
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/PerformanceTest.java
@@ -0,0 +1,108 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.studio.test.integration.ui;
+
+
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.GROUPS_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.dn;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.directory.api.ldap.model.entry.DefaultEntry;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.studio.ldapbrowser.common.BrowserCommonActivator;
+import org.apache.directory.studio.ldapbrowser.common.BrowserCommonConstants;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource;
+import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
+import org.apache.directory.studio.test.integration.ui.bots.EntryEditorBot;
+import org.junit.jupiter.params.ParameterizedTest;
+
+
+/**
+ * Tests performance.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class PerformanceTest extends AbstractTestBase
+{
+
+    /**
+     * Test for DIRSTUDIO-1119 (Group with over 1000 members crashes)
+     */
+    @ParameterizedTest
+    @LdapServersSource
+    public void testEditLargeGroup( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+        BrowserCommonActivator.getDefault()
+            .getPluginPreferences().setValue( BrowserCommonConstants.PREFERENCE_ENTRYEDITOR_ENABLE_FOLDING, false );
+
+        Dn dn = dn( "cn=Large Group", GROUPS_DN );
+        int n = 5000;
+        String memberAt = "member";
+        List<String> memberDns = new ArrayList<>( n );
+
+        server.withAdminConnection( conn -> {
+            Entry entry = new DefaultEntry( conn.getSchemaManager() );
+            entry.setDn( dn );
+            entry.add( "objectClass", "top", "groupOfNames" );
+            entry.add( "cn", "Large Group" );
+            for ( int i = 0; i < n; i++ )
+            {
+                String memberDn = "cn=user." + String.format( "%04d", i );
+                memberDns.add( memberDn );
+                entry.add( memberAt, memberDn );
+            }
+            conn.add( entry );
+        } );
+
+        String first = memberDns.get( 0 );
+        String second = memberDns.get( 1 );
+        String middle = memberDns.get( n / 2 );
+        String secondToLast = memberDns.get( n - 2 );
+        String last = memberDns.get( n - 1 );
+
+        browserViewBot.selectEntry( path( dn ) );
+
+        EntryEditorBot entryEditorBot = studioBot.getEntryEditorBot( dn.getName() );
+        entryEditorBot.activate();
+
+        // edit some values
+        entryEditorBot.editValueExpectingDnEditor( memberAt, first ).clickCancelButton();
+        entryEditorBot.editValueExpectingDnEditor( memberAt, last ).clickCancelButton();
+        entryEditorBot.editValueExpectingDnEditor( memberAt, middle ).clickCancelButton();
+        entryEditorBot.editValueExpectingDnEditor( memberAt, second ).clickCancelButton();
+        entryEditorBot.editValueExpectingDnEditor( memberAt, secondToLast ).clickCancelButton();
+
+        // delete some values
+        entryEditorBot.deleteValue( memberAt, second );
+        entryEditorBot.deleteValue( memberAt, secondToLast );
+
+        // edit some value after deletion
+        entryEditorBot.editValueExpectingDnEditor( memberAt, first ).clickCancelButton();
+        entryEditorBot.editValueExpectingDnEditor( memberAt, last ).clickCancelButton();
+        entryEditorBot.editValueExpectingDnEditor( memberAt, middle ).clickCancelButton();
+    }
+
+}
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/PreferencesTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/PreferencesTest.java
index 44a3346..046feba 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/PreferencesTest.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/PreferencesTest.java
@@ -21,44 +21,38 @@
 package org.apache.directory.studio.test.integration.ui;
 
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.File;
 import java.net.URL;
 import java.nio.charset.StandardCharsets;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
 import java.security.cert.X509Certificate;
+import java.util.Date;
 import java.util.List;
 
+import org.apache.directory.api.ldap.model.entry.DefaultEntry;
+import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.util.FileUtils;
-import org.apache.directory.server.annotations.CreateLdapServer;
-import org.apache.directory.server.annotations.CreateTransport;
-import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
-import org.apache.directory.server.core.security.CertificateUtil;
+import org.apache.directory.server.core.security.TlsKeyGenerator;
 import org.apache.directory.studio.connection.core.Connection;
 import org.apache.directory.studio.connection.core.ConnectionCorePlugin;
 import org.apache.directory.studio.connection.core.PasswordsKeyStoreManager;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource;
+import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
 import org.apache.directory.studio.test.integration.ui.bots.CertificateValidationPreferencePageBot;
 import org.apache.directory.studio.test.integration.ui.bots.CertificateViewerDialogBot;
-import org.apache.directory.studio.test.integration.ui.bots.ConnectionsViewBot;
 import org.apache.directory.studio.test.integration.ui.bots.KeepConnectionsPasswordsDialogBot;
+import org.apache.directory.studio.test.integration.ui.bots.ModificationLogsViewPreferencePageBot;
 import org.apache.directory.studio.test.integration.ui.bots.PasswordsKeystorePreferencePageBot;
 import org.apache.directory.studio.test.integration.ui.bots.PreferencesBot;
+import org.apache.directory.studio.test.integration.ui.bots.SearchLogsViewPreferencePageBot;
 import org.apache.directory.studio.test.integration.ui.bots.SetupMasterPasswordDialogBot;
-import org.apache.directory.studio.test.integration.ui.bots.StudioBot;
 import org.apache.directory.studio.test.integration.ui.bots.VerifyMasterPasswordDialogBot;
-import org.apache.directory.studio.test.integration.ui.bots.utils.Assertions;
-import org.apache.directory.studio.test.integration.ui.bots.utils.FrameworkRunnerWithScreenshotCaptureListener;
 import org.eclipse.core.runtime.Platform;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import sun.security.x509.X500Name;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
 
 
 /**
@@ -67,45 +61,17 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-@RunWith(FrameworkRunnerWithScreenshotCaptureListener.class)
-@CreateLdapServer(transports =
-    { @CreateTransport(protocol = "LDAP") })
-public class PreferencesTest extends AbstractLdapTestUnit
+public class PreferencesTest extends AbstractTestBase
 {
-    private StudioBot studioBot;
-    private ConnectionsViewBot connectionsViewBot;
-
-
-    @Before
-    public void setUp() throws Exception
-    {
-        studioBot = new StudioBot();
-        studioBot.resetLdapPerspective();
-        connectionsViewBot = studioBot.getConnectionView();
-    }
-
-
-    @After
-    public void tearDown() throws Exception
-    {
-        connectionsViewBot.deleteTestConnections();
-        Assertions.genericTearDownAssertions();
-    }
-
 
     /**
      * Test for DIRSTUDIO-580
      * (Setting "Validate certificates for secure LDAP connections" is not saved).
-     *
-     * @throws Exception
      */
     @Test
     public void testCertificatValidationSettingsSaved() throws Exception
     {
-        URL url = Platform.getInstanceLocation().getURL();
-        File file = new File( url.getFile()
-            + ".metadata/.plugins/org.eclipse.core.runtime/.settings/org.apache.directory.studio.connection.core.prefs" );
-        assertFalse( file.exists() );
+        File file = getConnectionCorePreferencesFile();
 
         // open preferences dialog
         PreferencesBot preferencesBot = studioBot.openPreferences();
@@ -134,9 +100,26 @@
         pageBot.clickRestoreDefaultsButton();
         assertTrue( pageBot.isValidateCertificatesSelected() );
 
-        // click OK, this should remove the property file as only defaults are set
+        // click OK, this should remove the property or the whole file
         preferencesBot.clickOkButton();
-        assertFalse( file.exists() );
+        if ( file.exists() )
+        {
+            lines = FileUtils.readLines( file, StandardCharsets.UTF_8 );
+            assertFalse( lines.contains( "validateCertificates=false" ) );
+        }
+        else
+        {
+            assertFalse( file.exists() );
+        }
+    }
+
+
+    private File getConnectionCorePreferencesFile()
+    {
+        URL url = Platform.getInstanceLocation().getURL();
+        File file = new File( url.getFile()
+            + ".metadata/.plugins/org.eclipse.core.runtime/.settings/org.apache.directory.studio.connection.core.prefs" );
+        return file;
     }
 
 
@@ -157,11 +140,15 @@
         preferencesBot.clickCancelButton();
 
         // add a certificate (not possible via native file dialog)
-        X500Name issuer = new X500Name( "apacheds", "directory", "apache", "US" );
-        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance( "EC" );
-        keyPairGenerator.initialize( 256 );
-        KeyPair keyPair = keyPairGenerator.generateKeyPair();
-        X509Certificate certificate = CertificateUtil.generateSelfSignedCertificate( issuer, keyPair, 365, "SHA256WithECDSA" );
+        Entry entry = new DefaultEntry();
+        String issuerDn = "cn=apacheds,ou=directory,o=apache,c=US";
+        Date startDate = new Date();
+        Date expiryDate = new Date( System.currentTimeMillis() + TlsKeyGenerator.YEAR_MILLIS );
+        String keyAlgo = "RSA";
+        int keySize = 1024;
+        CertificateValidationTest.addKeyPair( entry, issuerDn, issuerDn, startDate, expiryDate, keyAlgo, keySize,
+            null );
+        X509Certificate certificate = TlsKeyGenerator.getCertificate( entry );
         ConnectionCorePlugin.getDefault().getPermanentTrustStoreManager().addCertificate( certificate );
 
         // verify there is one certificate now
@@ -197,10 +184,11 @@
      * Test for DIRSTUDIO-1179
      * (java.io.IOException: Invalid secret key format after Java update).
      */
-    @Test
-    public void testConnectionPasswordsKeystore() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testConnectionPasswordsKeystore( TestLdapServer server ) throws Exception
     {
-        Connection connection = connectionsViewBot.createTestConnection( "BrowserTest", ldapServer.getPort() );
+        Connection connection = connectionsViewBot.createTestConnection( server );
         connectionsViewBot.closeSelectedConnections();
 
         // the global password keystore manager
@@ -233,7 +221,7 @@
         assertTrue( passwordsKeyStoreManager.isLoaded() );
 
         // verify connection can be opened because keystore is already loaded
-        connectionsViewBot.selectConnection( connection.getName() );
+        connectionsViewBot.select( connection.getName() );
         connectionsViewBot.openSelectedConnection();
         connectionsViewBot.closeSelectedConnections();
 
@@ -242,7 +230,7 @@
         assertFalse( passwordsKeyStoreManager.isLoaded() );
 
         // verify master password prompt when opening the connection
-        connectionsViewBot.selectConnection( connection.getName() );
+        connectionsViewBot.select( connection.getName() );
         connectionsViewBot.openSelectedConnectionExpectingVerifyMasterPasswordDialog( "secret12" );
         connectionsViewBot.closeSelectedConnections();
 
@@ -251,7 +239,8 @@
         pageBot = preferencesBot.openPasswordsKeystorePage();
         assertTrue( pageBot.isPasswordsKeystoreEnabled() );
         KeepConnectionsPasswordsDialogBot keepConnectionsPasswordsDialogBot = pageBot.disablePasswordsKeystore();
-        VerifyMasterPasswordDialogBot verifyMasterPasswordDialog = keepConnectionsPasswordsDialogBot.clickYesButtonExpectingVerifyMasterPasswordDialog();
+        VerifyMasterPasswordDialogBot verifyMasterPasswordDialog = keepConnectionsPasswordsDialogBot
+            .clickYesButtonExpectingVerifyMasterPasswordDialog();
         verifyMasterPasswordDialog.enterMasterPassword( "secret12" );
         verifyMasterPasswordDialog.clickOkButton();
         assertFalse( pageBot.isPasswordsKeystoreEnabled() );
@@ -264,9 +253,100 @@
         assertFalse( passwordsKeyStoreManager.isLoaded() );
 
         // verify connection can be opened and connections password was kept
-        connectionsViewBot.selectConnection( connection.getName() );
+        connectionsViewBot.select( connection.getName() );
         connectionsViewBot.openSelectedConnection();
         connectionsViewBot.closeSelectedConnections();
     }
 
+
+    @Test
+    public void testLdifEditorPreferencesPage() throws Exception
+    {
+        // open preferences dialog
+        PreferencesBot preferencesBot = studioBot.openPreferences();
+        assertTrue( preferencesBot.isVisible() );
+
+        // open LDIF editor syntax coloring page
+        preferencesBot.openLdifEditorSyntaxColoringPage();
+        preferencesBot.clickCancelButton();
+    }
+
+
+    @Test
+    public void testSearchLogsViewPreferencesPage() throws Exception
+    {
+        File file = getConnectionCorePreferencesFile();
+
+        // open preferences dialog
+        PreferencesBot preferencesBot = studioBot.openPreferences();
+        SearchLogsViewPreferencePageBot page = preferencesBot.openSearchLogsViewPage();
+
+        page.setEnableSearchRequestLogs( false );
+        page.setEnableSearchResultEntryLogs( true );
+        page.setLogFileCount( 7 );
+        page.setLogFileSize( 77 );
+        page.clickApplyButton();
+
+        assertTrue( file.exists() );
+        List<String> lines = FileUtils.readLines( file, StandardCharsets.UTF_8 );
+        assertTrue( lines.contains( "searchRequestLogsEnable=false" ) );
+        assertTrue( lines.contains( "searchResultEntryLogsEnable=true" ) );
+        assertTrue( lines.contains( "searchLogsFileCount=7" ) );
+        assertTrue( lines.contains( "searchLogsFileSize=77" ) );
+
+        page.clickRestoreDefaultsButton();
+        preferencesBot.clickOkButton();
+        if ( file.exists() )
+        {
+            lines = FileUtils.readLines( file, StandardCharsets.UTF_8 );
+            assertFalse( lines.contains( "searchRequestLogsEnable=false" ) );
+            assertFalse( lines.contains( "searchResultEntryLogsEnable=true" ) );
+            assertFalse( lines.contains( "searchLogsFileCount=7" ) );
+            assertFalse( lines.contains( "searchLogsFileSize=77" ) );
+        }
+        else
+        {
+            assertFalse( file.exists() );
+        }
+    }
+
+
+    @Test
+    public void testModificationLogsViewPreferencesPage() throws Exception
+    {
+        File file = getConnectionCorePreferencesFile();
+
+        // open preferences dialog
+        PreferencesBot preferencesBot = studioBot.openPreferences();
+        ModificationLogsViewPreferencePageBot page = preferencesBot.openModificationLogsViewPage();
+
+        page.setEnableModificationLogs( false );
+        page.setMaskedAttributes( "userPassword" );
+        page.setLogFileCount( 2 );
+        page.setLogFileSize( 22 );
+        page.clickApplyButton();
+
+        assertTrue( file.exists() );
+        List<String> lines = FileUtils.readLines( file, StandardCharsets.UTF_8 );
+        assertTrue( lines.contains( "modificationLogsEnable=false" ) );
+        assertTrue( lines.contains( "modificationLogsMaskedAttributes=userPassword" ) );
+        assertTrue( lines.contains( "modificationLogsFileCount=2" ) );
+        assertTrue( lines.contains( "modificationLogsFileSize=22" ) );
+
+        page.clickRestoreDefaultsButton();
+        preferencesBot.clickOkButton();
+        if ( file.exists() )
+        {
+            lines = FileUtils.readLines( file, StandardCharsets.UTF_8 );
+            assertFalse( lines.contains( "modificationLogsEnable=false" ) );
+            assertFalse( lines.contains( "modificationLogsMaskedAttributes=userPassword" ) );
+            assertFalse( lines.contains( "modificationLogsFileCount=2" ) );
+            assertFalse( lines.contains( "modificationLogsFileSize=22" ) );
+        }
+        else
+        {
+            assertFalse( file.exists() );
+        }
+    }
+
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ProgressViewTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ProgressViewTest.java
index 5e19dc8..d192a03 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ProgressViewTest.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ProgressViewTest.java
@@ -21,18 +21,11 @@
 package org.apache.directory.studio.test.integration.ui;
 
 
-import org.apache.directory.server.annotations.CreateLdapServer;
-import org.apache.directory.server.annotations.CreateTransport;
-import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
-import org.apache.directory.studio.test.integration.ui.bots.ConnectionsViewBot;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource;
+import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
 import org.apache.directory.studio.test.integration.ui.bots.ProgressViewBot;
-import org.apache.directory.studio.test.integration.ui.bots.StudioBot;
-import org.apache.directory.studio.test.integration.ui.bots.utils.Assertions;
-import org.apache.directory.studio.test.integration.ui.bots.utils.FrameworkRunnerWithScreenshotCaptureListener;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
 
 
 /**
@@ -40,29 +33,8 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-@RunWith(FrameworkRunnerWithScreenshotCaptureListener.class)
-@CreateLdapServer(transports =
-    { @CreateTransport(protocol = "LDAP") })
-public class ProgressViewTest extends AbstractLdapTestUnit
+public class ProgressViewTest extends AbstractTestBase
 {
-    private StudioBot studioBot;
-
-
-    @Before
-    public void setUp() throws Exception
-    {
-        studioBot = new StudioBot();
-        studioBot.resetLdapPerspective();
-    }
-
-
-    @After
-    public void tearDown() throws Exception
-    {
-        studioBot.getConnectionView().deleteTestConnections();
-        Assertions.genericTearDownAssertions();
-    }
-
 
     @Test
     public void testRemoveAllFinishedOperations() throws Exception
@@ -72,14 +44,13 @@
     }
 
 
-    @Test
-    public void testNoRemainingOpenConnectionJobs() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testNoRemainingOpenConnectionJobs( TestLdapServer server ) throws Exception
     {
-        ConnectionsViewBot connectionView = studioBot.getConnectionView();
-
-        connectionView.createTestConnection( "ProgressViewTest", ldapServer.getPort() );
-        connectionView.createTestConnection( "ProgressViewTest", ldapServer.getPort() );
-        connectionView.createTestConnection( "ProgressViewTest", ldapServer.getPort() );
+        connectionsViewBot.createTestConnection( server );
+        connectionsViewBot.createTestConnection( server );
+        connectionsViewBot.createTestConnection( server );
 
         // actual assertion is done in Assertions.genericTearDownAssertions()
     }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/RcpAppTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/RcpAppTest.java
index c02ac61..b856742 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/RcpAppTest.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/RcpAppTest.java
@@ -21,24 +21,16 @@
 package org.apache.directory.studio.test.integration.ui;
 
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
 import org.apache.directory.studio.test.integration.ui.bots.ExportWizardBot;
 import org.apache.directory.studio.test.integration.ui.bots.ImportWizardBot;
 import org.apache.directory.studio.test.integration.ui.bots.NewWizardBot;
 import org.apache.directory.studio.test.integration.ui.bots.PreferencesBot;
 import org.apache.directory.studio.test.integration.ui.bots.ShowViewsBot;
-import org.apache.directory.studio.test.integration.ui.bots.StudioBot;
-import org.apache.directory.studio.test.integration.ui.bots.utils.Assertions;
-import org.apache.directory.studio.test.integration.ui.bots.utils.FrameworkRunnerWithScreenshotCaptureListener;
-import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.api.Test;
 
 
 /**
@@ -47,29 +39,8 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-@RunWith(FrameworkRunnerWithScreenshotCaptureListener.class)
-public class RcpAppTest extends AbstractLdapTestUnit
+public class RcpAppTest extends AbstractTestBase
 {
-    private SWTWorkbenchBot bot;
-    private StudioBot studioBot;
-
-
-    @Before
-    public void setUp() throws Exception
-    {
-        bot = new SWTWorkbenchBot();
-        studioBot = new StudioBot();
-        studioBot.resetLdapPerspective();
-    }
-
-
-    @After
-    public void tearDown() throws Exception
-    {
-        Assertions.genericTearDownAssertions();
-    }
-
-
     /**
      * Verify views in LDAP perspective.
      */
@@ -315,7 +286,9 @@
         assertTrue( prefs.pageExists( "Apache Directory Studio", "Schema Editor", "Search View" ) );
         assertTrue( prefs.pageExists( "Apache Directory Studio", "Shutdown" ) );
 
-        assertTrue( prefs.pageExists( "General", "Network Connections" ) );
+        assertTrue( prefs.pageExists( "General", "Appearance" ) );
+        assertTrue( prefs.pageExists( "General", "Appearance", "Text Editors" ) );
+        assertTrue( prefs.pageExists( "General", "Appearance", "Colors and Fonts" ) );
         assertTrue( prefs.pageExists( "Help" ) );
         assertTrue( prefs.pageExists( "Install/Update" ) );
 
@@ -338,6 +311,8 @@
         assertFalse( prefs.pageExists( "Team" ) );
         assertFalse( prefs.pageExists( "Maven" ) );
         assertFalse( prefs.pageExists( "Java" ) );
+        assertFalse( prefs.pageExists( "General", "Quick Search" ) );
+        assertFalse( prefs.pageExists( "General", "Network Connections" ) );
 
         prefs.clickCancelButton();
     }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ReferralDialogTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ReferralDialogTest.java
index 1593e7b..1be45d0 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ReferralDialogTest.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ReferralDialogTest.java
@@ -21,30 +21,29 @@
 package org.apache.directory.studio.test.integration.ui;
 
 
-import static org.apache.directory.studio.test.integration.ui.Constants.LOCALHOST;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.MISC_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.REFERRALS_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.REFERRAL_LOOP_1_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.REFERRAL_LOOP_2_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.REFERRAL_TO_MISC_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.REFERRAL_TO_REFERRALS_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.REFERRAL_TO_REFERRAL_TO_USERS_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.REFERRAL_TO_USER1_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.REFERRAL_TO_USERS_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USER1_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USERS_DN;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import org.apache.directory.server.annotations.CreateLdapServer;
-import org.apache.directory.server.annotations.CreateTransport;
-import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
-import org.apache.directory.api.ldap.model.entry.DefaultEntry;
-import org.apache.directory.api.ldap.model.entry.Entry;
-import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.studio.connection.core.Connection;
 import org.apache.directory.studio.connection.core.Connection.ReferralHandlingMethod;
 import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection;
-import org.apache.directory.studio.test.integration.ui.bots.BrowserViewBot;
-import org.apache.directory.studio.test.integration.ui.bots.ConnectionsViewBot;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource.Mode;
+import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
 import org.apache.directory.studio.test.integration.ui.bots.ReferralDialogBot;
-import org.apache.directory.studio.test.integration.ui.bots.StudioBot;
-import org.apache.directory.studio.test.integration.ui.bots.utils.Assertions;
-import org.apache.directory.studio.test.integration.ui.bots.utils.FrameworkRunnerWithScreenshotCaptureListener;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.params.ParameterizedTest;
 
 
 /**
@@ -53,84 +52,42 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-@RunWith(FrameworkRunnerWithScreenshotCaptureListener.class)
-@CreateLdapServer(transports =
-    { @CreateTransport(protocol = "LDAP") })
-public class ReferralDialogTest extends AbstractLdapTestUnit
+public class ReferralDialogTest extends AbstractTestBase
 {
-    private StudioBot studioBot;
-    private ConnectionsViewBot connectionsViewBot;
-    private BrowserViewBot browserViewBot;
-
-    private Connection connection;
-
-    private String[] parentPath;
-    private String[] referralPath;
-    private String[] targetPath;
-
-
-    @Before
-    public void setUp() throws Exception
-    {
-        studioBot = new StudioBot();
-        studioBot.resetLdapPerspective();
-        connectionsViewBot = studioBot.getConnectionView();
-        connection = connectionsViewBot.createTestConnection( "ReferralDialogTest", ldapServer.getPort() );
-        browserViewBot = studioBot.getBrowserView();
-
-        // create referral entry
-        Entry entry = new DefaultEntry( service.getSchemaManager() );
-        entry.setDn( new Dn( "cn=referralDialogTest,ou=system" ) );
-        entry.add( "objectClass", "top", "referral", "extensibleObject" );
-        entry.add( "cn", "referralDialogTest" );
-        entry.add( "ref", "ldap://" + LOCALHOST + ":" + ldapServer.getPort() + "/ou=users,ou=system" );
-        service.getAdminSession().add( entry );
-
-        // get paths
-        parentPath = new String[]
-            { "DIT", "Root DSE", "ou=system" };
-        referralPath = new String[]
-            { "DIT", "Root DSE", "ou=system", "cn=referralDialogTest" };
-        targetPath = new String[]
-            { "DIT", "Root DSE", "ou=system",
-                "ldap://" + LOCALHOST + ":" + ldapServer.getPort() + "/ou=users,ou=system" };
-    }
-
-
-    @After
-    public void tearDown() throws Exception
-    {
-        connectionsViewBot.closeSelectedConnections();
-        connectionsViewBot.deleteTestConnections();
-        Assertions.genericTearDownAssertions();
-    }
-
 
     /**
      * Test for DIRSTUDIO-343.
      *
      * Follows a continuation reference.
      */
-    @Test
-    public void testBrowseAndFollowContinuationReference()
+    @ParameterizedTest
+    @LdapServersSource
+    public void testBrowseAndFollowContinuationReference( TestLdapServer server ) throws Exception
     {
         // ensure that referrals handling method is FOLLOW
+        Connection connection = connectionsViewBot.createTestConnection( server );
         connection.getConnectionParameter().setExtendedIntProperty(
-            IBrowserConnection.CONNECTION_PARAMETER_REFERRALS_HANDLING_METHOD, ReferralHandlingMethod.FOLLOW.ordinal() );
+            IBrowserConnection.CONNECTION_PARAMETER_REFERRALS_HANDLING_METHOD,
+            ReferralHandlingMethod.FOLLOW.ordinal() );
         int referralsHandlingMethodOrdinal = connection.getConnectionParameter().getExtendedIntProperty(
             IBrowserConnection.CONNECTION_PARAMETER_REFERRALS_HANDLING_METHOD );
         assertEquals( ReferralHandlingMethod.FOLLOW.ordinal(), referralsHandlingMethodOrdinal );
 
-        // expand ou=system, that reads the referral and opens the referral dialog
-        ReferralDialogBot referralDialogBot = browserViewBot.expandEntryExpectingReferralDialog( parentPath );
+        // expand ou=referrals, that reads the referrals and opens the referral dialog
+        ReferralDialogBot referralDialogBot = browserViewBot.expandEntryExpectingReferralDialog( path( REFERRALS_DN ) );
         assertTrue( referralDialogBot.isVisible() );
         assertEquals( connection.getName(), referralDialogBot.getSelectedConnection() );
         referralDialogBot.clickOkButton();
 
-        // ensure that the target exists, the referral is not visible
-        assertFalse( browserViewBot.existsEntry( referralPath ) );
-        assertTrue( browserViewBot.existsEntry( targetPath ) );
-        browserViewBot.selectEntry( targetPath );
+        // ensure that the continuation URLs are visible and can be expanded, but not the referrals entries
+        assertReferralEntriesAreNotVisible();
+        assertTrue( browserViewBot.existsEntry( pathWithRefLdapUrl( server, USER1_DN ) ) );
+        assertTrue( browserViewBot.existsEntry( pathWithRefLdapUrl( server, USERS_DN ) ) );
+        browserViewBot.selectAndExpandEntry( pathWithRefLdapUrl( server, USERS_DN ) );
+        assertTrue( browserViewBot.existsEntry( pathWithRefLdapUrl( server, REFERRALS_DN ) ) );
+        browserViewBot.selectAndExpandEntry( pathWithRefLdapUrl( server, REFERRALS_DN ) );
+        assertTrue( browserViewBot.existsEntry( pathWithRefLdapUrl( server, MISC_DN ) ) );
+        browserViewBot.selectAndExpandEntry( pathWithRefLdapUrl( server, MISC_DN ) );
     }
 
 
@@ -140,59 +97,68 @@
      * Does not follow a continuation reference by clicking the cancel button in
      * the referral dialog.
      */
-    @Test
-    public void testBrowseAndCancelFollowingContinuationReference()
+    @ParameterizedTest
+    @LdapServersSource
+    public void testBrowseAndCancelFollowingContinuationReference( TestLdapServer server ) throws Exception
     {
         // ensure that referrals handling method is FOLLOW
+        Connection connection = connectionsViewBot.createTestConnection( server );
         connection.getConnectionParameter().setExtendedIntProperty(
-            IBrowserConnection.CONNECTION_PARAMETER_REFERRALS_HANDLING_METHOD, ReferralHandlingMethod.FOLLOW.ordinal() );
+            IBrowserConnection.CONNECTION_PARAMETER_REFERRALS_HANDLING_METHOD,
+            ReferralHandlingMethod.FOLLOW.ordinal() );
         int referralsHandlingMethodOrdinal = connection.getConnectionParameter().getExtendedIntProperty(
             IBrowserConnection.CONNECTION_PARAMETER_REFERRALS_HANDLING_METHOD );
         assertEquals( ReferralHandlingMethod.FOLLOW.ordinal(), referralsHandlingMethodOrdinal );
 
-        // expand ou=system, that reads the referral and opens the referral dialog
-        ReferralDialogBot referralDialogBot = browserViewBot.expandEntryExpectingReferralDialog( parentPath );
+        // expand ou=referrals, that reads the referral and opens the referral dialog
+        ReferralDialogBot referralDialogBot = browserViewBot.expandEntryExpectingReferralDialog( path( REFERRALS_DN ) );
         assertTrue( referralDialogBot.isVisible() );
         assertEquals( connection.getName(), referralDialogBot.getSelectedConnection() );
         referralDialogBot.clickCancelButton();
 
-        // ensure that neither the target, nor the referral exist
-        assertFalse( browserViewBot.existsEntry( referralPath ) );
-        assertFalse( browserViewBot.existsEntry( targetPath ) );
+        // ensure that neither the continuation URLs, nor the referral entries are visible
+        assertReferralEntriesAreNotVisible();
+        assertRefLdapUrlsAreNotVisible( server );
     }
 
 
     /**
      * Tests ignore referral by setting the connection property to IGNORE.
      */
-    @Test
-    public void testBrowseAndIgnoreReferral()
+    @ParameterizedTest
+    @LdapServersSource
+    public void testBrowseAndIgnoreReferral( TestLdapServer server ) throws Exception
     {
         // ensure that referrals handling method is IGNORE
+        Connection connection = connectionsViewBot.createTestConnection( server );
         connection.getConnectionParameter().setExtendedIntProperty(
-            IBrowserConnection.CONNECTION_PARAMETER_REFERRALS_HANDLING_METHOD, ReferralHandlingMethod.IGNORE.ordinal() );
+            IBrowserConnection.CONNECTION_PARAMETER_REFERRALS_HANDLING_METHOD,
+            ReferralHandlingMethod.IGNORE.ordinal() );
         int referralsHandlingMethodOrdinal = connection.getConnectionParameter().getExtendedIntProperty(
             IBrowserConnection.CONNECTION_PARAMETER_REFERRALS_HANDLING_METHOD );
         assertEquals( ReferralHandlingMethod.IGNORE.ordinal(), referralsHandlingMethodOrdinal );
 
-        // expand ou=system, no referral dialog expected
-        browserViewBot.expandEntry( parentPath );
+        // expand ou=referrals, no referral dialog expected
+        browserViewBot.selectAndExpandEntry( path( REFERRALS_DN ) );
 
-        // ensure that neither the target, nor the referral exist
-        assertFalse( browserViewBot.existsEntry( referralPath ) );
-        assertFalse( browserViewBot.existsEntry( targetPath ) );
+        // ensure that neither the continuation URLs, nor the referral entries are visible
+        assertReferralEntriesAreNotVisible();
+        assertRefLdapUrlsAreNotVisible( server );
     }
 
 
     /**
      * Tests manage referral entry by setting the ManageDsaIT control.
      */
-    @Test
-    public void testBrowseAndManageReferralEntry()
+    @ParameterizedTest
+    @LdapServersSource
+    public void testBrowseAndManageReferralEntry( TestLdapServer server ) throws Exception
     {
         // ensure that ManageDsaIT is set
+        Connection connection = connectionsViewBot.createTestConnection( server );
         connection.getConnectionParameter().setExtendedIntProperty(
-            IBrowserConnection.CONNECTION_PARAMETER_REFERRALS_HANDLING_METHOD, ReferralHandlingMethod.IGNORE.ordinal() );
+            IBrowserConnection.CONNECTION_PARAMETER_REFERRALS_HANDLING_METHOD,
+            ReferralHandlingMethod.IGNORE.ordinal() );
         connection.getConnectionParameter().setExtendedBoolProperty(
             IBrowserConnection.CONNECTION_PARAMETER_MANAGE_DSA_IT, true );
         int referralsHandlingMethodOrdinal = connection.getConnectionParameter().getExtendedIntProperty(
@@ -202,23 +168,30 @@
         assertEquals( ReferralHandlingMethod.IGNORE.ordinal(), referralsHandlingMethodOrdinal );
         assertTrue( manageDsaIT );
 
-        // expand ou=system, that reads the referral object
-        browserViewBot.expandEntry( parentPath );
+        // expand ou=referrals, that reads the referral object
+        browserViewBot.selectAndExpandEntry( path( REFERRALS_DN ) );
 
-        // ensure that the referral entry exists
-        assertTrue( browserViewBot.existsEntry( referralPath ) );
-        assertFalse( browserViewBot.existsEntry( targetPath ) );
-        browserViewBot.selectEntry( referralPath );
+        // ensure that the referral entries are visible, but not the continuation URLs
+        assertRefLdapUrlsAreNotVisible( server );
+        assertTrue( browserViewBot.existsEntry( path( REFERRAL_TO_USER1_DN ) ) );
+        assertTrue( browserViewBot.existsEntry( path( REFERRAL_TO_USERS_DN ) ) );
+        assertTrue( browserViewBot.existsEntry( path( REFERRAL_TO_REFERRAL_TO_USERS_DN ) ) );
+        assertTrue( browserViewBot.existsEntry( path( REFERRAL_TO_REFERRALS_DN ) ) );
+        assertTrue( browserViewBot.existsEntry( path( REFERRAL_LOOP_1_DN ) ) );
+        assertTrue( browserViewBot.existsEntry( path( REFERRAL_LOOP_2_DN ) ) );
+        assertTrue( browserViewBot.existsEntry( path( REFERRAL_TO_MISC_DN ) ) );
     }
 
 
     /**
      * Tests manual referral following.
      */
-    @Test
-    public void testBrowseAndFollowManuallyContinuationReference()
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testBrowseAndFollowManuallyContinuationReference( TestLdapServer server ) throws Exception
     {
         // ensure that referrals handling method is FOLLOW_MANUALLY
+        Connection connection = connectionsViewBot.createTestConnection( server );
         connection.getConnectionParameter().setExtendedIntProperty(
             IBrowserConnection.CONNECTION_PARAMETER_REFERRALS_HANDLING_METHOD,
             ReferralHandlingMethod.FOLLOW_MANUALLY.ordinal() );
@@ -226,22 +199,58 @@
             IBrowserConnection.CONNECTION_PARAMETER_REFERRALS_HANDLING_METHOD );
         assertEquals( ReferralHandlingMethod.FOLLOW_MANUALLY.ordinal(), referralsHandlingMethodOrdinal );
 
-        // expand ou=system, no referral dialog expected yet
-        browserViewBot.expandEntry( parentPath );
+        // expand ou=referrals, no referral dialog expected yet
+        browserViewBot.selectAndExpandEntry( path( REFERRALS_DN ) );
 
-        // ensure that the target exists, the referral is not visible
-        assertFalse( browserViewBot.existsEntry( referralPath ) );
-        assertTrue( browserViewBot.existsEntry( targetPath ) );
+        // ensure that only the referral targets are visible, not the referrals
+        assertReferralEntriesAreNotVisible();
+        assertTrue( browserViewBot.existsEntry( pathWithRefLdapUrl( server, USER1_DN ) ) );
+        assertTrue( browserViewBot.existsEntry( pathWithRefLdapUrl( server, USERS_DN ) ) );
+        assertTrue( browserViewBot.existsEntry( pathWithRefLdapUrl( server, REFERRAL_TO_USERS_DN ) ) );
+        assertTrue( browserViewBot.existsEntry( pathWithRefLdapUrl( server, REFERRALS_DN ) ) );
+        assertTrue( browserViewBot.existsEntry( pathWithRefLdapUrl( server, REFERRAL_LOOP_1_DN ) ) );
+        assertTrue( browserViewBot.existsEntry( pathWithRefLdapUrl( server, REFERRAL_LOOP_2_DN ) ) );
+        assertTrue( browserViewBot.existsEntry( pathWithRefLdapUrl( server, MISC_DN ) ) );
 
-        // select the target, that should popup the referral dialog
-        ReferralDialogBot referralDialogBot = browserViewBot.selectEntryExpectingReferralDialog( targetPath );
+        // select one target, that should popup the referral dialog
+        ReferralDialogBot referralDialogBot = browserViewBot
+            .selectEntryExpectingReferralDialog( pathWithRefLdapUrl( server, USER1_DN ) );
         assertTrue( referralDialogBot.isVisible() );
         assertEquals( connection.getName(), referralDialogBot.getSelectedConnection() );
         referralDialogBot.clickOkButton();
 
-        // ensure that the target exists, the referral is not visible
-        assertFalse( browserViewBot.existsEntry( referralPath ) );
-        assertTrue( browserViewBot.existsEntry( targetPath ) );
-        browserViewBot.selectEntry( targetPath );
+        // now all ref URLs can be expanded, no additional referral dialog is expected
+        browserViewBot.selectAndExpandEntry( pathWithRefLdapUrl( server, USER1_DN ) );
+        browserViewBot.selectAndExpandEntry( pathWithRefLdapUrl( server, USERS_DN ) );
+        browserViewBot.selectAndExpandEntry( pathWithRefLdapUrl( server, REFERRAL_TO_USERS_DN ) );
+        browserViewBot.selectAndExpandEntry( pathWithRefLdapUrl( server, REFERRALS_DN ) );
+        browserViewBot.selectAndExpandEntry( pathWithRefLdapUrl( server, REFERRAL_LOOP_1_DN ) );
+        browserViewBot.selectAndExpandEntry( pathWithRefLdapUrl( server, REFERRAL_LOOP_2_DN ) );
+        browserViewBot.selectAndExpandEntry( pathWithRefLdapUrl( server, MISC_DN ) );
     }
+
+
+    private void assertRefLdapUrlsAreNotVisible( TestLdapServer server )
+    {
+        assertFalse( browserViewBot.existsEntry( pathWithRefLdapUrl( server, USER1_DN ) ) );
+        assertFalse( browserViewBot.existsEntry( pathWithRefLdapUrl( server, USERS_DN ) ) );
+        assertFalse( browserViewBot.existsEntry( pathWithRefLdapUrl( server, REFERRAL_TO_USERS_DN ) ) );
+        assertFalse( browserViewBot.existsEntry( pathWithRefLdapUrl( server, REFERRALS_DN ) ) );
+        assertFalse( browserViewBot.existsEntry( pathWithRefLdapUrl( server, REFERRAL_LOOP_1_DN ) ) );
+        assertFalse( browserViewBot.existsEntry( pathWithRefLdapUrl( server, REFERRAL_LOOP_2_DN ) ) );
+        assertFalse( browserViewBot.existsEntry( pathWithRefLdapUrl( server, MISC_DN ) ) );
+    }
+
+
+    private void assertReferralEntriesAreNotVisible()
+    {
+        assertFalse( browserViewBot.existsEntry( path( REFERRAL_TO_USER1_DN ) ) );
+        assertFalse( browserViewBot.existsEntry( path( REFERRAL_TO_USERS_DN ) ) );
+        assertFalse( browserViewBot.existsEntry( path( REFERRAL_TO_REFERRAL_TO_USERS_DN ) ) );
+        assertFalse( browserViewBot.existsEntry( path( REFERRAL_TO_REFERRALS_DN ) ) );
+        assertFalse( browserViewBot.existsEntry( path( REFERRAL_LOOP_1_DN ) ) );
+        assertFalse( browserViewBot.existsEntry( path( REFERRAL_LOOP_2_DN ) ) );
+        assertFalse( browserViewBot.existsEntry( path( REFERRAL_TO_MISC_DN ) ) );
+    }
+
 }
\ No newline at end of file
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/RenameEntryTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/RenameEntryTest.java
index 1927e6a..2e679b5 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/RenameEntryTest.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/RenameEntryTest.java
@@ -21,22 +21,24 @@
 package org.apache.directory.studio.test.integration.ui;
 
 
-import static org.junit.Assert.assertTrue;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.DN_WITH_LEADING_SHARP_BACKSLASH_PREFIXED;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.DN_WITH_LEADING_SHARP_HEX_PAIR_ESCAPED;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.MULTI_VALUED_RDN_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.DN_WITH_ESCAPED_CHARACTERS_BACKSLASH_PREFIXED;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.DN_WITH_ESCAPED_CHARACTERS_HEX_PAIR_ESCAPED;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.dn;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import org.apache.directory.server.annotations.CreateLdapServer;
-import org.apache.directory.server.annotations.CreateTransport;
-import org.apache.directory.server.core.annotations.ApplyLdifFiles;
-import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
-import org.apache.directory.studio.test.integration.ui.bots.BrowserViewBot;
-import org.apache.directory.studio.test.integration.ui.bots.ConnectionsViewBot;
+import org.apache.directory.api.ldap.model.name.Ava;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.api.ldap.model.name.Rdn;
+import org.apache.directory.studio.test.integration.junit5.LdapServerType;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource;
+import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource.Mode;
 import org.apache.directory.studio.test.integration.ui.bots.RenameEntryDialogBot;
-import org.apache.directory.studio.test.integration.ui.bots.StudioBot;
-import org.apache.directory.studio.test.integration.ui.bots.utils.Assertions;
-import org.apache.directory.studio.test.integration.ui.bots.utils.FrameworkRunnerWithScreenshotCaptureListener;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.params.ParameterizedTest;
 
 
 /**
@@ -45,59 +47,37 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-@RunWith(FrameworkRunnerWithScreenshotCaptureListener.class)
-@CreateLdapServer(transports =
-    { @CreateTransport(protocol = "LDAP") })
-@ApplyLdifFiles( clazz = RenameEntryTest.class,
-    value = "org/apache/directory/studio/test/integration/ui/RenameEntryDialogTest.ldif" )
-public class RenameEntryTest extends AbstractLdapTestUnit
+public class RenameEntryTest extends AbstractTestBase
 {
-    private StudioBot studioBot;
-    private ConnectionsViewBot connectionsViewBot;
-    private BrowserViewBot browserViewBot;
-
-
-    @Before
-    public void setUp() throws Exception
-    {
-        studioBot = new StudioBot();
-        studioBot.resetLdapPerspective();
-        connectionsViewBot = studioBot.getConnectionView();
-        connectionsViewBot.createTestConnection( "RenameEntryTest", ldapServer.getPort() );
-        browserViewBot = studioBot.getBrowserView();
-    }
-
-
-    @After
-    public void tearDown() throws Exception
-    {
-        connectionsViewBot.deleteTestConnections();
-        Assertions.genericTearDownAssertions();
-    }
-
 
     /**
      * Test for DIRSTUDIO-318.
      *
      * Renames a multi-valued RDN by changing both RDN attributes.
-     *
-     * @throws Exception
-     *             the exception
      */
-    @Test
-    public void testRenameMultiValuedRdn() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testRenameMultiValuedRdn( TestLdapServer server ) throws Exception
     {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=Barbara Jensen+uid=bjensen" );
+        Dn oldDn = MULTI_VALUED_RDN_DN;
+        Rdn newRdn = new Rdn( new Ava( "cn", "Babs Jensen" ), new Ava( "uid", "dj" ) );
+        Dn newDn = dn( newRdn, oldDn.getParent() );
+
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( oldDn ) );
 
         RenameEntryDialogBot renameDialogBot = browserViewBot.openRenameDialog();
         assertTrue( renameDialogBot.isVisible() );
-        renameDialogBot.setRdnValue( 1, "Babs Jensen" );
-        renameDialogBot.setRdnValue( 2, "babsjens" );
+        for ( int i = 0; i < newRdn.size(); i++ )
+        {
+            renameDialogBot.setRdnType( i + 1, newRdn.getAva( i ).getType() );
+            renameDialogBot.setRdnValue( i + 1, newRdn.getAva( i ).getValue().getString() );
+        }
         renameDialogBot.clickOkButton();
 
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "cn=Babs Jensen+uid=babsjens" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=Babs Jensen+uid=babsjens" );
+        assertTrue( browserViewBot.existsEntry( path( newDn ) ) );
+        browserViewBot.selectEntry( path( newDn ) );
+        assertFalse( browserViewBot.existsEntry( path( oldDn ) ) );
     }
 
 
@@ -105,73 +85,123 @@
      * Test for DIRSTUDIO-484.
      *
      * Renames a RDN with escaped characters.
-     *
-     * @throws Exception
-     *             the exception
      */
-    @Test
-    public void testRenameRdnWithEscapedCharacters() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testRenameRdnWithEscapedCharacters( TestLdapServer server ) throws Exception
     {
-        browserViewBot
-            .selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=\\#\\\\\\+\\, \\\"\u00F6\u00E9\\\"" );
+        Dn oldDn = DN_WITH_ESCAPED_CHARACTERS_BACKSLASH_PREFIXED;
+        if ( server.getType() == LdapServerType.OpenLdap || server.getType() == LdapServerType.Fedora389ds )
+        {
+            oldDn = DN_WITH_ESCAPED_CHARACTERS_HEX_PAIR_ESCAPED;
+        }
+        Dn newDn = dn( oldDn.getRdn().getName() + " renamed", oldDn.getParent() );
+
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( oldDn ) );
 
         RenameEntryDialogBot renameDialogBot = browserViewBot.openRenameDialog();
         assertTrue( renameDialogBot.isVisible() );
-        renameDialogBot.setRdnValue( 1, "#\\+, \"\u00F6\u00E9\"2" );
+        renameDialogBot.setRdnValue( 1, newDn.getRdn().getValue() );
         renameDialogBot.clickOkButton();
 
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "cn=\\#\\\\\\+\\, \\\"\u00F6\u00E9\\\"2" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users",
-            "cn=\\#\\\\\\+\\, \\\"\u00F6\u00E9\\\"2" );
+        assertTrue( browserViewBot.existsEntry( path( newDn ) ) );
+        browserViewBot.selectEntry( path( newDn ) );
+        assertFalse( browserViewBot.existsEntry( path( oldDn ) ) );
     }
 
 
     /**
      * Test for DIRSTUDIO-589, DIRSTUDIO-591, DIRSHARED-38.
      *
-     * Rename an entry with sharp in DN: cn=\#123456.
+     * Rename an entry with leading sharp in DN: cn=\#123456.
      */
-    @Test
-    public void testRenameRdnWithSharp() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All)
+    public void testRenameRdnWithLeadingSharp( TestLdapServer server ) throws Exception
     {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=\\#123456" );
+        Dn oldDn = DN_WITH_LEADING_SHARP_BACKSLASH_PREFIXED;
+        Dn newDn = dn( "cn=\\#ABCDEF", oldDn.getParent() );
+        if ( server.getType() == LdapServerType.OpenLdap || server.getType() == LdapServerType.Fedora389ds )
+        {
+            oldDn = DN_WITH_LEADING_SHARP_HEX_PAIR_ESCAPED;
+            newDn = dn( "cn=\\23ABCDEF", oldDn.getParent() );
+        }
+
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( oldDn ) );
 
         RenameEntryDialogBot renameDialogBot = browserViewBot.openRenameDialog();
         assertTrue( renameDialogBot.isVisible() );
         renameDialogBot.setRdnValue( 1, "#ABCDEF" );
         renameDialogBot.clickOkButton();
 
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=\\#ABCDEF" ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=\\#ABCDEF" );
+        assertTrue( browserViewBot.existsEntry( path( newDn ) ) );
+        browserViewBot.selectEntry( path( newDn ) );
+        assertFalse( browserViewBot.existsEntry( path( oldDn ) ) );
     }
 
 
     /**
      * Test for DIRSHARED-39.
      *
-     * Rename an entry with trailing space in RDN.
+     * Rename an entry with leading and trailing space in RDN.
      */
-    @Test
-    public void testRenameRdnWithTrailingSpace() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.Fedora389ds, reason = "Leading and trailing space is trimmed by 389ds")
+    public void testRenameRdnWithTrailingSpace( TestLdapServer server ) throws Exception
     {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=\\#123456" );
+        Dn oldDn = DN_WITH_LEADING_SHARP_BACKSLASH_PREFIXED;
+        Dn newDn = dn( "cn=\\#ABCDEF\\ ", oldDn.getParent() );
+        if ( server.getType() == LdapServerType.OpenLdap )
+        {
+            oldDn = DN_WITH_LEADING_SHARP_HEX_PAIR_ESCAPED;
+            newDn = dn( "cn=\\23ABCDEF\\20", oldDn.getParent() );
+        }
+
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( oldDn ) );
 
         RenameEntryDialogBot renameDialogBot = browserViewBot.openRenameDialog();
         assertTrue( renameDialogBot.isVisible() );
         renameDialogBot.setRdnValue( 1, "#ABCDEF " );
         renameDialogBot.clickOkButton();
 
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=\\#ABCDEF\\ " ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=\\#ABCDEF\\ " );
+        assertTrue( browserViewBot.existsEntry( path( newDn ) ) );
+        browserViewBot.selectEntry( path( newDn ) );
+        assertFalse( browserViewBot.existsEntry( path( oldDn ) ) );
 
-        renameDialogBot = browserViewBot.openRenameDialog();
+    }
+
+
+    /**
+     * Test for DIRSHARED-39.
+     *
+     * Rename an entry with leading and trailing space in RDN.
+     */
+    @ParameterizedTest
+    @LdapServersSource(mode = Mode.All, except = LdapServerType.Fedora389ds, reason = "Leading and trailing space is trimmed by 389ds")
+    public void testRenameRdnWithLeadingAndTrailingSpace( TestLdapServer server ) throws Exception
+    {
+        Dn oldDn = DN_WITH_LEADING_SHARP_BACKSLASH_PREFIXED;
+        Dn newDn = dn( "cn=\\  #ABCDEF \\ ", oldDn.getParent() );
+        if ( server.getType() == LdapServerType.OpenLdap )
+        {
+            oldDn = DN_WITH_LEADING_SHARP_HEX_PAIR_ESCAPED;
+            newDn = dn( "cn=\\20 #ABCDEF \\20", oldDn.getParent() );
+        }
+
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( oldDn ) );
+
+        RenameEntryDialogBot renameDialogBot = browserViewBot.openRenameDialog();
         assertTrue( renameDialogBot.isVisible() );
-        renameDialogBot.setRdnValue( 1, "A " );
+        renameDialogBot.setRdnValue( 1, "  #ABCDEF  " );
         renameDialogBot.clickOkButton();
 
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=A\\ " ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users", "cn=A\\ " );
+        assertTrue( browserViewBot.existsEntry( path( newDn ) ) );
+        browserViewBot.selectEntry( path( newDn ) );
+        assertFalse( browserViewBot.existsEntry( path( oldDn ) ) );
     }
 
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/SchemaBrowserTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/SchemaBrowserTest.java
index d6064a1..625cfd1 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/SchemaBrowserTest.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/SchemaBrowserTest.java
@@ -21,22 +21,22 @@
 package org.apache.directory.studio.test.integration.ui;
 
 
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USER8_DN;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import org.apache.directory.server.annotations.CreateLdapServer;
-import org.apache.directory.server.annotations.CreateTransport;
-import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
 import org.apache.directory.studio.connection.core.Connection;
-import org.apache.directory.studio.test.integration.ui.bots.ConnectionsViewBot;
+import org.apache.directory.studio.ldapbrowser.core.BrowserCorePlugin;
+import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection;
+import org.apache.directory.studio.ldapbrowser.core.model.schema.Schema;
+import org.apache.directory.studio.test.integration.junit5.LdapServerType;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource;
+import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
+import org.apache.directory.studio.test.integration.ui.bots.ErrorDialogBot;
 import org.apache.directory.studio.test.integration.ui.bots.SchemaBrowserBot;
-import org.apache.directory.studio.test.integration.ui.bots.StudioBot;
-import org.apache.directory.studio.test.integration.ui.bots.utils.Assertions;
-import org.apache.directory.studio.test.integration.ui.bots.utils.FrameworkRunnerWithScreenshotCaptureListener;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.params.ParameterizedTest;
 
 
 /**
@@ -44,42 +44,18 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-@RunWith(FrameworkRunnerWithScreenshotCaptureListener.class)
-@CreateLdapServer(transports =
-    { @CreateTransport(protocol = "LDAP") })
-public class SchemaBrowserTest extends AbstractLdapTestUnit
+public class SchemaBrowserTest extends AbstractTestBase
 {
-    private StudioBot studioBot;
-    private ConnectionsViewBot connectionsViewBot;
-
-    private Connection connection;
-
-
-    @Before
-    public void setUp() throws Exception
-    {
-        studioBot = new StudioBot();
-        studioBot.resetLdapPerspective();
-        connectionsViewBot = studioBot.getConnectionView();
-        connection = connectionsViewBot.createTestConnection( "SchemaBrowserTest", ldapServer.getPort() );
-    }
-
-
-    @After
-    public void tearDown() throws Exception
-    {
-        connectionsViewBot.deleteTestConnections();
-        Assertions.genericTearDownAssertions();
-    }
-
 
     /**
      * Test for DIRSTUDIO-1061 (RawSchemaDefinition always shows single hyphen/dash)
      */
-    @Test
-    public void testRawSchemaDefinitionIsFilled() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testRawSchemaDefinitionIsFilled( TestLdapServer server ) throws Exception
     {
-        connectionsViewBot.selectConnection( connection.getName() );
+        Connection connection = connectionsViewBot.createTestConnection( server );
+        connectionsViewBot.select( connection.getName() );
         SchemaBrowserBot schemaBrowser = connectionsViewBot.openSchemaBrowser();
         //schemaBrowser.activateObjectClassesTab();
         schemaBrowser.selectObjectClass( "account" );
@@ -88,4 +64,35 @@
         assertTrue( rawSchemaDefinition.contains( "account" ) );
     }
 
+
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.OpenLdap, reason = "OpenLDAP specific test")
+    public void testNoPermissionToReadSchema( TestLdapServer server ) throws Exception
+    {
+        Connection connection = connectionsViewBot.createTestConnection( server );
+
+        // Close connection and reset cached schema
+        connectionsViewBot.closeSelectedConnections();
+        IBrowserConnection browserConnection = BrowserCorePlugin.getDefault().getConnectionManager()
+            .getBrowserConnection( connection );
+        browserConnection.setSchema( Schema.DEFAULT_SCHEMA );
+
+        // Open connection as uid=user.8 which is not allowed to read cn=subschema
+        connection.setBindPrincipal( USER8_DN.getName() );
+        connection.setBindPassword( "password" );
+        ErrorDialogBot errorDialog = connectionsViewBot.openSelectedConnectionExpectingNoSchemaProvidedErrorDialog();
+        assertThat( errorDialog.getErrorDetails(),
+            containsString( "No schema information returned by server, using default schema." ) );
+        errorDialog.clickOkButton();
+
+        // Verify default schema is used
+        SchemaBrowserBot schemaBrowser = connectionsViewBot.openSchemaBrowser();
+        schemaBrowser.selectObjectClass( "DEFAULTSCHEMA" );
+        String rawSchemaDefinition = schemaBrowser.getRawSchemaDefinition();
+        assertNotNull( rawSchemaDefinition );
+        assertTrue( rawSchemaDefinition.contains( "This is the Default Schema" ) );
+
+        // Verify browser
+        browserViewBot.selectEntry( ROOT_DSE_PATH );
+    }
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/SchemaEditorTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/SchemaEditorTest.java
index c83e14a..e672ffa 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/SchemaEditorTest.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/SchemaEditorTest.java
@@ -24,32 +24,26 @@
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.util.List;
 
-import org.apache.directory.server.annotations.CreateLdapServer;
-import org.apache.directory.server.annotations.CreateTransport;
-import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
 import org.apache.directory.studio.connection.core.Connection;
+import org.apache.directory.studio.test.integration.junit5.LdapServerType;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource;
+import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
 import org.apache.directory.studio.test.integration.ui.bots.AttributeTypeEditorBot;
-import org.apache.directory.studio.test.integration.ui.bots.ConnectionsViewBot;
 import org.apache.directory.studio.test.integration.ui.bots.NewSchemaProjectWizardBot;
 import org.apache.directory.studio.test.integration.ui.bots.ObjectClassEditorBot;
 import org.apache.directory.studio.test.integration.ui.bots.SchemaEditorBot;
 import org.apache.directory.studio.test.integration.ui.bots.SchemaProjectsViewBot;
 import org.apache.directory.studio.test.integration.ui.bots.SchemaSearchViewBot;
 import org.apache.directory.studio.test.integration.ui.bots.SchemaViewBot;
-import org.apache.directory.studio.test.integration.ui.bots.StudioBot;
-import org.apache.directory.studio.test.integration.ui.bots.utils.Assertions;
-import org.apache.directory.studio.test.integration.ui.bots.utils.FrameworkRunnerWithScreenshotCaptureListener;
-import org.apache.directory.studio.test.integration.ui.bots.utils.StudioSystemUtils;
-import org.junit.After;
-import org.junit.Assume;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
 
 
 /**
@@ -58,35 +52,24 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-@RunWith(FrameworkRunnerWithScreenshotCaptureListener.class)
-@CreateLdapServer(transports =
-    { @CreateTransport(protocol = "LDAP") })
-public class SchemaEditorTest extends AbstractLdapTestUnit
+public class SchemaEditorTest extends AbstractTestBase
 {
-    private StudioBot studioBot;
     private SchemaProjectsViewBot projectsView;
     private SchemaViewBot schemaView;
-    private ConnectionsViewBot connectionsViewBot;
-    private Connection connection;
 
-
-    @Before
+    @BeforeEach
     public void setUp() throws Exception
     {
-        studioBot = new StudioBot();
         studioBot.resetSchemaPerspective();
         projectsView = studioBot.getSchemaProjectsView();
         schemaView = studioBot.getSchemaView();
-        connectionsViewBot = studioBot.getConnectionView();
     }
 
 
-    @After
+    @AfterEach
     public void tearDown() throws Exception
     {
-        connectionsViewBot.deleteTestConnections();
         projectsView.deleteAllProjects();
-        Assertions.genericTearDownAssertions();
     }
 
 
@@ -96,11 +79,6 @@
     @Test
     public void testSearchForAliases() throws Exception
     {
-        /*
-         * This test fails on Jenkins Windows Server, to be investigated...
-         */
-        // Assume.assumeFalse( StudioSystemUtils.IS_OS_WINDOWS_SERVER );
-
         createProject( "Project Search For Aliases" );
 
         SchemaSearchViewBot searchView = studioBot.getSchemaSearchView();
@@ -182,11 +160,12 @@
     }
 
 
-    @Test
-    public void testCreateSchemaOnlineApacheDS() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.ApacheDS, reason = "ApacheDS specific test")
+    public void testCreateSchemaOnlineApacheDS( TestLdapServer server ) throws Exception
     {
         studioBot.resetLdapPerspective();
-        connection = connectionsViewBot.createTestConnection( "SchemaEditorTest", ldapServer.getPort() );
+        Connection connection = connectionsViewBot.createTestConnection( server );
         studioBot.resetSchemaPerspective();
 
         SchemaProjectsViewBot projectsView = studioBot.getSchemaProjectsView();
@@ -213,6 +192,58 @@
     }
 
 
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.OpenLdap, reason = "OpenLDAP specific test")
+    public void testCreateSchemaOnlineOpenLDAP( TestLdapServer server ) throws Exception
+    {
+        studioBot.resetLdapPerspective();
+        Connection connection = connectionsViewBot.createTestConnection( server );
+        studioBot.resetSchemaPerspective();
+
+        SchemaProjectsViewBot projectsView = studioBot.getSchemaProjectsView();
+        NewSchemaProjectWizardBot wizard = projectsView.openNewSchemaProjectWizard();
+        wizard.typeProjectName( "Project Online OpenLDAP" );
+        wizard.selectOnlineSchema();
+        wizard.clickNextButton();
+        wizard.selectConnection( connection.getName() );
+        wizard.clickFinishButton();
+
+        assertTrue( schemaView.existsSchema( "schema" ) );
+
+        assertTrue( schemaView.existsObjectClass( "schema", "top" ) );
+        assertTrue( schemaView.existsObjectClass( "schema", "olcGlobal" ) );
+
+        assertTrue( schemaView.existsAttributeType( "schema", "objectClass" ) );
+        assertTrue( schemaView.existsAttributeType( "schema", "olcBackend" ) );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.Fedora389ds, reason = "389ds specific test")
+    public void testCreateSchemaOnline389ds( TestLdapServer server ) throws Exception
+    {
+        studioBot.resetLdapPerspective();
+        Connection connection = connectionsViewBot.createTestConnection( server );
+        studioBot.resetSchemaPerspective();
+
+        SchemaProjectsViewBot projectsView = studioBot.getSchemaProjectsView();
+        NewSchemaProjectWizardBot wizard = projectsView.openNewSchemaProjectWizard();
+        wizard.typeProjectName( "Project Online 389ds" );
+        wizard.selectOnlineSchema();
+        wizard.clickNextButton();
+        wizard.selectConnection( connection.getName() );
+        wizard.clickFinishButton();
+
+        assertTrue( schemaView.existsSchema( "schema" ) );
+
+        assertTrue( schemaView.existsObjectClass( "schema", "top" ) );
+        assertTrue( schemaView.existsObjectClass( "schema", "nsConfig" ) );
+
+        assertTrue( schemaView.existsAttributeType( "schema", "objectClass" ) );
+        assertTrue( schemaView.existsAttributeType( "schema", "nsBaseDN" ) );
+    }
+
+
     @Test
     public void testOpenObjectClassEditor() throws Exception
     {
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/SearchTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/SearchTest.java
index ec23c64..a291fa7 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/SearchTest.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/SearchTest.java
@@ -21,36 +21,41 @@
 package org.apache.directory.studio.test.integration.ui;
 
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.ALIAS_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.CONTEXT_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.DN_WITH_LEADING_SHARP_BACKSLASH_PREFIXED;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.DN_WITH_LEADING_SHARP_HEX_PAIR_ESCAPED;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.GROUP1_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.GROUPS_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.MISC_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.REFERRAL_TO_USER1_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.SUBENTRY_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USER1_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USER8_DN;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.USERS_DN;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
+import org.apache.commons.lang3.StringUtils;
 import org.apache.directory.api.ldap.model.message.ModifyRequest;
 import org.apache.directory.api.ldap.model.message.ModifyRequestImpl;
-import org.apache.directory.api.ldap.model.name.Dn;
-import org.apache.directory.server.annotations.CreateLdapServer;
-import org.apache.directory.server.annotations.CreateTransport;
-import org.apache.directory.server.core.annotations.ApplyLdifFiles;
-import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
 import org.apache.directory.studio.connection.core.Connection;
 import org.apache.directory.studio.connection.core.Connection.AliasDereferencingMethod;
+import org.apache.directory.studio.connection.core.Utils;
 import org.apache.directory.studio.ldapbrowser.core.BrowserConnectionManager;
 import org.apache.directory.studio.ldapbrowser.core.BrowserCorePlugin;
 import org.apache.directory.studio.ldapbrowser.core.events.EventRegistry;
 import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection;
-import org.apache.directory.studio.test.integration.ui.bots.BrowserViewBot;
-import org.apache.directory.studio.test.integration.ui.bots.ConnectionsViewBot;
+import org.apache.directory.studio.test.integration.junit5.LdapServerType;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource;
+import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
+import org.apache.directory.studio.test.integration.ui.bots.FilterEditorDialogBot;
 import org.apache.directory.studio.test.integration.ui.bots.SearchDialogBot;
 import org.apache.directory.studio.test.integration.ui.bots.SearchPropertiesDialogBot;
 import org.apache.directory.studio.test.integration.ui.bots.SearchResultEditorBot;
-import org.apache.directory.studio.test.integration.ui.bots.StudioBot;
-import org.apache.directory.studio.test.integration.ui.bots.utils.Assertions;
-import org.apache.directory.studio.test.integration.ui.bots.utils.FrameworkRunnerWithScreenshotCaptureListener;
 import org.eclipse.swtbot.swt.finder.utils.SWTUtils;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.params.ParameterizedTest;
 
 
 /**
@@ -59,50 +64,21 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-@RunWith(FrameworkRunnerWithScreenshotCaptureListener.class)
-@CreateLdapServer(transports =
-    { @CreateTransport(protocol = "LDAP") })
-@ApplyLdifFiles(clazz = BrowserTest.class, value = "org/apache/directory/studio/test/integration/ui/BrowserTest.ldif")
-public class SearchTest extends AbstractLdapTestUnit
+public class SearchTest extends AbstractTestBase
 {
-    private StudioBot studioBot;
-    private ConnectionsViewBot connectionsViewBot;
-    private BrowserViewBot browserViewBot;
-
-    private Connection connection1;
-    private Connection connection2;
-
-
-    @Before
-    public void setUp() throws Exception
-    {
-        studioBot = new StudioBot();
-        studioBot.resetLdapPerspective();
-        connectionsViewBot = studioBot.getConnectionView();
-        connection1 = connectionsViewBot.createTestConnection( "SearchTest1", ldapServer.getPort() );
-        connection2 = connectionsViewBot.createTestConnection( "SearchTest2", ldapServer.getPort() );
-        browserViewBot = studioBot.getBrowserView();
-    }
-
-
-    @After
-    public void tearDown() throws Exception
-    {
-        connectionsViewBot.deleteTestConnections();
-        Assertions.genericTearDownAssertions();
-    }
-
 
     /**
      * Test for DIRSTUDIO-490.
      *
      * Copy/Paste a search between connections and verify that the associated browser connection is correct.
-     *
-     * @throws Exception
      */
-    @Test
-    public void testCopyPasteSearchBetweenConnections() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testCopyPasteSearchBetweenConnections( TestLdapServer server ) throws Exception
     {
+        Connection connection1 = connectionsViewBot.createTestConnection( server );
+        Connection connection2 = connectionsViewBot.createTestConnection( server );
+
         BrowserConnectionManager browserConnectionManager = BrowserCorePlugin.getDefault().getConnectionManager();
         IBrowserConnection browserConnection1 = browserConnectionManager.getBrowserConnectionByName( connection1
             .getName() );
@@ -112,8 +88,8 @@
         assertEquals( 0, browserConnection2.getSearchManager().getSearches().size() );
 
         // create a search for in connection 1
-        connectionsViewBot.selectConnection( connection1.getName() );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system" );
+        connectionsViewBot.select( connection1.getName() );
+        browserViewBot.selectEntry( path( CONTEXT_DN ) );
         SearchDialogBot dialogBot = browserViewBot.openSearchDialog();
         assertTrue( dialogBot.isVisible() );
         dialogBot.setSearchName( "Search all persons" );
@@ -129,9 +105,9 @@
 
         // copy/paste the created search from connection 1 to connection 2
         browserViewBot.copy();
-        connectionsViewBot.selectConnection( connection2.getName() );
+        connectionsViewBot.select( connection2.getName() );
         browserViewBot.selectEntry( "Searches" );
-        SearchPropertiesDialogBot searchPropertiesDialogBot = browserViewBot.pasteSearch();
+        SearchPropertiesDialogBot searchPropertiesDialogBot = browserViewBot.pasteSearch( "Search all persons" );
         assertTrue( searchPropertiesDialogBot.isVisible() );
         searchPropertiesDialogBot.clickCancelButton();
 
@@ -149,78 +125,128 @@
      * Test for DIRSTUDIO-587 (UI flickers on quick search).
      *
      * When performing a quick search only one UI update should be fired.
-     *
-     * @throws Exception
      */
-    @Test
-    public void testOnlyOneUiUpdateOnQuickSearch() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testOnlyOneUiUpdateOnQuickSearch( TestLdapServer server ) throws Exception
     {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system" );
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system" );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( CONTEXT_DN ) );
+        browserViewBot.expandEntry( path( CONTEXT_DN ) );
 
         browserViewBot.typeQuickSearchAttributeType( "ou" );
         browserViewBot.typeQuickSearchValue( "*" );
 
         long fireCount0 = EventRegistry.getFireCount();
         browserViewBot.clickRunQuickSearchButton();
-        browserViewBot.waitForEntry( "DIT", "Root DSE", "ou=system", "Quick Search" );
+        browserViewBot.waitForEntry( path( CONTEXT_DN, "Quick Search" ) );
         long fireCount1 = EventRegistry.getFireCount();
 
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "Quick Search" );
+        browserViewBot.selectEntry( path( CONTEXT_DN, "Quick Search" ) );
 
         // verify that only one event was fired
         long fireCount = fireCount1 - fireCount0;
-        assertEquals( "Only 1 event firings expected when running quick search.", 1, fireCount );
+        assertEquals( 1, fireCount, "Only 1 event firings expected when running quick search." );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testQuickSearch( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+        // quick search on context entry
+        browserViewBot.selectEntry( path( CONTEXT_DN ) );
+        browserViewBot.expandEntry( path( CONTEXT_DN ) );
+
+        browserViewBot.typeQuickSearchAttributeType( "ou" );
+        browserViewBot.typeQuickSearchValue( "*" );
+        browserViewBot.clickRunQuickSearchButton();
+
+        browserViewBot.waitForEntry( path( CONTEXT_DN, "Quick Search (5)" ) );
+        browserViewBot.selectEntry( path( CONTEXT_DN, "Quick Search (5)" ) );
+        browserViewBot.expandEntry( path( CONTEXT_DN, "Quick Search (5)" ) );
+        browserViewBot.selectEntry( path( CONTEXT_DN, "Quick Search (5)", USERS_DN.getName() ) );
+
+        // quick search on non-leaf entry
+        browserViewBot.selectEntry( path( USERS_DN ) );
+        browserViewBot.expandEntry( path( USERS_DN ) );
+
+        browserViewBot.typeQuickSearchAttributeType( "uid" );
+        browserViewBot.typeQuickSearchValue( "user.1" );
+        browserViewBot.clickRunQuickSearchButton();
+
+        browserViewBot.waitForEntry( path( USERS_DN, "Quick Search (1)" ) );
+        browserViewBot.selectEntry( path( USERS_DN, "Quick Search (1)" ) );
+        browserViewBot.expandEntry( path( USERS_DN, "Quick Search (1)" ) );
+        browserViewBot.selectEntry( path( USERS_DN, "Quick Search (1)", USER1_DN.getName() ) );
+
+        // quick search on leaf entry
+        browserViewBot.selectEntry( path( USER1_DN ) );
+        browserViewBot.expandEntry( path( USER1_DN ) );
+
+        browserViewBot.typeQuickSearchAttributeType( "uid" );
+        browserViewBot.typeQuickSearchValue( "user.1" );
+        browserViewBot.clickRunQuickSearchButton();
+
+        browserViewBot.waitForEntry( path( USER1_DN, "Quick Search (0)" ) );
+        browserViewBot.selectEntry( path( USER1_DN, "Quick Search (0)" ) );
+        browserViewBot.expandEntry( path( USER1_DN, "Quick Search (0)" ) );
+        browserViewBot.selectEntry( path( USER1_DN, "Quick Search (0)", "No Results" ) );
     }
 
 
     /**
      * Test for DIRSTUDIO-601.
      * (The 'Perform Search/Search Again' button in the Search Result Editor does not work correctly)
-     *
-     * @throws Exception
      */
-    @Test
-    public void testRefresh() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testRefresh( TestLdapServer server ) throws Exception
     {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system" );
+        connectionsViewBot.createTestConnection( server );
+        browserViewBot.selectEntry( path( GROUPS_DN ) );
         SearchDialogBot dialogBot = browserViewBot.openSearchDialog();
         assertTrue( dialogBot.isVisible() );
-        dialogBot.setSearchName( "Search Admin" );
-        dialogBot.setFilter( "(uid=admin)" );
-        dialogBot.setReturningAttributes( "objectClass, uid, description" );
+        dialogBot.setSearchName( "Search Group" );
+        dialogBot.setFilter( "(" + GROUP1_DN.getRdn().getName() + ")" );
+        dialogBot.setReturningAttributes( "objectClass, cn, description" );
         dialogBot.clickSearchButton();
-        browserViewBot.selectEntry( "Searches", "Search Admin" );
+        browserViewBot.selectEntry( "Searches", "Search Group" );
 
-        SearchResultEditorBot srEditorBot = studioBot.getSearchResultEditorBot( "Search Admin" );
+        SearchResultEditorBot srEditorBot = studioBot.getSearchResultEditorBot( "Search Group" );
         srEditorBot.activate();
         assertTrue( srEditorBot.isEnabled() );
 
         // assert that description attribute is empty
-        assertEquals( "uid=admin,ou=system", srEditorBot.getContent( 1, 1 ) );
+        assertEquals( GROUP1_DN.getName(), srEditorBot.getContent( 1, 1 ) );
         assertEquals( "", srEditorBot.getContent( 1, 4 ) );
 
         // add description
         ModifyRequest request = new ModifyRequestImpl();
-        request.setName( new Dn( "uid=admin,ou=system" ) );
+        request.setName( GROUP1_DN );
         request.replace( "description", "The 1st description." );
-        service.getAdminSession().modify( request );
+        server.withAdminConnection( conn -> {
+            conn.modify( request );
+        } );
 
         // refresh the search, using the toolbar icon
         srEditorBot.refresh();
         SWTUtils.sleep( 1000 );
 
         // assert the description attribute value is displayed now
-        assertEquals( "uid=admin,ou=system", srEditorBot.getContent( 1, 1 ) );
+        assertEquals( GROUP1_DN.getName(), srEditorBot.getContent( 1, 1 ) );
         assertEquals( "The 1st description.", srEditorBot.getContent( 1, 4 ) );
     }
 
 
-    @Test
-    public void testSearchAlias() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testSearchAlias( TestLdapServer server ) throws Exception
     {
+        connectionsViewBot.createTestConnection( server );
         String searchName = "Search Alias";
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system" );
+        browserViewBot.selectEntry( path( CONTEXT_DN ) );
         SearchDialogBot dialogBot = browserViewBot.openSearchDialog();
         assertTrue( dialogBot.isVisible() );
         dialogBot.setSearchName( searchName );
@@ -231,52 +257,58 @@
 
         // assert search result exists in tree
         browserViewBot.expandEntry( "Searches", "Search Alias" );
-        assertTrue( browserViewBot.existsEntry( "Searches", "Search Alias", "cn=alias,ou=special,ou=system" ) );
+        assertTrue( browserViewBot.existsEntry( "Searches", "Search Alias", ALIAS_DN.getName() ) );
 
         // assert attributes in search result editor
         browserViewBot.selectEntry( "Searches", "Search Alias" );
         SearchResultEditorBot srEditorBot = studioBot.getSearchResultEditorBot( "Search Alias" );
         srEditorBot.activate();
         assertTrue( srEditorBot.isEnabled() );
-        assertEquals( "cn=alias,ou=special,ou=system", srEditorBot.getContent( 1, 1 ) );
+        assertEquals( ALIAS_DN.getName(), srEditorBot.getContent( 1, 1 ) );
         assertEquals( "alias", srEditorBot.getContent( 1, 2 ) );
-        assertEquals( "ou=special,ou=system", srEditorBot.getContent( 1, 3 ) );
+        assertEquals( MISC_DN, srEditorBot.getContent( 1, 3 ) );
     }
 
 
-    @Test
-    public void testSearchReferral() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testSearchReferral( TestLdapServer server ) throws Exception
     {
+        connectionsViewBot.createTestConnection( server );
         String searchName = "Search Referral";
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system" );
+        browserViewBot.selectEntry( path( CONTEXT_DN ) );
         SearchDialogBot dialogBot = browserViewBot.openSearchDialog();
         assertTrue( dialogBot.isVisible() );
         dialogBot.setSearchName( searchName );
-        dialogBot.setFilter( "(objectClass=referral)" );
+        dialogBot.setFilter( "(&(objectClass=referral)(" + REFERRAL_TO_USER1_DN.getRdn().getName() + "))" );
         dialogBot.setReturningAttributes( "cn,ref" );
         dialogBot.setControlManageDsaIT( true );
         dialogBot.clickSearchButton();
 
         // assert search result exists in tree
         browserViewBot.expandEntry( "Searches", searchName );
-        assertTrue( browserViewBot.existsEntry( "Searches", searchName, "cn=referral,ou=special,ou=system" ) );
+        assertTrue(
+            browserViewBot.existsEntry( "Searches", searchName, Utils.shorten( REFERRAL_TO_USER1_DN.getName(), 50 ) ) );
 
         // assert attributes in search result editor
         browserViewBot.selectEntry( "Searches", searchName );
         SearchResultEditorBot srEditorBot = studioBot.getSearchResultEditorBot( searchName );
         srEditorBot.activate();
         assertTrue( srEditorBot.isEnabled() );
-        assertEquals( "cn=referral,ou=special,ou=system", srEditorBot.getContent( 1, 1 ) );
-        assertEquals( "referral", srEditorBot.getContent( 1, 2 ) );
-        assertEquals( "ldap://foo.example.com/ou=system", srEditorBot.getContent( 1, 3 ) );
+        assertEquals( REFERRAL_TO_USER1_DN.getName(), srEditorBot.getContent( 1, 1 ) );
+        assertEquals( REFERRAL_TO_USER1_DN.getRdn().getValue(), srEditorBot.getContent( 1, 2 ) );
+        assertEquals( StringUtils.abbreviate( server.getLdapUrl() + "/" + USER1_DN.getName(), 50 ),
+            srEditorBot.getContent( 1, 3 ) );
     }
 
 
-    @Test
-    public void testSearchSubentry() throws Exception
+    @ParameterizedTest
+    @LdapServersSource(only = LdapServerType.ApacheDS, reason = "ApacheDS specifc test")
+    public void testSearchSubentry( TestLdapServer server ) throws Exception
     {
+        connectionsViewBot.createTestConnection( server );
         String searchName = "Search Subentry";
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system" );
+        browserViewBot.selectEntry( path( CONTEXT_DN ) );
         SearchDialogBot dialogBot = browserViewBot.openSearchDialog();
         assertTrue( dialogBot.isVisible() );
         dialogBot.setSearchName( searchName );
@@ -287,30 +319,32 @@
 
         // assert search result exists in tree
         browserViewBot.expandEntry( "Searches", searchName );
-        assertTrue( browserViewBot.existsEntry( "Searches", searchName, "cn=subentry,ou=special,ou=system" ) );
+        assertTrue( browserViewBot.existsEntry( "Searches", searchName, SUBENTRY_DN.getName() ) );
 
         // assert attributes in search result editor
         browserViewBot.selectEntry( "Searches", searchName );
         SearchResultEditorBot srEditorBot = studioBot.getSearchResultEditorBot( searchName );
         srEditorBot.activate();
         assertTrue( srEditorBot.isEnabled() );
-        assertEquals( "cn=subentry,ou=special,ou=system", srEditorBot.getContent( 1, 1 ) );
-        assertEquals( "subentry", srEditorBot.getContent( 1, 2 ) );
-        assertEquals( "{ }", srEditorBot.getContent( 1, 3 ) );
+        assertEquals( SUBENTRY_DN.getName(), srEditorBot.getContent( 1, 1 ) );
+        assertEquals( SUBENTRY_DN.getRdn().getValue(), srEditorBot.getContent( 1, 2 ) );
+        assertEquals( "{}", srEditorBot.getContent( 1, 3 ) );
     }
 
 
-    @Test
-    public void testSearchWithPagingWithScrollMode() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testSearchWithPagingWithScrollMode( TestLdapServer server ) throws Exception
     {
+        connectionsViewBot.createTestConnection( server );
         String searchName = "Paged search with scroll mode";
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
+        browserViewBot.selectEntry( path( USERS_DN ) );
         SearchDialogBot dialogBot = browserViewBot.openSearchDialog();
         assertTrue( dialogBot.isVisible() );
         dialogBot.setSearchName( searchName );
         dialogBot.setFilter( "(objectClass=*)" );
         dialogBot.setReturningAttributes( "objectClass,ou,cn,uid" );
-        dialogBot.setControlPagedSearch( true, 5, true );
+        dialogBot.setControlPagedSearch( true, 3, true );
         dialogBot.clickSearchButton();
 
         // 1st page
@@ -335,25 +369,115 @@
     }
 
 
-    @Test
-    public void testSearchWithPagingWithoutScrollMode() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testSearchWithPagingWithoutScrollMode( TestLdapServer server ) throws Exception
     {
+        connectionsViewBot.createTestConnection( server );
         String searchName = "Paged search without scroll mode";
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "ou=users" );
+        browserViewBot.selectEntry( path( USERS_DN ) );
         SearchDialogBot dialogBot = browserViewBot.openSearchDialog();
         assertTrue( dialogBot.isVisible() );
         dialogBot.setSearchName( searchName );
         dialogBot.setFilter( "(objectClass=*)" );
         dialogBot.setReturningAttributes( "objectClass,ou,cn,uid" );
-        dialogBot.setControlPagedSearch( true, 5, false );
+        dialogBot.setControlPagedSearch( true, 3, false );
         dialogBot.clickSearchButton();
 
         browserViewBot.expandEntry( "Searches", searchName );
         assertFalse( browserViewBot.existsEntry( "Searches", searchName, "--- Top Page ---" ) );
         assertFalse( browserViewBot.existsEntry( "Searches", searchName, "--- Next Page ---" ) );
-        assertTrue( browserViewBot.existsEntry( "Searches", searchName + " (15+)" ) );
-        assertTrue( browserViewBot.existsEntry( "Searches", searchName, "uid=user.1" ) );
-        assertTrue( browserViewBot.existsEntry( "Searches", searchName, "uid=user.8" ) );
+        assertTrue( browserViewBot.existsEntry( "Searches", searchName + " (9+)" ) );
+        assertTrue( browserViewBot.existsEntry( "Searches", searchName, USER1_DN.getName() ) );
+        assertTrue( browserViewBot.existsEntry( "Searches", searchName, USER8_DN.getName() ) );
+    }
+
+
+    @ParameterizedTest
+    @LdapServersSource
+    public void testFilterEditor( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+        String searchName = "Test filter editor";
+        browserViewBot.selectEntry( path( USERS_DN ) );
+        SearchDialogBot dialogBot = browserViewBot.openSearchDialog();
+        assertTrue( dialogBot.isVisible() );
+        dialogBot.setSearchName( searchName );
+        dialogBot.setReturningAttributes( "objectClass,ou,cn,uid" );
+
+        FilterEditorDialogBot filterBot = dialogBot.openFilterEditor();
+        filterBot.setFilter( "(&(objectClass=*)(uid=user.1))" );
+        filterBot.clickFormatButton();
+        String formattetFilter = filterBot.getFilter();
+        filterBot.clickOkButton();
+        dialogBot.activate();
+        String filter = dialogBot.getFilter();
+        dialogBot.clickSearchButton();
+
+        browserViewBot.expandEntry( "Searches", searchName );
+        assertTrue( browserViewBot.existsEntry( "Searches", searchName, USER1_DN.getName() ) );
+        assertEquals( "(&(objectClass=*)(uid=user.1))", filter );
+        assertEquals( "(&\n    (objectClass=*)\n    (uid=user.1)\n)", formattetFilter );
+    }
+
+
+    /**
+     * Test for DIRSTUDIO-1078/DIRAPI-365: unable to use # pound hash sign in LDAP filters
+     */
+    @ParameterizedTest
+    @LdapServersSource
+    public void testFilterForDnWithLeadingHash( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+        String searchName = "Test filter for DN with leading hash character";
+        browserViewBot.selectEntry( path( CONTEXT_DN ) );
+        SearchDialogBot dialogBot = browserViewBot.openSearchDialog();
+        assertTrue( dialogBot.isVisible() );
+        dialogBot.setSearchName( searchName );
+        dialogBot.setReturningAttributes( "objectClass,ou,cn,uid" );
+
+        String filterValue = DN_WITH_LEADING_SHARP_BACKSLASH_PREFIXED.getName().replace( "\\#", "\\5c#" );
+        FilterEditorDialogBot filterBot = dialogBot.openFilterEditor();
+        filterBot.setFilter( "member=" + filterValue );
+        filterBot.clickFormatButton();
+        filterBot.clickOkButton();
+        dialogBot.activate();
+        String filter = dialogBot.getFilter();
+        dialogBot.clickSearchButton();
+
+        browserViewBot.expandEntry( "Searches", searchName );
+        assertTrue( browserViewBot.existsEntry( "Searches", searchName, GROUP1_DN.getName() ) );
+        assertEquals( "(member=" + filterValue + ")", filter );
+    }
+
+
+    /**
+     * Test for DIRSTUDIO-1078/DIRAPI-365: unable to use # pound hash sign in LDAP filters
+     */
+    @ParameterizedTest
+    @LdapServersSource
+    public void testFilterForDnWithLeadingHashHex( TestLdapServer server ) throws Exception
+    {
+        connectionsViewBot.createTestConnection( server );
+        String searchName = "Test filter for DN with leading hash character";
+        browserViewBot.selectEntry( path( CONTEXT_DN ) );
+        SearchDialogBot dialogBot = browserViewBot.openSearchDialog();
+        assertTrue( dialogBot.isVisible() );
+        dialogBot.setSearchName( searchName );
+        dialogBot.setReturningAttributes( "objectClass,ou,cn,uid" );
+
+        String filterValue = DN_WITH_LEADING_SHARP_HEX_PAIR_ESCAPED.getName().replace( "\\23", "\\5C23" );
+        FilterEditorDialogBot filterBot = dialogBot.openFilterEditor();
+        filterBot.setFilter( "member=" + filterValue );
+        filterBot.clickFormatButton();
+        filterBot.clickOkButton();
+        dialogBot.activate();
+        String filter = dialogBot.getFilter();
+        dialogBot.clickSearchButton();
+
+        browserViewBot.expandEntry( "Searches", searchName );
+        assertTrue( browserViewBot.existsEntry( "Searches", searchName, GROUP1_DN.getName() ) );
+        assertEquals( "(member=" + filterValue + ")", filter );
     }
 
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/SwtResourcesTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/SwtResourcesTest.java
index 75167ed..5a76bec 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/SwtResourcesTest.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/SwtResourcesTest.java
@@ -21,27 +21,19 @@
 package org.apache.directory.studio.test.integration.ui;
 
 
-import static org.junit.Assert.fail;
-import static org.junit.Assert.assertTrue;
+import static org.apache.directory.studio.test.integration.junit5.TestFixture.MISC_DN;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
 
-import org.apache.directory.server.annotations.CreateLdapServer;
-import org.apache.directory.server.annotations.CreateTransport;
-import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
-import org.apache.directory.studio.test.integration.ui.bots.BrowserViewBot;
-import org.apache.directory.studio.test.integration.ui.bots.ConnectionsViewBot;
+import org.apache.directory.studio.test.integration.junit5.LdapServersSource;
+import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
 import org.apache.directory.studio.test.integration.ui.bots.DeleteDialogBot;
 import org.apache.directory.studio.test.integration.ui.bots.NewEntryWizardBot;
-import org.apache.directory.studio.test.integration.ui.bots.StudioBot;
-import org.apache.directory.studio.test.integration.ui.bots.utils.Assertions;
-import org.apache.directory.studio.test.integration.ui.bots.utils.FrameworkRunnerWithScreenshotCaptureListener;
 import org.eclipse.swt.graphics.DeviceData;
 import org.eclipse.swtbot.swt.finder.SWTBot;
 import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable;
 import org.eclipse.swtbot.swt.finder.results.IntResult;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.params.ParameterizedTest;
 
 
 /**
@@ -50,47 +42,21 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-@RunWith(FrameworkRunnerWithScreenshotCaptureListener.class)
-@CreateLdapServer(transports =
-    { @CreateTransport(protocol = "LDAP") })
-public class SwtResourcesTest extends AbstractLdapTestUnit
+public class SwtResourcesTest extends AbstractTestBase
 {
-    private StudioBot studioBot;
-    private ConnectionsViewBot connectionsViewBot;
-    private BrowserViewBot browserViewBot;
-
-
-    @Before
-    public void setUp() throws Exception
-    {
-        studioBot = new StudioBot();
-        studioBot.resetLdapPerspective();
-        connectionsViewBot = studioBot.getConnectionView();
-        connectionsViewBot.createTestConnection( "SwtResourcesTest", ldapServer.getPort() );
-        browserViewBot = studioBot.getBrowserView();
-    }
-
-
-    @After
-    public void tearDown() throws Exception
-    {
-        connectionsViewBot.deleteTestConnections();
-        Assertions.genericTearDownAssertions();
-    }
-
 
     /**
      * Test for DIRSTUDIO-319.
      *
      * Creates multiple entries using the New Entry wizard. Checks that we don't
      * allocate too much SWT resources during the run.
-     *
-     * @throws Exception
-     *             the exception
      */
-    @Test
-    public void testSwtResourcesDelta() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testSwtResourcesDelta( TestLdapServer server ) throws Exception
     {
+        connectionsViewBot.createTestConnection( server );
+
         // run the new entry wizard once to ensure all SWT resources are created
         createAndDeleteEntry( "testSwtResourcesDelta" + 0 );
 
@@ -107,26 +73,24 @@
         int afterObjectCount = getSwtObjectCount();
 
         // we expect none or only very few additional SWT objects
-        assertTrue( "Too many SWT resources were allocated in testSwtResourcesDelta: before=" + beforeObjectCount
-            + ", after=" + afterObjectCount, afterObjectCount - beforeObjectCount < 5 );
+        assertTrue( afterObjectCount - beforeObjectCount < 5,
+            "Too many SWT resources were allocated in testSwtResourcesDelta: before=" + beforeObjectCount
+                + ", after=" + afterObjectCount );
     }
 
 
     /**
-     * Ensure that we have not allocated more the 1000 SWT resources during the
+     * Ensure that we have not allocated too many SWT resources during the
      * complete test suite.
-     *
-     * 1000 is not a fix number but it is a good starting point.
-     *
-     * @throws Exception
-     *             the exception
      */
-    @Test
-    public void testSwtResourcesCount() throws Exception
+    @ParameterizedTest
+    @LdapServersSource
+    public void testSwtResourcesCount( TestLdapServer server ) throws Exception
     {
+        connectionsViewBot.createTestConnection( server );
         int swtObjectCount = getSwtObjectCount();
-        System.out.println("### SWT resouces count: " + swtObjectCount);
-        assertTrue( "Too many SWT resources were allocated: " + swtObjectCount, swtObjectCount < 1000 );
+        System.out.println( "### SWT resouces count: " + swtObjectCount );
+        assertTrue( swtObjectCount < 1500, "Too many SWT resources were allocated: " + swtObjectCount );
     }
 
 
@@ -140,7 +104,8 @@
                 DeviceData info = bot.getDisplay().getDeviceData();
                 if ( !info.tracking )
                 {
-                    fail( "To run this test options 'org.eclipse.ui/debug' and 'org.eclipse.ui/trace/graphics' must be true." );
+                    fail(
+                        "To run this test options 'org.eclipse.ui/debug' and 'org.eclipse.ui/trace/graphics' must be true." );
                 }
                 return info.objects.length;
             }
@@ -150,8 +115,7 @@
 
     private void createAndDeleteEntry( final String name ) throws Exception
     {
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system" );
-        browserViewBot.expandEntry( "DIT", "Root DSE", "ou=system" );
+        browserViewBot.selectAndExpandEntry( path( MISC_DN ) );
         NewEntryWizardBot wizardBot = browserViewBot.openNewEntryWizard();
 
         wizardBot.selectCreateEntryFromScratch();
@@ -166,8 +130,8 @@
 
         wizardBot.clickFinishButton();
 
-        assertTrue( browserViewBot.existsEntry( "DIT", "Root DSE", "ou=system", "o=" + name ) );
-        browserViewBot.selectEntry( "DIT", "Root DSE", "ou=system", "o=" + name );
+        assertTrue( browserViewBot.existsEntry( path( MISC_DN, "o=" + name ) ) );
+        browserViewBot.selectEntry( path( MISC_DN, "o=" + name ) );
         DeleteDialogBot dialog = browserViewBot.openDeleteDialog();
         dialog.clickOkButton();
     }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ValueEditorTest.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ValueEditorTest.java
index 7aa245f..ac394d5 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ValueEditorTest.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ValueEditorTest.java
@@ -21,12 +21,13 @@
 package org.apache.directory.studio.test.integration.ui;
 
 
-import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.nio.charset.StandardCharsets.ISO_8859_1;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import java.nio.charset.StandardCharsets;
+import java.util.stream.Stream;
 
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.studio.ldapbrowser.core.model.IAttribute;
@@ -43,12 +44,9 @@
 import org.apache.directory.studio.valueeditors.TextValueEditor;
 import org.apache.directory.studio.valueeditors.bool.InPlaceBooleanValueEditor;
 import org.apache.directory.studio.valueeditors.oid.InPlaceOidValueEditor;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
-import org.junit.runners.Parameterized.Parameters;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
 
 /**
@@ -56,8 +54,7 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-@RunWith(Parameterized.class)
-public class ValueEditorTest
+public class ValueEditorTest extends AbstractTestBase
 {
 
     private static final String CN = "cn";
@@ -79,50 +76,55 @@
     private static final String NUMERIC_OID = "1.3.6.1.4.1.1466.20037";
     private static final String DESCR_OID = "a-zA-Z0-9";
 
-
-    @Parameters(name = "{0}")
-    public static Object[] data()
+    public static Stream<Arguments> data()
     {
-        return new Object[][]
+        return Stream.of( new Object[][]
             {
                 /*
                  * InPlaceTextValueEditor can handle string values and binary values that can be decoded as UTF-8.
                  */
 
-                { "InPlaceTextValueEditor - empty value",
+                {
+                    "InPlaceTextValueEditor - empty value",
                     Data.data().valueEditorClass( InPlaceTextValueEditor.class ).attribute( CN )
                         .rawValue( IValue.EMPTY_STRING_VALUE ).expectedRawValue( EMPTY_STRING )
                         .expectedDisplayValue( EMPTY_STRING ).expectedHasValue( true )
                         .expectedStringOrBinaryValue( EMPTY_STRING ) },
 
-                { "InPlaceTextValueEditor - empty string",
+                {
+                    "InPlaceTextValueEditor - empty string",
                     Data.data().valueEditorClass( InPlaceTextValueEditor.class ).attribute( CN )
                         .rawValue( EMPTY_STRING ).expectedRawValue( EMPTY_STRING ).expectedDisplayValue( EMPTY_STRING )
                         .expectedHasValue( true ).expectedStringOrBinaryValue( EMPTY_STRING ) },
 
-                { "InPlaceTextValueEditor - ascii",
+                {
+                    "InPlaceTextValueEditor - ascii",
                     Data.data().valueEditorClass( InPlaceTextValueEditor.class ).attribute( CN ).rawValue( ASCII )
                         .expectedRawValue( ASCII ).expectedDisplayValue( ASCII ).expectedHasValue( true )
                         .expectedStringOrBinaryValue( ASCII ) },
 
-                { "InPlaceTextValueEditor - unicode",
+                {
+                    "InPlaceTextValueEditor - unicode",
                     Data.data().valueEditorClass( InPlaceTextValueEditor.class ).attribute( CN ).rawValue( UNICODE )
                         .expectedRawValue( UNICODE ).expectedDisplayValue( UNICODE ).expectedHasValue( true )
                         .expectedStringOrBinaryValue( UNICODE ) },
 
-                { "InPlaceTextValueEditor - bytearray UTF8",
+                {
+                    "InPlaceTextValueEditor - bytearray UTF8",
                     Data.data().valueEditorClass( InPlaceTextValueEditor.class ).attribute( USER_PWD ).rawValue( UTF8 )
                         .expectedRawValue( UNICODE ).expectedDisplayValue( UNICODE ).expectedHasValue( true )
                         .expectedStringOrBinaryValue( UNICODE ) },
 
                 // text editor always tries to decode byte[] as UTF-8, so it can not handle ISO-8859-1 encoded byte[] 
-                { "InPlaceTextValueEditor - bytearray ISO-8859-1",
+                {
+                    "InPlaceTextValueEditor - bytearray ISO-8859-1",
                     Data.data().valueEditorClass( InPlaceTextValueEditor.class ).attribute( USER_PWD )
                         .rawValue( ISO88591 ).expectedRawValue( null ).expectedDisplayValue( IValueEditor.NULL )
                         .expectedHasValue( true ).expectedStringOrBinaryValue( null ) },
 
                 // text editor always tries to decode byte[] as UTF-8, so it can not handle arbitrary byte[] 
-                { "InPlaceTextValueEditor - bytearray PNG",
+                {
+                    "InPlaceTextValueEditor - bytearray PNG",
                     Data.data().valueEditorClass( InPlaceTextValueEditor.class ).attribute( USER_PWD ).rawValue( PNG )
                         .expectedRawValue( null ).expectedDisplayValue( IValueEditor.NULL ).expectedHasValue( true )
                         .expectedStringOrBinaryValue( null ) },
@@ -131,32 +133,38 @@
                  * InPlaceBooleanValueEditor can only handle TRUE or FALSE values.
                  */
 
-                { "InPlaceBooleanValueEditor - TRUE",
+                {
+                    "InPlaceBooleanValueEditor - TRUE",
                     Data.data().valueEditorClass( InPlaceBooleanValueEditor.class ).attribute( CN ).rawValue( TRUE )
                         .expectedRawValue( TRUE ).expectedDisplayValue( TRUE ).expectedHasValue( true )
                         .expectedStringOrBinaryValue( TRUE ) },
 
-                { "InPlaceBooleanValueEditor - FALSE",
+                {
+                    "InPlaceBooleanValueEditor - FALSE",
                     Data.data().valueEditorClass( InPlaceBooleanValueEditor.class ).attribute( CN ).rawValue( FALSE )
                         .expectedRawValue( FALSE ).expectedDisplayValue( FALSE ).expectedHasValue( true )
                         .expectedStringOrBinaryValue( FALSE ) },
 
-                { "InPlaceBooleanValueEditor - INVALID",
+                {
+                    "InPlaceBooleanValueEditor - INVALID",
                     Data.data().valueEditorClass( InPlaceBooleanValueEditor.class ).attribute( CN )
                         .rawValue( "invalid" ).expectedRawValue( null ).expectedDisplayValue( IValueEditor.NULL )
                         .expectedHasValue( true ).expectedStringOrBinaryValue( null ) },
 
-                { "InPlaceBooleanValueEditor - bytearray TRUE",
+                {
+                    "InPlaceBooleanValueEditor - bytearray TRUE",
                     Data.data().valueEditorClass( InPlaceBooleanValueEditor.class ).attribute( USER_PWD )
                         .rawValue( TRUE.getBytes( UTF_8 ) ).expectedRawValue( TRUE ).expectedDisplayValue( TRUE )
                         .expectedHasValue( true ).expectedStringOrBinaryValue( TRUE ) },
 
-                { "InPlaceBooleanValueEditor - bytearray FALSE",
+                {
+                    "InPlaceBooleanValueEditor - bytearray FALSE",
                     Data.data().valueEditorClass( InPlaceBooleanValueEditor.class ).attribute( USER_PWD )
                         .rawValue( FALSE.getBytes( UTF_8 ) ).expectedRawValue( FALSE ).expectedDisplayValue( FALSE )
                         .expectedHasValue( true ).expectedStringOrBinaryValue( FALSE ) },
 
-                { "InPlaceBooleanValueEditor - bytearray INVALID",
+                {
+                    "InPlaceBooleanValueEditor - bytearray INVALID",
                     Data.data().valueEditorClass( InPlaceBooleanValueEditor.class ).attribute( USER_PWD )
                         .rawValue( "invalid".getBytes( UTF_8 ) ).expectedRawValue( null )
                         .expectedDisplayValue( IValueEditor.NULL ).expectedHasValue( true )
@@ -166,28 +174,40 @@
                  * InPlaceOidValueEditor can only handle OIDs
                  */
 
-                { "InPlaceOidValueEditor - numeric OID",
+                {
+                    "InPlaceOidValueEditor - numeric OID",
                     Data.data().valueEditorClass( InPlaceOidValueEditor.class ).attribute( CN ).rawValue( NUMERIC_OID )
                         .expectedRawValue( NUMERIC_OID ).expectedDisplayValue( NUMERIC_OID + " (Start TLS)" )
                         .expectedHasValue( true ).expectedStringOrBinaryValue( NUMERIC_OID ) },
 
-                { "InPlaceOidValueEditor - descr OID",
+                {
+                    "InPlaceOidValueEditor - descr OID",
                     Data.data().valueEditorClass( InPlaceOidValueEditor.class ).attribute( CN ).rawValue( DESCR_OID )
                         .expectedRawValue( DESCR_OID ).expectedDisplayValue( DESCR_OID ).expectedHasValue( true )
                         .expectedStringOrBinaryValue( DESCR_OID ) },
 
-                { "InPlaceOidValueEditor - INVALID",
+                {
+                    "InPlaceOidValueEditor - relaxed descr OID",
+                    Data.data().valueEditorClass( InPlaceOidValueEditor.class ).attribute( CN )
+                        .rawValue( "orclDBEnterpriseRole_82" ).expectedRawValue( "orclDBEnterpriseRole_82" )
+                        .expectedDisplayValue( "orclDBEnterpriseRole_82" ).expectedHasValue( true )
+                        .expectedStringOrBinaryValue( "orclDBEnterpriseRole_82" ) },
+
+                {
+                    "InPlaceOidValueEditor - INVALID",
                     Data.data().valueEditorClass( InPlaceOidValueEditor.class ).attribute( CN ).rawValue( "in valid" )
                         .expectedRawValue( null ).expectedDisplayValue( IValueEditor.NULL ).expectedHasValue( true )
                         .expectedStringOrBinaryValue( null ) },
 
-                { "InPlaceOidValueEditor - bytearray numeric OID",
+                {
+                    "InPlaceOidValueEditor - bytearray numeric OID",
                     Data.data().valueEditorClass( InPlaceOidValueEditor.class ).attribute( USER_PWD )
                         .rawValue( NUMERIC_OID.getBytes( UTF_8 ) ).expectedRawValue( NUMERIC_OID )
                         .expectedDisplayValue( NUMERIC_OID + " (Start TLS)" ).expectedHasValue( true )
                         .expectedStringOrBinaryValue( NUMERIC_OID ) },
 
-                { "InPlaceOidValueEditor - bytearray INVALID",
+                {
+                    "InPlaceOidValueEditor - bytearray INVALID",
                     Data.data().valueEditorClass( InPlaceOidValueEditor.class ).attribute( USER_PWD )
                         .rawValue( "in valid".getBytes( UTF_8 ) ).expectedRawValue( null )
                         .expectedDisplayValue( IValueEditor.NULL ).expectedHasValue( true )
@@ -197,51 +217,60 @@
                  * TextValueEditor can handle string values and binary values that can be decoded as UTF-8.
                  */
 
-                { "TextValueEditor - empty string value",
+                {
+                    "TextValueEditor - empty string value",
                     Data.data().valueEditorClass( TextValueEditor.class ).attribute( CN )
                         .rawValue( IValue.EMPTY_STRING_VALUE ).expectedRawValue( EMPTY_STRING )
                         .expectedDisplayValue( EMPTY_STRING ).expectedHasValue( true )
                         .expectedStringOrBinaryValue( EMPTY_STRING ) },
 
-                { "TextValueEditor - empty string",
+                {
+                    "TextValueEditor - empty string",
                     Data.data().valueEditorClass( TextValueEditor.class ).attribute( CN ).rawValue( EMPTY_STRING )
                         .expectedRawValue( EMPTY_STRING ).expectedDisplayValue( EMPTY_STRING ).expectedHasValue( true )
                         .expectedStringOrBinaryValue( EMPTY_STRING ) },
 
-                { "TextValueEditor - ascii",
+                {
+                    "TextValueEditor - ascii",
                     Data.data().valueEditorClass( TextValueEditor.class ).attribute( CN ).rawValue( ASCII )
                         .expectedRawValue( ASCII ).expectedDisplayValue( ASCII ).expectedHasValue( true )
                         .expectedStringOrBinaryValue( ASCII ) },
 
-                { "TextValueEditor - unicode",
+                {
+                    "TextValueEditor - unicode",
                     Data.data().valueEditorClass( TextValueEditor.class ).attribute( CN ).rawValue( UNICODE )
                         .expectedRawValue( UNICODE ).expectedDisplayValue( UNICODE ).expectedHasValue( true )
                         .expectedStringOrBinaryValue( UNICODE ) },
 
-                { "TextValueEditor - empty binary value",
+                {
+                    "TextValueEditor - empty binary value",
                     Data.data().valueEditorClass( TextValueEditor.class ).attribute( USER_PWD )
                         .rawValue( IValue.EMPTY_BINARY_VALUE ).expectedRawValue( EMPTY_STRING )
                         .expectedDisplayValue( EMPTY_STRING ).expectedHasValue( true )
                         .expectedStringOrBinaryValue( EMPTY_STRING ) },
 
-                { "TextValueEditor - empty bytearray",
+                {
+                    "TextValueEditor - empty bytearray",
                     Data.data().valueEditorClass( TextValueEditor.class ).attribute( USER_PWD ).rawValue( EMPTY_BYTES )
                         .expectedRawValue( EMPTY_STRING ).expectedDisplayValue( EMPTY_STRING ).expectedHasValue( true )
                         .expectedStringOrBinaryValue( EMPTY_STRING ) },
 
-                { "TextValueEditor - bytearray UTF8",
+                {
+                    "TextValueEditor - bytearray UTF8",
                     Data.data().valueEditorClass( TextValueEditor.class ).attribute( USER_PWD ).rawValue( UTF8 )
                         .expectedRawValue( UNICODE ).expectedDisplayValue( UNICODE ).expectedHasValue( true )
                         .expectedStringOrBinaryValue( UNICODE ) },
 
                 // text editor always tries to decode byte[] as UTF-8, so it can not handle ISO-8859-1 encoded byte[] 
-                { "TextValueEditor - bytearray ISO-8859-1",
+                {
+                    "TextValueEditor - bytearray ISO-8859-1",
                     Data.data().valueEditorClass( TextValueEditor.class ).attribute( USER_PWD ).rawValue( ISO88591 )
                         .expectedRawValue( null ).expectedDisplayValue( IValueEditor.NULL ).expectedHasValue( true )
                         .expectedStringOrBinaryValue( null ) },
 
                 // text editor always tries to decode byte[] as UTF-8, so it can not handle arbitrary byte[]
-                { "TextValueEditor - bytearray PNG",
+                {
+                    "TextValueEditor - bytearray PNG",
                     Data.data().valueEditorClass( InPlaceTextValueEditor.class ).attribute( USER_PWD ).rawValue( PNG )
                         .expectedRawValue( null ).expectedDisplayValue( IValueEditor.NULL ).expectedHasValue( true )
                         .expectedStringOrBinaryValue( null ) },
@@ -250,65 +279,64 @@
                  * HexValueEditor can handle all string or binary values.
                  */
 
-                { "HexValueEditor - empty string value",
+                {
+                    "HexValueEditor - empty string value",
                     Data.data().valueEditorClass( HexValueEditor.class ).attribute( CN )
                         .rawValue( IValue.EMPTY_STRING_VALUE ).expectedRawValue( EMPTY_BYTES )
                         .expectedDisplayValue( "Binary Data (0 Bytes)" ).expectedHasValue( true )
                         .expectedStringOrBinaryValue( EMPTY_BYTES ) },
 
-                { "HexValueEditor - empty string",
+                {
+                    "HexValueEditor - empty string",
                     Data.data().valueEditorClass( HexValueEditor.class ).attribute( CN ).rawValue( EMPTY_STRING )
                         .expectedRawValue( EMPTY_BYTES ).expectedDisplayValue( "Binary Data (0 Bytes)" )
                         .expectedHasValue( true ).expectedStringOrBinaryValue( EMPTY_BYTES ) },
 
-                { "HexValueEditor - ascii",
+                {
+                    "HexValueEditor - ascii",
                     Data.data().valueEditorClass( HexValueEditor.class ).attribute( CN ).rawValue( ASCII )
                         .expectedRawValue( ASCII.getBytes( StandardCharsets.US_ASCII ) )
                         .expectedDisplayValue( "Binary Data (9 Bytes)" ).expectedHasValue( true )
                         .expectedStringOrBinaryValue( ASCII.getBytes( StandardCharsets.US_ASCII ) ) },
 
-                { "HexValueEditor - empty binary value",
+                {
+                    "HexValueEditor - empty binary value",
                     Data.data().valueEditorClass( HexValueEditor.class ).attribute( USER_PWD )
                         .rawValue( IValue.EMPTY_BINARY_VALUE ).expectedRawValue( EMPTY_BYTES )
                         .expectedDisplayValue( "Binary Data (0 Bytes)" ).expectedHasValue( true )
                         .expectedStringOrBinaryValue( EMPTY_BYTES ) },
 
-                { "HexValueEditor - empty bytearray",
+                {
+                    "HexValueEditor - empty bytearray",
                     Data.data().valueEditorClass( HexValueEditor.class ).attribute( USER_PWD ).rawValue( EMPTY_BYTES )
                         .expectedRawValue( EMPTY_BYTES ).expectedDisplayValue( "Binary Data (0 Bytes)" )
                         .expectedHasValue( true ).expectedStringOrBinaryValue( EMPTY_BYTES ) },
 
-                { "HexValueEditor - bytearray UTF8",
+                {
+                    "HexValueEditor - bytearray UTF8",
                     Data.data().valueEditorClass( HexValueEditor.class ).attribute( USER_PWD ).rawValue( UTF8 )
                         .expectedRawValue( UTF8 ).expectedDisplayValue( "Binary Data (30 Bytes)" )
                         .expectedHasValue( true ).expectedStringOrBinaryValue( UTF8 ) },
 
-                { "HexValueEditor - bytearray ISO-8859-1",
+                {
+                    "HexValueEditor - bytearray ISO-8859-1",
                     Data.data().valueEditorClass( HexValueEditor.class ).attribute( USER_PWD ).rawValue( ISO88591 )
                         .expectedRawValue( ISO88591 ).expectedDisplayValue( "Binary Data (4 Bytes)" )
                         .expectedHasValue( true ).expectedStringOrBinaryValue( ISO88591 ) },
 
-                { "HexValueEditor - bytearray PNG",
+                {
+                    "HexValueEditor - bytearray PNG",
                     Data.data().valueEditorClass( HexValueEditor.class ).attribute( USER_PWD ).rawValue( PNG )
                         .expectedRawValue( PNG ).expectedDisplayValue( "Binary Data (4 Bytes)" )
                         .expectedHasValue( true ).expectedStringOrBinaryValue( PNG ) },
-
-            };
+            } ).map( d -> Arguments.arguments( ( String ) d[0], ( Data ) d[1] ) );
     }
 
-    @Parameter(value = 0)
-    public String name;
-
-    @Parameter(value = 1)
-    public Data data;
-
     private IValue value;
 
     private IValueEditor editor;
 
-
-    @Before
-    public void setup() throws Exception
+    public void setup( String name, Data data ) throws Exception
     {
         IEntry entry = new DummyEntry( new Dn(), new DummyConnection( Schema.DEFAULT_SCHEMA ) );
         IAttribute attribute = new Attribute( entry, data.attribute );
@@ -317,9 +345,11 @@
     }
 
 
-    @Test
-    public void testGetRawValue()
+    @ParameterizedTest
+    @MethodSource("data")
+    public void testGetRawValue( String name, Data data ) throws Exception
     {
+        setup( name, data );
         if ( data.expectedRawValue instanceof byte[] )
         {
             assertArrayEquals( ( byte[] ) data.expectedRawValue, ( byte[] ) editor.getRawValue( value ) );
@@ -331,23 +361,29 @@
     }
 
 
-    @Test
-    public void testGetDisplayValue()
+    @ParameterizedTest
+    @MethodSource("data")
+    public void testGetDisplayValue( String name, Data data ) throws Exception
     {
+        setup( name, data );
         assertEquals( data.expectedDisplayValue, editor.getDisplayValue( value ) );
     }
 
 
-    @Test
-    public void testHasValue()
+    @ParameterizedTest
+    @MethodSource("data")
+    public void testHasValue( String name, Data data ) throws Exception
     {
+        setup( name, data );
         assertEquals( data.expectedHasValue, editor.hasValue( value ) );
     }
 
 
-    @Test
-    public void testGetStringOrBinaryValue()
+    @ParameterizedTest
+    @MethodSource("data")
+    public void testGetStringOrBinaryValue( String name, Data data ) throws Exception
     {
+        setup( name, data );
         if ( data.expectedStringOrBinaryValue instanceof byte[] )
         {
             assertArrayEquals( ( byte[] ) data.expectedStringOrBinaryValue,
@@ -376,7 +412,6 @@
 
         public Object expectedStringOrBinaryValue;
 
-
         public static Data data()
         {
             return new Data();
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/AbstractLogsViewBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/AbstractLogsViewBot.java
index 138809e..c25a4cb 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/AbstractLogsViewBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/AbstractLogsViewBot.java
@@ -20,6 +20,7 @@
 package org.apache.directory.studio.test.integration.ui.bots;
 
 
+import org.apache.commons.lang3.StringUtils;
 import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
 import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView;
 import org.eclipse.swtbot.swt.finder.waits.DefaultCondition;
@@ -29,8 +30,7 @@
 public class AbstractLogsViewBot
 {
 
-    private SWTBotView view;
-
+    protected SWTBotView view;
 
     public AbstractLogsViewBot( String title )
     {
@@ -64,7 +64,7 @@
                 {
                     refreshButton.click();
                 }
-                return view.bot().styledText().getText().contains( text );
+                return StringUtils.containsIgnoreCase( view.bot().styledText().getText(), text );
             }
 
 
@@ -76,4 +76,43 @@
 
         } );
     }
+
+
+    public void clear()
+    {
+        view.show();
+        view.toolbarPushButton( "Clear" ).click();
+        new DialogBot( "Delete" )
+        {
+        }.clickOkButton();
+    }
+
+
+    public boolean isOlderButtonEnabled()
+    {
+        view.show();
+        return view.toolbarPushButton( "Older" ).isEnabled();
+    }
+
+
+    public void clickOlderButton()
+    {
+        view.show();
+        view.toolbarPushButton( "Older" ).click();
+    }
+
+
+    public boolean isNewerButtonEnabled()
+    {
+        view.show();
+        return view.toolbarPushButton( "Newer" ).isEnabled();
+    }
+
+
+    public void clickNewerButton()
+    {
+        view.show();
+        view.toolbarPushButton( "Newer" ).click();
+    }
+
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/AciItemEditorDialogBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/AciItemEditorDialogBot.java
new file mode 100644
index 0000000..2b85df1
--- /dev/null
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/AciItemEditorDialogBot.java
@@ -0,0 +1,332 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.studio.test.integration.ui.bots;
+
+
+import org.apache.directory.api.ldap.model.constants.AuthenticationLevel;
+import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
+
+
+public class AciItemEditorDialogBot extends DialogBot
+{
+
+    public AciItemEditorDialogBot()
+    {
+        super( "ACI Item Editor" );
+        super.setWaitAfterClickOkButton( true, BrowserCoreMessages.jobs__execute_ldif_name );
+    }
+
+
+    public void activateVisualEditorTab()
+    {
+        bot.tabItem( "Visual Editor" ).activate();
+    }
+
+
+    public void setIdentificationTag( String identificationTag )
+    {
+        bot.textWithLabel( "Identification Tag:" ).setText( identificationTag );
+    }
+
+
+    public void setPrecedence( int precedence )
+    {
+        bot.spinnerWithLabel( "Precedence:" ).setSelection( precedence );
+    }
+
+
+    public void setAuthenticationLevel( AuthenticationLevel authenticationLevel )
+    {
+        bot.comboBoxWithLabel( "Authentication Level:" ).setSelection( authenticationLevel.getName() );
+    }
+
+
+    public void setUserFirst()
+    {
+        bot.radio( "User First" ).click();
+    }
+
+
+    public void setItemFirst()
+    {
+        bot.radio( "Item First" ).click();
+    }
+
+
+    public void enableUserClassAllUsers()
+    {
+        bot.table().getTableItem( 0 ).check();
+    }
+
+
+    public void disableUserClassAllUsers()
+    {
+        bot.table().getTableItem( 0 ).uncheck();
+    }
+
+
+    public void enableUserClassThisEntry()
+    {
+        bot.table().getTableItem( 1 ).check();
+    }
+
+
+    public void disableUserClassThisEntry()
+    {
+        bot.table().getTableItem( 1 ).uncheck();
+    }
+
+
+    public void enableUserClassParentOfEntry()
+    {
+        bot.table().getTableItem( 2 ).check();
+    }
+
+
+    public void disableUserClassParentOfEntry()
+    {
+        bot.table().getTableItem( 2 ).uncheck();
+    }
+
+
+    public void enableUserClassName()
+    {
+        bot.table().getTableItem( 3 ).check();
+    }
+
+
+    public void disableUserClassName()
+    {
+        bot.table().getTableItem( 3 ).uncheck();
+    }
+
+
+    public void enableUserClassUserGroup()
+    {
+        bot.table().getTableItem( 4 ).check();
+    }
+
+
+    public void disableUserClassUserGroup()
+    {
+        bot.table().getTableItem( 4 ).uncheck();
+    }
+
+
+    public void enableUserClassSubtree()
+    {
+        bot.table().getTableItem( 5 ).check();
+    }
+
+
+    public void disableUserClassSubtree()
+    {
+        bot.table().getTableItem( 5 ).uncheck();
+    }
+
+
+    public void enableProtectedItemEntry()
+    {
+        bot.table().getTableItem( 0 ).check();
+    }
+
+
+    public void disableProtectedItemEntry()
+    {
+        bot.table().getTableItem( 0 ).uncheck();
+    }
+
+
+    public void enableProtectedItemAllUserAttributeTypes()
+    {
+        bot.table().getTableItem( 1 ).check();
+    }
+
+
+    public void disableProtectedItemAllUserAttributeTypes()
+    {
+        bot.table().getTableItem( 1 ).uncheck();
+    }
+
+
+    public void enableProtectedItemAttributeType()
+    {
+        bot.table().getTableItem( 2 ).check();
+    }
+
+
+    public void disableProtectedItemAttributeType()
+    {
+        bot.table().getTableItem( 2 ).uncheck();
+    }
+
+
+    public void enableProtectedItemAllAttributeValues()
+    {
+        bot.table().getTableItem( 3 ).check();
+    }
+
+
+    public void disableProtectedItemAllAttributeValues()
+    {
+        bot.table().getTableItem( 3 ).uncheck();
+    }
+
+
+    public void enableProtectedItemAllUserAttributeTypesAndValues()
+    {
+        bot.table().getTableItem( 4 ).check();
+    }
+
+
+    public void disableProtectedItemAllUserAttributeTypesAndValues()
+    {
+        bot.table().getTableItem( 4 ).uncheck();
+    }
+
+
+    public void enableProtectedItemAttributeValues()
+    {
+        bot.table().getTableItem( 5 ).check();
+    }
+
+
+    public void disableProtectedItemAttributeValues()
+    {
+        bot.table().getTableItem( 5 ).uncheck();
+    }
+
+
+    public void enableProtectedItemSelfValue()
+    {
+        bot.table().getTableItem( 6 ).check();
+    }
+
+
+    public void disableProtectedItemSelfValue()
+    {
+        bot.table().getTableItem( 6 ).uncheck();
+    }
+
+
+    public void enableProtectedItemRangeOfValues()
+    {
+        bot.table().getTableItem( 7 ).check();
+    }
+
+
+    public void disableProtectedItemRangeOfValues()
+    {
+        bot.table().getTableItem( 7 ).uncheck();
+    }
+
+
+    public void enableProtectedItemMaxValueCount()
+    {
+        bot.table().getTableItem( 8 ).check();
+    }
+
+
+    public void disableProtectedItemMaxValueCount()
+    {
+        bot.table().getTableItem( 8 ).uncheck();
+    }
+
+
+    public void enableProtectedItemMaxNumberOfImmediateSubordinates()
+    {
+        bot.table().getTableItem( 9 ).check();
+    }
+
+
+    public void disableProtectedItemMaxNumberOfImmediateSubordinates()
+    {
+        bot.table().getTableItem( 9 ).uncheck();
+    }
+
+
+    public void enableProtectedItemRestrictedBy()
+    {
+        bot.table().getTableItem( 10 ).check();
+    }
+
+
+    public void disableProtectedItemRestrictedBy()
+    {
+        bot.table().getTableItem( 10 ).uncheck();
+    }
+
+
+    public void enableProtectedItemClasses()
+    {
+        bot.table().getTableItem( 11 ).check();
+    }
+
+
+    public void disableProtectedItemClasses()
+    {
+        bot.table().getTableItem( 11 ).uncheck();
+    }
+
+
+    public void activateSourceTab()
+    {
+        bot.tabItem( "Source" ).activate();
+    }
+
+
+    public void setSource( String source )
+    {
+        bot.styledText().setText( source );
+    }
+
+
+    public String getSource()
+    {
+        return bot.styledText().getText();
+    }
+
+
+    public void clickFormatButton()
+    {
+        super.clickButton( "Format" );
+    }
+
+
+    public void clickCheckSyntaxButtonOk()
+    {
+        super.clickButton( "Check Syntax" );
+        new DialogBot( "Syntax ok" )
+        {
+        }.clickOkButton();
+        activate();
+    }
+
+
+    public void clickCheckSyntaxButtonError()
+    {
+        String shellText = BotUtils.shell( () -> super.clickButton( "Check Syntax" ), "Syntax Error" ).getText();
+        new DialogBot( shellText )
+        {
+        }.clickOkButton();
+        activate();
+    }
+
+}
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ApacheDSConfigurationEditorBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ApacheDSConfigurationEditorBot.java
index 8bf6103..ac58dc2 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ApacheDSConfigurationEditorBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ApacheDSConfigurationEditorBot.java
@@ -21,7 +21,7 @@
 
 
 import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
-import org.apache.directory.studio.test.integration.ui.bots.utils.JobWatcher;
+import org.apache.directory.studio.test.integration.ui.utils.JobWatcher;
 import org.apache.mina.util.AvailablePortFinder;
 import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
 import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotMultiPageEditor;
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ApacheDSServersViewBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ApacheDSServersViewBot.java
index e1171ee..c516c1c 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ApacheDSServersViewBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ApacheDSServersViewBot.java
@@ -25,7 +25,7 @@
 import org.apache.directory.studio.ldapservers.LdapServersManager;
 import org.apache.directory.studio.ldapservers.model.LdapServer;
 import org.apache.directory.studio.ldapservers.model.LdapServerStatus;
-import org.apache.directory.studio.test.integration.ui.ContextMenuHelper;
+import org.apache.directory.studio.test.integration.ui.utils.ContextMenuHelper;
 import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
 import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView;
 import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences;
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/BotUtils.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/BotUtils.java
index b4cf48f..93d01b2 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/BotUtils.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/BotUtils.java
@@ -24,7 +24,6 @@
 import java.util.List;
 
 import org.apache.directory.ldap.client.api.LdapConnectionConfig;
-import org.apache.directory.ldap.client.api.LdapNetworkConnection;
 import org.eclipse.jface.dialogs.ErrorDialog;
 import org.eclipse.swtbot.swt.finder.SWTBot;
 import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences;
@@ -56,15 +55,7 @@
             {
                 public boolean test() throws Exception
                 {
-                    String shellText = bot.activeShell().getText();
-                    for ( String label : labels )
-                    {
-                        if ( shellText.equals( label ) && bot.button( "OK" ) != null )
-                        {
-                            return true;
-                        }
-                    }
-                    return false;
+                    return getShell( labels ) != null;
                 }
 
 
@@ -81,7 +72,28 @@
             ErrorDialog.AUTOMATED_MODE = errorDialogAutomatedMode;
         }
 
-        return bot.activeShell();
+        return getShell( labels );
+    }
+
+
+    private static SWTBotShell getShell( final String... labels )
+    {
+        SWTBotShell[] shells = bot.shells();
+        for ( SWTBotShell shell : shells )
+        {
+            String shellText = shell.getText();
+            for ( String label : labels )
+            {
+                if ( shellText.equals( label ) )
+                {
+                    shell.activate();
+                    if( bot.button( "OK" ) != null) {
+                        return shell;
+                    }
+                }
+            }
+        }
+        return null;
     }
 
 
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/BrowserViewBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/BrowserViewBot.java
index 2fb4712..13792d5 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/BrowserViewBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/BrowserViewBot.java
@@ -21,8 +21,8 @@
 
 
 import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
-import org.apache.directory.studio.test.integration.ui.ContextMenuHelper;
-import org.apache.directory.studio.test.integration.ui.bots.utils.JobWatcher;
+import org.apache.directory.studio.test.integration.ui.utils.ContextMenuHelper;
+import org.apache.directory.studio.test.integration.ui.utils.JobWatcher;
 import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
 import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView;
 
@@ -32,7 +32,6 @@
     private SWTWorkbenchBot bot;
     private BrowserWidgetBot browserBot;
 
-
     public BrowserViewBot()
     {
         bot = new SWTWorkbenchBot();
@@ -57,7 +56,8 @@
 
     public void selectEntry( String... path )
     {
-        boolean wait = !"Quick Search".equals( path[path.length - 1] )
+        boolean wait = !path[path.length - 1].startsWith( "Quick Search" )
+            && !path[path.length - 1].equals( "No Results" )
             && !"Searches".equals( path[0] );
         browserBot.selectEntry( wait, path );
     }
@@ -75,6 +75,13 @@
     }
 
 
+    public void selectAndExpandEntry( String... path )
+    {
+        selectEntry( path );
+        expandEntry( path );
+    }
+
+
     public void expandEntry( String... path )
     {
         browserBot.expandEntry( path );
@@ -210,7 +217,6 @@
             JobWatcher watcher = new JobWatcher( BrowserCoreMessages.jobs__copy_entries_name_1 );
             ContextMenuHelper.clickContextMenu( browserBot.getTree(), "Paste" );
             watcher.waitUntilDone();
-
         }
     }
 
@@ -229,10 +235,10 @@
     }
 
 
-    public SearchPropertiesDialogBot pasteSearch()
+    public SearchPropertiesDialogBot pasteSearch( String searchName )
     {
         ContextMenuHelper.clickContextMenu( browserBot.getTree(), "Paste" );
-        return new SearchPropertiesDialogBot();
+        return new SearchPropertiesDialogBot( searchName );
     }
 
 
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/BrowserWidgetBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/BrowserWidgetBot.java
index 37891b0..7fa0aa8 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/BrowserWidgetBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/BrowserWidgetBot.java
@@ -23,9 +23,11 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
-import org.apache.directory.studio.test.integration.ui.bots.utils.JobWatcher;
+import org.apache.directory.studio.test.integration.ui.utils.JobWatcher;
 import org.eclipse.swtbot.swt.finder.SWTBot;
 import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException;
 import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable;
@@ -43,7 +45,6 @@
 {
     private SWTBot bot;
 
-
     BrowserWidgetBot( SWTBot bot )
     {
         this.bot = bot;
@@ -243,7 +244,7 @@
         List<String> nodes = entry.getNodes();
         for ( String node : nodes )
         {
-            if ( node.toUpperCase().startsWith( nodeName.toUpperCase() ) )
+            if ( matches( node, nodeName ) )
             {
                 return node;
             }
@@ -258,7 +259,7 @@
         for ( SWTBotTreeItem item : allItems )
         {
             String node = item.getText();
-            if ( node.toUpperCase().startsWith( nodeName.toUpperCase() ) )
+            if ( matches( node, nodeName ) )
             {
                 return node;
             }
@@ -267,6 +268,19 @@
     }
 
 
+    private boolean matches( String candidate, String needle )
+    {
+        Pattern pattern = Pattern.compile( "(.*) \\(\\d+\\+?\\)" );
+        Matcher candidateMatcher = pattern.matcher( candidate );
+        Matcher needleMatcher = pattern.matcher( needle );
+        if ( candidateMatcher.matches() && !needleMatcher.matches() )
+        {
+            candidate = candidateMatcher.group( 1 );
+        }
+        return candidate.toUpperCase().equals( needle.toUpperCase() );
+    }
+
+
     SWTBotTree getTree()
     {
         return bot.tree();
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/CertificateEditorDialogBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/CertificateEditorDialogBot.java
new file mode 100644
index 0000000..3535e4d
--- /dev/null
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/CertificateEditorDialogBot.java
@@ -0,0 +1,42 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.studio.test.integration.ui.bots;
+
+
+import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
+import org.apache.directory.studio.valueeditors.certificate.CertificateDialog;
+
+
+public class CertificateEditorDialogBot extends DialogBot
+{
+
+    public CertificateEditorDialogBot()
+    {
+        super( "Certificate Editor" );
+        super.setWaitAfterClickOkButton( true, BrowserCoreMessages.jobs__execute_ldif_name );
+    }
+
+
+    public void typeFile( String file )
+    {
+        bot.textWithTooltip( CertificateDialog.LOAD_FILE_NAME_TOOLTIP ).setText( file );
+    }
+
+}
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/CertificateTrustDialogBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/CertificateTrustDialogBot.java
index 866297f..d472e8c 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/CertificateTrustDialogBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/CertificateTrustDialogBot.java
@@ -24,7 +24,6 @@
 import java.util.List;
 
 import org.eclipse.swtbot.swt.finder.widgets.SWTBotLabel;
-import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
 
 
 public class CertificateTrustDialogBot extends DialogBot
@@ -123,18 +122,4 @@
         bot.radio( "Always trust this certificate." ).click();
     }
 
-
-    public ErrorDialogBot clickOkButtonExpectingErrorDialog()
-    {
-        SWTBotShell shell = BotUtils.shell( new Runnable()
-        {
-            public void run()
-            {
-                clickOkButton();
-            }
-        }, "Error", "Problem Occurred" );
-        String shellText = shell.getText();
-
-        return new ErrorDialogBot(shellText);
-    }
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/CertificateValidationPreferencePageBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/CertificateValidationPreferencePageBot.java
index a9a8c51..7beeae4 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/CertificateValidationPreferencePageBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/CertificateValidationPreferencePageBot.java
@@ -20,30 +20,11 @@
 package org.apache.directory.studio.test.integration.ui.bots;
 
 
-public class CertificateValidationPreferencePageBot extends DialogBot
+public class CertificateValidationPreferencePageBot extends PreferencePageBot
 {
 
     private static final String VALIDATE_CERTIFICATES_FOR_SECURE_LDAP_CONNECTIONS = "Validate certificates for secure LDAP connections";
 
-
-    public CertificateValidationPreferencePageBot()
-    {
-        super( "Preferences" );
-    }
-
-
-    public void clickApplyButton()
-    {
-        super.clickButton( "Apply" );
-    }
-
-
-    public void clickRestoreDefaultsButton()
-    {
-        super.clickButton( "Restore Defaults" );
-    }
-
-
     public boolean isValidateCertificatesSelected()
     {
         return bot.checkBox( VALIDATE_CERTIFICATES_FOR_SECURE_LDAP_CONNECTIONS ).isChecked();
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ConnectionsViewBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ConnectionsViewBot.java
index cc39443..2dec487 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ConnectionsViewBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ConnectionsViewBot.java
@@ -20,7 +20,11 @@
 package org.apache.directory.studio.test.integration.ui.bots;
 
 
-import static org.apache.directory.studio.test.integration.ui.Constants.LOCALHOST;
+import static org.apache.directory.studio.test.integration.ui.utils.Constants.LOCALHOST;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 
 import org.apache.directory.studio.connection.core.Connection;
 import org.apache.directory.studio.connection.core.ConnectionCorePlugin;
@@ -33,8 +37,9 @@
 import org.apache.directory.studio.connection.core.Messages;
 import org.apache.directory.studio.connection.core.jobs.OpenConnectionsRunnable;
 import org.apache.directory.studio.connection.core.jobs.StudioConnectionJob;
-import org.apache.directory.studio.test.integration.ui.ContextMenuHelper;
-import org.apache.directory.studio.test.integration.ui.bots.utils.JobWatcher;
+import org.apache.directory.studio.test.integration.junit5.TestLdapServer;
+import org.apache.directory.studio.test.integration.ui.utils.ContextMenuHelper;
+import org.apache.directory.studio.test.integration.ui.utils.JobWatcher;
 import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
 import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView;
 import org.eclipse.swtbot.swt.finder.utils.TableCollection;
@@ -48,7 +53,6 @@
 {
     private SWTWorkbenchBot bot = new SWTWorkbenchBot();
 
-
     public NewConnectionWizardBot openNewConnectionWizard()
     {
         ContextMenuHelper.clickContextMenu( getConnectionsTree(), "New Connection..." );
@@ -57,10 +61,10 @@
     }
 
 
-    public SchemaBrowserBot openSchemaBrowser()
+    public NewConnectionFolderDialogBot openNewConnectionFolderDialog()
     {
-        ContextMenuHelper.clickContextMenu( getConnectionsTree(), "Open Schema Browser" );
-        return new SchemaBrowserBot();
+        ContextMenuHelper.clickContextMenu( getConnectionsTree(), "New Connection Folder..." );
+        return new NewConnectionFolderDialogBot();
     }
 
 
@@ -83,6 +87,17 @@
     }
 
 
+    public ErrorDialogBot openSelectedConnectionExpectingNoSchemaProvidedErrorDialog()
+    {
+        String shellText = BotUtils.shell( () -> {
+            JobWatcher watcher = new JobWatcher( Messages.jobs__open_connections_name_1 );
+            getConnectionsTree().contextMenu( "Open Connection" ).click();
+            watcher.waitUntilDone();
+        }, "Problem Occurred" ).getText();
+        return new ErrorDialogBot( shellText );
+    }
+
+
     public void closeSelectedConnections()
     {
         JobWatcher watcher = new JobWatcher( Messages.jobs__close_connections_name_1 );
@@ -91,13 +106,62 @@
     }
 
 
-    public void selectConnection( String connectionName )
+    public SchemaBrowserBot openSchemaBrowser()
     {
-        getConnectionsTree().select( connectionName );
+        ContextMenuHelper.clickContextMenu( getConnectionsTree(), "Open Schema Browser" );
+        return new SchemaBrowserBot();
     }
 
 
-    public String getSelectedConnection()
+    public DeleteDialogBot openDeleteConnectionDialog()
+    {
+        getConnectionsTree().contextMenu( "Delete Connection" ).click();
+        return new DeleteDialogBot( DeleteDialogBot.DELETE_CONNECTION );
+    }
+
+
+    public DeleteDialogBot openDeleteConnectionFolderDialog()
+    {
+        getConnectionsTree().contextMenu( DeleteDialogBot.DELETE_CONNECTION_FOLDER ).click();
+        return new DeleteDialogBot( DeleteDialogBot.DELETE_CONNECTION_FOLDER );
+    }
+
+
+    public ExportConnectionsWizardBot openExportConnectionsWizard()
+    {
+        getConnectionsTree().contextMenu( "Export" ).contextMenu( "Export Connections..." ).click();
+        return new ExportConnectionsWizardBot();
+    }
+
+
+    public ImportConnectionsWizardBot openImportConnectionsWizard()
+    {
+        getConnectionsTree().contextMenu( "Import" ).contextMenu( "Import Connections..." ).click();
+        return new ImportConnectionsWizardBot();
+    }
+
+
+    public ApacheDSConfigurationEditorBot openApacheDSConfiguration()
+    {
+        getConnectionsTree().contextMenu( "Open Configuration" ).click();
+        String title = getSelection() + " - Configuration";
+        return new ApacheDSConfigurationEditorBot( title );
+    }
+
+
+    public void select( String... path )
+    {
+        List<String> pathList = new ArrayList<String>( Arrays.asList( path ) );
+        SWTBotTreeItem item = getConnectionsTree().getTreeItem( pathList.remove( 0 ) );
+        while ( !pathList.isEmpty() )
+        {
+            item = item.getNode( pathList.remove( 0 ) );
+        }
+        item.select();
+    }
+
+
+    public String getSelection()
     {
         TableCollection selection = getConnectionsTree().selection();
         if ( selection != null && selection.rowCount() == 1 )
@@ -109,9 +173,9 @@
     }
 
 
-    public int getConnectionCount()
+    public int getCount()
     {
-        return getConnectionsTree().rowCount();
+        return getConnectionsTree().visibleRowCount();
     }
 
 
@@ -150,6 +214,14 @@
     }
 
 
+    public Connection createTestConnection( TestLdapServer server ) throws Exception
+    {
+        return createTestConnection( server.getType().name(), server.getHost(),
+            server.getPort(), server.getAdminDn(),
+            server.getAdminPassword() );
+    }
+
+
     /**
      * Creates the test connection.
      *
@@ -163,17 +235,24 @@
      */
     public Connection createTestConnection( String name, int port ) throws Exception
     {
+        return createTestConnection( name, LOCALHOST, port, "uid=admin,ou=system", "secret" );
+    }
+
+
+    public Connection createTestConnection( String name, String host, int port, String bindDn, String bindPassword )
+        throws Exception
+    {
         name = name + "_" + System.currentTimeMillis();
 
         ConnectionManager connectionManager = ConnectionCorePlugin.getDefault().getConnectionManager();
         ConnectionParameter connectionParameter = new ConnectionParameter();
         connectionParameter.setName( name );
-        connectionParameter.setHost( LOCALHOST );
+        connectionParameter.setHost( host );
         connectionParameter.setPort( port );
         connectionParameter.setEncryptionMethod( EncryptionMethod.NONE );
         connectionParameter.setAuthMethod( AuthenticationMethod.SIMPLE );
-        connectionParameter.setBindPrincipal( "uid=admin,ou=system" );
-        connectionParameter.setBindPassword( "secret" );
+        connectionParameter.setBindPrincipal( bindDn );
+        connectionParameter.setBindPassword( bindPassword );
         Connection connection = new Connection( connectionParameter );
         connectionManager.addConnection( connection );
 
@@ -182,7 +261,7 @@
         ConnectionFolder rootConnectionFolder = connectionFolderManager.getRootConnectionFolder();
         rootConnectionFolder.addConnectionId( connection.getId() );
 
-        selectConnection( name );
+        select( name );
         StudioConnectionJob job = new StudioConnectionJob( new OpenConnectionsRunnable( connection ) );
         job.execute();
         job.join();
@@ -201,14 +280,13 @@
         {
             connectionManager.removeConnection( connection );
         }
-    }
 
-
-    public ApacheDSConfigurationEditorBot openApacheDSConfiguration()
-    {
-        getConnectionsTree().contextMenu( "Open Configuration" ).click();
-        String title = getSelectedConnection() + " - Configuration";
-        return new ApacheDSConfigurationEditorBot( title );
+        ConnectionFolderManager connectionFolderManager = ConnectionCorePlugin.getDefault()
+            .getConnectionFolderManager();
+        for ( ConnectionFolder connectionFolder : connectionFolderManager.getConnectionFolders() )
+        {
+            connectionFolderManager.removeConnectionFolder( connectionFolder );
+        }
     }
 
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/DeleteDialogBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/DeleteDialogBot.java
index 722f875..7829fed 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/DeleteDialogBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/DeleteDialogBot.java
@@ -21,37 +21,23 @@
 
 
 import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
-import org.apache.directory.studio.test.integration.ui.bots.utils.JobWatcher;
 
 
 public class DeleteDialogBot extends DialogBot
 {
+    public static final String DELETE_CONNECTION = "Delete Connection";
+    public static final String DELETE_CONNECTION_FOLDER = "Delete Connection Folder";
     public static final String DELETE_ENTRY_TITLE = "Delete Entry";
     public static final String DELETE_ENTRIES_TITLE = "Delete Entries";
     public static final String DELETE_VALUE_TITLE = "Delete Value";
     public static final String DELETE_SERVER = "Delete Server";
     public static final String DELETE_PROJECT = "Delete Project";
 
-
     public DeleteDialogBot( String title )
     {
         super( title );
-    }
-
-
-    public void clickOkButton()
-    {
-        String jobWatcherTitle = getJobWatcherTitle( title );
-        if ( jobWatcherTitle != null )
-        {
-            JobWatcher watcher = new JobWatcher( jobWatcherTitle );
-            super.clickOkButton();
-            watcher.waitUntilDone();
-        }
-        else
-        {
-            super.clickOkButton();
-        }
+        String jobName = getJobWatcherTitle( title );
+        super.setWaitAfterClickOkButton( jobName != null, jobName );
     }
 
 
@@ -61,6 +47,8 @@
         {
             case DELETE_VALUE_TITLE:
                 return BrowserCoreMessages.jobs__execute_ldif_name;
+            case DELETE_CONNECTION:
+            case DELETE_CONNECTION_FOLDER:
             case DELETE_PROJECT:
                 return null;
             default:
@@ -68,9 +56,4 @@
         }
     }
 
-
-    public void clickCancelButton()
-    {
-        super.clickButton( "Cancel" );
-    }
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/DialogBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/DialogBot.java
index 029b5aa..fda9337 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/DialogBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/DialogBot.java
@@ -20,6 +20,8 @@
 package org.apache.directory.studio.test.integration.ui.bots;
 
 
+import org.apache.commons.lang3.StringUtils;
+import org.apache.directory.studio.test.integration.ui.utils.JobWatcher;
 import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
 import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences;
 import org.eclipse.swtbot.swt.finder.waits.DefaultCondition;
@@ -32,7 +34,7 @@
 
     protected SWTWorkbenchBot bot = new SWTWorkbenchBot();
     protected String title;
-
+    protected String[] okButtonJobWatcherJobNames = null;
 
     protected DialogBot( String title )
     {
@@ -40,6 +42,19 @@
     }
 
 
+    public void setWaitAfterClickOkButton( boolean wait, String... jobNames )
+    {
+        if ( wait )
+        {
+            this.okButtonJobWatcherJobNames = jobNames;
+        }
+        else
+        {
+            this.okButtonJobWatcherJobNames = null;
+        }
+    }
+
+
     public void activate()
     {
         bot.shell( title ).setFocus();
@@ -68,7 +83,23 @@
 
     public void clickOkButton()
     {
-        clickButton( "OK" );
+        if ( okButtonJobWatcherJobNames != null )
+        {
+            JobWatcher jobWatcher = new JobWatcher( okButtonJobWatcherJobNames );
+            clickButton( "OK" );
+            jobWatcher.waitUntilDone();
+        }
+        else
+        {
+            clickButton( "OK" );
+        }
+    }
+
+
+    public ErrorDialogBot clickOkButtonExpectingErrorDialog()
+    {
+        String shellText = BotUtils.shell( () -> clickButton( "OK" ), "Error", "Problem Occurred" ).getText();
+        return new ErrorDialogBot( shellText );
     }
 
 
@@ -107,7 +138,7 @@
     }
 
 
-    protected String clickCheckButton( final String label, final String title )
+    protected CheckResponse clickCheckButton( final String label, final String title )
     {
         SWTBotShell parentShell = bot.activeShell();
         SWTBotShell shell = BotUtils.shell( new Runnable()
@@ -119,17 +150,55 @@
         }, "Error", title );
 
         String shellText = shell.getText();
-        String labelText = bot.label( 1 ).getText(); // label(0) is the image
+        // label(0) may be the image
+        String messageText = bot.label( 0 ).getText();
+        if ( StringUtils.isBlank( messageText ) )
+        {
+            messageText = bot.label( 1 ).getText();
+        }
         bot.button( "OK" ).click();
         parentShell.activate();
 
         if ( shellText.equals( title ) )
         {
-            return null;
+            return new CheckResponse( false, shellText, messageText );
         }
         else
         {
-            return labelText;
+            return new CheckResponse( true, shellText, messageText );
         }
     }
+
+    public static class CheckResponse
+    {
+        boolean isError;
+        String title;
+        String message;
+
+        public CheckResponse( boolean isError, String title, String message )
+        {
+            this.isError = isError;
+            this.title = title;
+            this.message = message;
+        }
+
+
+        public boolean isError()
+        {
+            return isError;
+        }
+
+
+        public String getTitle()
+        {
+            return title;
+        }
+
+
+        public String getMessage()
+        {
+            return message;
+        }
+
+    }
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/DnEditorDialogBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/DnEditorDialogBot.java
index fbf7d56..cbe97f8 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/DnEditorDialogBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/DnEditorDialogBot.java
@@ -20,12 +20,16 @@
 package org.apache.directory.studio.test.integration.ui.bots;
 
 
+import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
+
+
 public class DnEditorDialogBot extends DialogBot
 {
 
     public DnEditorDialogBot()
     {
         super( "DN Editor" );
+        super.setWaitAfterClickOkButton( true, BrowserCoreMessages.jobs__execute_ldif_name );
     }
 
 
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/utils/StudioSystemUtils.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/EditAttributeWizardBot.java
similarity index 60%
copy from tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/utils/StudioSystemUtils.java
copy to tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/EditAttributeWizardBot.java
index d15e955..cba11d2 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/utils/StudioSystemUtils.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/EditAttributeWizardBot.java
@@ -17,21 +17,34 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.studio.test.integration.ui.bots.utils;
+package org.apache.directory.studio.test.integration.ui.bots;
 
 
-import org.apache.commons.lang3.SystemUtils;
-
-
-public class StudioSystemUtils extends SystemUtils
+public class EditAttributeWizardBot extends WizardBot
 {
-    public static final boolean IS_OS_WINDOWS_SERVER = isOSNameMatch( SystemUtils.OS_NAME, "Windows Server");
 
-    static boolean isOSNameMatch(final String osName, final String osNamePrefix) {
-        if (osName == null) {
-            return false;
-        }
-        return osName.startsWith(osNamePrefix);
+    public EditAttributeWizardBot()
+    {
+        super( "Edit Attribute Description" );
+    }
+
+
+    public void typeAttributeType( String text )
+    {
+        bot.comboBox().setText( text );
+    }
+
+
+    public void setLanguageTag( String lang, String country )
+    {
+        bot.comboBox( 0 ).setText( lang );
+        bot.comboBox( 1 ).setText( country );
+    }
+
+
+    public void selectBinaryOption()
+    {
+        bot.checkBox().select();
     }
 
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/EntryEditorBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/EntryEditorBot.java
index 328d408..0012f68 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/EntryEditorBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/EntryEditorBot.java
@@ -23,6 +23,7 @@
 
 import java.util.List;
 
+import org.apache.directory.studio.test.integration.ui.utils.ContextMenuHelper;
 import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
 import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotEditor;
 import org.eclipse.swtbot.swt.finder.SWTBot;
@@ -35,7 +36,6 @@
     private SWTBot bot;
     private EntryEditorWidgetBot editorBot;
 
-
     public EntryEditorBot( String title )
     {
         SWTWorkbenchBot bot = new SWTWorkbenchBot();
@@ -83,6 +83,12 @@
     }
 
 
+    public ErrorDialogBot typeValueAndFinishAndExpectErrorDialog( String value )
+    {
+        return editorBot.typeValueAndFinishAndExpectErrorDialog( value );
+    }
+
+
     public void addValue( String attributeType )
     {
         editorBot.addValue( attributeType );
@@ -95,6 +101,12 @@
     }
 
 
+    public EditAttributeWizardBot editAttribute( String attributeType, String value )
+    {
+        return editorBot.editAttribute( attributeType, value );
+    }
+
+
     public DnEditorDialogBot editValueExpectingDnEditor( String attributeType, String value )
     {
         return editorBot.editValueExpectingDnEditor( attributeType, value );
@@ -107,6 +119,31 @@
     }
 
 
+    public AciItemEditorDialogBot editValueExpectingAciItemEditor( String attributeType, String value )
+    {
+        return editorBot.editValueExpectingAciItemEditor( attributeType, value );
+    }
+
+
+    public SubtreeSpecificationEditorDialogBot editValueExpectingSubtreeSpecificationEditor( String attributeType,
+        String value )
+    {
+        return editorBot.editValueExpectingSubtreeSpecificationEditor( attributeType, value );
+    }
+
+
+    public CertificateEditorDialogBot editValueExpectingCertificateEditor( String attributeType, String value )
+    {
+        return editorBot.editValueExpectingCertificateEditor( attributeType, value );
+    }
+
+
+    public HexEditorDialogBot editValueExpectingHexEditor( String attributeType, String value )
+    {
+        return editorBot.editValueExpectingHexEditor( attributeType, value );
+    }
+
+
     public TextEditorDialogBot editValueWithTextEditor( String attributeType, String value )
     {
         return editorBot.editValueWithTextEditor( attributeType, value );
@@ -119,6 +156,12 @@
     }
 
 
+    public ErrorDialogBot deleteValueExpectingErrorDialog( String attributeType, String value )
+    {
+        return editorBot.deleteValueExpectingErrorDialog( attributeType, value );
+    }
+
+
     public void copyValue( String attributeType, String value )
     {
         editorBot.copyValue( attributeType, value );
@@ -142,4 +185,10 @@
         editorBot.pasteValues();
     }
 
+
+    public void fetchOperationalAttributes()
+    {
+        ContextMenuHelper.clickContextMenu( bot.tree(), "Fetch Operational Attributes" );
+    }
+
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/EntryEditorWidgetBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/EntryEditorWidgetBot.java
index 3ea28eb..15bfdec 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/EntryEditorWidgetBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/EntryEditorWidgetBot.java
@@ -25,8 +25,8 @@
 import java.util.List;
 
 import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
-import org.apache.directory.studio.test.integration.ui.ContextMenuHelper;
-import org.apache.directory.studio.test.integration.ui.bots.utils.JobWatcher;
+import org.apache.directory.studio.test.integration.ui.utils.ContextMenuHelper;
+import org.apache.directory.studio.test.integration.ui.utils.JobWatcher;
 import org.eclipse.swtbot.swt.finder.SWTBot;
 import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException;
 import org.eclipse.swtbot.swt.finder.keyboard.Keystrokes;
@@ -42,7 +42,6 @@
 {
     private SWTBot bot;
 
-
     EntryEditorWidgetBot( SWTBot bot )
     {
         this.bot = bot;
@@ -95,6 +94,13 @@
     }
 
 
+    public ErrorDialogBot typeValueAndFinishAndExpectErrorDialog( String value )
+    {
+        String shellText = BotUtils.shell( () -> typeValueAndFinish( value, false ), "Error" ).getText();
+        return new ErrorDialogBot( shellText );
+    }
+
+
     void cancelEditValue()
     {
         SWTBotTree tree = bot.tree( 0 );
@@ -120,6 +126,16 @@
     }
 
 
+    EditAttributeWizardBot editAttribute( String attributeType, String value )
+    {
+        cancelEditValue();
+        SWTBotTreeItem treeItem = getTreeItem( attributeType, value );
+        treeItem.select();
+        ContextMenuHelper.clickContextMenu( bot.tree(), "Edit Attribute Description" );
+        return new EditAttributeWizardBot();
+    }
+
+
     void editValue( String attributeType, String value )
     {
         cancelEditValue();
@@ -151,6 +167,35 @@
     }
 
 
+    AciItemEditorDialogBot editValueExpectingAciItemEditor( String attributeType, String value )
+    {
+        editValue( attributeType, value );
+        return new AciItemEditorDialogBot();
+    }
+
+
+    SubtreeSpecificationEditorDialogBot editValueExpectingSubtreeSpecificationEditor( String attributeType,
+        String value )
+    {
+        editValue( attributeType, value );
+        return new SubtreeSpecificationEditorDialogBot();
+    }
+
+
+    CertificateEditorDialogBot editValueExpectingCertificateEditor( String attributeType, String value )
+    {
+        editValue( attributeType, value );
+        return new CertificateEditorDialogBot();
+    }
+
+
+    HexEditorDialogBot editValueExpectingHexEditor( String attributeType, String value )
+    {
+        editValue( attributeType, value );
+        return new HexEditorDialogBot();
+    }
+
+
     TextEditorDialogBot editValueWithTextEditor( String attributeType, String value )
     {
         editValueWith( attributeType, value, "^Text Editor$" );
@@ -164,7 +209,8 @@
         SWTBotTreeItem[] allItems = tree.getAllItems();
         for ( SWTBotTreeItem item : allItems )
         {
-            if ( item.cell( 0 ).equals( attributeType ) && item.cell( 1 ).equals( value ) )
+            if ( item.cell( 0 ).equalsIgnoreCase( attributeType )
+                && ( value == null || item.cell( 1 ).equals( value ) ) )
             {
                 return item;
             }
@@ -200,6 +246,16 @@
     }
 
 
+    public ErrorDialogBot deleteValueExpectingErrorDialog( String attributeType, String value )
+    {
+        SWTBotTreeItem treeItem = getTreeItem( attributeType, value );
+        treeItem.select();
+        ContextMenuHelper.clickContextMenu( bot.tree(), "Delete Value" );
+        DeleteDialogBot deleteDialogBot = new DeleteDialogBot( DeleteDialogBot.DELETE_VALUE_TITLE );
+        return deleteDialogBot.clickOkButtonExpectingErrorDialog();
+    }
+
+
     public void copyValue( String attributeType, String value )
     {
 
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ErrorDialogBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ErrorDialogBot.java
index 6661424..46b9cd7 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ErrorDialogBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ErrorDialogBot.java
@@ -19,6 +19,7 @@
  */
 package org.apache.directory.studio.test.integration.ui.bots;
 
+import org.apache.commons.lang3.StringUtils;
 
 public class ErrorDialogBot extends DialogBot
 {
@@ -37,7 +38,17 @@
 
     public String getErrorMessage()
     {
-        return bot.label( 1 ).getText();
+        // label(0) may be the image
+        int index = StringUtils.isBlank( bot.label( 0 ).getText() ) ? 1 : 0;
+        return bot.label( index ).getText();
+    }
+
+
+    public String getErrorDetails()
+    {
+        // label(0) may be the image
+        int index = StringUtils.isBlank( bot.label( 0 ).getText() ) ? 2 : 1;
+        return bot.label( index ).getText();
     }
 
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/Constants.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ExportConnectionsWizardBot.java
similarity index 73%
copy from tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/Constants.java
copy to tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ExportConnectionsWizardBot.java
index 4962877..2a329e5 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/Constants.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ExportConnectionsWizardBot.java
@@ -17,16 +17,20 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.studio.test.integration.ui;
+package org.apache.directory.studio.test.integration.ui.bots;
 
 
-import org.apache.directory.api.util.Network;
-
-
-public final class Constants
+public class ExportConnectionsWizardBot extends WizardBot
 {
-    public static final String LOCALHOST = Network.LOOPBACK_HOSTNAME;
+    public ExportConnectionsWizardBot()
+    {
+        super( "Connections Export" );
+    }
 
-    public static final String LOCALHOST_ADDRESS = Network.LOOPBACK.getHostAddress();
+
+    public void typeFile( String file )
+    {
+        bot.comboBox().setText( file );
+    }
 
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ExportWizardBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ExportWizardBot.java
index 092f37d..d169a88 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ExportWizardBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ExportWizardBot.java
@@ -25,7 +25,7 @@
 import org.apache.directory.api.ldap.model.message.SearchScope;
 import org.apache.directory.studio.connection.core.Connection.AliasDereferencingMethod;
 import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
-import org.apache.directory.studio.test.integration.ui.bots.utils.JobWatcher;
+import org.apache.directory.studio.test.integration.ui.utils.JobWatcher;
 import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences;
 import org.eclipse.swtbot.swt.finder.waits.DefaultCondition;
 
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/utils/StudioSystemUtils.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/FilterEditorDialogBot.java
similarity index 63%
copy from tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/utils/StudioSystemUtils.java
copy to tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/FilterEditorDialogBot.java
index d15e955..a8215b2 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/utils/StudioSystemUtils.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/FilterEditorDialogBot.java
@@ -17,21 +17,33 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.studio.test.integration.ui.bots.utils;
+package org.apache.directory.studio.test.integration.ui.bots;
 
 
-import org.apache.commons.lang3.SystemUtils;
-
-
-public class StudioSystemUtils extends SystemUtils
+public class FilterEditorDialogBot extends DialogBot
 {
-    public static final boolean IS_OS_WINDOWS_SERVER = isOSNameMatch( SystemUtils.OS_NAME, "Windows Server");
 
-    static boolean isOSNameMatch(final String osName, final String osNamePrefix) {
-        if (osName == null) {
-            return false;
-        }
-        return osName.startsWith(osNamePrefix);
+    public FilterEditorDialogBot()
+    {
+        super( "Filter Editor" );
+    }
+
+
+    public void setFilter( String filter )
+    {
+        bot.styledText().setText( filter );
+    }
+
+
+    public String getFilter()
+    {
+        return bot.styledText().getText();
+    }
+
+
+    public void clickFormatButton()
+    {
+        super.clickButton( "Format" );
     }
 
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/Constants.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/GeneratedPasswordDialogBot.java
similarity index 73%
copy from tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/Constants.java
copy to tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/GeneratedPasswordDialogBot.java
index 4962877..ab88a2d 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/Constants.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/GeneratedPasswordDialogBot.java
@@ -17,16 +17,21 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.studio.test.integration.ui;
+package org.apache.directory.studio.test.integration.ui.bots;
 
 
-import org.apache.directory.api.util.Network;
-
-
-public final class Constants
+public class GeneratedPasswordDialogBot extends DialogBot
 {
-    public static final String LOCALHOST = Network.LOOPBACK_HOSTNAME;
 
-    public static final String LOCALHOST_ADDRESS = Network.LOOPBACK.getHostAddress();
+    public GeneratedPasswordDialogBot()
+    {
+        super( "Generated Password" );
+    }
+
+
+    public String getGeneratedPassword()
+    {
+        return bot.text( 0 ).getText();
+    }
 
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/HexEditorDialogBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/HexEditorDialogBot.java
new file mode 100644
index 0000000..7a318a8
--- /dev/null
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/HexEditorDialogBot.java
@@ -0,0 +1,48 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.studio.test.integration.ui.bots;
+
+
+import org.apache.directory.studio.ldapbrowser.common.dialogs.HexDialog;
+import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
+
+
+public class HexEditorDialogBot extends DialogBot
+{
+
+    public HexEditorDialogBot()
+    {
+        super( "Hex Editor" );
+        super.setWaitAfterClickOkButton( true, BrowserCoreMessages.jobs__execute_ldif_name );
+    }
+
+
+    public void typeFile( String file )
+    {
+        bot.textWithTooltip( HexDialog.LOAD_FILE_NAME_TOOLTIP ).setText( file );
+    }
+
+
+    public String getHexText()
+    {
+        return bot.text().getText();
+    }
+
+}
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ImageEditorDialogBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ImageEditorDialogBot.java
index 3233fac..a551668 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ImageEditorDialogBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ImageEditorDialogBot.java
@@ -19,6 +19,7 @@
  */
 package org.apache.directory.studio.test.integration.ui.bots;
 
+import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
 
 public class ImageEditorDialogBot extends DialogBot
 {
@@ -26,6 +27,7 @@
     public ImageEditorDialogBot()
     {
         super( "Image Editor" );
+        super.setWaitAfterClickOkButton( true, BrowserCoreMessages.jobs__execute_ldif_name );
     }
 
 
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/Constants.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ImportConnectionsWizardBot.java
similarity index 73%
copy from tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/Constants.java
copy to tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ImportConnectionsWizardBot.java
index 4962877..7f0f6da 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/Constants.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ImportConnectionsWizardBot.java
@@ -17,16 +17,20 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.studio.test.integration.ui;
+package org.apache.directory.studio.test.integration.ui.bots;
 
 
-import org.apache.directory.api.util.Network;
-
-
-public final class Constants
+public class ImportConnectionsWizardBot extends WizardBot
 {
-    public static final String LOCALHOST = Network.LOOPBACK_HOSTNAME;
+    public ImportConnectionsWizardBot()
+    {
+        super( "Connections Import" );
+    }
 
-    public static final String LOCALHOST_ADDRESS = Network.LOOPBACK.getHostAddress();
+
+    public void typeFile( String file )
+    {
+        bot.comboBox().setText( file );
+    }
 
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ImportWizardBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ImportWizardBot.java
index f985963..b483dcb 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ImportWizardBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ImportWizardBot.java
@@ -21,7 +21,7 @@
 
 
 import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
-import org.apache.directory.studio.test.integration.ui.bots.utils.JobWatcher;
+import org.apache.directory.studio.test.integration.ui.utils.JobWatcher;
 
 
 public class ImportWizardBot extends WizardBot
@@ -30,7 +30,6 @@
     public static final String IMPORT_DSML_TITLE = "DSML Import";
     private String title;
 
-
     public ImportWizardBot()
     {
         this( "Import" );
@@ -71,4 +70,30 @@
         }
     }
 
+
+    public void setContinueOnError( boolean enabled )
+    {
+        if ( enabled )
+        {
+            bot.checkBox( "Continue on error" ).select();
+        }
+        else
+        {
+            bot.checkBox( "Continue on error" ).deselect();
+        }
+    }
+
+
+    public void setUpdateExistingEntries( boolean enabled )
+    {
+        if ( enabled )
+        {
+            bot.checkBox( "Update existing entries" ).select();
+        }
+        else
+        {
+            bot.checkBox( "Update existing entries" ).deselect();
+        }
+    }
+
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/LdifEditorBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/LdifEditorBot.java
index 1bdbe6f..e8122f6 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/LdifEditorBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/LdifEditorBot.java
@@ -21,6 +21,8 @@
 package org.apache.directory.studio.test.integration.ui.bots;
 
 
+import java.util.List;
+
 import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
 import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotEclipseEditor;
 import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotEditor;
@@ -30,10 +32,18 @@
 {
     private SWTBotEditor editor;
 
-
     public LdifEditorBot( String title )
     {
         SWTWorkbenchBot bot = new SWTWorkbenchBot();
+        List<? extends SWTBotEditor> editors = bot.editors();
+        for ( SWTBotEditor editor : editors )
+        {
+            if ( editor.getTitle().startsWith( title ) )
+            {
+                this.editor = editor;
+                return;
+            }
+        }
         editor = bot.editorByTitle( title );
     }
 
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ModificationLogsViewBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ModificationLogsViewBot.java
index a9b50b5..3c065cd 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ModificationLogsViewBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ModificationLogsViewBot.java
@@ -31,6 +31,7 @@
 import org.apache.directory.studio.ldifparser.model.container.LdifCommentContainer;
 import org.apache.directory.studio.ldifparser.model.container.LdifContainer;
 import org.apache.directory.studio.ldifparser.parser.LdifParser;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu;
 
 
 public class ModificationLogsViewBot extends AbstractLogsViewBot
@@ -47,6 +48,16 @@
     }
 
 
+    public void enableModificationLogs( boolean b )
+    {
+        view.show();
+        SWTBotMenu menuItem = view.viewMenu( "Enable Modification Logs" );
+        if ( menuItem.isChecked() != b )
+        {
+            menuItem.click();
+        }
+    }
+
     public void assertContainsOk( String... lines )
     {
         List<String> parts = new ArrayList<>();
@@ -87,7 +98,7 @@
                 return;
             }
         }
-        throw new AssertionError( "Expeted to find all parts " + parts + " in\n" + text );
+        throw new AssertionError( "Expected to find all parts " + parts + " in\n" + text );
     }
 
 
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ModificationLogsViewPreferencePageBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ModificationLogsViewPreferencePageBot.java
new file mode 100644
index 0000000..c5a8b68
--- /dev/null
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ModificationLogsViewPreferencePageBot.java
@@ -0,0 +1,56 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.studio.test.integration.ui.bots;
+
+
+public class ModificationLogsViewPreferencePageBot extends PreferencePageBot
+{
+
+    public void setEnableModificationLogs( boolean b )
+    {
+        activate();
+        if ( b )
+        {
+            bot.checkBox( 0 ).select();
+        }
+        else
+        {
+            bot.checkBox( 0 ).deselect();
+        }
+    }
+
+
+    public void setMaskedAttributes( String s )
+    {
+        bot.text( 1 ).setText( s );
+    }
+
+
+    public void setLogFileCount( int i )
+    {
+        bot.text( 2 ).setText( "" + i );
+    }
+
+
+    public void setLogFileSize( int i )
+    {
+        bot.text( 3 ).setText( "" + i );
+    }
+}
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/MoveEntriesDialogBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/MoveEntriesDialogBot.java
index 5622dd7..4427027 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/MoveEntriesDialogBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/MoveEntriesDialogBot.java
@@ -21,7 +21,6 @@
 
 
 import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
-import org.apache.directory.studio.test.integration.ui.bots.utils.JobWatcher;
 
 
 public class MoveEntriesDialogBot extends DialogBot
@@ -30,14 +29,7 @@
     public MoveEntriesDialogBot()
     {
         super( "Move Entries" );
-    }
-
-
-    public void clickOkButton()
-    {
-        JobWatcher watcher = new JobWatcher( BrowserCoreMessages.jobs__move_entry_name_1 );
-        super.clickOkButton();
-        watcher.waitUntilDone();
+        super.setWaitAfterClickOkButton( true, BrowserCoreMessages.jobs__move_entry_name_1 );
     }
 
 
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/NewAttributeWizardBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/NewAttributeWizardBot.java
index 1562294..62877bd 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/NewAttributeWizardBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/NewAttributeWizardBot.java
@@ -35,6 +35,19 @@
     }
 
 
+    public void setLanguageTag( String lang, String country )
+    {
+        bot.comboBox( 0 ).setText( lang );
+        bot.comboBox( 1 ).setText( country );
+    }
+
+
+    public void selectBinaryOption()
+    {
+        bot.checkBox().select();
+    }
+
+
     public DnEditorDialogBot clickFinishButtonExpectingDnEditor()
     {
         clickFinishButton();
@@ -55,4 +68,18 @@
         return new ImageEditorDialogBot();
     }
 
+
+    public CertificateEditorDialogBot clickFinishButtonExpectingCertificateEditor()
+    {
+        clickFinishButton();
+        return new CertificateEditorDialogBot();
+    }
+
+
+    public HexEditorDialogBot clickFinishButtonExpectingHexEditor()
+    {
+        clickFinishButton();
+        return new HexEditorDialogBot();
+    }
+
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/Constants.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/NewConnectionFolderDialogBot.java
similarity index 71%
copy from tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/Constants.java
copy to tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/NewConnectionFolderDialogBot.java
index 4962877..29c00f4 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/Constants.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/NewConnectionFolderDialogBot.java
@@ -17,16 +17,20 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.studio.test.integration.ui;
+package org.apache.directory.studio.test.integration.ui.bots;
 
-
-import org.apache.directory.api.util.Network;
-
-
-public final class Constants
+public class NewConnectionFolderDialogBot extends DialogBot
 {
-    public static final String LOCALHOST = Network.LOOPBACK_HOSTNAME;
 
-    public static final String LOCALHOST_ADDRESS = Network.LOOPBACK.getHostAddress();
+    public NewConnectionFolderDialogBot()
+    {
+        super( "New Connection Folder" );
+    }
+
+
+    public void setConnectionFoldername( String name )
+    {
+        bot.text().setText( name );
+    }
 
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/NewConnectionWizardBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/NewConnectionWizardBot.java
index 59cb804..1591c4a 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/NewConnectionWizardBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/NewConnectionWizardBot.java
@@ -20,8 +20,10 @@
 package org.apache.directory.studio.test.integration.ui.bots;
 
 
+import org.apache.directory.api.ldap.model.constants.SaslQoP;
+import org.apache.directory.api.ldap.model.constants.SaslSecurityStrength;
 import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
-import org.apache.directory.studio.test.integration.ui.bots.utils.JobWatcher;
+import org.apache.directory.studio.test.integration.ui.utils.JobWatcher;
 import org.eclipse.swtbot.swt.finder.widgets.SWTBotCombo;
 import org.eclipse.swtbot.swt.finder.widgets.SWTBotText;
 
@@ -36,10 +38,13 @@
     private static final String PORT = "Port:";
     private static final String CHECK_AUTHENTICATION = "Check Authentication";
     private static final String CHECK_NETWORK_PARAMETER = "Check Network Parameter";
+    private static final String VIEW_CERTIFICATE = "View Certificate...";
     private static final String BASE_DN = "Base DN:";
     private static final String GET_BASE_DNS_FROM_ROOT_DSE = "Get base DNs from Root DSE";
     private static final String SAVE_PASSWORD = "Save password";
     private static final String SASL_REALM = "SASL Realm:";
+    private static final String SASL_QUALITY_OF_PROTECTION = "Quality of Protection:";
+    private static final String SASL_PROTECTION_STRENGH = "Protection Strength:";
     private static final String BIND_PASSWORD = "Bind password:";
     private static final String BIND_DN_OR_USER = "Bind DN or user:";
     private static final String CRAM_MD5_SASL = "CRAM-MD5 (SASL)";
@@ -49,7 +54,7 @@
     private static final String SIMPLE_AUTHENTICATION = "Simple Authentication";
     private static final String AUTHENTICATION_METHOD = "Authentication Method";
     private static final String ENCRYPTION_METHOD = "Encryption method:";
-    private static final String NO_ENCRYPTION = "No Encryption";
+    private static final String NO_ENCRYPTION = "No encryption";
     private static final String START_TLS_ENCRYPTION = "Use StartTLS extension";
     private static final String LDAPS_ENCRYPTION = "Use SSL encryption (ldaps://)";
     private static final String USE_NATIVE_TGT = "Use native TGT";
@@ -61,7 +66,6 @@
     private static final String KDC_HOST = "KDC Host:";
     private static final String KDC_PORT = "KDC Port:";
 
-
     public NewConnectionWizardBot()
     {
         super( TITLE );
@@ -208,8 +212,44 @@
 
     public void typeRealm( String realm )
     {
-        SWTBotCombo dnCombo = bot.comboBoxWithLabel( SASL_REALM );
-        dnCombo.setText( realm );
+        SWTBotCombo combo = bot.comboBoxWithLabel( SASL_REALM );
+        combo.setText( realm );
+    }
+
+
+    public void selectQualityOfProtection( SaslQoP saslQoP )
+    {
+        SWTBotCombo combo = bot.comboBoxWithLabel( SASL_QUALITY_OF_PROTECTION );
+        switch ( saslQoP )
+        {
+            case AUTH:
+                combo.setSelection( 0 );
+                break;
+            case AUTH_INT:
+                combo.setSelection( 1 );
+                break;
+            case AUTH_CONF:
+                combo.setSelection( 2 );
+                break;
+        }
+    }
+
+
+    public void selectProtectionStrength( SaslSecurityStrength saslSecurityStrength )
+    {
+        SWTBotCombo combo = bot.comboBoxWithLabel( SASL_PROTECTION_STRENGH );
+        switch ( saslSecurityStrength )
+        {
+            case HIGH:
+                combo.setSelection( 0 );
+                break;
+            case MEDIUM:
+                combo.setSelection( 1 );
+                break;
+            case LOW:
+                combo.setSelection( 2 );
+                break;
+        }
     }
 
 
@@ -370,13 +410,33 @@
     }
 
 
+    public boolean isViewCertificateButtonEnabled()
+    {
+        return bot.button( VIEW_CERTIFICATE ).isEnabled();
+    }
+
+
+    public CertificateViewerDialogBot clickViewCertificateButton()
+    {
+        bot.button( VIEW_CERTIFICATE ).click();
+        return new CertificateViewerDialogBot();
+    }
+
+
+    public boolean isCheckNetworkParameterButtonEnabled()
+    {
+        return bot.button( CHECK_NETWORK_PARAMETER ).isEnabled();
+    }
+
+
     /**
      * Clicks the "check network parameter" button.
      * 
      * @return null if the OK dialog pops up, the error message if the error dialog pops up
      */
-    public String clickCheckNetworkParameterButton()
+    public CheckResponse clickCheckNetworkParameterButton()
     {
+        activate();
         return clickCheckButton( CHECK_NETWORK_PARAMETER, CHECK_NETWORK_PARAMETER );
     }
 
@@ -399,7 +459,8 @@
      */
     public String clickCheckAuthenticationButton()
     {
-        return clickCheckButton( CHECK_AUTHENTICATION, CHECK_AUTHENTICATION );
+        CheckResponse checkResponse = clickCheckButton( CHECK_AUTHENTICATION, CHECK_AUTHENTICATION );
+        return checkResponse.isError() ? checkResponse.getMessage() : null;
     }
 
 
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/NewEntryWizardBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/NewEntryWizardBot.java
index 3cf573b..98c8660 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/NewEntryWizardBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/NewEntryWizardBot.java
@@ -19,9 +19,10 @@
  */
 package org.apache.directory.studio.test.integration.ui.bots;
 
+
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
-import org.apache.directory.studio.test.integration.ui.bots.utils.JobWatcher;
+import org.apache.directory.studio.test.integration.ui.utils.JobWatcher;
 
 
 public class NewEntryWizardBot extends WizardBot
@@ -30,7 +31,6 @@
 
     private EntryEditorWidgetBot widgetBot;
 
-
     public NewEntryWizardBot()
     {
         super( TITLE );
@@ -94,6 +94,20 @@
     }
 
 
+    public NewAttributeWizardBot openNewAttributeWizard()
+    {
+        widgetBot.isVisisble();
+        return widgetBot.openNewAttributeWizard();
+    }
+
+
+    public EditAttributeWizardBot editAttribute( String attributeType, String value )
+    {
+        widgetBot.isVisisble();
+        return widgetBot.editAttribute( attributeType, value );
+    }
+
+
     public void editValue( String attributeType, String value )
     {
         widgetBot.isVisisble();
@@ -113,7 +127,7 @@
         while ( true )
         {
             String text = bot.text( 1 ).getText();
-            
+
             if ( Dn.isValid( text ) )
             {
                 return text;
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/NewWizardBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/NewWizardBot.java
index 82fdbca..aa3ab98 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/NewWizardBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/NewWizardBot.java
@@ -28,7 +28,7 @@
 
     public NewWizardBot()
     {
-        super( "New" );
+        super( "Select a wizard" );
     }
 
 
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/PasswordEditorDialogBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/PasswordEditorDialogBot.java
index 6016ec1..0a0e3d0 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/PasswordEditorDialogBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/PasswordEditorDialogBot.java
@@ -21,6 +21,7 @@
 
 
 import org.apache.directory.api.ldap.model.constants.LdapSecurityConstants;
+import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
 
 
 public class PasswordEditorDialogBot extends DialogBot
@@ -29,18 +30,7 @@
     public PasswordEditorDialogBot()
     {
         super( "Password Editor" );
-    }
-
-
-    public void clickOkButton()
-    {
-        super.clickButton( "OK" );
-    }
-
-
-    public void clickCancelButton()
-    {
-        super.clickButton( "Cancel" );
+        super.setWaitAfterClickOkButton( true, BrowserCoreMessages.jobs__execute_ldif_name );
     }
 
 
@@ -113,13 +103,15 @@
 
     public String clickVerifyButton()
     {
-        return clickCheckButton( "Verify", "Password Verification" );
+        CheckResponse checkResponse = clickCheckButton( "Verify", "Password Verification" );
+        return checkResponse.isError() ? checkResponse.getMessage() : null;
     }
 
 
     public String clickBindButton()
     {
-        return clickCheckButton( "Bind", "Check Authentication" );
+        CheckResponse checkResponse = clickCheckButton( "Bind", "Check Authentication" );
+        return checkResponse.isError() ? checkResponse.getMessage() : null;
     }
 
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/PasswordModifyExtendedOperationDialogBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/PasswordModifyExtendedOperationDialogBot.java
index b57e621..fea139f 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/PasswordModifyExtendedOperationDialogBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/PasswordModifyExtendedOperationDialogBot.java
@@ -20,7 +20,7 @@
 package org.apache.directory.studio.test.integration.ui.bots;
 
 
-import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
+import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
 
 
 public class PasswordModifyExtendedOperationDialogBot extends DialogBot
@@ -28,6 +28,7 @@
     public PasswordModifyExtendedOperationDialogBot()
     {
         super( "Password Modify Extended Operation (RFC 3062)" );
+        super.setWaitAfterClickOkButton( true, BrowserCoreMessages.jobs__extended_operation_name );
     }
 
 
@@ -123,19 +124,4 @@
         }
     }
 
-
-    public ErrorDialogBot clickOkButtonExpectingErrorDialog()
-    {
-        SWTBotShell shell = BotUtils.shell( new Runnable()
-        {
-            public void run()
-            {
-                clickOkButton();
-            }
-        }, "Error" );
-        String shellText = shell.getText();
-
-        return new ErrorDialogBot( shellText );
-    }
-
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/PasswordsKeystorePreferencePageBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/PasswordsKeystorePreferencePageBot.java
index 9d7fcd2..bd22e97 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/PasswordsKeystorePreferencePageBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/PasswordsKeystorePreferencePageBot.java
@@ -20,15 +20,9 @@
 package org.apache.directory.studio.test.integration.ui.bots;
 
 
-public class PasswordsKeystorePreferencePageBot extends DialogBot
+public class PasswordsKeystorePreferencePageBot extends PreferencePageBot
 {
 
-    public PasswordsKeystorePreferencePageBot()
-    {
-        super( "Preferences" );
-    }
-
-
     public boolean isPasswordsKeystoreEnabled()
     {
         activate();
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/Constants.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/PreferencePageBot.java
similarity index 68%
copy from tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/Constants.java
copy to tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/PreferencePageBot.java
index 4962877..3438718 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/Constants.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/PreferencePageBot.java
@@ -17,16 +17,27 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.studio.test.integration.ui;
+package org.apache.directory.studio.test.integration.ui.bots;
 
 
-import org.apache.directory.api.util.Network;
-
-
-public final class Constants
+public class PreferencePageBot extends DialogBot
 {
-    public static final String LOCALHOST = Network.LOOPBACK_HOSTNAME;
 
-    public static final String LOCALHOST_ADDRESS = Network.LOOPBACK.getHostAddress();
+    public PreferencePageBot()
+    {
+        super( "Preferences" );
+    }
+
+
+    public void clickApplyButton()
+    {
+        super.clickButton( "Apply" );
+    }
+
+
+    public void clickRestoreDefaultsButton()
+    {
+        super.clickButton( "Restore Defaults" );
+    }
 
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/PreferencesBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/PreferencesBot.java
index c65551a..e2f717d 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/PreferencesBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/PreferencesBot.java
@@ -19,7 +19,8 @@
  */
 package org.apache.directory.studio.test.integration.ui.bots;
 
-import org.apache.directory.studio.test.integration.ui.bots.utils.TreeBot;
+
+import org.apache.directory.studio.test.integration.ui.utils.TreeBot;
 
 
 public class PreferencesBot extends DialogBot
@@ -60,4 +61,27 @@
         return new PasswordsKeystorePreferencePageBot();
     }
 
+
+    public void openLdifEditorSyntaxColoringPage()
+    {
+        bot.tree().getTreeItem( "Apache Directory Studio" ).select().expand().getNode( "LDIF Editor" ).select()
+            .expand().getNode( "Syntax Coloring" ).select();
+    }
+
+
+    public SearchLogsViewPreferencePageBot openSearchLogsViewPage()
+    {
+        bot.tree().getTreeItem( "Apache Directory Studio" ).select().expand().getNode( "LDAP Browser" ).select()
+            .expand().getNode( "Views" ).expand().getNode( "Search Logs View" ).select();
+        return new SearchLogsViewPreferencePageBot();
+    }
+
+
+    public ModificationLogsViewPreferencePageBot openModificationLogsViewPage()
+    {
+        bot.tree().getTreeItem( "Apache Directory Studio" ).select().expand().getNode( "LDAP Browser" ).select()
+            .expand().getNode( "Views" ).expand().getNode( "Modification Logs View" ).select();
+        return new ModificationLogsViewPreferencePageBot();
+    }
+
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ReferralDialogBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ReferralDialogBot.java
index c68c45d..a463c49 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ReferralDialogBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ReferralDialogBot.java
@@ -21,7 +21,6 @@
 
 
 import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
-import org.apache.directory.studio.test.integration.ui.bots.utils.JobWatcher;
 import org.eclipse.swtbot.swt.finder.utils.TableCollection;
 import org.eclipse.swtbot.swt.finder.utils.TableRow;
 
@@ -32,16 +31,9 @@
     public ReferralDialogBot()
     {
         super( "Select Referral Connection" );
-    }
-
-
-    public void clickOkButton()
-    {
-        JobWatcher watcher = new JobWatcher( BrowserCoreMessages.jobs__init_entries_title_subonly,
-            BrowserCoreMessages.jobs__init_entries_title_attonly,
-            BrowserCoreMessages.jobs__create_entry_name_1 );
-        super.clickOkButton();
-        watcher.waitUntilDone();
+        super.setWaitAfterClickOkButton( true,
+            BrowserCoreMessages.jobs__init_entries_title_subonly,
+            BrowserCoreMessages.jobs__init_entries_title_attonly, BrowserCoreMessages.jobs__create_entry_name_1 );
     }
 
 
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/RenameEntryDialogBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/RenameEntryDialogBot.java
index 76ac490..155adb8 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/RenameEntryDialogBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/RenameEntryDialogBot.java
@@ -21,7 +21,6 @@
 
 
 import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
-import org.apache.directory.studio.test.integration.ui.bots.utils.JobWatcher;
 
 
 public class RenameEntryDialogBot extends DialogBot
@@ -30,14 +29,7 @@
     public RenameEntryDialogBot()
     {
         super( "Rename Entry" );
-    }
-
-
-    public void clickOkButton()
-    {
-        JobWatcher watcher = new JobWatcher( BrowserCoreMessages.jobs__rename_entry_name );
-        super.clickOkButton();
-        watcher.waitUntilDone();
+        super.setWaitAfterClickOkButton( true, BrowserCoreMessages.jobs__rename_entry_name );
     }
 
 
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SearchDialogBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SearchDialogBot.java
index 25e2134..8aba61d 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SearchDialogBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SearchDialogBot.java
@@ -54,6 +54,12 @@
     }
 
 
+    public String getFilter()
+    {
+        return searchPageWrapperBot.getFilter();
+    }
+
+
     public void setReturningAttributes( String string )
     {
         searchPageWrapperBot.setReturningAttributes( string );
@@ -101,4 +107,10 @@
         super.clickButton( "Search" );
     }
 
+
+    public FilterEditorDialogBot openFilterEditor()
+    {
+        return searchPageWrapperBot.openFilterEditor();
+    }
+
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SearchLogsViewBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SearchLogsViewBot.java
index dd69410..f742c53 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SearchLogsViewBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SearchLogsViewBot.java
@@ -20,6 +20,9 @@
 package org.apache.directory.studio.test.integration.ui.bots;
 
 
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu;
+
+
 public class SearchLogsViewBot extends AbstractLogsViewBot
 {
     public SearchLogsViewBot()
@@ -32,4 +35,26 @@
     {
         return super.getLogsText();
     }
+
+
+    public void enableSearchRequestLogs( boolean b )
+    {
+        view.show();
+        SWTBotMenu menuItem = view.viewMenu( "Enable Search Request Logs" );
+        if ( menuItem.isChecked() != b )
+        {
+            menuItem.click();
+        }
+    }
+
+
+    public void enableSearchResultEntryLogs( boolean b )
+    {
+        view.show();
+        SWTBotMenu menuItem = view.viewMenu( "Enable Search Result Entry Logs (!)" );
+        if ( menuItem.isChecked() != b )
+        {
+            menuItem.click();
+        }
+    }
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SearchLogsViewPreferencePageBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SearchLogsViewPreferencePageBot.java
new file mode 100644
index 0000000..eba102a
--- /dev/null
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SearchLogsViewPreferencePageBot.java
@@ -0,0 +1,65 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.studio.test.integration.ui.bots;
+
+
+public class SearchLogsViewPreferencePageBot extends PreferencePageBot
+{
+
+    public void setEnableSearchRequestLogs( boolean b )
+    {
+        activate();
+        if ( b )
+        {
+            bot.checkBox( 0 ).select();
+        }
+        else
+        {
+            bot.checkBox( 0 ).deselect();
+        }
+    }
+
+
+    public void setEnableSearchResultEntryLogs( boolean b )
+    {
+        activate();
+        if ( b )
+        {
+            bot.checkBox( 1 ).select();
+        }
+        else
+        {
+            bot.checkBox( 1 ).deselect();
+        }
+    }
+
+
+    public void setLogFileCount( int i )
+    {
+        bot.text( 1 ).setText( "" + i );
+    }
+
+
+    public void setLogFileSize( int i )
+    {
+        bot.text( 2 ).setText( "" + i );
+    }
+
+}
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SearchPageWrapperBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SearchPageWrapperBot.java
index 4ff6509..b0a3567 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SearchPageWrapperBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SearchPageWrapperBot.java
@@ -54,6 +54,12 @@
     }
 
 
+    String getFilter()
+    {
+        return bot.comboBoxWithLabel( "Filter:" ).getText();
+    }
+
+
     void setReturningAttributes( String string )
     {
         bot.comboBoxWithLabel( "Returning Attributes:" ).setText( string );
@@ -154,4 +160,11 @@
         bot.textWithLabel( "Count Limit:" ).setText( "" + countLimit );
     }
 
+
+    public FilterEditorDialogBot openFilterEditor()
+    {
+        bot.button( "Filter Editor..." ).click();
+        return new FilterEditorDialogBot();
+    }
+
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SearchPropertiesDialogBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SearchPropertiesDialogBot.java
index 6f1b655..d1352fc 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SearchPropertiesDialogBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SearchPropertiesDialogBot.java
@@ -25,10 +25,9 @@
 
     SearchPageWrapperBot searchPageWrapperBot;
 
-
-    public SearchPropertiesDialogBot()
+    public SearchPropertiesDialogBot( String searchName)
     {
-        super( "" );
+        super( "Properties for " + searchName );
         this.searchPageWrapperBot = new SearchPageWrapperBot( bot );
     }
 
@@ -51,16 +50,4 @@
         searchPageWrapperBot.setFilter( string );
     }
 
-
-    public void clickOkButton()
-    {
-        bot.button( "OK" ).click();
-    }
-
-
-    public void clickCancelButton()
-    {
-        bot.button( "Cancel" ).click();
-    }
-
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SearchResultEditorBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SearchResultEditorBot.java
index e72e1f5..ed05bdf 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SearchResultEditorBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SearchResultEditorBot.java
@@ -27,7 +27,7 @@
 import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.withTooltip;
 
 import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
-import org.apache.directory.studio.test.integration.ui.bots.utils.JobWatcher;
+import org.apache.directory.studio.test.integration.ui.utils.JobWatcher;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.ToolItem;
 import org.eclipse.swt.widgets.Widget;
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SelectCopyDepthDialogBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SelectCopyDepthDialogBot.java
index 0a27c27..53dacc4 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SelectCopyDepthDialogBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SelectCopyDepthDialogBot.java
@@ -21,7 +21,6 @@
 
 
 import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
-import org.apache.directory.studio.test.integration.ui.bots.utils.JobWatcher;
 
 
 public class SelectCopyDepthDialogBot extends DialogBot
@@ -29,8 +28,6 @@
     private String objectText;
     private String oneLevelText;
     private String subTreeText;
-    private String jobName;
-
 
     public SelectCopyDepthDialogBot( int numEntries )
     {
@@ -40,14 +37,14 @@
             objectText = "Object (Only the copied entries)";
             oneLevelText = "One Level (Only copied entries and their direct children)";
             subTreeText = "Subtree (The whole subtrees)";
-            jobName = BrowserCoreMessages.jobs__copy_entries_name_n;
+            super.setWaitAfterClickOkButton( true, BrowserCoreMessages.jobs__copy_entries_name_n );
         }
         else
         {
             objectText = "Object (Only the copied entry)";
             oneLevelText = "One Level (Only copied entry and its direct children)";
             subTreeText = "Subtree (The whole subtree)";
-            jobName = BrowserCoreMessages.jobs__copy_entries_name_1;
+            super.setWaitAfterClickOkButton( true, BrowserCoreMessages.jobs__copy_entries_name_1 );
         }
         activate();
     }
@@ -70,12 +67,4 @@
         bot.radio( subTreeText ).click();
     }
 
-
-    public void clickOkButton()
-    {
-        JobWatcher watcher = new JobWatcher( jobName );
-        super.clickOkButton();
-        watcher.waitUntilDone();
-    }
-
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SelectCopyStrategyBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SelectCopyStrategyBot.java
index 1bcd35d..3888c74 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SelectCopyStrategyBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/SelectCopyStrategyBot.java
@@ -21,7 +21,6 @@
 
 
 import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
-import org.apache.directory.studio.test.integration.ui.bots.utils.JobWatcher;
 
 
 public class SelectCopyStrategyBot extends DialogBot
@@ -29,6 +28,7 @@
     public SelectCopyStrategyBot()
     {
         super( "Select copy strategy" );
+        super.setWaitAfterClickOkButton( true, BrowserCoreMessages.jobs__copy_entries_name_1 );
         waitForDialog();
         activate();
     }
@@ -71,12 +71,4 @@
         bot.comboBox( index ).setText( text );
     }
 
-
-    public void clickOkButton()
-    {
-        JobWatcher watcher = new JobWatcher( BrowserCoreMessages.jobs__copy_entries_name_1 );
-        super.clickOkButton();
-        watcher.waitUntilDone();
-    }
-
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ShowViewsBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ShowViewsBot.java
index 742cc5b..0c8e702 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ShowViewsBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/ShowViewsBot.java
@@ -20,7 +20,7 @@
 package org.apache.directory.studio.test.integration.ui.bots;
 
 
-import org.apache.directory.studio.test.integration.ui.bots.utils.TreeBot;
+import org.apache.directory.studio.test.integration.ui.utils.TreeBot;
 
 
 public class ShowViewsBot extends DialogBot
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/StudioBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/StudioBot.java
index bd1c3a6..ce9848b 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/StudioBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/StudioBot.java
@@ -20,6 +20,10 @@
 package org.apache.directory.studio.test.integration.ui.bots;
 
 
+import java.util.Random;
+
+import org.eclipse.e4.ui.css.swt.theme.IThemeEngine;
+import org.eclipse.e4.ui.css.swt.theme.IThemeManager;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Event;
@@ -149,6 +153,25 @@
                     IWorkbench workbench = PlatformUI.getWorkbench();
                     IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
 
+                    // set default/dark theme
+                    /*
+                    IThemeManager tm = workbench.getService( IThemeManager.class );
+                    IThemeEngine te = tm.getEngineForDisplay( Display.getCurrent() );
+                    int random = new Random().nextInt( 3 );
+                    switch ( random )
+                    {
+                        case 0:
+                            te.setTheme( "org.eclipse.e4.ui.css.theme.e4_dark", false );
+                            break;
+                        case 1:
+                            te.setTheme( "org.eclipse.e4.ui.css.theme.e4_default", false );
+                            break;
+                        case 2:
+                            te.setTheme( "org.eclipse.e4.ui.css.theme.high-contrast", false );
+                            break;
+                    }
+                    */
+
                     // close welcome view
                     IWorkbenchPage page = window.getActivePage();
                     for ( IViewReference viewref : page.getViewReferences() )
@@ -160,6 +183,14 @@
                     }
 
                     // close shells (open dialogs)
+                    Shell[] shells = Display.getCurrent().getShells();
+                    for ( Shell shell : shells )
+                    {
+                        if ( shell != null && shell != window.getShell() )
+                        {
+                            shell.close();
+                        }
+                    }
                     Shell activeShell = Display.getCurrent().getActiveShell();
                     if ( activeShell != null && activeShell != window.getShell() )
                     {
@@ -180,11 +211,8 @@
                     }
 
                     // reset LDAP perspective
-                    if ( page.getActivePart() != null )
-                    {
-                        page.closeAllEditors( false );
-                        page.resetPerspective();
-                    }
+                    page.closeAllEditors( false );
+                    page.resetPerspective();
                 }
                 catch ( Exception e )
                 {
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/TextEditorDialogBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/TextEditorDialogBot.java
index 6db4100..7e94c7d 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/TextEditorDialogBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/TextEditorDialogBot.java
@@ -29,18 +29,6 @@
     }
 
 
-    public void clickOkButton()
-    {
-        super.clickButton( "OK" );
-    }
-
-
-    public void clickCancelButton()
-    {
-        super.clickButton( "Cancel" );
-    }
-
-
     public void setText( String text )
     {
         bot.text( 0 ).setText( text );
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/WizardBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/WizardBot.java
index 92489f2..332bd91 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/WizardBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/WizardBot.java
@@ -20,7 +20,7 @@
 package org.apache.directory.studio.test.integration.ui.bots;
 
 
-import org.apache.directory.studio.test.integration.ui.bots.utils.TreeBot;
+import org.apache.directory.studio.test.integration.ui.utils.TreeBot;
 import org.eclipse.swtbot.swt.finder.waits.Conditions;
 import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
 
@@ -60,6 +60,7 @@
 
     protected boolean isButtonEnabled( String buttonTitle )
     {
+        activate();
         return bot.button( buttonTitle ).isEnabled();
     }
 
@@ -93,9 +94,10 @@
     }
 
 
-    public void clickCancelButton()
+    public ErrorDialogBot clickFinishButtonExpectingError()
     {
-        clickButton( "Cancel" );
+        String shellText = BotUtils.shell( () -> clickFinishButton(), "Error", "Problem Occurred" ).getText();
+        return new ErrorDialogBot( shellText );
     }
 
 
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/utils/FrameworkRunnerWithScreenshotCaptureListener.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/utils/FrameworkRunnerWithScreenshotCaptureListener.java
deleted file mode 100644
index acf0ee4..0000000
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/utils/FrameworkRunnerWithScreenshotCaptureListener.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you 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.apache.directory.studio.test.integration.ui.bots.utils;
-
-
-import org.apache.directory.server.core.integ.FrameworkRunner;
-import org.eclipse.swtbot.swt.finder.junit.ScreenshotCaptureListener;
-import org.junit.runner.notification.RunListener;
-import org.junit.runner.notification.RunNotifier;
-import org.junit.runners.model.InitializationError;
-
-
-public class FrameworkRunnerWithScreenshotCaptureListener extends FrameworkRunner
-{
-
-    public FrameworkRunnerWithScreenshotCaptureListener( Class<?> clazz ) throws InitializationError
-    {
-        super( clazz );
-    }
-
-
-    public void run( RunNotifier notifier )
-    {
-        RunListener failureSpy = new ScreenshotCaptureListener();
-        notifier.removeListener( failureSpy );
-        notifier.addListener( failureSpy );
-        try
-        {
-            super.run( notifier );
-        }
-        finally
-        {
-            notifier.removeListener( failureSpy );
-        }
-    }
-
-}
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ApacheDsUtils.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/ApacheDsUtils.java
similarity index 94%
rename from tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ApacheDsUtils.java
rename to tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/ApacheDsUtils.java
index 3600f7b..4304613 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ApacheDsUtils.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/ApacheDsUtils.java
@@ -18,10 +18,10 @@
  *  
  */
 
-package org.apache.directory.studio.test.integration.ui;
+package org.apache.directory.studio.test.integration.ui.utils;
 
 
-import static org.apache.directory.studio.test.integration.ui.Constants.LOCALHOST;
+import static org.apache.directory.studio.test.integration.ui.utils.Constants.LOCALHOST;
 
 import java.util.Hashtable;
 
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/utils/Assertions.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/Assertions.java
similarity index 93%
rename from tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/utils/Assertions.java
rename to tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/Assertions.java
index 0bbc599..9039413 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/utils/Assertions.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/Assertions.java
@@ -17,10 +17,10 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.studio.test.integration.ui.bots.utils;
+package org.apache.directory.studio.test.integration.ui.utils;
 
 
-import static org.junit.Assert.fail;
+import static org.junit.jupiter.api.Assertions.fail;
 
 import org.apache.directory.studio.connection.core.Messages;
 import org.apache.directory.studio.test.integration.ui.bots.BotUtils;
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/utils/Characters.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/Characters.java
similarity index 95%
rename from tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/utils/Characters.java
rename to tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/Characters.java
index f9b51a5..830eb5b 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/utils/Characters.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/Characters.java
@@ -17,14 +17,12 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.studio.test.integration.ui.bots.utils;
+package org.apache.directory.studio.test.integration.ui.utils;
 
 
 import java.nio.charset.StandardCharsets;
 import java.util.Base64;
 
-import org.junit.Test;
-
 
 public class Characters
 {
@@ -60,7 +58,6 @@
     }
 
 
-    @Test
     public void print()
     {
         System.out.println( LATIN_A );
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/Constants.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/Constants.java
similarity index 94%
rename from tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/Constants.java
rename to tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/Constants.java
index 4962877..0f5db92 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/Constants.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/Constants.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.studio.test.integration.ui;
+package org.apache.directory.studio.test.integration.ui.utils;
 
 
 import org.apache.directory.api.util.Network;
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ContextMenuHelper.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/ContextMenuHelper.java
similarity index 98%
rename from tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ContextMenuHelper.java
rename to tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/ContextMenuHelper.java
index d8dac4e..de5bb61 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/ContextMenuHelper.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/ContextMenuHelper.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.studio.test.integration.ui;
+package org.apache.directory.studio.test.integration.ui.utils;
 
 
 import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.withRegex;
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/utils/JobWatcher.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/JobWatcher.java
similarity index 95%
rename from tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/utils/JobWatcher.java
rename to tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/JobWatcher.java
index 9744b5e..44cdc76 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/utils/JobWatcher.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/JobWatcher.java
@@ -17,10 +17,9 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.studio.test.integration.ui.bots.utils;
+package org.apache.directory.studio.test.integration.ui.utils;
 
 
-import java.time.Instant;
 import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -28,6 +27,7 @@
 import org.apache.directory.studio.common.core.jobs.StudioJob;
 import org.apache.directory.studio.connection.core.jobs.StudioConnectionRunnableWithProgress;
 import org.apache.directory.studio.connection.ui.RunnableContextRunner;
+import org.apache.directory.studio.test.integration.ui.bots.BotUtils;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.jobs.IJobChangeEvent;
 import org.eclipse.core.runtime.jobs.IJobManager;
@@ -52,7 +52,6 @@
     private final RunnableContextRunner.Listener runnnableContextRunnerListener;
     private final List<String> jobNames;
 
-
     private void removeListeners()
     {
         jobManager.removeJobChangeListener( jobChangeListener );
@@ -119,11 +118,9 @@
     public void waitUntilDone()
     {
         // System.out.println( "Wait for jobs: " + jobNames );
-        Instant start = Instant.now();
         SWTBot bot = new SWTBot();
         bot.waitUntil( new DefaultCondition()
         {
-
             public boolean test() throws Exception
             {
                 if ( done.get() )
@@ -143,5 +140,8 @@
                 return "Waited for jobs " + jobNames + " to finish";
             }
         }, SWTBotPreferences.TIMEOUT * 4 );
+
+        // Wait a bit longer after job is done to allow UI update
+        BotUtils.sleep( 100L );
     }
 }
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/ResourceUtils.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/ResourceUtils.java
new file mode 100644
index 0000000..dac7de2
--- /dev/null
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/ResourceUtils.java
@@ -0,0 +1,51 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.studio.test.integration.ui.utils;
+
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.UUID;
+
+import org.apache.directory.api.util.IOUtils;
+import org.apache.directory.studio.test.integration.ui.Activator;
+import org.eclipse.core.runtime.Platform;
+
+
+public class ResourceUtils
+{
+    public static String prepareInputFile( String inputFileName ) throws IOException
+    {
+        URL url = Platform.getInstanceLocation().getURL();
+        String destFile = url.getFile() + UUID.randomUUID().toString();
+
+        try ( InputStream is = Activator.class.getResourceAsStream( inputFileName );
+            FileOutputStream fos = new FileOutputStream( new File( destFile ) ); )
+        {
+            IOUtils.copy( is, fos );
+        }
+
+        return destFile;
+    }
+
+}
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/SWTBotUtils.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/SWTBotUtils.java
similarity index 99%
rename from tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/SWTBotUtils.java
rename to tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/SWTBotUtils.java
index afe8515..6235c7c 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/SWTBotUtils.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/SWTBotUtils.java
@@ -18,7 +18,7 @@
  *  
  */
 
-package org.apache.directory.studio.test.integration.ui;
+package org.apache.directory.studio.test.integration.ui.utils;
 
 
 import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.widgetOfType;
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/utils/StudioSystemUtils.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/StudioSystemUtils.java
similarity index 94%
rename from tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/utils/StudioSystemUtils.java
rename to tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/StudioSystemUtils.java
index d15e955..5215236 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/utils/StudioSystemUtils.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/StudioSystemUtils.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.studio.test.integration.ui.bots.utils;
+package org.apache.directory.studio.test.integration.ui.utils;
 
 
 import org.apache.commons.lang3.SystemUtils;
diff --git a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/utils/TreeBot.java b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/TreeBot.java
similarity index 96%
rename from tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/utils/TreeBot.java
rename to tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/TreeBot.java
index 2427b92..33e2bbf 100644
--- a/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/bots/utils/TreeBot.java
+++ b/tests/test.integration.ui/src/main/java/org/apache/directory/studio/test/integration/ui/utils/TreeBot.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.studio.test.integration.ui.bots.utils;
+package org.apache.directory.studio.test.integration.ui.utils;
 
 
 import java.util.Arrays;
diff --git a/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/BrowserTest.ldif b/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/BrowserTest.ldif
deleted file mode 100644
index 08c54eb..0000000
--- a/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/BrowserTest.ldif
+++ /dev/null
@@ -1,292 +0,0 @@
-#  Licensed to the Apache Software Foundation (ASF) under one
-#  or more contributor license agreements.  See the NOTICE file
-#  distributed with this work for additional information
-#  regarding copyright ownership.  The ASF licenses this file
-#  to you 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.
-#
-dn: uid=user.1,ou=users,ou=system
-objectClass: top
-objectClass: person
-objectClass: organizationalPerson
-objectClass: inetOrgPerson
-givenName: Aaccf
-sn: Amar
-cn: Aaccf Amar
-initials: AA
-uid: user.1
-mail: user.1@null
-userPassword: password
-telephoneNumber: 976-893-3312
-homePhone: 337-310-0727
-pager: 185-156-4071
-mobile: 626-188-0934
-employeeNumber: 1
-street: 27919 Broadway Street
-l: Tallahassee
-st: DE
-postalCode: 67698
-postalAddress: Aaccf Amar$27919 Broadway Street$Tallahassee, DE  67698
-description: This is the description for Aaccf Amar.
-roomNumber: 1388
-
-dn: uid=user.2,ou=users,ou=system
-objectClass: top
-objectClass: person
-objectClass: organizationalPerson
-objectClass: inetOrgPerson
-givenName: Aaren
-sn: Atp
-cn: Aaren Atp
-initials: AA
-uid: user.2
-mail: user.2@null
-userPassword: password
-telephoneNumber: 147-953-0396
-homePhone: 174-439-5329
-pager: 617-443-8449
-mobile: 045-464-2512
-employeeNumber: 2
-street: 36109 Center Street
-l: Harlingen
-st: CO
-postalCode: 21733
-postalAddress: Aaren Atp$36109 Center Street$Harlingen, CO  21733
-description: This is the description for Aaren Atp.
-roomNumber: 1198
-
-dn: uid=user.3,ou=users,ou=system
-objectClass: top
-objectClass: person
-objectClass: organizationalPerson
-objectClass: inetOrgPerson
-givenName: Aarika
-sn: Atpco
-cn: Aarika Atpco
-initials: AA
-uid: user.3
-mail: user.3@null
-userPassword: password
-telephoneNumber: 925-356-4943
-homePhone: 099-983-0308
-pager: 806-672-7363
-mobile: 425-493-8009
-employeeNumber: 3
-street: 14730 Fourteenth Street
-l: Evansville
-st: ND
-postalCode: 95526
-postalAddress: Aarika Atpco$14730 Fourteenth Street$Evansville, ND  95526
-description: This is the description for Aarika Atpco.
-roomNumber: 1135
-
-dn: uid=user.4,ou=users,ou=system
-objectClass: top
-objectClass: person
-objectClass: organizationalPerson
-objectClass: inetOrgPerson
-givenName: Aaron
-sn: Atrc
-cn: Aaron Atrc
-initials: AA
-uid: user.4
-mail: user.4@null
-userPassword: password
-telephoneNumber: 696-981-0488
-homePhone: 854-401-1330
-pager: 389-028-9518
-mobile: 117-882-4912
-employeeNumber: 4
-street: 98495 Fifteenth Street
-l: Miami
-st: PA
-postalCode: 16887
-postalAddress: Aaron Atrc$98495 Fifteenth Street$Miami, PA  16887
-description: This is the description for Aaron Atrc.
-roomNumber: 1311
-
-dn: uid=user.5,ou=users,ou=system
-objectClass: top
-objectClass: person
-objectClass: organizationalPerson
-objectClass: inetOrgPerson
-givenName: Aartjan
-sn: Aalders
-cn: Aartjan Aalders
-initials: AA
-uid: user.5
-mail: user.5@null
-userPassword: password
-telephoneNumber: 657-627-9753
-homePhone: 109-158-4533
-pager: 801-392-0010
-mobile: 763-973-0947
-employeeNumber: 5
-street: 52408 Ridge Street
-l: Omaha
-st: AR
-postalCode: 08015
-postalAddress: Aartjan Aalders$52408 Ridge Street$Omaha, AR  08015
-description: This is the description for Aartjan Aalders.
-roomNumber: 1090
-
-dn: uid=user.6,ou=users,ou=system
-objectClass: top
-objectClass: person
-objectClass: organizationalPerson
-objectClass: inetOrgPerson
-givenName: Abagael
-sn: Aasen
-cn: Abagael Aasen
-initials: AA
-uid: user.6
-mail: user.6@null
-userPassword: password
-telephoneNumber: 600-556-9017
-homePhone: 543-731-7797
-pager: 349-743-6572
-mobile: 042-921-9717
-employeeNumber: 6
-street: 87514 Dogwood Street
-l: Bloomington
-st: ID
-postalCode: 56762
-postalAddress: Abagael Aasen$87514 Dogwood Street$Bloomington, ID  56762
-description: This is the description for Abagael Aasen.
-roomNumber: 1449
-
-dn: uid=user.7,ou=users,ou=system
-objectClass: top
-objectClass: person
-objectClass: organizationalPerson
-objectClass: inetOrgPerson
-givenName: Abagail
-sn: Abadines
-cn: Abagail Abadines
-initials: AA
-uid: user.7
-mail: user.7@null
-userPassword: password
-telephoneNumber: 628-294-0713
-homePhone: 313-764-3970
-pager: 118-541-2978
-mobile: 111-360-9243
-employeeNumber: 7
-street: 60751 Main Street
-l: Macon
-st: MI
-postalCode: 38755
-postalAddress: Abagail Abadines$60751 Main Street$Macon, MI  38755
-description: This is the description for Abagail Abadines.
-roomNumber: 1312
-
-dn: uid=user.8,ou=users,ou=system
-objectClass: top
-objectClass: person
-objectClass: organizationalPerson
-objectClass: inetOrgPerson
-givenName: Abahri
-sn: Abazari
-cn: Abahri Abazari
-initials: AA
-uid: user.8
-mail: user.8@null
-userPassword: password
-telephoneNumber: 760-373-5805
-homePhone: 856-861-3648
-pager: 271-218-0027
-mobile: 957-465-6928
-employeeNumber: 8
-street: 81023 River Street
-l: Monroe
-st: SD
-postalCode: 51865
-postalAddress: Abahri Abazari$81023 River Street$Monroe, SD  51865
-description: This is the description for Abahri Abazari.
-roomNumber: 1963
-
-dn: cn=\#ACL_AD-Projects_Author,ou=users,ou=system
-objectClass: top
-objectClass: person
-cn: #ACL_AD-Projects_Author
-sn: #ACL_AD-Projects_Author
-
-dn: cn=nghZwwtHgxgyvVbTQCYyeY\+O4cc=,ou=users,ou=system
-objectClass: top
-objectClass: person
-cn: nghZwwtHgxgyvVbTQCYyeY+O4cc=
-sn: nghZwwtHgxgyvVbTQCYyeY+O4cc=
-
-dn: cn=nghZwwtHgxgyvVbTQCYyeY+email=,ou=users,ou=system
-objectClass: top
-objectClass: person
-objectClass: extensibleObject
-cn: nghZwwtHgxgyvVbTQCYyeY
-sn: nghZwwtHgxgyvVbTQCYyeY
-email: 
-
-dn: l=eu + l=de + l=Berlin + l=Brandenburger Tor, ou=users, ou=system
-objectClass: top
-objectClass: locality
-l: eu
-l: de
-l: Berlin
-l: Brandenburger Tor
-
-dn: cn=A, l=eu + l=de + l=Berlin + l=Brandenburger Tor, ou=users, ou=system
-objectClass: top
-objectClass: person
-cn: user.A
-sn: user.A
-
-dn: uid=user.0\,foo,ou=users, ou=system
-objectClass: top
-objectClass: person
-objectClass: organizationalPerson
-objectClass: inetOrgPerson
-sn: bbb
-cn: aaa
-uid: user.0,foo
-
-dn: ou=target,ou=system
-objectClass: top
-objectClass: organizationalUnit
-ou: target
-administrativeRole: accessControlSpecificArea
-
-dn: ou=special,ou=system
-objectClass: top
-objectClass: organizationalUnit
-ou: special
-administrativeRole: accessControlSpecificArea
-
-dn: cn=alias,ou=special,ou=system
-objectClass: alias
-objectClass: top
-objectClass: extensibleObject
-cn: alias
-aliasedObjectName: ou=special,ou=system
-
-dn: cn=referral,ou=special,ou=system
-objectClass: referral
-objectClass: top
-objectClass: extensibleObject
-cn: referral
-ref: ldap://foo.example.com/ou=system
-
-dn: cn=subentry,ou=special,ou=system
-objectClass: subentry
-objectClass: top
-cn: subentry
-subtreeSpecification: { }
-
diff --git a/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/DIRSTUDIO-1160.ldif b/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/DIRSTUDIO-1160.ldif
index d504a32..3b58de6 100644
--- a/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/DIRSTUDIO-1160.ldif
+++ b/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/DIRSTUDIO-1160.ldif
@@ -17,7 +17,7 @@
 #

 version: 1

 

-dn: cn=U0034692,ou=users,ou=system

+dn: cn=U0034692,ou=misc,dc=example,dc=org

 sn: Doe

 displayName:: SsO2aG4gRG/DpGXDtg==

 givenName:: SsO2aG4gRG/DpGXDtg==

diff --git a/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/EntryEditorTest.ldif b/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/EntryEditorTest.ldif
deleted file mode 100644
index 84ecb2a..0000000
--- a/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/EntryEditorTest.ldif
+++ /dev/null
@@ -1,69 +0,0 @@
-#  Licensed to the Apache Software Foundation (ASF) under one
-#  or more contributor license agreements.  See the NOTICE file
-#  distributed with this work for additional information
-#  regarding copyright ownership.  The ASF licenses this file
-#  to you 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.
-#
-dn: cn=Barbara Jensen,ou=users,ou=system
-objectClass: inetOrgPerson
-objectClass: organizationalPerson
-objectClass: person
-objectClass: top
-cn: Barbara Jensen
-sn: Jensen
-givenName: Barbara
-uid: bjensen
-
-dn: uid=hnelson,ou=users,ou=system
-objectClass: inetOrgPerson
-objectClass: organizationalPerson
-objectClass: person
-objectClass: top
-cn: Horatio Nelson
-sn: Nelson
-uid: hnelson
-description:: QSDDqSDigqwg0K8gzrsg16kg2Lkg4ruhIA==
-userPassword:: e1NTSEE1MTJ9aUlyTG1uR0MxdTNaTGFPWmRvSjZUMjBKdG9XQ05wWjArWGFLRnN
- 5bEVEdFpYK3I3bUZrcjRwYTNKMXE3VWpSZ3ZFV2lCd1FNUjZadjBoYnRsYnRqSTQ2TmR6WVRDdG9G
-jpegPhoto:: /9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw
- 8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRw
- hMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAAB
- AAEDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEA
- wUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKS
- o0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqK
- jpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QA
- HwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEB
- SExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSE
- lKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba
- 3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3+iii
- gD//2Q==
-
-# cn=\#\\\+\, \"öé\",ou=users,ou=system
-dn:: Y249XCNcXFwrXCwgXCLDtsOpXCIsb3U9dXNlcnMsb3U9c3lzdGVt
-objectClass: inetOrgPerson
-objectClass: organizationalPerson
-objectClass: person
-objectClass: top
-cn:: I1wrLCAiw7bDqSI=
-sn:: I1wrLCAiw7bDqSI=
-givenName:: I1wrLCAiw7bDqSI=
-uid:: I1wrLCAiw7bDqSI=
-
-dn: cn=My Group,ou=groups,ou=system
-objectClass: groupOfNames
-objectClass: top
-cn: My Group
-member: cn=Barbara Jensen,ou=users,ou=system
-
-
diff --git a/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/ImportExportTest.ldif b/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/ImportExportTest.ldif
deleted file mode 100644
index 9a4bd36..0000000
--- a/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/ImportExportTest.ldif
+++ /dev/null
@@ -1,53 +0,0 @@
-#  Licensed to the Apache Software Foundation (ASF) under one
-#  or more contributor license agreements.  See the NOTICE file
-#  distributed with this work for additional information
-#  regarding copyright ownership.  The ASF licenses this file
-#  to you 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.
-#
-dn:: Y249V29sZmdhbmcgS8O2bGJlbCxvdT11c2VycyxvdT1zeXN0ZW0=
-objectClass: person
-objectClass: organizationalPerson
-objectClass: inetOrgPerson
-objectClass: top
-cn:: V29sZmdhbmcgS8O2bGJlbA==
-sn:: S8O2bGJlbA==
-description: =1+1
-
-dn: ou=special,ou=system
-objectClass: top
-objectClass: organizationalUnit
-ou: special
-administrativeRole: accessControlSpecificArea
-
-dn: cn=alias,ou=special,ou=system
-objectClass: alias
-objectClass: top
-objectClass: extensibleObject
-cn: alias
-aliasedObjectName: ou=special,ou=system
-
-dn: cn=referral,ou=special,ou=system
-objectClass: referral
-objectClass: top
-objectClass: extensibleObject
-cn: referral
-ref: ldap://foo.example.com/ou=system
-
-dn: cn=subentry,ou=special,ou=system
-objectClass: subentry
-objectClass: top
-cn: subentry
-subtreeSpecification: { }
-
-
diff --git a/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/ImportExportTest_Modifications.ldif b/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/ImportExportTest_Modifications.ldif
index c9672be..0042152 100644
--- a/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/ImportExportTest_Modifications.ldif
+++ b/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/ImportExportTest_Modifications.ldif
@@ -15,85 +15,8 @@
 #  specific language governing permissions and limitations
 #  under the License.
 #
-dn: uid=user.1,ou=users,ou=system
-changetype: add
-objectClass: top
-objectClass: person
-objectClass: organizationalPerson
-objectClass: inetOrgPerson
-givenName: Aaccf
-sn: Amar
-cn: Aaccf Amar
-initials: AA
-uid: user.1
-mail: user.1@null
-userPassword: password
-telephoneNumber: 976-893-3312
-homePhone: 337-310-0727
-pager: 185-156-4071
-mobile: 626-188-0934
-employeeNumber: 1
-street: 27919 Broadway Street
-l: Tallahassee
-st: DE
-postalCode: 67698
-postalAddress: Aaccf Amar$27919 Broadway Street$Tallahassee, DE  67698
-description: This is the description for Aaccf Amar.
-roomNumber: 0000
 
-dn: uid=user.2,ou=users,ou=system
-changetype: add
-objectClass: top
-objectClass: person
-objectClass: organizationalPerson
-objectClass: inetOrgPerson
-givenName: Aaren
-sn: Atp
-cn: Aaren Atp
-initials: AA
-uid: user.2
-mail: user.2@null
-userPassword: password
-telephoneNumber: 147-953-0396
-homePhone: 174-439-5329
-pager: 617-443-8449
-mobile: 045-464-2512
-employeeNumber: 2
-street: 36109 Center Street
-l: Harlingen
-st: CO
-postalCode: 21733
-postalAddress: Aaren Atp$36109 Center Street$Harlingen, CO  21733
-description: This is the description for Aaren Atp.
-roomNumber: 1198
-
-dn: uid=user.3,ou=users,ou=system
-changetype: add
-objectClass: top
-objectClass: person
-objectClass: organizationalPerson
-objectClass: inetOrgPerson
-givenName: Aarika
-sn: Atpco
-cn: Aarika Atpco
-initials: AA
-uid: user.3
-mail: user.3@null
-userPassword: password
-telephoneNumber: 925-356-4943
-homePhone: 099-983-0308
-pager: 806-672-7363
-mobile: 425-493-8009
-employeeNumber: 3
-street: 14730 Fourteenth Street
-l: Evansville
-st: ND
-postalCode: 95526
-postalAddress: Aarika Atpco$14730 Fourteenth Street$Evansville, ND  95526
-description: This is the description for Aarika Atpco.
-roomNumber: 1135
-
-dn: uid=user.1,ou=users,ou=system
+dn: uid=user.1,ou=users,dc=example,dc=org
 changetype: modify
 delete: initials
 initials: AA
@@ -103,6 +26,12 @@
 add: description
 description:: QSDDqSDigqwg0K8gzrsg16kg2Lkg4ruhIA==
 -
+add: description;lang-en
+description;lang-en: English
+-
+add: description;lang-de
+description;lang-de: Deutsch
+-
 add: roomNumber
 roomNumber: 1234
 roomNumber: 2345
@@ -114,14 +43,28 @@
 employeeType: Intern
 -
 replace: mail
-mail: mail: user.1@example.com
-mail: mail: Aaccf.Amar@example.com
+mail: user.1@example.com
+mail: Aaccf.Amar@example.com
+-
+add: userCertificate;binary
+userCertificate;binary:: MIICcTCCAdqgAwIBAgIBEjANBgkqhkiG9w0BAQUFADBDMRMwEQYKCZImiZPy
+ LGQBGRYDY29tMRcwFQYKCZImiZPyLGQBGRYHZXhhbXBsZTETMBEGA1UEAxMKRXhhbXBsZSBDQTAeF
+ w0wNDA5MTUxMTQ4MjFaFw0wNTAzMTUxMTQ4MjFaMEMxEzARBgoJkiaJk/IsZAEZFgNjb20xFzAVBg
+ oJkiaJk/IsZAEZFgdleGFtcGxlMRMwEQYDVQQDEwpFbmQgRW50aXR5MIGfMA0GCSqGSIb3DQEBAQU
+ AA4GNADCBiQKBgQDhauQDMJcCPPQQ87UeTX8Ue/b10HjppIrwo3Xs7bZWln+ImYWa8j5od4frntGf
+ wLQX3KuJI6QdfhYjTE+oTfUxuHyq4xpJCfRLJtsnZzCCEgFK6Rq2wQxTi2z8L3pD7DM2fjKye9Wqz
+ wEUxhLsE/ItFHqLIVgUE0xGo5ryFpX/IwIDAQABo3UwczAhBgNVHREEGjAYgRZlbmQuZW50aXR5QG
+ V4YW1wbGUuY29tMB0GA1UdDgQWBBQXe5Iw/0TWZuGQECJsFk/AjkHdbTAfBgNVHSMEGDAWgBQIaK+
+ FM8g5Snr4gpOOcGpKIIQsMjAOBgNVHQ8BAf8EBAMCBsAwDQYJKoZIhvcNAQEFBQADgYEAACAoNFto
+ MgG7CjYOrXHFlRrhBM+urcdiFKQbNjHA4gw92R7AANwQoLqFb0HLYnq3TGOBJl7SgEVeM+dwRTs5O
+ yZKnDvyJjZpCHm7+5ZDd0thi6GrkWTg8zdhPBqjpMmKsr9z1E3kWORi6rwgdJKGDs6EYHbpc7vHhd
+ ORRepiXc0=
 
 
-dn: uid=user.2,ou=users,ou=system
+dn: uid=user.2,ou=users,dc=example,dc=org
 changetype: delete
 
-dn: uid=user.3,ou=users,ou=system
+dn: uid=user.3,ou=users,dc=example,dc=org
 changetype: moddn
 newrdn: uid=user.33
 deleteoldrdn: 1
diff --git a/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/ImportExportTest_ImportDontUpdateUI.ldif b/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/ImportExportTest_User1to8.ldif
similarity index 88%
rename from tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/ImportExportTest_ImportDontUpdateUI.ldif
rename to tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/ImportExportTest_User1to8.ldif
index 1c800ea..4b39ca7 100644
--- a/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/ImportExportTest_ImportDontUpdateUI.ldif
+++ b/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/ImportExportTest_User1to8.ldif
@@ -15,7 +15,7 @@
 #  specific language governing permissions and limitations
 #  under the License.
 #
-dn: uid=User.1,ou=users,ou=system
+dn: uid=User.1,ou=misc.1.1.1,ou=misc.1.1,ou=misc.1,ou=misc,dc=example,dc=org
 objectClass: top
 objectClass: person
 objectClass: organizationalPerson
@@ -40,7 +40,7 @@
 description: This is the description for Aaccf Amar.
 roomNumber: 1388
 
-dn: uid=user.2,ou=users,ou=system
+dn: uid=user.2,ou=misc.1.1.1,ou=misc.1.1,ou=misc.1,ou=misc,dc=example,dc=org
 objectClass: top
 objectClass: person
 objectClass: organizationalPerson
@@ -65,7 +65,7 @@
 description: This is the description for Aaren Atp.
 roomNumber: 1198
 
-dn: uid=user.3,ou=users,ou=system
+dn: uid=user.3,ou=misc.1.1.1,ou=misc.1.1,ou=misc.1,ou=misc,dc=example,dc=org
 objectClass: top
 objectClass: person
 objectClass: organizationalPerson
@@ -90,7 +90,7 @@
 description: This is the description for Aarika Atpco.
 roomNumber: 1135
 
-dn: uid=user.4,ou=users,ou=system
+dn: uid=user.4,ou=misc.1.1.1,ou=misc.1.1,ou=misc.1,ou=misc,dc=example,dc=org
 objectClass: top
 objectClass: person
 objectClass: organizationalPerson
@@ -115,7 +115,7 @@
 description: This is the description for Aaron Atrc.
 roomNumber: 1311
 
-dn: uid=user.5,ou=users,ou=system
+dn: uid=user.5,ou=misc.1.1.1,ou=misc.1.1,ou=misc.1,ou=misc,dc=example,dc=org
 objectClass: top
 objectClass: person
 objectClass: organizationalPerson
@@ -140,7 +140,7 @@
 description: This is the description for Aartjan Aalders.
 roomNumber: 1090
 
-dn: uid=user.6,ou=users,ou=system
+dn: uid=user.6,ou=misc.1.1.1,ou=misc.1.1,ou=misc.1,ou=misc,dc=example,dc=org
 objectClass: top
 objectClass: person
 objectClass: organizationalPerson
@@ -165,7 +165,7 @@
 description: This is the description for Abagael Aasen.
 roomNumber: 1449
 
-dn: uid=user.7,ou=users,ou=system
+dn: uid=user.7,ou=misc.1.1.1,ou=misc.1.1,ou=misc.1,ou=misc,dc=example,dc=org
 objectClass: top
 objectClass: person
 objectClass: organizationalPerson
@@ -190,7 +190,7 @@
 description: This is the description for Abagail Abadines.
 roomNumber: 1312
 
-dn: uid=user.8,ou=users,ou=system
+dn: uid=user.8,ou=misc.1.1.1,ou=misc.1.1,ou=misc.1,ou=misc,dc=example,dc=org
 objectClass: top
 objectClass: person
 objectClass: organizationalPerson
diff --git a/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/RenameEntryDialogTest.ldif b/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/RenameEntryDialogTest.ldif
deleted file mode 100644
index 197592f..0000000
--- a/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/RenameEntryDialogTest.ldif
+++ /dev/null
@@ -1,48 +0,0 @@
-#  Licensed to the Apache Software Foundation (ASF) under one
-#  or more contributor license agreements.  See the NOTICE file
-#  distributed with this work for additional information
-#  regarding copyright ownership.  The ASF licenses this file
-#  to you 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.
-#
-dn: cn=Barbara Jensen+uid=bjensen,ou=users,ou=system
-objectClass: inetOrgPerson
-objectClass: organizationalPerson
-objectClass: person
-objectClass: top
-cn: Barbara Jensen
-sn: Jensen
-givenName: Barbara
-uid: bjensen
-
-# cn=\#\\\+\, \"öé\",ou=users,ou=system
-dn:: Y249XCNcXFwrXCwgXCLDtsOpXCIsb3U9dXNlcnMsb3U9c3lzdGVt
-objectClass: inetOrgPerson
-objectClass: organizationalPerson
-objectClass: person
-objectClass: top
-cn:: I1wrLCAiw7bDqSI=
-sn:: I1wrLCAiw7bDqSI=
-givenName:: I1wrLCAiw7bDqSI=
-uid:: I1wrLCAiw7bDqSI=
-
-dn: cn=\#123456,ou=users,ou=system
-objectClass: inetOrgPerson
-objectClass: organizationalPerson
-objectClass: person
-objectClass: top
-cn: #123456
-sn: #123456
-givenName: #123456
-uid: #123456
-
diff --git a/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/allbytes.data b/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/allbytes.data
new file mode 100644
index 0000000..c866266
--- /dev/null
+++ b/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/allbytes.data
Binary files differ
diff --git a/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/rfc5280_cert1.cer b/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/rfc5280_cert1.cer
new file mode 100644
index 0000000..bad00d0
--- /dev/null
+++ b/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/rfc5280_cert1.cer
Binary files differ
diff --git a/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/rfc5280_cert2.cer b/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/rfc5280_cert2.cer
new file mode 100644
index 0000000..34af010
--- /dev/null
+++ b/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/rfc5280_cert2.cer
Binary files differ
diff --git a/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/rfc5280_cert3.cer b/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/rfc5280_cert3.cer
new file mode 100644
index 0000000..f9613dc
--- /dev/null
+++ b/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/rfc5280_cert3.cer
Binary files differ
diff --git a/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/rfc5280_crl.crl b/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/rfc5280_crl.crl
new file mode 100644
index 0000000..a4cc405
--- /dev/null
+++ b/tests/test.integration.ui/src/main/resources/org/apache/directory/studio/test/integration/ui/rfc5280_crl.crl
Binary files differ
diff --git a/tools/colorscheme.ods b/tools/colorscheme.ods
new file mode 100644
index 0000000..bcd83f0
--- /dev/null
+++ b/tools/colorscheme.ods
Binary files differ
diff --git a/tools/testlab/README.md b/tools/testlab/README.md
new file mode 100644
index 0000000..b3980d8
--- /dev/null
+++ b/tools/testlab/README.md
@@ -0,0 +1,77 @@
+# Test Lab
+
+## Host preparation
+
+To be able to access the services with their FQDN add aliases to the `/etc/hosts`. 
+Note that this is a hack rather than a proper solution.
+
+```
+/etc/hosts:
+127.0.0.100     kerby.example.com
+127.0.0.101     openldap.example.com
+127.0.0.102     fedora389ds.example.com
+```
+
+## Apache Kerby as Kerberos KDC
+
+Uses Docker image `coheigea/kerby`, source at https://github.com/coheigea/testcases/tree/master/apache/docker/kerby.
+
+Start the Kerby server
+
+```
+docker run -it --rm --name kerby -h kerby.example.com -u $(id -u):$(id -g) -p 60088:60088/tcp -p 60088:60088/udp -v $(pwd)/tools/testlab/kerby-data:/kerby-data coheigea/kerby
+```
+
+Initial creation of service accounts and keytabs:
+
+```
+docker exec -it kerby bash
+stty rows 24 columns 80
+sh bin/kadmin.sh /kerby-data/conf/ -k /kerby-data/keytabs/admin.keytab
+
+addprinc -pw secret hnelson@EXAMPLE.COM
+
+addprinc -pw randall ldap/openldap.example.com@EXAMPLE.COM
+ktadd -k /kerby-data/keytabs/ldap.keytab ldap/openldap.example.com@EXAMPLE.COM
+addprinc -pw randall ldap/fedora389ds.example.com@EXAMPLE.COM
+ktadd -k /kerby-data/keytabs/ldap.keytab ldap/fedora389ds.example.com@EXAMPLE.COM
+```
+
+## OpenLDAP
+
+```
+docker run -it --rm --name openldap -h openldap.example.com -p 20389:389 -p 20636:636 -e LDAP_TLS_VERIFY_CLIENT=never -v $(pwd)/tools/testlab/ldap.keytab:/etc/krb5.keytab -v $(pwd)/tools/testlab/krb5.conf:/etc/krb5.conf osixia/openldap:1.5.0
+```
+
+## Fedora 389ds
+
+```
+docker run -it --rm --name fedora389ds -h fedora389ds.example.com -p 21389:3389 -p 21636:3636 -e DS_DM_PASSWORD=admin -v $(pwd)/tools/testlab/ldap.keytab:/etc/krb5.keytab -v $(pwd)/tools/testlab/krb5.conf:/etc/krb5.conf 389ds/dirsrv bash -c "zypper install -y cyrus-sasl-crammd5 cyrus-sasl-digestmd5 cyrus-sasl-gssapi; set -m; /usr/lib/dirsrv/dscontainer -r & while ! /usr/lib/dirsrv/dscontainer -H; do sleep 5; done; sleep 5; /usr/sbin/dsconf localhost backend create --suffix dc=example,dc=org --be-name example; fg"
+```
+
+## Usage
+
+### GSSAPI authentication
+
+```
+export KRB5_CONFIG=$(pwd)/tools/testlab/krb5.conf
+echo "secret" | kinit hnelson
+ldapwhoami -H ldap://openldap.example.com:20389 -Y GSSAPI -N
+ldapwhoami -H ldap://fedora389ds.example.com:21389 -Y GSSAPI -N
+```
+
+### UI integration tests
+
+```
+docker run -it --rm \
+    -u $(id -u):$(id -g) \
+    -v ~/.m2:/home/hnelson/.m2 \
+    -v $(pwd):/home/hnelson/project \
+    -v $(pwd)/tools/testlab/krb5.conf:/etc/krb5.conf \
+    --link=kerby:kerby.example.com \
+    --link=openldap:openldap.example.com -e OPENLDAP_HOST=openldap.example.com -e OPENLDAP_PORT=389 -e OPENLDAP_PORT_SSL=636 \
+    --link=fedora389ds:fedora389ds.example.com -e FEDORA_389DS_HOST=fedora389ds.example.com -e FEDORA_389DS_PORT=3389 -e FEDORA_389DS_PORT_SSL=3636 \
+    apachedirectory/maven-build:jdk-11 bash -c "mvn -V -f pom-first.xml clean install && mvn -V clean install -Denable-ui-tests"
+
+```
+
diff --git a/tools/testlab/kerby-data/backend/json-backend.json b/tools/testlab/kerby-data/backend/json-backend.json
new file mode 100644
index 0000000..0d47acd
--- /dev/null
+++ b/tools/testlab/kerby-data/backend/json-backend.json
@@ -0,0 +1,116 @@
+{
+  "adminprotocol/localhost@EXAMPLE.COM": {
+    "principal": "adminprotocol/localhost@EXAMPLE.COM",
+    "keyVersion": 1,
+    "kdcFlags": 0,
+    "disabled": false,
+    "locked": false,
+    "expireTime": "253402300799900",
+    "createdTime": "1528713224740",
+    "keys": {
+      "AES128_CTS_HMAC_SHA1_96": {
+        "kvno": 1,
+        "key": "3019A003020111A112041091CDC8A37ADE5268236C840523F87038"
+      },
+      "DES3_CBC_SHA1": {
+        "kvno": 1,
+        "key": "3021A003020110A11A0418F7AE8A9B6D7AF2E59D49DF193476CE511FFE1091C464A823"
+      }
+    }
+  },
+  "ldap/fedora389ds.example.com@EXAMPLE.COM": {
+    "principal": "ldap/fedora389ds.example.com@EXAMPLE.COM",
+    "keyVersion": 1,
+    "kdcFlags": 0,
+    "disabled": false,
+    "locked": false,
+    "expireTime": "253402300799900",
+    "createdTime": "1623646752731",
+    "keys": {
+      "DES3_CBC_SHA1": {
+        "kvno": 1,
+        "key": "3021A003020110A11A04182A1FF2DFC47AB0B0E068EA3D3476AE19511ACDE6970D5467"
+      },
+      "AES128_CTS_HMAC_SHA1_96": {
+        "kvno": 1,
+        "key": "3019A003020111A1120410B13B78BDE0374D463D877871A3C8B88F"
+      }
+    }
+  },
+  "krbtgt/EXAMPLE.COM@EXAMPLE.COM": {
+    "principal": "krbtgt/EXAMPLE.COM@EXAMPLE.COM",
+    "keyVersion": 1,
+    "kdcFlags": 0,
+    "disabled": false,
+    "locked": false,
+    "expireTime": "253402300799900",
+    "createdTime": "1528713224693",
+    "keys": {
+      "AES128_CTS_HMAC_SHA1_96": {
+        "kvno": 1,
+        "key": "3019A003020111A1120410BF87D478614F7A6D76C0462F2AD180AE"
+      },
+      "DES3_CBC_SHA1": {
+        "kvno": 1,
+        "key": "3021A003020110A11A0418627F34BF7F261964F1E55B5849B3D583BCD0795E34FB317A"
+      }
+    }
+  },
+  "ldap/openldap.example.com@EXAMPLE.COM": {
+    "principal": "ldap/openldap.example.com@EXAMPLE.COM",
+    "keyVersion": 1,
+    "kdcFlags": 0,
+    "disabled": false,
+    "locked": false,
+    "expireTime": "253402300799900",
+    "createdTime": "1623646740945",
+    "keys": {
+      "DES3_CBC_SHA1": {
+        "kvno": 1,
+        "key": "3021A003020110A11A0418DA0458C110D9435776F4BC32BFAE1C94624A7A402979D6F8"
+      },
+      "AES128_CTS_HMAC_SHA1_96": {
+        "kvno": 1,
+        "key": "3019A003020111A11204106A8382B60767C62E8766B741F92406A4"
+      }
+    }
+  },
+  "hnelson@EXAMPLE.COM": {
+    "principal": "hnelson@EXAMPLE.COM",
+    "keyVersion": 1,
+    "kdcFlags": 0,
+    "disabled": false,
+    "locked": false,
+    "expireTime": "253402300799900",
+    "createdTime": "1623569412700",
+    "keys": {
+      "DES3_CBC_SHA1": {
+        "kvno": 1,
+        "key": "3021A003020110A11A04185707CE2952922C1C8CBF43C23D8F8C5E9E8CF75D3E4A5E25"
+      },
+      "AES128_CTS_HMAC_SHA1_96": {
+        "kvno": 1,
+        "key": "3019A003020111A1120410AD214B38B69DFCCAACF15F346D417B90"
+      }
+    }
+  },
+  "kadmin/EXAMPLE.COM@EXAMPLE.COM": {
+    "principal": "kadmin/EXAMPLE.COM@EXAMPLE.COM",
+    "keyVersion": 1,
+    "kdcFlags": 0,
+    "disabled": false,
+    "locked": false,
+    "expireTime": "253402300799900",
+    "createdTime": "1528713224726",
+    "keys": {
+      "AES128_CTS_HMAC_SHA1_96": {
+        "kvno": 1,
+        "key": "3019A003020111A112041064F2D24DE79182AD88AC9A60ED6F9983"
+      },
+      "DES3_CBC_SHA1": {
+        "kvno": 1,
+        "key": "3021A003020110A11A04189BCBA454B3FB4A540746ECC1D3A283BCFBD307A15BE5EA1C"
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/tools/testlab/kerby-data/conf/adminClient.conf b/tools/testlab/kerby-data/conf/adminClient.conf
new file mode 100644
index 0000000..7c6909b
--- /dev/null
+++ b/tools/testlab/kerby-data/conf/adminClient.conf
@@ -0,0 +1,23 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+[libdefaults]
+default_realm = EXAMPLE.COM
+admin_port = 65417
+keytab_file = admin.keytab
+protocol = adminprotocol
+server_name = localhost
diff --git a/tools/testlab/kerby-data/conf/adminServer.conf b/tools/testlab/kerby-data/conf/adminServer.conf
new file mode 100644
index 0000000..08af51c
--- /dev/null
+++ b/tools/testlab/kerby-data/conf/adminServer.conf
@@ -0,0 +1,24 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+[libdefaults]
+default_realm = EXAMPLE.COM
+admin_realm = EXAMPLE.COM
+admin_port = 65417
+keytab_file = protocol.keytab
+protocol = adminprotocol
+server_name = localhost
diff --git a/tools/testlab/kerby-data/conf/backend.conf b/tools/testlab/kerby-data/conf/backend.conf
new file mode 100644
index 0000000..3bbe481
--- /dev/null
+++ b/tools/testlab/kerby-data/conf/backend.conf
@@ -0,0 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+
+kdc_identity_backend = org.apache.kerby.kerberos.kdc.identitybackend.JsonIdentityBackend
+backend.json.dir = /kerby-data/backend
diff --git a/tools/testlab/kerby-data/conf/kdc.conf b/tools/testlab/kerby-data/conf/kdc.conf
new file mode 100644
index 0000000..34f2973
--- /dev/null
+++ b/tools/testlab/kerby-data/conf/kdc.conf
@@ -0,0 +1,23 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+
+[kdcdefaults]
+  kdc_host = kerby.example.com
+  kdc_udp_port = 60088
+  kdc_tcp_port = 60088
+  kdc_realm = EXAMPLE.COM
diff --git a/tools/testlab/kerby-data/conf/krb5.conf b/tools/testlab/kerby-data/conf/krb5.conf
new file mode 100644
index 0000000..6692859
--- /dev/null
+++ b/tools/testlab/kerby-data/conf/krb5.conf
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+
+[libdefaults]
+    kdc_realm = EXAMPLE.COM
+    default_realm = EXAMPLE.COM
+    udp_preference_limit = 4096
+    kdc_tcp_port = 60088
+    kdc_udp_port = 60088
+
+[realms]
+    EXAMPLE.COM = {
+        kdc = localhost:60088
+    }
\ No newline at end of file
diff --git a/tools/testlab/kerby-data/keytabs/admin.keytab b/tools/testlab/kerby-data/keytabs/admin.keytab
new file mode 100644
index 0000000..55e1add
--- /dev/null
+++ b/tools/testlab/kerby-data/keytabs/admin.keytab
Binary files differ
diff --git a/tools/testlab/krb5.conf b/tools/testlab/krb5.conf
new file mode 100644
index 0000000..b6f9369
--- /dev/null
+++ b/tools/testlab/krb5.conf
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+
+[libdefaults]
+    kdc_realm = EXAMPLE.COM
+    default_realm = EXAMPLE.COM
+    udp_preference_limit = 1
+    kdc_tcp_port = 60088
+    kdc_udp_port = 60088
+
+[realms]
+    EXAMPLE.COM = {
+        kdc = kerby.example.com:60088
+    }
diff --git a/tools/testlab/ldap.keytab b/tools/testlab/ldap.keytab
new file mode 100644
index 0000000..11e2700
--- /dev/null
+++ b/tools/testlab/ldap.keytab
Binary files differ