/*
 * Copyright (c) 2014, 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.
 */

package com.oracle.security.ucrypto;

import java.io.*;
import static java.io.StreamTokenizer.*;
import java.math.BigInteger;
import java.util.*;

import java.security.*;

import sun.security.action.GetPropertyAction;
import sun.security.util.PropertyExpander;

Configuration container and file parsing. Currently, there is only one supported entry "disabledServices" for disabling crypto services. Its syntax is as follows: disabledServices = { . ... } where can be "MessageDigest", "Cipher", etc. and reprepresents the value that's passed into the various getInstance() calls.
Since: 9
/** * Configuration container and file parsing. * * Currently, there is only one supported entry "disabledServices" * for disabling crypto services. Its syntax is as follows: * * disabledServices = { * <ServiceType>.<Algorithm> * ... * } * * where <Service> can be "MessageDigest", "Cipher", etc. and <Algorithm> * reprepresents the value that's passed into the various getInstance() calls. * * @since 9 */
final class Config { // Reader and StringTokenizer used during parsing private Reader reader; private StreamTokenizer st; private Set<String> parsedKeywords; // set of disabled crypto services, e.g. MessageDigest.SHA1, or // Cipher.AES/ECB/PKCS5Padding private Set<String> disabledServices; Config(String filename) throws IOException { FileInputStream in = new FileInputStream(expand(filename)); reader = new BufferedReader(new InputStreamReader(in, "ISO-8859-1")); parsedKeywords = new HashSet<String>(); st = new StreamTokenizer(reader); setupTokenizer(); parse(); } String[] getDisabledServices() { if (disabledServices != null) { return disabledServices.toArray(new String[disabledServices.size()]); } else { return new String[0]; } } private static String expand(final String s) throws IOException { try { return PropertyExpander.expand(s); } catch (Exception e) { throw new RuntimeException(e.getMessage()); } } private void setupTokenizer() { st.resetSyntax(); st.wordChars('a', 'z'); st.wordChars('A', 'Z'); st.wordChars('0', '9'); st.wordChars(':', ':'); st.wordChars('.', '.'); st.wordChars('_', '_'); st.wordChars('-', '-'); st.wordChars('/', '/'); st.wordChars('\\', '\\'); st.wordChars('$', '$'); st.wordChars('{', '{'); // need {} for property subst st.wordChars('}', '}'); st.wordChars('*', '*'); st.wordChars('+', '+'); st.wordChars('~', '~'); // XXX check ASCII table and add all other characters except special // special: #="(), st.whitespaceChars(0, ' '); st.commentChar('#'); st.eolIsSignificant(true); st.quoteChar('\"'); } private ConfigException excToken(String msg) { return new ConfigException(msg + " " + st); } private ConfigException excLine(String msg) { return new ConfigException(msg + ", line " + st.lineno()); } private void parse() throws IOException { while (true) { int token = nextToken(); if (token == TT_EOF) { break; } if (token == TT_EOL) { continue; } if (token != TT_WORD) { throw excToken("Unexpected token:"); } String word = st.sval; if (word.equals("disabledServices")) { parseDisabledServices(word); } else { throw new ConfigException ("Unknown keyword '" + word + "', line " + st.lineno()); } parsedKeywords.add(word); } reader.close(); reader = null; st = null; parsedKeywords = null; } // // Parsing helper methods // private int nextToken() throws IOException { int token = st.nextToken(); return token; } private void parseEquals() throws IOException { int token = nextToken(); if (token != '=') { throw excToken("Expected '=', read"); } } private void parseOpenBraces() throws IOException { while (true) { int token = nextToken(); if (token == TT_EOL) { continue; } if ((token == TT_WORD) && st.sval.equals("{")) { return; } throw excToken("Expected '{', read"); } } private boolean isCloseBraces(int token) { return (token == TT_WORD) && st.sval.equals("}"); } private void checkDup(String keyword) throws IOException { if (parsedKeywords.contains(keyword)) { throw excLine(keyword + " must only be specified once"); } } private void parseDisabledServices(String keyword) throws IOException { checkDup(keyword); disabledServices = new HashSet<String>(); parseEquals(); parseOpenBraces(); while (true) { int token = nextToken(); if (isCloseBraces(token)) { break; } if (token == TT_EOL) { continue; } if (token != TT_WORD) { throw excToken("Expected mechanism, read"); } disabledServices.add(st.sval); } } } class ConfigException extends IOException { private static final long serialVersionUID = 254492758127673194L; ConfigException(String msg) { super(msg); } }