org.chromium.debug.core/src/org/chromium/debug/core/model/ConnectionLoggerImpl.java
changeset 2 e4420d2515f1
child 52 f577ea64429e
equal deleted inserted replaced
1:ef76fc2ac88c 2:e4420d2515f1
       
     1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
       
     2 // Use of this source code is governed by a BSD-style license that can be
       
     3 // found in the LICENSE file.
       
     4 
       
     5 package org.chromium.debug.core.model;
       
     6 
       
     7 import java.io.IOException;
       
     8 import java.io.Reader;
       
     9 import java.io.Writer;
       
    10 
       
    11 import org.chromium.sdk.ConnectionLogger;
       
    12 import org.eclipse.debug.core.DebugPlugin;
       
    13 import org.eclipse.debug.core.model.ITerminate;
       
    14 
       
    15 /**
       
    16  * Connection logger that writes both incoming and outgoing streams into
       
    17  * logWriter with simple annotations.
       
    18  */
       
    19 public class ConnectionLoggerImpl implements ConnectionLogger {
       
    20   /**
       
    21    * Additional interface logger sends its output to.
       
    22    */
       
    23   public interface LogLifecycleListener {
       
    24     /**
       
    25      * Notifies about logging start. Before this call {@link ConnectionLoggerImpl}
       
    26      * is considered to be simply garbage-collectible. After this call
       
    27      * {@link ConnectionLoggerImpl} must call {@link #logClosed()}.
       
    28      *
       
    29      * @param connectionLogger instance of host {@link ConnectionLoggerImpl}, which is nice
       
    30      *        to have because theoretically we may receive this call before constructor of
       
    31      *        {@link ConnectionLoggerImpl} returned
       
    32      */
       
    33     void logStarted(ConnectionLoggerImpl connectionLogger);
       
    34 
       
    35     /**
       
    36      * Notifies about log stream being closed. Technically, last messages may arrive
       
    37      * even after this. It is supposed that log representation may be closed on this call
       
    38      * because we are not 100% accurate.
       
    39      */
       
    40     void logClosed();
       
    41   }
       
    42 
       
    43 
       
    44   public ConnectionLoggerImpl(Writer logWriter, LogLifecycleListener lifecycleListener) {
       
    45     this.logWriter = logWriter;
       
    46     this.lifecycleListener = lifecycleListener;
       
    47   }
       
    48 
       
    49   public Writer wrapWriter(final Writer streamWriter) {
       
    50     return new Writer() {
       
    51       @Override
       
    52       public void close() throws IOException {
       
    53         streamWriter.close();
       
    54         flushLogWriter();
       
    55       }
       
    56       @Override
       
    57       public void flush() throws IOException {
       
    58         streamWriter.flush();
       
    59         flushLogWriter();
       
    60       }
       
    61       @Override
       
    62       public void write(char[] cbuf, int off, int len) throws IOException {
       
    63         streamWriter.write(cbuf, off, len);
       
    64 
       
    65         writeToLog(cbuf, off, len, this,
       
    66             Messages.ConnectionLoggerImpl_SentToChrome);
       
    67       }
       
    68     };
       
    69   }
       
    70   public Reader wrapReader(final Reader streamReader) {
       
    71     return new Reader() {
       
    72       @Override
       
    73       public void close() throws IOException {
       
    74         streamReader.close();
       
    75         flushLogWriter();
       
    76       }
       
    77 
       
    78       @Override
       
    79       public int read(char[] cbuf, int off, int len) throws IOException {
       
    80         int res = streamReader.read(cbuf, off, len);
       
    81         if (res > 0) {
       
    82           writeToLog(cbuf, off, res, this,
       
    83               Messages.ConnectionLoggerImpl_ReceivedFromChrome);
       
    84           flushLogWriter();
       
    85         }
       
    86         return res;
       
    87       }
       
    88     };
       
    89   }
       
    90 
       
    91   public void start() {
       
    92     lifecycleListener.logStarted(this);
       
    93   }
       
    94 
       
    95   public void handleEos() {
       
    96     isClosed = true;
       
    97     lifecycleListener.logClosed();
       
    98   }
       
    99 
       
   100   public ITerminate getConnectionTerminate() {
       
   101     return connectionTerminate;
       
   102   }
       
   103 
       
   104   public void setConnectionCloser(ConnectionCloser connectionCloser) {
       
   105     this.connectionCloser = connectionCloser;
       
   106   }
       
   107 
       
   108   private synchronized void writeToLog(char[] cbuf, int off, int len, Object source,
       
   109       String sourceName) {
       
   110     try {
       
   111       if (lastSource != source) {
       
   112         if (lastSource != null) {
       
   113           logWriter.append('\n');
       
   114         }
       
   115         logWriter.append("> ").append(sourceName).append('\n'); //$NON-NLS-1$
       
   116         lastSource = source;
       
   117       }
       
   118       logWriter.write(cbuf, off, len);
       
   119     } catch (IOException e) {
       
   120       DebugPlugin.log(e);
       
   121     }
       
   122   }
       
   123   private void flushLogWriter() {
       
   124     try {
       
   125       logWriter.flush();
       
   126     } catch (IOException e) {
       
   127       DebugPlugin.log(e);
       
   128     }
       
   129   }
       
   130 
       
   131   private final Writer logWriter;
       
   132   private final LogLifecycleListener lifecycleListener;
       
   133   private Object lastSource = null;
       
   134   private volatile ConnectionCloser connectionCloser = null;
       
   135   private volatile boolean isClosed = false;
       
   136 
       
   137   private final ITerminate connectionTerminate = new ITerminate() {
       
   138     public boolean canTerminate() {
       
   139       return !isClosed && connectionCloser != null;
       
   140     }
       
   141 
       
   142     public boolean isTerminated() {
       
   143       return isClosed;
       
   144     }
       
   145 
       
   146     public void terminate() {
       
   147       ConnectionCloser connectionCloser0 = ConnectionLoggerImpl.this.connectionCloser;
       
   148       if (connectionCloser0 == null) {
       
   149         throw new IllegalStateException();
       
   150       }
       
   151       connectionCloser0.closeConnection();
       
   152     }
       
   153   };
       
   154 }