Home | History | Annotate | Download | only in ddmlib
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.ddmlib;
     18 
     19 import java.io.UnsupportedEncodingException;
     20 import java.util.ArrayList;
     21 
     22 /**
     23  * Base implementation of {@link IShellOutputReceiver}, that takes the raw data coming from the
     24  * socket, and convert it into {@link String} objects.
     25  * <p/>Additionally, it splits the string by lines.
     26  * <p/>Classes extending it must implement {@link #processNewLines(String[])} which receives
     27  * new parsed lines as they become available.
     28  */
     29 public abstract class MultiLineReceiver implements IShellOutputReceiver {
     30 
     31     private boolean mTrimLines = true;
     32 
     33     /** unfinished message line, stored for next packet */
     34     private String mUnfinishedLine = null;
     35 
     36     private final ArrayList<String> mArray = new ArrayList<String>();
     37 
     38     /**
     39      * Set the trim lines flag.
     40      * @param trim hether the lines are trimmed, or not.
     41      */
     42     public void setTrimLine(boolean trim) {
     43         mTrimLines = trim;
     44     }
     45 
     46     /* (non-Javadoc)
     47      * @see com.android.ddmlib.adb.IShellOutputReceiver#addOutput(
     48      *      byte[], int, int)
     49      */
     50     public final void addOutput(byte[] data, int offset, int length) {
     51         if (isCancelled() == false) {
     52             String s = null;
     53             try {
     54                 s = new String(data, offset, length, "ISO-8859-1"); //$NON-NLS-1$
     55             } catch (UnsupportedEncodingException e) {
     56                 // normal encoding didn't work, try the default one
     57                 s = new String(data, offset,length);
     58             }
     59 
     60             // ok we've got a string
     61             if (s != null) {
     62                 // if we had an unfinished line we add it.
     63                 if (mUnfinishedLine != null) {
     64                     s = mUnfinishedLine + s;
     65                     mUnfinishedLine = null;
     66                 }
     67 
     68                 // now we split the lines
     69                 mArray.clear();
     70                 int start = 0;
     71                 do {
     72                     int index = s.indexOf("\r\n", start); //$NON-NLS-1$
     73 
     74                     // if \r\n was not found, this is an unfinished line
     75                     // and we store it to be processed for the next packet
     76                     if (index == -1) {
     77                         mUnfinishedLine = s.substring(start);
     78                         break;
     79                     }
     80 
     81                     // so we found a \r\n;
     82                     // extract the line
     83                     String line = s.substring(start, index);
     84                     if (mTrimLines) {
     85                         line = line.trim();
     86                     }
     87                     mArray.add(line);
     88 
     89                     // move start to after the \r\n we found
     90                     start = index + 2;
     91                 } while (true);
     92 
     93                 if (mArray.size() > 0) {
     94                     // at this point we've split all the lines.
     95                     // make the array
     96                     String[] lines = mArray.toArray(new String[mArray.size()]);
     97 
     98                     // send it for final processing
     99                     processNewLines(lines);
    100                 }
    101             }
    102         }
    103     }
    104 
    105     /* (non-Javadoc)
    106      * @see com.android.ddmlib.adb.IShellOutputReceiver#flush()
    107      */
    108     public final void flush() {
    109         if (mUnfinishedLine != null) {
    110             processNewLines(new String[] { mUnfinishedLine });
    111         }
    112 
    113         done();
    114     }
    115 
    116     /**
    117      * Terminates the process. This is called after the last lines have been through
    118      * {@link #processNewLines(String[])}.
    119      */
    120     public void done() {
    121         // do nothing.
    122     }
    123 
    124     /**
    125      * Called when new lines are being received by the remote process.
    126      * <p/>It is guaranteed that the lines are complete when they are given to this method.
    127      * @param lines The array containing the new lines.
    128      */
    129     public abstract void processNewLines(String[] lines);
    130 }
    131