Frames | No Frames |
1: /* ConfigFileTokenizer.java -- JAAS Login Configuration default syntax tokenizer 2: Copyright (C) 2006 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package gnu.javax.security.auth.login; 40: 41: import gnu.java.security.Configuration; 42: 43: import java.io.BufferedReader; 44: import java.io.IOException; 45: import java.io.Reader; 46: import java.util.logging.Logger; 47: 48: /** 49: * A UTF-8 friendly, JAAS Login Module Configuration file tokenizer written in 50: * the deault syntax. This class emulates, to a certain extent, the behavior of 51: * a {@link java.io.StreamTokenizer} instance <code>st</code>, when set as 52: * follows: 53: * 54: * <pre> 55: * st.resetSyntax(); 56: * st.lowerCaseMode(false); 57: * st.slashSlashComments(true); 58: * st.slashStarComments(true); 59: * st.eolIsSignificant(false); 60: * st.wordChars('_', '_'); 61: * st.wordChars('$', '$'); 62: * st.wordChars('A', 'Z'); 63: * st.wordChars('a', 'z'); 64: * st.wordChars('0', '9'); 65: * st.wordChars('.', '.'); 66: * st.whitespaceChars(' ', ' '); 67: * st.whitespaceChars('\t', '\t'); 68: * st.whitespaceChars('\f', '\f'); 69: * st.whitespaceChars('\r', '\r'); 70: * st.whitespaceChars('\n', '\n'); 71: * st.quoteChar('"'); 72: * st.quoteChar('\''); 73: * </pre> 74: * 75: * <p>The most important (negative) difference with a 76: * {@link java.io.StreamTokenizer} is that this tokenizer does not properly 77: * handle C++ and Java // style comments in the middle of the line. It only 78: * ignores them if/when found at the start of the line.</p> 79: */ 80: public class ConfigFileTokenizer 81: { 82: private static final Logger log = Logger.getLogger(ConfigFileParser.class.getName()); 83: /** A constant indicating that the end of the stream has been read. */ 84: public static final int TT_EOF = -1; 85: /** A constant indicating that a word token has been read. */ 86: public static final int TT_WORD = -3; 87: /** A constant indicating that no tokens have been read yet. */ 88: private static final int TT_NONE = -4; 89: 90: public String sval; 91: public int ttype; 92: 93: private BufferedReader br; 94: boolean initialised; 95: private StringBuffer sb; 96: private int sbNdx; 97: 98: // Constructor(s) 99: // -------------------------------------------------------------------------- 100: 101: /** Trivial constructor. */ 102: ConfigFileTokenizer(Reader r) 103: { 104: super(); 105: 106: br = r instanceof BufferedReader ? (BufferedReader) r : new BufferedReader(r); 107: initialised = false; 108: } 109: 110: // Class methods 111: // -------------------------------------------------------------------------- 112: 113: // Instance methods 114: // -------------------------------------------------------------------------- 115: 116: public int nextToken() throws IOException 117: { 118: if (!initialised) 119: init(); 120: 121: if (sbNdx >= sb.length()) 122: return TT_EOF; 123: 124: skipWhitespace(); 125: 126: if (sbNdx >= sb.length()) 127: return TT_EOF; 128: 129: int endNdx; 130: if (Character.isJavaIdentifierPart(sb.charAt(sbNdx))) 131: { 132: endNdx = sbNdx + 1; 133: while (Character.isJavaIdentifierPart(sb.charAt(endNdx)) 134: || sb.charAt(endNdx) == '.') 135: endNdx++; 136: 137: ttype = TT_WORD; 138: sval = sb.substring(sbNdx, endNdx); 139: sbNdx = endNdx; 140: return ttype; 141: } 142: 143: int c = sb.charAt(sbNdx); 144: if (c == '{' || c == '}' || c == ';' || c == '=') 145: { 146: ttype = c; 147: sbNdx++; 148: return ttype; 149: } 150: 151: if (c == '"' || c == '\'') 152: { 153: ttype = c; 154: String quote = sb.substring(sbNdx, sbNdx + 1); 155: int i = sbNdx + 1; 156: while (true) 157: { 158: // find a candidate 159: endNdx = sb.indexOf(quote, i); 160: if (endNdx == -1) 161: abort("Missing closing quote: " + quote); 162: 163: // found one; is it escaped? 164: if (sb.charAt(endNdx - 1) != '\\') 165: break; 166: 167: i++; 168: continue; 169: } 170: 171: endNdx++; 172: sval = sb.substring(sbNdx, endNdx); 173: sbNdx = endNdx; 174: return ttype; 175: } 176: 177: abort("Unknown character: " + sb.charAt(sbNdx)); 178: return Integer.MIN_VALUE; 179: } 180: 181: public void pushBack() 182: { 183: sbNdx -= ttype != TT_WORD ? 1 : sval.length(); 184: } 185: 186: private void init() throws IOException 187: { 188: sb = new StringBuffer(); 189: String line; 190: while ((line = br.readLine()) != null) 191: { 192: line = line.trim(); 193: if (line.length() == 0) 194: continue; 195: 196: if (line.startsWith("#") || line.startsWith("//")) 197: continue; 198: 199: sb.append(line).append(" "); 200: } 201: 202: sbNdx = 0; 203: sval = null; 204: ttype = TT_NONE; 205: 206: initialised = true; 207: } 208: 209: private void skipWhitespace() throws IOException 210: { 211: int endNdx; 212: while (sbNdx < sb.length()) 213: if (Character.isWhitespace(sb.charAt(sbNdx))) 214: { 215: sbNdx++; 216: while (sbNdx < sb.length() && Character.isWhitespace(sb.charAt(sbNdx))) 217: sbNdx++; 218: 219: continue; 220: } 221: else if (sb.charAt(sbNdx) == '/' && sb.charAt(sbNdx + 1) == '*') 222: { 223: endNdx = sb.indexOf("*/", sbNdx + 2); 224: if (endNdx == -1) 225: abort("Missing closing */ sequence"); 226: 227: sbNdx = endNdx + 2; 228: continue; 229: } 230: else 231: break; 232: } 233: 234: private void abort(String m) throws IOException 235: { 236: if (Configuration.DEBUG) 237: { 238: log.fine(m); 239: log.fine("sb = " + sb); 240: log.fine("sbNdx = " + sbNdx); 241: } 242: throw new IOException(m); 243: } 244: }