|
Java example source code file (Config.java)
The Config.java Java example source code/* * Copyright (c) 2000, 2013, 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 * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * * (C) Copyright IBM Corp. 1999 All Rights Reserved. * Copyright 1997 The Open Group Research Institute. All rights reserved. */ package sun.security.krb5; import java.io.File; import java.io.FileInputStream; import java.util.Hashtable; import java.util.Vector; import java.util.ArrayList; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; import java.util.StringTokenizer; import java.net.InetAddress; import java.net.UnknownHostException; import java.security.AccessController; import java.security.PrivilegedExceptionAction; import java.util.Arrays; import java.util.List; import java.util.Locale; import sun.net.dns.ResolverConfiguration; import sun.security.krb5.internal.crypto.EType; import sun.security.krb5.internal.Krb5; /** * This class maintains key-value pairs of Kerberos configurable constants * from configuration file or from user specified system properties. */ public class Config { /* * Only allow a single instance of Config. */ private static Config singleton = null; /* * Hashtable used to store configuration information. */ private Hashtable<String,Object> stanzaTable = new Hashtable<>(); private static boolean DEBUG = sun.security.krb5.internal.Krb5.DEBUG; // these are used for hexdecimal calculation. private static final int BASE16_0 = 1; private static final int BASE16_1 = 16; private static final int BASE16_2 = 16 * 16; private static final int BASE16_3 = 16 * 16 * 16; /** * Specified by system properties. Must be both null or non-null. */ private final String defaultRealm; private final String defaultKDC; // used for native interface private static native String getWindowsDirectory(boolean isSystem); /** * Gets an instance of Config class. One and only one instance (the * singleton) is returned. * * @exception KrbException if error occurs when constructing a Config * instance. Possible causes would be either of java.security.krb5.realm or * java.security.krb5.kdc not specified, error reading configuration file. */ public static synchronized Config getInstance() throws KrbException { if (singleton == null) { singleton = new Config(); } return singleton; } /** * Refresh and reload the Configuration. This could involve, * for example reading the Configuration file again or getting * the java.security.krb5.* system properties again. This method * also tries its best to update static fields in other classes * that depend on the configuration. * * @exception KrbException if error occurs when constructing a Config * instance. Possible causes would be either of java.security.krb5.realm or * java.security.krb5.kdc not specified, error reading configuration file. */ public static synchronized void refresh() throws KrbException { singleton = new Config(); KdcComm.initStatic(); EType.initStatic(); Checksum.initStatic(); } private static boolean isMacosLionOrBetter() { // split the "10.x.y" version number String osname = getProperty("os.name"); if (!osname.contains("OS X")) { return false; } String osVersion = getProperty("os.version"); String[] fragments = osVersion.split("\\."); // sanity check the "10." part of the version if (!fragments[0].equals("10")) return false; if (fragments.length < 2) return false; // check if Mac OS X 10.7(.y) try { int minorVers = Integer.parseInt(fragments[1]); if (minorVers >= 7) return true; } catch (NumberFormatException e) { // was not an integer } return false; } /** * Private constructor - can not be instantiated externally. */ private Config() throws KrbException { /* * If either one system property is specified, we throw exception. */ String tmp = getProperty("java.security.krb5.kdc"); if (tmp != null) { // The user can specify a list of kdc hosts separated by ":" defaultKDC = tmp.replace(':', ' '); } else { defaultKDC = null; } defaultRealm = getProperty("java.security.krb5.realm"); if ((defaultKDC == null && defaultRealm != null) || (defaultRealm == null && defaultKDC != null)) { throw new KrbException ("System property java.security.krb5.kdc and " + "java.security.krb5.realm both must be set or " + "neither must be set."); } // Always read the Kerberos configuration file try { List<String> configFile; String fileName = getJavaFileName(); if (fileName != null) { configFile = loadConfigFile(fileName); stanzaTable = parseStanzaTable(configFile); if (DEBUG) { System.out.println("Loaded from Java config"); } } else { boolean found = false; if (isMacosLionOrBetter()) { try { stanzaTable = SCDynamicStoreConfig.getConfig(); if (DEBUG) { System.out.println("Loaded from SCDynamicStoreConfig"); } found = true; } catch (IOException ioe) { // OK. Will go on with file } } if (!found) { fileName = getNativeFileName(); configFile = loadConfigFile(fileName); stanzaTable = parseStanzaTable(configFile); if (DEBUG) { System.out.println("Loaded from native config"); } } } } catch (IOException ioe) { // I/O error, mostly like krb5.conf missing. // No problem. We'll use DNS or system property etc. } } /** * Gets the last-defined string value for the specified keys. * @param keys the keys, as an array from section name, sub-section names * (if any), to value name. * @return the value. When there are multiple values for the same key, * returns the last one. {@code null} is returned if not all the keys are * defined. For example, {@code get("libdefaults", "forwardable")} will * return null if "forwardable" is not defined in [libdefaults], and * {@code get("realms", "R", "kdc")} will return null if "R" is not * defined in [realms] or "kdc" is not defined for "R". * @throws IllegalArgumentException if any of the keys is illegal, either * because a key not the last one is not a (sub)section name or the last * key is still a section name. For example, {@code get("libdefaults")} * throws this exception because [libdefaults] is a section name instead of * a value name, and {@code get("libdefaults", "forwardable", "tail")} * also throws this exception because "forwardable" is already a value name * and has no sub-key at all (given "forwardable" is defined, otherwise, * this method has no knowledge if it's a value name or a section name), */ public String get(String... keys) { Vector<String> v = getString0(keys); if (v == null) return null; return v.lastElement(); } /** * Gets all values for the specified keys. * @throws IllegalArgumentException if any of the keys is illegal * (See {@link #get}) */ public String getAll(String... keys) { Vector<String> v = getString0(keys); if (v == null) return null; StringBuilder sb = new StringBuilder(); boolean first = true; for (String s: v) { if (first) { sb.append(s); first = false; } else { sb.append(' ').append(s); } } return sb.toString(); } /** * Returns true if keys exists, can be either final string(s) or sub-stanza * @throws IllegalArgumentException if any of the keys is illegal * (See {@link #get}) */ public boolean exists(String... keys) { return get0(keys) != null; } // Returns final string value(s) for given keys. @SuppressWarnings("unchecked") private Vector<String> getString0(String... keys) { try { return (Vector<String>)get0(keys); } catch (ClassCastException cce) { throw new IllegalArgumentException(cce); } } // Internal method. Returns the value for keys, which can be a sub-stanza // or final string value(s). // The only method (except for toString) that reads stanzaTable directly. @SuppressWarnings("unchecked") private Object get0(String... keys) { Object current = stanzaTable; try { for (String key: keys) { current = ((Hashtable<String,Object>)current).get(key); if (current == null) return null; } return current; } catch (ClassCastException cce) { throw new IllegalArgumentException(cce); } } /** * Gets the int value for the specified keys. * @param keys the keys * @return the int value, Integer.MIN_VALUE is returned if it cannot be * found or the value is not a legal integer. * @throw IllegalArgumentException if any of the keys is illegal * @see #get(java.lang.String[]) */ public int getIntValue(String... keys) { String result = get(keys); int value = Integer.MIN_VALUE; if (result != null) { try { value = parseIntValue(result); } catch (NumberFormatException e) { if (DEBUG) { System.out.println("Exception in getting value of " + Arrays.toString(keys) + " " + e.getMessage()); System.out.println("Setting " + Arrays.toString(keys) + " to minimum value"); } value = Integer.MIN_VALUE; } } return value; } /** * Gets the boolean value for the specified keys. * @param keys the keys * @return the boolean value, false is returned if it cannot be * found or the value is not "true" (case insensitive). * @throw IllegalArgumentException if any of the keys is illegal * @see #get(java.lang.String[]) */ public boolean getBooleanValue(String... keys) { String val = get(keys); if (val != null && val.equalsIgnoreCase("true")) { return true; } else { return false; } } /** * Parses a string to an integer. The convertible strings include the * string representations of positive integers, negative integers, and * hex decimal integers. Valid inputs are, e.g., -1234, +1234, * 0x40000. * * @param input the String to be converted to an Integer. * @return an numeric value represented by the string * @exception NumberFormationException if the String does not contain a * parsable integer. */ private int parseIntValue(String input) throws NumberFormatException { int value = 0; if (input.startsWith("+")) { String temp = input.substring(1); return Integer.parseInt(temp); } else if (input.startsWith("0x")) { String temp = input.substring(2); char[] chars = temp.toCharArray(); if (chars.length > 8) { throw new NumberFormatException(); } else { for (int i = 0; i < chars.length; i++) { int index = chars.length - i - 1; switch (chars[i]) { case '0': value += 0; break; case '1': value += 1 * getBase(index); break; case '2': value += 2 * getBase(index); break; case '3': value += 3 * getBase(index); break; case '4': value += 4 * getBase(index); break; case '5': value += 5 * getBase(index); break; case '6': value += 6 * getBase(index); break; case '7': value += 7 * getBase(index); break; case '8': value += 8 * getBase(index); break; case '9': value += 9 * getBase(index); break; case 'a': case 'A': value += 10 * getBase(index); break; case 'b': case 'B': value += 11 * getBase(index); break; case 'c': case 'C': value += 12 * getBase(index); break; case 'd': case 'D': value += 13 * getBase(index); break; case 'e': case 'E': value += 14 * getBase(index); break; case 'f': case 'F': value += 15 * getBase(index); break; default: throw new NumberFormatException("Invalid numerical format"); } } } if (value < 0) { throw new NumberFormatException("Data overflow."); } } else { value = Integer.parseInt(input); } return value; } private int getBase(int i) { int result = 16; switch (i) { case 0: result = BASE16_0; break; case 1: result = BASE16_1; break; case 2: result = BASE16_2; break; case 3: result = BASE16_3; break; default: for (int j = 1; j < i; j++) { result *= 16; } } return result; } /** * Reads lines to the memory from the configuration file. * * Configuration file contains information about the default realm, * ticket parameters, location of the KDC and the admin server for * known realms, etc. The file is divided into sections. Each section * contains one or more name/value pairs with one pair per line. A * typical file would be: * <pre> * [libdefaults] * default_realm = EXAMPLE.COM * default_tgs_enctypes = des-cbc-md5 * default_tkt_enctypes = des-cbc-md5 * [realms] * EXAMPLE.COM = { * kdc = kerberos.example.com * kdc = kerberos-1.example.com * admin_server = kerberos.example.com * } * SAMPLE_COM = { * kdc = orange.sample.com * admin_server = orange.sample.com * } * [domain_realm] * blue.sample.com = TEST.SAMPLE.COM * .backup.com = EXAMPLE.COM * </pre> * @return an ordered list of strings representing the config file after * some initial processing, including:<ol> * <li> Comment lines and empty lines are removed * <li> "{" not at the end of a line is appended to the previous line * <li> The content of a section is also placed between "{" and "}". * <li> Lines are trimmed * @throws IOException if there is an I/O error * @throws KrbException if there is a file format error */ private List<String> loadConfigFile(final String fileName) throws IOException, KrbException { try { List<String> v = new ArrayList<>(); try (BufferedReader br = new BufferedReader(new InputStreamReader( AccessController.doPrivileged( new PrivilegedExceptionAction<FileInputStream> () { public FileInputStream run() throws IOException { return new FileInputStream(fileName); } })))) { String line; String previous = null; while ((line = br.readLine()) != null) { line = line.trim(); if (line.startsWith("#") || line.isEmpty()) { // ignore comments and blank line // Comments start with #. continue; } // In practice, a subsection might look like: // [realms] // EXAMPLE.COM = // { // kdc = kerberos.example.com // ... // } // Before parsed into stanza table, it needs to be // converted into a canonicalized style (no indent): // realms = { // EXAMPLE.COM = { // kdc = kerberos.example.com // ... // } // } // if (line.startsWith("[")) { if (!line.endsWith("]")) { throw new KrbException("Illegal config content:" + line); } if (previous != null) { v.add(previous); v.add("}"); } String title = line.substring( 1, line.length()-1).trim(); if (title.isEmpty()) { throw new KrbException("Illegal config content:" + line); } previous = title + " = {"; } else if (line.startsWith("{")) { if (previous == null) { throw new KrbException( "Config file should not start with \"{\""); } previous += " {"; if (line.length() > 1) { // { and content on the same line v.add(previous); previous = line.substring(1).trim(); } } else { if (previous == null) { throw new KrbException( "Config file must starts with a section"); } v.add(previous); previous = line; } } if (previous != null) { v.add(previous); v.add("}"); } } return v; } catch (java.security.PrivilegedActionException pe) { throw (IOException)pe.getException(); } } /** * Parses stanza names and values from configuration file to * stanzaTable (Hashtable). Hashtable key would be stanza names, * (libdefaults, realms, domain_realms, etc), and the hashtable value * would be another hashtable which contains the key-value pairs under * a stanza name. The value of this sub-hashtable can be another hashtable * containing another sub-sub-section or a vector of strings for * final values (even if there is only one value defined). * <p> * For duplicates section names, the latter overwrites the former. For * duplicate value names, the values are in a vector in its appearing order. * </ol> * Please note that this behavior is Java traditional. and it is * not the same as the MIT krb5 behavior, where:<ol> * <li>Duplicated root sections will be merged * <li>For duplicated sub-sections, the former overwrites the latter * <li>Duplicate keys for values are always saved in a vector * </ol> * @param v the strings in the file, never null, might be empty * @throws KrbException if there is a file format error */ @SuppressWarnings("unchecked") private Hashtable<String,Object> parseStanzaTable(List Other Java examples (source code examples)Here is a short list of links related to this Java Config.java source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.