001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2009 Sun Microsystems, Inc.
015 * Portions Copyright 2014 ForgeRock AS.
016 */
017package org.opends.server.tools;
018
019import java.io.BufferedOutputStream;
020import java.io.Closeable;
021import java.io.IOException;
022import java.net.Socket;
023
024import org.forgerock.i18n.slf4j.LocalizedLogger;
025import org.forgerock.opendj.io.ASN1;
026import org.forgerock.opendj.io.ASN1Writer;
027import org.forgerock.opendj.ldap.ByteString;
028import org.opends.server.protocols.ldap.LDAPMessage;
029import org.opends.server.types.RecordingOutputStream;
030import org.opends.server.util.ServerConstants;
031import org.opends.server.util.StaticUtils;
032
033/**
034 * This class defines a utility that can be used to write LDAP messages over a
035 * provided socket.
036 */
037public class LDAPWriter implements Closeable
038{
039  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
040
041  private Socket socket;
042  private ASN1Writer asn1Writer;
043  private RecordingOutputStream debugOutputStream;
044
045
046  /**
047   * Creates a new LDAP writer that will write messages to the provided
048   * socket and trace the messages using a provided tracer.
049   *
050   * @param  socket  The socket to use to write LDAP messages.
051   *
052   * @throws  IOException  If a problem occurs while attempting to obtain an
053   *                       output stream for the socket.
054   */
055  public LDAPWriter(Socket socket)
056       throws IOException
057  {
058    this.socket = socket;
059    this.debugOutputStream =
060        new RecordingOutputStream(
061        new BufferedOutputStream(socket.getOutputStream(), 4096));
062    this.asn1Writer = ASN1.getWriter(debugOutputStream);
063  }
064
065  /**
066   * Writes an LDAP message to the associated output stream.
067   *
068   * @param   message      The message to be written.
069   *
070   * @throws  IOException  If a problem occurs while trying to write the
071   *                       information over the output stream.
072   */
073  public void writeMessage(LDAPMessage message)
074       throws IOException
075  {
076    if(logger.isTraceEnabled())
077    {
078      logger.trace(message.toString());
079      debugOutputStream.setRecordingEnabled(true);
080    }
081
082    message.write(asn1Writer);
083    asn1Writer.flush();
084
085    if(debugOutputStream.isRecordingEnabled())
086    {
087      ByteString bytesRead = debugOutputStream.getRecordedBytes();
088      debugOutputStream.clearRecordedBytes();
089
090      logger.trace("bytes written to wire(len=" + bytesRead.length() + "):"
091          + ServerConstants.EOL + bytesRead.toHexPlusAsciiString(4));
092    }
093  }
094
095  /**
096   * Closes this LDAP writer and the underlying socket.
097   */
098  @Override
099  public void close()
100  {
101    StaticUtils.close(asn1Writer, debugOutputStream);
102    StaticUtils.close(socket);
103  }
104}