Add Spring LDAP Samples

This commit is contained in:
Josh Cummings
2024-10-02 11:43:16 -06:00
commit a9b676a925
164 changed files with 17068 additions and 0 deletions

213
.gitignore vendored Normal file
View File

@@ -0,0 +1,213 @@
# Created by https://www.toptal.com/developers/gitignore/api/gradle,java,intellij,eclipse
# Edit at https://www.toptal.com/developers/gitignore?templates=gradle,java,intellij,eclipse
### Eclipse ###
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
.recommenders
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# PyDev specific (Python IDE for Eclipse)
*.pydevproject
# CDT-specific (C/C++ Development Tooling)
.cproject
# CDT- autotools
.autotools
# Java annotation processor (APT)
.factorypath
# PDT-specific (PHP Development Tools)
.buildpath
# sbteclipse plugin
.target
# Tern plugin
.tern-project
# TeXlipse plugin
.texlipse
# STS (Spring Tool Suite)
.springBeans
# Code Recommenders
.recommenders/
# Annotation Processing
.apt_generated/
.apt_generated_test/
# Scala IDE specific (Scala & Java development for Eclipse)
.cache-main
.scala_dependencies
.worksheet
# Uncomment this line if you wish to ignore the project description file.
# Typically, this file would be tracked if it contains build/dependency configurations:
#.project
### Eclipse Patch ###
# Spring Boot Tooling
.sts4-cache/
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/libraries-with-intellij-classes.xml
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
.idea/artifacts
.idea/compiler.xml
.idea/jarRepositories.xml
.idea/modules.xml
.idea/*.iml
.idea/modules
*.iml
*.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### Intellij Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
# .idea/misc.xml
# *.ipr
# Sonarlint plugin
.idea/**/sonarlint/
# SonarQube Plugin
.idea/**/sonarIssues.xml
# Markdown Navigator plugin
.idea/**/markdown-navigator.xml
.idea/**/markdown-navigator-enh.xml
.idea/**/markdown-navigator/
# Cache file creation bug
# See https://youtrack.jetbrains.com/issue/JBR-2257
.idea/$CACHE_FILE$
### Java ###
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### Gradle ###
.gradle
build/
# Ignore Gradle GUI config
gradle-app.setting
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar
# Cache of project
.gradletasknamecache
# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
# gradle/wrapper/gradle-wrapper.properties
### Gradle Patch ###
**/build/
# End of https://www.toptal.com/developers/gitignore/api/gradle,java,intellij,eclipse

15
.idea/checkstyle-idea.xml generated Normal file
View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CheckStyle-IDEA" serialisationVersion="2">
<checkstyleVersion>10.18.1</checkstyleVersion>
<scanScope>JavaOnly</scanScope>
<option name="thirdPartyClasspath" />
<option name="activeLocationIds" />
<option name="locations">
<list>
<ConfigurationLocation id="bundled-sun-checks" type="BUNDLED" scope="All" description="Sun Checks">(bundled)</ConfigurationLocation>
<ConfigurationLocation id="bundled-google-checks" type="BUNDLED" scope="All" description="Google Checks">(bundled)</ConfigurationLocation>
</list>
</option>
</component>
</project>

8
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK" />
</project>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

12
README.adoc Normal file
View File

@@ -0,0 +1,12 @@
image::https://github.com/spring-projects/spring-ldap-samples/workflows/CI/badge.svg[link=https://github.com/spring-projects/spring-ldap-samples/actions?query=workflow%3ACI]
image::https://img.shields.io/badge/Revved%20up%20by-Develocity-06A0CE?logo=Gradle&labelColor=02303A["Revved up by Develocity", link="https://ge.spring.io/scans?search.rootProjectNames=spring-ldap-samples"]
== Samples catalog
Refer to these sample projects for some examples on using Spring LDAP:
* boot - https://github.com/spring-projects/spring-ldap-samples/tree/main/servlet/spring-boot/java/boot[demonstrates basic Spring Boot usage]
* plain - https://github.com/spring-projects/spring-ldap-samples/tree/main/servlet/xml/java/plain[demonstrates 'plain' usage of Spring LDAP]
* odm - https://github.com/spring-projects/spring-ldap-samples/tree/main/servlet/xml/java/odm[demonstrates the Object-Directory mapping functionality]
* user-admin - https://github.com/spring-projects/spring-ldap-samples/tree/main/servlet/xml/java/user-admin[a fully functional user admin application implemented using Spring LDAP]

75
build.gradle Normal file
View File

@@ -0,0 +1,75 @@
plugins {
id "checkstyle"
id "io.spring.javaformat" version "0.0.42"
id 'io.spring.nohttp' version '0.0.11'
}
allprojects {
apply plugin: 'checkstyle'
apply plugin: 'io.spring.javaformat'
dependencies {
checkstyle "io.spring.javaformat:spring-javaformat-checkstyle:0.0.42"
}
// Ensure every test task has at least a single test
tasks.withType(Test).configureEach {
afterSuite { desc, result ->
if (result.testCount == 0) {
throw new IllegalStateException("No tests were found. Ensure that useJUnitPlatform was used.")
}
}
}
// Spring Framework 6.1 requires -parameters to be able to introspect method parameter names
tasks.withType(JavaCompile) {
options.compilerArgs.add("-parameters")
}
tasks.matching { it.name == 'formatAot' }.all { task ->
task.enabled = false
}
tasks.matching { it.name == 'formatAotTest' }.all { task ->
task.enabled = false
}
tasks.matching { it.name == 'checkFormatAot' }.all { task ->
task.enabled = false
}
tasks.matching { it.name == 'checkFormatAotTest' }.all { task ->
task.enabled = false
}
tasks.matching { it.name == "checkstyleAot" }.all { task ->
task.enabled = false
}
tasks.matching { it.name == "checkstyleAotTest" }.all { task ->
task.enabled = false
}
}
if (hasProperty('buildScan')) {
develocity {
buildScan {
termsOfUseUrl = 'https://gradle.com/terms-of-service'
termsOfUseAgree = 'yes'
}
}
}
repositories {
mavenCentral()
}
tasks.register('runAllTests') {
var allTasks = rootProject.getAllTasks(true)
var allTestsTasks = allTasks.values().collect { t ->
t.findAll { it.name == 'test' || it.name == 'integrationTest' }
}.flatten()
it.dependsOn {
allTestsTasks
}
}

View File

@@ -0,0 +1,17 @@
^\Q/*\E$
^\Q * Copyright \E2012-20\d\d\Q the original author or authors.\E$
^\Q *\E$
^\Q * Licensed under the Apache License, Version 2.0 (the "License");\E$
^\Q * you may not use this file except in compliance with the License.\E$
^\Q * You may obtain a copy of the License at\E$
^\Q *\E$
^\Q * https://www.apache.org/licenses/LICENSE-2.0\E$
^\Q *\E$
^\Q * Unless required by applicable law or agreed to in writing, software\E$
^\Q * distributed under the License is distributed on an "AS IS" BASIS,\E$
^\Q * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\E$
^\Q * See the License for the specific language governing permissions and\E$
^\Q * limitations under the License.\E$
^\Q */\E$
^$
^.*$

View File

