Package com.starlight.intrepid.gui

Source Code of com.starlight.intrepid.gui.ConnectionDebugPane$DurationRenderer

package com.starlight.intrepid.gui;

import ca.odell.glazedlists.*;
import ca.odell.glazedlists.gui.AdvancedTableFormat;
import ca.odell.glazedlists.swing.DefaultEventTableModel;
import com.starlight.intrepid.ConnectionListener;
import com.starlight.intrepid.Intrepid;
import com.starlight.intrepid.IntrepidSetup;
import com.starlight.intrepid.VMID;
import com.starlight.intrepid.auth.ConnectionArgs;
import com.starlight.intrepid.auth.UserContextInfo;
import com.starlight.thread.SharedThreadPool;
import com.starlight.ui.UIKit;

import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.text.DateFormat;
import java.util.Comparator;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;


/**
* A panel that shows the connections active in an Intrepid instance.
*/
public class ConnectionDebugPane extends JPanel implements ConnectionListener {
  private static final AtomicLong REUSED_ATOMIC_LONG = new AtomicLong();

  private final JTable table;

  private final Intrepid instance;
  private final EventList<ConnectionInfoContainer> root_list;
  private final EventList<ConnectionInfoContainer> sort_list;

  private final DisposableMap<InetSocketAddress,ConnectionInfoContainer> info_map;

  private final Timer repaint_timer = new Timer( 5000, new RepaintActionListener() );


  public ConnectionDebugPane( Intrepid instance ) {
    this.instance = instance;

    root_list = new BasicEventList<ConnectionInfoContainer>();
    sort_list = new SortedList<ConnectionInfoContainer>( root_list );
    info_map = GlazedLists.syncEventListToMap( root_list,
      new FunctionList.Function<ConnectionInfoContainer, InetSocketAddress>() {
        @Override
        public InetSocketAddress evaluate( ConnectionInfoContainer info ) {
          return info.socket_address;
        }
      } );

    instance.addConnectionListener( this );

    table = new JTable( new DefaultEventTableModel<ConnectionInfoContainer>(
      sort_list, new ConnectionTableFormat() ) );
    table.setDefaultRenderer( AtomicLong.class, new DurationRenderer() );
    table.setDefaultRenderer( InetSocketAddress.class,
      new InetSocketAddressRenderer() );
    UIKit.autosizeTableColumn( table, 0, "000.000.000.000:00000", true, 2 );
    UIKit.autosizeTableColumn( table, 2, "0000:00:00", true, 2 );
    UIKit.autosizeTableColumn( table, 3, ConnectionState.RECONNECTING, true, 2 );
    UIKit.autosizeTableColumn( table, 4, "SSL/Compress", true, 2 );

    setLayout( new BorderLayout() );

    add( new JScrollPane( table ), BorderLayout.CENTER );

    repaint_timer.start();
  }


  public void dispose() {
    instance.removeConnectionListener( this );

    repaint_timer.stop();

    info_map.dispose();
    sort_list.dispose();
  }


  @Override
  public void connectionClosed( final InetAddress host, final int port,
    final VMID source_vmid, final VMID vmid, final Object attachment,
    final boolean will_attempt_reconnect ) {

    if ( !SwingUtilities.isEventDispatchThread() ) {
      SwingUtilities.invokeLater( new Runnable() {
        @Override
        public void run() {
          connectionClosed( host, port, source_vmid, vmid, attachment,
            will_attempt_reconnect );
        }
      } );
      return;
    }

    InetSocketAddress address = new InetSocketAddress( host, port );

    final ConnectionInfoContainer info = info_map.get( address );
    if ( info == null ) return;

    if ( will_attempt_reconnect ) info.state = ConnectionState.RECONNECTING;
    else {
      info.state = ConnectionState.CLOSED;

      // Schedule the info to be removed in 15 seconds.
      SharedThreadPool.INSTANCE.schedule( new Runnable() {
        @Override
        public void run() {
          if ( !SwingUtilities.isEventDispatchThread() ) {
            SwingUtilities.invokeLater( this );
            return;
          }

          sort_list.remove( info );
        }
      }, 15, TimeUnit.SECONDS );
    }

    table.repaint();
  }

