From b0d8851b93ac7eb639f66d4479b84727137b7fb0 Mon Sep 17 00:00:00 2001
From: Martin Goik <goik@hdm-stuttgart.de>
Date: Thu, 14 Apr 2016 12:02:47 +0200
Subject: [PATCH] SDI Java LDAP access example

---
 Doc/Sdi/ldap.xml                              | 96 ++++++++++++++++---
 P/Sdi/ReadMyData/.gitignore                   |  4 +
 P/Sdi/ReadMyData/pom.xml                      | 53 ++++++++++
 .../mi/sdai/readmydata/.gitignore             |  1 +
 .../mi/sdai/readmydata/Messages.java          | 22 +++++
 .../mi/sdai/readmydata/ReadMyLdap.java        | 56 +++++++++++
 .../readmydata/messages.properties.template   |  2 +
 .../ReadMyData/src/main/resources/log4j2.xml  | 21 ++++
 .../mi/sda2/ldaptivetest/AppTest.java         | 10 ++
 P/pom.xml                                     |  4 +
 10 files changed, 258 insertions(+), 11 deletions(-)
 create mode 100644 P/Sdi/ReadMyData/.gitignore
 create mode 100644 P/Sdi/ReadMyData/pom.xml
 create mode 100644 P/Sdi/ReadMyData/src/main/java/de/hdm_stuttgart/mi/sdai/readmydata/.gitignore
 create mode 100644 P/Sdi/ReadMyData/src/main/java/de/hdm_stuttgart/mi/sdai/readmydata/Messages.java
 create mode 100644 P/Sdi/ReadMyData/src/main/java/de/hdm_stuttgart/mi/sdai/readmydata/ReadMyLdap.java
 create mode 100644 P/Sdi/ReadMyData/src/main/java/de/hdm_stuttgart/mi/sdai/readmydata/messages.properties.template
 create mode 100644 P/Sdi/ReadMyData/src/main/resources/log4j2.xml
 create mode 100644 P/Sdi/ReadMyData/src/test/java/de/hdm_stuttgart/mi/sda2/ldaptivetest/AppTest.java

diff --git a/Doc/Sdi/ldap.xml b/Doc/Sdi/ldap.xml
index ca048b820..2b0d5ccd8 100644
--- a/Doc/Sdi/ldap.xml
+++ b/Doc/Sdi/ldap.xml
@@ -8,13 +8,6 @@
          xmlns:db="http://docbook.org/ns/docbook">
   <title><xref linkend="glo_LDAP"/></title>
 
-  <programlisting language="none">TODO:
-Grau:
-
-In Thunderbird: "@" benötigt.
-
-Ldapmodify erlaubt icht-objectclass konforme Daten</programlisting>
-
   <section xml:id="ldapPrepare">
     <title>Recommended Preparations</title>
 
@@ -72,9 +65,9 @@ Ldapmodify erlaubt icht-objectclass konforme Daten</programlisting>
       </listitem>
 
       <listitem>
-        <para>What is the role of <acronym>LDAP</acronym> objectclass
-        definitions? How do they relate to <acronym>LDAP</acronym> schema
-        definitions?</para>
+        <para>What is the role of <acronym>LDAP</acronym>
+        <property>objectclass</property> definitions? How do they relate to
+        <acronym>LDAP</acronym> schema definitions?</para>
       </listitem>
 
       <listitem>
@@ -661,7 +654,7 @@ modifying entry "olcDatabase={0}config,cn=config"</programlisting>
         </listitem>
 
         <listitem>
-          <para> Restore the exported data on your replica using <command
+          <para>Restore the exported data on your replica using <command
           xlink:href="http://linux.die.net/man/8/slapadd">slapadd</command>.</para>
         </listitem>
       </orderedlist>
@@ -709,5 +702,86 @@ modifying entry "olcDatabase={0}config,cn=config"</programlisting>
       however sufficient. Thus define a suitable replication user for this
       purpose being endowed with just sufficient privileges:</para>
     </section>
