/*
*
* Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program 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.
*
* This program 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 at /legal/license.txt).
*
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 or visit www.sun.com if you need additional
* information or have any questions.
*/
package sun.misc;
import java.io.*;
import java.util.LinkedList;
/*
* @(#)MemberFilterConfig.java 1.5 06/10/10
*/
/*
* Input consists of a sequence of class specifiers.
* Input syntax is:
* CLASS classname
* FIELDS
* fieldname:fieldsig
* ...
* METHODS
* methodname:methodsig
* ...
*
* Classnames and signatures are all in internal format: / is the
* component separator. When a class appears in a signature, it is of
* the Lname; form. Method sigatures have return type.
*
* Either fields or methods may be missing
* Newlines are not significant.
* Whitespace is not allowed within the name:sig pair.
* Other whitespace is ignored.
* # starts a comment.
*/
class MemberFilterConfig{
String fileName;
FileReader inFile;
StreamTokenizer in;
MemberFilter filter;
boolean verbose;
private static final String empty[] = new String[0];
MemberFilterConfig(String configFileName) throws IOException {
fileName = configFileName;
inFile = new FileReader(configFileName);
in = new StreamTokenizer(new BufferedReader(inFile));
// now have file open.
// Configure the tokenizer.
in.commentChar('#');
in.slashSlashComments(false);
in.eolIsSignificant(false);
in.wordChars('a','z');
in.wordChars('A','[');
in.wordChars('0','9');
in.wordChars('<','<'); // appears in name <init>
in.wordChars('>','>');
in.wordChars('_','_');
in.wordChars(':',':'); // make special separator wordChar
in.wordChars(';',';'); // make all parts of a signature wordChar
in.wordChars('(',')');
in.wordChars('/','/'); // make name component separator wordChar
in.whitespaceChars(' ',' '); // ignore space
in.whitespaceChars('\t','\t'); // ignore tabs
// construct the MemberFilter
filter = new MemberFilter();
}
// keywords in easy-to-manipulate integer form
private static final int NOKEY = 0;
private static final int CLASS = 1;
private static final int FIELDS = 2;
private static final int METHODS = 3;
private static final int MAXKEY = 3;
private static final String keys[] = {
"", "CLASS", "FIELDS", "METHODS"
};
private static int keyword(String word){
for( int i = 1; i <= MAXKEY; i++ ){
if (word.equals(keys[i])) return i;
}
return NOKEY;
}
private String
nextWord() throws Exception{
int token = in.nextToken();
if (token == in.TT_EOF){
throw new EOFException("EOF");
}
if (token != in.TT_WORD){
throw new Exception("token type");
}
return in.sval;
}
private int
expecting(int token1, int token2, int token3) throws Exception{
int key;
key = keyword(nextWord());
if (key != token1 && key != token2 && key != token3){
throw new Exception("token value ".concat(in.sval));
}
return key;
}
static private void
printStringArray(String name, String val[]){
if (val == null || val.length == 0)
return;
System.out.println(name);
int l = val.length;
for(int i=0; i<l; i++){
System.out.print('\t');
System.out.println(val[i]);
}
}
private void
parseClass() throws Exception {
String classname = null;
String word = null;
int keyword;
int token;
LinkedList methods = new LinkedList();
LinkedList fields = new LinkedList();
try{
// parse CLASS and classname
expecting(CLASS, -1, -1);
classname = nextWord();
while(true){
// parse FIELDS or METHODS
keyword = expecting(FIELDS, METHODS, CLASS);
LinkedList thislist;
if (keyword == CLASS){
// beginning of next class signals the end of this one.
in.pushBack();
break;
}
thislist = (keyword == FIELDS)? fields : methods;
while(true){
String memberName = nextWord();
// see if this name is a keyword.
// since the memberNames, if properly formed,
// must contain :, there should be no danger of
// confusion.
keyword = keyword(memberName);
if (keyword != NOKEY){
in.pushBack();
break;
}
// make sure we have our :
if (memberName.indexOf(':') == -1){
throw new Exception("format error in ".concat(memberName));
}
thislist.add(memberName);
}
}
}finally{
if (classname != null){
// here, using empty as a prototype for String[]
String methodstrings[] = (String[])methods.toArray(empty);
String fieldstrings[] = (String[])fields.toArray(empty);
if (verbose){
System.out.print("CLASS ");
System.out.println(classname);
printStringArray(" FIELDS", fieldstrings);
printStringArray(" METHODS", methodstrings);
}
filter.addRestrictions(classname,
fieldstrings, methodstrings);
}
}
}
private void
printExceptionInfo(Exception e, String msg){
System.err.print(fileName);
System.err.print(": ");
if (in != null){
System.err.print("line ");
System.err.println(String.valueOf(in.lineno()));
}
System.err.print(msg);
System.err.print(": ");
System.err.println(e.getMessage());
}
public void
setVerbose(boolean v){
verbose = v;
}
public MemberFilter
parseFile(){
if (!filter.findROMFilterData()) {
try{
while(true){
parseClass();
}
}catch(EOFException e){
// normal termination. do nothing
}catch(IOException e){
printExceptionInfo(e, "IO error");
return null;
}catch(Exception e){
printExceptionInfo(e, "syntax error");
return null;
}
filter.doneAddingRestrictions();
}
return filter;
}
}