/*
* [Wassup.java]
*
* Summary: Displays system properties both safe and restricted.
*
* Copyright: (c) 1998-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 1998-11-30
* 1.1 1998-12-01 try exhaustive list of system properties for
* Applets.
* bigger screen.
* 1.2 1998-12-14 add codebase
* colors done a different way
* check for proper JVM version.
* 1.3 1998-12-21 add test BAT and HTML files for various JVMs
* and browsers.
* 1.4 1998-12-28 use new Comparator interface
* 1.5 1999-01-07 allow Wassup to execute without a GUI, based on code by
* David B. Gleason (mailto:David.Gleason@bull.com)
* Bull HN Information Systems, Inc.
* 1.6 1999-10-03 use JDK 1.2 RSA signed jar
* select restricted or safe.
* 1.7 2000-12-28 update jar signing certificate
* 1.8 2002-03-30 use phony Sun cert, instead of Netscape code signing.
* switch to SunSort from HeapSort
* 1.9 2002-04-08 lower case package
* 2.0 2004-06-01 add about box
* 2.1 2005-08-01 display version separately
* 2.2 2005-08-11 revise the list of safe properties
* to be consistent with JDK 1.5.
* Formerly safe properties are now restricted.
* 2.3 2006-03-05 reformat with IntelliJ, add Javadoc.
* 2.4 2007-04-28 new racier logo, PAD.
* 2.5 2008-04-03 add build to title, tidy code.
* 2.6 2014-04-24 convert to Swing
*/
package com.mindprod.wassup;
import com.mindprod.common18.Build;
import com.mindprod.common18.CMPAboutJBox;
import com.mindprod.common18.Common18;
import com.mindprod.common18.FontFactory;
import com.mindprod.common18.Hybrid;
import com.mindprod.common18.Laf;
import com.mindprod.common18.VersionCheck;
import javax.swing.JApplet;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import java.awt.Color;
import java.awt.Container;
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.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Properties;
import static java.lang.System.*;
/**
* Displays system properties both safe and restricted.
*
* Applet to display all the Java System properties May also be run as an application.
*
* Wassup let's you know what's up with your Java environment. It will tell you the System Properties, as many as the
* Security System will let you peek at. This includes such things as which JVM is running, which version of Java, which
* vendor. It may be run as either an Applet or an application. When you run Wassup as an application it shows you
* considerably more information. The Java sandbox considers it a security risk to reveal that information to an Applet.
* As an application, you can see all the possible System Properties. When you run as an unsigned Applet, your view is
* much more limited.
*
* Wassup allows you to see the restricted properties if you use the Java Plug-in 1.2+ and grant permission, or if you
* run it as an application. The restricted properties include all the properties there are. The safe ones include only
* those you can see in an Applet with out signing and a security grant. * System.getProperty() vs
* System.getProperties.getProperty() You need write access to be able to use the second form that lets you list all
* possible properties, even if you don't know their names.
*
* @author Roedy Green, Canadian Mind Products
* @version 2.6 2014-04-24 convert to Swing.
* @since 1998-11-30
*/
public final class Wassup extends JApplet
{
/**
* height of Applet box in pixels. Does not include surrounding frame.
*/
private static final int APPLET_HEIGHT = 398;
/**
* Width of Applet box in pixels.
*/
private static final int APPLET_WIDTH = 628;
private static final int FIRST_COPYRIGHT_YEAR = 1998;
private static final String WORDING_FOR_SAFE =
"Safe Java System Properties accessible even to unsigned Applets.";
private static final String WORDING_FOR_RESTRICTED =
"Restricted Java System Properties accessible only to signed Applets and applications.";
private static final String WORDING_FOR_BOTH =
"Safe and Restricted Java System Properties accessible to signed Applets and applications.";
/**
* j
* non-displaying copyright
*/
private static final String EMBEDDED_COPYRIGHT =
"Copyright: (c) 1998-2017 Roedy Green, Canadian Mind Products, http://mindprod.com";
private static final String RELEASE_DATE = "2014-04-24";
private static final String TITLE_STRING = "CMP Wassup";
private static final String VERSION_STRING = "2.6";
private static final Color BACKGROUND_FOR_PROPERTIES = new Color( 0xfcfffc );
private static final Color BACKGROUND_FOR_APPLET = new Color( 0xeeffee );
private static final Color FOREGROUND_FOR_SAFE = new Color( 0x008000 );
private static final Color FOREGROUND_FOR_RESTRICTED = new Color( 0xa00000 );
private static final Color FOREGROUND_FOR_BOTH = new Color( 0x80600F );
private static final Color FOREGROUND_FOR_LABEL = new Color( 0x0000b0 );
/**
* for titles
*/
private static final Color FOREGROUND_FOR_TITLE = new Color( 0xdc143c );
/**
* for for title
*/
private static final Font FONT_FOR_TITLE = FontFactory.build( "Dialog", Font.BOLD, 16 );
/**
* for for title second part
*/
private static final Font FONT_FOR_TITLE2 = FontFactory.build( "Dialog", Font.PLAIN, 14 );
/**
* choose safe or restricted properties
*/
private JComboBox safe;
/**
* explanation if which properties are showing
*/
private JLabel captionLabel;
/**
* display java version specially
*/
private JLabel javaVersion;
/**
* program title
*/
private JLabel title;
/**
* second title line for app
*/
private JLabel title2;
/**
* property=value pairs
*/
private JTextArea keyValuePairs;
/**
* true if permit Restricted mode where we get at restricted properties
*/
private boolean allowRestricted = false;
private Container contentPane;
private JScrollPane scrollPane;
/**
* Constructor
*/
public Wassup()
{
}
/**
* Constructor
*
* @param allowRestricted true if we can get at restricted properties. Can if signed or running an application.
*/
private Wassup( boolean allowRestricted )
{
this.allowRestricted = allowRestricted;
}
/**
* Get a sorted list of all the System properties. Only works in applications and signed Applets.
* includes the safe proerties
*
* @param separator usually "\n\n"
*
* @return String containing pairs of property-value
*/
private static String displayRestrictedProperties( String separator )
{
try
{
Properties sysprops = System.getProperties();
// Count properties
int count = sysprops.size();
// prepare Matrix to hold the properties
String[][] matrix = new String[ count ][ 2 ];
// read System properties into the matrix
int j = 0;// Java won't let me put this in the for loop, Ouch!
for ( Enumeration e = sysprops.propertyNames(); j < count; j++ )
{
String key = ( String ) e.nextElement();
String value = sysprops.getProperty( key );
matrix[ j ][ 0 ] = key;
matrix[ j ][ 1 ] = value;
} // end for
// sort by key
Arrays.sort( matrix, new ByKey() );
// concatenate all key value pairs.
StringBuilder result = new StringBuilder( 4 * 1024 );
result.append( "R E S T R I C T E D P R O P E R T I E S" );
result.append( separator );
for ( int i = 0; i < count; i++ )
{
String key = matrix[ i ][ 0 ];
if ( key != null )
{
String value = matrix[ i ][ 1 ];
if ( value != null )
{
switch ( value )
{
case "\r\n":
value = "[hex chars: 0x0d 0x0a i.e. CrLf, \\r\\n]";
break;
case "\n":
value = "[hex char: 0x0a i.e. Lf, \\n]";
break;
case "\r":
value = "[hex char: 0x0d i.e. Cr, \\r]";
break;
}
result.append( key );
result.append( " = " );
result.append( value );
result.append( separator );
}
}
} // end for
return result.toString();
}
catch ( Exception e )
{
return "No security clearance to see the restricted System properties.";
}
} // end displayRestrictedProperties
/**
* Get a sorted list of all the safe System properties.
*
* @param separator usually \n\n
*
* @return pairs of property-value
*/
private static String displaySafeProperties( String separator )
{
// for documentation on System properties see "properties" in the Java
// glossary
// at http://mindprod.com/jgloss/properties.html or in the Javadoc for
// System.getProperties.
// If an unsafe name creeps in, no harm. It just won't be displayed.
String[] safeNames = {
"browser",
"browser.version",
"file.separator",
"java.class.version",
"java.specification.name",
"java.specification.vendor",
"java.specification.version",
"java.vendor",
"java.vendor.url",
"java.version",
"java.vm.name",
"java.vm.specification.name",
"java.vm.specification.vendor",
"java.vm.specification.version",
"java.vm.vendor",
"java.vm.version",
"line.separator",
"os.arch",
"os.name",
"os.version",
"path.separator", };
int count = safeNames.length;
// no need to sort, already in alpha order
// concatenate all key value pairs.
StringBuilder result = new StringBuilder( 4096 );
result.append( "S A F E P R O P E R T I E S" );
result.append( separator );
for ( String key : safeNames )
{
if ( key != null )
{
try
{
String value = System.getProperty( key );
if ( value != null )
{
if ( value.equals( "\r\n" ) )
{
value =
"[binary chars: 0x0d 0x0a i.e. CrLf, \\r\\n]";
}
else if ( value.equals( "\n" ) )
{
value = "[binary char: 0x0a i.e. Lf, \\n]";
}
result.append( key );
result.append( " = " );
result.append( value );
result.append( separator );
} // end if
}
catch ( Exception e )
{
/* if not allowed to peek, we don't display anything */
}
} // end if
} // end for
return result.toString();
} // end displaySafeProperties
/**
* output System properties to System.out, only in non-gui version.
*
* @param allowRestricted true if we are allowed to look at restricted properties.
*/
private static void outputProperties( boolean allowRestricted )
{
/* display on System.out */
out.println( TITLE_STRING + " " + VERSION_STRING );
String lineSeparator =
System.getProperties().getProperty( "line.separator" );
// double space
lineSeparator += lineSeparator;
// print the safe properties and values
out.println( displayRestrictedProperties( lineSeparator ) );
if ( allowRestricted )
{
out.println( displayRestrictedProperties( lineSeparator ) );
}
} // end outPutProperties
/**
* allocate all components
*/
private void buildComponents()
{
title = new JLabel( TITLE_STRING + " " + VERSION_STRING );
title.setFont( FONT_FOR_TITLE );
title.setForeground( FOREGROUND_FOR_TITLE );
title2 = new JLabel(
"released:" +
RELEASE_DATE +
" build:" +
Build.BUILD_NUMBER
);
title2.setFont( FONT_FOR_TITLE2 );
title2.setForeground( FOREGROUND_FOR_TITLE );
safe = new JComboBox<>();
safe.setFont( FontFactory.build( "Dialog", Font.PLAIN, 12 ) );
// turn off the write-in feature.
safe.setEditable( false );
safe.addItem( "safe" );
if ( allowRestricted )
{
safe.addItem( "restricted" );
safe.addItem( "both" );
}
safe.setSelectedIndex( 0 );
safe.addItemListener( new ItemListener()
{
/**
* Notice any change to safe/restricted choice
* @param event details of just what the user clicked.
*/
public void itemStateChanged( ItemEvent event )
{
Object object = event.getSource();
if ( object == safe )
{
showProperties();
} // end if
} // end itemStateChanged
} // end anonymous class
);// end addActionListener line
javaVersion = new JLabel( "Java version "
+ System.getProperty( "java.version" ),
JLabel.RIGHT
);
javaVersion.setFont( FontFactory.build( "Dialog", Font.BOLD, 16 ) );
javaVersion.setForeground( FOREGROUND_FOR_LABEL );
keyValuePairs = new JTextArea( "", 0, 0 );
keyValuePairs.setBackground( BACKGROUND_FOR_PROPERTIES );
keyValuePairs.setForeground( FOREGROUND_FOR_SAFE );
keyValuePairs.setEditable( false );
// no way to add whitespace border
keyValuePairs.setFont( FontFactory.build( "Dialog", Font.PLAIN, 15 ) );
scrollPane = new JScrollPane( keyValuePairs, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED );
scrollPane.setVisible( true );
captionLabel = new JLabel( WORDING_FOR_SAFE );
captionLabel.setFont( FontFactory.build( "Dialog", Font.BOLD, 11 ) );
captionLabel.setForeground( FOREGROUND_FOR_SAFE );
}
/**
* build a menu with Look & Feel and About across the top
*/
private void buildMenu()
{
// turn on anti-alias
System.setProperty( "swing.aatext", "true" );
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,
"Shows Java System properties,",
"both safe and restricted.",
"freeware",
RELEASE_DATE,
FIRST_COPYRIGHT_YEAR,
"Roedy Green",
"WASSUP",
"1.8" );
}
} );
}
/**
* layout components in a gridbag
*/
private void layoutComponents()
{
// -----0------1----- 2---
// 0 ------title1- title2 0
// 1 safe---------------- 1
// 2 --------properties-- 2
// 3 -------caption ----- 3
// x y w h wtx wty anchor fill T L B R padx pady
contentPane.add( title,
new GridBagConstraints( 0,
0,
2,
1,
0.0,
0.0,
GridBagConstraints.WEST,
GridBagConstraints.NONE,
new Insets( 10, 10, 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,
2,
1,
0.0,
0.0,
GridBagConstraints.EAST,
GridBagConstraints.NONE,
new Insets( 10, 5, 5, 10 ),
0,
0 )
);
// x y w h wtx wty anchor fill T L B R padx pady
contentPane.add( safe,
new GridBagConstraints( 0,
2,
1,
1,
0.0,
0.0,
GridBagConstraints.WEST,
GridBagConstraints.NONE,
new Insets( 5, 10, 5, 5 ),
0,
0 )
);
// x y w h wtx wty anchor fill T L B R padx pady
contentPane.add( javaVersion,
new GridBagConstraints( 2,
2,
1,
1,
0.0,
0.0,
GridBagConstraints.EAST,
GridBagConstraints.NONE,
new Insets( 5, 5, 5, 10 ),
0,
0 )
);
// x y w h wtx wty anchor fill T L B R padx pady
contentPane.add( scrollPane /* containing key value pairs */,
new GridBagConstraints( 0,
3,
3,
1,
100.0,
100.0,
GridBagConstraints.CENTER,
GridBagConstraints.BOTH,
new Insets( 10, 10, 10, 10 ),
0,
0 )
);
// x y w h wtx wty anchor fill T L B R padx pady
contentPane.add( captionLabel,
new GridBagConstraints( 0,
4,
3,
1,
0.0,
0.0,
GridBagConstraints.CENTER,
GridBagConstraints.BOTH,
new Insets( 5, 10, 10, 10 ),
0,
0 )
);
}
/**
* Show properties and update caption based on current safe/restricted selection.
*/
void showProperties()
{
// Fill the JTextArea with the properties
switch ( safe.getSelectedIndex() )
{
case 0:
default:
{
captionLabel.setText( WORDING_FOR_SAFE );
captionLabel.setForeground( FOREGROUND_FOR_SAFE );
keyValuePairs.setForeground( FOREGROUND_FOR_SAFE );
keyValuePairs.setText( displaySafeProperties( "\n\n" ) );
break;
}
case 1:
{
captionLabel.setText( WORDING_FOR_RESTRICTED );
captionLabel.setForeground( FOREGROUND_FOR_RESTRICTED );
keyValuePairs.setForeground( FOREGROUND_FOR_RESTRICTED );
keyValuePairs.setText( displayRestrictedProperties( "\n\n" ) );
break;
}
case 2:
{
captionLabel.setText( WORDING_FOR_BOTH );
captionLabel.setForeground( FOREGROUND_FOR_BOTH );
keyValuePairs.setForeground( FOREGROUND_FOR_BOTH );
keyValuePairs.setText( displaySafeProperties( "\n\n" ) + displayRestrictedProperties( "\n\n" ) );
break;
}
}
// wind back to the top to read, setValue has no effect
// scroller.getVerticalScrollBar().setValue( 0 );
keyValuePairs.setCaretPosition( 0 );
} // end showProperties
/**
* Allow this Applet to run as as application as well.
*
* @param args command line argument, nogui if want output batch to System.out instead of running GUI.
*/
public static void main( String args[] )
{
boolean gui = true;
// check for nogui command line argument
if ( args.length > 0 && ( args[ 0 ].equalsIgnoreCase( "nogui" )
|| args[ 0 ].equalsIgnoreCase( "/nogui" )
|| args[ 0 ]
.equalsIgnoreCase( "-nogui" ) ) )
{
gui = false;
}
// check for gui=false System property.
// Can only do this in an application.
if ( System.getProperty( "GUI", "true" ).equals( "false" ) )
{
gui = false;
}
if ( gui )
{
// display results on screen
// when run as application will call init, start, stop, destroy
Hybrid.fireup( new Wassup( true/* allowRestricted */ ),
TITLE_STRING + " " + VERSION_STRING,
APPLET_WIDTH,
APPLET_HEIGHT );
}
else
{
// non gui version
/* display on System.out */
outputProperties( true );
}
} // end main
/**
* 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.
*/
public void destroy()
{
captionLabel = null;
javaVersion = null;
scrollPane = null;
keyValuePairs = null;
safe = null;
title = null;
title2 = null;
}
/**
* Called by the browser or Applet viewer to inform
* this Applet that it has been loaded into the System.
*/
public void init()
{
contentPane = this.getContentPane();
if ( !VersionCheck.isJavaVersionOK( 1, 7, 0, contentPane ) )
{
// effectively abort
return;
}
Common18.setLaf();
contentPane.setLayout( new GridBagLayout() );
contentPane.setBackground( BACKGROUND_FOR_APPLET );
allowRestricted = true;
contentPane.setLayout( new GridBagLayout() );
buildMenu();
buildComponents();
layoutComponents();
showProperties();
this.validate();
this.setVisible( true );
} // end init
// Callback delegate to describe collating sequence
/**
* sort by first row which contains the key.
*/
private static class ByKey implements Comparator
{
/**
* sort by first row.
* Defines an alternate sort order for String[].
* Compare two String[] Objects.
* Compares [0].
* Informally, returns (a-b), or +ve if a is more positive than b.
*
* @param a first String[] to compare
* @param b second String[] to compare
*
* @return +ve if a>b, 0 if a==b, -ve if a<b
*/
public final int compare( String[] a, String[] b )
{
return a[ 0 ].compareToIgnoreCase( b[ 0 ] );
}
}
}