+
+    <section xml:id="sdiSectLdapByJava">
+      <title>Accessing <xref linkend="glo_LDAP"/> by a <xref
+      linkend="glo_Java"/> application.</title>
+
+      <para>Accessing <xref linkend="glo_LDAP"/> requires a suitable client
+      component. A standard <xref linkend="glo_JDK"/> or <xref
+      linkend="glo_JRE"/> ships with a <acronym
+      xlink:href="https://docs.oracle.com/javase/7/docs/technotes/guides/jndi/jndi-ldap.html">JNDI</acronym>
+      provider. The <xref linkend="glo_API"/> however requires a lot of
+      boilerplate code.</para>
+
+      <para><orgname xlink:href="http://www.ldaptive.org">Ldaptive</orgname>
+      offers a promising client provider <xref linkend="glo_API"/>. Start a
+      <xref linkend="glo_Maven"/> based <xref linkend="glo_Soft_Eclipse"/>
+      project which reads your own HdM <xref linkend="glo_LDAP"/> data being
+      provided by the MI replica server
+      <code>ldap1.mi.hdm-stuttgart.de</code>.</para>
+
+      <tip>
+        <itemizedlist>
+          <listitem>
+            <para>Read the <link
+            xlink:href="http://www.ldaptive.org/#quick-start-guide">quick
+            start guide</link> and consult the <link
+            xlink:href="http://www.ldaptive.org/javadocs">Ldaptive
+            API</link>.</para>
+          </listitem>
+
+          <listitem>
+            <para>Using <orgname
+            xlink:href="http://www.ldaptive.org">Ldaptive</orgname> may be
+            accomplished by adding the following <xref linkend="glo_Maven"/>
+            dependencies to your project's <filename>pom.xml</filename>
+            file:</para>
+
+            <programlisting language="xml">&lt;dependencies&gt;
+  &lt;dependency&gt;
+    &lt;groupId&gt;org.ldaptive&lt;/groupId&gt;
+    &lt;artifactId&gt;ldaptive&lt;/artifactId&gt;
+    &lt;version&gt;1.1.0&lt;/version&gt;
+  &lt;/dependency&gt;
+
+  &lt;dependency&gt;
+    &lt;groupId&gt;org.slf4j&lt;/groupId&gt;
+    &lt;artifactId&gt;slf4j-api&lt;/artifactId&gt;
+    &lt;version&gt;1.7.21&lt;/version&gt;
+  &lt;/dependency&gt;
+
+  &lt;dependency&gt;
+    &lt;groupId&gt;org.slf4j&lt;/groupId&gt;
+    &lt;artifactId&gt;slf4j-simple&lt;/artifactId&gt;
+    &lt;version&gt;1.7.21&lt;/version&gt;
+  &lt;/dependency&gt;
+&lt;/dependencies&gt;
+</programlisting>
+          </listitem>
+        </itemizedlist>
+      </tip>
+
+      <para>Solution available at:</para>
+
+      <annotation role="make">
+        <para role="eclipse">Sdi/ReadMyData</para>
+      </annotation>
+
+      <para>Notice: The above project will read the required password from a
+      <package>de.hdm_stuttgart.mi.sdai.readmydata.messages.properties</package>
+      file corresponding to
+      <filename>src/main/java/de/hdm_stuttgart/mi/sdai/readmydata/messages.properties</filename>.
+      Due to password protection this file has been excluded from versioning.
+      You will however find <filename>messages.properties.template</filename>
+      next to the intended location containing the appropriate property key
+      name. Using your own account data should enable you running the
+      application.</para>
+
+      <caution>
+        <para>Do not miss changing the value of
+        <code>ReadMyLdap.bindDn</code>!</para>
+      </caution>
+    </section>
   </section>
 </chapter>
