DSSeries LDAP V3 Client for Java Programming Guide
Introduction
This document describes how to install and program the DSSeries LDAP V3
classes. It is not intended to be an introduction to JNDI or LDAP, it assumes
you've read Sun's JNDI document included with the release and understand
how LDAP operates.
At this time the following LDAP V3 functions are implemented:
-
Support for all LDAP V3 operations except for Controls and Extended
Operations
-
LDAP V3 operations can be performed using URLs
-
Referral support
-
Extensible Search capability
-
UTF-8 support
This document is organized as follows:
-
Introduction
-
Installation
-
Using DSSeries LDAP V3 Client for Java
-
LDAP V3 URL Overview
-
Searching and Getting Attributes
-
Adding and Deleting
-
Modifying Attributes
-
Renaming
-
Browsing a Directory
-
Binary Attributes
-
URL Processing
-
Manipulating JNDI Properties
-
Referrals
-
Miscellaneous
The classes require JDK 1.x or higher.
Installation
-
Download ibmjndi.zip.
-
Create a directory for DSSeries LDAP V3 classes.
-
Unzip using winunzip or compatible utility into this directory. We'll assume
c:\dssJava. You should
have the following in that directory:
Guide.html |
this file |
README |
quick instructions |
ibmjndi.zip |
DSSeries classes |
jndi.zip |
Sun JNDI classes |
examples |
examples |
docs |
documentation |
-
Append the following to your CLASSPATH:
c:\dssJava\jndi.zip;c:\dssJava\ibmjndi.zip:c:\dssJava
UNIX variants:
/dssJava/jnid.zip:/dssJava/ibmjni.zip:/dssJava
-
In the examples directory are some test programs that can be compiled and
used to test with. Please see the README file in those directories
for directions on their use.
Using DSSeries LDAP V3 Client for Java
To use the DSSeries LDAP V3 classes, two properties must be set in the
environment properties passed to the IntialDirContext constructor:
-
java.naming.factory.initial - this property MUST be set to "com.ibm.jndi.LDAPCtxFactory".
-
java.naming.factory.url.pkgs - this property MUST be set to "com.ibm.jndi".
Example:
Properties env = new Properties();
env.put("java.naming.factory.initial","com.ibm.jndi.LDAPCtxFactory");
env.put("java.naming.factory.url.pkgs","com.ibm.jndi");
DirContext ctx = new InitialDirContext(env);
Alternatively you can specify the properties from the command line:
java "-Djava.naming.factory.initial=com.ibm.jndi.LDAPCtxFactory,-Dndi.urlfactory.pkgs=com.ibm.jndi"
LDAP V3 URL Overview
One of the most powerful features of LDAP V3 is its URL. LDAP V3
defines URLs that can be used to search and modify directory entries
or base DSSeries LDAP V3 operations in a directory hierarchy.
The format of the url is:
ldap://[hostname]:[port]/[dn]?[attributes]?[scope]?[filter]?[extensions]
Below is an explanation of the various parts of the LDAP V3 URL:
ldap:// - this is the scheme id of
the URL.The first seven characters of the URL must be set to
these characters for the classes to parse the URL correctly.
hostname - the host to connect to,
if it is missing JNDI defaults to localhost.
port - TCP/IP port to use, if it is
missing JNDI defaults to 389.
dn - the LDAP dn (distinguished name)
to base the operation in the hierarchy at
attributes - the attributes to return
from the search
scope - the scope of the search, if it is
missing, a scope of base is used.
filter - the filter to use, if it is
missing, a filter of "(objectclass=*)" is used.
extensions - these are special fields
to carry authentication information, they are unused
at this time.
In addition, since LDAP URLs conform to RFC 1738, unsafe characters
occurring inside the URL elements must be escaped. These characters are:
?&/@:{}\^~[]`"<>#% and a space character.
URL examples:
-
ldap://
host: localhost
port: 389
dn: null
attributes: null
scope: base
filter: (objectclass=*)
-
ldap://ldapserver/ou=hr,o=IBM,c=US??base
host: ldapserver
port:389
dn: ou=hr,o=IBM,c=US
attributes: null
scope: base
filter: (objectclass=*)
-
ldap://ldapserver:711/o=IBM,c=US?roomnumber,sn?object?
(%26(cn=smith)(roomnumber = 1200)(dept=human%20resources))
host: ldapserver
port: 711 dn: o=IBM,c=US
attributes: roomnumber,sn
scope: object
filter: (%26(cn=smith)(roomnumber=1200)(dept=human%20resources))
The last example shows how the character '&' and space character
need to be escaped (26 is the hex value for '&' , 20 for the
space). In a more readable form, the filter element would look:
(&(cn=smith)(roomnumber=1200)(dept=human resources))
but must be passed into JNDI escaped as above.
Searching and Getting Attributes
DSSeries LDAP V3 provides great flexibility in searching and retrieving
attributes from LDAP directories. Probably two of the most used methods
in the API are the search and getAttribute methods. Below,
are several examples of Java code that search a directory and retrieve
entry attributes. The parameters for these operations are directory entries
with a surname of "smith" and a base of "o=IBM, c=US".
Also demonstrated, is the technique to set the properties to use
the DSSeries LDAP V3 classes described in the section above
"Using DSSeries LDAP V3".
-
This example uses LDAP V3 URL to do a subtree search. Note how the hostname
and port of the ldapserver are determined by the URL string passed into
the search method:
Properties env = new Properties();
env.put("java.naming.factory.initial","com.ibm.jndi.LDAPCtxFactory");
env.put("java.naming.factory.url.pkgs","com.ibm.jndi");
String url="ldap://ldapserver:711/o=IBM,c=US??sub?(sn=smith)";
try {
DirContext ctx = new InitialDirContext(defProp);
NamingEnumeration results = ctx.search(url);
} catch (NamingException e) {
System.err.println("Search example failed "+e.getMessage());
}
To return phone number attributes only, change the
search url to:
ldap://ldapserver:711/o=IBM,c=US?telephonenumber?sub?(sn=smith)
-
This example does the same search as above; but doesn't use aURL to do
the search. Instead the search filter, base and contraints are built explicitly
and passed into the method:
Properties env = new Properties();
env.put("java.naming.factory.initial","com.ibm.jndi.LDAPCtxFactory");
env.put("java.naming.factory.url.pkgs","com.ibm.jndi");
env.put("java.naming.provider.url","ldap://ldapserver");
String base="ou=IBM,c=US";
String filter="(sn=smith");
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
try {
DirContext ctx = new InitialDirContext(defProp);
NamingEnumeration results = ctx.search(base,filter,constraints);
} catch (NamingException e) {
System.err.println("Search example failed "+e.getMessage());
}
Note how the special JNDI property "java.naming.provider.url" must be
set to tell
DSSeries LDAP V3 what server and port to use. To return
only the telephone
numbers attributes, add the following code to #2 example:
String attr[]=new String[1];
attr[0]="telephonenumber";
constraints.setReturningAttributes(attr);
-
The next example, uses a LDAP URL to return all the attributes
for the LDAP distinguished name
"cn=bill smith, o=IBM, c=US":
Properties env = new Properties();
env.put("java.naming.factory.initial","com.ibm.jndi.LDAPCtxFactory");
env.put("java.naming.factory.url.pkgs","com.ibm.jndi");
String url="ldap://ldapserver/cn=bill smith,o=IBM,c=US";
try {
DirContext ctx = new InitialDirContext(defProp);
Attributes results = ctx.getAttributes(url);
} catch (NamingException e) {
System.err.println("Search example failed "+e.getMessage());
}
To return the entries telephone number and roomnumber, change
the URL to:
ldap://ldapserver/cn=bill smith,o=IBM,c=US?roomnumber,telephonenumber
Adding and Deleting
JNDI makes it easy to add and delete entries in a directory. Since most
LDAP servers should
require authentication for changes, this section also illustrates passing
authentication information into DSSeries LDAP V3. We assume that the LDAP
system administrator has password protected write
access to the data.
-
This example adds an entry with the attributes roomnumber and telephonenumber
to the directory
ldapserver listening at port 711:
Properties env = new Properties();
env.put("java.naming.factory.initial","com.ibm.jndi.LDAPCtxFactory");
env.put("java.naming.factory.url.pkgs","com.ibm.jndi");
env.put("java.naming.provider.url","ldap://ldapserver:711");
env.put("java.naming.security.principal","cn=Directory Manager, o=IBM,
c=US");
env.put("java.naming.security.credentials","dirpassword");
Attributes atSet = new Attributes();
Attribute objClasses = new Attribute("objectclass");
objClasses.add("person");
objClasses.add("organizationalPerson");
objClasses.add("inetOrgPerson");
Attribute roomNum = new Attribute("roomnumber", "2000");
Attribute teleNum = new Attribute("telephonenumber", "1-800-use-LDAP");
atSet.add(roomNum);
atSet.add(teleNum);
String name="cn=mary smith,o=IBM,c=US";
try {
DirContext ctx = new InitialDirContext(defProp);
ctx.createSubcontext(name, atSet);
} catch (NameAlreadyBoundException nabe) {
System.out.println("createSubContext: " + name + " "+ nabe.getMessage());
} catch (NamingException e) {
System.err.println("createSubContext: " + name + " "+ e.getMessage());
}
-
This example deletes the above entry:
Properties env = new Properties();
env.put("java.naming.factory.initial","com.ibm.jndi.LDAPCtxFactory");
env.put("java.naming.factory.url.pkgs","com.ibm.jndi");
env.put("java.naming.provider.url","ldap://ldapserver:711");
env.put("java.naming.security.principal","cn=Directory Manager, o=IBM,
c=US");
env.put("java.naming.security.credentials","dirpassword");
String name="cn=mary smith,o=IBM,c=US";
try {
DirContext ctx = new InitialDirContext(defProp);
ctx.destroySubcontext(name);
} catch (NameNotFoundException nnfe) {
System.out.println( "destroySubcontext: " + name + nnfe.getMessage());
} catch (NamingException ne) {
System.err.println("destroySubcontext: "+name+" " + ne.getMessage());
}
-
This example deletes the same entry; but uses a URL passed into the
destroyContext method to define the server, port and entry to delete:
Properties env = new Properties();
env.put("java.naming.factory.initial","com.ibm.jndi.LDAPCtxFactory");
env.put("java.naming.factory.url.pkgs","com.ibm.jndi");
env.put("java.naming.security.principal","cn=Directory Manager, o=IBM,
c=US");
env.put("java.naming.security.credentials","dirpassword");
String url="ldap://ldapserver:711/cn=mary smith,o=IBM,c=US";
try {
DirContext ctx = new InitialDirContext(defProp);
ctx.destroySubcontext(url);
} catch (NameNotFoundException nnfe) {
System.out.println( "destroySubcontext: " + name + nnfe.getMessage());
} catch (NamingException ne) {
System.err.println("destroySubcontext: "+name+" " + ne.getMessage());
}
Modifying Attributes
DSSeries LDAP V3 can modify, create or remove attributes from directory
entries.
-
This example will replace will smith's surname, add his room number,
and delete his
phone number:
Properties env = new Properties();
env.put("java.naming.factory.initial","com.ibm.jndi.LDAPCtxFactory");
env.put("java.naming.factory.url.pkgs","com.ibm.jndi");
env.put("java.naming.security.principal","cn=Directory Manager, o=IBM,
c=US");
env.put("java.naming.security.credentials","dirpassword");
String url="ldap://ldapserver:711/cn=will smith,o=IBM,c=US";
ModificationItem[] mods
= new ModificationItem[]();
Attribute modAdd = new Attribute("roomnumber", "5000");
mods.append(DirContext.ADD_ATTRIBUTE, modAdd);
Attribute modReplace = new Attribute("sn", "smith");
mods.append(DirContext.REPLACE_ATTRIBUTE, modReplace);
Attribute modDelete = new Attribute("telephonenumber", "456-7777");
mods.append(DirContext.REMOVE_ATTRIBUTE, modDelete);
try {
DirContext ctx = new InitialDirContext(defProp);
ctx.modifyAttributes(url, mods);
} catch (NamingException ne) {
System.err.println("modify failed" + ne.getMessage());
}
Renaming a Directory Entry
LDAP V3 allows directory entries to rename the leftmost, or least significant
component (relative distinguished name) of a directory entry. For example,
you could rename "cn=bill smith,o=IBM,c=US" to "cn=william smith,o=IBM,c=US".
-
This example renames a directory entry using a URL to define host,
port and entry to modify:
Properties env = new Properties();
env.put("java.naming.factory.initial","com.ibm.jndi.LDAPCtxFactory");
env.put("java.naming.factory.url.pkgs","com.ibm.jndi");
env.put("java.naming.security.principal","cn=Directory Manager, o=IBM,
c=US");
env.put("java.naming.security.credentials","dirpassword");
String oldname="ldap://ldapserver:711/cn=bill smith,o=IBM,c=US";
String newname="cn=william smith";
try
{
DirContext ctx = new InitialDirContext(defProp);
ctx.rename(oldname, newname);
} catch (NamingException ne) {
System.err.println("rename("rename: " + ne.getMessage());
}
Browsing a Directory Hierarchy
Dsseries JNDI can be used to browse and maneuver around a directory
hierarchy. Suppose you wanted to browse the entries of the human
resources department at IBM. The following example will:
-
gets all of the relative distinguished names under "ou=hr,o=IBM,c=US" by
using the list method
-
enumerate through them looking for "cn=mary smith",
-
get a context for "cn=mary smith"
-
returns her room and telephone numbers
NamingEnumeration listResults=null;
Properties env = new Properties();
env.put("java.naming.factory.initial","com.ibm.jndi.LDAPCtxFactory");
env.put("java.naming.factory.url.pkgs","com.ibm.jndi");
String hrUrl="ldap://ldapserver:711/ou=hr,o=IBM,c=US";
String rdn="cn=mary smith";
try {
DirContext ctx = new InitialDirContext(defProp);
listResults=ctx.list(hrUrl);
while (listResults.hasMore()) {
NameClassPair ncp=listResults.next();
String thisName=ncp.getName();
if(thisName.equals(rdn)) {
DirContext ctx2=(DirContext)ctx.lookup(rdn);
String attrs[]=new String[2];
attrs[0]="telephonenumber";
attrs[1]="roomnumber";
Attributes rdnRes=ctx2.getAttributes("",attrs);
}
}
} catch (NamingException ne) {
System.err.println("browse error " + ne.getMessage());
}
Everything should look familar except using the null string to return the
attributes for
ctx2. The empty name tells JNDI to refer to the current context for
the operation. Also, note how the
lookup of the rdn is relative to the context for "ou=hr,o=IBM,c=US".
Handling Binary Attributes
LDAP servers can return binary objects. Examples of a binary object a user
might want to
read from LDAP are Jpeg photos or X.509 certificates. LDAP V3 defines
the special attribute description
option "binary" that tell LDAP V3 servers to return the attribute in
binary format. This does not affect
how the object is stored by the server and only tells the server
to return the data in a binary format.
LDAP V2 has no such option and will return binary data if the attribute
is declared binary in the schema.
This example shows how to read a binary entry from a LDAP V3 server.
You should note the binary option
after the attribute name "jpegphoto" in the URL:
Properties env = new Properties();
env.put("java.naming.factory.initial","com.ibm.jndi.LDAPCtxFactory");
env.put("java.naming.factory.url.pkgs","com.ibm.jndi");
String url="ldap://ldapserver/cn=bill smith,o=IBM,c=US?jpegphoto;binary
try {
DirContext ctx=new InitialDirContext(env);
Attributes res=ctx.getAttributes(env);
} catch (NamingException ne) {
System.err.println("binary get" + ne.getMessage());
}
Attribute attr=results.get("jpegphoto;binary");
Enumeration e=attr.getAll();
byte[] photo=(byte[])e.nextElement();
To do a V2 search, change the URL to:
ldap://ldapserver/cn=bill smith,o=IBM,c=US?jpegphoto
This example shows how to write a binary attribute to a server, we assume
the method
readPhotoFromDisk reads in a jpeg image file and returns it in a byte
array. We will add the
attribute to the entry:
Properties env = new Properties();
env.put("java.naming.factory.initial","com.ibm.jndi.LDAPCtxFactory");
env.put("java.naming.factory.url.pkgs","com.ibm.jndi");
byte[] photo=readPhotoFromDisk(somefilename);
String url="ldap://ldapserver/cn=bill smith,o=IBM,c=US
ModificationItem[] mods
= new ModificationItem[]();
Attribute modAdd = new Attribute("jpegphoto", (byte[]) photo);
mods.append(DirContext.ADD_ATTRIBUTE, modAdd);
try {
DirContext ctx=new InitialDirContext(env);
ctx.modifyAttributes(url, mods);
} catch (NamingException ne) {
System.err.println("binary get" + ne.getMessage());
}
URL Processing
Because of the DSSeries LDAP V3's flexibility, it's possible to have conflicts
between URLs and JNDI
properties. Consider the following:
Properties env = new Properties();
env.put("java.naming.factory.initial","com.ibm.jndi.LDAPCtxFactory");
env.put("java.naming.factory.url.pkgs","com.ibm.jndi");
env.put("java.naming.provider.url","ldap://ldapserver:711");
String url="ldap://ldapserver2:1200/cn=bill smith,o=IBM,c=US
ModificationItem[] mods
= new ModificationItem[]();
Attribute modAdd = new Attribute("jpegphoto", (byte[]) photo);
mods.append(DirContext.ADD_ATTRIBUTE, modAdd);
try {
DirContext ctx=new InitialDirContext(env);
ctx.modifyAttributes(url, mods);
} catch (NamingException ne) {
System.err.println("binary get" + ne.getMessage());
}
Note that there is a conflict between the property "java.naming.provider.url"
and the URL passed to the modifyAttributes method. In cases such as this,
the URL passed into the method takes priority. The
search would be performed on ldapserver2, at port 1200.
It is possible to get a context relative to some part of the directory
hierarchy; but do an LDAP operation on a totally different machine and
base:
Properties env = new Properties();
env.put("java.naming.factory.initial","com.ibm.jndi.LDAPCtxFactory");
env.put("java.naming.factory.url.pkgs","com.ibm.jndi");
env.put("java.naming.provider.url","ldap://ldapserver:711/o=Ace Industry,c=UK");
String url="ldap://ldapserver2:1200/cn=bill smith,o=IBM,c=US
try {
DirContext ctx = new InitialDirContext(env);
Attributes results = ctx.getAttributes(url);
...
In the above example, the context is bound to "o=Ace Industry, c=US"
on server ldapserver and at port 711;
but the attributes received are from ldapserver2, port 1200, and entry
"cn=bill smith,o=IBM,c=US".
Property Manipulation
Several methods exist to manipulate environment properties. You can
examine, set, add
properties to, and delete properties from a context's properties. The
example below demonstrate
using those methods to change a context's default properties. First
we will get a context's
setting, than add ("add.this","to.the.environment") to the context's
settings, finally we remove
the setting "add.this".
Properties env = new Properties();
env.put("java.naming.factory.initial","com.ibm.jndi.LDAPCtxFactory");
env.put("java.naming.factory.url.pkgs","com.ibm.jndi");
DirContext ctx=new InitialDirContext(env);
Hashtable ht=ctx.getEnvironment();
...
Hashtable undefTbl=ctx.addToEnvironment("add.this","to.the.environment");
undefTbl=ctx.removeFromEnvironment("add.this");
Attempts to delete nonexistent properties are ignored. Attempts to
add properties that exist already
over write them.
Referrals
A LDAP V3 server can return an array of referral URLs when
it receives a request for an operation
against a directory hierarchy the server does not serve. The
LDAP server administrator is responsible for configuring the server to
respond with referrals.
Referral Looping
When DSSeries LDAP V3 receives a referral from a server, it attempts to
perform the LDAP operation on the new server(s). It is possible for that
server(s) to return an array of referral URLs. Each new set of referrals
is called a "referral hop"; DSSeries LDAP V3 will attempt ten referral
hops to satisfy an request. In addition, it's possible for LDAP servers
to return referrals to each other (referral looping). DSSeries LDAP V3
detects when servers are configured to generate referral loops, and will
avoid referral looping between servers. It's also possible to be referred
from a LDAP V3 server to a LDAP V2 server, DSSeries LDAP V3 will
first attempt to perform the operation using LDAP V3, if that fails, step
down to LDAP V2 and try the operation.
Referral Authentication
At this time, all referral operations will be attempted using anonymous
binds. In the future, the LDAP V3 URL extension mechanism could
provide binding information for referrals, as well as other methods of
providing referral authentication currently being developed for DSSeries
LDAP V3.
Referral Performance
LDAP V3 referrals are expensive operations, developers should consider
if chasing referrals automatically is required. Below are some of the referral
chasing issues we' ve experienced:
-
Network segmentation can make referral chasing a time consuming process.
Since LDAP V3 is TCP connection based, referral attempts to
unreachable servers will time out based on TCP connection setup time
out values. These values are determined by the underlying operating
system TCP implementation and are typically are in the range of 1
or 2 minutes.
-
If a referral from a server contains a new filter, the operation will be
tried with a the new filter.
-
Its possible for an a large number of servers to be tried. Although
there is a limit on the number of hops to try there is no limit on number
of referrals in a referral set.
Referral Exceptions
Setting JNDI property "java.naming.referral" to follow
tells DSSeries LDAP V3 to automatically chase LDAP V3 referrals. They will
throw a referral exception if the property is set to throw and
a referral is received. Finally, if the property is set to ignore,
the referral will be ignored. If the property is not set, DSSeries LDAP
V3 automatically chases referrals. Below is an example of using the "java.naming.referral"
property to automatically follow referrals:
Properties env = new Properties();
env.put("java.naming.factory.initial","com.ibm.jndi.LDAPCtxFactory");
env.put("java.naming.factory.url.pkgs","com.ibm.jndi");
env.put("java.naming.referral","follow");
String url="ldap://ldapserver:711/o=IBM,c=US??sub?(sn=smith)";
try {
DirContext ctx = new InitialDirContext(defProp);
NamingEnumeration results = ctx.search(url);
} catch (NamingException e) {
System.err.println("Search example failed "+e.getMessage());
}
The next example sets the property to throw, catches the referral
exception and exits. See the SearchRef.java file (ldaegs/ldap directory)
for more robust example.
env.put("java.naming.referral","throw");
String url="ldap://ldapserver:711/o=IBM,c=US??sub?(sn=smith)";
try {
DirContext ctx = new InitialDirContext(defProp);
NamingEnumeration results = ctx.search(url);
} catch (ReferralException re) {
System.err.println("Referral exception caught");
System.exit(0);
} catch (NamingException e) {
System.err.println("Search example failed "+e.getMessage());
}
Set the property it ignore; if the referral should be ignored.
Miscellaneous
When you only need to talk to LDAP V2 servers; the special property
"ldap.version" should be set to 2. This avoids having DSSeries LDAP V3
first try connecting at V3 and then stepping down to V2 when a protocol
error is
received.
Properties env = new Properties();
env.put("java.naming.factory.initial","com.ibm.jndi.LDAPCtxFactory");
env.put("java.naming.factory.url.pkgs","com.ibm.jndi");
env.put("ldap.version","2");
LDAP V3 allows for servers to return data without doing a bind first. To
tell DSSeries LDAP V3 to attempt an LDAP operation without binding first,
set the special property "ldap.noBind" to true. When servers
receive an LDAP operation with no bind, they treat the operation as an
anonymous bind. The default is try a LDAP bind first (ldap.noBind=false).
Properties env = new Properties();
env.put("java.naming.factory.initial","com.ibm.jndi.LDAPCtxFactory");
env.put("java.naming.factory.url.pkgs","com.ibm.jndi");
env.put("ldap.noBind","true");
Searches and getAttributes are excellent candidates for no bind operations,
since they are read only operations and are more likely to succeed with
anonymous privileges. Currently DSSeries LDAP V3 will not automatically
retry a bind at LDAP V2 if a noBind LDAP V3 operation fails.
The java.naming.batchsize property can be used to limit the amount of
entries returned from a search.
Properties env = new Properties();
env.put("java.naming.factory.initial","com.ibm.jndi.LDAPCtxFactory");
env.put("java.naming.factory.url.pkgs","com.ibm.jndi");
env.put("java.naming.batchsize","10");
The above code tells the LDAP server to only return 10 results. It's
possible to have a conflict between explicitly setting the batchsize via
the Search Controls setCountSize() method and the implicitly setting it
via the property. When there is a conflict the explicit setting takes precedence.
Properties env = new Properties();
env.put("java.naming.factory.initial","com.ibm.jndi.LDAPCtxFactory");
env.put("java.naming.factory.url.pkgs","com.ibm.jndi");
env.put("java.naming.batchsize","10");
Search Controls ctrls=new SearchControls();
ctrls.setCountLimit((long)100);
In this example the count limit is set to 100.
Properties Not Implemented
Currently the following JNDI properties are currently not implemented:
java.naming.language
java.naming.security.protocol
java.naming.provider.version
java.naming.authoritative
In addition the java.naming.security.authentication supports only none
and simple.