/* * Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ /* * ConsolePanel.java * * Created on 14-May-2011, 6:08:48 PM */ package mage.server.console; import mage.remote.Session; import mage.view.TableView; import mage.view.UserView; import org.apache.log4j.Logger; import javax.swing.*; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableRowSorter; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import static javax.swing.JTable.AUTO_RESIZE_NEXT_COLUMN; import static javax.swing.JTable.AUTO_RESIZE_OFF; /** * @author BetaSteward_at_googlemail.com */ public class ConsolePanel extends javax.swing.JPanel { private static final Logger logger = Logger.getLogger(ConsolePanel.class); private final TableUserModel tableUserModel; private final TableTableModel tableTableModel; private UpdateUsersTask updateUsersTask; private UpdateTablesTask updateTablesTask; /** * Creates new form ConsolePanel */ public ConsolePanel() { this.tableUserModel = new TableUserModel(); this.tableTableModel = new TableTableModel(); initComponents(); spinnerMuteDurationMinutes.setValue(60); this.tblUsers.createDefaultColumnsFromModel(); this.tblUsers.setRowSorter(new TableRowSorter(tableUserModel)); this.tblUsers.setAutoResizeMode(AUTO_RESIZE_OFF); this.tblTables.createDefaultColumnsFromModel(); this.tblTables.setRowSorter(new TableRowSorter(tableTableModel)); this.tblUsers.setAutoResizeMode(AUTO_RESIZE_NEXT_COLUMN); } public void update(List<UserView> users) { int row = this.tblUsers.getSelectedRow(); tableUserModel.loadData(users); this.tblUsers.repaint(); this.tblUsers.getSelectionModel().setSelectionInterval(row, row); } public void update(Collection<TableView> tables) { int row = this.tblTables.getSelectedRow(); tableTableModel.loadData(tables); this.tblTables.repaint(); this.tblTables.getSelectionModel().setSelectionInterval(row, row); } public void start() { updateUsersTask = new UpdateUsersTask(ConsoleFrame.getSession(), this); updateTablesTask = new UpdateTablesTask(ConsoleFrame.getSession(), ConsoleFrame.getSession().getMainRoomId(), this); updateUsersTask.execute(); updateTablesTask.execute(); } public void stop() { if (updateUsersTask != null && !updateUsersTask.isDone()) { updateUsersTask.cancel(true); } if (updateTablesTask != null && !updateTablesTask.isDone()) { updateTablesTask.cancel(true); } } /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always * regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { jSplitPane1 = new javax.swing.JSplitPane(); jPanel1 = new javax.swing.JPanel(); jPanel3 = new javax.swing.JPanel(); jScrollPane1 = new javax.swing.JScrollPane(); tblUsers = new javax.swing.JTable(); jPanel4 = new javax.swing.JPanel(); btnDisconnect = new javax.swing.JButton(); btnEndSession = new javax.swing.JButton(); btnMuteUser = new javax.swing.JButton(); btnDeActivate = new javax.swing.JButton(); btnLockUser = new javax.swing.JButton(); lblMinutes = new javax.swing.JLabel(); spinnerMuteDurationMinutes = new javax.swing.JSpinner(); jPanel2 = new javax.swing.JPanel(); jPanel5 = new javax.swing.JPanel(); jScrollPane2 = new javax.swing.JScrollPane(); tblTables = new javax.swing.JTable(); jPanel6 = new javax.swing.JPanel(); btnRemoveTable = new javax.swing.JButton(); jSplitPane1.setDividerLocation(250); jSplitPane1.setResizeWeight(0.5); tblUsers.setModel(tableUserModel); jScrollPane1.setViewportView(tblUsers); javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); jPanel3.setLayout(jPanel3Layout); jPanel3Layout.setHorizontalGroup( jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) ); jPanel3Layout.setVerticalGroup( jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 339, Short.MAX_VALUE) ); jPanel4.setVerifyInputWhenFocusTarget(false); btnDisconnect.setText("Disconnect"); btnDisconnect.addActionListener(evt -> btnDisconnectActionPerformed(evt)); btnEndSession.setText("End session"); btnEndSession.addActionListener(evt -> btnEndSessionActionPerformed(evt)); btnMuteUser.setText("Mute user"); btnMuteUser.setActionCommand("Mute 1h"); btnMuteUser.addActionListener(evt -> btnMuteUserActionPerformed(evt)); btnDeActivate.setText("(de)activate"); btnDeActivate.setActionCommand("Mute 1h"); btnDeActivate.addActionListener(evt -> btnDeActivateActionPerformed(evt)); btnLockUser.setText("Lock user"); btnLockUser.setActionCommand("Mute 1h"); btnLockUser.addActionListener(evt -> btnLockUserActionPerformed(evt)); lblMinutes.setText("Minutes"); javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4); jPanel4.setLayout(jPanel4Layout); jPanel4Layout.setHorizontalGroup( jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel4Layout.createSequentialGroup() .addContainerGap() .addComponent(btnDisconnect) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addGroup(jPanel4Layout.createSequentialGroup() .addComponent(btnEndSession) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(btnMuteUser)) .addGroup(jPanel4Layout.createSequentialGroup() .addComponent(btnDeActivate) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(btnLockUser, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(lblMinutes) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(spinnerMuteDurationMinutes, javax.swing.GroupLayout.PREFERRED_SIZE, 64, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); jPanel4Layout.setVerticalGroup( jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel4Layout.createSequentialGroup() .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel4Layout.createSequentialGroup() .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(btnDisconnect) .addComponent(btnEndSession) .addComponent(btnMuteUser)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(btnDeActivate) .addComponent(btnLockUser))) .addGroup(jPanel4Layout.createSequentialGroup() .addGap(16, 16, 16) .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(lblMinutes) .addComponent(spinnerMuteDurationMinutes, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))) .addContainerGap()) ); javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGap(0, 0, 0) .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, 57, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(0, 0, 0)) ); jSplitPane1.setLeftComponent(jPanel1); tblTables.setModel(tableTableModel); jScrollPane2.setViewportView(tblTables); javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5); jPanel5.setLayout(jPanel5Layout); jPanel5Layout.setHorizontalGroup( jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 453, Short.MAX_VALUE) ); jPanel5Layout.setVerticalGroup( jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 340, Short.MAX_VALUE) ); btnRemoveTable.setText("Remove Table"); btnRemoveTable.addActionListener(evt -> btnRemoveTableActionPerformed(evt)); javax.swing.GroupLayout jPanel6Layout = new javax.swing.GroupLayout(jPanel6); jPanel6.setLayout(jPanel6Layout); jPanel6Layout.setHorizontalGroup( jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel6Layout.createSequentialGroup() .addContainerGap() .addComponent(btnRemoveTable) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); jPanel6Layout.setVerticalGroup( jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel6Layout.createSequentialGroup() .addComponent(btnRemoveTable) .addContainerGap(31, Short.MAX_VALUE)) ); javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); jPanel2.setLayout(jPanel2Layout); jPanel2Layout.setHorizontalGroup( jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jPanel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jPanel6, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); jPanel2Layout.setVerticalGroup( jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup() .addComponent(jPanel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGap(0, 0, 0) .addComponent(jPanel6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) ); jSplitPane1.setRightComponent(jPanel2); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jSplitPane1, javax.swing.GroupLayout.Alignment.TRAILING) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jSplitPane1, javax.swing.GroupLayout.Alignment.TRAILING) ); }// </editor-fold>//GEN-END:initComponents private void btnDisconnectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDisconnectActionPerformed int row = this.tblUsers.convertRowIndexToModel(tblUsers.getSelectedRow()); ConsoleFrame.getSession().disconnectUser((String) tableUserModel.getValueAt(row, TableUserModel.POS_SESSION_ID)); }//GEN-LAST:event_btnDisconnectActionPerformed private void btnRemoveTableActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRemoveTableActionPerformed int row = this.tblTables.convertRowIndexToModel(tblTables.getSelectedRow()); ConsoleFrame.getSession().removeTable((UUID) tableTableModel.getValueAt(row, 7)); }//GEN-LAST:event_btnRemoveTableActionPerformed private void btnEndSessionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnEndSessionActionPerformed int row = this.tblUsers.convertRowIndexToModel(tblUsers.getSelectedRow()); ConsoleFrame.getSession().endUserSession((String) tableUserModel.getValueAt(row, TableUserModel.POS_GAME_INFO)); }//GEN-LAST:event_btnEndSessionActionPerformed private void btnMuteUserActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnMuteUserActionPerformed int row = this.tblUsers.convertRowIndexToModel(tblUsers.getSelectedRow()); ConsoleFrame.getSession().muteUserChat((String) tableUserModel.getValueAt(row, TableUserModel.POS_USER_NAME), ((Number) spinnerMuteDurationMinutes.getValue()).longValue()); }//GEN-LAST:event_btnMuteUserActionPerformed private void btnDeActivateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeActivateActionPerformed int row = this.tblUsers.convertRowIndexToModel(tblUsers.getSelectedRow()); ConsoleFrame.getSession().toggleActivation((String) tableUserModel.getValueAt(row, TableUserModel.POS_USER_NAME)); }//GEN-LAST:event_btnDeActivateActionPerformed private void btnLockUserActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnLockUserActionPerformed int row = this.tblUsers.convertRowIndexToModel(tblUsers.getSelectedRow()); ConsoleFrame.getSession().lockUser((String) tableUserModel.getValueAt(row, TableUserModel.POS_USER_NAME), ((Number) spinnerMuteDurationMinutes.getValue()).longValue()); }//GEN-LAST:event_btnLockUserActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton btnDeActivate; private javax.swing.JButton btnDisconnect; private javax.swing.JButton btnEndSession; private javax.swing.JButton btnLockUser; private javax.swing.JButton btnMuteUser; private javax.swing.JButton btnRemoveTable; private javax.swing.JPanel jPanel1; private javax.swing.JPanel jPanel2; private javax.swing.JPanel jPanel3; private javax.swing.JPanel jPanel4; private javax.swing.JPanel jPanel5; private javax.swing.JPanel jPanel6; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane2; private javax.swing.JSplitPane jSplitPane1; private javax.swing.JLabel lblMinutes; private javax.swing.JSpinner spinnerMuteDurationMinutes; private javax.swing.JTable tblTables; private javax.swing.JTable tblUsers; // End of variables declaration//GEN-END:variables } class TableUserModel extends AbstractTableModel { public static final int POS_USER_NAME = 0; public static final int POS_HOST = 1; public static final int POS_TIME_CONNECTED = 2; public static final int POS_SESSION_ID = 3; public static final int POS_GAME_INFO = 4; public static final int POS_USER_STATE = 5; public static final int POS_CHAT_MUTE = 6; public static final int POS_CLIENT_VERSION = 7; private final String[] columnNames = new String[]{"User Name", "Host", "Time Connected", "SessionId", "Gameinfo", "User state", "Chat mute", "Client Version"}; private UserView[] users = new UserView[0]; private static final DateFormat formatterTime = new SimpleDateFormat("HH:mm:ss"); private static final DateFormat formatterTimeStamp = new SimpleDateFormat("yy-M-dd HH:mm:ss"); public void loadData(List<UserView> users) { this.users = users.toArray(new UserView[0]); this.fireTableDataChanged(); } @Override public int getRowCount() { return users.length; } @Override public int getColumnCount() { return columnNames.length; } @Override public Object getValueAt(int arg0, int arg1) { switch (arg1) { case POS_USER_NAME: return users[arg0].getUserName(); case POS_HOST: return users[arg0].getHost(); case POS_TIME_CONNECTED: return formatterTime.format(users[arg0].getTimeConnected()); case POS_SESSION_ID: return users[arg0].getSessionId(); case POS_GAME_INFO: return users[arg0].getGameInfo(); case POS_USER_STATE: return users[arg0].getUserState(); case POS_CHAT_MUTE: if (users[arg0].getMuteChatUntil() == null) { return ""; } return formatterTimeStamp.format(users[arg0].getMuteChatUntil()); case POS_CLIENT_VERSION: return users[arg0].getClientVersion(); } return ""; } @Override public String getColumnName(int columnIndex) { String colName = ""; if (columnIndex <= getColumnCount()) { colName = columnNames[columnIndex]; } return colName; } @Override public Class getColumnClass(int columnIndex) { return String.class; } @Override public boolean isCellEditable(int rowIndex, int columnIndex) { return false; } } class TableTableModel extends AbstractTableModel { private final String[] columnNames = new String[]{"Table Name", "Owner", "Game Type", "Deck Type", "Status"}; private TableView[] tables = new TableView[0]; public void loadData(Collection<TableView> tables) { this.tables = tables.toArray(new TableView[0]); this.fireTableDataChanged(); } @Override public int getRowCount() { return tables.length; } @Override public int getColumnCount() { return columnNames.length; } @Override public Object getValueAt(int arg0, int arg1) { switch (arg1) { case 0: return tables[arg0].getTableName(); case 1: return tables[arg0].getControllerName(); case 2: return tables[arg0].getGameType(); case 3: return tables[arg0].getDeckType(); case 4: return tables[arg0].getTableState().toString(); case 5: return tables[arg0].isTournament(); case 6: if (!tables[arg0].getGames().isEmpty()) { return tables[arg0].getGames().get(0); } return null; case 7: return tables[arg0].getTableId(); } return ""; } @Override public String getColumnName(int columnIndex) { String colName = ""; if (columnIndex <= getColumnCount()) { colName = columnNames[columnIndex]; } return colName; } @Override public Class getColumnClass(int columnIndex) { return String.class; } @Override public boolean isCellEditable(int rowIndex, int columnIndex) { if (columnIndex != 5) { return false; } return true; } } class UpdateUsersTask extends SwingWorker<Void, List<UserView>> { private final Session session; private final ConsolePanel panel; private List<UserView> previousUsers; private static final Logger logger = Logger.getLogger(UpdateUsersTask.class); Map<String, String> peopleIps = new HashMap<>(); UpdateUsersTask(Session session, ConsolePanel panel) { this.session = session; this.panel = panel; } @Override protected Void doInBackground() throws Exception { while (!isCancelled()) { List<UserView> users = session.getUsers(); if (previousUsers == null || checkUserListChanged(users)) { logger.debug("Need to update the user list"); this.publish(users); previousUsers = users; } Thread.sleep(2000); } return null; } private boolean checkUserListChanged(List<UserView> usersToCheck) { if (previousUsers == null || usersToCheck == null) { return true; } if (previousUsers.size() != usersToCheck.size()) { // new user appeared return true; } for (UserView u1 : previousUsers) { boolean found = false; for (UserView u2 : usersToCheck) { if (u1.getUserName().equals(u2.getUserName())) { found = true; String s = u1.getUserName() + ',' + u1.getHost(); if (peopleIps.get(s) == null) { logger.warn("Found new user: " + u1.getUserName() + ',' + u1.getHost()); peopleIps.put(s, "1"); } s = u2.getUserName() + ',' + u2.getHost(); if (peopleIps.get(s) == null) { logger.warn("Found new user: " + u1.getUserName() + ',' + u1.getHost()); peopleIps.put(s, "1"); } break; } } if (!found) { // some new user replaced old one return true; } } // seems nothing has been changed return false; } @Override protected void process(List<List<UserView>> view) { panel.update(view.get(0)); } @Override protected void done() { try { get(); } catch (InterruptedException ex) { logger.fatal("Update Users Task error", ex); } catch (ExecutionException ex) { logger.fatal("Update Users Task error", ex); } catch (CancellationException ex) { } } } class UpdateTablesTask extends SwingWorker<Void, Collection<TableView>> { private final Session session; private final UUID roomId; private final ConsolePanel panel; private static final Logger logger = Logger.getLogger(UpdateTablesTask.class); UpdateTablesTask(Session session, UUID roomId, ConsolePanel panel) { this.session = session; this.roomId = roomId; this.panel = panel; } @Override protected Void doInBackground() throws Exception { while (!isCancelled()) { this.publish(session.getTables(roomId)); Thread.sleep(3000); } return null; } @Override protected void process(List<Collection<TableView>> view) { panel.update(view.get(0)); } @Override protected void done() { try { get(); } catch (InterruptedException ex) { logger.fatal("Update Tables Task error", ex); } catch (ExecutionException ex) { logger.fatal("Update Tables Task error", ex); } catch (CancellationException ex) { } } }