6476261: (reflect) GenericSignatureFormatError When signature includes nested inner classes

6832374: (reflect) malformed signature can cause parser to go into infinite loop
7052898: (reflect) SignatureParser will accept strings outside of the grammar

Various signature parsing fixes; additional review by sonali.goel@oracle.com

Reviewed-by: alanb
This commit is contained in:
Joe Darcy 2011-08-22 17:12:48 -07:00
parent 765c6904e3
commit d0bd4f51ce
4 changed files with 330 additions and 106 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,17 +25,15 @@
package sun.reflect.generics.parser; package sun.reflect.generics.parser;
import java.lang.reflect.GenericSignatureFormatError; import java.lang.reflect.GenericSignatureFormatError;
import java.util.*; import java.util.*;
import sun.reflect.generics.tree.*; import sun.reflect.generics.tree.*;
/** /**
* Parser for type signatures, as defined in the Java Virtual * Parser for type signatures, as defined in the Java Virtual
// Machine Specification (JVMS) chapter 4. * Machine Specification (JVMS) chapter 4.
* Converts the signatures into an abstract syntax tree (AST) representation. * Converts the signatures into an abstract syntax tree (AST) representation.
// See the package sun.reflect.generics.tree for details of the AST. * See the package sun.reflect.generics.tree for details of the AST.
*/ */
public class SignatureParser { public class SignatureParser {
// The input is conceptually a character stream (though currently it's // The input is conceptually a character stream (though currently it's
@ -58,8 +56,8 @@ public class SignatureParser {
// if (current != x {error("expected an x"); // if (current != x {error("expected an x");
// //
// where x is some character constant. // where x is some character constant.
// The assertion inidcates, that, as currently written, // The assertion indicates, that, as currently written,
// the code should nver reach this point unless the input is an // the code should never reach this point unless the input is an
// x. On the other hand, the test is there to check the legality // x. On the other hand, the test is there to check the legality
// of the input wrt to a given production. It may be that at a later // of the input wrt to a given production. It may be that at a later
// time the code might be called directly, and if the input is // time the code might be called directly, and if the input is
@ -68,7 +66,7 @@ public class SignatureParser {
private char[] input; // the input signature private char[] input; // the input signature
private int index = 0; // index into the input private int index = 0; // index into the input
// used to mark end of input // used to mark end of input
private static final char EOI = ':'; private static final char EOI = ':';
private static final boolean DEBUG = false; private static final boolean DEBUG = false;
@ -104,6 +102,11 @@ public class SignatureParser {
index++; index++;
} }
// For debugging, prints current character to the end of the input.
private String remainder() {
return new String(input, index, input.length-index);
}
// Match c against a "set" of characters // Match c against a "set" of characters
private boolean matches(char c, char... set) { private boolean matches(char c, char... set) {
for (char e : set) { for (char e : set) {
@ -117,8 +120,17 @@ public class SignatureParser {
// Currently throws a GenericSignatureFormatError. // Currently throws a GenericSignatureFormatError.
private Error error(String errorMsg) { private Error error(String errorMsg) {
if (DEBUG) System.out.println("Parse error:" + errorMsg); return new GenericSignatureFormatError("Signature Parse error: " + errorMsg +
return new GenericSignatureFormatError(); "\n\tRemaining input: " + remainder());
}
/**
* Verify the parse has made forward progress; throw an exception
* if no progress.
*/
private void progress(int startingPosition) {
if (index <= startingPosition)
throw error("Failure to make progress!");
} }
/** /**
@ -163,6 +175,7 @@ public class SignatureParser {
/** /**
* Parses a type signature * Parses a type signature
* and produces an abstract syntax tree representing it. * and produces an abstract syntax tree representing it.
*
* @param s a string representing the input type signature * @param s a string representing the input type signature
* @return An abstract syntax tree for a type signature * @return An abstract syntax tree for a type signature
* corresponding to the input string * corresponding to the input string
@ -183,38 +196,58 @@ public class SignatureParser {
// and when it completes parsing, it leaves the input at the first // and when it completes parsing, it leaves the input at the first
// character after the input parses. // character after the input parses.
// parse a class signature based on the implicit input. /*
* Note on grammar conventions: a trailing "*" matches zero or
* more occurrences, a trailing "+" matches one or more occurrences,
* "_opt" indicates an optional component.
*/
/**
* ClassSignature:
* FormalTypeParameters_opt SuperclassSignature SuperinterfaceSignature*
*/
private ClassSignature parseClassSignature() { private ClassSignature parseClassSignature() {
// parse a class signature based on the implicit input.
assert(index == 0); assert(index == 0);
return ClassSignature.make(parseZeroOrMoreFormalTypeParameters(), return ClassSignature.make(parseZeroOrMoreFormalTypeParameters(),
parseClassTypeSignature(), parseClassTypeSignature(), // Only rule for SuperclassSignature
parseSuperInterfaces()); parseSuperInterfaces());
} }
private FormalTypeParameter[] parseZeroOrMoreFormalTypeParameters(){ private FormalTypeParameter[] parseZeroOrMoreFormalTypeParameters(){
if (current() == '<') { return parseFormalTypeParameters();} if (current() == '<') {
else {return new FormalTypeParameter[0];} return parseFormalTypeParameters();
} else {
return new FormalTypeParameter[0];
}
} }
/**
* FormalTypeParameters:
* "<" FormalTypeParameter+ ">"
*/
private FormalTypeParameter[] parseFormalTypeParameters(){ private FormalTypeParameter[] parseFormalTypeParameters(){
Collection<FormalTypeParameter> ftps = List<FormalTypeParameter> ftps = new ArrayList<>(3);
new ArrayList<FormalTypeParameter>(3);
assert(current() == '<'); // should not have been called at all assert(current() == '<'); // should not have been called at all
if (current() != '<') { throw error("expected <");} if (current() != '<') { throw error("expected '<'");}
advance(); advance();
ftps.add(parseFormalTypeParameter()); ftps.add(parseFormalTypeParameter());
while (current() != '>') { while (current() != '>') {
int startingPosition = index;
ftps.add(parseFormalTypeParameter()); ftps.add(parseFormalTypeParameter());
progress(startingPosition);
} }
advance(); advance();
FormalTypeParameter[] ftpa = new FormalTypeParameter[ftps.size()]; return ftps.toArray(new FormalTypeParameter[ftps.size()]);
return ftps.toArray(ftpa);
} }
/**
* FormalTypeParameter:
* Identifier ClassBound InterfaceBound*
*/
private FormalTypeParameter parseFormalTypeParameter(){ private FormalTypeParameter parseFormalTypeParameter(){
String id = parseIdentifier(); String id = parseIdentifier();
FieldTypeSignature[] bs = parseZeroOrMoreBounds(); FieldTypeSignature[] bs = parseBounds();
return FormalTypeParameter.make(id, bs); return FormalTypeParameter.make(id, bs);
} }
@ -229,7 +262,8 @@ public class SignatureParser {
case '[': case '[':
case ':': case ':':
case '>': case '>':
case '<': return result.toString(); case '<':
return result.toString();
default:{ default:{
result.append(c); result.append(c);
advance(); advance();
@ -239,26 +273,42 @@ public class SignatureParser {
} }
return result.toString(); return result.toString();
} }
/**
* FieldTypeSignature:
* ClassTypeSignature
* ArrayTypeSignature
* TypeVariableSignature
*/
private FieldTypeSignature parseFieldTypeSignature() { private FieldTypeSignature parseFieldTypeSignature() {
return parseFieldTypeSignature(true);
}
private FieldTypeSignature parseFieldTypeSignature(boolean allowArrays) {
switch(current()) { switch(current()) {
case 'L': case 'L':
return parseClassTypeSignature(); return parseClassTypeSignature();
case 'T': case 'T':
return parseTypeVariableSignature(); return parseTypeVariableSignature();
case '[': case '[':
return parseArrayTypeSignature(); if (allowArrays)
return parseArrayTypeSignature();
else
throw error("Array signature not allowed here.");
default: throw error("Expected Field Type Signature"); default: throw error("Expected Field Type Signature");
} }
} }
/**
* ClassTypeSignature:
* "L" PackageSpecifier_opt SimpleClassTypeSignature ClassTypeSignatureSuffix* ";"
*/
private ClassTypeSignature parseClassTypeSignature(){ private ClassTypeSignature parseClassTypeSignature(){
assert(current() == 'L'); assert(current() == 'L');
if (current() != 'L') { throw error("expected a class type");} if (current() != 'L') { throw error("expected a class type");}
advance(); advance();
List<SimpleClassTypeSignature> scts = List<SimpleClassTypeSignature> scts = new ArrayList<>(5);
new ArrayList<SimpleClassTypeSignature>(5); scts.add(parsePackageNameAndSimpleClassTypeSignature());
scts.add(parseSimpleClassTypeSignature(false));
parseClassTypeSignatureSuffix(scts); parseClassTypeSignatureSuffix(scts);
if (current() != ';') if (current() != ';')
throw error("expected ';' got '" + current() + "'"); throw error("expected ';' got '" + current() + "'");
@ -267,25 +317,65 @@ public class SignatureParser {
return ClassTypeSignature.make(scts); return ClassTypeSignature.make(scts);
} }
private SimpleClassTypeSignature parseSimpleClassTypeSignature(boolean dollar){ /**
String id = parseIdentifier(); * PackageSpecifier:
char c = current(); * Identifier "/" PackageSpecifier*
switch (c) { */
case ';': private SimpleClassTypeSignature parsePackageNameAndSimpleClassTypeSignature() {
case '/': // Parse both any optional leading PackageSpecifier as well as
return SimpleClassTypeSignature.make(id, dollar, new TypeArgument[0]) ; // the following SimpleClassTypeSignature.
case '<': {
return SimpleClassTypeSignature.make(id, dollar, parseTypeArguments()); String id = parseIdentifier();
}
default: {throw error("expected < or ; or /");} if (current() == '/') { // package name
StringBuilder idBuild = new StringBuilder(id);
while(current() == '/') {
advance();
idBuild.append(".");
idBuild.append(parseIdentifier());
} }
id = idBuild.toString();
}
switch (current()) {
case ';':
return SimpleClassTypeSignature.make(id, false, new TypeArgument[0]); // all done!
case '<':
if (DEBUG) System.out.println("\t remainder: " + remainder());
return SimpleClassTypeSignature.make(id, false, parseTypeArguments());
default:
throw error("expected '<' or ';' but got " + current());
}
} }
/**
* SimpleClassTypeSignature:
* Identifier TypeArguments_opt
*/
private SimpleClassTypeSignature parseSimpleClassTypeSignature(boolean dollar){
String id = parseIdentifier();
char c = current();
switch (c) {
case ';':
case '.':
return SimpleClassTypeSignature.make(id, dollar, new TypeArgument[0]) ;
case '<':
return SimpleClassTypeSignature.make(id, dollar, parseTypeArguments());
default:
throw error("expected '<' or ';' or '.', got '" + c + "'.");
}
}
/**
* ClassTypeSignatureSuffix:
* "." SimpleClassTypeSignature
*/
private void parseClassTypeSignatureSuffix(List<SimpleClassTypeSignature> scts) { private void parseClassTypeSignatureSuffix(List<SimpleClassTypeSignature> scts) {
while (current() == '/' || current() == '.') { while (current() == '.') {
boolean dollar = (current() == '.');
advance(); advance();
scts.add(parseSimpleClassTypeSignature(dollar)); scts.add(parseSimpleClassTypeSignature(true));
} }
} }
@ -294,10 +384,14 @@ public class SignatureParser {
else {return new TypeArgument[0];} else {return new TypeArgument[0];}
} }
/**
* TypeArguments:
* "<" TypeArgument+ ">"
*/
private TypeArgument[] parseTypeArguments() { private TypeArgument[] parseTypeArguments() {
Collection<TypeArgument> tas = new ArrayList<TypeArgument>(3); List<TypeArgument> tas = new ArrayList<>(3);
assert(current() == '<'); assert(current() == '<');
if (current() != '<') { throw error("expected <");} if (current() != '<') { throw error("expected '<'");}
advance(); advance();
tas.add(parseTypeArgument()); tas.add(parseTypeArgument());
while (current() != '>') { while (current() != '>') {
@ -305,10 +399,14 @@ public class SignatureParser {
tas.add(parseTypeArgument()); tas.add(parseTypeArgument());
} }
advance(); advance();
TypeArgument[] taa = new TypeArgument[tas.size()]; return tas.toArray(new TypeArgument[tas.size()]);
return tas.toArray(taa);
} }
/**
* TypeArgument:
* WildcardIndicator_opt FieldTypeSignature
* "*"
*/
private TypeArgument parseTypeArgument() { private TypeArgument parseTypeArgument() {
FieldTypeSignature[] ub, lb; FieldTypeSignature[] ub, lb;
ub = new FieldTypeSignature[1]; ub = new FieldTypeSignature[1];
@ -334,18 +432,20 @@ public class SignatureParser {
ub[0] = SimpleClassTypeSignature.make("java.lang.Object", false, ta); ub[0] = SimpleClassTypeSignature.make("java.lang.Object", false, ta);
return Wildcard.make(ub, lb); return Wildcard.make(ub, lb);
} }
default: return parseFieldTypeSignature(); default:
return parseFieldTypeSignature();
} }
} }
// TypeVariableSignature -> T identifier /**
* TypeVariableSignature:
private TypeVariableSignature parseTypeVariableSignature(){ * "T" Identifier ";"
*/
private TypeVariableSignature parseTypeVariableSignature() {
assert(current() == 'T'); assert(current() == 'T');
if (current() != 'T') { throw error("expected a type variable usage");} if (current() != 'T') { throw error("expected a type variable usage");}
advance(); advance();
TypeVariableSignature ts = TypeVariableSignature ts = TypeVariableSignature.make(parseIdentifier());
TypeVariableSignature.make(parseIdentifier());
if (current() != ';') { if (current() != ';') {
throw error("; expected in signature of type variable named" + throw error("; expected in signature of type variable named" +
ts.getIdentifier()); ts.getIdentifier());
@ -354,16 +454,21 @@ public class SignatureParser {
return ts; return ts;
} }
// ArrayTypeSignature -> [ TypeSignature /**
* ArrayTypeSignature:
* "[" TypeSignature
*/
private ArrayTypeSignature parseArrayTypeSignature() { private ArrayTypeSignature parseArrayTypeSignature() {
if (current() != '[') {throw error("expected array type signature");} if (current() != '[') {throw error("expected array type signature");}
advance(); advance();
return ArrayTypeSignature.make(parseTypeSignature()); return ArrayTypeSignature.make(parseTypeSignature());
} }
// TypeSignature -> BaseType | FieldTypeSignature /**
* TypeSignature:
* FieldTypeSignature
* BaseType
*/
private TypeSignature parseTypeSignature() { private TypeSignature parseTypeSignature() {
switch (current()) { switch (current()) {
case 'B': case 'B':
@ -373,8 +478,11 @@ public class SignatureParser {
case 'I': case 'I':
case 'J': case 'J':
case 'S': case 'S':
case 'Z':return parseBaseType(); case 'Z':
default: return parseFieldTypeSignature(); return parseBaseType();
default:
return parseFieldTypeSignature();
} }
} }
@ -408,12 +516,18 @@ public class SignatureParser {
assert(false); assert(false);
throw error("expected primitive type"); throw error("expected primitive type");
} }
} }
} }
private FieldTypeSignature[] parseZeroOrMoreBounds() { /**
Collection<FieldTypeSignature> fts = * ClassBound:
new ArrayList<FieldTypeSignature>(3); * ":" FieldTypeSignature_opt
*
* InterfaceBound:
* ":" FieldTypeSignature
*/
private FieldTypeSignature[] parseBounds() {
List<FieldTypeSignature> fts = new ArrayList<>(3);
if (current() == ':') { if (current() == ':') {
advance(); advance();
@ -430,24 +544,31 @@ public class SignatureParser {
advance(); advance();
fts.add(parseFieldTypeSignature()); fts.add(parseFieldTypeSignature());
} }
} } else
error("Bound expected");
FieldTypeSignature[] fta = new FieldTypeSignature[fts.size()]; return fts.toArray(new FieldTypeSignature[fts.size()]);
return fts.toArray(fta);
} }
/**
* SuperclassSignature:
* ClassTypeSignature
*/
private ClassTypeSignature[] parseSuperInterfaces() { private ClassTypeSignature[] parseSuperInterfaces() {
Collection<ClassTypeSignature> cts = List<ClassTypeSignature> cts = new ArrayList<>(5);
new ArrayList<ClassTypeSignature>(5);
while(current() == 'L') { while(current() == 'L') {
cts.add(parseClassTypeSignature()); cts.add(parseClassTypeSignature());
} }
ClassTypeSignature[] cta = new ClassTypeSignature[cts.size()]; return cts.toArray(new ClassTypeSignature[cts.size()]);
return cts.toArray(cta);
} }
// parse a method signature based on the implicit input.
/**
* MethodTypeSignature:
* FormalTypeParameters_opt "(" TypeSignature* ")" ReturnType ThrowsSignature*
*/
private MethodTypeSignature parseMethodTypeSignature() { private MethodTypeSignature parseMethodTypeSignature() {
// Parse a method signature based on the implicit input.
FieldTypeSignature[] ets; FieldTypeSignature[] ets;
assert(index == 0); assert(index == 0);
@ -457,19 +578,19 @@ public class SignatureParser {
parseZeroOrMoreThrowsSignatures()); parseZeroOrMoreThrowsSignatures());
} }
// (TypeSignature*) // "(" TypeSignature* ")"
private TypeSignature[] parseFormalParameters() { private TypeSignature[] parseFormalParameters() {
if (current() != '(') {throw error("expected (");} if (current() != '(') {throw error("expected '('");}
advance(); advance();
TypeSignature[] pts = parseZeroOrMoreTypeSignatures(); TypeSignature[] pts = parseZeroOrMoreTypeSignatures();
if (current() != ')') {throw error("expected )");} if (current() != ')') {throw error("expected ')'");}
advance(); advance();
return pts; return pts;
} }
// TypeSignature* // TypeSignature*
private TypeSignature[] parseZeroOrMoreTypeSignatures() { private TypeSignature[] parseZeroOrMoreTypeSignatures() {
Collection<TypeSignature> ts = new ArrayList<TypeSignature>(); List<TypeSignature> ts = new ArrayList<>();
boolean stop = false; boolean stop = false;
while (!stop) { while (!stop) {
switch(current()) { switch(current()) {
@ -484,47 +605,46 @@ public class SignatureParser {
case 'L': case 'L':
case 'T': case 'T':
case '[': { case '[': {
ts.add(parseTypeSignature()); ts.add(parseTypeSignature());
break; break;
} }
default: stop = true; default: stop = true;
} }
} }
/* while( matches(current(), return ts.toArray(new TypeSignature[ts.size()]);
'B', 'C', 'D', 'F', 'I', 'J', 'S', 'Z', 'L', 'T', '[')
) {
ts.add(parseTypeSignature());
}*/
TypeSignature[] ta = new TypeSignature[ts.size()];
return ts.toArray(ta);
} }
// ReturnType -> V | TypeSignature /**
* ReturnType:
* TypeSignature
* VoidDescriptor
*/
private ReturnType parseReturnType(){ private ReturnType parseReturnType(){
if (current() == 'V') { if (current() == 'V') {
advance(); advance();
return VoidDescriptor.make(); return VoidDescriptor.make();
} else return parseTypeSignature(); } else
return parseTypeSignature();
} }
// ThrowSignature* // ThrowSignature*
private FieldTypeSignature[] parseZeroOrMoreThrowsSignatures(){ private FieldTypeSignature[] parseZeroOrMoreThrowsSignatures(){
Collection<FieldTypeSignature> ets = List<FieldTypeSignature> ets = new ArrayList<>(3);
new ArrayList<FieldTypeSignature>(3);
while( current() == '^') { while( current() == '^') {
ets.add(parseThrowsSignature()); ets.add(parseThrowsSignature());
} }
FieldTypeSignature[] eta = new FieldTypeSignature[ets.size()]; return ets.toArray(new FieldTypeSignature[ets.size()]);
return ets.toArray(eta);
} }
// ThrowSignature -> ^ FieldTypeSignature /**
* ThrowsSignature:
* "^" ClassTypeSignature
* "^" TypeVariableSignature
*/
private FieldTypeSignature parseThrowsSignature() { private FieldTypeSignature parseThrowsSignature() {
assert(current() == '^'); assert(current() == '^');
if (current() != '^') { throw error("expected throws signature");} if (current() != '^') { throw error("expected throws signature");}
advance(); advance();
return parseFieldTypeSignature(); return parseFieldTypeSignature(false);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,7 +23,7 @@
/* /*
* @test * @test
* @bug 5003916 6704655 6873951 * @bug 5003916 6704655 6873951 6476261
* @summary Testing parsing of signatures attributes of nested classes * @summary Testing parsing of signatures attributes of nested classes
* @author Joseph D. Darcy * @author Joseph D. Darcy
*/ */
@ -38,12 +38,12 @@ import static java.util.Arrays.*;
"java.util.concurrent.ConcurrentHashMap$KeyIterator", "java.util.concurrent.ConcurrentHashMap$KeyIterator",
"java.util.concurrent.ConcurrentHashMap$ValueIterator", "java.util.concurrent.ConcurrentHashMap$ValueIterator",
"java.util.AbstractList$ListItr", "java.util.AbstractList$ListItr",
// "java.util.EnumMap$EntryIterator", "java.util.EnumMap$EntryIterator",
// "java.util.EnumMap$KeyIterator", "java.util.EnumMap$KeyIterator",
// "java.util.EnumMap$ValueIterator", "java.util.EnumMap$ValueIterator",
// "java.util.IdentityHashMap$EntryIterator", "java.util.IdentityHashMap$EntryIterator",
// "java.util.IdentityHashMap$KeyIterator", "java.util.IdentityHashMap$KeyIterator",
// "java.util.IdentityHashMap$ValueIterator", "java.util.IdentityHashMap$ValueIterator",
"java.util.WeakHashMap$EntryIterator", "java.util.WeakHashMap$EntryIterator",
"java.util.WeakHashMap$KeyIterator", "java.util.WeakHashMap$KeyIterator",
"java.util.WeakHashMap$ValueIterator", "java.util.WeakHashMap$ValueIterator",
@ -52,12 +52,12 @@ import static java.util.Arrays.*;
"java.util.HashMap$ValueIterator", "java.util.HashMap$ValueIterator",
"java.util.LinkedHashMap$EntryIterator", "java.util.LinkedHashMap$EntryIterator",
"java.util.LinkedHashMap$KeyIterator", "java.util.LinkedHashMap$KeyIterator",
"java.util.LinkedHashMap$ValueIterator"}) "java.util.LinkedHashMap$ValueIterator",
"javax.swing.JComboBox$AccessibleJComboBox"})
public class Probe { public class Probe {
public static void main (String... args) throws Throwable { public static void main (String... args) throws Throwable {
Classes classesAnnotation = (Probe.class).getAnnotation(Classes.class); Classes classesAnnotation = (Probe.class).getAnnotation(Classes.class);
List<String> names = List<String> names = new ArrayList<>(asList(classesAnnotation.value()));
new ArrayList<String>(asList(classesAnnotation.value()));
int errs = 0; int errs = 0;
for(String name: names) { for(String name: names) {

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2006, 2011, 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.
*
* 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.
*/
/*
* @test
* @bug 6476261
* @summary More testing of parsing of signatures attributes of nested classes
*/
import java.lang.reflect.*;
public class SignatureTest<T> {
class Inner1 {
class Inner11 {
}
}
public void f(SignatureTest<String>.Inner1.Inner11 x) {}
public void g(SignatureTest<String>.Inner1 x) {}
public static void main(String[] args) throws Exception {
Class clazz = SignatureTest.class;
for (Method m : clazz.getDeclaredMethods()) {
System.out.println();
System.out.println(m.toString());
System.out.println(m.toGenericString());
System.out.println(m.getGenericParameterTypes());
}
}
}

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2011, 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.
*
* 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.
*/
/*
* @test
* @bug 6832374 7052898
* @summary Test bad signatures get a GenericSignatureFormatError thrown.
* @author Joseph D. Darcy
*/
import java.lang.reflect.*;
import sun.reflect.generics.parser.SignatureParser;
public class TestBadSignatures {
public static void main(String[] args) {
String[] badSignatures = {
// Missing ":" after first type bound
"<T:Lfoo/tools/nsc/symtab/Names;Lfoo/tools/nsc/symtab/Symbols;",
// Arrays improperly indicated for exception information
"<E:Ljava/lang/Exception;>(TE;[Ljava/lang/RuntimeException;)V^[TE;",
};
for(String badSig : badSignatures) {
try {
SignatureParser.make().parseMethodSig(badSig);
throw new RuntimeException("Expected GenericSignatureFormatError for " +
badSig);
} catch(GenericSignatureFormatError gsfe) {
System.out.println(gsfe.toString()); // Expected
}
}
}
}