FileDocCategorySizeDatePackage
LogFilter.javaAPI DocAndroid 1.5 API15756Wed May 06 22:41:08 BST 2009com.android.ddmuilib.logcat

LogFilter

public class LogFilter extends Object
logcat output filter class

Fields Summary
public static final int
MODE_PID
public static final int
MODE_TAG
public static final int
MODE_LEVEL
private String
mName
private int
mMode
Filtering mode. Value can be a mix of MODE_PID, MODE_TAG, MODE_LEVEL
private int
mPid
pid used for filtering. Only valid if mMode is MODE_PID.
private int
mLogLevel
Single level log level as defined in Log.mLevelChar. Only valid if mMode is MODE_LEVEL
private String
mTag
log tag filtering. Only valid if mMode is MODE_TAG
private org.eclipse.swt.widgets.Table
mTable
private org.eclipse.swt.widgets.TabItem
mTabItem
private boolean
mIsCurrentTabItem
private int
mUnreadCount
private String[]
mTempKeywordFilters
Temp keyword filtering
private int
mTempPid
temp pid filtering
private String
mTempTag
temp tag filtering
private int
mTempLogLevel
temp log level filtering
private LogColors
mColors
private boolean
mTempFilteringStatus
private final ArrayList
mMessages
private final ArrayList
mNewMessages
private boolean
mSupportsDelete
private boolean
mSupportsEdit
private int
mRemovedMessageCount
Constructors Summary
public LogFilter(String name)
Creates a filter with a particular mode.

param
name The name to be displayed in the UI


                          
       
        mName = name;
    
public LogFilter()


    
Methods Summary
booleanaccept(com.android.ddmuilib.logcat.LogPanel.LogMessage logMessage)
Filters a message.

param
logMessage the Message
return
true if the message is accepted by the filter.

        // do the regular filtering now
        if ((mMode & MODE_PID) == MODE_PID && mPid != logMessage.data.pid) {
            return false;
        }

        if ((mMode & MODE_TAG) == MODE_TAG && (
                logMessage.data.tag == null ||
                logMessage.data.tag.equals(mTag) == false)) {
            return false;
        }

        int msgLogLevel = logMessage.data.logLevel.getPriority();

        // test the temp log filtering first, as it replaces the old one
        if (mTempLogLevel != -1) {
            if (mTempLogLevel > msgLogLevel) {
                return false;
            }
        } else if ((mMode & MODE_LEVEL) == MODE_LEVEL &&
                mLogLevel > msgLogLevel) {
            return false;
        }

        // do the temp filtering now.
        if (mTempKeywordFilters != null) {
            String msg = logMessage.msg;

            for (String kw : mTempKeywordFilters) {
                try {
                    if (msg.contains(kw) == false && msg.matches(kw) == false) {
                        return false;
                    }
                } catch (PatternSyntaxException e) {
                    // if the string is not a valid regular expression,
                    // this exception is thrown.
                    return false;
                }
            }
        }

        if (mTempPid != -1 && mTempPid != logMessage.data.pid) {
           return false;
        }

        if (mTempTag != null && mTempTag.length() > 0) {
            if (mTempTag.equals(logMessage.data.tag) == false) {
                return false;
            }
        }

        return true;
    
public booleanaddMessage(com.android.ddmuilib.logcat.LogPanel.LogMessage newMessage, com.android.ddmuilib.logcat.LogPanel.LogMessage oldMessage)
Adds a new message and optionally removes an old message.

