From 22094368c2865dcfb6daf8366425212b721a4657 Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Thu, 05 Feb 2009 17:42:14 +0000
Subject: [PATCH] Merge ASN1 branch to trunk
---
opends/src/server/org/opends/server/protocols/internal/InternalLDAPOutputStream.java | 533 ++++++++++++++++++----------------------------------------
1 files changed, 169 insertions(+), 364 deletions(-)
diff --git a/opends/src/server/org/opends/server/protocols/internal/InternalLDAPOutputStream.java b/opends/src/server/org/opends/server/protocols/internal/InternalLDAPOutputStream.java
index 8eb9a94..860c925 100644
--- a/opends/src/server/org/opends/server/protocols/internal/InternalLDAPOutputStream.java
+++ b/opends/src/server/org/opends/server/protocols/internal/InternalLDAPOutputStream.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Copyright 2008 Sun Microsystems, Inc.
+ * Copyright 2009 Sun Microsystems, Inc.
*/
package org.opends.server.protocols.internal;
@@ -30,16 +30,15 @@
import java.io.OutputStream;
import java.io.IOException;
-import java.util.ArrayList;
+import java.io.InputStream;
+import java.util.List;
import org.opends.messages.Message;
import org.opends.server.core.*;
-import org.opends.server.protocols.asn1.ASN1Element;
+import org.opends.server.protocols.asn1.ASN1;
+import org.opends.server.protocols.asn1.ASN1Reader;
import org.opends.server.protocols.ldap.*;
-import org.opends.server.types.AuthenticationType;
-import org.opends.server.types.Control;
-import org.opends.server.types.SearchResultEntry;
-import org.opends.server.types.SearchResultReference;
+import org.opends.server.types.*;
import static org.opends.messages.ProtocolMessages.*;
import static org.opends.server.protocols.ldap.LDAPConstants.*;
@@ -69,28 +68,126 @@
// Indicates whether this stream has been closed.
private boolean closed;
- // Indicates whether the type of the ASN.1 element is needed.
- private boolean needType;
-
- // The BER type for the ASN.1 element being read.
- private byte elementType;
-
- // The data for the ASN.1 element being read.
- private byte[] elementBytes;
-
- // The length bytes for the ASN.1 element being read.
- private byte[] lengthBytes;
-
- // The offset in the appropriate array at which we should begin
- // writing data. This could either refer to the length or data
- // array, depending on the stage of the encoding process.
- private int arrayOffset;
+ private final ASN1Reader reader;
// The internal LDAP socket with which this output stream is
// associated.
- private InternalLDAPSocket socket;
+ private final InternalLDAPSocket socket;
+ // The immediate data being written.
+ private ByteSequenceReader byteBuffer;
+ // The save buffer used to store any unprocessed data waiting
+ // to be read as ASN.1 elements. (Usually due to writing incomplete
+ // ASN.1 elements.)
+ private final ByteStringBuilder saveBuffer;
+
+ private final ByteSequenceReader saveBufferReader;
+
+ /**
+ * An adaptor class for reading from a save buffer and the bytes
+ * being written sequentially using the InputStream interface.
+ *
+ * Since the bytes being written are only available duing the write
+ * call, any unused data will be appended to the save buffer before
+ * returning from the write method. This reader will always read the
+ * save buffer first before the actual bytes being written to ensure
+ * bytes are read in the same order as they are written.
+ */
+ private class CombinedBufferInputStream extends InputStream
+ {
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int available()
+ {
+ // The number of available bytes is the sum of the save buffer
+ // and the last read data in the NIO ByteStringBuilder.
+ return saveBufferReader.remaining() + byteBuffer.remaining();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int read()
+ {
+ if(saveBufferReader.remaining() > 0)
+ {
+ // Try saved buffer first
+ return 0xFF & saveBufferReader.get();
+ }
+ if(byteBuffer.remaining() > 0)
+ {
+ // Must still be on the channel buffer
+ return 0xFF & byteBuffer.get();
+ }
+
+ return -1;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int read(byte[] bytes)
+ {
+ return read(bytes, 0, bytes.length);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int read(byte[] value, int off, int length)
+ {
+ int bytesCopied=0;
+ int len;
+ if(saveBufferReader.remaining() > 0)
+ {
+ // Copy out of the last saved buffer first
+ len = Math.min(saveBufferReader.remaining(), length);
+ saveBufferReader.get(value, off, len);
+ bytesCopied += len;
+ }
+ if(bytesCopied < length && byteBuffer.remaining() > 0)
+ {
+ // Copy out of the channel buffer if we haven't got
+ // everything we needed.
+ len = Math.min(byteBuffer.remaining(), length - bytesCopied);
+ byteBuffer.get(value, off + bytesCopied, len);
+ bytesCopied += len;
+ }
+ return bytesCopied;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public long skip(long length)
+ {
+ int bytesSkipped=0;
+ int len;
+ if(saveBufferReader.remaining() > 0)
+ {
+ // Skip in the last saved buffer first
+ len = Math.min(saveBufferReader.remaining(), (int)length);
+ saveBufferReader.position(saveBufferReader.position() + len);
+ bytesSkipped += len;
+ }
+ if(bytesSkipped < length && byteBuffer.remaining() > 0)
+ {
+ //Skip in the channel buffer if we haven't skipped enough.
+ len = Math.min(byteBuffer.remaining(),
+ (int)length - bytesSkipped);
+ byteBuffer.position(byteBuffer.position() + len);
+ bytesSkipped += len;
+ }
+ return bytesSkipped;
+ }
+ }
/**
* Creates a new instance of an internal LDAP output stream that is
@@ -102,14 +199,13 @@
public InternalLDAPOutputStream(InternalLDAPSocket socket)
{
this.socket = socket;
+ this.closed = false;
+ this.saveBuffer = new ByteStringBuilder();
+ this.saveBufferReader = saveBuffer.asReader();
- closed = false;
-
- needType = true;
- elementType = 0x00;
- elementBytes = null;
- lengthBytes = null;
- arrayOffset = 0;
+ CombinedBufferInputStream bufferStream =
+ new CombinedBufferInputStream();
+ this.reader = ASN1.getReader(bufferStream);
}
@@ -199,125 +295,32 @@
throw new IOException(m.toString());
}
- if (len == 0)
+ byteBuffer = ByteString.wrap(b, off, len).asReader();
+
+ try
{
- return;
- }
-
-
- // See if we need to read the BER type.
- int position = off;
- int remaining = len;
- if (needType)
- {
- elementType = b[position++];
- needType = false;
-
- if (--remaining <= 0)
+ while(reader.elementAvailable())
{
- return;
+ LDAPMessage msg = LDAPReader.readMessage(reader);
+ processMessage(msg);
}
}
-
-
- // See if we need to read the first length byte.
- if ((lengthBytes == null) && (elementBytes == null))
+ catch(Exception e)
{
- int length = b[position++];
- if (length == (length & 0x7F))
- {
- // It's a single-byte length, so we can create the value
- // array.
- elementBytes = new byte[length];
- }
- else
- {
- // It's a multi-byte length, so we can create the length
- // array.
- lengthBytes = new byte[length & 0x7F];
- }
-
- arrayOffset = 0;
- if (--remaining <= 0)
- {
- return;
- }
+ throw new IOException(e.getMessage());
}
-
- // See if we need to continue reading part of a multi-byte length.
- if (lengthBytes != null)
+ // Clear the save buffer if we have read all of it
+ if(saveBufferReader.remaining() == 0)
{
- // See if we have enough to read the full length. If so, then
- // do it. Otherwise, read what we can and return.
- int needed = lengthBytes.length - arrayOffset;
- if (remaining >= needed)
- {
- System.arraycopy(b, position, lengthBytes, arrayOffset,
- needed);
- position += needed;
- remaining -= needed;
-
- int length = 0;
- for (byte lb : lengthBytes)
- {
- length <<= 8;
- length |= (lb & 0xFF);
- }
-
- elementBytes = new byte[length];
- lengthBytes = null;
- arrayOffset = 0;
- if (remaining <= 0)
- {
- return;
- }
- }
- else
- {
- System.arraycopy(b, position, lengthBytes, arrayOffset,
- remaining);
- arrayOffset += remaining;
- return;
- }
+ saveBuffer.clear();
+ saveBufferReader.rewind();
}
-
- // See if we need to read data for the element value.
- if (elementBytes != null)
+ // Append any unused data in the channel buffer to the save buffer
+ if(byteBuffer.remaining() > 0)
{
- // See if we have enough to read the full value. If so, then
- // do it, create the element, and process it. Otherwise, read
- // what we can and return.
- int needed = elementBytes.length - arrayOffset;
- if (remaining >= needed)
- {
- System.arraycopy(b, position, elementBytes, arrayOffset,
- needed);
- position += needed;
- remaining -= needed;
- processElement(new ASN1Element(elementType, elementBytes));
-
- needType = true;
- arrayOffset = 0;
- lengthBytes = null;
- elementBytes = null;
- }
- else
- {
- System.arraycopy(b, position, lengthBytes, arrayOffset,
- remaining);
- arrayOffset += remaining;
- return;
- }
- }
-
-
- // If there is still more data available, then call this method
- // again to process it.
- if (remaining > 0)
- {
- write(b, position, remaining);
+ saveBuffer.append(byteBuffer, byteBuffer.remaining());
}
}
@@ -339,73 +342,7 @@
public synchronized void write(int b)
throws IOException
{
- if (closed)
- {
- Message m = ERR_INTERNALOS_CLOSED.get();
- throw new IOException(m.toString());
- }
-
- if (needType)
- {
- elementType = (byte) (b & 0xFF);
- needType = false;
- return;
- }
- else if (elementBytes != null)
- {
- // The byte should be part of the element value.
- elementBytes[arrayOffset++] = (byte) (b & 0xFF);
- if (arrayOffset == elementBytes.length)
- {
- // The element has been completed, so process it.
- processElement(new ASN1Element(elementType, elementBytes));
- }
-
- lengthBytes = null;
- elementBytes = null;
- arrayOffset = 0;
- needType = true;
-
- return;
- }
- else if (lengthBytes != null)
- {
- // The byte should be part of a multi-byte length.
- lengthBytes[arrayOffset++] = (byte) (b & 0xFF);
- if (arrayOffset == lengthBytes.length)
- {
- int length = 0;
- for (int i=0; i < lengthBytes.length; i++)
- {
- length <<= 8;
- length |= (lengthBytes[i] & 0xFF);
- }
-
- elementBytes = new byte[length];
- lengthBytes = null;
- arrayOffset = 0;
- }
-
- return;
- }
- else
- {
- if ((b & 0x7F) == b)
- {
- // It's the complete length.
- elementBytes = new byte[b];
- lengthBytes = null;
- arrayOffset = 0;
- }
- else
- {
- lengthBytes = new byte[b & 0x7F];
- elementBytes = null;
- arrayOffset = 0;
- }
-
- return;
- }
+ write(new byte[]{(byte)b}, 0, 1);
}
@@ -416,25 +353,15 @@
* the appropriate response message(s) to the client through the
* corresponding internal LDAP input stream.
*
- * @param element The ASN.1 element to be processed.
+ * @param message The LDAP message to process.
*
* @throws IOException If a problem occurs while attempting to
* decode the provided ASN.1 element as an
* LDAP message.
*/
- private void processElement(ASN1Element element)
+ private void processMessage(LDAPMessage message)
throws IOException
{
- LDAPMessage message;
- try
- {
- message = LDAPMessage.decode(element.decodeAsSequence());
- }
- catch (Exception e)
- {
- throw new IOException(e.getMessage());
- }
-
switch (message.getProtocolOpType())
{
case OP_TYPE_ABANDON_REQUEST:
@@ -509,19 +436,10 @@
int messageID = message.getMessageID();
AddRequestProtocolOp request = message.getAddRequestProtocolOp();
- ArrayList<Control> requestControls = new ArrayList<Control>();
- if (message.getControls() != null)
- {
- for (LDAPControl c : message.getControls())
- {
- requestControls.add(c.getControl());
- }
- }
-
InternalClientConnection conn = socket.getConnection();
AddOperationBasis op =
new AddOperationBasis(conn, conn.nextOperationID(),
- messageID, requestControls,
+ messageID, message.getControls(),
request.getDN(),
request.getAttributes());
op.run();
@@ -531,12 +449,7 @@
op.getErrorMessage().toMessage(),
op.getMatchedDN(),
op.getReferralURLs());
- ArrayList<LDAPControl> responseControls =
- new ArrayList<LDAPControl>();
- for (Control c : op.getResponseControls())
- {
- responseControls.add(new LDAPControl(c));
- }
+ List<Control> responseControls = op.getResponseControls();
socket.getInputStream().addLDAPMessage(
new LDAPMessage(messageID, addResponse, responseControls));
@@ -572,19 +485,10 @@
return;
}
- ArrayList<Control> requestControls = new ArrayList<Control>();
- if (message.getControls() != null)
- {
- for (LDAPControl c : message.getControls())
- {
- requestControls.add(c.getControl());
- }
- }
-
InternalClientConnection conn = socket.getConnection();
BindOperationBasis op =
new BindOperationBasis(conn, conn.nextOperationID(),
- messageID, requestControls,
+ messageID, message.getControls(),
String.valueOf(request.getProtocolVersion()),
request.getDN(), request.getSimplePassword());
op.run();
@@ -594,12 +498,7 @@
op.getErrorMessage().toMessage(),
op.getMatchedDN(),
op.getReferralURLs());
- ArrayList<LDAPControl> responseControls =
- new ArrayList<LDAPControl>();
- for (Control c : op.getResponseControls())
- {
- responseControls.add(new LDAPControl(c));
- }
+ List<Control> responseControls = op.getResponseControls();
if (bindResponse.getResultCode() == LDAPResultCode.SUCCESS)
{
@@ -630,19 +529,10 @@
CompareRequestProtocolOp request =
message.getCompareRequestProtocolOp();
- ArrayList<Control> requestControls = new ArrayList<Control>();
- if (message.getControls() != null)
- {
- for (LDAPControl c : message.getControls())
- {
- requestControls.add(c.getControl());
- }
- }
-
InternalClientConnection conn = socket.getConnection();
CompareOperationBasis op =
new CompareOperationBasis(conn, conn.nextOperationID(),
- messageID, requestControls, request.getDN(),
+ messageID, message.getControls(), request.getDN(),
request.getAttributeType(),
request.getAssertionValue());
op.run();
@@ -653,12 +543,7 @@
op.getErrorMessage().toMessage(),
op.getMatchedDN(),
op.getReferralURLs());
- ArrayList<LDAPControl> responseControls =
- new ArrayList<LDAPControl>();
- for (Control c : op.getResponseControls())
- {
- responseControls.add(new LDAPControl(c));
- }
+ List<Control> responseControls = op.getResponseControls();
socket.getInputStream().addLDAPMessage(
new LDAPMessage(messageID, compareResponse,
@@ -684,19 +569,10 @@
DeleteRequestProtocolOp request =
message.getDeleteRequestProtocolOp();
- ArrayList<Control> requestControls = new ArrayList<Control>();
- if (message.getControls() != null)
- {
- for (LDAPControl c : message.getControls())
- {
- requestControls.add(c.getControl());
- }
- }
-
InternalClientConnection conn = socket.getConnection();
DeleteOperationBasis op =
new DeleteOperationBasis(conn, conn.nextOperationID(),
- messageID, requestControls, request.getDN());
+ messageID, message.getControls(), request.getDN());
op.run();
DeleteResponseProtocolOp deleteResponse =
@@ -705,12 +581,7 @@
op.getErrorMessage().toMessage(),
op.getMatchedDN(),
op.getReferralURLs());
- ArrayList<LDAPControl> responseControls =
- new ArrayList<LDAPControl>();
- for (Control c : op.getResponseControls())
- {
- responseControls.add(new LDAPControl(c));
- }
+ List<Control> responseControls = op.getResponseControls();
socket.getInputStream().addLDAPMessage(
new LDAPMessage(messageID, deleteResponse,
@@ -746,19 +617,10 @@
return;
}
- ArrayList<Control> requestControls = new ArrayList<Control>();
- if (message.getControls() != null)
- {
- for (LDAPControl c : message.getControls())
- {
- requestControls.add(c.getControl());
- }
- }
-
InternalClientConnection conn = socket.getConnection();
ExtendedOperationBasis op =
new ExtendedOperationBasis(conn, conn.nextOperationID(),
- messageID, requestControls, request.getOID(),
+ messageID, message.getControls(), request.getOID(),
request.getValue());
op.run();
@@ -769,12 +631,7 @@
op.getMatchedDN(),
op.getReferralURLs(), op.getResponseOID(),
op.getResponseValue());
- ArrayList<LDAPControl> responseControls =
- new ArrayList<LDAPControl>();
- for (Control c : op.getResponseControls())
- {
- responseControls.add(new LDAPControl(c));
- }
+ List<Control> responseControls = op.getResponseControls();
socket.getInputStream().addLDAPMessage(
new LDAPMessage(messageID, extendedResponse,
@@ -800,19 +657,10 @@
ModifyRequestProtocolOp request =
message.getModifyRequestProtocolOp();
- ArrayList<Control> requestControls = new ArrayList<Control>();
- if (message.getControls() != null)
- {
- for (LDAPControl c : message.getControls())
- {
- requestControls.add(c.getControl());
- }
- }
-
InternalClientConnection conn = socket.getConnection();
ModifyOperationBasis op =
new ModifyOperationBasis(conn, conn.nextOperationID(),
- messageID, requestControls, request.getDN(),
+ messageID, message.getControls(), request.getDN(),
request.getModifications());
op.run();
@@ -822,12 +670,7 @@
op.getErrorMessage().toMessage(),
op.getMatchedDN(),
op.getReferralURLs());
- ArrayList<LDAPControl> responseControls =
- new ArrayList<LDAPControl>();
- for (Control c : op.getResponseControls())
- {
- responseControls.add(new LDAPControl(c));
- }
+ List<Control> responseControls = op.getResponseControls();
socket.getInputStream().addLDAPMessage(
new LDAPMessage(messageID, modifyResponse,
@@ -853,21 +696,12 @@
ModifyDNRequestProtocolOp request =
message.getModifyDNRequestProtocolOp();
- ArrayList<Control> requestControls = new ArrayList<Control>();
- if (message.getControls() != null)
- {
- for (LDAPControl c : message.getControls())
- {
- requestControls.add(c.getControl());
- }
- }
-
InternalClientConnection conn = socket.getConnection();
ModifyDNOperationBasis op =
new ModifyDNOperationBasis(conn, conn.nextOperationID(),
- messageID, requestControls, request.getEntryDN(),
- request.getNewRDN(), request.deleteOldRDN(),
- request.getNewSuperior());
+ messageID, message.getControls(), request.getEntryDN(),
+ request.getNewRDN(), request.deleteOldRDN(),
+ request.getNewSuperior());
op.run();
ModifyDNResponseProtocolOp modifyDNResponse =
@@ -876,12 +710,7 @@
op.getErrorMessage().toMessage(),
op.getMatchedDN(),
op.getReferralURLs());
- ArrayList<LDAPControl> responseControls =
- new ArrayList<LDAPControl>();
- for (Control c : op.getResponseControls())
- {
- responseControls.add(new LDAPControl(c));
- }
+ List<Control> responseControls = op.getResponseControls();
socket.getInputStream().addLDAPMessage(
new LDAPMessage(messageID, modifyDNResponse,
@@ -907,23 +736,14 @@
SearchRequestProtocolOp request =
message.getSearchRequestProtocolOp();
- ArrayList<Control> requestControls = new ArrayList<Control>();
- if (message.getControls() != null)
- {
- for (LDAPControl c : message.getControls())
- {
- requestControls.add(c.getControl());
- }
- }
-
InternalClientConnection conn = socket.getConnection();
InternalSearchOperation op =
new InternalSearchOperation(conn, conn.nextOperationID(),
- messageID, requestControls, request.getBaseDN(),
- request.getScope(), request.getDereferencePolicy(),
- request.getSizeLimit(), request.getTimeLimit(),
- request.getTypesOnly(), request.getFilter(),
- request.getAttributes(), this);
+ messageID, message.getControls(), request.getBaseDN(),
+ request.getScope(), request.getDereferencePolicy(),
+ request.getSizeLimit(), request.getTimeLimit(),
+ request.getTypesOnly(), request.getFilter(),
+ request.getAttributes(), this);
op.run();
SearchResultDoneProtocolOp searchDone =
@@ -932,12 +752,7 @@
op.getErrorMessage().toMessage(),
op.getMatchedDN(),
op.getReferralURLs());
- ArrayList<LDAPControl> responseControls =
- new ArrayList<LDAPControl>();
- for (Control c : op.getResponseControls())
- {
- responseControls.add(new LDAPControl(c));
- }
+ List<Control> responseControls = op.getResponseControls();
socket.getInputStream().addLDAPMessage(
new LDAPMessage(messageID, searchDone, responseControls));
@@ -963,12 +778,7 @@
InternalSearchOperation searchOperation,
SearchResultEntry searchEntry)
{
- ArrayList<LDAPControl> entryControls =
- new ArrayList<LDAPControl>();
- for (Control c : searchEntry.getControls())
- {
- entryControls.add(new LDAPControl(c));
- }
+ List<Control> entryControls = searchEntry.getControls();
SearchResultEntryProtocolOp entry =
new SearchResultEntryProtocolOp(searchEntry);
@@ -998,12 +808,7 @@
InternalSearchOperation searchOperation,
SearchResultReference searchReference)
{
- ArrayList<LDAPControl> entryControls =
- new ArrayList<LDAPControl>();
- for (Control c : searchReference.getControls())
- {
- entryControls.add(new LDAPControl(c));
- }
+ List<Control> entryControls = searchReference.getControls();
SearchResultReferenceProtocolOp reference =
new SearchResultReferenceProtocolOp(searchReference);
--
Gitblit v1.10.0