@@ -0,0 +1,50 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="com.puppycrawl.tools.checkstyle.Checker">
<module name="SuppressionFilter">
<property name="file" value="${config_loc}/suppressions.xml"/>
</module>
<module name="io.spring.javaformat.checkstyle.SpringChecks">
<property name="avoidStaticImportExcludes" value="org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.*,
org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction.*,
org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction.*,
org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.*" />
<property name="excludes" value="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck" />
<property name="excludes" value="com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocPackageCheck" />
</module>
<module name="com.puppycrawl.tools.checkstyle.TreeWalker">
<module name="io.spring.javaformat.checkstyle.check.SpringJUnit5Check" />
<module
name="com.puppycrawl.tools.checkstyle.checks.imports.IllegalImportCheck">
<property name="regexp" value="true" />
<property name="illegalPkgs"
value="^sun.*, ^org\.apache\.commons\.(?!compress|dbcp2|lang|lang3|logging|pool2).*, ^com\.datastax\.oss\.driver\.shaded.*, ^com\.google\.common.*, ^io\.micrometer\.shaded.*, ^org\.flywaydb\.core\.internal.*, ^org\.testcontainers\.shaded.*" />
<property name="illegalClasses"
value="^com\.hazelcast\.util\.Base64, ^org\.junit\.rules\.ExpectedException, ^org\.mockito\.InjectMocks, ^org\.slf4j\.LoggerFactory, ^org.springframework.context.annotation.ScannedGenericBeanDefinition, ^reactor\.core\.support\.Assert" />
</module>
<module name="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck">
<property name="format" value="^\t* +\t*\S" />
<property name="message"
value="Line has leading space characters; indentation should be performed with tabs only." />
<property name="ignoreComments" value="true" />
</module>
<module name="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck">
<property name="maximum" value="0"/>
<property name="format" value="org\.junit\.(Assert|jupiter\.api\.Assertions)\.assert" />
<property name="message"
value="Please use AssertJ imports." />
<property name="ignoreComments" value="true" />
</module>
<module name="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpCheck">
<property name="format" value="[ \t]+$" />
<property name="illegalPattern" value="true" />
<property name="message" value="Trailing whitespace" />
</module>
<module name="io.spring.javaformat.checkstyle.check.SpringJavadocCheck">
<property name="publicOnlySinceTags" value="true" />
<property name="requireSinceTag" value="false" />
</module>
</module>
</module>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0"?>
<!DOCTYPE suppressions PUBLIC "-//Puppy Crawl//DTD Suppressions 1.1//EN"
"https://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
<suppressions>
<!-- OpenSamlActionTestingSupport is copied from Open SAML source -->
<suppress files="servlet/spring-boot/java/saml2-login/src/integTest/java/example/OpenSamlActionTestingSupport.java" checks=".*"/>
<!-- Saml2Utils is copied from Open SAML source -->
<suppress files="servlet/spring-boot/java/saml2-login/src/integTest/java/example/Saml2Utils.java" checks=".*"/>
</suppressions>

View File

@@ -0,0 +1,25 @@
version: '3.8'
networks:
samples:
driver: bridge
services:
cas:
image: apereo/cas:6.6.6
container_name: cas
restart: always
ports:
- "8090:8080"
command: >
--cas.standalone.configuration-directory=/etc/cas/config
--server.ssl.enabled=false
--server.port=8080
--cas.service-registry.core.init-from-json=true
--cas.service-registry.json.location=file:/etc/cas/services
--cas.tgc.secure=false
--cas.tgc.sameSitePolicy=Lax
volumes:
- ./services/http-1.json:/etc/cas/services/http-1.json
networks:
- samples

View File

@@ -0,0 +1,8 @@
{
"@class": "org.apereo.cas.services.CasRegisteredService",
"serviceId": "^(https?)://.*",
"name": "HTTP/HTTPS",
"id": 1,
"description": "This service definition authorizes all application urls that support HTTP and HTTPS protocols.",
"evaluationOrder": 10000
}

20
find-latest-minor-version.sh Executable file
View File

@@ -0,0 +1,20 @@
#!/bin/bash
increment_version() {
local version="$1"
local last_digit=$(echo "$version" | rev | cut -d '.' -f 1 | rev)
local incremented_digit=$((last_digit + 1))
echo "${version%.*}.$incremented_digit"
}
find_next_minor_version() {
local current_version=$1
local maven_url=$2
local next_version=$(increment_version "$current_version")
local url="$maven_url/$next_version/"
local response=$(curl --write-out "%{http_code}\n" --silent --output /dev/null "$url")
if [ "$response" -eq 200 ]; then
echo "$next_version"
fi
}

4
gradle.properties Normal file
View File

@@ -0,0 +1,4 @@
version=3.3.0
spring-ldap.version=3.3.0-SNAPSHOT
org.gradle.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError
org.gradle.caching=true

12
gradle/libs.versions.toml Normal file
View File

@@ -0,0 +1,12 @@
[versions]
org-springframework-boot = "3.4.0-SNAPSHOT"
[libraries]
org-springframework-spring-framework-bom = "org.springframework:spring-framework-bom:6.2.0-M6"
org-springframework-data-spring-data-bom = "org.springframework.data:spring-data-bom:2024.0.2"
org-springframework-ldap-spring-ldap-core = "org.springframework.ldap:spring-ldap-core:3.3.0-SNAPSHOT"
org-springframework-ldap-spring-ldap-test = "org.springframework.ldap:spring-ldap-test:3.3.0-SNAPSHOT"
[plugins]
io-spring-dependency-management = { id = "io.spring.dependency-management", version = "1.1.6" }
org-springframework-boot = { id = "org.springframework.boot", version.ref = "org-springframework-boot" }

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

244
gradlew vendored Executable file
View File

@@ -0,0 +1,244 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://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.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

92
gradlew.bat vendored Normal file
View File

@@ -0,0 +1,92 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

3
includes.sh Executable file
View File

@@ -0,0 +1,3 @@
#!/usr/bin/env bash
find -name "build.gradle*" | sed -E 's#\.?/#:#g' | sed 's#:build.gradle.*$##' | xargs -I{} echo "include \"{}\"" | sort

View File

@@ -0,0 +1,35 @@
A Hello World Spring LDAP application using Spring Boot
The application is protected by Spring Security and uses an embedded UnboundID container for its LDAP server.
You can authenticate with HTTP basic using `bob`/`bobspassword`:
[source,bash]
----
curl --user bob:bobspassword localhost:8080
----
And you should see the response:
[source,bash]
----
Hello, bob
----
Also, you can hit the `cn` endpoint which uses `LdapTemplate` to query the datastore for the user's `cn` attribute value, like so:
[source,bash]
----
curl --user bob:bobspassword localhost:8080/cn
----
This should result in:
[source,bash]
----
[
"Bob Hamilton"
]
----
To run the example, do `./gradlew :bootRun`.

View File

@@ -0,0 +1,25 @@
plugins {
alias(libs.plugins.org.springframework.boot)
alias(libs.plugins.io.spring.dependency.management)
id 'java-library'
}
repositories {
mavenCentral()
maven { url "https://repo.spring.io/milestone" }
maven { url "https://repo.spring.io/snapshot" }
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-ldap'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.security:spring-security-ldap'
implementation 'com.unboundid:unboundid-ldapsdk'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
}
tasks.named('test') {
useJUnitPlatform()
}

View File

@@ -0,0 +1,4 @@
version=3.3.0
spring-ldap.version=3.3.0-SNAPSHOT
org.gradle.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError
org.gradle.caching=true

View File

@@ -0,0 +1,12 @@
[versions]
org-springframework-boot = "3.4.0-SNAPSHOT"
[libraries]
org-springframework-spring-framework-bom = "org.springframework:spring-framework-bom:6.2.0-M6"
org-springframework-data-spring-data-bom = "org.springframework.data:spring-data-bom:2024.0.2"
org-springframework-ldap-spring-ldap-core = "org.springframework.ldap:spring-ldap-core:3.3.0-SNAPSHOT"
org-springframework-ldap-spring-ldap-test = "org.springframework.ldap:spring-ldap-test:3.3.0-SNAPSHOT"
[plugins]
io-spring-dependency-management = { id = "io.spring.dependency-management", version = "1.1.6" }
org-springframework-boot = { id = "org.springframework.boot", version.ref = "org-springframework-boot" }

Binary file not shown.

View File

@@ -0,0 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

244
servlet/spring-boot/java/boot/gradlew vendored Executable file
View File

@@ -0,0 +1,244 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://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.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

View File

