src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Configuration.java
changeset 53333 fd6de53a0d6e
parent 53332 ab474ef0a0ac
parent 53010 086dfcfc3731
child 53334 b94283cb226b
equal deleted inserted replaced
53332:ab474ef0a0ac 53333:fd6de53a0d6e
     1 /*
       
     2  * Copyright (c) 2002-2016, the original author or authors.
       
     3  *
       
     4  * This software is distributable under the BSD license. See the terms of the
       
     5  * BSD license in the documentation provided with this software.
       
     6  *
       
     7  * http://www.opensource.org/licenses/bsd-license.php
       
     8  */
       
     9 package jdk.internal.jline.internal;
       
    10 
       
    11 import java.io.BufferedInputStream;
       
    12 import java.io.File;
       
    13 import java.io.IOException;
       
    14 import java.io.InputStream;
       
    15 import java.io.FileNotFoundException;
       
    16 import java.net.URL;
       
    17 import java.nio.charset.Charset;
       
    18 import java.nio.charset.IllegalCharsetNameException;
       
    19 import java.util.Map;
       
    20 import java.util.Properties;
       
    21 
       
    22 import static jdk.internal.jline.internal.Preconditions.checkNotNull;
       
    23 
       
    24 /**
       
    25  * Provides access to configuration values.
       
    26  *
       
    27  * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
       
    28  * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
       
    29  * @since 2.4
       
    30  */
       
    31 public class Configuration
       
    32 {
       
    33     /**
       
    34      * System property which can point to a file or URL containing configuration properties to load.
       
    35      *
       
    36      * @since 2.7
       
    37      */
       
    38     public static final String JLINE_CONFIGURATION = "jline.configuration";
       
    39 
       
    40     /**
       
    41      * Default configuration file name loaded from user's home directory.
       
    42      */
       
    43     public static final String JLINE_RC = ".jline.rc";
       
    44 
       
    45     private static volatile Properties properties;
       
    46 
       
    47     private static Properties initProperties() {
       
    48         URL url = determineUrl();
       
    49         Properties props = new Properties();
       
    50         try {
       
    51             loadProperties(url, props);
       
    52         }
       
    53         catch (FileNotFoundException e) {
       
    54             // debug here and no stack trace, as this can happen normally if default jline.rc file is missing
       
    55             Log.debug("Unable to read configuration: ", e.toString());
       
    56         }
       
    57         catch (IOException e) {
       
    58             Log.warn("Unable to read configuration from: ", url, e);
       
    59         }
       
    60         return props;
       
    61     }
       
    62 
       
    63     private static void loadProperties(final URL url, final Properties props) throws IOException {
       
    64         Log.debug("Loading properties from: ", url);
       
    65         InputStream input = url.openStream();
       
    66         try {
       
    67             props.load(new BufferedInputStream(input));
       
    68         }
       
    69         finally {
       
    70             try {
       
    71                 input.close();
       
    72             }
       
    73             catch (IOException e) {
       
    74                 // ignore
       
    75             }
       
    76         }
       
    77 
       
    78         if (Log.DEBUG) {
       
    79             Log.debug("Loaded properties:");
       
    80             for (Map.Entry<Object,Object> entry : props.entrySet()) {
       
    81                 Log.debug("  ", entry.getKey(), "=", entry.getValue());
       
    82             }
       
    83         }
       
    84     }
       
    85 
       
    86     private static URL determineUrl() {
       
    87         // See if user has customized the configuration location via sysprop
       
    88         String tmp = System.getProperty(JLINE_CONFIGURATION);
       
    89         if (tmp != null) {
       
    90             return Urls.create(tmp);
       
    91         }
       
    92         else {
       
    93             // Otherwise try the default
       
    94             File file = new File(getUserHome(), JLINE_RC);
       
    95             return Urls.create(file);
       
    96         }
       
    97     }
       
    98 
       
    99     /**
       
   100      * @since 2.7
       
   101      */
       
   102     public static void reset() {
       
   103         Log.debug("Resetting");
       
   104         properties = null;
       
   105 
       
   106         // force new properties to load
       
   107         getProperties();
       
   108     }
       
   109 
       
   110     /**
       
   111      * @since 2.7
       
   112      */
       
   113     public static Properties getProperties() {
       
   114         // Not sure its worth to guard this with any synchronization, volatile field probably sufficient
       
   115         if (properties == null) {
       
   116             properties = initProperties();
       
   117         }
       
   118         return properties;
       
   119     }
       
   120 
       
   121     public static String getString(final String name, final String defaultValue) {
       
   122         checkNotNull(name);
       
   123 
       
   124         String value;
       
   125 
       
   126         // Check sysprops first, it always wins
       
   127         value = System.getProperty(name);
       
   128 
       
   129         if (value == null) {
       
   130             // Next try userprops
       
   131             value = getProperties().getProperty(name);
       
   132 
       
   133             if (value == null) {
       
   134                 // else use the default
       
   135                 value = defaultValue;
       
   136             }
       
   137         }
       
   138 
       
   139         return value;
       
   140     }
       
   141 
       
   142     public static String getString(final String name) {
       
   143         return getString(name, null);
       
   144     }
       
   145 
       
   146     public static boolean getBoolean(final String name) {
       
   147         return getBoolean(name, false);
       
   148     }
       
   149 
       
   150     public static boolean getBoolean(final String name, final boolean defaultValue) {
       
   151         String value = getString(name);
       
   152         if (value == null) {
       
   153             return defaultValue;
       
   154         }
       
   155         return value.length() == 0
       
   156             || value.equalsIgnoreCase("1")
       
   157             || value.equalsIgnoreCase("on")
       
   158             || value.equalsIgnoreCase("true");
       
   159     }
       
   160 
       
   161     /**
       
   162      * @since 2.6
       
   163      */
       
   164     public static int getInteger(final String name, final int defaultValue) {
       
   165         String str = getString(name);
       
   166         if (str == null) {
       
   167             return defaultValue;
       
   168         }
       
   169         return Integer.parseInt(str);
       
   170     }
       
   171 
       
   172     /**
       
   173      * @since 2.6
       
   174      */
       
   175     public static long getLong(final String name, final long defaultValue) {
       
   176         String str = getString(name);
       
   177         if (str == null) {
       
   178             return defaultValue;
       
   179         }
       
   180         return Long.parseLong(str);
       
   181     }
       
   182 
       
   183     //
       
   184     // System property helpers
       
   185     //
       
   186 
       
   187     /**
       
   188      * @since 2.7
       
   189      */
       
   190     public static String getLineSeparator() {
       
   191         return System.getProperty("line.separator");
       
   192     }
       
   193 
       
   194     public static File getUserHome() {
       
   195         return new File(System.getProperty("user.home"));
       
   196     }
       
   197 
       
   198     public static String getOsName() {
       
   199         return System.getProperty("os.name").toLowerCase();
       
   200     }
       
   201 
       
   202     /**
       
   203      * @since 2.7
       
   204      */
       
   205     public static boolean isWindows() {
       
   206         return getOsName().startsWith("windows");
       
   207     }
       
   208 
       
   209     public static boolean isHpux() {
       
   210         return getOsName().startsWith("hp");
       
   211     }
       
   212 
       
   213     // FIXME: Sort out use of property access of file.encoding in InputStreamReader, should consolidate configuration access here
       
   214 
       
   215     public static String getFileEncoding() {
       
   216         return System.getProperty("file.encoding");
       
   217     }
       
   218 
       
   219     /**
       
   220      * Get the default encoding.  Will first look at the LC_ALL, LC_CTYPE, and LANG environment variables, then the input.encoding
       
   221      * system property, then the default charset according to the JVM.
       
   222      *
       
   223      * @return The default encoding to use when none is specified.
       
   224      */
       
   225     public static String getEncoding() {
       
   226         // Check for standard locale environment variables, in order of precedence, first.
       
   227         // See http://www.gnu.org/s/libc/manual/html_node/Locale-Categories.html
       
   228         for (String envOption : new String[]{"LC_ALL", "LC_CTYPE", "LANG"}) {
       
   229             String envEncoding = extractEncodingFromCtype(System.getenv(envOption));
       
   230             if (envEncoding != null) {
       
   231                 try {
       
   232                     if (Charset.isSupported(envEncoding)) {
       
   233                         return envEncoding;
       
   234                     }
       
   235                 } catch (IllegalCharsetNameException e) {
       
   236                     continue;
       
   237                 }
       
   238             }
       
   239         }
       
   240         return getString("input.encoding", Charset.defaultCharset().name());
       
   241     }
       
   242 
       
   243     /**
       
   244      * Parses the LC_CTYPE value to extract the encoding according to the POSIX standard, which says that the LC_CTYPE
       
   245      * environment variable may be of the format <code>[language[_territory][.codeset][@modifier]]</code>
       
   246      *
       
   247      * @param ctype The ctype to parse, may be null
       
   248      * @return The encoding, if one was present, otherwise null
       
   249      */
       
   250     static String extractEncodingFromCtype(String ctype) {
       
   251         if (ctype != null && ctype.indexOf('.') > 0) {
       
   252             String encodingAndModifier = ctype.substring(ctype.indexOf('.') + 1);
       
   253             if (encodingAndModifier.indexOf('@') > 0) {
       
   254                 return encodingAndModifier.substring(0, encodingAndModifier.indexOf('@'));
       
   255             } else {
       
   256                 return encodingAndModifier;
       
   257             }
       
   258         }
       
   259         return null;
       
   260     }
       
   261 }