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 */ 017 018package org.opends.server.tools; 019 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.ASN1Reader; 027import org.forgerock.opendj.ldap.ByteString; 028import org.forgerock.opendj.ldap.DecodeException; 029import org.opends.server.protocols.ldap.LDAPMessage; 030import org.opends.server.types.LDAPException; 031import org.opends.server.types.RecordingInputStream; 032import org.opends.server.util.ServerConstants; 033import org.opends.server.util.StaticUtils; 034 035/** 036 * This class defines a utility that can be used to read LDAP messages from a 037 * provided socket. 038 */ 039public class LDAPReader implements Closeable 040{ 041 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 042 043 private Socket socket; 044 private ASN1Reader asn1Reader; 045 private RecordingInputStream debugInputStream; 046 047 /** 048 * Creates a new LDAP reader that will read messages from the provided 049 * socket and trace the messages using a provided tracer. 050 * 051 * @param socket The socket from which to read the LDAP messages. 052 * 053 * @throws IOException If a problem occurs while attempting to obtain an 054 * input stream for the socket. 055 */ 056 public LDAPReader(Socket socket) 057 throws IOException 058 { 059 this.socket = socket; 060 this.debugInputStream = new RecordingInputStream(socket.getInputStream()); 061 this.asn1Reader = ASN1.getReader(debugInputStream); 062 } 063 064 /** 065 * Reads an LDAP message from the associated input stream. 066 * 067 * @return The LDAP message read from the associated input stream, or 068 * <CODE>null</CODE> if the end of the stream has been reached. 069 * 070 * @throws IOException If a problem occurs while attempting to read from the 071 * input stream. 072 * 073 * @throws DecodeException If a problem occurs while attempting to decode the 074 * data read as an ASN.1 sequence. 075 076 * @throws LDAPException If a problem occurs while attempting to decode the 077 * LDAP message. 078 */ 079 public LDAPMessage readMessage() 080 throws IOException, DecodeException, LDAPException 081 { 082 debugInputStream.setRecordingEnabled(logger.isTraceEnabled()); 083 084 if(!asn1Reader.hasNextElement()) 085 { 086 // EOF was reached... 087 return null; 088 } 089 090 LDAPMessage message = 091 org.opends.server.protocols.ldap.LDAPReader.readMessage(asn1Reader); 092 093 if(debugInputStream.isRecordingEnabled()) 094 { 095 ByteString bytesRead = debugInputStream.getRecordedBytes(); 096 debugInputStream.clearRecordedBytes(); 097 098 logger.trace("bytes read from wire(len=" + bytesRead.length() + "):" 099 + ServerConstants.EOL + bytesRead.toHexPlusAsciiString(4)); 100 logger.trace(message.toString()); 101 } 102 103 return message; 104 } 105 106 /** 107 * Closes this LDAP reader and the underlying socket. 108 */ 109 @Override 110 public void close() 111 { 112 StaticUtils.close(asn1Reader); 113 StaticUtils.close(socket); 114 } 115}