blob: ac1fa9104af0d4dc1a85d69e8f83e86bcb4db40e [file] [log] [blame]
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.ddmlib;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
/**
* Base implementation of {@link IShellOutputReceiver}, that takes the raw data coming from the
* socket, and convert it into {@link String} objects.
* <p/>Additionally, it splits the string by lines.
* <p/>Classes extending it must implement {@link #processNewLines(String[])} which receives
* new parsed lines as they become available.
*/
public abstract class MultiLineReceiver implements IShellOutputReceiver {
private boolean mTrimLines = true;
/** unfinished message line, stored for next packet */
private String mUnfinishedLine = null;
private final ArrayList<String> mArray = new ArrayList<String>();
/**
* Set the trim lines flag.
* @param trim hether the lines are trimmed, or not.
*/
public void setTrimLine(boolean trim) {
mTrimLines = trim;
}
/* (non-Javadoc)
* @see com.android.ddmlib.adb.IShellOutputReceiver#addOutput(
* byte[], int, int)
*/
@Override
public final void addOutput(byte[] data, int offset, int length) {
if (isCancelled() == false) {
String s = null;
try {
s = new String(data, offset, length, "UTF-8"); //$NON-NLS-1$
} catch (UnsupportedEncodingException e) {
// normal encoding didn't work, try the default one
s = new String(data, offset,length);
}
// ok we've got a string
if (s != null) {
// if we had an unfinished line we add it.
if (mUnfinishedLine != null) {
s = mUnfinishedLine + s;
mUnfinishedLine = null;
}
// now we split the lines
mArray.clear();
int start = 0;
do {
int index = s.indexOf("\r\n", start); //$NON-NLS-1$
// if \r\n was not found, this is an unfinished line
// and we store it to be processed for the next packet
if (index == -1) {
mUnfinishedLine = s.substring(start);
break;
}
// so we found a \r\n;
// extract the line
String line = s.substring(start, index);
if (mTrimLines) {
line = line.trim();
}
mArray.add(line);
// move start to after the \r\n we found
start = index + 2;
} while (true);
if (mArray.size() > 0) {
// at this point we've split all the lines.
// make the array
String[] lines = mArray.toArray(new String[mArray.size()]);
// send it for final processing
processNewLines(lines);
}
}
}
}
/* (non-Javadoc)
* @see com.android.ddmlib.adb.IShellOutputReceiver#flush()
*/
@Override
public final void flush() {
if (mUnfinishedLine != null) {
processNewLines(new String[] { mUnfinishedLine });
}
done();
}
/**
* Terminates the process. This is called after the last lines have been through
* {@link #processNewLines(String[])}.
*/
public void done() {
// do nothing.
}
/**
* Called when new lines are being received by the remote process.
* <p/>It is guaranteed that the lines are complete when they are given to this method.
* @param lines The array containing the new lines.
*/
public abstract void processNewLines(String[] lines);
}