зеркало из https://github.com/mozilla/pjs.git
Updtates for LDAPJDK 4.17
This commit is contained in:
Родитель
939b8670f9
Коммит
aa729f7d11
|
@ -168,9 +168,9 @@ public interface LDAPAsynchronousConnection {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes a single change to an existing entry in the directory (for
|
* Makes a single change to an existing entry in the directory.
|
||||||
* example, changes the value of an attribute, adds a new attribute
|
* For example, changes the value of an attribute, adds a new attribute
|
||||||
* value, or removes an existing attribute value).<BR>
|
* value, or removes an existing attribute value.<BR>
|
||||||
* The LDAPModification object specifies both the change to be made and
|
* The LDAPModification object specifies both the change to be made and
|
||||||
* the LDAPAttribute value to be changed.
|
* the LDAPAttribute value to be changed.
|
||||||
*
|
*
|
||||||
|
@ -190,9 +190,9 @@ public interface LDAPAsynchronousConnection {
|
||||||
throws LDAPException;
|
throws LDAPException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes a single change to an existing entry in the directory (for
|
* Makes a single change to an existing entry in the directory.
|
||||||
* example, changes the value of an attribute, adds a new attribute
|
* For example, changes the value of an attribute, adds a new attribute
|
||||||
* value, or removes an existing attribute value).<BR>
|
* value, or removes an existing attribute value.<BR>
|
||||||
* The LDAPModification object specifies both the change to be made and
|
* The LDAPModification object specifies both the change to be made and
|
||||||
* the LDAPAttribute value to be changed.
|
* the LDAPAttribute value to be changed.
|
||||||
*
|
*
|
||||||
|
@ -215,9 +215,9 @@ public interface LDAPAsynchronousConnection {
|
||||||
throws LDAPException;
|
throws LDAPException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes a set of changes to an existing entry in the directory (for
|
* Makes a set of changes to an existing entry in the directory.
|
||||||
* example, changes attribute values, adds new attribute values, or
|
* For example, changes attribute values, adds new attribute values, or
|
||||||
* removes existing attribute values).
|
* removes existing attribute values.
|
||||||
* <P>
|
* <P>
|
||||||
* @param dn distinguished name of the entry to modify
|
* @param dn distinguished name of the entry to modify
|
||||||
* @param mods a set of modifications to make to the entry
|
* @param mods a set of modifications to make to the entry
|
||||||
|
@ -235,9 +235,9 @@ public interface LDAPAsynchronousConnection {
|
||||||
throws LDAPException;
|
throws LDAPException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes a set of changes to an existing entry in the directory (for
|
* Makes a set of changes to an existing entry in the directory.
|
||||||
* example, changes attribute values, adds new attribute values, or
|
* For example, changes attribute values, adds new attribute values, or
|
||||||
* removes existing attribute values).
|
* removes existing attribute values.
|
||||||
*
|
*
|
||||||
* @param dn distinguished name of the entry to modify
|
* @param dn distinguished name of the entry to modify
|
||||||
* @param mods a set of modifications to make to the entry
|
* @param mods a set of modifications to make to the entry
|
||||||
|
|
|
@ -38,12 +38,12 @@ import java.net.*;
|
||||||
* When a connection is successfully created, a socket is opened. The socket
|
* When a connection is successfully created, a socket is opened. The socket
|
||||||
* is passed to the LDAPConnThread. The LDAPConnThread must call
|
* is passed to the LDAPConnThread. The LDAPConnThread must call
|
||||||
* invalidateConnection() if the connection is lost due to a network or
|
* invalidateConnection() if the connection is lost due to a network or
|
||||||
* server error, or disconnect() if the connection is deliberately terminated
|
* server error, or closeConnection() if the connection is deliberately terminated
|
||||||
* by the user.
|
* by the user.
|
||||||
*/
|
*/
|
||||||
class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
|
class LDAPConnSetupMgr implements java.io.Serializable {
|
||||||
|
|
||||||
static final long serialVersionUID = 1519402748245755306L;
|
static final long serialVersionUID = 1519402748245755307L;
|
||||||
/**
|
/**
|
||||||
* Policy for opening a connection when multiple servers are used
|
* Policy for opening a connection when multiple servers are used
|
||||||
*/
|
*/
|
||||||
|
@ -65,28 +65,32 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
|
||||||
* Representation for a server in the server list.
|
* Representation for a server in the server list.
|
||||||
*/
|
*/
|
||||||
class ServerEntry {
|
class ServerEntry {
|
||||||
String host;
|
LDAPUrl url;
|
||||||
int port;
|
|
||||||
int connSetupStatus;
|
int connSetupStatus;
|
||||||
Thread connSetupThread;
|
Thread connSetupThread;
|
||||||
|
|
||||||
ServerEntry(String host, int port, int status) {
|
ServerEntry(LDAPUrl url, int status) {
|
||||||
this.host = host;
|
this.url = url;
|
||||||
this.port = port;
|
|
||||||
connSetupStatus = status;
|
connSetupStatus = status;
|
||||||
connSetupThread = null;
|
connSetupThread = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "{" +host+":"+port + " status="+connSetupStatus+"}";
|
return "{" + url + " status="+connSetupStatus+"}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Socket to the connected server
|
* Socket to the connected server
|
||||||
*/
|
*/
|
||||||
private Socket m_socket = null;
|
private Socket m_socket = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Original, underlying socket to the server, see layerSocket()
|
||||||
|
*/
|
||||||
|
private Socket m_origSocket = null;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Last exception occured during connection setup
|
* Last exception occured during connection setup
|
||||||
*/
|
*/
|
||||||
|
@ -128,25 +132,50 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
|
||||||
*/
|
*/
|
||||||
private transient int m_attemptCnt = 0;
|
private transient int m_attemptCnt = 0;
|
||||||
|
|
||||||
/**
|
|
||||||
* Connection IDs for ldap trace messages
|
|
||||||
*/
|
|
||||||
private static int m_nextId;
|
|
||||||
private int m_id;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
* @param host list of host names to which to connect
|
* @param host list of host names to which to connect
|
||||||
* @param port list of port numbers corresponding to the host list
|
* @param port list of port numbers corresponding to the host list
|
||||||
* @param factory socket factory for SSL connections
|
* @param factory socket factory for SSL connections
|
||||||
*/
|
*/
|
||||||
LDAPConnSetupMgr(String[] hosts, int[] ports, LDAPSocketFactory factory) {
|
LDAPConnSetupMgr(String[] hosts, int[] ports, LDAPSocketFactory factory) throws LDAPException{
|
||||||
m_dsList = new ServerEntry[hosts.length];
|
m_dsList = new ServerEntry[hosts.length];
|
||||||
|
boolean secure = (factory != null);
|
||||||
for (int i=0; i < hosts.length; i++) {
|
for (int i=0; i < hosts.length; i++) {
|
||||||
m_dsList[i] = new ServerEntry(hosts[i], ports[i], NEVER_USED);
|
String url = secure ? "ldaps://" : "ldap://";
|
||||||
|
url += hosts[i] + ":" + ports[i];
|
||||||
|
try {
|
||||||
|
m_dsList[i] = new ServerEntry(new LDAPUrl(url), NEVER_USED);
|
||||||
|
}
|
||||||
|
catch (MalformedURLException ex) {
|
||||||
|
throw new LDAPException("Invalid host:port " + hosts[i]+":"+ports[i],
|
||||||
|
LDAPException.PARAM_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_factory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
LDAPConnSetupMgr(String[] urls, LDAPSocketFactory factory) throws LDAPException{
|
||||||
|
m_dsList = new ServerEntry[urls.length];
|
||||||
|
for (int i=0; i < urls.length; i++) {
|
||||||
|
try {
|
||||||
|
LDAPUrl url = new LDAPUrl(urls[i]);
|
||||||
|
m_dsList[i] = new ServerEntry(url, NEVER_USED);
|
||||||
|
}
|
||||||
|
catch (MalformedURLException ex) {
|
||||||
|
throw new LDAPException("Malformed LDAP URL " + urls[i],
|
||||||
|
LDAPException.PARAM_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_factory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
LDAPConnSetupMgr(LDAPUrl[] urls, LDAPSocketFactory factory) throws LDAPException{
|
||||||
|
m_dsList = new ServerEntry[urls.length];
|
||||||
|
for (int i=0; i < urls.length; i++) {
|
||||||
|
m_dsList[i] = new ServerEntry(urls[i], NEVER_USED);
|
||||||
}
|
}
|
||||||
m_factory = factory;
|
m_factory = factory;
|
||||||
m_id = m_nextId++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -204,7 +233,7 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
|
||||||
th.interrupt();
|
th.interrupt();
|
||||||
cleanup();
|
cleanup();
|
||||||
throw new LDAPException(
|
throw new LDAPException(
|
||||||
"connect timeout, " + getServerList() + " might be unreachable",
|
"Connect timeout, " + getServerList() + " might be unreachable",
|
||||||
LDAPException.CONNECT_ERROR);
|
LDAPException.CONNECT_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,12 +242,13 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new LDAPException(
|
throw new LDAPException(
|
||||||
"failed to connect to server " + getServerList(),
|
"Failed to connect to server " + getServerList(),
|
||||||
LDAPException.CONNECT_ERROR);
|
LDAPException.CONNECT_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reset() {
|
private void reset() {
|
||||||
m_socket = null;
|
m_socket = null;
|
||||||
|
m_origSocket = null;
|
||||||
m_connException = null;
|
m_connException = null;
|
||||||
m_attemptCnt = 0;
|
m_attemptCnt = 0;
|
||||||
|
|
||||||
|
@ -231,9 +261,9 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuffer sb = new StringBuffer();
|
||||||
for (int i=0; i < m_dsList.length; i++) {
|
for (int i=0; i < m_dsList.length; i++) {
|
||||||
sb.append(i==0 ? "" : " ");
|
sb.append(i==0 ? "" : " ");
|
||||||
sb.append(m_dsList[i].host);
|
sb.append(m_dsList[i].url.getHost());
|
||||||
sb.append(":");
|
sb.append(":");
|
||||||
sb.append(m_dsList[i].port);
|
sb.append(m_dsList[i].url.getPort());
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
@ -268,9 +298,25 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
|
||||||
newDsList[j] = m_dsList[m_dsIdx];
|
newDsList[j] = m_dsList[m_dsIdx];
|
||||||
m_dsList = newDsList;
|
m_dsList = newDsList;
|
||||||
m_dsIdx = j;
|
m_dsIdx = j;
|
||||||
|
|
||||||
|
try {
|
||||||
|
m_socket.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
} finally {
|
||||||
|
m_socket = null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_socket = null;
|
if (m_origSocket != null) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
m_origSocket.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
} finally {
|
||||||
|
m_origSocket = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -278,30 +324,69 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
|
||||||
* Mark the connected server status as DISCONNECTED. This will
|
* Mark the connected server status as DISCONNECTED. This will
|
||||||
* put it at top of the server list for the next connect attempt.
|
* put it at top of the server list for the next connect attempt.
|
||||||
*/
|
*/
|
||||||
void disconnect() {
|
void closeConnection() {
|
||||||
if (m_socket != null) {
|
if (m_socket != null) {
|
||||||
|
|
||||||
m_dsList[m_dsIdx].connSetupStatus = DISCONNECTED;
|
m_dsList[m_dsIdx].connSetupStatus = DISCONNECTED;
|
||||||
|
|
||||||
|
try {
|
||||||
|
m_socket.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
} finally {
|
||||||
|
m_socket = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_origSocket != null) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
m_origSocket.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
} finally {
|
||||||
|
m_origSocket = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_socket = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Socket getSocket() {
|
Socket getSocket() {
|
||||||
return m_socket;
|
return m_socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Layer a new socket over the existing one (used by startTLS)
|
||||||
|
*/
|
||||||
|
void layerSocket(LDAPTLSSocketFactory factory) throws LDAPException{
|
||||||
|
Socket s = factory.makeSocket(m_socket);
|
||||||
|
m_origSocket = m_socket;
|
||||||
|
m_socket = s;
|
||||||
|
}
|
||||||
|
|
||||||
String getHost() {
|
String getHost() {
|
||||||
if (m_dsIdx >= 0) {
|
if (m_dsIdx >= 0) {
|
||||||
return m_dsList[m_dsIdx].host;
|
return m_dsList[m_dsIdx].url.getHost();
|
||||||
}
|
}
|
||||||
return m_dsList[0].host;
|
return m_dsList[0].url.getHost();
|
||||||
}
|
}
|
||||||
|
|
||||||
int getPort() {
|
int getPort() {
|
||||||
if (m_dsIdx >= 0) {
|
if (m_dsIdx >= 0) {
|
||||||
return m_dsList[m_dsIdx].port;
|
return m_dsList[m_dsIdx].url.getPort();
|
||||||
}
|
}
|
||||||
return m_dsList[0].port;
|
return m_dsList[0].url.getPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isSecure() {
|
||||||
|
if (m_dsIdx >= 0) {
|
||||||
|
return m_dsList[m_dsIdx].url.isSecure();
|
||||||
|
}
|
||||||
|
return m_dsList[0].url.isSecure();
|
||||||
|
}
|
||||||
|
|
||||||
|
LDAPUrl getLDAPUrl() {
|
||||||
|
if (m_dsIdx >= 0) {
|
||||||
|
return m_dsList[m_dsIdx].url;
|
||||||
|
}
|
||||||
|
return m_dsList[0].url;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getConnSetupDelay() {
|
int getConnSetupDelay() {
|
||||||
|
@ -363,8 +448,7 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
|
||||||
|
|
||||||
//Create a Thread to execute connectSetver()
|
//Create a Thread to execute connectSetver()
|
||||||
final int dsIdx = i;
|
final int dsIdx = i;
|
||||||
String threadName = "ConnSetupMgr " +
|
String threadName = "ConnSetupMgr " + m_dsList[dsIdx].url;
|
||||||
m_dsList[dsIdx].host + ":" + m_dsList[dsIdx].port;
|
|
||||||
Thread t = new Thread(new Runnable() {
|
Thread t = new Thread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
connectServer(dsIdx);
|
connectServer(dsIdx);
|
||||||
|
@ -407,20 +491,29 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
|
||||||
Thread currThread = Thread.currentThread();
|
Thread currThread = Thread.currentThread();
|
||||||
Socket sock = null;
|
Socket sock = null;
|
||||||
LDAPException conex = null;
|
LDAPException conex = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
/* If we are to create a socket ourselves, make sure it has
|
/* If we are to create a socket ourselves, make sure it has
|
||||||
sufficient privileges to connect to the desired host */
|
sufficient privileges to connect to the desired host */
|
||||||
if (m_factory == null) {
|
if (!entry.url.isSecure()) {
|
||||||
sock = new Socket (entry.host, entry.port);
|
sock = new Socket (entry.url.getHost(), entry.url.getPort());
|
||||||
//s.setSoLinger( false, -1 );
|
|
||||||
} else {
|
} else {
|
||||||
sock = m_factory.makeSocket(entry.host, entry.port);
|
LDAPSocketFactory factory = m_factory;
|
||||||
|
if (factory == null) {
|
||||||
|
factory = entry.url.getSocketFactory();
|
||||||
|
}
|
||||||
|
if (factory == null) {
|
||||||
|
throw new LDAPException("Can not connect, no socket factory " + entry.url,
|
||||||
|
LDAPException.OTHER);
|
||||||
|
}
|
||||||
|
sock = factory.makeSocket(entry.url.getHost(), entry.url.getPort());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sock.setTcpNoDelay( true );
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
conex = new LDAPException("failed to connect to server "
|
conex = new LDAPException("failed to connect to server "
|
||||||
+ entry.host+":"+entry.port, LDAPException.CONNECT_ERROR);
|
+ entry.url, LDAPException.CONNECT_ERROR);
|
||||||
}
|
}
|
||||||
catch (LDAPException e) {
|
catch (LDAPException e) {
|
||||||
conex = e;
|
conex = e;
|
||||||
|
@ -514,29 +607,5 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
|
||||||
str += m_dsList[i]+ " ";
|
str += m_dsList[i]+ " ";
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
}
|
|
||||||
|
|
||||||
int getID() {
|
|
||||||
return m_id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String getLDAPUrl() {
|
|
||||||
return ((m_factory == null) ? "ldap" : "ldaps") +
|
|
||||||
"://" + getHost() + ":" + getPort();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object clone() {
|
|
||||||
try {
|
|
||||||
LDAPConnSetupMgr cloneMgr = (LDAPConnSetupMgr) super.clone();
|
|
||||||
cloneMgr.m_dsList = new ServerEntry[m_dsList.length];
|
|
||||||
for (int i=0; i<m_dsList.length; i++) {
|
|
||||||
ServerEntry e = m_dsList[i];
|
|
||||||
cloneMgr.m_dsList[i] = new ServerEntry(e.host, e.port, e.connSetupStatus);
|
|
||||||
}
|
|
||||||
return cloneMgr;
|
|
||||||
}
|
|
||||||
catch (CloneNotSupportedException ex) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ import java.text.SimpleDateFormat;
|
||||||
* All LDAPConnections send requests and get responses from
|
* All LDAPConnections send requests and get responses from
|
||||||
* LDAPConnThread (a thread).
|
* LDAPConnThread (a thread).
|
||||||
*/
|
*/
|
||||||
class LDAPConnThread extends Thread {
|
class LDAPConnThread implements Runnable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constants
|
* Constants
|
||||||
|
@ -61,21 +61,25 @@ class LDAPConnThread extends Thread {
|
||||||
* Internal variables
|
* Internal variables
|
||||||
*/
|
*/
|
||||||
transient private static int m_highMsgId;
|
transient private static int m_highMsgId;
|
||||||
transient private InputStream m_serverInput;
|
transient private InputStream m_serverInput, m_origServerInput;
|
||||||
transient private OutputStream m_serverOutput;
|
transient private OutputStream m_serverOutput, m_origServerOutput;
|
||||||
transient private Hashtable m_requests;
|
transient private Hashtable m_requests;
|
||||||
transient private Hashtable m_messages = null;
|
transient private Hashtable m_messages = null;
|
||||||
transient private Vector m_registered;
|
transient private Vector m_registered;
|
||||||
transient private boolean m_disconnected = false;
|
|
||||||
transient private LDAPCache m_cache = null;
|
transient private LDAPCache m_cache = null;
|
||||||
transient private boolean m_doRun = true;
|
|
||||||
private Socket m_socket = null;
|
|
||||||
transient private Thread m_thread = null;
|
transient private Thread m_thread = null;
|
||||||
transient Object m_sendRequestLock = new Object();
|
transient private Object m_sendRequestLock = new Object();
|
||||||
transient LDAPConnSetupMgr m_connMgr = null;
|
transient private LDAPConnSetupMgr m_connMgr = null;
|
||||||
transient Object m_traceOutput = null;
|
transient private Object m_traceOutput = null;
|
||||||
transient private int m_backlogCheckCounter = BACKLOG_CHKCNT;
|
transient private int m_backlogCheckCounter = BACKLOG_CHKCNT;
|
||||||
|
transient private boolean m_bound;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connection IDs for ldap trace messages
|
||||||
|
*/
|
||||||
|
transient private static int m_nextId;
|
||||||
|
transient private int m_id;
|
||||||
|
|
||||||
|
|
||||||
// Time Stemp format Hour(0-23):Minute:Second.Milliseconds used for trace msgs
|
// Time Stemp format Hour(0-23):Minute:Second.Milliseconds used for trace msgs
|
||||||
static SimpleDateFormat m_timeFormat = new SimpleDateFormat("HH:mm:ss.SSS");
|
static SimpleDateFormat m_timeFormat = new SimpleDateFormat("HH:mm:ss.SSS");
|
||||||
|
@ -83,47 +87,82 @@ class LDAPConnThread extends Thread {
|
||||||
/**
|
/**
|
||||||
* Constructs a connection thread that maintains connection to the
|
* Constructs a connection thread that maintains connection to the
|
||||||
* LDAP server.
|
* LDAP server.
|
||||||
* @param host LDAP host name
|
* @param connMgr the connection setup manager
|
||||||
* @param port LDAP port number
|
* @param cache cache object or null
|
||||||
* @param factory LDAP socket factory
|
* @param traceOutput trace object or null
|
||||||
*/
|
*/
|
||||||
public LDAPConnThread(LDAPConnSetupMgr connMgr, LDAPCache cache, Object traceOutput)
|
public LDAPConnThread(LDAPConnSetupMgr connMgr, LDAPCache cache, Object traceOutput) {
|
||||||
throws LDAPException {
|
|
||||||
super("LDAPConnThread " + connMgr.getHost() +":"+ connMgr.getPort());
|
|
||||||
m_requests = new Hashtable ();
|
m_requests = new Hashtable ();
|
||||||
m_registered = new Vector ();
|
m_registered = new Vector ();
|
||||||
m_connMgr = connMgr;
|
m_connMgr = connMgr;
|
||||||
m_socket = connMgr.getSocket();
|
|
||||||
setCache( cache );
|
setCache( cache );
|
||||||
setTraceOutput(traceOutput);
|
setTraceOutput(traceOutput);
|
||||||
|
}
|
||||||
setDaemon(true);
|
|
||||||
|
synchronized void connect(LDAPConnection ldc) throws LDAPException{
|
||||||
|
|
||||||
|
if (m_thread != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
m_connMgr.openConnection();
|
||||||
m_serverInput = new BufferedInputStream (m_socket.getInputStream());
|
m_serverInput = new BufferedInputStream (m_connMgr.getSocket().getInputStream());
|
||||||
m_serverOutput = new BufferedOutputStream (m_socket.getOutputStream());
|
m_serverOutput = new BufferedOutputStream(m_connMgr.getSocket().getOutputStream());
|
||||||
|
register(ldc);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|
||||||
// a kludge to make the thread go away. Since the thread has already
|
|
||||||
// been created, the only way to clean up the thread is to call the
|
|
||||||
// start() method. Otherwise, the exit method will be never called
|
|
||||||
// because the start() was never called. In the run method, the stop
|
|
||||||
// method calls right away if the m_doRun is set to false.
|
|
||||||
m_doRun = false;
|
|
||||||
start();
|
|
||||||
throw new LDAPException ( "failed to connect to server " +
|
throw new LDAPException ( "failed to connect to server " +
|
||||||
m_connMgr.getHost(), LDAPException.CONNECT_ERROR );
|
m_connMgr.getHost(), LDAPException.CONNECT_ERROR );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (traceOutput != null) {
|
m_id = m_nextId++;
|
||||||
StringBuffer sb = new StringBuffer(" connected to ");
|
String url = m_connMgr.getLDAPUrl().getServerUrl();
|
||||||
sb.append(m_connMgr.getLDAPUrl());
|
|
||||||
|
if (m_traceOutput != null) {
|
||||||
|
StringBuffer sb = new StringBuffer(" Connected to ");
|
||||||
|
sb.append(url);
|
||||||
logTraceMessage(sb);
|
logTraceMessage(sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
start(); /* start the thread */
|
String threadID = "LDAPConnThread-" + m_id + " " + url;
|
||||||
|
m_thread = new Thread(this, threadID);
|
||||||
|
m_thread.setDaemon(true);
|
||||||
|
m_thread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized String toString() {
|
||||||
|
if (m_thread != null) {
|
||||||
|
return m_thread.getName();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "LDAPConnThread-" + m_id + " <disconnected>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Layer a SSL socket over the current non-SSL one
|
||||||
|
*/
|
||||||
|
void layerSocket(LDAPTLSSocketFactory factory) throws Exception {
|
||||||
|
synchronized (m_sendRequestLock) {
|
||||||
|
try {
|
||||||
|
m_connMgr.layerSocket(factory);
|
||||||
|
setInputStream(m_connMgr.getSocket().getInputStream());
|
||||||
|
setOutputStream(m_connMgr.getSocket().getOutputStream());
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
m_serverInput = m_origServerInput;
|
||||||
|
m_serverOutput = m_origServerOutput;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setBound(boolean bound) {
|
||||||
|
m_bound = bound;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isBound() {
|
||||||
|
return (m_thread != null) && m_bound;
|
||||||
}
|
}
|
||||||
|
|
||||||
InputStream getInputStream() {
|
InputStream getInputStream() {
|
||||||
|
@ -142,6 +181,10 @@ class LDAPConnThread extends Thread {
|
||||||
m_serverOutput = os;
|
m_serverOutput = os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getRequestCount() {
|
||||||
|
return m_requests.size();
|
||||||
|
}
|
||||||
|
|
||||||
void setTraceOutput(Object traceOutput) {
|
void setTraceOutput(Object traceOutput) {
|
||||||
synchronized (m_sendRequestLock) {
|
synchronized (m_sendRequestLock) {
|
||||||
if (traceOutput == null) {
|
if (traceOutput == null) {
|
||||||
|
@ -161,7 +204,7 @@ class LDAPConnThread extends Thread {
|
||||||
String timeStamp = m_timeFormat.format(new Date());
|
String timeStamp = m_timeFormat.format(new Date());
|
||||||
StringBuffer sb = new StringBuffer(timeStamp);
|
StringBuffer sb = new StringBuffer(timeStamp);
|
||||||
sb.append(" ldc=");
|
sb.append(" ldc=");
|
||||||
sb.append(m_connMgr.getID());
|
sb.append(m_id);
|
||||||
|
|
||||||
synchronized( m_sendRequestLock ) {
|
synchronized( m_sendRequestLock ) {
|
||||||
if (m_traceOutput instanceof PrintWriter) {
|
if (m_traceOutput instanceof PrintWriter) {
|
||||||
|
@ -207,38 +250,71 @@ class LDAPConnThread extends Thread {
|
||||||
void sendRequest (LDAPConnection conn, JDAPProtocolOp request,
|
void sendRequest (LDAPConnection conn, JDAPProtocolOp request,
|
||||||
LDAPMessageQueue toNotify, LDAPConstraints cons)
|
LDAPMessageQueue toNotify, LDAPConstraints cons)
|
||||||
throws LDAPException {
|
throws LDAPException {
|
||||||
if (!m_doRun) {
|
|
||||||
throw new LDAPException ( "not connected to a server",
|
if (m_thread == null) {
|
||||||
LDAPException.SERVER_DOWN );
|
throw new LDAPException ( "Not connected to a server",
|
||||||
|
LDAPException.SERVER_DOWN );
|
||||||
}
|
}
|
||||||
|
|
||||||
LDAPMessage msg =
|
LDAPMessage msg =
|
||||||
new LDAPMessage(allocateId(), request, cons.getServerControls());
|
new LDAPMessage(allocateId(), request, cons.getServerControls());
|
||||||
|
|
||||||
if ( toNotify != null ) {
|
if ( toNotify != null ) {
|
||||||
if (!(request instanceof JDAPAbandonRequest ||
|
/* Only worry about toNotify if we expect a response... */
|
||||||
request instanceof JDAPUnbindRequest)) {
|
m_requests.put (new Integer (msg.getMessageID()), toNotify);
|
||||||
/* Only worry about toNotify if we expect a response... */
|
|
||||||
this.m_requests.put (new Integer (msg.getMessageID()), toNotify);
|
/* Notify the backlog checker that there may be another outstanding
|
||||||
/* Notify the backlog checker that there may be another outstanding
|
request */
|
||||||
request */
|
resultRetrieved();
|
||||||
resultRetrieved();
|
|
||||||
}
|
|
||||||
toNotify.addRequest(msg.getMessageID(), conn, this, cons.getTimeLimit());
|
toNotify.addRequest(msg.getMessageID(), conn, this, cons.getTimeLimit());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!sendRequest(msg, /*ignoreErrors=*/false)) {
|
||||||
|
throw new LDAPException("Server or network error",
|
||||||
|
LDAPException.SERVER_DOWN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean sendRequest (LDAPMessage msg, boolean ignoreErrors) {
|
||||||
synchronized( m_sendRequestLock ) {
|
synchronized( m_sendRequestLock ) {
|
||||||
try {
|
try {
|
||||||
if (m_traceOutput != null) {
|
if (m_traceOutput != null) {
|
||||||
logTraceMessage(msg.toTraceString());
|
logTraceMessage(msg.toTraceString());
|
||||||
}
|
}
|
||||||
msg.write (m_serverOutput);
|
msg.write (m_serverOutput);
|
||||||
m_serverOutput.flush ();
|
m_serverOutput.flush();
|
||||||
} catch (IOException e) {
|
return true;
|
||||||
networkError(e);
|
|
||||||
}
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
if (!ignoreErrors) {
|
||||||
|
networkError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (NullPointerException e) {
|
||||||
|
// m_serverOutput is null bacause of network error
|
||||||
|
if (!ignoreErrors) {
|
||||||
|
if (m_thread != null) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void sendUnbindRequest(LDAPControl[] ctrls) {
|
||||||
|
LDAPMessage msg =
|
||||||
|
new LDAPMessage(allocateId(), new JDAPUnbindRequest(), ctrls);
|
||||||
|
sendRequest(msg, /*ignoreErrors=*/true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendAbandonRequest(int id, LDAPControl[] ctrls) {
|
||||||
|
LDAPMessage msg =
|
||||||
|
new LDAPMessage(allocateId(), new JDAPAbandonRequest(id), ctrls);
|
||||||
|
sendRequest(msg, /*ignoreErrors=*/true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register with this connection thread.
|
* Register with this connection thread.
|
||||||
* @param conn LDAP connection
|
* @param conn LDAP connection
|
||||||
|
@ -252,8 +328,8 @@ class LDAPConnThread extends Thread {
|
||||||
return m_registered.size();
|
return m_registered.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isRunning() {
|
boolean isConnected() {
|
||||||
return m_doRun;
|
return m_thread != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -261,111 +337,118 @@ class LDAPConnThread extends Thread {
|
||||||
* is deregistered. Then, this thread should be killed.
|
* is deregistered. Then, this thread should be killed.
|
||||||
* @param conn LDAP connection
|
* @param conn LDAP connection
|
||||||
*/
|
*/
|
||||||
public synchronized void deregister(LDAPConnection conn) {
|
/**
|
||||||
|
* De-Register with this connection thread. If all the connection
|
||||||
|
* is deregistered. Then, this thread should be killed.
|
||||||
|
* @param conn LDAP connection
|
||||||
|
*/
|
||||||
|
synchronized void deregister(LDAPConnection conn) {
|
||||||
|
|
||||||
|
if (m_thread == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_registered.removeElement(conn);
|
m_registered.removeElement(conn);
|
||||||
if (m_registered.size() == 0) {
|
if (m_registered.size() == 0) {
|
||||||
try {
|
|
||||||
|
// No more request processing
|
||||||
|
Thread t = m_thread;
|
||||||
|
m_thread = null;
|
||||||
|
|
||||||
if (!m_disconnected) {
|
try {
|
||||||
LDAPSearchConstraints cons = conn.getSearchConstraints();
|
// Notify the server
|
||||||
sendRequest (null, new JDAPUnbindRequest (), null, cons);
|
sendUnbindRequest(conn.getConstraints().getServerControls());
|
||||||
}
|
|
||||||
|
|
||||||
// must be set after the call to sendRequest
|
// interrupt the thread
|
||||||
m_doRun =false;
|
try {
|
||||||
|
t.interrupt();
|
||||||
if ( m_thread != null && m_thread != Thread.currentThread()) {
|
wait(500);
|
||||||
|
|
||||||
m_thread.interrupt();
|
|
||||||
|
|
||||||
// Wait up to 1 sec for thread to accept disconnect
|
|
||||||
// notification. When the interrupt is accepted,
|
|
||||||
// m_thread is set to null. See run() method.
|
|
||||||
try {
|
|
||||||
wait(1000);
|
|
||||||
}
|
|
||||||
catch (InterruptedException e) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
catch (InterruptedException ignore) {}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LDAPConnection.printDebug(e.toString());
|
LDAPConnection.printDebug(e.toString());
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
cleanUp();
|
cleanUp(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clean ups before shutdown the thread.
|
* Clean up after the thread shutdown.
|
||||||
|
* The list of registered clients m_registered is left in the current state
|
||||||
|
* to enable the clients to recover the connection.
|
||||||
*/
|
*/
|
||||||
private void cleanUp() {
|
private void cleanUp(LDAPException ex) {
|
||||||
if (!m_disconnected) {
|
|
||||||
|
resultRetrieved();
|
||||||
|
|
||||||
|
try {
|
||||||
|
m_serverOutput.close ();
|
||||||
|
} catch (Exception e) {
|
||||||
|
} finally {
|
||||||
|
m_serverOutput = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
m_serverInput.close ();
|
||||||
|
} catch (Exception e) {
|
||||||
|
} finally {
|
||||||
|
m_serverInput = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_origServerInput != null) {
|
||||||
try {
|
try {
|
||||||
m_serverOutput.close ();
|
m_origServerInput.close ();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
} finally {
|
} finally {
|
||||||
m_serverOutput = null;
|
m_origServerInput = null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_origServerOutput != null) {
|
||||||
try {
|
try {
|
||||||
m_serverInput.close ();
|
m_origServerOutput.close ();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
} finally {
|
} finally {
|
||||||
m_serverInput = null;
|
m_origServerOutput = null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
// Notify the Connection Manager
|
||||||
m_socket.close ();
|
if (ex != null) {
|
||||||
} catch (Exception e) {
|
// the connection is lost
|
||||||
} finally {
|
m_connMgr.invalidateConnection();
|
||||||
m_socket = null;
|
}
|
||||||
}
|
else {
|
||||||
|
// the connection is closed
|
||||||
m_disconnected = true;
|
m_connMgr.closeConnection();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
// Set the status for all outstanding requests
|
||||||
* Notify the Connection Setup Manager that the connection was
|
Enumeration requests = m_requests.elements();
|
||||||
* terminated by the user
|
while (requests.hasMoreElements()) {
|
||||||
*/
|
try {
|
||||||
m_connMgr.disconnect();
|
LDAPMessageQueue listener =
|
||||||
|
(LDAPMessageQueue)requests.nextElement();
|
||||||
/**
|
if (ex != null) {
|
||||||
* Cancel all outstanding requests
|
listener.setException(this, ex);
|
||||||
*/
|
}
|
||||||
if (m_requests != null) {
|
else {
|
||||||
Enumeration requests = m_requests.elements();
|
|
||||||
while (requests.hasMoreElements()) {
|
|
||||||
LDAPMessageQueue listener =
|
|
||||||
(LDAPMessageQueue)requests.nextElement();
|
|
||||||
listener.removeAllRequests(this);
|
listener.removeAllRequests(this);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify all the registered about this bad moment.
|
|
||||||
* IMPORTANT: This needs to be done at last. Otherwise, the socket
|
|
||||||
* input stream and output stream might never get closed and the whole
|
|
||||||
* task will get stuck in the stop method when we tried to stop the
|
|
||||||
* LDAPConnThread.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (m_registered != null) {
|
|
||||||
Vector registerCopy = (Vector)m_registered.clone();
|
|
||||||
|
|
||||||
Enumeration cancelled = registerCopy.elements();
|
|
||||||
|
|
||||||
while (cancelled.hasMoreElements ()) {
|
|
||||||
LDAPConnection c = (LDAPConnection)cancelled.nextElement();
|
|
||||||
c.deregisterConnection();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
m_registered.removeAllElements();
|
catch (Exception ignore) {}
|
||||||
m_requests.clear();
|
}
|
||||||
m_messages = null;
|
m_requests.clear();
|
||||||
m_cache = null;
|
|
||||||
|
if (m_messages != null) {
|
||||||
|
m_messages.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_bound = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -383,8 +466,8 @@ class LDAPConnThread extends Thread {
|
||||||
while( listeners.hasMoreElements() ) {
|
while( listeners.hasMoreElements() ) {
|
||||||
LDAPMessageQueue l = (LDAPMessageQueue)listeners.nextElement();
|
LDAPMessageQueue l = (LDAPMessageQueue)listeners.nextElement();
|
||||||
|
|
||||||
// If there are any threads waiting for a regular response
|
// If there are clients waiting for a regular response
|
||||||
// message, we have to go read the next incoming message
|
// message, skip backlog checking
|
||||||
if ( !(l instanceof LDAPSearchListener) ) {
|
if ( !(l instanceof LDAPSearchListener) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -437,29 +520,21 @@ class LDAPConnThread extends Thread {
|
||||||
* Reads from the LDAP server input stream for incoming LDAP messages.
|
* Reads from the LDAP server input stream for incoming LDAP messages.
|
||||||
*/
|
*/
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
||||||
// if there is a problem of establishing connection to the server,
|
|
||||||
// stop the thread right away...
|
|
||||||
if (!m_doRun) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_thread = Thread.currentThread();
|
|
||||||
LDAPMessage msg = null;
|
LDAPMessage msg = null;
|
||||||
JDAPBERTagDecoder decoder = new JDAPBERTagDecoder();
|
JDAPBERTagDecoder decoder = new JDAPBERTagDecoder();
|
||||||
|
int[] nread = new int[1];
|
||||||
|
|
||||||
while (m_doRun) {
|
while (Thread.currentThread() == m_thread) {
|
||||||
yield();
|
|
||||||
int[] nread = new int[1];
|
|
||||||
nread[0] = 0;
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// Check after every BACKLOG_CHKCNT messages if the backlog is not too high
|
// Check every BACKLOG_CHKCNT messages if the backlog is not too high
|
||||||
if (--m_backlogCheckCounter <= 0) {
|
if (--m_backlogCheckCounter <= 0) {
|
||||||
m_backlogCheckCounter = BACKLOG_CHKCNT;
|
m_backlogCheckCounter = BACKLOG_CHKCNT;
|
||||||
checkBacklog();
|
checkBacklog();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nread[0] = 0;
|
||||||
BERElement element = BERElement.getElement(decoder,
|
BERElement element = BERElement.getElement(decoder,
|
||||||
m_serverInput,
|
m_serverInput,
|
||||||
nread);
|
nread);
|
||||||
|
@ -473,17 +548,14 @@ class LDAPConnThread extends Thread {
|
||||||
// entry, thereby avoiding serialization of the entry stored in the
|
// entry, thereby avoiding serialization of the entry stored in the
|
||||||
// cache
|
// cache
|
||||||
processResponse (msg, nread[0]);
|
processResponse (msg, nread[0]);
|
||||||
|
Thread.yield();
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (m_doRun) {
|
if (Thread.currentThread() == m_thread) {
|
||||||
networkError(e);
|
networkError(e);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// interrupted from deregister()
|
resultRetrieved();
|
||||||
synchronized (this) {
|
|
||||||
m_thread = null;
|
|
||||||
notifyAll();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -502,24 +574,6 @@ class LDAPConnThread extends Thread {
|
||||||
return; /* nobody is waiting for this response (!) */
|
return; /* nobody is waiting for this response (!) */
|
||||||
}
|
}
|
||||||
|
|
||||||
// For asynch operations controls are to be read from the LDAPMessage
|
|
||||||
// For synch operations controls are copied into the LDAPConnection
|
|
||||||
// For synch search operations, controls are also copied into
|
|
||||||
// LDAPSearchResults (see LDAPConnection.checkSearchMsg())
|
|
||||||
if ( ! l.isAsynchOp()) {
|
|
||||||
|
|
||||||
/* Were there any controls for this client? */
|
|
||||||
LDAPControl[] con = msg.getControls();
|
|
||||||
if (con != null) {
|
|
||||||
int msgid = msg.getMessageID();
|
|
||||||
LDAPConnection ldc = l.getConnection(msgid);
|
|
||||||
if (ldc != null) {
|
|
||||||
ldc.setResponseControls( this,
|
|
||||||
new LDAPResponseControl(ldc, msgid, con));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_cache != null && (l instanceof LDAPSearchListener)) {
|
if (m_cache != null && (l instanceof LDAPSearchListener)) {
|
||||||
cacheSearchResult((LDAPSearchListener)l, msg, size);
|
cacheSearchResult((LDAPSearchListener)l, msg, size);
|
||||||
}
|
}
|
||||||
|
@ -530,10 +584,42 @@ class LDAPConnThread extends Thread {
|
||||||
m_requests.remove (messageID);
|
m_requests.remove (messageID);
|
||||||
if (m_requests.size() == 0) {
|
if (m_requests.size() == 0) {
|
||||||
m_backlogCheckCounter = BACKLOG_CHKCNT;
|
m_backlogCheckCounter = BACKLOG_CHKCNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Change IO streams if startTLS extended op completed
|
||||||
|
if (msg instanceof LDAPExtendedResponse) {
|
||||||
|
LDAPExtendedResponse extrsp = (LDAPExtendedResponse) msg;
|
||||||
|
String extid = extrsp.getID();
|
||||||
|
if (extrsp.getResultCode() == 0 && extid != null &&
|
||||||
|
extid.equals(LDAPConnection.OID_startTLS)) {
|
||||||
|
|
||||||
|
changeIOStreams();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void changeIOStreams() {
|
||||||
|
|
||||||
|
// Note: For the startTLS, the new streams are layered over the
|
||||||
|
// existing ones so current IO streams as well as the socket MUST
|
||||||
|
// not be closed.
|
||||||
|
m_origServerInput = m_serverInput;
|
||||||
|
m_origServerOutput = m_serverOutput;
|
||||||
|
m_serverInput = null;
|
||||||
|
m_serverOutput = null;
|
||||||
|
|
||||||
|
while (m_serverInput == null || m_serverOutput == null) {
|
||||||
|
try {
|
||||||
|
if (Thread.currentThread() != m_thread) {
|
||||||
|
return; // user disconnected
|
||||||
|
}
|
||||||
|
Thread.sleep(200);
|
||||||
|
} catch (InterruptedException ignore) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collect search results to be added to the LDAPCache. Search results are
|
* Collect search results to be added to the LDAPCache. Search results are
|
||||||
* packaged in a vector and temporary stored into a hashtable m_messages
|
* packaged in a vector and temporary stored into a hashtable m_messages
|
||||||
|
@ -629,12 +715,13 @@ class LDAPConnThread extends Thread {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop dispatching responses for a particular message ID.
|
* Stop dispatching responses for a particular message ID and send
|
||||||
|
* the abandon request.
|
||||||
* @param id Message ID for which to discard responses.
|
* @param id Message ID for which to discard responses.
|
||||||
*/
|
*/
|
||||||
void abandon (int id ) {
|
void abandon (int id, LDAPControl[] ctrls) {
|
||||||
|
|
||||||
if (!m_doRun) {
|
if (m_thread == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -647,6 +734,8 @@ class LDAPConnThread extends Thread {
|
||||||
l.removeRequest(id);
|
l.removeRequest(id);
|
||||||
}
|
}
|
||||||
resultRetrieved(); // If LDAPConnThread is blocked in checkBacklog()
|
resultRetrieved(); // If LDAPConnThread is blocked in checkBacklog()
|
||||||
|
|
||||||
|
sendAbandonRequest(id, ctrls);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -657,7 +746,7 @@ class LDAPConnThread extends Thread {
|
||||||
*/
|
*/
|
||||||
LDAPMessageQueue changeListener (int id, LDAPMessageQueue toNotify) {
|
LDAPMessageQueue changeListener (int id, LDAPMessageQueue toNotify) {
|
||||||
|
|
||||||
if (!m_doRun) {
|
if (m_thread == null) {
|
||||||
toNotify.setException(this, new LDAPException("Server or network error",
|
toNotify.setException(this, new LDAPException("Server or network error",
|
||||||
LDAPException.SERVER_DOWN));
|
LDAPException.SERVER_DOWN));
|
||||||
return null;
|
return null;
|
||||||
|
@ -672,26 +761,11 @@ class LDAPConnThread extends Thread {
|
||||||
*/
|
*/
|
||||||
private synchronized void networkError (Exception e) {
|
private synchronized void networkError (Exception e) {
|
||||||
|
|
||||||
m_doRun =false;
|
if (m_thread == null) {
|
||||||
|
return;
|
||||||
// notify the Connection Setup Manager that the connection is lost
|
|
||||||
m_connMgr.invalidateConnection();
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
// notify each listener that the server is down.
|
|
||||||
Enumeration requests = m_requests.elements();
|
|
||||||
while (requests.hasMoreElements()) {
|
|
||||||
LDAPMessageQueue listener =
|
|
||||||
(LDAPMessageQueue)requests.nextElement();
|
|
||||||
listener.setException(this, new LDAPException("Server or network error",
|
|
||||||
LDAPException.SERVER_DOWN));
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (NullPointerException ee) {
|
|
||||||
System.err.println("Exception: "+ee.toString());
|
|
||||||
}
|
}
|
||||||
|
m_thread = null; // No more request processing
|
||||||
cleanUp();
|
cleanUp(new LDAPException("Server or network error",
|
||||||
|
LDAPException.SERVER_DOWN));
|
||||||
}
|
}
|
||||||
}
|
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -360,30 +360,31 @@ public class LDAPConstraints implements Cloneable, java.io.Serializable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes a copy of an existing set of constraints.
|
* Makes a copy of an existing set of constraints.
|
||||||
* @returns a copy of an existing set of constraints
|
* @return a copy of an existing set of constraints
|
||||||
*/
|
*/
|
||||||
public Object clone() {
|
public Object clone() {
|
||||||
LDAPConstraints o = new LDAPConstraints();
|
try {
|
||||||
|
LDAPConstraints o = (LDAPConstraints) super.clone();
|
||||||
|
|
||||||
o.m_time_limit = this.m_time_limit;
|
if ( (this.m_clientControls != null) &&
|
||||||
o.referrals = this.referrals;
|
(this.m_clientControls.length > 0) ) {
|
||||||
o.m_bind_proc = this.m_bind_proc;
|
o.m_clientControls = new LDAPControl[this.m_clientControls.length];
|
||||||
o.m_rebind_proc = this.m_rebind_proc;
|
for( int i = 0; i < this.m_clientControls.length; i++ )
|
||||||
o.m_hop_limit = this.m_hop_limit;
|
o.m_clientControls[i] =
|
||||||
if ( (this.m_clientControls != null) &&
|
(LDAPControl)this.m_clientControls[i].clone();
|
||||||
(this.m_clientControls.length > 0) ) {
|
}
|
||||||
o.m_clientControls = new LDAPControl[this.m_clientControls.length];
|
if ( (this.m_serverControls != null) &&
|
||||||
for( int i = 0; i < this.m_clientControls.length; i++ )
|
(this.m_serverControls.length > 0) ) {
|
||||||
o.m_clientControls[i] =
|
o.m_serverControls = new LDAPControl[this.m_serverControls.length];
|
||||||
(LDAPControl)this.m_clientControls[i].clone();
|
for( int i = 0; i < this.m_serverControls.length; i++ )
|
||||||
|
o.m_serverControls[i] =
|
||||||
|
(LDAPControl)this.m_serverControls[i].clone();
|
||||||
|
}
|
||||||
|
return o;
|
||||||
}
|
}
|
||||||
if ( (this.m_serverControls != null) &&
|
catch (CloneNotSupportedException ex) {
|
||||||
(this.m_serverControls.length > 0) ) {
|
// shold never happen, the class is Cloneable
|
||||||
o.m_serverControls = new LDAPControl[this.m_serverControls.length];
|
return null;
|
||||||
for( int i = 0; i < this.m_serverControls.length; i++ )
|
|
||||||
o.m_serverControls[i] =
|
|
||||||
(LDAPControl)this.m_serverControls[i].clone();
|
|
||||||
}
|
}
|
||||||
return o;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,6 +123,7 @@ import java.io.*;
|
||||||
* 95 <A HREF="#MORE_RESULTS_TO_RETURN">MORE_RESULTS_TO_RETURN</A>
|
* 95 <A HREF="#MORE_RESULTS_TO_RETURN">MORE_RESULTS_TO_RETURN</A>
|
||||||
* 96 <A HREF="#CLIENT_LOOP">CLIENT_LOOP</A>
|
* 96 <A HREF="#CLIENT_LOOP">CLIENT_LOOP</A>
|
||||||
* 97 <A HREF="#REFERRAL_LIMIT_EXCEEDED">REFERRAL_LIMIT_EXCEEDED</A>
|
* 97 <A HREF="#REFERRAL_LIMIT_EXCEEDED">REFERRAL_LIMIT_EXCEEDED</A>
|
||||||
|
* 112 <A HREF="#TLS_NOT_SUPPORTED">TLS_NOT_SUPPORTED</A> (LDAP v3)
|
||||||
* </PRE>
|
* </PRE>
|
||||||
* <P>
|
* <P>
|
||||||
*
|
*
|
||||||
|
@ -132,7 +133,7 @@ import java.io.*;
|
||||||
public class LDAPException extends java.lang.Exception
|
public class LDAPException extends java.lang.Exception
|
||||||
implements java.io.Serializable {
|
implements java.io.Serializable {
|
||||||
|
|
||||||
static final long serialVersionUID = -9215007872184847924L;
|
static final long serialVersionUID = -9215007872184847925L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (0) The operation completed successfully.
|
* (0) The operation completed successfully.
|
||||||
|
@ -556,11 +557,21 @@ public class LDAPException extends java.lang.Exception
|
||||||
*/
|
*/
|
||||||
public final static int REFERRAL_LIMIT_EXCEEDED = 0x61;
|
public final static int REFERRAL_LIMIT_EXCEEDED = 0x61;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (112) The socket factory of the connection is not capable
|
||||||
|
* of initiating a TLS session.
|
||||||
|
* <P>
|
||||||
|
*
|
||||||
|
* @see netscape.ldap.LDAPConnection#startTLS
|
||||||
|
*/
|
||||||
|
public final static int TLS_NOT_SUPPORTED = 0x70;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal variables
|
* Internal variables
|
||||||
*/
|
*/
|
||||||
private int resultCode = -1;
|
private int resultCode = -1;
|
||||||
private String errorMessage = null;
|
private String errorMessage = null;
|
||||||
|
private String extraMessage = null;
|
||||||
private String matchedDN = null;
|
private String matchedDN = null;
|
||||||
private Locale m_locale = Locale.getDefault();
|
private Locale m_locale = Locale.getDefault();
|
||||||
private static Hashtable cacheResource = new Hashtable();
|
private static Hashtable cacheResource = new Hashtable();
|
||||||
|
@ -733,17 +744,32 @@ public class LDAPException extends java.lang.Exception
|
||||||
public String getLDAPErrorMessage () {
|
public String getLDAPErrorMessage () {
|
||||||
return errorMessage;
|
return errorMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds additional explanation to the error message
|
||||||
|
*/
|
||||||
|
void setExtraMessage (String msg) {
|
||||||
|
if (extraMessage == null) {
|
||||||
|
extraMessage = msg;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
extraMessage += "; " + msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the maximal subset of a DN which could be matched by the
|
* Returns the maximal subset of a DN which could be matched by the
|
||||||
* server, if the server returned one of the following errors:
|
* server.
|
||||||
|
*
|
||||||
|
* The method should be used if the server returned one of the
|
||||||
|
* following errors:
|
||||||
* <UL>
|
* <UL>
|
||||||
* <LI><CODE>NO_SUCH_OBJECT</CODE>
|
* <LI><CODE>NO_SUCH_OBJECT</CODE>
|
||||||
* <LI><CODE>ALIAS_PROBLEM</CODE>
|
* <LI><CODE>ALIAS_PROBLEM</CODE>
|
||||||
* <LI><CODE>INVALID_DN_SYNTAX</CODE>
|
* <LI><CODE>INVALID_DN_SYNTAX</CODE>
|
||||||
* <LI><CODE>ALIAS_DEREFERENCING_PROBLEM</CODE>
|
* <LI><CODE>ALIAS_DEREFERENCING_PROBLEM</CODE>
|
||||||
* </UL>
|
* </UL>
|
||||||
* </PRE>
|
|
||||||
* For example, if the DN <CODE>cn=Babs Jensen, o=People, c=Airius.com</CODE>
|
* For example, if the DN <CODE>cn=Babs Jensen, o=People, c=Airius.com</CODE>
|
||||||
* could not be found by the DN <CODE>o=People, c=Airius.com</CODE>
|
* could not be found by the DN <CODE>o=People, c=Airius.com</CODE>
|
||||||
* could be found, the matched DN is
|
* could be found, the matched DN is
|
||||||
|
@ -791,14 +817,19 @@ public class LDAPException extends java.lang.Exception
|
||||||
*/
|
*/
|
||||||
public String toString() {
|
public String toString() {
|
||||||
String str = super.toString() + " (" + resultCode + ")" ;
|
String str = super.toString() + " (" + resultCode + ")" ;
|
||||||
if ( (errorMessage != null) && (errorMessage.length() > 0) )
|
if ( (errorMessage != null) && (errorMessage.length() > 0) ) {
|
||||||
str += "; " + errorMessage;
|
str += "; " + errorMessage;
|
||||||
if ( (matchedDN != null) && (matchedDN.length() > 0) )
|
}
|
||||||
|
if ( (matchedDN != null) && (matchedDN.length() > 0) ) {
|
||||||
str += "; matchedDN = " + matchedDN;
|
str += "; matchedDN = " + matchedDN;
|
||||||
String errorStr = null;
|
}
|
||||||
if (((errorStr = errorCodeToString(m_locale)) != null) &&
|
String errorStr = errorCodeToString(m_locale);
|
||||||
(errorStr.length() > 0))
|
if ((errorStr != null) && (errorStr.length() > 0)) {
|
||||||
str += "; " + errorStr;
|
str += "; " + errorStr;
|
||||||
|
}
|
||||||
|
if (extraMessage != null) {
|
||||||
|
str += "; " + extraMessage;
|
||||||
|
}
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ import java.util.Vector;
|
||||||
*/
|
*/
|
||||||
class LDAPMessageQueue implements java.io.Serializable {
|
class LDAPMessageQueue implements java.io.Serializable {
|
||||||
|
|
||||||
static final long serialVersionUID = -7163312406176592277L;
|
static final long serialVersionUID = -7163312406176592278L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request entry encapsulates request parameters
|
* Request entry encapsulates request parameters
|
||||||
|
@ -88,6 +88,27 @@ class LDAPMessageQueue implements java.io.Serializable {
|
||||||
return m_asynchOp;
|
return m_asynchOp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blocks until a response is available.
|
||||||
|
* Used by LDAPConnection.sendRequest (synch ops) to test if the server
|
||||||
|
* is really available after a request had been sent.
|
||||||
|
* @exception LDAPException Network error exception
|
||||||
|
* @exception LDAPInterruptedException The invoking thread was interrupted
|
||||||
|
*/
|
||||||
|
synchronized void waitFirstMessage () throws LDAPException {
|
||||||
|
|
||||||
|
while(m_requestList.size() != 0 && m_exception == null && m_messageQueue.size() == 0) {
|
||||||
|
waitForMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Network exception occurred ?
|
||||||
|
if (m_exception != null) {
|
||||||
|
LDAPException ex = m_exception;
|
||||||
|
m_exception = null;
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Blocks until a response is available or until all operations
|
* Blocks until a response is available or until all operations
|
||||||
* associated with the object have completed or been canceled.
|
* associated with the object have completed or been canceled.
|
||||||
|
@ -287,7 +308,7 @@ class LDAPMessageQueue implements java.io.Serializable {
|
||||||
// Mark conn as bound for asych bind operations
|
// Mark conn as bound for asych bind operations
|
||||||
if (isAsynchOp() && msg.getType() == msg.BIND_RESPONSE) {
|
if (isAsynchOp() && msg.getType() == msg.BIND_RESPONSE) {
|
||||||
if (((LDAPResponse) msg).getResultCode() == 0) {
|
if (((LDAPResponse) msg).getResultCode() == 0) {
|
||||||
getConnection(msg.getMessageID()).markConnAsBound();
|
getConnection(msg.getMessageID()).setBound(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -178,7 +178,7 @@ public class LDAPSSLSocketFactory
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <B>This method is currently not implemented.</B>
|
* <B>This method is currently not implemented</B>.
|
||||||
* Enables client authentication for an application that uses
|
* Enables client authentication for an application that uses
|
||||||
* an external (file-based) certificate database.
|
* an external (file-based) certificate database.
|
||||||
* Call this method before you call <CODE>makeSocket</CODE>.
|
* Call this method before you call <CODE>makeSocket</CODE>.
|
||||||
|
|
|
@ -225,7 +225,7 @@ public class LDAPSaslBind implements LDAPBind, java.io.Serializable {
|
||||||
_saslClient,
|
_saslClient,
|
||||||
className, "getOutputStream", args, argNames);
|
className, "getOutputStream", args, argNames);
|
||||||
ldc.setOutputStream(os);
|
ldc.setOutputStream(os);
|
||||||
ldc.markConnAsBound();
|
ldc.setBound(true);
|
||||||
} catch (LDAPException e) {
|
} catch (LDAPException e) {
|
||||||
throw e;
|
throw e;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -34,11 +34,25 @@ package netscape.ldap;
|
||||||
public class LDAPSearchConstraints extends LDAPConstraints
|
public class LDAPSearchConstraints extends LDAPConstraints
|
||||||
implements Cloneable {
|
implements Cloneable {
|
||||||
|
|
||||||
|
|
||||||
|
// Constants for behavior when a search continuation reference cannot
|
||||||
|
// be followed
|
||||||
|
/**
|
||||||
|
* Continue processing if there is an error following a search continuation
|
||||||
|
* reference
|
||||||
|
*/
|
||||||
|
public static final int REFERRAL_ERROR_CONTINUE = 0;
|
||||||
|
/**
|
||||||
|
* Throw exception if there is an error following a search continuation
|
||||||
|
* reference
|
||||||
|
*/
|
||||||
|
public static final int REFERRAL_ERROR_EXCEPTION = 1;
|
||||||
private int deref;
|
private int deref;
|
||||||
private int maxRes;
|
private int maxRes;
|
||||||
private int batch;
|
private int batch;
|
||||||
private int serverTimeLimit;
|
private int serverTimeLimit;
|
||||||
private int maxBacklog = 100;
|
private int maxBacklog = 100;
|
||||||
|
private int referralErrors = REFERRAL_ERROR_CONTINUE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an <CODE>LDAPSearchConstraints</CODE> object that specifies
|
* Constructs an <CODE>LDAPSearchConstraints</CODE> object that specifies
|
||||||
|
@ -81,8 +95,10 @@ public class LDAPSearchConstraints extends LDAPConstraints
|
||||||
* @param hop_limit maximum number of referrals to follow in a
|
* @param hop_limit maximum number of referrals to follow in a
|
||||||
* sequence when attempting to resolve a request
|
* sequence when attempting to resolve a request
|
||||||
* @see netscape.ldap.LDAPConnection#setOption(int, java.lang.Object)
|
* @see netscape.ldap.LDAPConnection#setOption(int, java.lang.Object)
|
||||||
* @see netscape.ldap.LDAPConnection#search(netscape.ldap.LDAPUrl, netscape.ldap.LDAPSearchConstraints)
|
* @see netscape.ldap.LDAPConnection#search(netscape.ldap.LDAPUrl,
|
||||||
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean, netscape.ldap.LDAPSearchConstraints)
|
netscape.ldap.LDAPSearchConstraints)
|
||||||
|
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String,
|
||||||
|
java.lang.String[], boolean, netscape.ldap.LDAPSearchConstraints)
|
||||||
*/
|
*/
|
||||||
public LDAPSearchConstraints( int msLimit, int dereference,
|
public LDAPSearchConstraints( int msLimit, int dereference,
|
||||||
int maxResults, boolean doReferrals, int batchSize,
|
int maxResults, boolean doReferrals, int batchSize,
|
||||||
|
@ -125,8 +141,10 @@ public class LDAPSearchConstraints extends LDAPConstraints
|
||||||
* @param hop_limit maximum number of referrals to follow in a
|
* @param hop_limit maximum number of referrals to follow in a
|
||||||
* sequence when attempting to resolve a request
|
* sequence when attempting to resolve a request
|
||||||
* @see netscape.ldap.LDAPConnection#setOption(int, java.lang.Object)
|
* @see netscape.ldap.LDAPConnection#setOption(int, java.lang.Object)
|
||||||
* @see netscape.ldap.LDAPConnection#search(netscape.ldap.LDAPUrl, netscape.ldap.LDAPSearchConstraints)
|
* @see netscape.ldap.LDAPConnection#search(netscape.ldap.LDAPUrl,
|
||||||
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean, netscape.ldap.LDAPSearchConstraints)
|
netscape.ldap.LDAPSearchConstraints)
|
||||||
|
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String,
|
||||||
|
java.lang.String[], boolean, netscape.ldap.LDAPSearchConstraints)
|
||||||
*/
|
*/
|
||||||
public LDAPSearchConstraints( int msLimit, int timeLimit,
|
public LDAPSearchConstraints( int msLimit, int timeLimit,
|
||||||
int dereference,
|
int dereference,
|
||||||
|
@ -171,8 +189,10 @@ public class LDAPSearchConstraints extends LDAPConstraints
|
||||||
* @param hop_limit maximum number of referrals to follow in a
|
* @param hop_limit maximum number of referrals to follow in a
|
||||||
* sequence when attempting to resolve a request
|
* sequence when attempting to resolve a request
|
||||||
* @see netscape.ldap.LDAPConnection#setOption(int, java.lang.Object)
|
* @see netscape.ldap.LDAPConnection#setOption(int, java.lang.Object)
|
||||||
* @see netscape.ldap.LDAPConnection#search(netscape.ldap.LDAPUrl, netscape.ldap.LDAPSearchConstraints)
|
* @see netscape.ldap.LDAPConnection#search(netscape.ldap.LDAPUrl,
|
||||||
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean, netscape.ldap.LDAPSearchConstraints)
|
netscape.ldap.LDAPSearchConstraints)
|
||||||
|
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String,
|
||||||
|
java.lang.String[], boolean, netscape.ldap.LDAPSearchConstraints)
|
||||||
*/
|
*/
|
||||||
public LDAPSearchConstraints( int msLimit, int timeLimit,
|
public LDAPSearchConstraints( int msLimit, int timeLimit,
|
||||||
int dereference,
|
int dereference,
|
||||||
|
@ -296,51 +316,101 @@ public class LDAPSearchConstraints extends LDAPConstraints
|
||||||
return maxBacklog;
|
return maxBacklog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reports if errors when following search continuation references are
|
||||||
|
* to cause processing of the remaining results to be aborted.
|
||||||
|
* <p>
|
||||||
|
* If an LDAP server does not contain an entry at the base DN for a search,
|
||||||
|
* it may be configured to return a referral. If it contains an entry at
|
||||||
|
* the base DN of a subtree search, one or more of the child entries may
|
||||||
|
* contain search continuation references. The search continuation
|
||||||
|
* references are returned to the client, which may follow them by issuing
|
||||||
|
* a search request to the host indicated in the search reference.
|
||||||
|
* <p>
|
||||||
|
* If the <CODE>LDAPConnection</CODE> object has been configured to follow
|
||||||
|
* referrals automatically, it may fail when issuing a search request to
|
||||||
|
* the host indicated in a search reference, e.g. because there is no
|
||||||
|
* entry there, because it does not have credentials, because it does not
|
||||||
|
* have sufficient permissions, etc. If the client aborts evaluation of the
|
||||||
|
* search results (obtained through <CODE>LDAPSearchResults</CODE>) when a
|
||||||
|
* search reference cannot be followed, any remaining results are discarded.
|
||||||
|
* <p>
|
||||||
|
* Up to version 4.17 of the Java LDAP SDK, the SDK printed an error
|
||||||
|
* message but continued to process the remaining search results and search
|
||||||
|
* continuation references.
|
||||||
|
* <p>
|
||||||
|
* As of SDK version 4.17, the default behavior is still to continue
|
||||||
|
* processing any remaining search results and search continuation
|
||||||
|
* references if there is an error following a referral, but the behavior
|
||||||
|
* may be changed with <CODE>setReferralErrors</CODE> to throw an exception
|
||||||
|
* instead.
|
||||||
|
*
|
||||||
|
* @return <CODE>REFERRAL_ERROR_CONTINUE</CODE> if remaining results are
|
||||||
|
* to be processed when there is an error following a search continuation
|
||||||
|
* reference, <CODE>REFERRAL_ERROR_EXCEPTION</CODE> if such an error is to
|
||||||
|
* cause an <CODE>LDAPException</CODE>.
|
||||||
|
*
|
||||||
|
* @see netscape.ldap.LDAPConstraints#setReferrals
|
||||||
|
* @since LDAPJDK 4.17
|
||||||
|
*/
|
||||||
|
public int getReferralErrors() {
|
||||||
|
return referralErrors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies if errors when following search continuation references are
|
||||||
|
* to cause processing of the remaining results to be aborted.
|
||||||
|
* <p>
|
||||||
|
* If an LDAP server does not contain an entry at the base DN for a search,
|
||||||
|
* it may be configured to return a referral. If it contains an entry at
|
||||||
|
* the base DN of a subtree search, one or more of the child entries may
|
||||||
|
* contain search continuation references. The search continuation
|
||||||
|
* references are returned to the client, which may follow them by issuing
|
||||||
|
* a search request to the host indicated in the search reference.
|
||||||
|
* <p>
|
||||||
|
* If the <CODE>LDAPConnection</CODE> object has been configured to follow
|
||||||
|
* referrals automatically, it may fail when issuing a search request to
|
||||||
|
* the host indicated in a search reference, e.g. because there is no
|
||||||
|
* entry there, because it does not have credentials, because it does not
|
||||||
|
* have sufficient permissions, etc. If the client aborts evaluation of the
|
||||||
|
* search results (obtained through <CODE>LDAPSearchResults</CODE>) when a
|
||||||
|
* search reference cannot be followed, any remaining results are discarded.
|
||||||
|
* <p>
|
||||||
|
* Up to version 4.17 of the Java LDAP SDK, the SDK printed an error
|
||||||
|
* message but continued to process the remaining search results and search
|
||||||
|
* continuation references.
|
||||||
|
* <p>
|
||||||
|
* As of SDK version 4.17, the default behavior is still to continue
|
||||||
|
* processing any remaining search results and search continuation
|
||||||
|
* references if there is an error following a referral, but the behavior
|
||||||
|
* may be changed with <CODE>setReferralErrors</CODE> to throw an exception
|
||||||
|
* instead.
|
||||||
|
*
|
||||||
|
* @param errorBehavior Either <CODE>REFERRAL_ERROR_CONTINUE</CODE> if
|
||||||
|
* remaining results are to be processed when there is an error following a
|
||||||
|
* search continuation reference or <CODE>REFERRAL_ERROR_EXCEPTION</CODE>
|
||||||
|
* if such an error is to cause an <CODE>LDAPException</CODE>.
|
||||||
|
*
|
||||||
|
* @see netscape.ldap.LDAPSearchConstraints#getReferralErrors
|
||||||
|
* @see netscape.ldap.LDAPSearchResults#next
|
||||||
|
* @see netscape.ldap.LDAPSearchResults#nextElement
|
||||||
|
* @since LDAPJDK 4.17
|
||||||
|
*/
|
||||||
|
public void setReferralErrors(int errorBehavior) {
|
||||||
|
if ( (errorBehavior != REFERRAL_ERROR_CONTINUE) &&
|
||||||
|
(errorBehavior != REFERRAL_ERROR_EXCEPTION) ) {
|
||||||
|
throw new IllegalArgumentException( "Invalid error behavior: " +
|
||||||
|
errorBehavior );
|
||||||
|
}
|
||||||
|
referralErrors = errorBehavior;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes a copy of an existing set of search constraints.
|
* Makes a copy of an existing set of search constraints.
|
||||||
* @return a copy of an existing set of search constraints.
|
* @return a copy of an existing set of search constraints.
|
||||||
*/
|
*/
|
||||||
public Object clone() {
|
public Object clone() {
|
||||||
LDAPSearchConstraints o = new LDAPSearchConstraints();
|
LDAPSearchConstraints o = (LDAPSearchConstraints) super.clone();
|
||||||
|
|
||||||
o.serverTimeLimit = this.serverTimeLimit;
|
|
||||||
o.deref = this.deref;
|
|
||||||
o.maxRes = this.maxRes;
|
|
||||||
o.batch = this.batch;
|
|
||||||
o.maxBacklog = this.maxBacklog;
|
|
||||||
|
|
||||||
o.setHopLimit(this.getHopLimit());
|
|
||||||
o.setReferrals(this.getReferrals());
|
|
||||||
o.setTimeLimit(this.getTimeLimit());
|
|
||||||
|
|
||||||
if (this.getBindProc() != null) {
|
|
||||||
o.setBindProc(this.getBindProc());
|
|
||||||
} else {
|
|
||||||
o.setRebindProc(this.getRebindProc());
|
|
||||||
}
|
|
||||||
|
|
||||||
LDAPControl[] tClientControls = this.getClientControls();
|
|
||||||
LDAPControl[] oClientControls;
|
|
||||||
|
|
||||||
if ( (tClientControls != null) &&
|
|
||||||
(tClientControls.length > 0) ) {
|
|
||||||
oClientControls = new LDAPControl[tClientControls.length];
|
|
||||||
for( int i = 0; i < tClientControls.length; i++ )
|
|
||||||
oClientControls[i] = (LDAPControl)tClientControls[i].clone();
|
|
||||||
o.setClientControls(oClientControls);
|
|
||||||
}
|
|
||||||
|
|
||||||
LDAPControl[] tServerControls = this.getServerControls();
|
|
||||||
LDAPControl[] oServerControls;
|
|
||||||
|
|
||||||
if ( (tServerControls != null) &&
|
|
||||||
(tServerControls.length > 0) ) {
|
|
||||||
oServerControls = new LDAPControl[tServerControls.length];
|
|
||||||
for( int i = 0; i < tServerControls.length; i++ )
|
|
||||||
oServerControls[i] = (LDAPControl)tServerControls[i].clone();
|
|
||||||
o.setServerControls(oServerControls);
|
|
||||||
}
|
|
||||||
|
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,7 +426,8 @@ public class LDAPSearchConstraints extends LDAPConstraints
|
||||||
sb.append("server time limit " + serverTimeLimit + ", ");
|
sb.append("server time limit " + serverTimeLimit + ", ");
|
||||||
sb.append("aliases " + deref + ", ");
|
sb.append("aliases " + deref + ", ");
|
||||||
sb.append("batch size " + batch + ", ");
|
sb.append("batch size " + batch + ", ");
|
||||||
sb.append("max backlog " + maxBacklog);
|
sb.append("max backlog " + maxBacklog + ", ");
|
||||||
|
sb.append("referralErrors " + referralErrors);
|
||||||
sb.append('}');
|
sb.append('}');
|
||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
|
|
|
@ -549,7 +549,7 @@ public class LDAPSearchResults implements Enumeration, java.io.Serializable {
|
||||||
currBase, currScope, currFilter,
|
currBase, currScope, currFilter,
|
||||||
currAttrs, currAttrsOnly);
|
currAttrs, currAttrsOnly);
|
||||||
} catch (LDAPException e) {
|
} catch (LDAPException e) {
|
||||||
System.err.println("LDAPSearchResults.fetchResult: "+e);
|
add(e);
|
||||||
} finally {
|
} finally {
|
||||||
currConn.releaseSearchListener(resultSource);
|
currConn.releaseSearchListener(resultSource);
|
||||||
}
|
}
|
||||||
|
@ -567,7 +567,7 @@ public class LDAPSearchResults implements Enumeration, java.io.Serializable {
|
||||||
currConn.checkSearchMsg(this, msg, currCons,
|
currConn.checkSearchMsg(this, msg, currCons,
|
||||||
currBase, currScope, currFilter, currAttrs, currAttrsOnly);
|
currBase, currScope, currFilter, currAttrs, currAttrsOnly);
|
||||||
} catch (LDAPException e) {
|
} catch (LDAPException e) {
|
||||||
System.err.println("Exception: "+e);
|
add(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public
|
||||||
|
* License Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS
|
||||||
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
* implied. See the License for the specific language governing
|
||||||
|
* rights and limitations under the License.
|
||||||
|
*
|
||||||
|
* The Original Code is mozilla.org code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is Netscape
|
||||||
|
* Communications Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 2002 Netscape Communications Corporation. All
|
||||||
|
* Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*/
|
||||||
|
package netscape.ldap;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A socket factory interface for supporting the start TLS LDAPv3
|
||||||
|
* extension (RFC 2830).
|
||||||
|
* <P>
|
||||||
|
*
|
||||||
|
* @version 1.0
|
||||||
|
* @since LDAPJDK 4.17
|
||||||
|
*/
|
||||||
|
public interface LDAPTLSSocketFactory extends LDAPSocketFactory {
|
||||||
|
/**
|
||||||
|
* Creates an SSL socket layered over an existing socket.
|
||||||
|
*
|
||||||
|
* Used for the start TLS operations (RFC2830).
|
||||||
|
*
|
||||||
|
* @param s An existing non-SSL socket
|
||||||
|
* @return A SSL socket layered over the input socket
|
||||||
|
* @exception LDAPException on error creating socket
|
||||||
|
* @see LDAPConnection#startTLS
|
||||||
|
*/
|
||||||
|
public Socket makeSocket(Socket s) throws LDAPException;
|
||||||
|
}
|
|
@ -24,7 +24,6 @@ package netscape.ldap;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import netscape.ldap.factory.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an LDAP URL. The complete specification for LDAP URLs is in
|
* Represents an LDAP URL. The complete specification for LDAP URLs is in
|
||||||
|
@ -81,7 +80,7 @@ import netscape.ldap.factory.*;
|
||||||
*/
|
*/
|
||||||
public class LDAPUrl implements java.io.Serializable {
|
public class LDAPUrl implements java.io.Serializable {
|
||||||
|
|
||||||
static final long serialVersionUID = -3245440798565713640L;
|
static final long serialVersionUID = -3245440798565713641L;
|
||||||
public static String defaultFilter = "(objectClass=*)";
|
public static String defaultFilter = "(objectClass=*)";
|
||||||
|
|
||||||
private String m_hostName;
|
private String m_hostName;
|
||||||
|
@ -371,7 +370,7 @@ public class LDAPUrl implements java.io.Serializable {
|
||||||
} else
|
} else
|
||||||
m_attributes = null;
|
m_attributes = null;
|
||||||
|
|
||||||
StringBuffer url = new StringBuffer (secure ? "LDAPS://" :"LDAP://");
|
StringBuffer url = new StringBuffer (secure ? "ldaps://" :"ldap://");
|
||||||
|
|
||||||
if (host != null) {
|
if (host != null) {
|
||||||
url.append (host);
|
url.append (host);
|
||||||
|
@ -444,6 +443,15 @@ public class LDAPUrl implements java.io.Serializable {
|
||||||
return m_DN;
|
return m_DN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the server part of the ldap url, ldap://host:port
|
||||||
|
* @return server url.
|
||||||
|
*/
|
||||||
|
String getServerUrl() {
|
||||||
|
return (m_secure ? "ldaps://" : "ldap://") +
|
||||||
|
m_hostName + ":" + m_portNumber;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the collection of attributes specified in the URL, or null
|
* Return the collection of attributes specified in the URL, or null
|
||||||
* for "every attribute"
|
* for "every attribute"
|
||||||
|
@ -545,10 +553,10 @@ public class LDAPUrl implements java.io.Serializable {
|
||||||
|
|
||||||
if (m_factory == null) {
|
if (m_factory == null) {
|
||||||
|
|
||||||
// No factory explicity set, try to determine
|
// No factory explicitly set, try to determine
|
||||||
// the default one.
|
// the default one.
|
||||||
try {
|
try {
|
||||||
// First try iPlanet JSSSocketFactory
|
// First try Mozilla JSSSocketFactory
|
||||||
Class c = Class.forName("netscape.ldap.factory.JSSSocketFactory");
|
Class c = Class.forName("netscape.ldap.factory.JSSSocketFactory");
|
||||||
m_factory = (LDAPSocketFactory) c.newInstance();
|
m_factory = (LDAPSocketFactory) c.newInstance();
|
||||||
}
|
}
|
||||||
|
@ -561,7 +569,8 @@ public class LDAPUrl implements java.io.Serializable {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// then try Sun JSSESocketFactory
|
// then try Sun JSSESocketFactory
|
||||||
m_factory = new JSSESocketFactory(null);
|
Class c = Class.forName("netscape.ldap.factory.JSSESocketFactory");
|
||||||
|
m_factory = (LDAPSocketFactory) c.newInstance();
|
||||||
}
|
}
|
||||||
catch (Throwable e) {
|
catch (Throwable e) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,3 +49,4 @@
|
||||||
95=More results to return
|
95=More results to return
|
||||||
96=Client detected loop
|
96=Client detected loop
|
||||||
97=Referral hop limit exceeded
|
97=Referral hop limit exceeded
|
||||||
|
112=Cannot start TLS
|
||||||
|
|
|
@ -49,3 +49,4 @@
|
||||||
95=Es stehen noch weitere Ergebnisse zur Verfügung
|
95=Es stehen noch weitere Ergebnisse zur Verfügung
|
||||||
96=Client stellte Schleife fest
|
96=Client stellte Schleife fest
|
||||||
97=Beschränkung für Zwischenschritte bei Referenz überschritten
|
97=Beschränkung für Zwischenschritte bei Referenz überschritten
|
||||||
|
112=TLS kann nicht activiert werden
|
||||||
|
|
|
@ -49,3 +49,4 @@
|
||||||
95=Autres résultats à venir
|
95=Autres résultats à venir
|
||||||
96=Client a détecté la boucle
|
96=Client a détecté la boucle
|
||||||
97=Nombre de rebonds sur référence trop grand
|
97=Nombre de rebonds sur référence trop grand
|
||||||
|
112=Impossible d'activer TLS
|
||||||
|
|
|
@ -49,3 +49,4 @@
|
||||||
95=\u3055\u3089\u306B\u7D50\u679C\u304C\u8FD4\u3055\u308C\u307E\u3059\u3002
|
95=\u3055\u3089\u306B\u7D50\u679C\u304C\u8FD4\u3055\u308C\u307E\u3059\u3002
|
||||||
96=\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u304C\u30EB\u30FC\u30D7\u3092\u691C\u51FA\u3057\u307E\u3057\u305F\u3002
|
96=\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u304C\u30EB\u30FC\u30D7\u3092\u691C\u51FA\u3057\u307E\u3057\u305F\u3002
|
||||||
97=\u30EC\u30D5\u30A7\u30E9\u30EB \u30DB\u30C3\u30D7 \u30EA\u30DF\u30C3\u30C8\u3092\u8D85\u904E\u3057\u307E\u3057\u305F\u3002
|
97=\u30EC\u30D5\u30A7\u30E9\u30EB \u30DB\u30C3\u30D7 \u30EA\u30DF\u30C3\u30C8\u3092\u8D85\u904E\u3057\u307E\u3057\u305F\u3002
|
||||||
|
112=TLS\u3092\u-6a75\u59cb\u3067\u304d\u307e\u305b\u3093\u3002
|
||||||
|
|
|
@ -37,16 +37,23 @@ import netscape.ldap.*;
|
||||||
* @see LDAPSocketFactory
|
* @see LDAPSocketFactory
|
||||||
* @see LDAPConnection#LDAPConnection(netscape.ldap.LDAPSocketFactory)
|
* @see LDAPConnection#LDAPConnection(netscape.ldap.LDAPSocketFactory)
|
||||||
*/
|
*/
|
||||||
public class JSSESocketFactory
|
public class JSSESocketFactory implements LDAPTLSSocketFactory,
|
||||||
implements LDAPSocketFactory, java.io.Serializable {
|
java.io.Serializable {
|
||||||
|
|
||||||
static final long serialVersionUID = 6834205777733266609L;
|
static final long serialVersionUID = 6834205777733266610L;
|
||||||
|
|
||||||
// Optional explicit cipher suites to use
|
// Optional explicit cipher suites to use
|
||||||
private String[] suites;
|
protected String[] suites;
|
||||||
// The socket factory
|
// The socket factory
|
||||||
private SSLSocketFactory factory;
|
protected SSLSocketFactory factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default factory constructor
|
||||||
|
*/
|
||||||
|
public JSSESocketFactory() {
|
||||||
|
this(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory constructor that uses the default JSSE SSLSocketFactory
|
* Factory constructor that uses the default JSSE SSLSocketFactory
|
||||||
*
|
*
|
||||||
|
@ -73,7 +80,7 @@ public class JSSESocketFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an SSL socket
|
* Creates an SSL socket.
|
||||||
*
|
*
|
||||||
* @param host Host name or IP address of SSL server
|
* @param host Host name or IP address of SSL server
|
||||||
* @param port Port numbers of SSL server
|
* @param port Port numbers of SSL server
|
||||||
|
@ -98,16 +105,49 @@ public class JSSESocketFactory
|
||||||
sock.startHandshake();
|
sock.startHandshake();
|
||||||
|
|
||||||
} catch (UnknownHostException e) {
|
} catch (UnknownHostException e) {
|
||||||
throw new LDAPException("SSL connection to " + host +
|
throw new LDAPException("JSSESocketFactory.makeSocket - Unknown host: " + host,
|
||||||
":" + port + ", " + e.getMessage(),
|
|
||||||
LDAPException.CONNECT_ERROR);
|
LDAPException.CONNECT_ERROR);
|
||||||
} catch (IOException f) {
|
} catch (IOException f) {
|
||||||
throw new LDAPException("SSL connection to " + host +
|
throw new LDAPException("JSSESocketFactory.makeSocket " +
|
||||||
":" + port + ", " + f.getMessage(),
|
host + ":" + port + ", " + f.getMessage(),
|
||||||
LDAPException.CONNECT_ERROR);
|
LDAPException.CONNECT_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an SSL socket layered over an existing socket.
|
||||||
|
*
|
||||||
|
* Used for the startTLS implementation (RFC2830).
|
||||||
|
*
|
||||||
|
* @param s An existing non-SSL socket
|
||||||
|
* @return A SSL socket layered over the input socket
|
||||||
|
* @exception LDAPException on error creating socket
|
||||||
|
* @since LDAPJDK 4.17
|
||||||
|
*/
|
||||||
|
public Socket makeSocket(Socket s)
|
||||||
|
throws LDAPException {
|
||||||
|
|
||||||
|
SSLSocket sock = null;
|
||||||
|
String host = s.getInetAddress().getHostName();
|
||||||
|
int port = s.getPort();
|
||||||
|
|
||||||
|
try {
|
||||||
|
sock = (SSLSocket)factory.createSocket(s, host, port, /*autoClose=*/ true);
|
||||||
|
|
||||||
|
if (suites != null) {
|
||||||
|
sock.setEnabledCipherSuites(suites);
|
||||||
|
}
|
||||||
|
|
||||||
|
sock.startHandshake();
|
||||||
|
|
||||||
|
} catch (IOException f) {
|
||||||
|
throw new LDAPException("JSSESocketFactory - start TLS, " + f.getMessage(),
|
||||||
|
LDAPException.TLS_NOT_SUPPORTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,291 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public
|
||||||
|
* License Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS
|
||||||
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
* implied. See the License for the specific language governing
|
||||||
|
* rights and limitations under the License.
|
||||||
|
*
|
||||||
|
* The Original Code is mozilla.org code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is Netscape
|
||||||
|
* Communications Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||||
|
* Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*/
|
||||||
|
package netscape.ldap.factory;
|
||||||
|
|
||||||
|
import java.net.*;
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
import netscape.ldap.*;
|
||||||
|
|
||||||
|
import org.mozilla.jss.ssl.SSLSocket;
|
||||||
|
import org.mozilla.jss.ssl.SSLCertificateApprovalCallback.ValidityStatus;
|
||||||
|
import org.mozilla.jss.ssl.SSLCertificateApprovalCallback;
|
||||||
|
import org.mozilla.jss.crypto.X509Certificate;
|
||||||
|
import org.mozilla.jss.crypto.AlreadyInitializedException;
|
||||||
|
import org.mozilla.jss.CryptoManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an SSL socket connection to a server, using the Netscape/Mozilla
|
||||||
|
* JSS package.
|
||||||
|
* This class implements the <CODE>LDAPSocketFactory</CODE>
|
||||||
|
* interface.
|
||||||
|
* <P>
|
||||||
|
* <B>NOTE: This class is internal to Netscape and is distributed only with
|
||||||
|
* Netscape products</B>.
|
||||||
|
* <P>
|
||||||
|
* By default, the factory uses "secmod.db", "key3.db" and "cert7.db"
|
||||||
|
* databases in the current directory. If you need to override this default
|
||||||
|
* setting, then you should call the static <CODE>initialize</CODE> method
|
||||||
|
* before creating the first instance of <CODE>JSSSocketFactory</CODE>.
|
||||||
|
* <P>
|
||||||
|
* <PRE>
|
||||||
|
* ...
|
||||||
|
* JSSSocketFactory.initialize("../certDir");
|
||||||
|
* LDAPConnection ld = new LDAPConnection(new JSSSocketFactory());
|
||||||
|
* ...
|
||||||
|
* </PRE>
|
||||||
|
* @version 1.1
|
||||||
|
* @see LDAPSocketFactory
|
||||||
|
* @see LDAPConnection#LDAPConnection(netscape.ldap.LDAPSocketFactory)
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class JSSSocketFactory implements Serializable,
|
||||||
|
LDAPTLSSocketFactory,
|
||||||
|
SSLCertificateApprovalCallback
|
||||||
|
{
|
||||||
|
|
||||||
|
static final long serialVersionUID = -6926469178017736903L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default security module database path "secmod.db".
|
||||||
|
*/
|
||||||
|
public static final String defaultModDB = "secmod.db";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default key database path "key3.db".
|
||||||
|
*/
|
||||||
|
public static final String defaultKeyDB = "key3.db";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default certificate database path "cert7.db".
|
||||||
|
*/
|
||||||
|
public static final String defaultCertDB = "cert7.db";
|
||||||
|
|
||||||
|
private static String moddb;
|
||||||
|
private static String keydb;
|
||||||
|
private static String certdb;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new <CODE>JSSSocketFactory</CODE>.
|
||||||
|
* <CODE>CryptoManager.initialize(certdbDir)</CODE> or
|
||||||
|
* JSSSocketFactory.initialize(certdbDir)</CODE> must be called once in the
|
||||||
|
* application before using the object.
|
||||||
|
*
|
||||||
|
* @exception LDAPException on initialization error
|
||||||
|
* @see netscape.ldap.factory.JSSSocketFactory#JSSSocketFactory(java.lang.String)
|
||||||
|
*/
|
||||||
|
public JSSSocketFactory() throws LDAPException{
|
||||||
|
initialize(".");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new <CODE>JSSSocketFactory</CODE>, initializing the
|
||||||
|
* JSS security system if it has not already been initialized
|
||||||
|
*
|
||||||
|
* @param certdbDir The full path, relative or absolute, of the certificate
|
||||||
|
* database directory
|
||||||
|
* @exception LDAPException on initialization error
|
||||||
|
*/
|
||||||
|
public JSSSocketFactory( String certdbDir ) throws LDAPException{
|
||||||
|
initialize( certdbDir );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the JSS security subsystem.
|
||||||
|
* <P>
|
||||||
|
* This method allows you to override the current directory as the
|
||||||
|
* default certificate database directory. The directory is expected
|
||||||
|
* to contain <CODE>secmod.db</CODE>, <CODE>key3.db</CODE> and
|
||||||
|
* <CODE>cert7.db</CODE> files as the security module database, key database
|
||||||
|
* and certificate database respectively.
|
||||||
|
* <P>
|
||||||
|
* The method may be called only once, before the first instance of
|
||||||
|
* <CODE>JSSSocketFactory</CODE> is created. When creating the first
|
||||||
|
* instance, the constructor will automatically initialize the JSS
|
||||||
|
* security subsystem using the defaults, unless it is already initialized.
|
||||||
|
* <P>
|
||||||
|
* @param certdbDir The full path, relative or absolute, of the certificate
|
||||||
|
* database directory.
|
||||||
|
* @exception LDAPException on initialization error
|
||||||
|
* @see netscape.ldap.factory.JSSSocketFactory#JSSSocketFactory(String)
|
||||||
|
*/
|
||||||
|
public static void initialize( String certdbDir ) throws LDAPException {
|
||||||
|
moddb = certdbDir + File.separator + JSSSocketFactory.defaultModDB;
|
||||||
|
keydb = certdbDir + File.separator + JSSSocketFactory.defaultKeyDB;
|
||||||
|
certdb = certdbDir + File.separator + JSSSocketFactory.defaultCertDB;
|
||||||
|
try {
|
||||||
|
CryptoManager.initialize( certdbDir );
|
||||||
|
} catch (AlreadyInitializedException e) {
|
||||||
|
// This is ok
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new LDAPException("Failed to initialize JSSSocketFactory: "
|
||||||
|
+ e.getMessage(), LDAPException.OTHER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the JSS security subsystem.
|
||||||
|
* <P>
|
||||||
|
* This method allows you to override the default name and location of
|
||||||
|
* the security module database, key database and certificate databases.
|
||||||
|
* <P>
|
||||||
|
* The method may be called only once, before the first instance of
|
||||||
|
* <CODE>JSSSocketFactory</CODE> is created. When creating the first
|
||||||
|
* instance, the constructor will automatically initialize the JSS
|
||||||
|
* security subsystem using the defaults, unless it is already initialized.
|
||||||
|
* <P>
|
||||||
|
* @param moddb The full path, relative or absolute, of the security
|
||||||
|
* module database.
|
||||||
|
* @param keydb The full path, relative or absolute, of the key database.
|
||||||
|
* @param keydb The full path, relative or absolute, of the certificate
|
||||||
|
* database.
|
||||||
|
* @see netscape.ldap.factory.JSSSocketFactory#JSSSocketFactory
|
||||||
|
* @see netscape.ldap.factory.JSSSocketFactory#initialize(java.lang.String)
|
||||||
|
* @exception LDAPException on initialization error
|
||||||
|
* @deprecated Please call <CODE>JSSSocketFactory(String certDir)</CODE> instead
|
||||||
|
*/
|
||||||
|
public static void initialize( String moddb, String keydb, String certdb )
|
||||||
|
throws LDAPException {
|
||||||
|
JSSSocketFactory.moddb = moddb;
|
||||||
|
JSSSocketFactory.keydb = keydb;
|
||||||
|
JSSSocketFactory.certdb = certdb;
|
||||||
|
int ind = certdb.lastIndexOf( File.separator );
|
||||||
|
String certdbDir = ( ind == 0 ) ? File.separator :
|
||||||
|
( ind > 0 ) ? certdb.substring( 0, ind ) : ".";
|
||||||
|
initialize( certdbDir );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the full path of the security module
|
||||||
|
* database
|
||||||
|
*
|
||||||
|
* @return The full path, relative or absolute, of the security module database
|
||||||
|
*/
|
||||||
|
public static String getModDB() {
|
||||||
|
return moddb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the full path of the key database
|
||||||
|
*
|
||||||
|
* @return The full path, relative or absolute, of the key database
|
||||||
|
*/
|
||||||
|
public static String getKeyDB() {
|
||||||
|
return keydb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the full path of the certificate database
|
||||||
|
*
|
||||||
|
* @return The full path, relative or absolute, of the certificate database
|
||||||
|
*/
|
||||||
|
public static String getCertDB() {
|
||||||
|
return certdb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an SSL socket
|
||||||
|
*
|
||||||
|
* @param host Host name or IP address of SSL server
|
||||||
|
* @param port Port numbers of SSL server
|
||||||
|
* @return A socket for an encrypted session
|
||||||
|
* @exception LDAPException on error creating socket
|
||||||
|
*/
|
||||||
|
public Socket makeSocket( String host, int port ) throws LDAPException {
|
||||||
|
SSLSocket socket = null;
|
||||||
|
try {
|
||||||
|
|
||||||
|
socket = new SSLSocket( host, // address
|
||||||
|
port, // port
|
||||||
|
null, // localAddress
|
||||||
|
0, // localPort
|
||||||
|
this, // certApprovalCallback
|
||||||
|
null // clientCertSelectionCallback
|
||||||
|
);
|
||||||
|
|
||||||
|
socket.forceHandshake();
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (UnknownHostException e) {
|
||||||
|
throw new LDAPException("JSSSocketFactory.makeSocket - Unknown host: " + host,
|
||||||
|
LDAPException.CONNECT_ERROR);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new LDAPException("JSSSocketFactory.makeSocket " +
|
||||||
|
host + ":" + port + ", " + e.getMessage(),
|
||||||
|
LDAPException.CONNECT_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default implementation of the SSLCertificateApprovalCallback
|
||||||
|
* interface.
|
||||||
|
* <P>
|
||||||
|
* This default implementation always returns true. If you need to
|
||||||
|
* verify the server certificate validity, then you should override
|
||||||
|
* this method.
|
||||||
|
* <P>
|
||||||
|
* @param serverCert X509 Certificate
|
||||||
|
* @param status The validity of the server certificate
|
||||||
|
* @return <CODE>true</CODE>, by default we trust the certificate
|
||||||
|
*/
|
||||||
|
public boolean approve(X509Certificate serverCert,
|
||||||
|
ValidityStatus status) {
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an SSL socket layered over an existing socket.
|
||||||
|
*
|
||||||
|
* Used for the startTLS implementation (RFC2830).
|
||||||
|
*
|
||||||
|
* @param s An existing non-SSL socket
|
||||||
|
* @return A SSL socket layered over the input socket
|
||||||
|
* @exception LDAPException on error creating socket
|
||||||
|
* @since LDAPJDK 4.17
|
||||||
|
*/
|
||||||
|
public Socket makeSocket(Socket s) throws LDAPException {
|
||||||
|
SSLSocket socket = null;
|
||||||
|
String host = s.getInetAddress().getHostName();
|
||||||
|
int port = s.getPort();
|
||||||
|
try {
|
||||||
|
socket = new SSLSocket( s,
|
||||||
|
host,
|
||||||
|
this, // certApprovalCallback
|
||||||
|
null // clientCertSelectionCallback
|
||||||
|
);
|
||||||
|
|
||||||
|
socket.forceHandshake();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new LDAPException("JSSSocketFactory - start TLS, " + e.getMessage(),
|
||||||
|
LDAPException.TLS_NOT_SUPPORTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
return socket;
|
||||||
|
}
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче