/* * [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 ] ); } } }