This commit is contained in:
miodrag%netscape.com 2002-12-03 00:38:20 +00:00
Родитель 939b8670f9
Коммит aa729f7d11
19 изменённых файлов: 1650 добавлений и 1002 удалений

Просмотреть файл

@ -168,9 +168,9 @@ public interface LDAPAsynchronousConnection {
/**
* Makes a single change to an existing entry in the directory (for
* example, changes the value of an attribute, adds a new attribute
* value, or removes an existing attribute value).<BR>
* Makes a single change to an existing entry in the directory.
* For example, changes the value of an attribute, adds a new attribute
* value, or removes an existing attribute value.<BR>
* The LDAPModification object specifies both the change to be made and
* the LDAPAttribute value to be changed.
*
@ -190,9 +190,9 @@ public interface LDAPAsynchronousConnection {
throws LDAPException;
/**
* Makes a single change to an existing entry in the directory (for
* example, changes the value of an attribute, adds a new attribute
* value, or removes an existing attribute value).<BR>
* Makes a single change to an existing entry in the directory.
* For example, changes the value of an attribute, adds a new attribute
* value, or removes an existing attribute value.<BR>
* The LDAPModification object specifies both the change to be made and
* the LDAPAttribute value to be changed.
*
@ -215,9 +215,9 @@ public interface LDAPAsynchronousConnection {
throws LDAPException;
/**
* Makes a set of changes to an existing entry in the directory (for
* example, changes attribute values, adds new attribute values, or
* removes existing attribute values).
* Makes a set of changes to an existing entry in the directory.
* For example, changes attribute values, adds new attribute values, or
* removes existing attribute values.
* <P>
* @param dn distinguished name of the entry to modify
* @param mods a set of modifications to make to the entry
@ -235,9 +235,9 @@ public interface LDAPAsynchronousConnection {
throws LDAPException;
/**
* Makes a set of changes to an existing entry in the directory (for
* example, changes attribute values, adds new attribute values, or
* removes existing attribute values).
* Makes a set of changes to an existing entry in the directory.
* For example, changes attribute values, adds new attribute values, or
* removes existing attribute values.
*
* @param dn distinguished name of the entry to modify
* @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
* is passed to the LDAPConnThread. The LDAPConnThread must call
* 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.
*/
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
*/
@ -65,28 +65,32 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
* Representation for a server in the server list.
*/
class ServerEntry {
String host;
int port;
LDAPUrl url;
int connSetupStatus;
Thread connSetupThread;
ServerEntry(String host, int port, int status) {
this.host = host;
this.port = port;
ServerEntry(LDAPUrl url, int status) {
this.url = url;
connSetupStatus = status;
connSetupThread = null;
}
}
public String toString() {
return "{" +host+":"+port + " status="+connSetupStatus+"}";
return "{" + url + " status="+connSetupStatus+"}";
}
}
/**
* Socket to the connected server
*/
private Socket m_socket = null;
/**
* Original, underlying socket to the server, see layerSocket()
*/
private Socket m_origSocket = null;
/**
* Last exception occured during connection setup
*/
@ -128,25 +132,50 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
*/
private transient int m_attemptCnt = 0;
/**
* Connection IDs for ldap trace messages
*/
private static int m_nextId;
private int m_id;
/**
* Constructor
* @param host list of host names to which to connect
* @param port list of port numbers corresponding to the host list
* @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];
boolean secure = (factory != null);
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_id = m_nextId++;
}
/**
@ -204,7 +233,7 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
th.interrupt();
cleanup();
throw new LDAPException(
"connect timeout, " + getServerList() + " might be unreachable",
"Connect timeout, " + getServerList() + " might be unreachable",
LDAPException.CONNECT_ERROR);
}
@ -213,12 +242,13 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
}
throw new LDAPException(
"failed to connect to server " + getServerList(),
"Failed to connect to server " + getServerList(),
LDAPException.CONNECT_ERROR);
}
private void reset() {
m_socket = null;
m_origSocket = null;
m_connException = null;
m_attemptCnt = 0;
@ -231,9 +261,9 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
StringBuffer sb = new StringBuffer();
for (int i=0; i < m_dsList.length; i++) {
sb.append(i==0 ? "" : " ");
sb.append(m_dsList[i].host);
sb.append(m_dsList[i].url.getHost());
sb.append(":");
sb.append(m_dsList[i].port);
sb.append(m_dsList[i].url.getPort());
}
return sb.toString();
}
@ -268,9 +298,25 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
newDsList[j] = m_dsList[m_dsIdx];
m_dsList = newDsList;
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
* put it at top of the server list for the next connect attempt.
*/
void disconnect() {
void closeConnection() {
if (m_socket != null) {
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() {
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() {
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() {
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() {
@ -363,8 +448,7 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
//Create a Thread to execute connectSetver()
final int dsIdx = i;
String threadName = "ConnSetupMgr " +
m_dsList[dsIdx].host + ":" + m_dsList[dsIdx].port;
String threadName = "ConnSetupMgr " + m_dsList[dsIdx].url;
Thread t = new Thread(new Runnable() {
public void run() {
connectServer(dsIdx);
@ -407,20 +491,29 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
Thread currThread = Thread.currentThread();
Socket sock = null;
LDAPException conex = null;
try {
/* If we are to create a socket ourselves, make sure it has
sufficient privileges to connect to the desired host */
if (m_factory == null) {
sock = new Socket (entry.host, entry.port);
//s.setSoLinger( false, -1 );
if (!entry.url.isSecure()) {
sock = new Socket (entry.url.getHost(), entry.url.getPort());
} 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) {
conex = new LDAPException("failed to connect to server "
+ entry.host+":"+entry.port, LDAPException.CONNECT_ERROR);
+ entry.url, LDAPException.CONNECT_ERROR);
}
catch (LDAPException e) {
conex = e;
@ -514,29 +607,5 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
str += m_dsList[i]+ " ";
}
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
* LDAPConnThread (a thread).
*/
class LDAPConnThread extends Thread {
class LDAPConnThread implements Runnable {
/**
* Constants
@ -61,21 +61,25 @@ class LDAPConnThread extends Thread {
* Internal variables
*/
transient private static int m_highMsgId;
transient private InputStream m_serverInput;
transient private OutputStream m_serverOutput;
transient private InputStream m_serverInput, m_origServerInput;
transient private OutputStream m_serverOutput, m_origServerOutput;
transient private Hashtable m_requests;
transient private Hashtable m_messages = null;
transient private Vector m_registered;
transient private boolean m_disconnected = false;
transient private Vector m_registered;
transient private LDAPCache m_cache = null;
transient private boolean m_doRun = true;
private Socket m_socket = null;
transient private Thread m_thread = null;
transient Object m_sendRequestLock = new Object();
transient LDAPConnSetupMgr m_connMgr = null;
transient Object m_traceOutput = null;
transient private Object m_sendRequestLock = new Object();
transient private LDAPConnSetupMgr m_connMgr = null;
transient private Object m_traceOutput = null;
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
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
* LDAP server.
* @param host LDAP host name
* @param port LDAP port number
* @param factory LDAP socket factory
* @param connMgr the connection setup manager
* @param cache cache object or null
* @param traceOutput trace object or null
*/
public LDAPConnThread(LDAPConnSetupMgr connMgr, LDAPCache cache, Object traceOutput)
throws LDAPException {
super("LDAPConnThread " + connMgr.getHost() +":"+ connMgr.getPort());
public LDAPConnThread(LDAPConnSetupMgr connMgr, LDAPCache cache, Object traceOutput) {
m_requests = new Hashtable ();
m_registered = new Vector ();
m_connMgr = connMgr;
m_socket = connMgr.getSocket();
setCache( cache );
setTraceOutput(traceOutput);
setDaemon(true);
}
synchronized void connect(LDAPConnection ldc) throws LDAPException{
if (m_thread != null) {
return;
}
try {
m_serverInput = new BufferedInputStream (m_socket.getInputStream());
m_serverOutput = new BufferedOutputStream (m_socket.getOutputStream());
m_connMgr.openConnection();
m_serverInput = new BufferedInputStream (m_connMgr.getSocket().getInputStream());
m_serverOutput = new BufferedOutputStream(m_connMgr.getSocket().getOutputStream());
register(ldc);
} 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 " +
m_connMgr.getHost(), LDAPException.CONNECT_ERROR );
}
if (traceOutput != null) {
StringBuffer sb = new StringBuffer(" connected to ");
sb.append(m_connMgr.getLDAPUrl());
m_id = m_nextId++;
String url = m_connMgr.getLDAPUrl().getServerUrl();
if (m_traceOutput != null) {
StringBuffer sb = new StringBuffer(" Connected to ");
sb.append(url);
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() {
@ -142,6 +181,10 @@ class LDAPConnThread extends Thread {
m_serverOutput = os;
}
int getRequestCount() {
return m_requests.size();
}
void setTraceOutput(Object traceOutput) {
synchronized (m_sendRequestLock) {
if (traceOutput == null) {
@ -161,7 +204,7 @@ class LDAPConnThread extends Thread {
String timeStamp = m_timeFormat.format(new Date());
StringBuffer sb = new StringBuffer(timeStamp);
sb.append(" ldc=");
sb.append(m_connMgr.getID());
sb.append(m_id);
synchronized( m_sendRequestLock ) {
if (m_traceOutput instanceof PrintWriter) {
@ -207,38 +250,71 @@ class LDAPConnThread extends Thread {
void sendRequest (LDAPConnection conn, JDAPProtocolOp request,
LDAPMessageQueue toNotify, LDAPConstraints cons)
throws LDAPException {
if (!m_doRun) {
throw new LDAPException ( "not connected to a server",
LDAPException.SERVER_DOWN );
if (m_thread == null) {
throw new LDAPException ( "Not connected to a server",
LDAPException.SERVER_DOWN );
}
LDAPMessage msg =
new LDAPMessage(allocateId(), request, cons.getServerControls());
if ( toNotify != null ) {
if (!(request instanceof JDAPAbandonRequest ||
request instanceof JDAPUnbindRequest)) {
/* 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
request */
resultRetrieved();
}
/* Only worry about toNotify if we expect a response... */
m_requests.put (new Integer (msg.getMessageID()), toNotify);
/* Notify the backlog checker that there may be another outstanding
request */
resultRetrieved();
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 ) {
try {
if (m_traceOutput != null) {
logTraceMessage(msg.toTraceString());
}
msg.write (m_serverOutput);
m_serverOutput.flush ();
} catch (IOException e) {
networkError(e);
m_serverOutput.flush();
return true;
}
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.
* @param conn LDAP connection
@ -252,8 +328,8 @@ class LDAPConnThread extends Thread {
return m_registered.size();
}
boolean isRunning() {
return m_doRun;
boolean isConnected() {
return m_thread != null;
}
/**
@ -261,111 +337,118 @@ class LDAPConnThread extends Thread {
* is deregistered. Then, this thread should be killed.
* @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);
if (m_registered.size() == 0) {
try {
// No more request processing
Thread t = m_thread;
m_thread = null;
if (!m_disconnected) {
LDAPSearchConstraints cons = conn.getSearchConstraints();
sendRequest (null, new JDAPUnbindRequest (), null, cons);
}
try {
// Notify the server
sendUnbindRequest(conn.getConstraints().getServerControls());
// must be set after the call to sendRequest
m_doRun =false;
if ( m_thread != null && m_thread != Thread.currentThread()) {
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) {
}
// interrupt the thread
try {
t.interrupt();
wait(500);
}
catch (InterruptedException ignore) {}
} catch (Exception e) {
LDAPConnection.printDebug(e.toString());
}
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() {
if (!m_disconnected) {
private void cleanUp(LDAPException ex) {
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 {
m_serverOutput.close ();
m_origServerInput.close ();
} catch (Exception e) {
} finally {
m_serverOutput = null;
m_origServerInput = null;
}
}
if (m_origServerOutput != null) {
try {
m_serverInput.close ();
m_origServerOutput.close ();
} catch (Exception e) {
} finally {
m_serverInput = null;
m_origServerOutput = null;
}
}
try {
m_socket.close ();
} catch (Exception e) {
} finally {
m_socket = null;
}
m_disconnected = true;
// Notify the Connection Manager
if (ex != null) {
// the connection is lost
m_connMgr.invalidateConnection();
}
else {
// the connection is closed
m_connMgr.closeConnection();
}
/**
* Notify the Connection Setup Manager that the connection was
* terminated by the user
*/
m_connMgr.disconnect();
/**
* Cancel all outstanding requests
*/
if (m_requests != null) {
Enumeration requests = m_requests.elements();
while (requests.hasMoreElements()) {
LDAPMessageQueue listener =
(LDAPMessageQueue)requests.nextElement();
// Set the status for all outstanding requests
Enumeration requests = m_requests.elements();
while (requests.hasMoreElements()) {
try {
LDAPMessageQueue listener =
(LDAPMessageQueue)requests.nextElement();
if (ex != null) {
listener.setException(this, ex);
}
else {
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();
m_requests.clear();
m_messages = null;
m_cache = null;
catch (Exception ignore) {}
}
m_requests.clear();
if (m_messages != null) {
m_messages.clear();
}
m_bound = false;
}
/**
@ -383,8 +466,8 @@ class LDAPConnThread extends Thread {
while( listeners.hasMoreElements() ) {
LDAPMessageQueue l = (LDAPMessageQueue)listeners.nextElement();
// If there are any threads waiting for a regular response
// message, we have to go read the next incoming message
// If there are clients waiting for a regular response
// message, skip backlog checking
if ( !(l instanceof LDAPSearchListener) ) {
return;
}
@ -437,29 +520,21 @@ class LDAPConnThread extends Thread {
* Reads from the LDAP server input stream for incoming LDAP messages.
*/
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;
JDAPBERTagDecoder decoder = new JDAPBERTagDecoder();
int[] nread = new int[1];
while (m_doRun) {
yield();
int[] nread = new int[1];
nread[0] = 0;
while (Thread.currentThread() == m_thread) {
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) {
m_backlogCheckCounter = BACKLOG_CHKCNT;
checkBacklog();
}
nread[0] = 0;
BERElement element = BERElement.getElement(decoder,
m_serverInput,
nread);
@ -473,17 +548,14 @@ class LDAPConnThread extends Thread {
// entry, thereby avoiding serialization of the entry stored in the
// cache
processResponse (msg, nread[0]);
Thread.yield();
} catch (Exception e) {
if (m_doRun) {
if (Thread.currentThread() == m_thread) {
networkError(e);
}
else {
// interrupted from deregister()
synchronized (this) {
m_thread = null;
notifyAll();
}
resultRetrieved();
}
}
}
@ -502,24 +574,6 @@ class LDAPConnThread extends Thread {
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)) {
cacheSearchResult((LDAPSearchListener)l, msg, size);
}
@ -530,10 +584,42 @@ class LDAPConnThread extends Thread {
m_requests.remove (messageID);
if (m_requests.size() == 0) {
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
* 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.
*/
void abandon (int id ) {
void abandon (int id, LDAPControl[] ctrls) {
if (!m_doRun) {
if (m_thread == null) {
return;
}
@ -647,6 +734,8 @@ class LDAPConnThread extends Thread {
l.removeRequest(id);
}
resultRetrieved(); // If LDAPConnThread is blocked in checkBacklog()
sendAbandonRequest(id, ctrls);
}
/**
@ -657,7 +746,7 @@ class LDAPConnThread extends Thread {
*/
LDAPMessageQueue changeListener (int id, LDAPMessageQueue toNotify) {
if (!m_doRun) {
if (m_thread == null) {
toNotify.setException(this, new LDAPException("Server or network error",
LDAPException.SERVER_DOWN));
return null;
@ -672,26 +761,11 @@ class LDAPConnThread extends Thread {
*/
private synchronized void networkError (Exception e) {
m_doRun =false;
// 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());
if (m_thread == null) {
return;
}
cleanUp();
m_thread = null; // No more request processing
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.
* @returns a copy of an existing set of constraints
* @return a copy of an existing set of constraints
*/
public Object clone() {
LDAPConstraints o = new LDAPConstraints();
try {
LDAPConstraints o = (LDAPConstraints) super.clone();
o.m_time_limit = this.m_time_limit;
o.referrals = this.referrals;
o.m_bind_proc = this.m_bind_proc;
o.m_rebind_proc = this.m_rebind_proc;
o.m_hop_limit = this.m_hop_limit;
if ( (this.m_clientControls != null) &&
(this.m_clientControls.length > 0) ) {
o.m_clientControls = new LDAPControl[this.m_clientControls.length];
for( int i = 0; i < this.m_clientControls.length; i++ )
o.m_clientControls[i] =
(LDAPControl)this.m_clientControls[i].clone();
if ( (this.m_clientControls != null) &&
(this.m_clientControls.length > 0) ) {
o.m_clientControls = new LDAPControl[this.m_clientControls.length];
for( int i = 0; i < this.m_clientControls.length; i++ )
o.m_clientControls[i] =
(LDAPControl)this.m_clientControls[i].clone();
}
if ( (this.m_serverControls != null) &&
(this.m_serverControls.length > 0) ) {
o.m_serverControls = new LDAPControl[this.m_serverControls.length];
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) &&
(this.m_serverControls.length > 0) ) {
o.m_serverControls = new LDAPControl[this.m_serverControls.length];
for( int i = 0; i < this.m_serverControls.length; i++ )
o.m_serverControls[i] =
(LDAPControl)this.m_serverControls[i].clone();
catch (CloneNotSupportedException ex) {
// shold never happen, the class is Cloneable
return null;
}
return o;
}
}

Просмотреть файл

@ -123,6 +123,7 @@ import java.io.*;
* 95 <A HREF="#MORE_RESULTS_TO_RETURN">MORE_RESULTS_TO_RETURN</A>
* 96 <A HREF="#CLIENT_LOOP">CLIENT_LOOP</A>
* 97 <A HREF="#REFERRAL_LIMIT_EXCEEDED">REFERRAL_LIMIT_EXCEEDED</A>
* 112 <A HREF="#TLS_NOT_SUPPORTED">TLS_NOT_SUPPORTED</A> (LDAP v3)
* </PRE>
* <P>
*
@ -132,7 +133,7 @@ import java.io.*;
public class LDAPException extends java.lang.Exception
implements java.io.Serializable {
static final long serialVersionUID = -9215007872184847924L;
static final long serialVersionUID = -9215007872184847925L;
/**
* (0) The operation completed successfully.
@ -556,11 +557,21 @@ public class LDAPException extends java.lang.Exception
*/
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
*/
private int resultCode = -1;
private String errorMessage = null;
private String extraMessage = null;
private String matchedDN = null;
private Locale m_locale = Locale.getDefault();
private static Hashtable cacheResource = new Hashtable();
@ -733,17 +744,32 @@ public class LDAPException extends java.lang.Exception
public String getLDAPErrorMessage () {
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
* 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>
* <LI><CODE>NO_SUCH_OBJECT</CODE>
* <LI><CODE>ALIAS_PROBLEM</CODE>
* <LI><CODE>INVALID_DN_SYNTAX</CODE>
* <LI><CODE>ALIAS_DEREFERENCING_PROBLEM</CODE>
* </UL>
* </PRE>
* 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 be found, the matched DN is
@ -791,14 +817,19 @@ public class LDAPException extends java.lang.Exception
*/
public String toString() {
String str = super.toString() + " (" + resultCode + ")" ;
if ( (errorMessage != null) && (errorMessage.length() > 0) )
if ( (errorMessage != null) && (errorMessage.length() > 0) ) {
str += "; " + errorMessage;
if ( (matchedDN != null) && (matchedDN.length() > 0) )
}
if ( (matchedDN != null) && (matchedDN.length() > 0) ) {
str += "; matchedDN = " + matchedDN;
String errorStr = null;
if (((errorStr = errorCodeToString(m_locale)) != null) &&
(errorStr.length() > 0))
str += "; " + errorStr;
}
String errorStr = errorCodeToString(m_locale);
if ((errorStr != null) && (errorStr.length() > 0)) {
str += "; " + errorStr;
}
if (extraMessage != null) {
str += "; " + extraMessage;
}
return str;
}

Просмотреть файл

@ -35,7 +35,7 @@ import java.util.Vector;
*/
class LDAPMessageQueue implements java.io.Serializable {
static final long serialVersionUID = -7163312406176592277L;
static final long serialVersionUID = -7163312406176592278L;
/**
* Request entry encapsulates request parameters
@ -88,6 +88,27 @@ class LDAPMessageQueue implements java.io.Serializable {
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
* 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
if (isAsynchOp() && msg.getType() == msg.BIND_RESPONSE) {
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
* an external (file-based) certificate database.
* Call this method before you call <CODE>makeSocket</CODE>.

Просмотреть файл

@ -225,7 +225,7 @@ public class LDAPSaslBind implements LDAPBind, java.io.Serializable {
_saslClient,
className, "getOutputStream", args, argNames);
ldc.setOutputStream(os);
ldc.markConnAsBound();
ldc.setBound(true);
} catch (LDAPException e) {
throw e;
} catch (Exception e) {

Просмотреть файл

@ -34,11 +34,25 @@ package netscape.ldap;
public class LDAPSearchConstraints extends LDAPConstraints
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 maxRes;
private int batch;
private int serverTimeLimit;
private int maxBacklog = 100;
private int referralErrors = REFERRAL_ERROR_CONTINUE;
/**
* 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
* sequence when attempting to resolve a request
* @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(java.lang.String, int, java.lang.String, java.lang.String[], boolean, netscape.ldap.LDAPSearchConstraints)
* @see netscape.ldap.LDAPConnection#search(netscape.ldap.LDAPUrl,
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,
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
* sequence when attempting to resolve a request
* @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(java.lang.String, int, java.lang.String, java.lang.String[], boolean, netscape.ldap.LDAPSearchConstraints)
* @see netscape.ldap.LDAPConnection#search(netscape.ldap.LDAPUrl,
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,
int dereference,
@ -171,8 +189,10 @@ public class LDAPSearchConstraints extends LDAPConstraints
* @param hop_limit maximum number of referrals to follow in a
* sequence when attempting to resolve a request
* @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(java.lang.String, int, java.lang.String, java.lang.String[], boolean, netscape.ldap.LDAPSearchConstraints)
* @see netscape.ldap.LDAPConnection#search(netscape.ldap.LDAPUrl,
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,
int dereference,
@ -296,51 +316,101 @@ public class LDAPSearchConstraints extends LDAPConstraints
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.
* @return a copy of an existing set of search constraints.
*/
public Object clone() {
LDAPSearchConstraints o = new LDAPSearchConstraints();
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);
}
LDAPSearchConstraints o = (LDAPSearchConstraints) super.clone();
return o;
}
@ -356,7 +426,8 @@ public class LDAPSearchConstraints extends LDAPConstraints
sb.append("server time limit " + serverTimeLimit + ", ");
sb.append("aliases " + deref + ", ");
sb.append("batch size " + batch + ", ");
sb.append("max backlog " + maxBacklog);
sb.append("max backlog " + maxBacklog + ", ");
sb.append("referralErrors " + referralErrors);
sb.append('}');
return sb.toString();

Просмотреть файл

@ -549,7 +549,7 @@ public class LDAPSearchResults implements Enumeration, java.io.Serializable {
currBase, currScope, currFilter,
currAttrs, currAttrsOnly);
} catch (LDAPException e) {
System.err.println("LDAPSearchResults.fetchResult: "+e);
add(e);
} finally {
currConn.releaseSearchListener(resultSource);
}
@ -567,7 +567,7 @@ public class LDAPSearchResults implements Enumeration, java.io.Serializable {
currConn.checkSearchMsg(this, msg, currCons,
currBase, currScope, currFilter, currAttrs, currAttrsOnly);
} 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.io.*;
import java.net.MalformedURLException;
import netscape.ldap.factory.*;
/**
* 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 {
static final long serialVersionUID = -3245440798565713640L;
static final long serialVersionUID = -3245440798565713641L;
public static String defaultFilter = "(objectClass=*)";
private String m_hostName;
@ -371,7 +370,7 @@ public class LDAPUrl implements java.io.Serializable {
} else
m_attributes = null;
StringBuffer url = new StringBuffer (secure ? "LDAPS://" :"LDAP://");
StringBuffer url = new StringBuffer (secure ? "ldaps://" :"ldap://");
if (host != null) {
url.append (host);
@ -444,6 +443,15 @@ public class LDAPUrl implements java.io.Serializable {
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
* for "every attribute"
@ -545,10 +553,10 @@ public class LDAPUrl implements java.io.Serializable {
if (m_factory == null) {
// No factory explicity set, try to determine
// No factory explicitly set, try to determine
// the default one.
try {
// First try iPlanet JSSSocketFactory
// First try Mozilla JSSSocketFactory
Class c = Class.forName("netscape.ldap.factory.JSSSocketFactory");
m_factory = (LDAPSocketFactory) c.newInstance();
}
@ -561,7 +569,8 @@ public class LDAPUrl implements java.io.Serializable {
try {
// 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) {
}

Просмотреть файл

@ -49,3 +49,4 @@
95=More results to return
96=Client detected loop
97=Referral hop limit exceeded
112=Cannot start TLS

Просмотреть файл

@ -49,3 +49,4 @@
95=Es stehen noch weitere Ergebnisse zur Verfügung
96=Client stellte Schleife fest
97=Beschränkung für Zwischenschritte bei Referenz überschritten
112=TLS kann nicht activiert werden

Просмотреть файл

@ -49,3 +49,4 @@
95=Autres résultats à venir
96=Client a détecté la boucle
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
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
112=TLS\u3092\u-6a75\u59cb\u3067\u304d\u307e\u305b\u3093\u3002

Просмотреть файл

@ -37,16 +37,23 @@ import netscape.ldap.*;
* @see LDAPSocketFactory
* @see LDAPConnection#LDAPConnection(netscape.ldap.LDAPSocketFactory)
*/
public class JSSESocketFactory
implements LDAPSocketFactory, java.io.Serializable {
public class JSSESocketFactory implements LDAPTLSSocketFactory,
java.io.Serializable {
static final long serialVersionUID = 6834205777733266609L;
static final long serialVersionUID = 6834205777733266610L;
// Optional explicit cipher suites to use
private String[] suites;
protected String[] suites;
// 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
*
@ -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 port Port numbers of SSL server
@ -98,16 +105,49 @@ public class JSSESocketFactory
sock.startHandshake();
} catch (UnknownHostException e) {
throw new LDAPException("SSL connection to " + host +
":" + port + ", " + e.getMessage(),
throw new LDAPException("JSSESocketFactory.makeSocket - Unknown host: " + host,
LDAPException.CONNECT_ERROR);
} catch (IOException f) {
throw new LDAPException("SSL connection to " + host +
":" + port + ", " + f.getMessage(),
throw new LDAPException("JSSESocketFactory.makeSocket " +
host + ":" + port + ", " + f.getMessage(),
LDAPException.CONNECT_ERROR);
}
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;
}
}