@@ -0,0 +1,92 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -0,0 +1,8 @@
pluginManagement {
repositories {
mavenCentral()
gradlePluginPortal()
maven { url 'https://repo.spring.io/milestone' }
maven { url "https://repo.spring.io/snapshot" }
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2005-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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 sample;
import java.util.List;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
private final LdapTemplate ldap;
public HelloController(LdapTemplate ldap) {
this.ldap = ldap;
}
@GetMapping
public String hello(Authentication authentication) {
return "Hello, " + authentication.getName();
}
@GetMapping("/cn")
public List<String> cn(Authentication authentication) {
AttributesMapper<String> mapper = (attrs) -> attrs.get("cn").get().toString();
return this.ldap.search("ou=people", "uid=" + authentication.getName(), mapper);
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2005-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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 sample;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.core.support.BaseLdapPathContextSource;
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
import org.springframework.security.ldap.authentication.BindAuthenticator;
import org.springframework.security.ldap.authentication.LdapAuthenticationProvider;
import org.springframework.security.ldap.authentication.LdapAuthenticator;
import org.springframework.security.ldap.server.UnboundIdContainer;
import org.springframework.security.ldap.userdetails.PersonContextMapper;
@Configuration
public class SecurityConfig {
@Bean
UnboundIdContainer ldapContainer() {
UnboundIdContainer container = new UnboundIdContainer("dc=springframework,dc=org", "classpath:users.ldif");
container.setPort(0);
return container;
}
@Bean
ContextSource contextSource(UnboundIdContainer container) {
int port = container.getPort();
return new DefaultSpringSecurityContextSource("ldap://localhost:" + port + "/dc=springframework,dc=org");
}
@Bean
BindAuthenticator authenticator(BaseLdapPathContextSource contextSource) {
BindAuthenticator authenticator = new BindAuthenticator(contextSource);
authenticator.setUserDnPatterns(new String[] { "uid={0},ou=people" });
return authenticator;
}
@Bean
LdapAuthenticationProvider authenticationProvider(LdapAuthenticator authenticator) {
LdapAuthenticationProvider provider = new LdapAuthenticationProvider(authenticator);
provider.setUserDetailsContextMapper(new PersonContextMapper());
return provider;
}
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2005-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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 sample;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringLdapSimpleSampleApplication {
public static void main(String[] args) {
SpringApplication.run(SpringLdapSimpleSampleApplication.class, args);
}
}

View File

@@ -0,0 +1,124 @@
dn: ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: groups
dn: ou=subgroups,ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: subgroups
dn: ou=people,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: people
dn: ou=space cadets,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: space cadets
dn: ou=\"quoted people\",dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: "quoted people"
dn: ou=otherpeople,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: otherpeople
dn: uid=ben,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Ben Alex
sn: Alex
uid: ben
userPassword: $2a$10$c6bSeWPhg06xB1lvmaWNNe4NROmZiSpYhlocU/98HNr2MhIOiSt36
dn: uid=bob,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Bob Hamilton
sn: Hamilton
uid: bob
userPassword: bobspassword
dn: uid=joe,ou=otherpeople,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Joe Smeth
sn: Smeth
uid: joe
userPassword: joespassword
dn: cn=mouse\, jerry,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Mouse, Jerry
sn: Mouse
uid: jerry
userPassword: jerryspassword
dn: cn=slash/guy,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: slash/guy
sn: Slash
uid: slashguy
userPassword: slashguyspassword
dn: cn=quote\"guy,ou=\"quoted people\",dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: quote\"guy
sn: Quote
uid: quoteguy
userPassword: quoteguyspassword
dn: uid=space cadet,ou=space cadets,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Space Cadet
sn: Cadet
uid: space cadet
userPassword: spacecadetspassword
dn: cn=developers,ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: groupOfUniqueNames
cn: developers
ou: developer
uniqueMember: uid=ben,ou=people,dc=springframework,dc=org
uniqueMember: uid=bob,ou=people,dc=springframework,dc=org
dn: cn=managers,ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: groupOfUniqueNames
cn: managers
ou: manager
uniqueMember: uid=ben,ou=people,dc=springframework,dc=org
uniqueMember: cn=mouse\, jerry,ou=people,dc=springframework,dc=org
dn: cn=submanagers,ou=subgroups,ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: groupOfUniqueNames
cn: submanagers
ou: submanager
uniqueMember: uid=ben,ou=people,dc=springframework,dc=org

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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 sample;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpHeaders;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
@AutoConfigureMockMvc
class SpringLdapSimpleSampleApplicationTests {
@Autowired
MockMvc mvc;
@Test
void indexWhenCorrectUsernameAndPasswordThenAuthenticates() throws Exception {
HttpHeaders http = new HttpHeaders();
http.setBasicAuth("bob", "bobspassword");
this.mvc.perform(get("/").headers(http)).andExpect(status().isOk()).andExpect(content().string("Hello, bob"));
}
@Test
void cnWhenCorrectUsernameAndPasswordThenShowsCommonName() throws Exception {
HttpHeaders http = new HttpHeaders();
http.setBasicAuth("bob", "bobspassword");
this.mvc.perform(get("/cn").headers(http))
.andExpect(status().isOk())
.andExpect(jsonPath("$.[0]").value("Bob Hamilton"));
}
}

View File

@@ -0,0 +1,25 @@
plugins {
alias(libs.plugins.org.springframework.boot)
alias(libs.plugins.io.spring.dependency.management)
id "nebula.integtest" version "8.2.0"
id 'java'
}
repositories {
mavenCentral()
maven { url "https://repo.spring.io/milestone" }
maven { url "https://repo.spring.io/snapshot" }
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.withType(Test).configureEach {
useJUnitPlatform()
}

View File

@@ -0,0 +1,4 @@
version=6.1.1
spring-ldap.version=6.4.0-SNAPSHOT
org.gradle.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError
org.gradle.caching=true

View File

@@ -0,0 +1 @@
../../../../../gradle/libs.versions.toml

Binary file not shown.

View File

@@ -0,0 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

244
servlet/spring-boot/java/hello/gradlew vendored Executable file
View File

@@ -0,0 +1,244 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://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.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

View File

@@ -0,0 +1,92 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -0,0 +1,8 @@
pluginManagement {
repositories {
mavenCentral()
gradlePluginPortal()
maven { url 'https://repo.spring.io/milestone' }
maven { url "https://repo.spring.io/snapshot" }
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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 example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Hello application.
*
* @author Joe Grandja
*/
@SpringBootApplication
public class HelloApplication {
public static void main(String[] args) {
SpringApplication.run(HelloApplication.class, args);
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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 example;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
/**
* Controller for "/".
*
* @author Joe Grandja
*/
@Controller
public class IndexController {
@GetMapping("/")
public String index() {
return "index";
}
}

View File

@@ -0,0 +1,9 @@
<html xmlns:th="https://www.thymeleaf.org">
<head>
<title>Hello Security!</title>
</head>
<body>
<h1>Hello Security</h1>
<a th:href="@{/logout}">Log Out</a>
</body>
</html>

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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 example;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* @author Rob Winch
*/
@SpringBootTest
@AutoConfigureMockMvc
public class HelloApplicationTests {
@Autowired
private MockMvc mockMvc;
@Test
void indexThenOk() throws Exception {
// @formatter:off
this.mockMvc.perform(get("/"))
.andExpect(status().isOk());
// @formatter:on
}
}

View File

@@ -0,0 +1,9 @@
Sample application demonstrating how to do the most basic stuff in Spring LDAP using the Object-Directory Mapping facilities.
A very simple dao implementation is provided in `org.springframework.ldap.samples.plain.dao.OdmPersonDaoImpl`
It demonstrates some basic operations using Spring LDAP Object-Directory Mapping.
The core Spring application context of the sample is defined in `resources/applicationContext.xml`.
This ApplicationContext will start an in-process Apache Directory Server instance, automatically populated
with some test data. The data will be reset every time the application is restarted.
To run the example, do `gradle jettyRun`, and then navigate to `http://localhost:8080/odm`

View File

@@ -0,0 +1,41 @@
plugins {
id 'java-library'
id "org.gretty" version "4.0.3"
id "war"
}
repositories {
mavenCentral()
maven { url "https://repo.spring.io/snapshot" }
maven { url "https://repo.spring.io/milestone" }
}
dependencies {
implementation platform(libs.org.springframework.spring.framework.bom)
implementation platform(libs.org.springframework.data.spring.data.bom)
implementation "org.springframework.data:spring-data-ldap"
implementation libs.org.springframework.ldap.spring.ldap.core
implementation libs.org.springframework.ldap.spring.ldap.test
implementation "org.springframework:spring-context"
implementation "org.springframework:spring-webmvc"
implementation "commons-lang:commons-lang:2.6"
implementation 'com.unboundid:unboundid-ldapsdk:7.0.1'
implementation 'org.glassfish.web:jakarta.servlet.jsp.jstl:3.0.1'
implementation 'jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api:3.0.1'
implementation 'jakarta.servlet.jsp:jakarta.servlet.jsp-api:4.0.0'
compileOnly 'jakarta.servlet:jakarta.servlet-api:6.1.0'
runtimeOnly 'ch.qos.logback:logback-classic:1.5.6'
testImplementation platform('org.junit:junit-bom:5.10.3')
testImplementation "org.springframework:spring-test"
testImplementation 'com.unboundid:unboundid-ldapsdk:7.0.1'
testImplementation "org.assertj:assertj-core:3.26.3"
testImplementation "org.junit.jupiter:junit-jupiter-api"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine"
}
tasks.named('test') {
useJUnitPlatform()
}

View File

@@ -0,0 +1,4 @@
version=6.1.1
spring-ldap.version=3.3.0-SNAPSHOT
org.gradle.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError
org.gradle.caching=true

View File

@@ -0,0 +1,12 @@
[versions]
org-springframework-boot = "3.4.0-SNAPSHOT"
[libraries]
org-springframework-spring-framework-bom = "org.springframework:spring-framework-bom:6.2.0-M6"
org-springframework-data-spring-data-bom = "org.springframework.data:spring-data-bom:2024.0.2"
org-springframework-ldap-spring-ldap-core = "org.springframework.ldap:spring-ldap-core:3.3.0-SNAPSHOT"
org-springframework-ldap-spring-ldap-test = "org.springframework.ldap:spring-ldap-test:3.3.0-SNAPSHOT"
[plugins]
io-spring-dependency-management = { id = "io.spring.dependency-management", version = "1.1.6" }
org-springframework-boot = { id = "org.springframework.boot", version.ref = "org-springframework-boot" }

Binary file not shown.

View File

@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

240
servlet/xml/java/odm/gradlew vendored Executable file
View File

@@ -0,0 +1,240 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://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.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

91
servlet/xml/java/odm/gradlew.bat vendored Executable file
View File

@@ -0,0 +1,91 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -0,0 +1,8 @@
pluginManagement {
repositories {
mavenCentral()
gradlePluginPortal()
maven { url 'https://repo.spring.io/milestone' }
maven { url "https://repo.spring.io/snapshot" }
}
}

View File

@@ -0,0 +1,142 @@
/*
* Copyright 2005-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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.springframework.ldap.samples.odm.domain;
import javax.naming.Name;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.springframework.ldap.odm.annotations.Attribute;
import org.springframework.ldap.odm.annotations.DnAttribute;
import org.springframework.ldap.odm.annotations.Entry;
import org.springframework.ldap.odm.annotations.Id;
import org.springframework.ldap.odm.annotations.Transient;
/**
* Simple class representing a single person.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
@Entry(objectClasses = { "inetOrgPerson", "organizationalPerson", "person", "top" })
public class Person {
@Id
private Name dn;
@Attribute(name = "cn")
@DnAttribute(value = "cn", index = 2)
private String fullName;
@Attribute(name = "sn")
private String lastName;
private String description;
@Transient
@DnAttribute(value = "c", index = 0)
private String country;
@Transient
@DnAttribute(value = "ou", index = 1)
private String company;
@Attribute(name = "telephoneNumber")
private String phone;
public Person() {
}
public Person(String country, String company, String fullname) {
this.country = country;
this.company = company;
this.fullName = fullname;
}
public Name getDn() {
return this.dn;
}
public void setDn(Name dn) {
this.dn = dn;
}
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public String getFullName() {
return this.fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getLastName() {
return this.lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getCompany() {
return this.company;
}
public void setCompany(String company) {
this.company = company;
}
public String getCountry() {
return this.country;
}
public void setCountry(String country) {
this.country = country;
}
public String getPhone() {
return this.phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this, obj);
}
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2005-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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.springframework.ldap.samples.odm.repository;
import java.util.List;
import org.springframework.data.ldap.repository.LdapRepository;
import org.springframework.ldap.samples.odm.domain.Person;
/**
* Data Access Object interface for the Person entity.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public interface PersonRepository extends LdapRepository<Person>, PersonRepositoryExtension {
default List<String> getAllPersonNames() {
return findAll().stream().map(Person::getFullName).toList();
}
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2005-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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.springframework.ldap.samples.odm.repository;
import org.springframework.ldap.samples.odm.domain.Person;
/**
* An extension to {@link PersonRepository}, adding the ability to find a person by their
* DN attributes.
*
* @author Josh Cummings
*/
public interface PersonRepositoryExtension {
Person findByPrimaryKey(String country, String company, String fullname);
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2005-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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.springframework.ldap.samples.odm.repository;
import org.springframework.LdapDataEntry;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.LdapClient;
import org.springframework.ldap.odm.core.ObjectDirectoryMapper;
import org.springframework.ldap.samples.odm.domain.Person;
/**
* An implementation of {@link PersonRepositoryExtension}.
*
* This extension uses ODM to calculate the DN so that it can be looked up.
*
* @author Josh Cummings
*/
public class PersonRepositoryExtensionImpl implements PersonRepositoryExtension {
private final LdapClient ldap;
private final ObjectDirectoryMapper odm;
public PersonRepositoryExtensionImpl(LdapClient ldap, ObjectDirectoryMapper odm) {
this.ldap = ldap;
this.odm = odm;
}
@Override
public Person findByPrimaryKey(String country, String company, String fullname) {
Person person = new Person(country, company, fullname);
return this.ldap.search().name(this.odm.getCalculatedId(person)).toObject((ContextMapper<Person>) (ctx) -> {
LdapDataEntry entry = (LdapDataEntry) ctx;
return this.odm.mapFromLdapDataEntry(entry, Person.class);
});
}
}

View File

@@ -0,0 +1,146 @@
/*
* Copyright 2005-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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.springframework.ldap.samples.odm.web;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import javax.naming.Name;
import org.apache.commons.lang.StringUtils;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.samples.odm.domain.Person;
import org.springframework.ldap.samples.odm.repository.PersonRepository;
import org.springframework.ldap.samples.utils.HtmlRowLdapTreeVisitor;
import org.springframework.ldap.samples.utils.LdapTree;
import org.springframework.ldap.samples.utils.LdapTreeBuilder;
import org.springframework.ldap.support.LdapUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
/**
* Default controller.
*
* @author Mattias Hellborg Arthursson
*/
@Controller
public class DefaultController {
private final LdapTreeBuilder ldapTreeBuilder;
private final PersonRepository persons;
public DefaultController(LdapTreeBuilder ldapTreeBuilder, PersonRepository persons) {
this.ldapTreeBuilder = ldapTreeBuilder;
this.persons = persons;
}
@RequestMapping("/welcome.do")
public void welcomeHandler() {
}
@RequestMapping("/showTree.do")
public ModelAndView showTree() {
LdapTree ldapTree = this.ldapTreeBuilder.getLdapTree(LdapUtils.emptyLdapName());
HtmlRowLdapTreeVisitor visitor = new PersonLinkHtmlRowLdapTreeVisitor();
ldapTree.traverse(visitor);
return new ModelAndView("showTree", "rows", visitor.getRows());
}
@RequestMapping("/addPerson.do")
public String addPerson() {
Person person = getPerson();
this.persons.save(person);
return "redirect:/showTree.do";
}
@RequestMapping("/updatePhoneNumber.do")
public String updatePhoneNumber() {
Person person = this.persons.findByPrimaryKey("Sweden", "company1", "John Doe");
person.setPhone(StringUtils.join(new String[] { person.getPhone(), "0" }));
this.persons.save(person);
return "redirect:/showTree.do";
}
@RequestMapping("/removePerson.do")
public String removePerson() {
Person person = getPerson();
this.persons.delete(person);
return "redirect:/showTree.do";
}
@RequestMapping("/showPerson.do")
public ModelMap showPerson(String country, String company, String fullName) {
Person person = this.persons.findByPrimaryKey(country, company, fullName);
return new ModelMap("person", person);
}
private Person getPerson() {
Person person = new Person();
person.setFullName("John Doe");
person.setLastName("Doe");
person.setCompany("company1");
person.setCountry("Sweden");
person.setDescription("Test user");
return person;
}
/**
* Generates appropriate links for person leaves in the tree.
*
* @author Mattias Hellborg Arthursson
*/
private static final class PersonLinkHtmlRowLdapTreeVisitor extends HtmlRowLdapTreeVisitor {
@Override
protected String getLinkForNode(DirContextOperations node) {
String[] objectClassValues = node.getStringAttributes("objectClass");
if (containsValue(objectClassValues, "person")) {
Name dn = node.getDn();
String country = encodeValue(LdapUtils.getStringValue(dn, "c"));
String company = encodeValue(LdapUtils.getStringValue(dn, "ou"));
String fullName = encodeValue(LdapUtils.getStringValue(dn, "cn"));
return "showPerson.do?country=" + country + "&company=" + company + "&fullName=" + fullName;
}
else {
return super.getLinkForNode(node);
}
}
private String encodeValue(String value) {
return URLEncoder.encode(value, StandardCharsets.UTF_8);
}
private boolean containsValue(String[] values, String value) {
for (String oneValue : values) {
if (StringUtils.equals(oneValue, value)) {
return true;
}
}
return false;
}
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2005-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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.springframework.ldap.samples.utils;
import java.util.LinkedList;
import java.util.List;
import org.springframework.ldap.core.DirContextOperations;
public class HtmlRowLdapTreeVisitor implements LdapTreeVisitor {
private final List<String> rows = new LinkedList<>();
public void visit(DirContextOperations node, int currentDepth) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < currentDepth; i++) {
sb.append("&nbsp;&nbsp;&nbsp;&nbsp;");
}
sb.append("<a href='")
.append(getLinkForNode(node))
.append("'>")
.append(node.getDn())
.append("</a>")
.append("<br>\n");
this.rows.add(sb.toString());
}
protected String getLinkForNode(DirContextOperations node) {
return "#";
}
public List<String> getRows() {
return this.rows;
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright 2005-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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.springframework.ldap.samples.utils;
import java.util.LinkedList;
import java.util.List;
import org.springframework.ldap.core.DirContextOperations;
public class LdapTree {
private final DirContextOperations node;
private List<LdapTree> subContexts = new LinkedList<>();
public LdapTree(DirContextOperations node) {
this.node = node;
}
public DirContextOperations getNode() {
return this.node;
}
public List<LdapTree> getSubContexts() {
return this.subContexts;
}
public void setSubContexts(List<LdapTree> subContexts) {
this.subContexts = subContexts;
}
public void addSubTree(LdapTree ldapTree) {
this.subContexts.add(ldapTree);
}
public void traverse(LdapTreeVisitor visitor) {
traverse(visitor, 0);
}
private void traverse(LdapTreeVisitor visitor, int currentDepth) {
visitor.visit(this.node, currentDepth);
for (LdapTree subContext : this.subContexts) {
subContext.traverse(visitor, currentDepth + 1);
}
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2005-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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.springframework.ldap.samples.utils;
import javax.naming.Name;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.LdapClient;
import org.springframework.ldap.support.LdapUtils;
public class LdapTreeBuilder {
private final LdapClient ldap;
public LdapTreeBuilder(LdapClient ldap) {
this.ldap = ldap;
}
public LdapTree getLdapTree(Name root) {
DirContextOperations context = this.ldap.search().name(root).toEntry();
return getLdapTree(context);
}
private LdapTree getLdapTree(DirContextOperations rootContext) {
LdapTree ldapTree = new LdapTree(rootContext);
this.ldap.listBindings(rootContext.getDn()).toList((ContextMapper<Object>) (ctx) -> {
Name dn = ((DirContextOperations) ctx).getDn();
dn = LdapUtils.prepend(dn, rootContext.getDn());
ldapTree.addSubTree(getLdapTree(dn));
return null;
});
return ldapTree;
}
}

View File

@@ -0,0 +1,25 @@
/*
* Copyright 2005-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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.springframework.ldap.samples.utils;
import org.springframework.ldap.core.DirContextOperations;
public interface LdapTreeVisitor {
void visit(DirContextOperations node, int currentDepth);
}

View File

@@ -0,0 +1,3 @@
<body>
Plain example of Spring LDAP usage.
</body>

View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:ldap="http://www.springframework.org/schema/ldap"
xmlns:data-ldap="http://www.springframework.org/schema/data/ldap"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/ldap https://www.springframework.org/schema/ldap/spring-ldap.xsd
http://www.springframework.org/schema/data/ldap https://www.springframework.org/schema/data/ldap/spring-ldap.xsd">
<context:property-placeholder location="classpath:/ldap.properties" />
<ldap:context-source id="contextSource"
password="${sample.ldap.password}"
url="${sample.ldap.url}"
username="${sample.ldap.userDn}"
base="${sample.ldap.base}" />
<ldap:ldap-template id="ldapTemplate" context-source-ref="contextSource"/>
<bean id="ldap" class="org.springframework.ldap.core.LdapClient" factory-method="create">
<constructor-arg ref="contextSource"/>
</bean>
<bean id="odm" class="org.springframework.ldap.odm.core.impl.DefaultObjectDirectoryMapper"/>
<bean id="ldapTreeBuilder" class="org.springframework.ldap.samples.utils.LdapTreeBuilder">
<constructor-arg ref="ldap" />
</bean>
<data-ldap:repositories base-package="org.springframework.ldap.samples.odm.repository" />
<beans profile="default">
<!-- Populates the LDAP server with initial data -->
<bean class="org.springframework.ldap.test.unboundid.LdifPopulator" depends-on="embeddedLdapServer">
<property name="contextSource" ref="contextSource" />
<property name="resource" value="classpath:/setup_data.ldif" />
<property name="base" value="${sample.ldap.base}" />
<property name="clean" value="${sample.ldap.clean}" />
<property name="defaultBase" value="dc=jayway,dc=se" />
</bean>
<!--
This is for test and demo purposes only - EmbeddedLdapServerFactoryBean launches an in-process
LDAP server.
-->
<bean id="embeddedLdapServer" class="org.springframework.ldap.test.unboundid.EmbeddedLdapServerFactoryBean">
<property name="partitionName" value="jayway"/>
<property name="partitionSuffix" value="${sample.ldap.base}" />
<property name="port" value="18880" />
</bean>
</beans>
</beans>

View File

@@ -0,0 +1,5 @@
sample.ldap.url=ldap://127.0.0.1:18880
sample.ldap.userDn=uid=admin,ou=system
sample.ldap.password=secret
sample.ldap.base=dc=jayway,dc=se
sample.ldap.clean=true

View File

@@ -0,0 +1,14 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@@ -0,0 +1,35 @@
dn: c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: country
c: Sweden
description: The country of Sweden
dn: ou=company1,c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: organizationalUnit
ou: company1
description: First company in Sweden
dn: cn=Some Person,ou=company1,c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
uid: some.person
userPassword: password
cn: Some Person
sn: Person
description: Sweden, Company1, Some Person
telephoneNumber: +46 555-123456
dn: cn=Some Person2,ou=company1,c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
uid: some.person2
userPassword: password
cn: Some Person2
sn: Person2
description: Sweden, Company1, Some Person2
telephoneNumber: +46 555-654321

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan
base-package="org.springframework.ldap.samples.odm.web" />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>

View File

@@ -0,0 +1,20 @@
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<body>
<a href="showTree.do">Back</a>
<p>
Full name: ${person.fullName}
<br>
LastName: ${person.lastName}
<br>
Description: ${person.description}
<br>
Country: ${person.country}
<br>
Company: ${person.company}
<br>
Phone: ${person.phone}
<br>
</p>
</html>

View File

@@ -0,0 +1,17 @@
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<body>
<h2>Operations</h2>
<h3>Clicking a link below performs the described operation which will be reflected in the LDAP tree below</h3>
<a href="addPerson.do">Add new test person 'John Doe'</a> (only works once)<br>
<a href="updatePhoneNumber.do">Add a '0' to the phone number of test person</a> (only works if the person has been created)<br>
<a href="removePerson.do">Remove test person</a><br>
<p>
<h2>Tree contents</h2>
<h3>Click a person row to see the attribute values (country and company rows do not have additional info)</h3>
<c:forEach var="row" items="${rows}">
${row}
</c:forEach>
</p>
</body>
</html>

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="Tiink-preview" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee https://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<display-name>Spring LDAP Basic Example</display-name>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/applicationContext.xml</param-value>
</context-param>
<servlet>
<servlet-name>basic</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/basic-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>basic</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.htm</welcome-file>
</welcome-file-list>
</web-app>

View File

@@ -0,0 +1,5 @@
<html>
<head>
<meta HTTP-EQUIV="REFRESH" content="0; url=showTree.do">
</head>
</html>

View File

@@ -0,0 +1,112 @@
/*
* Copyright 2005-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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.springframework.ldap.samples.odm.repository;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ldap.NameNotFoundException;
import org.springframework.ldap.samples.odm.domain.Person;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/**
* Abstract base class for PersonDao integration tests.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
@ExtendWith(SpringExtension.class)
@ContextConfiguration("/applicationContext.xml")
public class PersonRepositorySampleIntegrationTests {
protected Person person;
@Autowired
private PersonRepository personRepository;
@BeforeEach
void preparePerson() {
this.person = new Person();
this.person.setCountry("Sweden");
this.person.setCompany("company1");
this.person.setFullName("Some Person");
this.person.setLastName("Person");
this.person.setDescription("Sweden, Company1, Some Person");
this.person.setPhone("+46 555-123456");
}
/**
* Having a single test method test create, update and delete is not exactly the ideal
* way of testing, since they depend on each other. A better way would be to separate
* the tests and load a test fixture before each operation, in order to guarantee the
* expected state every time. See the ldaptemplate-person sample for the correct way
* to do this.
*/
@Test
void testCreateUpdateDelete() {
this.person.setFullName("Another Person");
this.personRepository.save(this.person);
Person person = this.personRepository.findByPrimaryKey("Sweden", "company1", "Another Person");
assertThat(person).isEqualTo(this.person);
this.person.setDescription("Another description");
this.personRepository.save(this.person);
person = this.personRepository.findByPrimaryKey("Sweden", "company1", "Another Person");
assertThat(person.getDescription()).isEqualTo("Another description");
this.personRepository.delete(this.person);
assertThatExceptionOfType(NameNotFoundException.class)
.isThrownBy(() -> this.personRepository.findByPrimaryKey("Sweden", "company1", "Another Person"));
}
@Test
void testGetAllPersonNames() {
List<String> result = this.personRepository.getAllPersonNames();
assertThat(result).hasSize(2);
String first = result.get(0);
assertThat(first).isEqualTo("Some Person");
}
@Test
void testFindAll() {
List<Person> result = this.personRepository.findAll();
assertThat(result).hasSize(2);
Person first = result.get(0);
assertThat(first.getFullName()).isEqualTo("Some Person");
}
@Test
void testFindByPrimaryKey() {
Person result = this.personRepository.findByPrimaryKey("Sweden", "company1", "Some Person");
assertThat(result.getCountry()).isEqualTo("Sweden");
assertThat(result.getCompany()).isEqualTo("company1");
assertThat(result.getDescription()).isEqualTo("Sweden, Company1, Some Person");
assertThat(result.getPhone()).isEqualTo("+46 555-123456");
assertThat(result.getFullName()).isEqualTo("Some Person");
assertThat(result.getLastName()).isEqualTo("Person");
}
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright 2005-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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.springframework.ldap.samples.utils;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.naming.ldap.LdapName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.support.LdapUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.assertj.core.api.Assertions.assertThat;
@ExtendWith(SpringExtension.class)
@ContextConfiguration("/applicationContext.xml")
public class LdapTreeBuilderIntegrationTests {
@Autowired
private LdapTreeBuilder tested;
@Test
void testGetLdapTree() {
LdapTree ldapTree = this.tested.getLdapTree(LdapUtils.newLdapName("c=Sweden"));
ldapTree.traverse(new TestVisitor());
}
private static final class TestVisitor implements LdapTreeVisitor {
private static final LdapName DN_1 = LdapUtils.newLdapName("c=Sweden");
private static final LdapName DN_2 = LdapUtils.newLdapName("ou=company1,c=Sweden");
private static final LdapName DN_3 = LdapUtils.newLdapName("cn=Some Person,ou=company1,c=Sweden");
private static final LdapName DN_4 = LdapUtils.newLdapName("cn=Some Person2,ou=company1,c=Sweden");
private final Map<LdapName, Integer> names = new LinkedHashMap<>();
private final Iterator<LdapName> keyIterator;
private TestVisitor() {
this.names.put(DN_1, 0);
this.names.put(DN_2, 1);
this.names.put(DN_3, 2);
this.names.put(DN_4, 2);
this.keyIterator = this.names.keySet().iterator();
}
@Override
public void visit(DirContextOperations node, int currentDepth) {
LdapName next = this.keyIterator.next();
assertThat(node.getDn()).isEqualTo(next);
assertThat(currentDepth).isEqualTo(this.names.get(next).intValue());
}
}
}

View File

@@ -0,0 +1,9 @@
Sample application demonstrating how to do the most basic stuff in Spring LDAP.
A very simple dao implementation is provided in `org.springframework.ldap.samples.plain.dao.PersonRepositoryImpl`
It demonstrates some basic operations using Spring LDAP.
The core Spring application context of the sample is defined in `resources/applicationContext.xml`.
This application context will start an in-process Apache Directory Server instance, automatically populated
with some test data. The data will be reset every time the application is restarted.
To run the example, do `gradle jettyRun`, and then navigate to `http://localhost:8080/plain`

View File

@@ -0,0 +1,42 @@
plugins {
id 'java-library'
id "org.gretty" version "4.0.3"
id "war"
alias(libs.plugins.io.spring.dependency.management)
}
repositories {
mavenCentral()
maven { url "https://repo.spring.io/snapshot" }
maven { url "https://repo.spring.io/milestone" }
}
dependencies {
implementation platform(libs.org.springframework.spring.framework.bom)
implementation platform(libs.org.springframework.data.spring.data.bom)
implementation "org.springframework.data:spring-data-ldap"
implementation libs.org.springframework.ldap.spring.ldap.core
implementation libs.org.springframework.ldap.spring.ldap.test
implementation "org.springframework:spring-context"
implementation "org.springframework:spring-webmvc"
implementation "commons-lang:commons-lang:2.6"
implementation 'com.unboundid:unboundid-ldapsdk:7.0.1'
implementation 'org.glassfish.web:jakarta.servlet.jsp.jstl:3.0.1'
implementation 'jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api:3.0.1'
implementation 'jakarta.servlet.jsp:jakarta.servlet.jsp-api:4.0.0'
compileOnly 'jakarta.servlet:jakarta.servlet-api:6.1.0'
runtimeOnly 'ch.qos.logback:logback-classic:1.5.6'
testImplementation platform('org.junit:junit-bom:5.10.3')
testImplementation "org.springframework:spring-test"
testImplementation "org.assertj:assertj-core:3.26.3"
testImplementation "org.junit.jupiter:junit-jupiter-api"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine"
}
tasks.named('test') {
useJUnitPlatform()
}

View File

@@ -0,0 +1,4 @@
version=3.3.0
spring-ldap.version=3.3.0-SNAPSHOT
org.gradle.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError
org.gradle.caching=true

View File

@@ -0,0 +1,12 @@
[versions]
org-springframework-boot = "3.4.0-SNAPSHOT"
[libraries]
org-springframework-spring-framework-bom = "org.springframework:spring-framework-bom:6.2.0-M6"
org-springframework-data-spring-data-bom = "org.springframework.data:spring-data-bom:2024.0.2"
org-springframework-ldap-spring-ldap-core = "org.springframework.ldap:spring-ldap-core:3.3.0-SNAPSHOT"
org-springframework-ldap-spring-ldap-test = "org.springframework.ldap:spring-ldap-test:3.3.0-SNAPSHOT"
[plugins]
io-spring-dependency-management = { id = "io.spring.dependency-management", version = "1.1.6" }
org-springframework-boot = { id = "org.springframework.boot", version.ref = "org-springframework-boot" }

Binary file not shown.

View File

@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

240
servlet/xml/java/plain/gradlew vendored Executable file
View File

@@ -0,0 +1,240 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://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.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

91
servlet/xml/java/plain/gradlew.bat vendored Executable file
View File

@@ -0,0 +1,91 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -0,0 +1,8 @@
pluginManagement {
repositories {
mavenCentral()
gradlePluginPortal()
maven { url 'https://repo.spring.io/milestone' }
maven { url "https://repo.spring.io/snapshot" }
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright 2005-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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.springframework.ldap.samples.plain.domain;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
/**
* Simple class representing a single person.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public class Person {
private String fullName;
private String lastName;
private String description;
private String country;
private String company;
private String phone;
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public String getFullName() {
return this.fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getLastName() {
return this.lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getCompany() {
return this.company;
}
public void setCompany(String company) {
this.company = company;
}
public String getCountry() {
return this.country;
}
public void setCountry(String country) {
this.country = country;
}
public String getPhone() {
return this.phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this, obj);
}
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2005-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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.springframework.ldap.samples.plain.repository;
import java.util.List;
import org.springframework.ldap.samples.plain.domain.Person;
/**
* Data Access Object interface for the Person entity.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public interface PersonRepository {
void create(Person person);
void update(Person person);
void delete(Person person);
List<String> getAllPersonNames();
List<Person> findAll();
Person findByPrimaryKey(String country, String company, String fullname);
}

View File

@@ -0,0 +1,140 @@
/*
* Copyright 2005-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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.springframework.ldap.samples.plain.repository;
import java.util.List;
import javax.naming.Name;
import javax.naming.ldap.LdapName;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.LdapClient;
import org.springframework.ldap.core.support.AbstractContextMapper;
import org.springframework.ldap.query.LdapQuery;
import org.springframework.ldap.query.LdapQueryBuilder;
import org.springframework.ldap.samples.plain.domain.Person;
import org.springframework.ldap.support.LdapNameBuilder;
import org.springframework.ldap.support.LdapUtils;
/**
* Default implementation of PersonDao. This implementation uses DirContextAdapter for
* managing attribute values. We use a ContextMapper to map from the found contexts to our
* domain objects. This is especially useful since we in this case have properties in our
* domain objects that depend on parts of the DN.
*
* We could have worked with Attributes and an AttributesMapper implementation instead,
* but working with Attributes is a bore and also, working with AttributesMapper objects
* (or, indeed Attributes) does not give us access to the distinguished name. However, we
* do use it in one method that only needs a single attribute:
* {@link #getAllPersonNames()}.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public class PersonRepositoryImpl implements PersonRepository {
private final LdapClient ldap;
public PersonRepositoryImpl(LdapClient ldap) {
this.ldap = ldap;
}
@Override
public void create(Person person) {
Name dn = buildDn(person);
DirContextOperations context = new DirContextAdapter(dn);
mapToContext(person, context);
this.ldap.bind(dn).object(context).execute();
}
@Override
public void update(Person person) {
Name dn = buildDn(person);
DirContextAdapter context = this.ldap.search().name(dn).toEntry();
mapToContext(person, context);
this.ldap.modify(dn).attributes(context.getModificationItems()).execute();
}
@Override
public void delete(Person person) {
this.ldap.unbind(buildDn(person)).execute();
}
@Override
public List<String> getAllPersonNames() {
LdapQuery query = LdapQueryBuilder.query().attributes("cn").where("objectclass").is("person");
return this.ldap.search()
.query(query)
.toList((AttributesMapper<String>) (attributes) -> attributes.get("cn").get().toString());
}
@Override
public List<Person> findAll() {
return this.ldap.search()
.query(LdapQueryBuilder.query().where("objectclass").is("person"))
.toList(PERSON_CONTEXT_MAPPER);
}
@Override
public Person findByPrimaryKey(String country, String company, String fullname) {
LdapName dn = buildDn(country, company, fullname);
return this.ldap.search().name(dn).toObject(PERSON_CONTEXT_MAPPER);
}
private LdapName buildDn(Person person) {
return buildDn(person.getCountry(), person.getCompany(), person.getFullName());
}
private LdapName buildDn(String country, String company, String fullname) {
return LdapNameBuilder.newInstance().add("c", country).add("ou", company).add("cn", fullname).build();
}
private void mapToContext(Person person, DirContextOperations context) {
context.setAttributeValues("objectclass", new String[] { "top", "person" });
context.setAttributeValue("cn", person.getFullName());
context.setAttributeValue("sn", person.getLastName());
context.setAttributeValue("description", person.getDescription());
context.setAttributeValue("telephoneNumber", person.getPhone());
}
/**
* Maps from DirContextAdapter to Person objects. A DN for a person will be of the
* form <code>cn=[fullname],ou=[company],c=[country]</code>, so the values of these
* attributes must be extracted from the DN. For this, we use the LdapName along with
* utility methods in LdapUtils.
*/
private static final ContextMapper<Person> PERSON_CONTEXT_MAPPER = new AbstractContextMapper<>() {
@Override
public Person doMapFromContext(DirContextOperations context) {
Person person = new Person();
LdapName dn = LdapUtils.newLdapName(context.getDn());
person.setCountry(LdapUtils.getStringValue(dn, 0));
person.setCompany(LdapUtils.getStringValue(dn, 1));
person.setFullName(context.getStringAttribute("cn"));
person.setLastName(context.getStringAttribute("sn"));
person.setDescription(context.getStringAttribute("description"));
person.setPhone(context.getStringAttribute("telephoneNumber"));
return person;
}
};
}

View File

@@ -0,0 +1,146 @@
/*
* Copyright 2005-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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.springframework.ldap.samples.plain.web;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import javax.naming.Name;
import org.apache.commons.lang.StringUtils;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.samples.plain.domain.Person;
import org.springframework.ldap.samples.plain.repository.PersonRepository;
import org.springframework.ldap.samples.utils.HtmlRowLdapTreeVisitor;
import org.springframework.ldap.samples.utils.LdapTree;
import org.springframework.ldap.samples.utils.LdapTreeBuilder;
import org.springframework.ldap.support.LdapUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
/**
* Default controller.
*
* @author Mattias Hellborg Arthursson
*/
@Controller
public class DefaultController {
private final LdapTreeBuilder ldapTreeBuilder;
private final PersonRepository persons;
public DefaultController(LdapTreeBuilder ldapTreeBuilder, PersonRepository persons) {
this.ldapTreeBuilder = ldapTreeBuilder;
this.persons = persons;
}
@RequestMapping("/welcome.do")
public void welcomeHandler() {
}
@RequestMapping("/showTree.do")
public ModelAndView showTree() {
LdapTree ldapTree = this.ldapTreeBuilder.getLdapTree(LdapUtils.emptyLdapName());
HtmlRowLdapTreeVisitor visitor = new PersonLinkHtmlRowLdapTreeVisitor();
ldapTree.traverse(visitor);
return new ModelAndView("showTree", "rows", visitor.getRows());
}
@RequestMapping("/addPerson.do")
public String addPerson() {
Person person = getPerson();
this.persons.create(person);
return "redirect:/showTree.do";
}
@RequestMapping("/updatePhoneNumber.do")
public String updatePhoneNumber() {
Person person = this.persons.findByPrimaryKey("Sweden", "company1", "John Doe");
person.setPhone(StringUtils.join(new String[] { person.getPhone(), "0" }));
this.persons.update(person);
return "redirect:/showTree.do";
}
@RequestMapping("/removePerson.do")
public String removePerson() {
Person person = getPerson();
this.persons.delete(person);
return "redirect:/showTree.do";
}
@RequestMapping("/showPerson.do")
public ModelMap showPerson(String country, String company, String fullName) {
Person person = this.persons.findByPrimaryKey(country, company, fullName);
return new ModelMap("person", person);
}
private Person getPerson() {
Person person = new Person();
person.setFullName("John Doe");
person.setLastName("Doe");
person.setCompany("company1");
person.setCountry("Sweden");
person.setDescription("Test user");
return person;
}
/**
* Generates appropriate links for person leaves in the tree.
*
* @author Mattias Hellborg Arthursson
*/
private static final class PersonLinkHtmlRowLdapTreeVisitor extends HtmlRowLdapTreeVisitor {
@Override
protected String getLinkForNode(DirContextOperations node) {
String[] objectClassValues = node.getStringAttributes("objectClass");
if (containsValue(objectClassValues, "person")) {
Name dn = node.getDn();
String country = encodeValue(LdapUtils.getStringValue(dn, "c"));
String company = encodeValue(LdapUtils.getStringValue(dn, "ou"));
String fullName = encodeValue(LdapUtils.getStringValue(dn, "cn"));
return "showPerson.do?country=" + country + "&company=" + company + "&fullName=" + fullName;
}
else {
return super.getLinkForNode(node);
}
}
private String encodeValue(String value) {
return URLEncoder.encode(value, StandardCharsets.UTF_8);
}
private boolean containsValue(String[] values, String value) {
for (String oneValue : values) {
if (StringUtils.equals(oneValue, value)) {
return true;
}
}
return false;
}
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2005-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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.springframework.ldap.samples.utils;
import java.util.LinkedList;
import java.util.List;
import org.springframework.ldap.core.DirContextOperations;
public class HtmlRowLdapTreeVisitor implements LdapTreeVisitor {
private final List<String> rows = new LinkedList<>();
public void visit(DirContextOperations node, int currentDepth) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < currentDepth; i++) {
sb.append("&nbsp;&nbsp;&nbsp;&nbsp;");
}
sb.append("<a href='")
.append(getLinkForNode(node))
.append("'>")
.append(node.getDn())
.append("</a>")
.append("<br>\n");
this.rows.add(sb.toString());
}
protected String getLinkForNode(DirContextOperations node) {
return "#";
}
public List<String> getRows() {
return this.rows;
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright 2005-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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.springframework.ldap.samples.utils;
import java.util.LinkedList;
import java.util.List;
import org.springframework.ldap.core.DirContextOperations;
public class LdapTree {
private final DirContextOperations node;
private List<LdapTree> subContexts = new LinkedList<>();
public LdapTree(DirContextOperations node) {
this.node = node;
}
public DirContextOperations getNode() {
return this.node;
}
public List<LdapTree> getSubContexts() {
return this.subContexts;
}
public void setSubContexts(List<LdapTree> subContexts) {
this.subContexts = subContexts;
}
public void addSubTree(LdapTree ldapTree) {
this.subContexts.add(ldapTree);
}
public void traverse(LdapTreeVisitor visitor) {
traverse(visitor, 0);
}
private void traverse(LdapTreeVisitor visitor, int currentDepth) {
visitor.visit(this.node, currentDepth);
for (LdapTree subContext : this.subContexts) {
subContext.traverse(visitor, currentDepth + 1);
}
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2005-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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.springframework.ldap.samples.utils;
import javax.naming.Name;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.LdapClient;
import org.springframework.ldap.support.LdapUtils;
public class LdapTreeBuilder {
private final LdapClient ldap;
public LdapTreeBuilder(LdapClient ldap) {
this.ldap = ldap;
}
public LdapTree getLdapTree(Name root) {
DirContextOperations context = this.ldap.search().name(root).toEntry();
return getLdapTree(context);
}
private LdapTree getLdapTree(final DirContextOperations rootContext) {
final LdapTree ldapTree = new LdapTree(rootContext);
this.ldap.listBindings(rootContext.getDn()).toList((ContextMapper<Object>) (ctx) -> {
Name dn = ((DirContextOperations) ctx).getDn();
dn = LdapUtils.prepend(dn, rootContext.getDn());
ldapTree.addSubTree(getLdapTree(dn));
return null;
});
return ldapTree;
}
}

View File

@@ -0,0 +1,25 @@
/*
* Copyright 2005-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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.springframework.ldap.samples.utils;
import org.springframework.ldap.core.DirContextOperations;
public interface LdapTreeVisitor {
void visit(DirContextOperations node, int currentDepth);
}

View File

@@ -0,0 +1,3 @@
<body>
Plain example of Spring LDAP usage.
</body>

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:ldap="http://www.springframework.org/schema/ldap"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/ldap https://www.springframework.org/schema/ldap/spring-ldap.xsd">
<context:property-placeholder location="classpath:/ldap.properties" />
<ldap:context-source id="contextSource"
password="${sample.ldap.password}"
url="${sample.ldap.url}"
username="${sample.ldap.userDn}"
base="${sample.ldap.base}" />
<bean id="ldap" class="org.springframework.ldap.core.LdapClient" factory-method="create">
<constructor-arg ref="contextSource"/>
</bean>
<!-- Populates the LDAP server with initial data -->
<bean id="ldifPopulator" class="org.springframework.ldap.test.LdifPopulator" depends-on="embeddedLdapServer">
<property name="contextSource" ref="contextSource" />
<property name="resource" value="classpath:/setup_data.ldif" />
<property name="base" value="${sample.ldap.base}" />
<property name="clean" value="${sample.ldap.clean}" />
<property name="defaultBase" value="dc=jayway,dc=se" />
</bean>
<!--
This is for test and demo purposes only - EmbeddedLdapServerFactoryBean launches an in-process
LDAP server.
-->
<bean id="embeddedLdapServer" class="org.springframework.ldap.test.unboundid.EmbeddedLdapServerFactoryBean">
<property name="partitionName" value="jayway"/>
<property name="partitionSuffix" value="${sample.ldap.base}" />
<property name="port" value="18880" />
</bean>
<bean id="persons"
class="org.springframework.ldap.samples.plain.repository.PersonRepositoryImpl">
<constructor-arg ref="ldap" />
</bean>
<bean id="ldapTreeBuilder"
class="org.springframework.ldap.samples.utils.LdapTreeBuilder">
<constructor-arg ref="ldap" />
</bean>
</beans>

View File

@@ -0,0 +1,5 @@
sample.ldap.url=ldap://127.0.0.1:18880
sample.ldap.userDn=uid=admin,ou=system
sample.ldap.password=secret
sample.ldap.base=dc=jayway,dc=se
sample.ldap.clean=true

View File

@@ -0,0 +1,7 @@
log4j.rootCategory=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
log4j.logger.org.apache.directory=ERROR

View File

@@ -0,0 +1,14 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@@ -0,0 +1,35 @@
dn: c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: country
c: Sweden
description: The country of Sweden
dn: ou=company1,c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: organizationalUnit
ou: company1
description: First company in Sweden
dn: cn=Some Person,ou=company1,c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
uid: some.person
userPassword: password
cn: Some Person
sn: Person
description: Sweden, Company1, Some Person
telephoneNumber: +46 555-123456
dn: cn=Some Person2,ou=company1,c=Sweden,dc=jayway,dc=se
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
uid: some.person2
userPassword: password
cn: Some Person2
sn: Person2
description: Sweden, Company1, Some Person2
telephoneNumber: +46 555-654321

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan
base-package="org.springframework.ldap.samples.plain.web" />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>

View File

@@ -0,0 +1,20 @@
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<body>
<a href="showTree.do">Back</a>
<p>
Full name: ${person.fullName}
<br>
LastName: ${person.lastName}
<br>
Description: ${person.description}
<br>
Country: ${person.country}
<br>
Company: ${person.company}
<br>
Phone: ${person.phone}
<br>
</p>
</html>

Some files were not shown because too many files have changed in this diff Show More