/* * Copyright (C) 2011 Laurent Caillette * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, either * version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.novelang.outfit; import java.io.File; import java.util.Enumeration; import java.util.List; import java.util.Properties; import java.util.Set; import java.util.StringTokenizer; import com.google.common.collect.Lists; import com.google.common.collect.Ordering; import com.google.common.collect.Sets; import org.apache.commons.lang.SystemUtils; import org.novelang.logger.Logger; import org.novelang.logger.LoggerFactory; /** * Utility class for dumping system properties. * * @author Laurent Caillette */ public final class EnvironmentTools { private static final Logger LOGGER = LoggerFactory.getLogger( EnvironmentTools.class ) ; private EnvironmentTools() { } public static String getEnvironmentInformation() { final StringBuffer stringBuffer = new StringBuffer() ; appendEnvironmentInformation( stringBuffer ) ; return stringBuffer.toString() ; } /** * Feeds a <code>StringBuffer</code> with all standard environment information * known to be useful. * @param stringBuffer a non-null <code>StringBuffer</code>. */ public static void appendEnvironmentInformation( final StringBuffer stringBuffer ) { stringBuffer.append( "System properties: \n" ) ; appendSystemProperties( stringBuffer, System.getProperties(), " " ) ; } /** * Feeds a <code>StringBuffer</code> with <code>Properties</code> content. * For some keys like paths formatting is enhanced a bit. * @param stringBuffer a non-null <code>StringBuffer</code>. * @param systemProperties a non-null object as returned by * {@link System#getProperties()}. * @param indent a non-null <code>String</code> containing * the prefix for indenting lines (four spaces characters are usually ok). */ public static void appendSystemProperties( final StringBuffer stringBuffer, final Properties systemProperties, final String indent ) { final Enumeration propertyNames = systemProperties.propertyNames() ; final List< String > propertyNameList = Lists.newArrayList() ; while( propertyNames.hasMoreElements() ) { propertyNameList.add( ( String ) propertyNames.nextElement() ) ; } final String pathIndent = indent + " " ; for( final String name : Ordering.natural().sortedCopy( propertyNameList ) ) { stringBuffer.append( indent ) ; final String propertyValue = systemProperties.getProperty( name ) ; if( ! appendIfPath( stringBuffer, name, propertyValue, pathIndent ) && ! appendIfLineSeparator( stringBuffer, name, propertyValue ) ) { stringBuffer.append( name ) ; stringBuffer.append( " = " ) ; stringBuffer.append( propertyValue ) ; stringBuffer.append( "\n" ) ; } } } private static final String LINE_SEPARATOR_PROPERTY_NAME = "line.separator" ; private static final Set< String > PATH_PROPERTY_NAMES = Sets.newHashSet( "java.class.path", "java.library.path", "sun.boot.class.path", "java.endorsed.dirs", "sun.boot.library.path", "java.ext.dirs" ) ; private static boolean appendIfPath( final StringBuffer stringBuffer, final String propertyName, final String classpath, final String indent ) { if( PATH_PROPERTY_NAMES.contains( propertyName ) ) { stringBuffer.append( propertyName ) ; stringBuffer.append( " = " ) ; appendPath( stringBuffer, classpath, indent ) ; return true ; } else { return false ; } } private static boolean appendIfLineSeparator( final StringBuffer stringBuffer, final String name, final String lineSeparator ) { if( LINE_SEPARATOR_PROPERTY_NAME.equals( name ) ) { final char[] separatorChars = lineSeparator.toCharArray() ; stringBuffer.append( LINE_SEPARATOR_PROPERTY_NAME ) ; stringBuffer.append( " =" ) ; for( final char c : separatorChars ) { stringBuffer.append( " 0x" ); stringBuffer.append( TextTools.to8byteHex( c ).toUpperCase() ); } stringBuffer.append( "\n" ) ; return true ; } else { return false ; } } /** * Feeds a <code>StringBuffer</code> with one classpath entry per line. * @param stringBuffer a non-null <code>StringBuffer</code>. * @param classpath a string containing classpath as returned by * <code>System.getProperty( "java.class.path" )</code>. * @param indent a non-null <code>String</code> containing * the prefix for indenting lines (four spaces characters are usually ok). */ public static void appendPath( final StringBuffer stringBuffer, final String classpath, final String indent ) { final StringTokenizer tokenizer = new StringTokenizer( classpath, File.pathSeparator ); final File[] classpathEntries = new File[ tokenizer.countTokens() ] ; int i = 0 ; while ( tokenizer.hasMoreTokens() ) { classpathEntries[ i ] = new File( tokenizer.nextToken() ) ; i++; } // Arrays.sort( classpathEntries, new Comparator< File >() { // public int compare( File file1, File file2 ) { // return file1.getName().compareTo( file2.getName() ) ; // } // } ) ; switch( classpathEntries.length ) { case 0 : break ; case 1 : stringBuffer.append( classpathEntries[ 0 ] ) ; break ; default : for( final File classpathEntry : classpathEntries ) { stringBuffer.append( SystemUtils.LINE_SEPARATOR ); stringBuffer.append( indent ); stringBuffer.append( classpathEntry ); } } stringBuffer.append( "\n" ) ; } public static void logSystemProperties() { LOGGER.info( getEnvironmentInformation() ) ; } }