  @Override
  public void connectionOpened( final InetAddress host, final int port,
    final Object attachment, final VMID source_vmid, final VMID vmid,
    final UserContextInfo user_context, final VMID previous_vmid,
    final Object connection_type_description, final byte ack_rate_sec ) {

    if ( !SwingUtilities.isEventDispatchThread() ) {
      SwingUtilities.invokeLater( new Runnable() {
        @Override
        public void run() {
          connectionOpened( host, port, attachment, source_vmid, vmid,
            user_context,
            previous_vmid, connection_type_description, ack_rate_sec );
        }
      } );
      return;
    }

    InetSocketAddress address = new InetSocketAddress( host, port );

    ConnectionInfoContainer info = info_map.get( address );
    if ( info == null ) {
      info = new ConnectionInfoContainer();
      info.socket_address = new InetSocketAddress( host, port );

      root_list.add( info );
    }

    info.vmid = vmid;
    info.state = ConnectionState.OK;
    info.user_context = user_context;
    info.type_desc = connection_type_description;

    table.repaint();
  }

  @Override
  public void connectionOpenFailed( final InetAddress host, final int port,
    final Object attachment, final Exception error, final boolean will_retry ) {

    if ( !SwingUtilities.isEventDispatchThread() ) {
      SwingUtilities.invokeLater( new Runnable() {
        @Override
        public void run() {
          connectionOpenFailed( host, port, attachment, error, will_retry );
        }
      } );
      return;
    }

    InetSocketAddress address = new InetSocketAddress( host, port );
    final ConnectionInfoContainer info = info_map.get( address );
    if ( info == null ) return;

    if ( will_retry ) {
      info.state = ConnectionState.CONNECTING;  // Leave(?) at connecting
    }
    else {
      info.state = ConnectionState.CLOSED;

      // Schedule the info to be removed in 15 seconds.
      SharedThreadPool.INSTANCE.schedule( new Runnable() {
        @Override
        public void run() {
          if ( !SwingUtilities.isEventDispatchThread() ) {
            SwingUtilities.invokeLater( this );
            return;
          }

          sort_list.remove( info );
        }
      }, 15, TimeUnit.SECONDS );
    }

    table.repaint();
  }

  @Override
  public void connectionOpening( final InetAddress host, final int port,
    final Object attachment, final ConnectionArgs args,
    final Object connection_type_description ) {

    if ( !SwingUtilities.isEventDispatchThread() ) {
      SwingUtilities.invokeLater( new Runnable() {
        @Override
        public void run() {
          connectionOpening( host, port, attachment, args,
            connection_type_description );
        }
      } );
      return;
    }


    InetSocketAddress address = new InetSocketAddress( host, port );

    ConnectionInfoContainer info = info_map.get( address );
    if ( info != null ) {
      info.state = ConnectionState.CONNECTING;
      table.repaint();
      return;
    }

    info = new ConnectionInfoContainer();
    info.socket_address = address;
    info.state = ConnectionState.CONNECTING;
    info.type_desc = connection_type_description;

    root_list.add( info );
    repaint();
  }


  private static enum ConnectionState {
    CONNECTING,
    OK,
    RECONNECTING,
    CLOSED
  }

  private static class ConnectionInfoContainer
    implements Comparable<ConnectionInfoContainer> {

    private InetSocketAddress socket_address;
    private VMID vmid;
    private long start_time;
    private UserContextInfo user_context;
    private ConnectionState state;
    private Object type_desc;

    ConnectionInfoContainer() {
      start_time = System.currentTimeMillis();
    }

    @Override
    public int compareTo( ConnectionInfoContainer o ) {
      if ( start_time < o.start_time ) return -1;
      else if ( start_time == o.start_time ) return 0;
      else return 1;
    }
  }


