001: /*
002: *
003: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
004: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License version
008: * 2 only, as published by the Free Software Foundation.
009: *
010: * This program is distributed in the hope that it will be useful, but
011: * WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * General Public License version 2 for more details (a copy is
014: * included at /legal/license.txt).
015: *
016: * You should have received a copy of the GNU General Public License
017: * version 2 along with this work; if not, write to the Free Software
018: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
019: * 02110-1301 USA
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
022: * Clara, CA 95054 or visit www.sun.com if you need additional
023: * information or have any questions.
024: */
025:
026: package sun.misc;
027:
028: import java.io.*;
029: import java.util.LinkedList;
030:
031: /*
032: * @(#)MemberFilterConfig.java 1.5 06/10/10
033: */
034: /*
035: * Input consists of a sequence of class specifiers.
036: * Input syntax is:
037: * CLASS classname
038: * FIELDS
039: * fieldname:fieldsig
040: * ...
041: * METHODS
042: * methodname:methodsig
043: * ...
044: *
045: * Classnames and signatures are all in internal format: / is the
046: * component separator. When a class appears in a signature, it is of
047: * the Lname; form. Method sigatures have return type.
048: *
049: * Either fields or methods may be missing
050: * Newlines are not significant.
051: * Whitespace is not allowed within the name:sig pair.
052: * Other whitespace is ignored.
053: * # starts a comment.
054: */
055:
056: class MemberFilterConfig {
057:
058: String fileName;
059: FileReader inFile;
060: StreamTokenizer in;
061: MemberFilter filter;
062: boolean verbose;
063:
064: private static final String empty[] = new String[0];
065:
066: MemberFilterConfig(String configFileName) throws IOException {
067: fileName = configFileName;
068: inFile = new FileReader(configFileName);
069: in = new StreamTokenizer(new BufferedReader(inFile));
070: // now have file open.
071: // Configure the tokenizer.
072: in.commentChar('#');
073: in.slashSlashComments(false);
074: in.eolIsSignificant(false);
075: in.wordChars('a', 'z');
076: in.wordChars('A', '[');
077: in.wordChars('0', '9');
078: in.wordChars('<', '<'); // appears in name <init>
079: in.wordChars('>', '>');
080: in.wordChars('_', '_');
081: in.wordChars(':', ':'); // make special separator wordChar
082: in.wordChars(';', ';'); // make all parts of a signature wordChar
083: in.wordChars('(', ')');
084: in.wordChars('/', '/'); // make name component separator wordChar
085: in.whitespaceChars(' ', ' '); // ignore space
086: in.whitespaceChars('\t', '\t'); // ignore tabs
087: // construct the MemberFilter
088: filter = new MemberFilter();
089: }
090:
091: // keywords in easy-to-manipulate integer form
092: private static final int NOKEY = 0;
093: private static final int CLASS = 1;
094: private static final int FIELDS = 2;
095: private static final int METHODS = 3;
096: private static final int MAXKEY = 3;
097:
098: private static final String keys[] = { "", "CLASS", "FIELDS",
099: "METHODS" };
100:
101: private static int keyword(String word) {
102: for (int i = 1; i <= MAXKEY; i++) {
103: if (word.equals(keys[i]))
104: return i;
105: }
106: return NOKEY;
107: }
108:
109: private String nextWord() throws Exception {
110: int token = in.nextToken();
111: if (token == in.TT_EOF) {
112: throw new EOFException("EOF");
113: }
114: if (token != in.TT_WORD) {
115: throw new Exception("token type");
116: }
117: return in.sval;
118: }
119:
120: private int expecting(int token1, int token2, int token3)
121: throws Exception {
122: int key;
123: key = keyword(nextWord());
124: if (key != token1 && key != token2 && key != token3) {
125: throw new Exception("token value ".concat(in.sval));
126: }
127: return key;
128: }
129:
130: static private void printStringArray(String name, String val[]) {
131: if (val == null || val.length == 0)
132: return;
133: System.out.println(name);
134: int l = val.length;
135: for (int i = 0; i < l; i++) {
136: System.out.print('\t');
137: System.out.println(val[i]);
138: }
139: }
140:
141: private void parseClass() throws Exception {
142: String classname = null;
143: String word = null;
144: int keyword;
145: int token;
146: LinkedList methods = new LinkedList();
147: LinkedList fields = new LinkedList();
148: try {
149: // parse CLASS and classname
150: expecting(CLASS, -1, -1);
151: classname = nextWord();
152:
153: while (true) {
154: // parse FIELDS or METHODS
155: keyword = expecting(FIELDS, METHODS, CLASS);
156: LinkedList this list;
157: if (keyword == CLASS) {
158: // beginning of next class signals the end of this one.
159: in.pushBack();
160: break;
161: }
162: this list = (keyword == FIELDS) ? fields : methods;
163: while (true) {
164: String memberName = nextWord();
165: // see if this name is a keyword.
166: // since the memberNames, if properly formed,
167: // must contain :, there should be no danger of
168: // confusion.
169: keyword = keyword(memberName);
170: if (keyword != NOKEY) {
171: in.pushBack();
172: break;
173: }
174: // make sure we have our :
175: if (memberName.indexOf(':') == -1) {
176: throw new Exception("format error in "
177: .concat(memberName));
178: }
179: this list.add(memberName);
180: }
181: }
182: } finally {
183: if (classname != null) {
184: // here, using empty as a prototype for String[]
185: String methodstrings[] = (String[]) methods
186: .toArray(empty);
187: String fieldstrings[] = (String[]) fields
188: .toArray(empty);
189: if (verbose) {
190: System.out.print("CLASS ");
191: System.out.println(classname);
192: printStringArray(" FIELDS", fieldstrings);
193: printStringArray(" METHODS", methodstrings);
194: }
195: filter.addRestrictions(classname, fieldstrings,
196: methodstrings);
197: }
198: }
199: }
200:
201: private void printExceptionInfo(Exception e, String msg) {
202: System.err.print(fileName);
203: System.err.print(": ");
204: if (in != null) {
205: System.err.print("line ");
206: System.err.println(String.valueOf(in.lineno()));
207: }
208: System.err.print(msg);
209: System.err.print(": ");
210: System.err.println(e.getMessage());
211: }
212:
213: public void setVerbose(boolean v) {
214: verbose = v;
215: }
216:
217: public MemberFilter parseFile() {
218: if (!filter.findROMFilterData()) {
219: try {
220: while (true) {
221: parseClass();
222: }
223: } catch (EOFException e) {
224: // normal termination. do nothing
225: } catch (IOException e) {
226: printExceptionInfo(e, "IO error");
227: return null;
228: } catch (Exception e) {
229: printExceptionInfo(e, "syntax error");
230: return null;
231: }
232: filter.doneAddingRestrictions();
233: }
234: return filter;
235: }
236: }
|