The new message is filtered through {@link #accept(LogMessage)}. Calls to {@link #flush()} from a UI thread will display it (and other pending messages) to the associated {@link Table}.

param
logMessage the MessageData object to filter
return
true if the message was accepted.

        synchronized (mMessages) {
            if (oldMessage != null) {
                int index = mMessages.indexOf(oldMessage);
                if (index != -1) {
                    // TODO check that index will always be -1 or 0, as only the oldest message is ever removed.
                    mMessages.remove(index);
                    mRemovedMessageCount++;
                }
                
                // now we look for it in mNewMessages. This can happen if the new message is added
                // and then removed because too many messages are added between calls to #flush()
                index = mNewMessages.indexOf(oldMessage);
                if (index != -1) {
                    // TODO check that index will always be -1 or 0, as only the oldest message is ever removed.
                    mNewMessages.remove(index);
                }
            }

            boolean filter = accept(newMessage);

            if (filter) {
                // at this point the message is accepted, we add it to the list
                mMessages.add(newMessage);
                mNewMessages.add(newMessage);
            }

            return filter;
        }
    
private voidaddTableItem(com.android.ddmuilib.logcat.LogPanel.LogMessage msg)
Add a TableItem for the index-th item of the buffer

param
filter The index of the table in which to insert the item.

        TableItem item = new TableItem(mTable, SWT.NONE);
        item.setText(0, msg.data.time);
        item.setText(1, new String(new char[] { msg.data.logLevel.getPriorityLetter() }));
        item.setText(2, msg.data.pidString);
        item.setText(3, msg.data.tag);
        item.setText(4, msg.msg);

        // add the buffer index as data
        item.setData(msg);

        if (msg.data.logLevel == LogLevel.INFO) {
            item.setForeground(mColors.infoColor);
        } else if (msg.data.logLevel == LogLevel.DEBUG) {
            item.setForeground(mColors.debugColor);
        } else if (msg.data.logLevel == LogLevel.ERROR) {
            item.setForeground(mColors.errorColor);
        } else if (msg.data.logLevel == LogLevel.WARN) {
            item.setForeground(mColors.warningColor);
        } else {
            item.setForeground(mColors.verboseColor);
        }
    
public voidclear()
Removes all the items in the filter and its {@link Table}.

        mRemovedMessageCount = 0;
        mNewMessages.clear();
        mMessages.clear();
        mTable.removeAll();
    
public voiddispose()

        mTable.dispose();
        mTabItem.dispose();
        mTable = null;
        mTabItem = null;
    
public voidflush()
Takes all the accepted messages and display them. This must be called from a UI thread.

        // if scroll bar is at the bottom, we will scroll
        ScrollBar bar = mTable.getVerticalBar();
        boolean scroll = bar.getMaximum() == bar.getSelection() + bar.getThumb();
        
        // if we are not going to scroll, get the current first item being shown.
        int topIndex = mTable.getTopIndex();

        // disable drawing
        mTable.setRedraw(false);
        
        int totalCount = mNewMessages.size();

        try {
            // remove the items of the old messages.
            for (int i = 0 ; i < mRemovedMessageCount && mTable.getItemCount() > 0 ; i++) {
                mTable.remove(0);
            }
    
            if (mUnreadCount > mTable.getItemCount()) {
                mUnreadCount = mTable.getItemCount();
            }
    
            // add the new items
            for (int i = 0  ; i < totalCount ; i++) {
                LogMessage msg = mNewMessages.get(i);
                addTableItem(msg);
            }
        } catch (SWTException e) {
            // log the error and keep going. Content of the logcat table maybe unexpected
            // but at least ddms won't crash.
            Log.e("LogFilter", e);
        }
        
        // redraw
        mTable.setRedraw(true);

        // scroll if needed, by showing the last item
        if (scroll) {
            totalCount = mTable.getItemCount();
            if (totalCount > 0) {
                mTable.showItem(mTable.getItem(totalCount-1));
            }
        } else if (mRemovedMessageCount > 0) {
            // we need to make sure the topIndex is still visible.
            // Because really old items are removed from the list, this could make it disappear
            // if we don't change the scroll value at all.

            topIndex -= mRemovedMessageCount;
            if (topIndex < 0) {
                // looks like it disappeared. Lets just show the first item
                mTable.showItem(mTable.getItem(0));
            } else {
                mTable.showItem(mTable.getItem(topIndex));
            }
        }

        // if this filter is not the current one, we update the tab text
        // with the amount of unread message
        if (mIsCurrentTabItem == false) {
            mUnreadCount += mNewMessages.size();
            totalCount = mTable.getItemCount();
            if (mUnreadCount > 0) {
                mTabItem.setText(mName + " (" // $NON-NLS-1$
                        + (mUnreadCount > totalCount ? totalCount : mUnreadCount)
                        + ")");  // $NON-NLS-1$
            } else {
                mTabItem.setText(mName);  // $NON-NLS-1$
            }
        }
        
        mNewMessages.clear();
    
public intgetFilteringMode()
Returns the current filtering mode.

return
A bitmask. Possible values are MODE_PID, MODE_TAG, MODE_LEVEL

        return mMode;
    
public intgetLogLevel()

        if ((mMode & MODE_LEVEL) == MODE_LEVEL) {
            return mLogLevel;
        }

        return -1;
    
public java.lang.StringgetName()
Returns the UI display name.

        return mName;
    
public intgetPidFilter()
Returns the pid filter if valid, otherwise -1

        if ((mMode & MODE_PID) == MODE_PID)
            return mPid;
        return -1;
    
public org.eclipse.swt.widgets.TablegetTable()
Returns the UI table object.

return

        return mTable;
    
public java.lang.StringgetTagFilter()

        if ((mMode & MODE_TAG) == MODE_TAG)
            return mTag;
        return null;
    
booleangetTempFilterStatus()

        return mTempFilteringStatus;
    
intgetUnreadCount()

        return mUnreadCount;
    
public booleanloadFromString(java.lang.String string)

        String[] segments = string.split(":"); // $NON-NLS-1$
        int index = 0;

        // get the name
        mName = segments[index++];

        // get the mode
        mMode = Integer.parseInt(segments[index++]);

        if ((mMode & MODE_PID) == MODE_PID) {
            mPid = Integer.parseInt(segments[index++]);
        }

        if ((mMode & MODE_LEVEL) == MODE_LEVEL) {
            mLogLevel = Integer.parseInt(segments[index++]);
        }

        if ((mMode & MODE_TAG) == MODE_TAG) {
            mTag = segments[index++];
        }

        return true;
    
public voidresetFilteringMode()
Resets the filtering mode to be 0 (i.e. no filter).

        mMode = 0;
    
voidresetTempFiltering()

        if (mTempPid != -1 || mTempTag != null || mTempKeywordFilters != null) {
            mTempFilteringStatus = true;
        }

        mTempPid = -1;
        mTempTag = null;
        mTempKeywordFilters = null;
    
voidresetTempFilteringStatus()

        mTempFilteringStatus = false;
    
voidsetColors(LogColors colors)

        mColors = colors;
    
public voidsetLogLevel(int level)

        if (level == -1) {
            mMode &= ~MODE_LEVEL;
        } else {
            mMode |= MODE_LEVEL;
            mLogLevel = level;
        }

    
voidsetName(java.lang.String name)
Sets the name of the filter.

        mName = name;
    
public voidsetPidMode(int pid)
Adds PID to the current filtering mode.

param
pid

        if (pid != -1) {
            mMode |= MODE_PID;
        } else {
            mMode &= ~MODE_PID;
        }
        mPid = pid;
    
public voidsetSelectedState(boolean selected)
Sets the selected state of the filter.

param
selected selection state.

        if (selected) {
            if (mTabItem != null) {
                mTabItem.setText(mName);
            }
            mUnreadCount = 0;
        }
        mIsCurrentTabItem = selected;
    
voidsetSupportsDelete(boolean support)

        mSupportsDelete = support;
    
voidsetSupportsEdit(boolean support)

        mSupportsEdit = support;
    
public voidsetTagMode(java.lang.String tag)

        if (tag != null && tag.length() > 0) {
            mMode |= MODE_TAG;
        } else {
            mMode &= ~MODE_TAG;
        }
        mTag = tag;
    
voidsetTempKeywordFiltering(java.lang.String[] segments)

        mTempKeywordFilters = segments;
        mTempFilteringStatus = true;
    
voidsetTempPidFiltering(int pid)

        mTempPid = pid;
        mTempFilteringStatus = true;
    
voidsetTempTagFiltering(java.lang.String tag)

        mTempTag = tag;
        mTempFilteringStatus = true;
    
voidsetUnreadCount(int unreadCount)

        mUnreadCount = unreadCount;
    
public voidsetWidgets(org.eclipse.swt.widgets.TabItem tabItem, org.eclipse.swt.widgets.Table table)
Set the Table ui widget associated with this filter.

param
tabItem The item in the TabFolder
param
table The Table object

        mTable = table;
        mTabItem = tabItem;
    
public booleansupportsDelete()

        return mSupportsDelete ;
    
public booleansupportsEdit()

        return mSupportsEdit;
    
public java.lang.StringtoString()

        StringBuilder sb = new StringBuilder(mName);

        sb.append(':");
        sb.append(mMode);
        if ((mMode & MODE_PID) == MODE_PID) {
            sb.append(':");
            sb.append(mPid);
        }

        if ((mMode & MODE_LEVEL) == MODE_LEVEL) {
            sb.append(':");
            sb.append(mLogLevel);
        }

        if ((mMode & MODE_TAG) == MODE_TAG) {
            sb.append(':");
            sb.append(mTag);
        }

        return sb.toString();
    
public booleanuiReady()
Returns true if the filter is ready for ui.

        return (mTable != null && mTabItem != null);