  private class ConnectionTableFormat
    implements AdvancedTableFormat<ConnectionInfoContainer> {

    @Override
    public Class getColumnClass( int column ) {
      switch( column ) {
        case 0:
          return InetSocketAddress.class;
        case 1:
          return VMID.class;
        case 2:
          return AtomicLong.class;
        case 3:
          return ConnectionState.class;
        case 4:
        case 5:
          return String.class;
        default:
          assert false : "Unknown column: " + column;
          return Object.class;
      }
    }

    @Override
    public Comparator getColumnComparator( int column ) {
      return null;
    }

    @Override
    public int getColumnCount() {
      return 5;
    }

    @Override
    public String getColumnName( int column ) {
      switch( column ) {
        case 0:
          return Resources.HEADER_ADDRESS.getValue();
        case 1:
          return Resources.HEADER_VMID.getValue();
        case 2:
          return Resources.HEADER_DURATION.getValue();
        case 3:
          return Resources.HEADER_STATUS.getValue();
        case 4:
          return Resources.HEADER_TYPE.getValue();
        case 5:
          return Resources.HEADER_USER.getValue();
        default:
          assert false : "Unknown column: " + column;
          return "Unknown: " + column;
      }
    }

    @Override
    public Object getColumnValue( ConnectionInfoContainer info, int column ) {
      assert SwingUtilities.isEventDispatchThread();

      switch( column ) {
        case 0:
          return info.socket_address;
        case 1:
          return info.vmid;
        case 2:
          REUSED_ATOMIC_LONG.set( info.start_time );
          return REUSED_ATOMIC_LONG;
        case 3:
          return info.state;
        case 4:
          return info.type_desc == null ?
            null : String.valueOfinfo.type_desc );
        case 5:
          UserContextInfo context = info.user_context;
          if ( context == null ) return null;
          else return context.getUserName();
        default:
          assert false : "Unknown column: " + column;
          return null;
      }
    }
  }


  private class DurationRenderer extends DefaultTableCellRenderer {
    private final DateFormat tooltip_formatter = DateFormat.getDateTimeInstance();
    private final Date reused_date = new Date();

    @Override
    public Component getTableCellRendererComponent( JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column ) {

      String tooltip = null;
      if ( value instanceof Number ) {
        long start_time = ( ( Number ) value ).longValue();
        reused_date.setTime( start_time );

        tooltip = tooltip_formatter.format( reused_date );

        long duration = System.currentTimeMillis() - start_time;
        value = toDurationString( duration );
      }

      JComponent component =
        ( JComponent ) super.getTableCellRendererComponent( table, value,
        isSelected, hasFocus, row, column );

      if ( tooltip != null ) component.setToolTipText( tooltip );

      return component;
    }

    private String toDurationString( long duration ) {
      long time = duration / 1000;
      String seconds = Integer.toString( ( int ) ( time % 60 ) );
      String minutes = Integer.toString( ( int ) ( ( time % 3600 ) / 60 ) );
      String hours = Integer.toString( ( int ) ( time / 3600 ) );
      for ( int i = 0; i < 2; i++ ) {
        if ( seconds.length() < 2 ) {
          seconds = "0" + seconds;
        }
        if ( minutes.length() < 2 ) {
          minutes = "0" + minutes;
        }
        if ( hours.length() < 2 ) {
          hours = "0" + hours;
        }
      }
      return new StringBuilder( hours ).append( ':' ).append( minutes ).append(
        ':' ).append( seconds ).toString();
    }
  }


  private class InetSocketAddressRenderer extends DefaultTableCellRenderer {
    @Override
    public Component getTableCellRendererComponent( JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column ) {

      if ( value != null && value instanceof InetSocketAddress ) {
        InetSocketAddress sock_address = ( InetSocketAddress ) value;
        StringBuilder buf =
          new StringBuilder( sock_address.getAddress().getHostAddress() );
        buf.append( ':' );
        buf.append( sock_address.getPort() );
        value = buf.toString();
      }
      return super.getTableCellRendererComponent( table, value, isSelected,
        hasFocus, row, column );
    }
  }


  private class RepaintActionListener implements ActionListener {
    @Override
    public void actionPerformed( ActionEvent e ) {
      table.repaint();
    }
  }


  public static void main( String[] args ) throws Exception {
    if ( args.length == 0 ) {
      System.out.println( "Usage: ConnectionDebugPane server" );
      System.out.println( "                           client <port>" );
      System.out.println( "                           try_client <port>" );
      return;
    }

    if ( args[ 0 ].equalsIgnoreCase( "server" ) ) {
      Intrepid instance = Intrepid.create( new IntrepidSetup().openServer() );
      System.out.println( "Server listening on port " + instance.getServerPort() );

      ConnectionDebugPane pane = new ConnectionDebugPane( instance );
      UIKit.testComponent( pane );
    }
    else if ( args[ 0 ].equalsIgnoreCase( "try_client" ) ) {
      int port = Integer.parseInt( args[ 1 ] );

      Intrepid instance = Intrepid.create( null );

      ConnectionDebugPane pane = new ConnectionDebugPane( instance );
      UIKit.testComponent( pane );

      System.out.println( "Connecting to server..." );

      instance.tryConnect( InetAddress.getLocalHost(), port, null, null,
        10, TimeUnit.MINUTES );
    }
    else {
      int port = Integer.parseInt( args[ 1 ] );

      Intrepid instance = Intrepid.create( null );

      System.out.println( "Connecting to server..." );

      instance.connect( InetAddress.getLocalHost(), port, null, null );
    }
  }
}
TOP

Related Classes of com.starlight.intrepid.gui.ConnectionDebugPane$DurationRenderer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.