/* * [Available.java] * * Summary: Checks to see if Server Available. * * Copyright: (c) 2010-2017 Roedy Green, Canadian Mind Products, http://mindprod.com * * Licence: This software may be copied and used freely for any purpose but military. * http://mindprod.com/contact/nonmil.html * * Requires: JDK 1.8+ * * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/ * * Version History: * 1.0 2010-03-16 initial version * 1.1 2010-03-23 L&F user selectable, persistent, probe done on background thread, * reports ping and http status separately */ package com.mindprod.available; import com.mindprod.common18.Build; import com.mindprod.common18.CMPAboutJBox; import com.mindprod.common18.FontFactory; import com.mindprod.common18.HybridJ; import com.mindprod.common18.JEButton; import com.mindprod.common18.Laf; import com.mindprod.common18.ST; import com.mindprod.common18.VersionCheck; import com.mindprod.http.Probe; import javax.swing.ImageIcon; import javax.swing.JApplet; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JTextField; import javax.swing.SwingUtilities; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.Color; import java.awt.Container; import java.awt.Cursor; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.net.InetAddress; /** * Checks to see if Server Available. * * @author Roedy Green, Canadian Mind Products * @version 1.1 2010-03-23 L&F user selectable, persistent, probe done on background thread, * reports ping and http status separately * @since 2010-03-16 */ public final class Available extends JApplet implements ActionListener, ChangeListener, Runnable { /** * height of Applet box in pixels. Does not include surrounding frame. */ private static final int APPLET_HEIGHT = 410; /** * Width of Applet box in pixels. */ private static final int APPLET_WIDTH = 600; private static final int FIRST_COPYRIGHT_YEAR = 2010; /** * copyright not displayed * * @noinspection UnusedDeclaration */ private static final String EMBEDDED_COPYRIGHT = "Copyright: (c) 2010-2017 Roedy Green, Canadian Mind Products, http://mindprod.com"; /** * text for instructions */ private static final String INSTRUCTIONS1 = "Key the URL or IP of the server without the"; /** * text for instructions */ private static final String INSTRUCTIONS2 = "lead http:// e.g. mindprod.com or 65.110.21.43"; /** * text for instructions */ private static final String INSTRUCTIONS3 = "then click PROBE."; /** * when this version was released */ private static final String RELEASE_DATE = "2010-03-22"; /** * name of program */ private static final String TITLE_STRING = "Available"; /** * latest version */ private static final String VERSION_STRING = "1.1"; /** * background colour for entire Applet */ private static final Color BACKGROUND_FOR_APPLET = new Color( 0xfaf0e6 )/* linen */; /** * background colour for instructions */ private static final Color BACKGROUND_FOR_INSTRUCTIONS = BACKGROUND_FOR_APPLET; /** * background colour for labels */ private static final Color BACKGROUND_FOR_LABEL = BACKGROUND_FOR_APPLET; /** * for titles */ private static final Color BACKGROUND_FOR_TITLE = BACKGROUND_FOR_APPLET; /** * background colour for input fields */ private static final Color BACKGROUND_FOR_INPUT = new Color( 0xffffff ); /** * background colour for result fields */ private static final Color BACKGROUND_FOR_RESULT = Color.WHITE; /** * foreground colour for input fields */ private static final Color FOREGROUND_FOR_INPUT = new Color( 0x1e90ff )/* dodger blue */; /** * foreground colour for instructions */ private static final Color FOREGROUND_FOR_INSTRUCTIONS = new Color( 0x006400 )/* dark green */; /** * foreground colour for labels */ private static final Color FOREGROUND_FOR_LABEL = new Color( 0x0000b0 ); /** * foreground colour for result fields */ private static final Color FOREGROUND_FOR_RESULT = new Color( 0x1874cd ); /** * for titles */ private static final Color FOREGROUND_FOR_TITLE = new Color( 0xdc143c ); /** * font for input fields */ private static final Font FONT_FOR_EDITABLE_FIELDS = FontFactory.build( "Dialog", Font.BOLD, 17 ); /** * font for instructions */ private static final Font FONT_FOR_INSTRUCTIONS = FontFactory.build( "Dialog", Font.PLAIN, 14 ); /** * font for for labels */ private static final Font FONT_FOR_LABELS = FontFactory.build( "Dialog", Font.BOLD, 15 ); /** * font for result fields */ private static final Font FONT_FOR_RESULTS = FontFactory.build( "Dialog", Font.BOLD, 15 ); /** * for for title line */ private static final Font FONT_FOR_TITLE = FontFactory.build( "Dialog", Font.BOLD, 16 ); /** * font for for title second line */ private static final Font FONT_FOR_TITLE2 = FontFactory.build( "Dialog", Font.PLAIN, 14 ); /** * icon to indicate a this server is down */ private static final ImageIcon HTTP_DOWN_ICON = new ImageIcon( Available.class.getResource( "image/httpdown.png" ) ); /** * icon to indicate a this server is up and running. */ private static final ImageIcon HTTP_UP_ICON = new ImageIcon( Available.class.getResource( "image/httpup.png" ) ); /** * icon to indicate a this server is down */ private static final ImageIcon PING_DOWN_ICON = new ImageIcon( Available.class.getResource( "image/pingdown.png" ) ); /** * icon to indicate a this server is up and running. */ private static final ImageIcon PING_UP_ICON = new ImageIcon( Available.class.getResource( "image/pingup.png" ) ); /** * space to leave around the applet */ private static final int[] margin = { 9, 12, 9, 12 }/* t l b r */; /** * check button */ private JButton probe; /** * label for domain */ private JLabel domainLabel; /** * httpState text display */ private JLabel httpState; /** * icon to symbolise state of probed http server */ private JLabel httpStateIcon; /** * displayed instructions on how to use */ private JLabel instructions1; /** * displayed instructions on how to use */ private JLabel instructions2; /** * displayed instructions on how to use */ private JLabel instructions3; /** * label for ip */ private JLabel ipLabel; /** * pingState text display */ private JLabel pingState; /** * icon to symbolise state of probed echo server */ private JLabel pingStateIcon; /** * Displayed title */ private JLabel title; /** * title, second line */ private JLabel title2; /** * label for url */ private JLabel urlLabel; /** * domain display */ private JTextField domain; /** * ip display */ private JTextField ip; /** * url entry */ private JTextField url; /** * allocate all components */ private void buildComponents() { title = new JLabel( TITLE_STRING + " " + VERSION_STRING ); title.setForeground( FOREGROUND_FOR_TITLE ); title.setBackground( BACKGROUND_FOR_TITLE ); title.setFont( FONT_FOR_TITLE ); title2 = new JLabel( "released:" + RELEASE_DATE + " build:" + Build.BUILD_NUMBER ); title2.setFont( FONT_FOR_TITLE2 ); title2.setForeground( FOREGROUND_FOR_TITLE ); title2.setBackground( BACKGROUND_FOR_TITLE ); urlLabel = new JLabel( "Server URL:" ); urlLabel.setForeground( FOREGROUND_FOR_LABEL ); urlLabel.setBackground( BACKGROUND_FOR_LABEL ); urlLabel.setFont( FONT_FOR_LABELS ); ipLabel = new JLabel( "IP:" ); ipLabel.setForeground( FOREGROUND_FOR_LABEL ); ipLabel.setBackground( BACKGROUND_FOR_LABEL ); ipLabel.setFont( FONT_FOR_LABELS ); domainLabel = new JLabel( "Domain:" ); domainLabel.setForeground( FOREGROUND_FOR_LABEL ); domainLabel.setBackground( BACKGROUND_FOR_LABEL ); domainLabel.setFont( FONT_FOR_LABELS ); url = new JTextField( "", JTextField.LEFT ); url.setEditable( true ); url.setForeground( FOREGROUND_FOR_INPUT ); url.setBackground( BACKGROUND_FOR_INPUT ); url.setOpaque( true ); url.setFont( FONT_FOR_EDITABLE_FIELDS ); url.setMargin( new Insets( 2, 2, 2, 2 ) ); url.setToolTipText( "Key the domain or IP of a server then hit Probe." ); probe = new JEButton( "Probe" ); probe.setToolTipText( "Probe the server." ); ip = new JTextField( "", JTextField.LEFT ); ip.setEditable( false ); ip.setForeground( FOREGROUND_FOR_RESULT ); ip.setBackground( BACKGROUND_FOR_RESULT ); ip.setOpaque( true ); ip.setFont( FONT_FOR_RESULTS ); ip.setMargin( new Insets( 2, 2, 2, 2 ) ); domain = new JTextField( "", JTextField.LEFT ); domain.setEditable( false ); domain.setForeground( FOREGROUND_FOR_RESULT ); domain.setBackground( BACKGROUND_FOR_RESULT ); domain.setOpaque( true ); domain.setFont( FONT_FOR_RESULTS ); domain.setMargin( new Insets( 2, 2, 2, 2 ) ); httpStateIcon = new JLabel(); httpState = new JLabel(); httpState.setForeground( FOREGROUND_FOR_LABEL ); httpState.setBackground( BACKGROUND_FOR_LABEL ); httpState.setFont( FONT_FOR_LABELS ); pingStateIcon = new JLabel(); pingState = new JLabel(); pingState.setForeground( FOREGROUND_FOR_LABEL ); pingState.setBackground( BACKGROUND_FOR_LABEL ); pingState.setFont( FONT_FOR_LABELS ); instructions1 = new JLabel( INSTRUCTIONS1 ); instructions1.setBackground( BACKGROUND_FOR_INSTRUCTIONS ); instructions1.setForeground( FOREGROUND_FOR_INSTRUCTIONS ); instructions1.setFont( FONT_FOR_INSTRUCTIONS ); instructions2 = new JLabel( INSTRUCTIONS2 ); instructions2.setBackground( BACKGROUND_FOR_INSTRUCTIONS ); instructions2.setForeground( FOREGROUND_FOR_INSTRUCTIONS ); instructions2.setFont( FONT_FOR_INSTRUCTIONS ); instructions3 = new JLabel( INSTRUCTIONS3 ); instructions3.setBackground( BACKGROUND_FOR_INSTRUCTIONS ); instructions3.setForeground( FOREGROUND_FOR_INSTRUCTIONS ); instructions3.setFont( FONT_FOR_INSTRUCTIONS ); } /** * build a menu with Look & Feel and About across the top */ private void buildMenu() { final JMenuBar menubar = new JMenuBar(); setJMenuBar( menubar ); final JMenu lafMenu = Laf.buildLookAndFeelMenu(); if ( lafMenu != null ) { menubar.add( lafMenu ); } final JMenu menuHelp = new JMenu( "Help" ); menubar.add( menuHelp ); final JMenuItem aboutItem = new JMenuItem( "About" ); menuHelp.add( aboutItem ); aboutItem.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent e ) { // open about frame new CMPAboutJBox( TITLE_STRING, VERSION_STRING, "Probe the availability of a server.", "Discover a server's domain and IP.", "freeware", RELEASE_DATE, FIRST_COPYRIGHT_YEAR, "Roedy Green", "AVAILABLE", "1.8" ); } } ); } /** * freeze components during probe */ private void freeze() { setCursor( Cursor.getPredefinedCursor( Cursor.WAIT_CURSOR ) ); probe.setEnabled( false ); url.setEnabled( false ); instructions1.setText( "Wait . . ." ); instructions2.setText( "" ); instructions3.setText( "" ); pingStateIcon.setIcon( null ); pingState.setText( "" ); httpStateIcon.setIcon( null ); httpState.setText( "" ); } /** * What happens after PROBE button hit. * handles probing the server on a background thread */ private void hit() { freeze(); // call run in the background to probe the server. new Thread( this ).start(); } /** * Install listeners */ private void installHooks() { probe.addActionListener( this ); url.addActionListener( this ); } /** * Layout components in a GridBag * * @param contentPane JApplet contentPane. */ private void layoutComponents( Container contentPane ) { // layout // ---0-------------1-------------2---------3----- // 0 ---- title --- title2 -----------------------0 // 1 1 // 2 server: -------URL ----------------------- 2 // 3 -------- -------------- ----- ---PROBE 3 // 4 ip: ------ip------ httpicon pingicon 4 // 5 domain: -----domain----- " " 5 // 6 ------- --------------- httpstate echostate 6 // 7 ------ --instructions1-------------------- 7 // 8 ------- --instructions2 ------------------- 8 // 9 ------- --instructions3 ------------------- 9 // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( title, new GridBagConstraints( 0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets( margin[ 0 ], margin[ 1 ], 5, 5 ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( title2, new GridBagConstraints( 1, 0, 3, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets( margin[ 0 ], 5, 5, margin[ 3 ] ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( urlLabel, new GridBagConstraints( 0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets( 5, margin[ 1 ], 5, 5 ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( url, new GridBagConstraints( 1, 2, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets( 5, 5, 5, margin[ 3 ] ), 300, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( probe, new GridBagConstraints( 3, 3, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets( 5, 5, 5, margin[ 3 ] ), 20, 10 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( ipLabel, new GridBagConstraints( 0, 4, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets( 5, margin[ 1 ], 5, 5 ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( ip, new GridBagConstraints( 1, 4, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets( 5, 5, 5, 5 ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( domainLabel, new GridBagConstraints( 0, 5, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets( 5, margin[ 0 ], 5, 5 ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( domain, new GridBagConstraints( 1, 5, 1, 1, 1.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.HORIZONTAL, new Insets( 5, 5, 5, 5 ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( httpStateIcon, new GridBagConstraints( 2, 4, 1, 2, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets( 5, 5, 5, margin[ 3 ] ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( httpState, new GridBagConstraints( 2, 6, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets( 5, 5, 5, margin[ 3 ] ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( pingStateIcon, new GridBagConstraints( 3, 4, 1, 2, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets( 5, 5, 5, margin[ 3 ] ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( pingState, new GridBagConstraints( 3, 6, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets( 5, 5, 5, margin[ 3 ] ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( instructions1, new GridBagConstraints( 1, 7, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets( 5, 5, 1, margin[ 3 ] ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( instructions2, new GridBagConstraints( 1, 8, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets( 5, 5, 5, margin[ 3 ] ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( instructions3, new GridBagConstraints( 1, 9, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets( 5, 5, margin[ 2 ], margin[ 3 ] ), 0, 0 ) ); } /** * thaw components after probe completes */ private void thaw() { probe.setEnabled( true ); url.setEnabled( true ); instructions1.setText( INSTRUCTIONS1 ); instructions2.setText( INSTRUCTIONS2 ); instructions3.setText( INSTRUCTIONS3 ); setCursor( Cursor.getPredefinedCursor( Cursor.DEFAULT_CURSOR ) ); } /** * Allow JApplet to be run as an Application * * @param args not used. */ public static void main( String[] args ) { HybridJ.fireup( new Available(), TITLE_STRING + " " + VERSION_STRING, APPLET_WIDTH, APPLET_HEIGHT ); } /** * Invoked when an action occurs. * * @param e event, not used */ public void actionPerformed( ActionEvent e ) { hit(); } /** * Called by the browser or Applet viewer to inform * this Applet that it is being reclaimed and that it should destroy * any resources that it has allocated. */ @Override public void destroy() { domain = null; domainLabel = null; httpState = null; httpStateIcon = null; instructions1 = null; instructions2 = null; instructions3 = null; ip = null; ipLabel = null; pingState = null; pingStateIcon = null; probe = null; title = null; title2 = null; url = null; urlLabel = null; } /** * Called by the browser or Applet viewer to inform * this Applet that it has been loaded into the system. */ @Override public void init() { Container contentPane = this.getContentPane(); if ( !VersionCheck.isJavaVersionOK( 1, 7, 0, contentPane ) ) { // effectively abort return; } buildMenu(); // also initial L&F contentPane.setLayout( new GridBagLayout() ); contentPane.setBackground( BACKGROUND_FOR_APPLET ); buildComponents(); layoutComponents( contentPane ); installHooks(); validate(); setVisible( true ); } /** * What happens after PROBE button hit. * handles probing the server on a background thread */ public void run() { boolean pingReachable; boolean httpReachable; try { // throws UnknownHostException final InetAddress address = InetAddress.getByName( url.getText() ); String host = address.getHostName(); if ( ST.isLegal( host, "0123456789." ) ) { // if just got a legal IP, try the canonical form to get a proper domain. host = address.getCanonicalHostName(); } final String fHost = host; SwingUtilities.invokeLater( new Runnable() { public void run() { ip.setText( address.getHostAddress() ); domain.setText( fHost ); } } ); try { // ping echo port 7 or via ICMP. Throws IOException pingReachable = address.isReachable( null /* interface */, 64 /* ttl */, 10000 /* timeout 10 seconds */ ); } catch ( IOException e ) { pingReachable = false; } // need final version of reachable for inner class final boolean fPingReachable = pingReachable; SwingUtilities.invokeLater( new Runnable() { public void run() { if ( fPingReachable ) { pingStateIcon.setIcon( PING_UP_ICON ); pingState.setText( "ping reachable" ); } else { pingStateIcon.setIcon( PING_DOWN_ICON ); pingState.setText( "ping not reachable" ); } } } ); // probe http home page. Sent throws no exception. final int response = new Probe().send( url.getText(), 80, null, 2 ); httpReachable = 0 <= response && response <= 399; } catch ( IOException e ) { httpReachable = false; } final boolean fHttpReachable = httpReachable; SwingUtilities.invokeLater( new Runnable() { public void run() { if ( fHttpReachable ) { httpStateIcon.setIcon( HTTP_UP_ICON ); httpState.setText( "http is up" ); } else { httpStateIcon.setIcon( HTTP_DOWN_ICON ); httpState.setText( "http is down" ); } thaw(); } } ); } /** * Applet has scrolled onscreen. */ public void start() { validate(); } /** * Invoked when the target of the listener has changed its state. * * @param e a ChangeEvent object, not used */ public void stateChanged( ChangeEvent e ) { hit(); } /** * Applet scrolled offscreen */ public void stop() { } }