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.lang.CPStringBuilder; 42: 43: import gnu.java.security.Configuration; 44: 45: import java.io.BufferedReader; 46: import java.io.IOException; 47: import java.io.Reader; 48: import java.util.logging.Logger; 49: 50: /** 51: * A UTF-8 friendly, JAAS Login Module Configuration file tokenizer written in 52: * the deault syntax. This class emulates, to a certain extent, the behavior of 53: * a {@link java.io.StreamTokenizer} instance <code>st</code>, when set as 54: * follows: 55: * 56: * <pre> 57: * st.resetSyntax(); 58: * st.lowerCaseMode(false); 59: * st.slashSlashComments(true); 60: * st.slashStarComments(true); 61: * st.eolIsSignificant(false); 62: * st.wordChars('_', '_'); 63: * st.wordChars('$', '$'); 64: * st.wordChars('A', 'Z'); 65: * st.wordChars('a', 'z'); 66: * st.wordChars('0', '9'); 67: * st.wordChars('.', '.'); 68: * st.whitespaceChars(' ', ' '); 69: * st.whitespaceChars('\t', '\t'); 70: * st.whitespaceChars('\f', '\f'); 71: * st.whitespaceChars('\r', '\r'); 72: * st.whitespaceChars('\n', '\n'); 73: * st.quoteChar('"'); 74: * st.quoteChar('\''); 75: * </pre> 76: * 77: * <p>The most important (negative) difference with a 78: * {@link java.io.StreamTokenizer} is that this tokenizer does not properly 79: * handle C++ and Java // style comments in the middle of the line. It only 80: * ignores them if/when found at the start of the line.</p> 81: */ 82: public class ConfigFileTokenizer 83: { 84: private static final Logger log = Logger.getLogger(ConfigFileParser.class.getName()); 85: /** A constant indicating that the end of the stream has been read. */ 86: public static final int TT_EOF = -1; 87: /** A constant indicating that a word token has been read. */ 88: public static final int TT_WORD = -3; 89: /** A constant indicating that no tokens have been read yet. */ 90: private static final int TT_NONE = -4; 91: 92: public String sval; 93: public int ttype; 94: 95: private BufferedReader br; 96: boolean initialised; 97: private CPStringBuilder sb; 98: private int sbNdx; 99: 100: // Constructor(s) 101: // -------------------------------------------------------------------------- 102: 103: /** Trivial constructor. */ 104: ConfigFileTokenizer(Reader r) 105: { 106: super(); 107: 108: br = r instanceof BufferedReader ? (BufferedReader) r : new BufferedReader(r); 109: initialised = false; 110: } 111: 112: // Class methods 113: // -------------------------------------------------------------------------- 114: 115: // Instance methods 116: // -------------------------------------------------------------------------- 117: 118: public int nextToken() throws IOException 119: { 120: if (!initialised) 121: init(); 122: 123: if (sbNdx >= sb.length()) 124: return TT_EOF; 125: 126: skipWhitespace(); 127: 128: if (sbNdx >= sb.length()) 129: return TT_EOF; 130: 131: int endNdx; 132: if (Character.isJavaIdentifierPart(sb.charAt(sbNdx))) 133: { 134: endNdx = sbNdx + 1; 135: while (Character.isJavaIdentifierPart(sb.charAt(endNdx)) 136: || sb.charAt(endNdx) == '.') 137: endNdx++; 138: 139: ttype = TT_WORD; 140: sval = sb.substring(sbNdx, endNdx); 141: sbNdx = endNdx; 142: return ttype; 143: } 144: 145: int c = sb.charAt(sbNdx); 146: if (c == '{' || c == '}' || c == ';' || c == '=') 147: { 148: ttype = c; 149: sbNdx++; 150: return ttype; 151: } 152: 153: if (c == '"' || c == '\'') 154: { 155: ttype = c; 156: String quote = sb.substring(sbNdx, sbNdx + 1); 157: int i = sbNdx + 1; 158: while (true) 159: { 160: // find a candidate 161: endNdx = sb.indexOf(quote, i); 162: if (endNdx == -1) 163: abort("Missing closing quote: " + quote); 164: 165: // found one; is it escaped? 166: if (sb.charAt(endNdx - 1) != '\\') 167: break; 168: 169: i++; 170: continue; 171: } 172: 173: endNdx++; 174: sval = sb.substring(sbNdx, endNdx); 175: sbNdx = endNdx; 176: return ttype; 177: } 178: 179: abort("Unknown character: " + sb.charAt(sbNdx)); 180: return Integer.MIN_VALUE; 181: } 182: 183: public void pushBack() 184: { 185: sbNdx -= ttype != TT_WORD ? 1 : sval.length(); 186: } 187: 188: private void init() throws IOException 189: { 190: sb = new CPStringBuilder(); 191: String line; 192: while ((line = br.readLine()) != null) 193: { 194: line = line.trim(); 195: if (line.length() == 0) 196: continue; 197: 198: if (line.startsWith("#") || line.startsWith("//")) 199: continue; 200: 201: sb.append(line).append(" "); 202: } 203: 204: sbNdx = 0; 205: sval = null; 206: ttype = TT_NONE; 207: 208: initialised = true; 209: } 210: 211: private void skipWhitespace() throws IOException 212: { 213: int endNdx; 214: while (sbNdx < sb.length()) 215: if (Character.isWhitespace(sb.charAt(sbNdx))) 216: { 217: sbNdx++; 218: while (sbNdx < sb.length() && Character.isWhitespace(sb.charAt(sbNdx))) 219: sbNdx++; 220: 221: continue; 222: } 223: else if (sb.charAt(sbNdx) == '/' && sb.charAt(sbNdx + 1) == '*') 224: { 225: endNdx = sb.indexOf("*/", sbNdx + 2); 226: if (endNdx == -1) 227: abort("Missing closing */ sequence"); 228: 229: sbNdx = endNdx + 2; 230: continue; 231: } 232: else 233: break; 234: } 235: 236: private void abort(String m) throws IOException 237: { 238: if (Configuration.DEBUG) 239: { 240: log.fine(m); 241: log.fine("sb = " + sb); 242: log.fine("sbNdx = " + sbNdx); 243: } 244: throw new IOException(m); 245: } 246: }