mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-23 16:55:09 +00:00
8005117: Eliminate dependency from ConfigSpiFile to com.sun.security.auth.login.ConfigFile
Reviewed-by: alanb, mchung, weijun
This commit is contained in:
parent
627cd88eba
commit
4bc8e6ac87
@ -25,41 +25,39 @@
|
||||
|
||||
package com.sun.security.auth.login;
|
||||
|
||||
import javax.security.auth.AuthPermission;
|
||||
import javax.security.auth.login.AppConfigurationEntry;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import javax.security.auth.login.Configuration;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.MalformedURLException;
|
||||
import java.text.MessageFormat;
|
||||
import sun.security.util.Debug;
|
||||
import sun.security.util.ResourcesMgr;
|
||||
import sun.security.util.PropertyExpander;
|
||||
|
||||
// NOTE: As of JDK 8, this class instantiates
|
||||
// sun.security.provider.ConfigSpiFile and forwards all methods to that
|
||||
// implementation. All implementation fixes and enhancements should be made to
|
||||
// sun.security.provider.ConfigSpiFile and not this class.
|
||||
// See JDK-8005117 for more information.
|
||||
|
||||
/**
|
||||
* This class represents a default implementation for
|
||||
* <code>javax.security.auth.login.Configuration</code>.
|
||||
* {@code javax.security.auth.login.Configuration}.
|
||||
*
|
||||
* <p> This object stores the runtime login configuration representation,
|
||||
* and is the amalgamation of multiple static login
|
||||
* configurations that resides in files.
|
||||
* The algorithm for locating the login configuration file(s) and reading their
|
||||
* information into this <code>Configuration</code> object is:
|
||||
* information into this {@code Configuration} object is:
|
||||
*
|
||||
* <ol>
|
||||
* <li>
|
||||
* Loop through the security properties,
|
||||
* <i>login.config.url.1</i>, <i>login.config.url.2</i>, ...,
|
||||
* <i>login.config.url.X</i>.
|
||||
* Each property value specifies a <code>URL</code> pointing to a
|
||||
* Each property value specifies a {@code URL} pointing to a
|
||||
* login configuration file to be loaded. Read in and load
|
||||
* each configuration.
|
||||
*
|
||||
* <li>
|
||||
* The <code>java.lang.System</code> property
|
||||
* The {@code java.lang.System} property
|
||||
* <i>java.security.auth.login.config</i>
|
||||
* may also be set to a <code>URL</code> pointing to another
|
||||
* may also be set to a {@code URL} pointing to another
|
||||
* login configuration file
|
||||
* (which is the case when a user uses the -D switch at runtime).
|
||||
* If this property is defined, and its use is allowed by the
|
||||
@ -80,593 +78,63 @@ import sun.security.util.PropertyExpander;
|
||||
*
|
||||
* <p> The configuration syntax supported by this implementation
|
||||
* is exactly that syntax specified in the
|
||||
* <code>javax.security.auth.login.Configuration</code> class.
|
||||
* {@code javax.security.auth.login.Configuration} class.
|
||||
*
|
||||
* @see javax.security.auth.login.LoginContext
|
||||
* @see java.security.Security security properties
|
||||
*/
|
||||
public class ConfigFile extends javax.security.auth.login.Configuration {
|
||||
public class ConfigFile extends Configuration {
|
||||
|
||||
private StreamTokenizer st;
|
||||
private int lookahead;
|
||||
private int linenum;
|
||||
private HashMap<String, LinkedList<AppConfigurationEntry>> configuration;
|
||||
private boolean expandProp = true;
|
||||
private URL url;
|
||||
|
||||
private static Debug debugConfig = Debug.getInstance("configfile");
|
||||
private static Debug debugParser = Debug.getInstance("configparser");
|
||||
private sun.security.provider.ConfigSpiFile configFile;
|
||||
|
||||
/**
|
||||
* Create a new <code>Configuration</code> object.
|
||||
* Create a new {@code Configuration} object.
|
||||
*
|
||||
* @throws SecurityException if the {@code Configuration} can not be
|
||||
* initialized
|
||||
*/
|
||||
public ConfigFile() {
|
||||
try {
|
||||
init(url);
|
||||
} catch (IOException ioe) {
|
||||
throw (SecurityException)
|
||||
new SecurityException(ioe.getMessage()).initCause(ioe);
|
||||
}
|
||||
configFile = new sun.security.provider.ConfigSpiFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new <code>Configuration</code> object from the specified URI.
|
||||
* Create a new {@code Configuration} object from the specified {@code URI}.
|
||||
*
|
||||
* @param uri Create a new Configuration object from this URI.
|
||||
* @param uri the {@code URI}
|
||||
* @throws SecurityException if the {@code Configuration} can not be
|
||||
* initialized
|
||||
* @throws NullPointerException if {@code uri} is null
|
||||
*/
|
||||
public ConfigFile(URI uri) {
|
||||
// only load config from the specified URI
|
||||
try {
|
||||
url = uri.toURL();
|
||||
init(url);
|
||||
} catch (MalformedURLException mue) {
|
||||
throw (SecurityException)
|
||||
new SecurityException(mue.getMessage()).initCause(mue);
|
||||
} catch (IOException ioe) {
|
||||
throw (SecurityException)
|
||||
new SecurityException(ioe.getMessage()).initCause(ioe);
|
||||
}
|
||||
configFile = new sun.security.provider.ConfigSpiFile(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read and initialize the entire login Configuration.
|
||||
* Retrieve an entry from the {@code Configuration} using an application
|
||||
* name as an index.
|
||||
*
|
||||
* <p>
|
||||
*
|
||||
* @exception IOException if the Configuration can not be initialized. <p>
|
||||
* @exception SecurityException if the caller does not have permission
|
||||
* to initialize the Configuration.
|
||||
*/
|
||||
private void init(URL url) throws IOException {
|
||||
|
||||
boolean initialized = false;
|
||||
FileReader fr = null;
|
||||
String sep = File.separator;
|
||||
|
||||
if ("false".equals(System.getProperty("policy.expandProperties"))) {
|
||||
expandProp = false;
|
||||
}
|
||||
|
||||
// new configuration
|
||||
HashMap<String, LinkedList<AppConfigurationEntry>> newConfig =
|
||||
new HashMap<>();
|
||||
|
||||
if (url != null) {
|
||||
|
||||
/**
|
||||
* If the caller specified a URI via Configuration.getInstance,
|
||||
* we only read from that URI
|
||||
*/
|
||||
if (debugConfig != null) {
|
||||
debugConfig.println("reading " + url);
|
||||
}
|
||||
init(url, newConfig);
|
||||
configuration = newConfig;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Caller did not specify URI via Configuration.getInstance.
|
||||
* Read from URLs listed in the java.security properties file.
|
||||
*/
|
||||
|
||||
String allowSys = java.security.Security.getProperty
|
||||
("policy.allowSystemProperty");
|
||||
|
||||
if ("true".equalsIgnoreCase(allowSys)) {
|
||||
String extra_config = System.getProperty
|
||||
("java.security.auth.login.config");
|
||||
if (extra_config != null) {
|
||||
boolean overrideAll = false;
|
||||
if (extra_config.startsWith("=")) {
|
||||
overrideAll = true;
|
||||
extra_config = extra_config.substring(1);
|
||||
}
|
||||
try {
|
||||
extra_config = PropertyExpander.expand(extra_config);
|
||||
} catch (PropertyExpander.ExpandException peee) {
|
||||
MessageFormat form = new MessageFormat
|
||||
(ResourcesMgr.getString
|
||||
("Unable.to.properly.expand.config",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source = {extra_config};
|
||||
throw new IOException(form.format(source));
|
||||
}
|
||||
|
||||
URL configURL = null;
|
||||
try {
|
||||
configURL = new URL(extra_config);
|
||||
} catch (java.net.MalformedURLException mue) {
|
||||
File configFile = new File(extra_config);
|
||||
if (configFile.exists()) {
|
||||
configURL = configFile.toURI().toURL();
|
||||
} else {
|
||||
MessageFormat form = new MessageFormat
|
||||
(ResourcesMgr.getString
|
||||
("extra.config.No.such.file.or.directory.",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source = {extra_config};
|
||||
throw new IOException(form.format(source));
|
||||
}
|
||||
}
|
||||
|
||||
if (debugConfig != null) {
|
||||
debugConfig.println("reading "+configURL);
|
||||
}
|
||||
init(configURL, newConfig);
|
||||
initialized = true;
|
||||
if (overrideAll) {
|
||||
if (debugConfig != null) {
|
||||
debugConfig.println("overriding other policies!");
|
||||
}
|
||||
configuration = newConfig;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int n = 1;
|
||||
String config_url;
|
||||
while ((config_url = java.security.Security.getProperty
|
||||
("login.config.url."+n)) != null) {
|
||||
try {
|
||||
config_url = PropertyExpander.expand
|
||||
(config_url).replace(File.separatorChar, '/');
|
||||
if (debugConfig != null) {
|
||||
debugConfig.println("\tReading config: " + config_url);
|
||||
}
|
||||
init(new URL(config_url), newConfig);
|
||||
initialized = true;
|
||||
} catch (PropertyExpander.ExpandException peee) {
|
||||
MessageFormat form = new MessageFormat
|
||||
(ResourcesMgr.getString
|
||||
("Unable.to.properly.expand.config",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source = {config_url};
|
||||
throw new IOException(form.format(source));
|
||||
}
|
||||
n++;
|
||||
}
|
||||
|
||||
if (initialized == false && n == 1 && config_url == null) {
|
||||
|
||||
// get the config from the user's home directory
|
||||
if (debugConfig != null) {
|
||||
debugConfig.println("\tReading Policy " +
|
||||
"from ~/.java.login.config");
|
||||
}
|
||||
config_url = System.getProperty("user.home");
|
||||
String userConfigFile = config_url +
|
||||
File.separatorChar + ".java.login.config";
|
||||
|
||||
// No longer throws an exception when there's no config file
|
||||
// at all. Returns an empty Configuration instead.
|
||||
if (new File(userConfigFile).exists()) {
|
||||
init(new File(userConfigFile).toURI().toURL(),
|
||||
newConfig);
|
||||
}
|
||||
}
|
||||
|
||||
configuration = newConfig;
|
||||
}
|
||||
|
||||
private void init(URL config,
|
||||
HashMap<String, LinkedList<AppConfigurationEntry>> newConfig)
|
||||
throws IOException {
|
||||
|
||||
InputStreamReader isr = null;
|
||||
try {
|
||||
isr = new InputStreamReader(getInputStream(config), "UTF-8");
|
||||
readConfig(isr, newConfig);
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
if (debugConfig != null) {
|
||||
debugConfig.println(fnfe.toString());
|
||||
}
|
||||
throw new IOException(ResourcesMgr.getString
|
||||
("Configuration.Error.No.such.file.or.directory",
|
||||
"sun.security.util.AuthResources"));
|
||||
} finally {
|
||||
if (isr != null) {
|
||||
isr.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an entry from the Configuration using an application name
|
||||
* as an index.
|
||||
*
|
||||
* <p>
|
||||
*
|
||||
* @param applicationName the name used to index the Configuration.
|
||||
* @return an array of AppConfigurationEntries which correspond to
|
||||
* the stacked configuration of LoginModules for this
|
||||
* application, or null if this application has no configured
|
||||
* LoginModules.
|
||||
* @param applicationName the name used to index the {@code Configuration}
|
||||
* @return an array of {@code AppConfigurationEntry} which correspond to
|
||||
* the stacked configuration of {@code LoginModule}s for this
|
||||
* application, or null if this application has no configured
|
||||
* {@code LoginModule}s.
|
||||
*/
|
||||
@Override
|
||||
public AppConfigurationEntry[] getAppConfigurationEntry
|
||||
(String applicationName) {
|
||||
(String applicationName) {
|
||||
|
||||
LinkedList<AppConfigurationEntry> list = null;
|
||||
synchronized (configuration) {
|
||||
list = configuration.get(applicationName);
|
||||
}
|
||||
|
||||
if (list == null || list.size() == 0)
|
||||
return null;
|
||||
|
||||
AppConfigurationEntry[] entries =
|
||||
new AppConfigurationEntry[list.size()];
|
||||
Iterator<AppConfigurationEntry> iterator = list.iterator();
|
||||
for (int i = 0; iterator.hasNext(); i++) {
|
||||
AppConfigurationEntry e = iterator.next();
|
||||
entries[i] = new AppConfigurationEntry(e.getLoginModuleName(),
|
||||
e.getControlFlag(),
|
||||
e.getOptions());
|
||||
}
|
||||
return entries;
|
||||
return configFile.engineGetAppConfigurationEntry(applicationName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh and reload the Configuration by re-reading all of the
|
||||
* Refresh and reload the {@code Configuration} by re-reading all of the
|
||||
* login configurations.
|
||||
*
|
||||
* <p>
|
||||
*
|
||||
* @exception SecurityException if the caller does not have permission
|
||||
* to refresh the Configuration.
|
||||
* @throws SecurityException if the caller does not have permission
|
||||
* to refresh the {@code Configuration}
|
||||
*/
|
||||
@Override
|
||||
public synchronized void refresh() {
|
||||
|
||||
java.lang.SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null)
|
||||
sm.checkPermission(new AuthPermission("refreshLoginConfiguration"));
|
||||
|
||||
java.security.AccessController.doPrivileged
|
||||
(new java.security.PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
try {
|
||||
init(url);
|
||||
} catch (java.io.IOException ioe) {
|
||||
throw (SecurityException) new SecurityException
|
||||
(ioe.getLocalizedMessage()).initCause(ioe);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void readConfig(Reader reader,
|
||||
HashMap<String, LinkedList<AppConfigurationEntry>> newConfig)
|
||||
throws IOException {
|
||||
|
||||
int linenum = 1;
|
||||
|
||||
if (!(reader instanceof BufferedReader))
|
||||
reader = new BufferedReader(reader);
|
||||
|
||||
st = new StreamTokenizer(reader);
|
||||
st.quoteChar('"');
|
||||
st.wordChars('$', '$');
|
||||
st.wordChars('_', '_');
|
||||
st.wordChars('-', '-');
|
||||
st.lowerCaseMode(false);
|
||||
st.slashSlashComments(true);
|
||||
st.slashStarComments(true);
|
||||
st.eolIsSignificant(true);
|
||||
|
||||
lookahead = nextToken();
|
||||
while (lookahead != StreamTokenizer.TT_EOF) {
|
||||
parseLoginEntry(newConfig);
|
||||
}
|
||||
}
|
||||
|
||||
private void parseLoginEntry(
|
||||
HashMap<String, LinkedList<AppConfigurationEntry>> newConfig)
|
||||
throws IOException {
|
||||
|
||||
String appName;
|
||||
String moduleClass;
|
||||
String sflag;
|
||||
AppConfigurationEntry.LoginModuleControlFlag controlFlag;
|
||||
LinkedList<AppConfigurationEntry> configEntries = new LinkedList<>();
|
||||
|
||||
// application name
|
||||
appName = st.sval;
|
||||
lookahead = nextToken();
|
||||
|
||||
if (debugParser != null) {
|
||||
debugParser.println("\tReading next config entry: " + appName);
|
||||
}
|
||||
|
||||
match("{");
|
||||
|
||||
// get the modules
|
||||
while (peek("}") == false) {
|
||||
// get the module class name
|
||||
moduleClass = match("module class name");
|
||||
|
||||
// controlFlag (required, optional, etc)
|
||||
sflag = match("controlFlag");
|
||||
if (sflag.equalsIgnoreCase("REQUIRED"))
|
||||
controlFlag =
|
||||
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED;
|
||||
else if (sflag.equalsIgnoreCase("REQUISITE"))
|
||||
controlFlag =
|
||||
AppConfigurationEntry.LoginModuleControlFlag.REQUISITE;
|
||||
else if (sflag.equalsIgnoreCase("SUFFICIENT"))
|
||||
controlFlag =
|
||||
AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT;
|
||||
else if (sflag.equalsIgnoreCase("OPTIONAL"))
|
||||
controlFlag =
|
||||
AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL;
|
||||
else {
|
||||
MessageFormat form = new MessageFormat(ResourcesMgr.getString
|
||||
("Configuration.Error.Invalid.control.flag.flag",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source = {sflag};
|
||||
throw new IOException(form.format(source));
|
||||
}
|
||||
|
||||
// get the args
|
||||
HashMap<String, String> options = new HashMap<>();
|
||||
String key;
|
||||
String value;
|
||||
while (peek(";") == false) {
|
||||
key = match("option key");
|
||||
match("=");
|
||||
try {
|
||||
value = expand(match("option value"));
|
||||
} catch (PropertyExpander.ExpandException peee) {
|
||||
throw new IOException(peee.getLocalizedMessage());
|
||||
}
|
||||
options.put(key, value);
|
||||
}
|
||||
|
||||
lookahead = nextToken();
|
||||
|
||||
// create the new element
|
||||
if (debugParser != null) {
|
||||
debugParser.println("\t\t" + moduleClass + ", " + sflag);
|
||||
java.util.Iterator<String> i = options.keySet().iterator();
|
||||
while (i.hasNext()) {
|
||||
key = i.next();
|
||||
debugParser.println("\t\t\t" +
|
||||
key +
|
||||
"=" +
|
||||
options.get(key));
|
||||
}
|
||||
}
|
||||
AppConfigurationEntry entry = new AppConfigurationEntry
|
||||
(moduleClass,
|
||||
controlFlag,
|
||||
options);
|
||||
configEntries.add(entry);
|
||||
}
|
||||
|
||||
match("}");
|
||||
match(";");
|
||||
|
||||
// add this configuration entry
|
||||
if (newConfig.containsKey(appName)) {
|
||||
MessageFormat form = new MessageFormat(ResourcesMgr.getString
|
||||
("Configuration.Error.Can.not.specify.multiple.entries.for.appName",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source = {appName};
|
||||
throw new IOException(form.format(source));
|
||||
}
|
||||
newConfig.put(appName, configEntries);
|
||||
}
|
||||
|
||||
private String match(String expect) throws IOException {
|
||||
|
||||
String value = null;
|
||||
|
||||
switch(lookahead) {
|
||||
case StreamTokenizer.TT_EOF:
|
||||
|
||||
MessageFormat form1 = new MessageFormat(ResourcesMgr.getString
|
||||
("Configuration.Error.expected.expect.read.end.of.file.",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source1 = {expect};
|
||||
throw new IOException(form1.format(source1));
|
||||
|
||||
case '"':
|
||||
case StreamTokenizer.TT_WORD:
|
||||
|
||||
if (expect.equalsIgnoreCase("module class name") ||
|
||||
expect.equalsIgnoreCase("controlFlag") ||
|
||||
expect.equalsIgnoreCase("option key") ||
|
||||
expect.equalsIgnoreCase("option value")) {
|
||||
value = st.sval;
|
||||
lookahead = nextToken();
|
||||
} else {
|
||||
MessageFormat form = new MessageFormat(ResourcesMgr.getString
|
||||
("Configuration.Error.Line.line.expected.expect.found.value.",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source = {new Integer(linenum), expect, st.sval};
|
||||
throw new IOException(form.format(source));
|
||||
}
|
||||
break;
|
||||
|
||||
case '{':
|
||||
|
||||
if (expect.equalsIgnoreCase("{")) {
|
||||
lookahead = nextToken();
|
||||
} else {
|
||||
MessageFormat form = new MessageFormat(ResourcesMgr.getString
|
||||
("Configuration.Error.Line.line.expected.expect.",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source = {new Integer(linenum), expect, st.sval};
|
||||
throw new IOException(form.format(source));
|
||||
}
|
||||
break;
|
||||
|
||||
case ';':
|
||||
|
||||
if (expect.equalsIgnoreCase(";")) {
|
||||
lookahead = nextToken();
|
||||
} else {
|
||||
MessageFormat form = new MessageFormat(ResourcesMgr.getString
|
||||
("Configuration.Error.Line.line.expected.expect.",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source = {new Integer(linenum), expect, st.sval};
|
||||
throw new IOException(form.format(source));
|
||||
}
|
||||
break;
|
||||
|
||||
case '}':
|
||||
|
||||
if (expect.equalsIgnoreCase("}")) {
|
||||
lookahead = nextToken();
|
||||
} else {
|
||||
MessageFormat form = new MessageFormat(ResourcesMgr.getString
|
||||
("Configuration.Error.Line.line.expected.expect.",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source = {new Integer(linenum), expect, st.sval};
|
||||
throw new IOException(form.format(source));
|
||||
}
|
||||
break;
|
||||
|
||||
case '=':
|
||||
|
||||
if (expect.equalsIgnoreCase("=")) {
|
||||
lookahead = nextToken();
|
||||
} else {
|
||||
MessageFormat form = new MessageFormat(ResourcesMgr.getString
|
||||
("Configuration.Error.Line.line.expected.expect.",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source = {new Integer(linenum), expect, st.sval};
|
||||
throw new IOException(form.format(source));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
MessageFormat form = new MessageFormat(ResourcesMgr.getString
|
||||
("Configuration.Error.Line.line.expected.expect.found.value.",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source = {new Integer(linenum), expect, st.sval};
|
||||
throw new IOException(form.format(source));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private boolean peek(String expect) {
|
||||
boolean found = false;
|
||||
|
||||
switch (lookahead) {
|
||||
case ',':
|
||||
if (expect.equalsIgnoreCase(","))
|
||||
found = true;
|
||||
break;
|
||||
case ';':
|
||||
if (expect.equalsIgnoreCase(";"))
|
||||
found = true;
|
||||
break;
|
||||
case '{':
|
||||
if (expect.equalsIgnoreCase("{"))
|
||||
found = true;
|
||||
break;
|
||||
case '}':
|
||||
if (expect.equalsIgnoreCase("}"))
|
||||
found = true;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
private int nextToken() throws IOException {
|
||||
int tok;
|
||||
while ((tok = st.nextToken()) == StreamTokenizer.TT_EOL) {
|
||||
linenum++;
|
||||
}
|
||||
return tok;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fast path reading from file urls in order to avoid calling
|
||||
* FileURLConnection.connect() which can be quite slow the first time
|
||||
* it is called. We really should clean up FileURLConnection so that
|
||||
* this is not a problem but in the meantime this fix helps reduce
|
||||
* start up time noticeably for the new launcher. -- DAC
|
||||
*/
|
||||
private InputStream getInputStream(URL url) throws IOException {
|
||||
if ("file".equalsIgnoreCase(url.getProtocol())) {
|
||||
// Compatibility notes:
|
||||
//
|
||||
// Code changed from
|
||||
// String path = url.getFile().replace('/', File.separatorChar);
|
||||
// return new FileInputStream(path);
|
||||
//
|
||||
// The original implementation would search for "/tmp/a%20b"
|
||||
// when url is "file:///tmp/a%20b". This is incorrect. The
|
||||
// current codes fix this bug and searches for "/tmp/a b".
|
||||
// For compatibility reasons, when the file "/tmp/a b" does
|
||||
// not exist, the file named "/tmp/a%20b" will be tried.
|
||||
//
|
||||
// This also means that if both file exists, the behavior of
|
||||
// this method is changed, and the current codes choose the
|
||||
// correct one.
|
||||
try {
|
||||
return url.openStream();
|
||||
} catch (Exception e) {
|
||||
String file = url.getPath();
|
||||
if (url.getHost().length() > 0) { // For Windows UNC
|
||||
file = "//" + url.getHost() + file;
|
||||
}
|
||||
if (debugConfig != null) {
|
||||
debugConfig.println("cannot read " + url +
|
||||
", try " + file);
|
||||
}
|
||||
return new FileInputStream(file);
|
||||
}
|
||||
} else {
|
||||
return url.openStream();
|
||||
}
|
||||
}
|
||||
|
||||
private String expand(String value)
|
||||
throws PropertyExpander.ExpandException, IOException {
|
||||
|
||||
if ("".equals(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (expandProp) {
|
||||
|
||||
String s = PropertyExpander.expand(value);
|
||||
|
||||
if (s == null || s.length() == 0) {
|
||||
MessageFormat form = new MessageFormat(ResourcesMgr.getString
|
||||
("Configuration.Error.Line.line.system.property.value.expanded.to.empty.value",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source = {new Integer(linenum), value};
|
||||
throw new IOException(form.format(source));
|
||||
}
|
||||
return s;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
configFile.engineRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,81 +25,668 @@
|
||||
|
||||
package sun.security.provider;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.security.Security;
|
||||
import java.security.URIParameter;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.*;
|
||||
import javax.security.auth.AuthPermission;
|
||||
import javax.security.auth.login.AppConfigurationEntry;
|
||||
import javax.security.auth.login.Configuration;
|
||||
import javax.security.auth.login.ConfigurationSpi;
|
||||
import javax.security.auth.login.AppConfigurationEntry;
|
||||
|
||||
import com.sun.security.auth.login.ConfigFile;
|
||||
import sun.security.util.Debug;
|
||||
import sun.security.util.PropertyExpander;
|
||||
import sun.security.util.ResourcesMgr;
|
||||
|
||||
/**
|
||||
* This class wraps the ConfigFile subclass implementation of Configuration
|
||||
* inside a ConfigurationSpi implementation that is available from the
|
||||
* SUN provider via the Configuration.getInstance calls.
|
||||
* This class represents a default implementation for
|
||||
* {@code javax.security.auth.login.Configuration}.
|
||||
*
|
||||
* <p> This object stores the runtime login configuration representation,
|
||||
* and is the amalgamation of multiple static login
|
||||
* configurations that resides in files.
|
||||
* The algorithm for locating the login configuration file(s) and reading their
|
||||
* information into this {@code Configuration} object is:
|
||||
*
|
||||
* <ol>
|
||||
* <li>
|
||||
* Loop through the security properties,
|
||||
* <i>login.config.url.1</i>, <i>login.config.url.2</i>, ...,
|
||||
* <i>login.config.url.X</i>.
|
||||
* Each property value specifies a <code>URL</code> pointing to a
|
||||
* login configuration file to be loaded. Read in and load
|
||||
* each configuration.
|
||||
*
|
||||
* <li>
|
||||
* The {@code java.lang.System} property
|
||||
* <i>java.security.auth.login.config</i>
|
||||
* may also be set to a {@code URL} pointing to another
|
||||
* login configuration file
|
||||
* (which is the case when a user uses the -D switch at runtime).
|
||||
* If this property is defined, and its use is allowed by the
|
||||
* security property file (the Security property,
|
||||
* <i>policy.allowSystemProperty</i> is set to <i>true</i>),
|
||||
* also load that login configuration.
|
||||
*
|
||||
* <li>
|
||||
* If the <i>java.security.auth.login.config</i> property is defined using
|
||||
* "==" (rather than "="), then ignore all other specified
|
||||
* login configurations and only load this configuration.
|
||||
*
|
||||
* <li>
|
||||
* If no system or security properties were set, try to read from the file,
|
||||
* ${user.home}/.java.login.config, where ${user.home} is the value
|
||||
* represented by the "user.home" System property.
|
||||
* </ol>
|
||||
*
|
||||
* <p> The configuration syntax supported by this implementation
|
||||
* is exactly that syntax specified in the
|
||||
* {@code javax.security.auth.login.Configuration} class.
|
||||
*
|
||||
* @see javax.security.auth.login.LoginContext
|
||||
* @see java.security.Security security properties
|
||||
*/
|
||||
public final class ConfigSpiFile extends ConfigurationSpi {
|
||||
|
||||
private ConfigFile cf;
|
||||
private URL url;
|
||||
private boolean expandProp = true;
|
||||
private Map<String, List<AppConfigurationEntry>> configuration;
|
||||
private int linenum;
|
||||
private StreamTokenizer st;
|
||||
private int lookahead;
|
||||
|
||||
private static Debug debugConfig = Debug.getInstance("configfile");
|
||||
private static Debug debugParser = Debug.getInstance("configparser");
|
||||
|
||||
/**
|
||||
* Create a new {@code Configuration} object.
|
||||
*
|
||||
* @throws SecurityException if the {@code Configuration} can not be
|
||||
* initialized
|
||||
*/
|
||||
public ConfigSpiFile() {
|
||||
try {
|
||||
init();
|
||||
} catch (IOException ioe) {
|
||||
throw new SecurityException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code Configuration} object from the specified {@code URI}.
|
||||
*
|
||||
* @param uri the {@code URI}
|
||||
* @throws SecurityException if the {@code Configuration} can not be
|
||||
* initialized
|
||||
* @throws NullPointerException if {@code uri} is null
|
||||
*/
|
||||
public ConfigSpiFile(URI uri) {
|
||||
// only load config from the specified URI
|
||||
try {
|
||||
url = uri.toURL();
|
||||
init();
|
||||
} catch (IOException ioe) {
|
||||
throw new SecurityException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
public ConfigSpiFile(final Configuration.Parameters params)
|
||||
throws java.io.IOException {
|
||||
throws IOException {
|
||||
|
||||
// call in a doPrivileged
|
||||
//
|
||||
// we have already passed the Configuration.getInstance
|
||||
// security check. also this class is not freely accessible
|
||||
// (it is in the "sun" package).
|
||||
//
|
||||
// we can not put doPrivileged calls into
|
||||
// ConfigFile because it is a public com.sun class
|
||||
|
||||
try {
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
if (params == null) {
|
||||
cf = new ConfigFile();
|
||||
} else {
|
||||
if (!(params instanceof URIParameter)) {
|
||||
throw new IllegalArgumentException
|
||||
("Unrecognized parameter: " + params);
|
||||
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
|
||||
public Void run() throws IOException {
|
||||
if (params == null) {
|
||||
init();
|
||||
} else {
|
||||
if (!(params instanceof URIParameter)) {
|
||||
throw new IllegalArgumentException
|
||||
("Unrecognized parameter: " + params);
|
||||
}
|
||||
URIParameter uriParam = (URIParameter)params;
|
||||
url = uriParam.getURI().toURL();
|
||||
init();
|
||||
}
|
||||
URIParameter uriParam = (URIParameter)params;
|
||||
|
||||
cf = new ConfigFile(uriParam.getURI());
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} catch (SecurityException se) {
|
||||
|
||||
// if ConfigFile threw a standalone SecurityException
|
||||
// (no cause), re-throw it.
|
||||
//
|
||||
// ConfigFile chains checked IOExceptions to SecurityException.
|
||||
|
||||
Throwable cause = se.getCause();
|
||||
if (cause != null && cause instanceof java.io.IOException) {
|
||||
throw (java.io.IOException)cause;
|
||||
}
|
||||
|
||||
// unrecognized cause
|
||||
throw se;
|
||||
} catch (PrivilegedActionException pae) {
|
||||
throw (IOException)pae.getException();
|
||||
}
|
||||
|
||||
// if ConfigFile throws some other RuntimeException,
|
||||
// if init() throws some other RuntimeException,
|
||||
// let it percolate up naturally.
|
||||
}
|
||||
|
||||
protected AppConfigurationEntry[] engineGetAppConfigurationEntry
|
||||
(String name) {
|
||||
return cf.getAppConfigurationEntry(name);
|
||||
/**
|
||||
* Read and initialize the entire login Configuration from the configured
|
||||
* URL.
|
||||
*
|
||||
* @throws IOException if the Configuration can not be initialized
|
||||
* @throws SecurityException if the caller does not have permission
|
||||
* to initialize the Configuration
|
||||
*/
|
||||
private void init() throws IOException {
|
||||
|
||||
boolean initialized = false;
|
||||
|
||||
// For policy.expandProperties, check if either a security or system
|
||||
// property is set to false (old code erroneously checked the system
|
||||
// prop so we must check both to preserve compatibility).
|
||||
String expand = Security.getProperty("policy.expandProperties");
|
||||
if (expand == null) {
|
||||
expand = System.getProperty("policy.expandProperties");
|
||||
}
|
||||
if ("false".equals(expand)) {
|
||||
expandProp = false;
|
||||
}
|
||||
|
||||
// new configuration
|
||||
Map<String, List<AppConfigurationEntry>> newConfig = new HashMap<>();
|
||||
|
||||
if (url != null) {
|
||||
/**
|
||||
* If the caller specified a URI via Configuration.getInstance,
|
||||
* we only read from that URI
|
||||
*/
|
||||
if (debugConfig != null) {
|
||||
debugConfig.println("reading " + url);
|
||||
}
|
||||
init(url, newConfig);
|
||||
configuration = newConfig;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Caller did not specify URI via Configuration.getInstance.
|
||||
* Read from URLs listed in the java.security properties file.
|
||||
*/
|
||||
String allowSys = Security.getProperty("policy.allowSystemProperty");
|
||||
|
||||
if ("true".equalsIgnoreCase(allowSys)) {
|
||||
String extra_config = System.getProperty
|
||||
("java.security.auth.login.config");
|
||||
if (extra_config != null) {
|
||||
boolean overrideAll = false;
|
||||
if (extra_config.startsWith("=")) {
|
||||
overrideAll = true;
|
||||
extra_config = extra_config.substring(1);
|
||||
}
|
||||
try {
|
||||
extra_config = PropertyExpander.expand(extra_config);
|
||||
} catch (PropertyExpander.ExpandException peee) {
|
||||
MessageFormat form = new MessageFormat
|
||||
(ResourcesMgr.getString
|
||||
("Unable.to.properly.expand.config",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source = {extra_config};
|
||||
throw new IOException(form.format(source));
|
||||
}
|
||||
|
||||
URL configURL = null;
|
||||
try {
|
||||
configURL = new URL(extra_config);
|
||||
} catch (MalformedURLException mue) {
|
||||
File configFile = new File(extra_config);
|
||||
if (configFile.exists()) {
|
||||
configURL = configFile.toURI().toURL();
|
||||
} else {
|
||||
MessageFormat form = new MessageFormat
|
||||
(ResourcesMgr.getString
|
||||
("extra.config.No.such.file.or.directory.",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source = {extra_config};
|
||||
throw new IOException(form.format(source));
|
||||
}
|
||||
}
|
||||
|
||||
if (debugConfig != null) {
|
||||
debugConfig.println("reading "+configURL);
|
||||
}
|
||||
init(configURL, newConfig);
|
||||
initialized = true;
|
||||
if (overrideAll) {
|
||||
if (debugConfig != null) {
|
||||
debugConfig.println("overriding other policies!");
|
||||
}
|
||||
configuration = newConfig;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int n = 1;
|
||||
String config_url;
|
||||
while ((config_url = Security.getProperty
|
||||
("login.config.url."+n)) != null) {
|
||||
try {
|
||||
config_url = PropertyExpander.expand
|
||||
(config_url).replace(File.separatorChar, '/');
|
||||
if (debugConfig != null) {
|
||||
debugConfig.println("\tReading config: " + config_url);
|
||||
}
|
||||
init(new URL(config_url), newConfig);
|
||||
initialized = true;
|
||||
} catch (PropertyExpander.ExpandException peee) {
|
||||
MessageFormat form = new MessageFormat
|
||||
(ResourcesMgr.getString
|
||||
("Unable.to.properly.expand.config",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source = {config_url};
|
||||
throw new IOException(form.format(source));
|
||||
}
|
||||
n++;
|
||||
}
|
||||
|
||||
if (initialized == false && n == 1 && config_url == null) {
|
||||
|
||||
// get the config from the user's home directory
|
||||
if (debugConfig != null) {
|
||||
debugConfig.println("\tReading Policy " +
|
||||
"from ~/.java.login.config");
|
||||
}
|
||||
config_url = System.getProperty("user.home");
|
||||
String userConfigFile = config_url +
|
||||
File.separatorChar + ".java.login.config";
|
||||
|
||||
// No longer throws an exception when there's no config file
|
||||
// at all. Returns an empty Configuration instead.
|
||||
if (new File(userConfigFile).exists()) {
|
||||
init(new File(userConfigFile).toURI().toURL(),
|
||||
newConfig);
|
||||
}
|
||||
}
|
||||
|
||||
configuration = newConfig;
|
||||
}
|
||||
|
||||
protected void engineRefresh() {
|
||||
cf.refresh();
|
||||
private void init(URL config,
|
||||
Map<String, List<AppConfigurationEntry>> newConfig)
|
||||
throws IOException {
|
||||
|
||||
try (InputStreamReader isr
|
||||
= new InputStreamReader(getInputStream(config), "UTF-8")) {
|
||||
readConfig(isr, newConfig);
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
if (debugConfig != null) {
|
||||
debugConfig.println(fnfe.toString());
|
||||
}
|
||||
throw new IOException(ResourcesMgr.getString
|
||||
("Configuration.Error.No.such.file.or.directory",
|
||||
"sun.security.util.AuthResources"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an entry from the Configuration using an application name
|
||||
* as an index.
|
||||
*
|
||||
* @param applicationName the name used to index the Configuration.
|
||||
* @return an array of AppConfigurationEntries which correspond to
|
||||
* the stacked configuration of LoginModules for this
|
||||
* application, or null if this application has no configured
|
||||
* LoginModules.
|
||||
*/
|
||||
@Override
|
||||
public AppConfigurationEntry[] engineGetAppConfigurationEntry
|
||||
(String applicationName) {
|
||||
|
||||
List<AppConfigurationEntry> list = null;
|
||||
synchronized (configuration) {
|
||||
list = configuration.get(applicationName);
|
||||
}
|
||||
|
||||
if (list == null || list.size() == 0)
|
||||
return null;
|
||||
|
||||
AppConfigurationEntry[] entries =
|
||||
new AppConfigurationEntry[list.size()];
|
||||
Iterator<AppConfigurationEntry> iterator = list.iterator();
|
||||
for (int i = 0; iterator.hasNext(); i++) {
|
||||
AppConfigurationEntry e = iterator.next();
|
||||
entries[i] = new AppConfigurationEntry(e.getLoginModuleName(),
|
||||
e.getControlFlag(),
|
||||
e.getOptions());
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh and reload the Configuration by re-reading all of the
|
||||
* login configurations.
|
||||
*
|
||||
* @throws SecurityException if the caller does not have permission
|
||||
* to refresh the Configuration.
|
||||
*/
|
||||
@Override
|
||||
public synchronized void engineRefresh() {
|
||||
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null)
|
||||
sm.checkPermission(new AuthPermission("refreshLoginConfiguration"));
|
||||
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
try {
|
||||
init();
|
||||
} catch (IOException ioe) {
|
||||
throw new SecurityException(ioe.getLocalizedMessage(), ioe);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void readConfig(Reader reader,
|
||||
Map<String, List<AppConfigurationEntry>> newConfig)
|
||||
throws IOException {
|
||||
|
||||
linenum = 1;
|
||||
|
||||
if (!(reader instanceof BufferedReader))
|
||||
reader = new BufferedReader(reader);
|
||||
|
||||
st = new StreamTokenizer(reader);
|
||||
st.quoteChar('"');
|
||||
st.wordChars('$', '$');
|
||||
st.wordChars('_', '_');
|
||||
st.wordChars('-', '-');
|
||||
st.lowerCaseMode(false);
|
||||
st.slashSlashComments(true);
|
||||
st.slashStarComments(true);
|
||||
st.eolIsSignificant(true);
|
||||
|
||||
lookahead = nextToken();
|
||||
while (lookahead != StreamTokenizer.TT_EOF) {
|
||||
parseLoginEntry(newConfig);
|
||||
}
|
||||
}
|
||||
|
||||
private void parseLoginEntry(
|
||||
Map<String, List<AppConfigurationEntry>> newConfig)
|
||||
throws IOException {
|
||||
|
||||
List<AppConfigurationEntry> configEntries = new LinkedList<>();
|
||||
|
||||
// application name
|
||||
String appName = st.sval;
|
||||
lookahead = nextToken();
|
||||
|
||||
if (debugParser != null) {
|
||||
debugParser.println("\tReading next config entry: " + appName);
|
||||
}
|
||||
|
||||
match("{");
|
||||
|
||||
// get the modules
|
||||
while (peek("}") == false) {
|
||||
// get the module class name
|
||||
String moduleClass = match("module class name");
|
||||
|
||||
// controlFlag (required, optional, etc)
|
||||
AppConfigurationEntry.LoginModuleControlFlag controlFlag;
|
||||
String sflag = match("controlFlag").toUpperCase();
|
||||
switch (sflag) {
|
||||
case "REQUIRED":
|
||||
controlFlag =
|
||||
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED;
|
||||
break;
|
||||
case "REQUISITE":
|
||||
controlFlag =
|
||||
AppConfigurationEntry.LoginModuleControlFlag.REQUISITE;
|
||||
break;
|
||||
case "SUFFICIENT":
|
||||
controlFlag =
|
||||
AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT;
|
||||
break;
|
||||
case "OPTIONAL":
|
||||
controlFlag =
|
||||
AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL;
|
||||
break;
|
||||
default:
|
||||
MessageFormat form = new MessageFormat(
|
||||
ResourcesMgr.getString
|
||||
("Configuration.Error.Invalid.control.flag.flag",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source = {sflag};
|
||||
throw new IOException(form.format(source));
|
||||
}
|
||||
|
||||
// get the args
|
||||
Map<String, String> options = new HashMap<>();
|
||||
while (peek(";") == false) {
|
||||
String key = match("option key");
|
||||
match("=");
|
||||
try {
|
||||
options.put(key, expand(match("option value")));
|
||||
} catch (PropertyExpander.ExpandException peee) {
|
||||
throw new IOException(peee.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
|
||||
lookahead = nextToken();
|
||||
|
||||
// create the new element
|
||||
if (debugParser != null) {
|
||||
debugParser.println("\t\t" + moduleClass + ", " + sflag);
|
||||
for (String key : options.keySet()) {
|
||||
debugParser.println("\t\t\t" + key +
|
||||
"=" + options.get(key));
|
||||
}
|
||||
}
|
||||
configEntries.add(new AppConfigurationEntry(moduleClass,
|
||||
controlFlag, options));
|
||||
}
|
||||
|
||||
match("}");
|
||||
match(";");
|
||||
|
||||
// add this configuration entry
|
||||
if (newConfig.containsKey(appName)) {
|
||||
MessageFormat form = new MessageFormat(ResourcesMgr.getString
|
||||
("Configuration.Error.Can.not.specify.multiple.entries.for.appName",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source = {appName};
|
||||
throw new IOException(form.format(source));
|
||||
}
|
||||
newConfig.put(appName, configEntries);
|
||||
}
|
||||
|
||||
private String match(String expect) throws IOException {
|
||||
|
||||
String value = null;
|
||||
|
||||
switch(lookahead) {
|
||||
case StreamTokenizer.TT_EOF:
|
||||
|
||||
MessageFormat form1 = new MessageFormat(ResourcesMgr.getString
|
||||
("Configuration.Error.expected.expect.read.end.of.file.",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source1 = {expect};
|
||||
throw new IOException(form1.format(source1));
|
||||
|
||||
case '"':
|
||||
case StreamTokenizer.TT_WORD:
|
||||
|
||||
if (expect.equalsIgnoreCase("module class name") ||
|
||||
expect.equalsIgnoreCase("controlFlag") ||
|
||||
expect.equalsIgnoreCase("option key") ||
|
||||
expect.equalsIgnoreCase("option value")) {
|
||||
value = st.sval;
|
||||
lookahead = nextToken();
|
||||
} else {
|
||||
MessageFormat form = new MessageFormat(ResourcesMgr.getString
|
||||
("Configuration.Error.Line.line.expected.expect.found.value.",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source = {new Integer(linenum), expect, st.sval};
|
||||
throw new IOException(form.format(source));
|
||||
}
|
||||
break;
|
||||
|
||||
case '{':
|
||||
|
||||
if (expect.equalsIgnoreCase("{")) {
|
||||
lookahead = nextToken();
|
||||
} else {
|
||||
MessageFormat form = new MessageFormat(ResourcesMgr.getString
|
||||
("Configuration.Error.Line.line.expected.expect.",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source = {new Integer(linenum), expect, st.sval};
|
||||
throw new IOException(form.format(source));
|
||||
}
|
||||
break;
|
||||
|
||||
case ';':
|
||||
|
||||
if (expect.equalsIgnoreCase(";")) {
|
||||
lookahead = nextToken();
|
||||
} else {
|
||||
MessageFormat form = new MessageFormat(ResourcesMgr.getString
|
||||
("Configuration.Error.Line.line.expected.expect.",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source = {new Integer(linenum), expect, st.sval};
|
||||
throw new IOException(form.format(source));
|
||||
}
|
||||
break;
|
||||
|
||||
case '}':
|
||||
|
||||
if (expect.equalsIgnoreCase("}")) {
|
||||
lookahead = nextToken();
|
||||
} else {
|
||||
MessageFormat form = new MessageFormat(ResourcesMgr.getString
|
||||
("Configuration.Error.Line.line.expected.expect.",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source = {new Integer(linenum), expect, st.sval};
|
||||
throw new IOException(form.format(source));
|
||||
}
|
||||
break;
|
||||
|
||||
case '=':
|
||||
|
||||
if (expect.equalsIgnoreCase("=")) {
|
||||
lookahead = nextToken();
|
||||
} else {
|
||||
MessageFormat form = new MessageFormat(ResourcesMgr.getString
|
||||
("Configuration.Error.Line.line.expected.expect.",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source = {new Integer(linenum), expect, st.sval};
|
||||
throw new IOException(form.format(source));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
MessageFormat form = new MessageFormat(ResourcesMgr.getString
|
||||
("Configuration.Error.Line.line.expected.expect.found.value.",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source = {new Integer(linenum), expect, st.sval};
|
||||
throw new IOException(form.format(source));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private boolean peek(String expect) {
|
||||
boolean found = false;
|
||||
|
||||
switch (lookahead) {
|
||||
case ',':
|
||||
if (expect.equalsIgnoreCase(","))
|
||||
found = true;
|
||||
break;
|
||||
case ';':
|
||||
if (expect.equalsIgnoreCase(";"))
|
||||
found = true;
|
||||
break;
|
||||
case '{':
|
||||
if (expect.equalsIgnoreCase("{"))
|
||||
found = true;
|
||||
break;
|
||||
case '}':
|
||||
if (expect.equalsIgnoreCase("}"))
|
||||
found = true;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
private int nextToken() throws IOException {
|
||||
int tok;
|
||||
while ((tok = st.nextToken()) == StreamTokenizer.TT_EOL) {
|
||||
linenum++;
|
||||
}
|
||||
return tok;
|
||||
}
|
||||
|
||||
private InputStream getInputStream(URL url) throws IOException {
|
||||
if ("file".equalsIgnoreCase(url.getProtocol())) {
|
||||
// Compatibility notes:
|
||||
//
|
||||
// Code changed from
|
||||
// String path = url.getFile().replace('/', File.separatorChar);
|
||||
// return new FileInputStream(path);
|
||||
//
|
||||
// The original implementation would search for "/tmp/a%20b"
|
||||
// when url is "file:///tmp/a%20b". This is incorrect. The
|
||||
// current codes fix this bug and searches for "/tmp/a b".
|
||||
// For compatibility reasons, when the file "/tmp/a b" does
|
||||
// not exist, the file named "/tmp/a%20b" will be tried.
|
||||
//
|
||||
// This also means that if both file exists, the behavior of
|
||||
// this method is changed, and the current codes choose the
|
||||
// correct one.
|
||||
try {
|
||||
return url.openStream();
|
||||
} catch (Exception e) {
|
||||
String file = url.getPath();
|
||||
if (url.getHost().length() > 0) { // For Windows UNC
|
||||
file = "//" + url.getHost() + file;
|
||||
}
|
||||
if (debugConfig != null) {
|
||||
debugConfig.println("cannot read " + url +
|
||||
", try " + file);
|
||||
}
|
||||
return new FileInputStream(file);
|
||||
}
|
||||
} else {
|
||||
return url.openStream();
|
||||
}
|
||||
}
|
||||
|
||||
private String expand(String value)
|
||||
throws PropertyExpander.ExpandException, IOException {
|
||||
|
||||
if (value.isEmpty()) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (expandProp) {
|
||||
|
||||
String s = PropertyExpander.expand(value);
|
||||
|
||||
if (s == null || s.length() == 0) {
|
||||
MessageFormat form = new MessageFormat(ResourcesMgr.getString
|
||||
("Configuration.Error.Line.line.system.property.value.expanded.to.empty.value",
|
||||
"sun.security.util.AuthResources"));
|
||||
Object[] source = {new Integer(linenum), value};
|
||||
throw new IOException(form.format(source));
|
||||
}
|
||||
return s;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user