diff --git a/P/Sdi/ReadMyData/.gitignore b/P/Sdi/ReadMyData/.gitignore
new file mode 100644
index 000000000..a1c3ab4d0
--- /dev/null
+++ b/P/Sdi/ReadMyData/.gitignore
@@ -0,0 +1,4 @@
+/target/
+/.settings/
+.classpath
+.project
diff --git a/P/Sdi/ReadMyData/pom.xml b/P/Sdi/ReadMyData/pom.xml
new file mode 100644
index 000000000..bed9fc4e4
--- /dev/null
+++ b/P/Sdi/ReadMyData/pom.xml
@@ -0,0 +1,53 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<groupId>de.hdm-stuttgart.mi.sdi</groupId>
+	<artifactId>readmydata</artifactId>
+	<version>0.9</version>
+	<packaging>jar</packaging>
+
+	<name>ReadMyData</name>
+
+	<url>http://www.mi.hdm-stuttgart.de/freedocs/topic/de.hdm_stuttgart.mi.lectures/sd1SectUsingMaven.html</url>
+
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+	</properties>
+
+	<dependencies>
+		<dependency>
+			<groupId>org.ldaptive</groupId>
+			<artifactId>ldaptive</artifactId>
+			<version>1.1.0</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.slf4j</groupId>
+			<artifactId>slf4j-api</artifactId>
+			<version>1.7.21</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.slf4j</groupId>
+			<artifactId>slf4j-simple</artifactId>
+			<version>1.7.21</version>
+		</dependency>
+	</dependencies>
+
+	<build>
+		<plugins>
+
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<version>3.3</version>
+				<configuration>
+					<source>1.8</source>
+					<target>1.8</target>
+				</configuration>
+			</plugin>
+
+		</plugins>
+	</build>
+</project>
diff --git a/P/Sdi/ReadMyData/src/main/java/de/hdm_stuttgart/mi/sdai/readmydata/.gitignore b/P/Sdi/ReadMyData/src/main/java/de/hdm_stuttgart/mi/sdai/readmydata/.gitignore
new file mode 100644
index 000000000..07fbaa318
--- /dev/null
+++ b/P/Sdi/ReadMyData/src/main/java/de/hdm_stuttgart/mi/sdai/readmydata/.gitignore
@@ -0,0 +1 @@
+/messages.properties
diff --git a/P/Sdi/ReadMyData/src/main/java/de/hdm_stuttgart/mi/sdai/readmydata/Messages.java b/P/Sdi/ReadMyData/src/main/java/de/hdm_stuttgart/mi/sdai/readmydata/Messages.java
new file mode 100644
index 000000000..0c122a983
--- /dev/null
+++ b/P/Sdi/ReadMyData/src/main/java/de/hdm_stuttgart/mi/sdai/readmydata/Messages.java
@@ -0,0 +1,22 @@
+package de.hdm_stuttgart.mi.sdai.readmydata;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+   private static final String BUNDLE_NAME = "de.hdm_stuttgart.mi.sdai.readmydata.messages";
+
+   private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+         .getBundle(BUNDLE_NAME);
+
+   private Messages() {
+   }
+
+   public static String getString(String key) {
+      try {
+         return RESOURCE_BUNDLE.getString(key);
+      } catch (MissingResourceException e) {
+         return '!' + key + '!';
+      }
+   }
+}
diff --git a/P/Sdi/ReadMyData/src/main/java/de/hdm_stuttgart/mi/sdai/readmydata/ReadMyLdap.java b/P/Sdi/ReadMyData/src/main/java/de/hdm_stuttgart/mi/sdai/readmydata/ReadMyLdap.java
new file mode 100644
index 000000000..3bf8c0614
--- /dev/null
+++ b/P/Sdi/ReadMyData/src/main/java/de/hdm_stuttgart/mi/sdai/readmydata/ReadMyLdap.java
@@ -0,0 +1,56 @@
+package de.hdm_stuttgart.mi.sdai.readmydata;
+
+import org.ldaptive.BindConnectionInitializer;
+import org.ldaptive.ConnectionConfig;
+import org.ldaptive.ConnectionFactory;
+import org.ldaptive.Credential;
+import org.ldaptive.DefaultConnectionFactory;
+import org.ldaptive.LdapAttribute;
+import org.ldaptive.LdapEntry;
+import org.ldaptive.LdapException;
+import org.ldaptive.SearchExecutor;
+import org.ldaptive.SearchResult;
+
+public class ReadMyLdap {
+
+   /**
+    * @param args Unused
+    * @throws LdapException
+    */
+   public static void main(String[] args) throws LdapException {
+      
+      final ConnectionConfig connConfig = new ConnectionConfig("ldap://ldap1.mi.hdm-stuttgart.de"); 
+      connConfig.setUseStartTLS(true);
+      connConfig.setConnectionInitializer(
+            new BindConnectionInitializer(
+                  Messages.getString("ReadMyLdap.bindDn"), 
+              new Credential(Messages.getString("ReadMyLdap.bindPassword")))); 
+      
+      final ConnectionFactory cf = new DefaultConnectionFactory(connConfig);
+
+      final SearchExecutor executor = new SearchExecutor();
+
+      executor.setBaseDn("ou=userlist, dc=hdm-stuttgart, dc=de"); //$NON-NLS-1$
+      final SearchResult result = executor.search(cf, "(uid=mistudent)").getResult(); //$NON-NLS-1$
+
+      final LdapEntry entry = result.getEntry();
+
+      
+      
+      for (final LdapAttribute att: entry.getAttributes()) {
+         if (att.isBinary()) {
+            System.out.println("Not displaying value of binary attribute '" + att.getName() + "'"); //$NON-NLS-1$ //$NON-NLS-2$
+         } else {
+            final int size = att.size(); 
+            if (1 == size) {
+               System.out.println(att.getName() + ": " + att.getStringValue()); //$NON-NLS-1$
+            } else {
+               int i = 0;
+               for (final String value: att.getStringValues()) {
+                  System.out.println(att.getName() + "[" + i++  + "]: " + value); //$NON-NLS-1$ //$NON-NLS-2$
+               }
+            }
+         }
+      }
+   }
+}
diff --git a/P/Sdi/ReadMyData/src/main/java/de/hdm_stuttgart/mi/sdai/readmydata/messages.properties.template b/P/Sdi/ReadMyData/src/main/java/de/hdm_stuttgart/mi/sdai/readmydata/messages.properties.template
new file mode 100644
index 000000000..adbffbf49
--- /dev/null
+++ b/P/Sdi/ReadMyData/src/main/java/de/hdm_stuttgart/mi/sdai/readmydata/messages.properties.template
@@ -0,0 +1,2 @@
+ReadMyLdap.bindDn=uid=mistudent, ou=userlist, dc=hdm-stuttgart, dc=de
+ReadMyLdap.bindPassword=verysecret
diff --git a/P/Sdi/ReadMyData/src/main/resources/log4j2.xml b/P/Sdi/ReadMyData/src/main/resources/log4j2.xml
new file mode 100644
index 000000000..cf51ef4ff
--- /dev/null
+++ b/P/Sdi/ReadMyData/src/main/resources/log4j2.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration>
+    <Appenders>
+        <File name="A1" fileName="A1.log" append="false">
+            <PatternLayout pattern="%t %-5p %c{2} - %m%n"/>
+        </File>
+        <Console name="STDOUT" target="SYSTEM_OUT">
+            <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
+        </Console>
+    </Appenders>
+    <Loggers>
+
+        <!-- You my want to define class or package level per-logger rules -->
+        <Logger name="de.hdm_stuttgart.mi.sda2.ldaptivetest.App" level="debug">
+            <AppenderRef ref="A1"/>
+        </Logger>
+        <Root level="info">
+            <AppenderRef ref="STDOUT"/>
+        </Root>
+    </Loggers>
+</Configuration>
\ No newline at end of file
diff --git a/P/Sdi/ReadMyData/src/test/java/de/hdm_stuttgart/mi/sda2/ldaptivetest/AppTest.java b/P/Sdi/ReadMyData/src/test/java/de/hdm_stuttgart/mi/sda2/ldaptivetest/AppTest.java
new file mode 100644
index 000000000..0f904e219
--- /dev/null
+++ b/P/Sdi/ReadMyData/src/test/java/de/hdm_stuttgart/mi/sda2/ldaptivetest/AppTest.java
@@ -0,0 +1,10 @@
+package de.hdm_stuttgart.mi.sda2.ldaptivetest;
+
+public class AppTest {
+    /**
+     * Dummy test method
+     */
+    public void testApp() {
+        // No tests yet defined.
+    }
+}
diff --git a/P/pom.xml b/P/pom.xml
index 170ccb930..6f7bcc521 100644
--- a/P/pom.xml
+++ b/P/pom.xml
@@ -178,6 +178,10 @@
     <module>Persist/Airline/airline_basic</module>
     <module>Persist/Airline/airline_key</module>
 
+
+    <!-- Software defined infrastructure -->
+    <module>Sdi/ReadMyData</module>
+
   </modules>
 
 <!--
-- 
GitLab