Приложение - проверяльщик отвечаемости WEB-сайтов с минимальной статистикой
Многопоточное GUI приложение, задача которого - читать по http указанные файлы (может быть неограничено). Есть возможность запуска и остановки процесса, протоколирование в файл, времени прочтения указанного файла, а так же результат этого прочтения (если возникает ошибка, указывается, какая именно). Последние результаты для всех файлов выводятся на экран в таблицу. Другими словами это приложение - проверяльщик отвечаемости WEB сайтов с минимальной статистикой.
jar-Архивzip-Архив с исходниками
Класс реализующий GUI
package filescheck; /** * Title: Класс реализующий GUI. * Description: * Copyright: Yura Ladik Copyright (c) 2002 * Company: * @author Yura Ladik * @version 0.1 */ import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.border.*; import java.beans.*; import java.util.Vector; import javax.swing.table.*; import javax.swing.text.*; import java.io.*; public class FilesCheck extends JFrame { Vector arrThread = new Vector(); // Массив потоков FilesCheckConnection // Компоненты графического пользовательского интерфейса JPanel contentPane; BorderLayout borderLayout1 = new BorderLayout(); JToolBar toolBar = new JToolBar(); JScrollPane jScrollPane1 = new JScrollPane(); JLabel statusBar = new JLabel(" No URL"); String[] columnNames = {"Status", "File name", "Size","Completed","Percent","Start Time","End Time","URL"}; JTable jTable =new JTable(new DefaultTableModel(columnNames,0)); JTextArea jTextArea1 = new JTextArea(); JTextField stringURL = new JTextField(); JButton button1 = new JButton(); JButton button2 = new JButton(); JButton button3 = new JButton(); JButton button4 = new JButton(); JButton button5 = new JButton(); /**Construct the frame*/ public FilesCheck() { enableEvents(AWTEvent.WINDOW_EVENT_MASK); try { jbInit(); } catch(Exception e) { e.printStackTrace(); } } /**Component initialization*/ private void jbInit() throws Exception { contentPane = (JPanel) this.getContentPane(); contentPane.setLayout(borderLayout1); this.setSize(new Dimension(640,480)); this.setTitle("FilesCheck"); // Загрузка изображений ImageIcon image1 = new ImageIcon(getToolkit().createImage("images/add.gif")); ImageIcon image2 = new ImageIcon(getToolkit().createImage("images/play.gif")); ImageIcon image3 = new ImageIcon(getToolkit().createImage("images/pause.gif")); ImageIcon image4 = new ImageIcon(getToolkit().createImage("images/delete.gif")); ImageIcon image5 = new ImageIcon(getToolkit().createImage("images/report.gif")); // Установка обработчиков событий jTable.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(MouseEvent e) { jTable_mouseClicked(e); } }); button1.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { button1_actionPerformed(e); } }); button2.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { button2_actionPerformed(e); } }); button3.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { button3_actionPerformed(e); } }); button4.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { button4_actionPerformed(e); } }); button5.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { button5_actionPerformed(e); } }); contentPane.add(toolBar, BorderLayout.NORTH); contentPane.add(statusBar, BorderLayout.SOUTH); contentPane.add(jScrollPane1, BorderLayout.CENTER); jScrollPane1.setBackground(Color.white); button1.setIcon(image1); button1.setToolTipText("Add"); button2.setIcon(image2); button2.setToolTipText("Start"); button3.setIcon(image3); button3.setToolTipText("Pause"); button4.setIcon(image4); button4.setToolTipText("Delete"); button5.setIcon(image5); button5.setToolTipText("View report file"); toolBar.add(stringURL); toolBar.add(button1); toolBar.add(button2); toolBar.add(button3); toolBar.add(button4); toolBar.add(button5); jTable.setSelectionMode(0); jTable.setEnabled(false); button2.setEnabled(false); button3.setEnabled(false); button4.setEnabled(false); jScrollPane1.getViewport().add(jTable); readReportFile(); // Считываем файл репорта } /**Overridden so we can exit when window is closed*/ protected void processWindowEvent(WindowEvent e) { super.processWindowEvent(e); if (e.getID() == WindowEvent.WINDOW_CLOSING) { FilesCheckConnection fcc; for(int i = 0; i < arrThread.size(); i++) { fcc=(FilesCheckConnection)arrThread.elementAt(i); fcc=null; } System.exit(0); } } /**Выполняется по щелчку мыши на таблице. Производится выбор строки и активация кнопок управления.*/ void jTable_mouseClicked(MouseEvent e) { jTable.addRowSelectionInterval(jTable.rowAtPoint(e.getPoint()), jTable.rowAtPoint(e.getPoint())); if(jTable.getSelectedRow() > -1) { button4.setEnabled(true); FilesCheckConnection fcc = (FilesCheckConnection)arrThread. elementAt(jTable.getSelectedRow()); // Меняем активность кнопок if(fcc.isStopThread()) { button3.setEnabled(false); button3.setEnabled(false); } else { if(fcc.isStartThread()) { button2.setEnabled(false); button3.setEnabled(true); } else { button2.setEnabled(true); button3.setEnabled(false); } } } } /** * Выполняется по нажатию кнопки button1 (Add). * Производится добавление * нового потока для скачивания файла по заданному URL. * Перестраиваеи таблицу. */ void button1_actionPerformed(ActionEvent e) { try { TableModel tm = new DefaultTableModel(columnNames,arrThread.size()+1); jTable.setModel(tm); FilesCheckConnection fcc = new FilesCheckConnection(this, stringURL.getText()); arrThread.add(fcc); fcc.start(); updadeTable(); // Обновляем таблицу } catch(Exception ee) { System.out.println("Error: "+ee); } } /** * Выполняется по нажатию кнопки button2 (Start). Стартуем поток. */ void button2_actionPerformed(ActionEvent e) { if(jTable.getSelectedRow() > -1) { FilesCheckConnection fcc = (FilesCheckConnection)arrThread. elementAt(jTable.getSelectedRow()); fcc.setStartThread(true); //Стартуем поток. // Меняем активность кнопок button2.setEnabled(false); button3.setEnabled(true); } } /** * Выполняется по нажатию кнопки button3 (Pause). Приостановка потока. */ void button3_actionPerformed(ActionEvent e) { if(jTable.getSelectedRow() > -1) { FilesCheckConnection fcc = (FilesCheckConnection)arrThread. elementAt(jTable.getSelectedRow()); fcc.setStartThread(false); //Приостановка потока // Меняем активность кнопок button2.setEnabled(true); button3.setEnabled(false); } } /** * Выполняется по нажатию кнопки button4 (Delete). * Удоляем поток и перестраиваем таблицу. */ void button4_actionPerformed(ActionEvent e) { FilesCheckConnection fcc = (FilesCheckConnection)arrThread. elementAt(jTable.getSelectedRow()); fcc = null; arrThread.remove(jTable.getSelectedRow()); TableModel tm = new DefaultTableModel(columnNames,arrThread.size()); jTable.setModel(tm); updadeTable(); // Обновляем таблицу } /** * Выполняется по нажатию кнопки button5 (View report File). * Создаём форму файла репорта. */ void button5_actionPerformed(ActionEvent e) { JFrame jf = new JFrame("Report File"); JScrollPane jScrollPane2 = new JScrollPane(); jScrollPane2.getViewport().add(jTextArea1); jf.getContentPane().add(jScrollPane2); jf.setSize(640,480); jf.setVisible(true); } /** * Сохраняет данные о завершении закачки или об ошибке в файл репорта. */ public synchronized void saveToReport(FilesCheckConnection fcc) { String msg = ""+fcc.getStartTime()+" | "; msg += fcc.getEndDate()+" | "; msg += fcc.getFileURL()+" | "; msg += ""+fcc.getSize()+" | "; msg += fcc.getStatusString()+" | "; msg += fcc.getError()+'\n'; jTextArea1.append(msg); saveReportFile(); } /** * Сохраняет файл репорта. */ public synchronized boolean saveReportFile() { try { // Open file File file = new File ("report.txt"); // Create an output writer that will write to that file. // FileWriter handles international characters encoding conversions. FileWriter out = new FileWriter(file); String text = jTextArea1.getText(); out.write(text); out.close(); return true; } catch (IOException e) { statusBar.setText("Error saving report file."); } return false; } /** * Считывет данные из файла репорта. */ public void readReportFile() { try { // Open file. File file = new File("report.txt"); // Get the size of the opened file. int size = (int)file.length(); // Set to zero a counter for counting the number of // characters that have been read from the file. int chars_read = 0; // Create an input reader based on the file, so we can read its data. // FileReader handles international character encoding conversions. FileReader in = new FileReader(file); // Create a character array of the size of the file, // to use as a data buffer, into which we will read // the text data. char[] data = new char[size]; // Read all available characters into the buffer. while(in.ready()) { // Increment the count for each character read, // and accumulate them in the data buffer. chars_read += in.read(data, chars_read, size - chars_read); } in.close(); // Create a temporary string containing the data, // and set the string into the JTextArea. jTextArea1.setText(new String(data, 0, chars_read)); } catch (IOException e) { statusBar.setText("Error opening report file."); } } /** * Обновляет таблицу содержащею данные, изменяющиеся в реальном времени. * Изменяем модель таблицы по умолчанию. */ public synchronized void updadeTable() { int index=arrThread.size(); for(int i = 0;i<index;i++) { FilesCheckConnection fcc = (FilesCheckConnection)arrThread.elementAt(i); updadeInfo(fcc); } // Новая модель таблицы DefaultTableCellRenderer colorRenderer = new DefaultTableCellRenderer() { public void setValue(Object value) { if (value instanceof ColoredColumn) { ColoredColumn cc = (ColoredColumn) value; setBackground(cc.getBGColor()); setForeground(cc.getFGColor()); setText(cc.getText()); } else { super.setValue(value); } } }; TableColumn colorColumn = jTable.getColumn("Status"); colorColumn.setCellRenderer(colorRenderer); jTable.getColumnModel().getColumn(0).setMaxWidth(80); jTable.getColumnModel().getColumn(0).setPreferredWidth(80); jTable.setEnabled(false); jTable.setSelectionMode(0); } /** * Обновляем данные о потоке в таблице. */ public synchronized void updadeInfo(FilesCheckConnection fcc) { ColoredColumn cc = new ColoredColumn("No starting",Color.white,Color.black); if(fcc.getStatus() == FilesCheckConnection.STATUS_DOWLOADING)cc = new ColoredColumn("Downloading",Color.white,Color.blue); else if(fcc.getStatus() == FilesCheckConnection.STATUS_DOWLOADING_FINISH)cc = new ColoredColumn("Complete",Color.green,Color.black); else if(fcc.getStatus() == FilesCheckConnection.STATUS_DOWLOADING_PAUSE)cc = new ColoredColumn("Pause",Color.yellow,Color.black); else if(fcc.getStatus() == FilesCheckConnection.STATUS_ERROR)cc = new ColoredColumn("Error",Color.red,Color.black); else if(fcc.getStatus() == FilesCheckConnection.STATUS_STARTING)cc = new ColoredColumn("Starting",Color.white,Color.green); int index=arrThread.indexOf(fcc); jTable.setValueAt(cc,index,0); jTable.setValueAt(fcc.getFileName(),index,1); jTable.setValueAt(""+fcc.getSize(),index,2); jTable.setValueAt(""+fcc.getCopmleted(),index,3); jTable.setValueAt(""+fcc.getPercent()+"%",index,4); jTable.setValueAt(fcc.getStartTime(),index,5); jTable.setValueAt(fcc.getEndDate(),index,6); jTable.setValueAt(fcc.getFileURL(),index,7); } }
Класс реализующий поток считывания файла по заданному URL
package filescheck; /** * Title: Поток считывания файла по заданному URL. * Description: Используется для считывания файла по заданному URL, * мониторинга процесса загрузки и протоколирования в файл. * Copyright: Yura Ladik Copyright (c) 2002 * Company: * @author Yura Ladik * @version 0.1 */ import java.net.URL; import java.net.URLConnection; import java.util.Date; import java.io.*; public class FilesCheckConnection extends Thread { private FilesCheck filesCheck;// Основная форма // Переменные текущего статуса потока public static int STATUS_ERROR = -1; // Статус ошибки public static int STATUS_NOSTARTED = 0; // Статус невозможности старта public static int STATUS_DOWLOADING = 1; // Статус загрузки public static int STATUS_DOWLOADING_FINISH = 2; // Статус успешной загрузки public static int STATUS_DOWLOADING_PAUSE = 3; // Статус режима пауза public static int STATUS_DELETED = 4; // Статус удаления public static int STATUS_STARTING = 5; // Статус начала загрузки // Переменные описывающее данный URL и поток private String error = ""; private int status = 0; private String fileName = ""; private long size = 0; private long completed = 0; private byte percent = 0; private Date startTime; private Date endTime; private URL fileURL; private boolean startThread; private boolean stopThread; /** * Конструктор FilesCheckConnection * * @param Основная форма */ public FilesCheckConnection(FilesCheck filesCheck) { this.filesCheck = filesCheck; } /** * Конструктор FilesCheckConnection */ public FilesCheckConnection(FilesCheck filesCheck, String fileURL) { this.filesCheck = filesCheck; try {// Проверяем наличие файла и правильность URL. this.fileURL = new URL(fileURL); synchronized(filesCheck.statusBar) { filesCheck.statusBar.setText("Adding URL successful"); status=STATUS_STARTING; // Указываем что загрузка началась. } } catch(Exception e) { synchronized(filesCheck.statusBar) { filesCheck.statusBar.setText("Error adding URL:"+e); } // Указываем что загрузка прервалась с ошибкой status = STATUS_ERROR; error= ""+e; // Обновляем информацию в таблице на основной форме filesCheck.updadeInfo(this); } } public void run() { if(fileURL != null) { // Обновляем информацию в таблице на основной форме filesCheck.updadeInfo(this); startThread=true; // Старт потока URLConnection connection; try { connection = fileURL.openConnection(); // Открываем соединение fileName = fileURL.getFile(); size = connection.getContentLength(); // Размер файла startTime = new Date(); // Текущая дата (старта) synchronized(filesCheck.statusBar) { filesCheck.statusBar.setText(""+startTime.toString()); } // Обновляем информацию в таблице на основной форме filesCheck.updadeInfo(this); } catch(Exception e) { status = STATUS_ERROR; // Статус ошибки error = ""+e; // Сохраняем данные о ошибке в файл репорта filesCheck.saveToReport(this); } try { // Входной поток InputStream in = fileURL.openConnection().getInputStream(); status = STATUS_DOWLOADING; // Статус загрузки int sizef = (int)size; int chars_read = 0; byte[] data = new byte[sizef]; // Обновляем информацию в таблице на основной форме filesCheck.updadeInfo(this); // Начинаем считывание данных из файла Date dd=new Date(); long ccc=dd.getTime(); while(completed != size) { synchronized(this) { while (!startThread) wait(100); //Режим паузы } data[(int)completed] = (byte)in.read(); // Считываем из потока побайтно completed++; // Прочитано байт percent=(byte)(completed/(size/100)); // Процент загрузки if(ccc>dd.getTime()+1) { ccc=dd.getTime(); // Обновляем информацию в таблице на основной форме filesCheck.updadeInfo(this); } } in.close(); // Закрываем поток endTime = new Date(); // Текущая дата (конец загрузки) status = STATUS_DOWLOADING_FINISH; // Статус успешной загрузки // Обновляем информацию в таблице на основной форме filesCheck.updadeInfo(this); // Сохраняем данные о успешной загрузке в файл репорта filesCheck.saveToReport(this); } catch(Exception e) { status = STATUS_ERROR; error = ""+e; // Сохраняем данные о ошибке в файл репорта filesCheck.saveToReport(this); } } stopThread=true; // Поток остановлен } /** * Возвращает текущий статус потока */ public int getStatus() { return status; } /** * Возвращает текущий статус потока строкой */ public String getStatusString() { switch(getStatus()) { case -1: return "STATUS_ERROR"; case 0: return "STATUS_NOSTARTED"; case 1: return "STATUS_DOWLOADING"; case 2: return "STATUS_DOWLOADING_FINISH"; case 3: return "STATUS_DOWLOADING_PAUSE"; case 4: return "STATUS_DELETED"; case 5: return "STATUS_STARTING"; default: return "STATUS_STARTING"; } } /** * Возвращает имя файла */ public String getFileName() { return fileName; } /** * Возвращает размер файла */ public long getSize() { return size; } /** * Возвращает размер загруженной части файла */ public long getCopmleted() { return completed; } /** * Возвращает размер загруженной части в процентах */ public byte getPercent() { return percent; } /** * Возвращает дату старта загрузки */ public Date getStartTime() { return startTime; } /** * Возвращает дату окончания загрузки */ public Date getEndDate() { return endTime; } /** * Возвращает URL */ public String getFileURL() { return fileURL.toExternalForm(); } /** * Возвращает ошибку */ public String getError() { return error; } /** * Приостанавливает или продолжает выполнение потока */ public void setStartThread(boolean start) { startThread = start; if(start) { status = STATUS_DOWLOADING; // Статус продолжения загрузки // Устанавливаем наименьший приоритет currentThread().setPriority(Thread.MIN_PRIORITY); } else { status = STATUS_DOWLOADING_PAUSE; // Статус режима пауза //Устанавливаем нормальный приоритет currentThread().setPriority(Thread.NORM_PRIORITY); } // Обновляем информацию в таблице на основной форме filesCheck.updadeInfo(this); } /** * Возвращает истину если поток продолжает * выполнение или ложь при приостановленном потоке */ public boolean isStartThread() { return startThread; } /** * Возвращает истину если поток остановлен */ public boolean isStopThread() { return stopThread; } }
Класс реализующий цветную ячейку таблицы
package filescheck; /** * Title: Цветная ячейка таблицы. * Description: Используется в создании нового * DefaultTableCellRenderer класса. * Copyright: Yura Ladik Copyright (c) 2002 * Company: * @author Yura Ladik * @version 1.0 */ import java.awt.Color; public class ColoredColumn { private String text = ""; // Текст private Color bgcolor = Color.white; // Цвет фона ячейки private Color fgcolor = Color.black; // Цвет текста ячейки /** * Конструктор */ public ColoredColumn() { } /** * Конструктор */ public ColoredColumn(String text,Color bgcolor, Color fgcolor) { this.text = text; this.bgcolor =bgcolor; this.fgcolor = fgcolor; } /** * Устанавливает текст в ячейке */ public void setText(String text) { this.text = text; } /** * Устанавливает цвет фона ячейки */ public void setBGColor(Color bgcolor) { this.bgcolor = bgcolor; } /** * Устанавливает цвет текста ячейки */ public void setFGColor(Color fgcolor) { this.fgcolor = fgcolor; } /** * Возвращает текст ячейки */ public String getText() { return text; } /** * Возвращает цвет фона ячейки */ public Color getBGColor() { return bgcolor; } /** * Возвращает цвет текста ячейки */ public Color getFGColor() { return fgcolor; } }
Класс Application
package filescheck; import javax.swing.UIManager; import java.awt.*; public class Application { boolean packFrame = false; /**Construct the application*/ public Application() { FilesCheck frame = new FilesCheck(); //Validate frames that have preset sizes //Pack frames that have useful preferred size //info, e.g. from their layout if (packFrame) { frame.pack(); } else { frame.validate(); } //Center the window Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); Dimension frameSize = frame.getSize(); if (frameSize.height > screenSize.height) { frameSize.height = screenSize.height; } if (frameSize.width > screenSize.width) { frameSize.width = screenSize.width; } frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2); frame.setVisible(true); } /**Main method*/ public static void main(String[] args) { try { UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); } catch(Exception e) { e.printStackTrace(); } new Application(); } }jar-Архив
zip-Архив с исходниками