Clover coverage report - DrJava Test Coverage (drjava-20120304-r5456)
Coverage timestamp: Sun Mar 4 2012 03:13:23 CST
file stats: LOC: 238   Methods: 12
NCLOC: 149   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
LessPanel.java 0% 0% 0% 0%
coverage
 1    /*BEGIN_COPYRIGHT_BLOCK
 2    *
 3    * Copyright (c) 2001-2010, JavaPLT group at Rice University (drjava@rice.edu)
 4    * All rights reserved.
 5    *
 6    * Redistribution and use in source and binary forms, with or without
 7    * modification, are permitted provided that the following conditions are met:
 8    * * Redistributions of source code must retain the above copyright
 9    * notice, this list of conditions and the following disclaimer.
 10    * * Redistributions in binary form must reproduce the above copyright
 11    * notice, this list of conditions and the following disclaimer in the
 12    * documentation and/or other materials provided with the distribution.
 13    * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
 14    * names of its contributors may be used to endorse or promote products
 15    * derived from this software without specific prior written permission.
 16    *
 17    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18    * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 19    * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 20    * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 21    * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 22    * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 23    * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 24    * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 25    * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 26    * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 27    * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28    *
 29    * This software is Open Source Initiative approved Open Source Software.
 30    * Open Source Initative Approved is a trademark of the Open Source Initiative.
 31    *
 32    * This file is part of DrJava. Download the current version of this project
 33    * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
 34    *
 35    * END_COPYRIGHT_BLOCK*/
 36   
 37    package edu.rice.cs.drjava.ui;
 38   
 39    import java.io.*;
 40   
 41    import javax.swing.*;
 42    import java.awt.event.*;
 43    import java.awt.*;
 44   
 45    import edu.rice.cs.util.swing.Utilities;
 46   
 47    /** Panel for displaying some component with buttons, one of which is an "Abort" button.
 48    * This should be used to display the output of an external process.
 49    * This class is a swing class that should only be accessed from the event thread.
 50    * @version $Id: LessPanel.java 5236 2010-04-27 01:43:36Z mgricken $
 51    */
 52    public class LessPanel extends AbortablePanel {
 53    /** Size of the buffer read at once. */
 54    public final int BUFFER_SIZE = 10240;
 55    /** Number of buffer reads before the event thread is allowed to do something else. */
 56    public final int BUFFER_READS_PER_TIMER = 5;
 57    protected JTextArea _textArea;
 58    protected File _f = null;
 59    protected FileReader _fr = null;
 60    protected JButton _updateNowButton;
 61    protected JButton _restartButton;
 62    protected Thread _updateThread;
 63    private char[] _buf = new char[BUFFER_SIZE];
 64    private int _red = -1;
 65    private long _totalRead = 0;
 66   
 67    /** Constructs a new "less" panel to watch file output.
 68    * This is swing view class and hence should only be accessed from the event thread.
 69    * @param frame the MainFrame
 70    * @param title title of the pane
 71    * @param f file to monitor
 72    */
 73  0 public LessPanel(MainFrame frame, String title, File f) {
 74  0 super(frame, title);
 75  0 initThread(f);
 76  0 updateText();
 77    // MainFrame.LOG.log("\tLessPanel ctor done");
 78    }
 79   
 80  0 protected void initThread(File f) {
 81  0 try {
 82    // MainFrame.LOG.log("\tLessPanel ctor");
 83    // MainFrame.LOG.log("\texists: " + f.exists());
 84    // MainFrame.LOG.log("\tcanRead: " + f.canRead());
 85    // MainFrame.LOG.log("\tisFile: " + f.isFile());
 86  0 if (f.exists() && f.canRead() && f.isFile()) {
 87    // MainFrame.LOG.log("\texists, can be read, is file");
 88    // MainFrame.LOG.log("\tfile length = " + f.length());
 89  0 _f = f;
 90  0 _fr = new FileReader(_f);
 91  0 _red = -1;
 92  0 _totalRead = 0;
 93  0 _updateThread = new Thread(new Runnable() {
 94  0 public void run() {
 95  0 while(_fr != null) {
 96  0 try {
 97  0 Thread.sleep(edu.rice.cs.drjava.DrJava.getConfig().
 98    getSetting(edu.rice.cs.drjava.config.OptionConstants.FOLLOW_FILE_DELAY));
 99    }
 100    catch(InterruptedException ie) { /* ignore */ }
 101  0 updateText();
 102    }
 103    }
 104    });
 105  0 _updateThread.start();
 106  0 _updateNowButton.setEnabled(true);
 107    // MainFrame.LOG.log("\tUpdate thread started");
 108    }
 109    }
 110    catch(Exception e) {
 111  0 _fr = null;
 112    }
 113    }
 114   
 115    /** Setup left panel. Must be overridden to return the component on the left side. */
 116  0 protected Component makeLeftPanel() {
 117  0 _textArea = new JTextArea();
 118  0 _textArea.setEditable(false);
 119  0 return _textArea;
 120    }
 121   
 122    /** Abort action was performed. Must be overridden to return the component on the left side. */
 123  0 protected void abortActionPerformed(ActionEvent e) {
 124  0 if (_fr != null) {
 125  0 try {
 126  0 _fr.close();
 127    }
 128    catch(IOException ioe) { /* ignore, just stop polling */ }
 129  0 _fr = null;
 130  0 updateButtons();
 131    }
 132    }
 133   
 134    /** Update button state and text. Should be overridden if additional buttons are added besides "Go To", "Remove" and "Remove All". */
 135  0 protected void updateButtons() {
 136  0 _abortButton.setEnabled(_fr != null);
 137  0 _updateNowButton.setEnabled(_fr != null);
 138  0 _restartButton.setEnabled(_fr == null);
 139    }
 140   
 141    /** Creates the buttons for controlling the regions. Should be overridden. */
 142  0 protected JComponent[] makeButtons() {
 143  0 _updateNowButton = new JButton("Update");
 144  0 _updateNowButton.addActionListener(new ActionListener() {
 145  0 public void actionPerformed(ActionEvent e) { updateText(); }
 146    });
 147  0 _restartButton = new JButton("Restart");
 148  0 _restartButton.addActionListener(new ActionListener() {
 149  0 public void actionPerformed(ActionEvent e) { restartFollowing(); }
 150    });
 151  0 _restartButton.setEnabled(false);
 152  0 return new JComponent[] { _updateNowButton, _restartButton };
 153    }
 154   
 155    /** Restart following this file. */
 156  0 protected void restartFollowing() {
 157  0 _textArea.setText("");
 158  0 initThread(_f);
 159  0 updateText();
 160    }
 161   
 162    /** Update the text area if there is new text in the file.
 163    * May not read all new text if there is too much, as that would
 164    * block the event thread for too long. */
 165  0 protected void updateText() {
 166  0 Utilities.invokeLater(new Runnable() {
 167  0 public void run() {
 168    // MainFrame.LOG.log("updateText");
 169  0 if ((_fr != null) &&
 170    (_updateNowButton.isEnabled())) {
 171  0 _updateNowButton.setEnabled(false);
 172  0 int changeCount = 0;
 173  0 long newSize = _f.length();
 174  0 if (_totalRead!=newSize) {
 175  0 if (_totalRead>newSize) {
 176    // must start over, file got smaller!
 177  0 _textArea.setText("");
 178  0 _totalRead = 0;
 179    }
 180  0 StringBuilder sb = new StringBuilder(_textArea.getText());
 181    // MainFrame.LOG.log("\tgot text");
 182  0 try {
 183  0 _fr.close();
 184  0 _fr = new FileReader(_f);
 185  0 _fr.skip(_totalRead);
 186    // MainFrame.LOG.log("\treading... skipped to " + _totalRead);
 187    // abort after reading 5 blocks (50 kB), read more later
 188    // don't block the event thread any longer
 189  0 while((changeCount<=BUFFER_READS_PER_TIMER) && ((_red = _fr.read(_buf)) >= 0)) {
 190    // MainFrame.LOG.log("\tread " + _red + " bytes");
 191  0 _totalRead += _red;
 192  0 sb.append(new String(_buf, 0, _red));
 193  0 ++changeCount;
 194    }
 195  0 if ((_red > 0) && (changeCount<BUFFER_READS_PER_TIMER)) {
 196  0 _totalRead += _red;
 197  0 sb.append(new String(_buf, 0, _red));
 198  0 ++changeCount;
 199    }
 200    }
 201    catch(IOException ioe) {
 202    // MainFrame.LOG.log("\taborted");
 203    // stop polling
 204  0 sb.append("\n\nI/O Exception reading file " + _f + "\n");
 205  0 ++changeCount;
 206  0 abortActionPerformed(null);
 207    }
 208    finally {
 209  0 if (changeCount > 0) {
 210    // MainFrame.LOG.log("\tsetting text");
 211  0 _textArea.setText(sb.toString());
 212  0 int maxLines = edu.rice.cs.drjava.DrJava.getConfig().
 213    getSetting(edu.rice.cs.drjava.config.OptionConstants.FOLLOW_FILE_LINES);
 214  0 if (maxLines > 0) { // if maxLines is 0, buffer is unlimited
 215  0 try {
 216  0 int start = 0;
 217  0 int len = _textArea.getText().length();
 218  0 int curLines = _textArea.getLineCount();
 219  0 if (curLines>maxLines) {
 220  0 start = _textArea.getLineStartOffset(curLines-maxLines);
 221  0 len -= start;
 222  0 sb = new StringBuilder(_textArea.getText(start,len));
 223  0 _textArea.setText(sb.toString());
 224    }
 225    }
 226    catch(javax.swing.text.BadLocationException e) { /* ignore, do not truncate */ }
 227    }
 228    // MainFrame.LOG.log("\ttext length = " + s.length());
 229    }
 230    }
 231    }
 232    }
 233    // MainFrame.LOG.log("\tupdating buttons");
 234  0 updateButtons();
 235    }
 236    });
 237    }
 238    }