001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2008 Sun Microsystems, Inc.
026     */
027    
028    package org.opends.server.tools;
029    
030    import org.opends.server.protocols.ldap.LDAPMessage;
031    import org.opends.server.protocols.ldap.LDAPConstants;
032    import org.opends.server.protocols.asn1.ASN1Element;
033    import org.opends.server.util.ServerConstants;
034    
035    import java.io.PrintStream;
036    import java.text.DateFormat;
037    import java.text.SimpleDateFormat;
038    import java.util.Date;
039    
040    /**
041     * A utility class for the LDAP client tools that performs verbose tracing of
042     * LDAP and ASN.1 messages.
043     */
044    public class VerboseTracer
045    {
046      /**
047       * Indicates whether verbose mode is on or off.
048       */
049      private boolean verbose;
050    
051      /**
052       * The print stream where tracing will be sent.
053       */
054      private PrintStream err;
055    
056      /**
057       * The time in milliseconds of the first message traced.
058       */
059      private long firstMessageTimestamp = 0;
060    
061      /**
062       * The time in millseconds of the previous message traced.
063       */
064      private long lastMessageTimestamp = 0;
065    
066      /**
067       * The format used for trace timestamps.
068       */
069      private DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
070    
071      /**
072       * Constructs a tracer with a specified verbosity and print stream.
073       * @param verbose Indicates whether verbose mode is on or off.
074       * @param err The print stream where tracing will be sent.
075       */
076      public VerboseTracer(boolean verbose, PrintStream err)
077      {
078        this.verbose = verbose;
079        this.err = err;
080      }
081    
082      /**
083       * Trace an incoming or outgoing message.
084       * @param messageDirection  Use "C>S" to indicate outgoing client to server.
085       *                          Use "S>C" to indicate incoming server to client.
086       * @param message The LDAP message to be traced.
087       * @param element The ASN.1 element of the message.
088       */
089      private synchronized void traceMessage(String messageDirection,
090                                             LDAPMessage message,
091                                             ASN1Element element)
092      {
093        StringBuilder header = new StringBuilder();
094        StringBuilder builder = new StringBuilder();
095    
096        long timestamp = System.currentTimeMillis();
097        long timeSinceLast;
098    
099        if (firstMessageTimestamp == 0)
100        {
101          firstMessageTimestamp = timestamp;
102        }
103    
104        if (lastMessageTimestamp == 0)
105        {
106          lastMessageTimestamp = timestamp;
107        }
108    
109        timeSinceLast = timestamp - lastMessageTimestamp;
110        if (timeSinceLast < 0)
111        {
112          timeSinceLast = 0;
113        }
114    
115        String timestampString = dateFormat.format(new Date(timestamp));
116    
117        header.append(messageDirection);
118        header.append(' ');
119        header.append(timestampString);
120    
121        // Include the number of milliseconds since the previous traced message.
122        header.append(" (");
123        header.append(timeSinceLast);
124        header.append("ms) ");
125    
126    
127        builder.append("LDAP: ");
128        builder.append(header);
129        builder.append(message);
130        builder.append(ServerConstants.EOL);
131    
132        builder.append("ASN1: ");
133        builder.append(header);
134        element.toString(builder, 0);
135    
136        err.print(builder);
137    
138        if (timestamp > lastMessageTimestamp)
139        {
140          lastMessageTimestamp = timestamp;
141        }
142      }
143    
144      /**
145       * Trace an incoming message.
146       * @param message The LDAP message to be traced.
147       * @param element The ASN.1 element of the message.
148       */
149      public void traceIncomingMessage(LDAPMessage message,
150                                                    ASN1Element element)
151      {
152        if (verbose)
153        {
154          if (message.getProtocolOpType() !=
155               LDAPConstants.OP_TYPE_SEARCH_RESULT_ENTRY)
156          {
157            traceMessage("S>C", message, element);
158          }
159        }
160      }
161    
162    
163      /**
164       * Trace an outgoing message.
165       * @param message The LDAP message to be traced.
166       * @param element The ASN.1 element of the message.
167       */
168      public void traceOutgoingMessage(LDAPMessage message,
169                                                    ASN1Element element)
170      {
171        if (verbose)
172        {
173          if (message.getProtocolOpType() !=
174               LDAPConstants.OP_TYPE_SEARCH_RESULT_ENTRY)
175          {
176            traceMessage("C>S", message, element);
177          }
178        }
179      }
180    
181    }