jdk/src/share/classes/sun/security/provider/ConfigSpiFile.java
changeset 19385 a7b34a4b1fcb
parent 19068 f2358d18923a
child 19386 761117da5004
equal deleted inserted replaced
19068:f2358d18923a 19385:a7b34a4b1fcb
     1 /*
       
     2  * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package sun.security.provider;
       
    27 
       
    28 import java.io.*;
       
    29 import java.net.MalformedURLException;
       
    30 import java.net.URI;
       
    31 import java.net.URL;
       
    32 import java.security.AccessController;
       
    33 import java.security.PrivilegedAction;
       
    34 import java.security.PrivilegedActionException;
       
    35 import java.security.PrivilegedExceptionAction;
       
    36 import java.security.Security;
       
    37 import java.security.URIParameter;
       
    38 import java.text.MessageFormat;
       
    39 import java.util.*;
       
    40 import javax.security.auth.AuthPermission;
       
    41 import javax.security.auth.login.AppConfigurationEntry;
       
    42 import javax.security.auth.login.Configuration;
       
    43 import javax.security.auth.login.ConfigurationSpi;
       
    44 import sun.security.util.Debug;
       
    45 import sun.security.util.PropertyExpander;
       
    46 import sun.security.util.ResourcesMgr;
       
    47 
       
    48 /**
       
    49  * This class represents a default implementation for
       
    50  * {@code javax.security.auth.login.Configuration}.
       
    51  *
       
    52  * <p> This object stores the runtime login configuration representation,
       
    53  * and is the amalgamation of multiple static login
       
    54  * configurations that resides in files.
       
    55  * The algorithm for locating the login configuration file(s) and reading their
       
    56  * information into this {@code Configuration} object is:
       
    57  *
       
    58  * <ol>
       
    59  * <li>
       
    60  *   Loop through the security properties,
       
    61  *   <i>login.config.url.1</i>, <i>login.config.url.2</i>, ...,
       
    62  *   <i>login.config.url.X</i>.
       
    63  *   Each property value specifies a <code>URL</code> pointing to a
       
    64  *   login configuration file to be loaded.  Read in and load
       
    65  *   each configuration.
       
    66  *
       
    67  * <li>
       
    68  *   The {@code java.lang.System} property
       
    69  *   <i>java.security.auth.login.config</i>
       
    70  *   may also be set to a {@code URL} pointing to another
       
    71  *   login configuration file
       
    72  *   (which is the case when a user uses the -D switch at runtime).
       
    73  *   If this property is defined, and its use is allowed by the
       
    74  *   security property file (the Security property,
       
    75  *   <i>policy.allowSystemProperty</i> is set to <i>true</i>),
       
    76  *   also load that login configuration.
       
    77  *
       
    78  * <li>
       
    79  *   If the <i>java.security.auth.login.config</i> property is defined using
       
    80  *   "==" (rather than "="), then ignore all other specified
       
    81  *   login configurations and only load this configuration.
       
    82  *
       
    83  * <li>
       
    84  *   If no system or security properties were set, try to read from the file,
       
    85  *   ${user.home}/.java.login.config, where ${user.home} is the value
       
    86  *   represented by the "user.home" System property.
       
    87  * </ol>
       
    88  *
       
    89  * <p> The configuration syntax supported by this implementation
       
    90  * is exactly that syntax specified in the
       
    91  * {@code javax.security.auth.login.Configuration} class.
       
    92  *
       
    93  * @see javax.security.auth.login.LoginContext
       
    94  * @see java.security.Security security properties
       
    95  */
       
    96 public final class ConfigSpiFile extends ConfigurationSpi {
       
    97 
       
    98     private URL url;
       
    99     private boolean expandProp = true;
       
   100     private Map<String, List<AppConfigurationEntry>> configuration;
       
   101     private int linenum;
       
   102     private StreamTokenizer st;
       
   103     private int lookahead;
       
   104 
       
   105     private static Debug debugConfig = Debug.getInstance("configfile");
       
   106     private static Debug debugParser = Debug.getInstance("configparser");
       
   107 
       
   108     /**
       
   109      * Create a new {@code Configuration} object.
       
   110      *
       
   111      * @throws SecurityException if the {@code Configuration} can not be
       
   112      *                           initialized
       
   113      */
       
   114     public ConfigSpiFile() {
       
   115         try {
       
   116             init();
       
   117         } catch (IOException ioe) {
       
   118             throw new SecurityException(ioe);
       
   119         }
       
   120     }
       
   121 
       
   122     /**
       
   123      * Create a new {@code Configuration} object from the specified {@code URI}.
       
   124      *
       
   125      * @param uri the {@code URI}
       
   126      * @throws SecurityException if the {@code Configuration} can not be
       
   127      *                           initialized
       
   128      * @throws NullPointerException if {@code uri} is null
       
   129      */
       
   130     public ConfigSpiFile(URI uri) {
       
   131         // only load config from the specified URI
       
   132         try {
       
   133             url = uri.toURL();
       
   134             init();
       
   135         } catch (IOException ioe) {
       
   136             throw new SecurityException(ioe);
       
   137         }
       
   138     }
       
   139 
       
   140     public ConfigSpiFile(final Configuration.Parameters params)
       
   141         throws IOException {
       
   142 
       
   143         // call in a doPrivileged
       
   144         //
       
   145         // we have already passed the Configuration.getInstance
       
   146         // security check.  also this class is not freely accessible
       
   147         // (it is in the "sun" package).
       
   148 
       
   149         try {
       
   150             AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
       
   151                 public Void run() throws IOException {
       
   152                     if (params == null) {
       
   153                         init();
       
   154                     } else {
       
   155                         if (!(params instanceof URIParameter)) {
       
   156                             throw new IllegalArgumentException
       
   157                                     ("Unrecognized parameter: " + params);
       
   158                         }
       
   159                         URIParameter uriParam = (URIParameter)params;
       
   160                         url = uriParam.getURI().toURL();
       
   161                         init();
       
   162                     }
       
   163                     return null;
       
   164                 }
       
   165             });
       
   166         } catch (PrivilegedActionException pae) {
       
   167             throw (IOException)pae.getException();
       
   168         }
       
   169 
       
   170         // if init() throws some other RuntimeException,
       
   171         // let it percolate up naturally.
       
   172     }
       
   173 
       
   174     /**
       
   175      * Read and initialize the entire login Configuration from the configured
       
   176      * URL.
       
   177      *
       
   178      * @throws IOException if the Configuration can not be initialized
       
   179      * @throws SecurityException if the caller does not have permission
       
   180      *                           to initialize the Configuration
       
   181      */
       
   182     private void init() throws IOException {
       
   183 
       
   184         boolean initialized = false;
       
   185 
       
   186         // For policy.expandProperties, check if either a security or system
       
   187         // property is set to false (old code erroneously checked the system
       
   188         // prop so we must check both to preserve compatibility).
       
   189         String expand = Security.getProperty("policy.expandProperties");
       
   190         if (expand == null) {
       
   191             expand = System.getProperty("policy.expandProperties");
       
   192         }
       
   193         if ("false".equals(expand)) {
       
   194             expandProp = false;
       
   195         }
       
   196 
       
   197         // new configuration
       
   198         Map<String, List<AppConfigurationEntry>> newConfig = new HashMap<>();
       
   199 
       
   200         if (url != null) {
       
   201             /**
       
   202              * If the caller specified a URI via Configuration.getInstance,
       
   203              * we only read from that URI
       
   204              */
       
   205             if (debugConfig != null) {
       
   206                 debugConfig.println("reading " + url);
       
   207             }
       
   208             init(url, newConfig);
       
   209             configuration = newConfig;
       
   210             return;
       
   211         }
       
   212 
       
   213         /**
       
   214          * Caller did not specify URI via Configuration.getInstance.
       
   215          * Read from URLs listed in the java.security properties file.
       
   216          */
       
   217         String allowSys = Security.getProperty("policy.allowSystemProperty");
       
   218 
       
   219         if ("true".equalsIgnoreCase(allowSys)) {
       
   220             String extra_config = System.getProperty
       
   221                                         ("java.security.auth.login.config");
       
   222             if (extra_config != null) {
       
   223                 boolean overrideAll = false;
       
   224                 if (extra_config.startsWith("=")) {
       
   225                     overrideAll = true;
       
   226                     extra_config = extra_config.substring(1);
       
   227                 }
       
   228                 try {
       
   229                     extra_config = PropertyExpander.expand(extra_config);
       
   230                 } catch (PropertyExpander.ExpandException peee) {
       
   231                     MessageFormat form = new MessageFormat
       
   232                         (ResourcesMgr.getString
       
   233                                 ("Unable.to.properly.expand.config",
       
   234                                 "sun.security.util.AuthResources"));
       
   235                     Object[] source = {extra_config};
       
   236                     throw new IOException(form.format(source));
       
   237                 }
       
   238 
       
   239                 URL configURL = null;
       
   240                 try {
       
   241                     configURL = new URL(extra_config);
       
   242                 } catch (MalformedURLException mue) {
       
   243                     File configFile = new File(extra_config);
       
   244                     if (configFile.exists()) {
       
   245                         configURL = configFile.toURI().toURL();
       
   246                     } else {
       
   247                         MessageFormat form = new MessageFormat
       
   248                             (ResourcesMgr.getString
       
   249                                 ("extra.config.No.such.file.or.directory.",
       
   250                                 "sun.security.util.AuthResources"));
       
   251                         Object[] source = {extra_config};
       
   252                         throw new IOException(form.format(source));
       
   253                     }
       
   254                 }
       
   255 
       
   256                 if (debugConfig != null) {
       
   257                     debugConfig.println("reading "+configURL);
       
   258                 }
       
   259                 init(configURL, newConfig);
       
   260                 initialized = true;
       
   261                 if (overrideAll) {
       
   262                     if (debugConfig != null) {
       
   263                         debugConfig.println("overriding other policies!");
       
   264                     }
       
   265                     configuration = newConfig;
       
   266                     return;
       
   267                 }
       
   268             }
       
   269         }
       
   270 
       
   271         int n = 1;
       
   272         String config_url;
       
   273         while ((config_url = Security.getProperty
       
   274                                         ("login.config.url."+n)) != null) {
       
   275             try {
       
   276                 config_url = PropertyExpander.expand
       
   277                         (config_url).replace(File.separatorChar, '/');
       
   278                 if (debugConfig != null) {
       
   279                     debugConfig.println("\tReading config: " + config_url);
       
   280                 }
       
   281                 init(new URL(config_url), newConfig);
       
   282                 initialized = true;
       
   283             } catch (PropertyExpander.ExpandException peee) {
       
   284                 MessageFormat form = new MessageFormat
       
   285                         (ResourcesMgr.getString
       
   286                                 ("Unable.to.properly.expand.config",
       
   287                                 "sun.security.util.AuthResources"));
       
   288                 Object[] source = {config_url};
       
   289                 throw new IOException(form.format(source));
       
   290             }
       
   291             n++;
       
   292         }
       
   293 
       
   294         if (initialized == false && n == 1 && config_url == null) {
       
   295 
       
   296             // get the config from the user's home directory
       
   297             if (debugConfig != null) {
       
   298                 debugConfig.println("\tReading Policy " +
       
   299                                 "from ~/.java.login.config");
       
   300             }
       
   301             config_url = System.getProperty("user.home");
       
   302             String userConfigFile = config_url +
       
   303                       File.separatorChar + ".java.login.config";
       
   304 
       
   305             // No longer throws an exception when there's no config file
       
   306             // at all. Returns an empty Configuration instead.
       
   307             if (new File(userConfigFile).exists()) {
       
   308                 init(new File(userConfigFile).toURI().toURL(),
       
   309                      newConfig);
       
   310             }
       
   311         }
       
   312 
       
   313         configuration = newConfig;
       
   314     }
       
   315 
       
   316     private void init(URL config,
       
   317                       Map<String, List<AppConfigurationEntry>> newConfig)
       
   318                       throws IOException {
       
   319 
       
   320         try (InputStreamReader isr
       
   321                 = new InputStreamReader(getInputStream(config), "UTF-8")) {
       
   322             readConfig(isr, newConfig);
       
   323         } catch (FileNotFoundException fnfe) {
       
   324             if (debugConfig != null) {
       
   325                 debugConfig.println(fnfe.toString());
       
   326             }
       
   327             throw new IOException(ResourcesMgr.getString
       
   328                     ("Configuration.Error.No.such.file.or.directory",
       
   329                     "sun.security.util.AuthResources"));
       
   330         }
       
   331     }
       
   332 
       
   333     /**
       
   334      * Retrieve an entry from the Configuration using an application name
       
   335      * as an index.
       
   336      *
       
   337      * @param applicationName the name used to index the Configuration.
       
   338      * @return an array of AppConfigurationEntries which correspond to
       
   339      *         the stacked configuration of LoginModules for this
       
   340      *         application, or null if this application has no configured
       
   341      *         LoginModules.
       
   342      */
       
   343     @Override
       
   344     public AppConfigurationEntry[] engineGetAppConfigurationEntry
       
   345         (String applicationName) {
       
   346 
       
   347         List<AppConfigurationEntry> list = null;
       
   348         synchronized (configuration) {
       
   349             list = configuration.get(applicationName);
       
   350         }
       
   351 
       
   352         if (list == null || list.size() == 0)
       
   353             return null;
       
   354 
       
   355         AppConfigurationEntry[] entries =
       
   356                                 new AppConfigurationEntry[list.size()];
       
   357         Iterator<AppConfigurationEntry> iterator = list.iterator();
       
   358         for (int i = 0; iterator.hasNext(); i++) {
       
   359             AppConfigurationEntry e = iterator.next();
       
   360             entries[i] = new AppConfigurationEntry(e.getLoginModuleName(),
       
   361                                                    e.getControlFlag(),
       
   362                                                    e.getOptions());
       
   363         }
       
   364         return entries;
       
   365     }
       
   366 
       
   367     /**
       
   368      * Refresh and reload the Configuration by re-reading all of the
       
   369      * login configurations.
       
   370      *
       
   371      * @throws SecurityException if the caller does not have permission
       
   372      *                           to refresh the Configuration.
       
   373      */
       
   374     @Override
       
   375     public synchronized void engineRefresh() {
       
   376 
       
   377         SecurityManager sm = System.getSecurityManager();
       
   378         if (sm != null)
       
   379             sm.checkPermission(new AuthPermission("refreshLoginConfiguration"));
       
   380 
       
   381         AccessController.doPrivileged(new PrivilegedAction<Void>() {
       
   382             public Void run() {
       
   383                 try {
       
   384                     init();
       
   385                 } catch (IOException ioe) {
       
   386                     throw new SecurityException(ioe.getLocalizedMessage(), ioe);
       
   387                 }
       
   388                 return null;
       
   389             }
       
   390         });
       
   391     }
       
   392 
       
   393     private void readConfig(Reader reader,
       
   394         Map<String, List<AppConfigurationEntry>> newConfig)
       
   395         throws IOException {
       
   396 
       
   397         linenum = 1;
       
   398 
       
   399         if (!(reader instanceof BufferedReader))
       
   400             reader = new BufferedReader(reader);
       
   401 
       
   402         st = new StreamTokenizer(reader);
       
   403         st.quoteChar('"');
       
   404         st.wordChars('$', '$');
       
   405         st.wordChars('_', '_');
       
   406         st.wordChars('-', '-');
       
   407         st.wordChars('*', '*');
       
   408         st.lowerCaseMode(false);
       
   409         st.slashSlashComments(true);
       
   410         st.slashStarComments(true);
       
   411         st.eolIsSignificant(true);
       
   412 
       
   413         lookahead = nextToken();
       
   414         while (lookahead != StreamTokenizer.TT_EOF) {
       
   415             parseLoginEntry(newConfig);
       
   416         }
       
   417     }
       
   418 
       
   419     private void parseLoginEntry(
       
   420         Map<String, List<AppConfigurationEntry>> newConfig)
       
   421         throws IOException {
       
   422 
       
   423         List<AppConfigurationEntry> configEntries = new LinkedList<>();
       
   424 
       
   425         // application name
       
   426         String appName = st.sval;
       
   427         lookahead = nextToken();
       
   428 
       
   429         if (debugParser != null) {
       
   430             debugParser.println("\tReading next config entry: " + appName);
       
   431         }
       
   432 
       
   433         match("{");
       
   434 
       
   435         // get the modules
       
   436         while (peek("}") == false) {
       
   437             // get the module class name
       
   438             String moduleClass = match("module class name");
       
   439 
       
   440             // controlFlag (required, optional, etc)
       
   441             AppConfigurationEntry.LoginModuleControlFlag controlFlag;
       
   442             String sflag = match("controlFlag").toUpperCase();
       
   443             switch (sflag) {
       
   444                 case "REQUIRED":
       
   445                     controlFlag =
       
   446                         AppConfigurationEntry.LoginModuleControlFlag.REQUIRED;
       
   447                     break;
       
   448                 case "REQUISITE":
       
   449                     controlFlag =
       
   450                         AppConfigurationEntry.LoginModuleControlFlag.REQUISITE;
       
   451                     break;
       
   452                 case "SUFFICIENT":
       
   453                     controlFlag =
       
   454                         AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT;
       
   455                     break;
       
   456                 case "OPTIONAL":
       
   457                     controlFlag =
       
   458                         AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL;
       
   459                     break;
       
   460                 default:
       
   461                     MessageFormat form = new MessageFormat(
       
   462                         ResourcesMgr.getString
       
   463                         ("Configuration.Error.Invalid.control.flag.flag",
       
   464                         "sun.security.util.AuthResources"));
       
   465                     Object[] source = {sflag};
       
   466                     throw new IOException(form.format(source));
       
   467             }
       
   468 
       
   469             // get the args
       
   470             Map<String, String> options = new HashMap<>();
       
   471             while (peek(";") == false) {
       
   472                 String key = match("option key");
       
   473                 match("=");
       
   474                 try {
       
   475                     options.put(key, expand(match("option value")));
       
   476                 } catch (PropertyExpander.ExpandException peee) {
       
   477                     throw new IOException(peee.getLocalizedMessage());
       
   478                 }
       
   479             }
       
   480 
       
   481             lookahead = nextToken();
       
   482 
       
   483             // create the new element
       
   484             if (debugParser != null) {
       
   485                 debugParser.println("\t\t" + moduleClass + ", " + sflag);
       
   486                 for (String key : options.keySet()) {
       
   487                     debugParser.println("\t\t\t" + key +
       
   488                                         "=" + options.get(key));
       
   489                 }
       
   490             }
       
   491             configEntries.add(new AppConfigurationEntry(moduleClass,
       
   492                                                         controlFlag, options));
       
   493         }
       
   494 
       
   495         match("}");
       
   496         match(";");
       
   497 
       
   498         // add this configuration entry
       
   499         if (newConfig.containsKey(appName)) {
       
   500             MessageFormat form = new MessageFormat(ResourcesMgr.getString
       
   501                 ("Configuration.Error.Can.not.specify.multiple.entries.for.appName",
       
   502                 "sun.security.util.AuthResources"));
       
   503             Object[] source = {appName};
       
   504             throw new IOException(form.format(source));
       
   505         }
       
   506         newConfig.put(appName, configEntries);
       
   507     }
       
   508 
       
   509     private String match(String expect) throws IOException {
       
   510 
       
   511         String value = null;
       
   512 
       
   513         switch(lookahead) {
       
   514         case StreamTokenizer.TT_EOF:
       
   515 
       
   516             MessageFormat form1 = new MessageFormat(ResourcesMgr.getString
       
   517                 ("Configuration.Error.expected.expect.read.end.of.file.",
       
   518                 "sun.security.util.AuthResources"));
       
   519             Object[] source1 = {expect};
       
   520             throw new IOException(form1.format(source1));
       
   521 
       
   522         case '"':
       
   523         case StreamTokenizer.TT_WORD:
       
   524 
       
   525             if (expect.equalsIgnoreCase("module class name") ||
       
   526                 expect.equalsIgnoreCase("controlFlag") ||
       
   527                 expect.equalsIgnoreCase("option key") ||
       
   528                 expect.equalsIgnoreCase("option value")) {
       
   529                 value = st.sval;
       
   530                 lookahead = nextToken();
       
   531             } else {
       
   532                 MessageFormat form = new MessageFormat(ResourcesMgr.getString
       
   533                         ("Configuration.Error.Line.line.expected.expect.found.value.",
       
   534                         "sun.security.util.AuthResources"));
       
   535                 Object[] source = {new Integer(linenum), expect, st.sval};
       
   536                 throw new IOException(form.format(source));
       
   537             }
       
   538             break;
       
   539 
       
   540         case '{':
       
   541 
       
   542             if (expect.equalsIgnoreCase("{")) {
       
   543                 lookahead = nextToken();
       
   544             } else {
       
   545                 MessageFormat form = new MessageFormat(ResourcesMgr.getString
       
   546                         ("Configuration.Error.Line.line.expected.expect.",
       
   547                         "sun.security.util.AuthResources"));
       
   548                 Object[] source = {new Integer(linenum), expect, st.sval};
       
   549                 throw new IOException(form.format(source));
       
   550             }
       
   551             break;
       
   552 
       
   553         case ';':
       
   554 
       
   555             if (expect.equalsIgnoreCase(";")) {
       
   556                 lookahead = nextToken();
       
   557             } else {
       
   558                 MessageFormat form = new MessageFormat(ResourcesMgr.getString
       
   559                         ("Configuration.Error.Line.line.expected.expect.",
       
   560                         "sun.security.util.AuthResources"));
       
   561                 Object[] source = {new Integer(linenum), expect, st.sval};
       
   562                 throw new IOException(form.format(source));
       
   563             }
       
   564             break;
       
   565 
       
   566         case '}':
       
   567 
       
   568             if (expect.equalsIgnoreCase("}")) {
       
   569                 lookahead = nextToken();
       
   570             } else {
       
   571                 MessageFormat form = new MessageFormat(ResourcesMgr.getString
       
   572                         ("Configuration.Error.Line.line.expected.expect.",
       
   573                         "sun.security.util.AuthResources"));
       
   574                 Object[] source = {new Integer(linenum), expect, st.sval};
       
   575                 throw new IOException(form.format(source));
       
   576             }
       
   577             break;
       
   578 
       
   579         case '=':
       
   580 
       
   581             if (expect.equalsIgnoreCase("=")) {
       
   582                 lookahead = nextToken();
       
   583             } else {
       
   584                 MessageFormat form = new MessageFormat(ResourcesMgr.getString
       
   585                         ("Configuration.Error.Line.line.expected.expect.",
       
   586                         "sun.security.util.AuthResources"));
       
   587                 Object[] source = {new Integer(linenum), expect, st.sval};
       
   588                 throw new IOException(form.format(source));
       
   589             }
       
   590             break;
       
   591 
       
   592         default:
       
   593             MessageFormat form = new MessageFormat(ResourcesMgr.getString
       
   594                         ("Configuration.Error.Line.line.expected.expect.found.value.",
       
   595                         "sun.security.util.AuthResources"));
       
   596             Object[] source = {new Integer(linenum), expect, st.sval};
       
   597             throw new IOException(form.format(source));
       
   598         }
       
   599         return value;
       
   600     }
       
   601 
       
   602     private boolean peek(String expect) {
       
   603         boolean found = false;
       
   604 
       
   605         switch (lookahead) {
       
   606         case ',':
       
   607             if (expect.equalsIgnoreCase(","))
       
   608                 found = true;
       
   609             break;
       
   610         case ';':
       
   611             if (expect.equalsIgnoreCase(";"))
       
   612                 found = true;
       
   613             break;
       
   614         case '{':
       
   615             if (expect.equalsIgnoreCase("{"))
       
   616                 found = true;
       
   617             break;
       
   618         case '}':
       
   619             if (expect.equalsIgnoreCase("}"))
       
   620                 found = true;
       
   621             break;
       
   622         default:
       
   623         }
       
   624         return found;
       
   625     }
       
   626 
       
   627     private int nextToken() throws IOException {
       
   628         int tok;
       
   629         while ((tok = st.nextToken()) == StreamTokenizer.TT_EOL) {
       
   630             linenum++;
       
   631         }
       
   632         return tok;
       
   633     }
       
   634 
       
   635     private InputStream getInputStream(URL url) throws IOException {
       
   636         if ("file".equalsIgnoreCase(url.getProtocol())) {
       
   637             // Compatibility notes:
       
   638             //
       
   639             // Code changed from
       
   640             //   String path = url.getFile().replace('/', File.separatorChar);
       
   641             //   return new FileInputStream(path);
       
   642             //
       
   643             // The original implementation would search for "/tmp/a%20b"
       
   644             // when url is "file:///tmp/a%20b". This is incorrect. The
       
   645             // current codes fix this bug and searches for "/tmp/a b".
       
   646             // For compatibility reasons, when the file "/tmp/a b" does
       
   647             // not exist, the file named "/tmp/a%20b" will be tried.
       
   648             //
       
   649             // This also means that if both file exists, the behavior of
       
   650             // this method is changed, and the current codes choose the
       
   651             // correct one.
       
   652             try {
       
   653                 return url.openStream();
       
   654             } catch (Exception e) {
       
   655                 String file = url.getPath();
       
   656                 if (url.getHost().length() > 0) {  // For Windows UNC
       
   657                     file = "//" + url.getHost() + file;
       
   658                 }
       
   659                 if (debugConfig != null) {
       
   660                     debugConfig.println("cannot read " + url +
       
   661                                         ", try " + file);
       
   662                 }
       
   663                 return new FileInputStream(file);
       
   664             }
       
   665         } else {
       
   666             return url.openStream();
       
   667         }
       
   668     }
       
   669 
       
   670     private String expand(String value)
       
   671         throws PropertyExpander.ExpandException, IOException {
       
   672 
       
   673         if (value.isEmpty()) {
       
   674             return value;
       
   675         }
       
   676 
       
   677         if (expandProp) {
       
   678 
       
   679             String s = PropertyExpander.expand(value);
       
   680 
       
   681             if (s == null || s.length() == 0) {
       
   682                 MessageFormat form = new MessageFormat(ResourcesMgr.getString
       
   683                         ("Configuration.Error.Line.line.system.property.value.expanded.to.empty.value",
       
   684                         "sun.security.util.AuthResources"));
       
   685                 Object[] source = {new Integer(linenum), value};
       
   686                 throw new IOException(form.format(source));
       
   687             }
       
   688             return s;
       
   689         } else {
       
   690             return value;
       
   691         }
       
   692     }
       
   693 }