Логин:   Пароль:




Новости
Рассылки
Форум
Поиск


Java
- Апплеты
- Вопрос-ответ
- Классы
- Примеры
- Руководства
- Статьи
- IDE
- Словарь терминов
- Скачать

Мобильная Java
- Игры
- Примеры
- Статьи
- WAP, WML и пр.

JavaScript
- Вопрос-ответ
- Примеры
- Статьи

Веб-мастеринг
- HTML
- CSS
- SSI

Разминка для ума
Проекты
Книги
Ссылки
Программы
Юмор :)




Rambler's Top100

Java: ПримерыПриложение - проверяльщик отвечаемости WEB-сайтов с минимальной статистикой

Приложение - проверяльщик отвечаемости 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-Архив с исходниками


Д. Гудман
"JavaScript и DHTML. Сборник рецептов. Для профессионалов"
Подробнее>>
Заказать>>


Х. М. Дейтел, П. Дж. Дейтел
"Как программировать на Java. Книга 2. Файлы, сети, базы данных"
Подробнее>>
Заказать>>

Узнай о чем ты на самом деле сейчас думаешь тут.


[an error occurred while processing this directive]



Apache Struts 2.0.11
Apache MyFaces Trinidad Core 1.2.3.
Sun переводит мобильные устройства с Java ME на Java SE
Хакерская атака!