Merge
This commit is contained in:
commit
bab241d2e7
@ -0,0 +1,32 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# - Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# - Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
|
# documentation and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# - Neither the name of Oracle nor the names of its
|
||||||
|
# contributors may be used to endorse or promote products derived
|
||||||
|
# from this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
#
|
||||||
|
|
||||||
|
arch=x86_64
|
@ -0,0 +1,32 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# - Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# - Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
|
# documentation and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# - Neither the name of Oracle nor the names of its
|
||||||
|
# contributors may be used to endorse or promote products derived
|
||||||
|
# from this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
#
|
||||||
|
|
||||||
|
platform=macosx
|
@ -39,11 +39,11 @@
|
|||||||
<classpath mode="boot">${bootstrap.jdk}/jre/lib/rt.jar</classpath>
|
<classpath mode="boot">${bootstrap.jdk}/jre/lib/rt.jar</classpath>
|
||||||
<built-to>${root}/build/${platform}-${arch}/classes</built-to>
|
<built-to>${root}/build/${platform}-${arch}/classes</built-to>
|
||||||
<javadoc-built-to>${root}/build/${platform}-${arch}/docs/api</javadoc-built-to>
|
<javadoc-built-to>${root}/build/${platform}-${arch}/docs/api</javadoc-built-to>
|
||||||
<source-level>1.7</source-level>
|
<source-level>1.8</source-level>
|
||||||
</compilation-unit>
|
</compilation-unit>
|
||||||
<compilation-unit>
|
<compilation-unit>
|
||||||
<package-root>${root}/test</package-root>
|
<package-root>${root}/test</package-root>
|
||||||
<unit-tests/>
|
<unit-tests/>
|
||||||
<source-level>1.7</source-level>
|
<source-level>1.8</source-level>
|
||||||
</compilation-unit>
|
</compilation-unit>
|
||||||
</java-data>
|
</java-data>
|
||||||
|
@ -37,11 +37,11 @@
|
|||||||
<classpath mode="boot">${bootstrap.jdk}/jre/lib/rt.jar</classpath>
|
<classpath mode="boot">${bootstrap.jdk}/jre/lib/rt.jar</classpath>
|
||||||
<built-to>${root}/build/${platform}-${arch}/classes</built-to>
|
<built-to>${root}/build/${platform}-${arch}/classes</built-to>
|
||||||
<javadoc-built-to>${root}/build/${platform}-${arch}/docs/api</javadoc-built-to>
|
<javadoc-built-to>${root}/build/${platform}-${arch}/docs/api</javadoc-built-to>
|
||||||
<source-level>1.7</source-level>
|
<source-level>1.8</source-level>
|
||||||
</compilation-unit>
|
</compilation-unit>
|
||||||
<compilation-unit>
|
<compilation-unit>
|
||||||
<package-root>${root}/test</package-root>
|
<package-root>${root}/test</package-root>
|
||||||
<unit-tests/>
|
<unit-tests/>
|
||||||
<source-level>1.7</source-level>
|
<source-level>1.8</source-level>
|
||||||
</compilation-unit>
|
</compilation-unit>
|
||||||
</java-data>
|
</java-data>
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
<project name="make" basedir="..">
|
<project name="make" basedir="..">
|
||||||
|
|
||||||
<target name="-make.init" depends="-init,-pre-init.linux,-pre-init.solaris,-pre-init.windows">
|
<target name="-make.init" depends="-init,-pre-init.linux,-pre-init.macosx,-pre-init.solaris,-pre-init.windows,-pre-init.macosx">
|
||||||
<property name="make.options" value=""/> <!-- default, can be overridden per user or per project -->
|
<property name="make.options" value=""/> <!-- default, can be overridden per user or per project -->
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
@ -42,6 +42,11 @@
|
|||||||
<property name="make" value="make"/>
|
<property name="make" value="make"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
<target name="-pre-init.macosx" if="os.macosx">
|
||||||
|
<property name="platform" value="macosx"/>
|
||||||
|
<property name="make" value="make"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
<target name="-pre-init.solaris" if="os.solaris">
|
<target name="-pre-init.solaris" if="os.solaris">
|
||||||
<property name="platform" value="solaris"/>
|
<property name="platform" value="solaris"/>
|
||||||
<property name="make" value="gmake"/>
|
<property name="make" value="gmake"/>
|
||||||
|
@ -85,6 +85,9 @@
|
|||||||
<property name="includes" value="(nothing)"/>
|
<property name="includes" value="(nothing)"/>
|
||||||
<property name="excludes" value=""/>
|
<property name="excludes" value=""/>
|
||||||
<property name="javadoc.dir" location="${build.dir}/javadoc/${ant.project.name}"/>
|
<property name="javadoc.dir" location="${build.dir}/javadoc/${ant.project.name}"/>
|
||||||
|
<condition property="os.macosx">
|
||||||
|
<os family="mac"/>
|
||||||
|
</condition>
|
||||||
<condition property="os.linux">
|
<condition property="os.linux">
|
||||||
<os name="linux"/>
|
<os name="linux"/>
|
||||||
</condition>
|
</condition>
|
||||||
@ -126,10 +129,6 @@
|
|||||||
<javac srcdir="@{srcdir}" includes="@{includes}" excludes="@{excludes}" sourcepath=""
|
<javac srcdir="@{srcdir}" includes="@{includes}" excludes="@{excludes}" sourcepath=""
|
||||||
destdir="@{classesdir}" fork="true" executable="${bootstrap.javac}"
|
destdir="@{classesdir}" fork="true" executable="${bootstrap.javac}"
|
||||||
debug="${javac.debug}" debuglevel="${javac.debuglevel}">
|
debug="${javac.debug}" debuglevel="${javac.debuglevel}">
|
||||||
<compilerarg value="-source"/>
|
|
||||||
<compilerarg value="1.5"/>
|
|
||||||
<compilerarg value="-target"/>
|
|
||||||
<compilerarg value="1.6"/> <!-- for usability of JDK 6 as snapshot; change to 1.7 when JSR 294 put back -->
|
|
||||||
<!-- Mandatory for compiling partial JDK sources against a snapshot; should NEVER be used for any other purpose: -->
|
<!-- Mandatory for compiling partial JDK sources against a snapshot; should NEVER be used for any other purpose: -->
|
||||||
<compilerarg value="-XDignore.symbol.file=true"/>
|
<compilerarg value="-XDignore.symbol.file=true"/>
|
||||||
<compilerarg line="${javac.options}"/>
|
<compilerarg line="${javac.options}"/>
|
||||||
|
@ -1287,19 +1287,24 @@ class Attribute implements Comparable<Attribute> {
|
|||||||
if (localRef == 0) {
|
if (localRef == 0) {
|
||||||
globalRef = null; // N.B. global null reference is -1
|
globalRef = null; // N.B. global null reference is -1
|
||||||
} else {
|
} else {
|
||||||
globalRef = holder.getCPMap()[localRef];
|
Entry[] cpMap = holder.getCPMap();
|
||||||
if (e.refKind == CONSTANT_Signature
|
globalRef = (localRef >= 0 && localRef < cpMap.length
|
||||||
|
? cpMap[localRef]
|
||||||
|
: null);
|
||||||
|
byte tag = e.refKind;
|
||||||
|
if (globalRef != null && tag == CONSTANT_Signature
|
||||||
&& globalRef.getTag() == CONSTANT_Utf8) {
|
&& globalRef.getTag() == CONSTANT_Utf8) {
|
||||||
// Cf. ClassReader.readSignatureRef.
|
// Cf. ClassReader.readSignatureRef.
|
||||||
String typeName = globalRef.stringValue();
|
String typeName = globalRef.stringValue();
|
||||||
globalRef = ConstantPool.getSignatureEntry(typeName);
|
globalRef = ConstantPool.getSignatureEntry(typeName);
|
||||||
} else if (e.refKind == CONSTANT_FieldSpecific) {
|
}
|
||||||
assert(globalRef.getTag() >= CONSTANT_Integer);
|
String got = (globalRef == null
|
||||||
assert(globalRef.getTag() <= CONSTANT_String ||
|
? "invalid CP index"
|
||||||
globalRef.getTag() >= CONSTANT_MethodHandle);
|
: "type=" + ConstantPool.tagName(globalRef.tag));
|
||||||
assert(globalRef.getTag() <= CONSTANT_MethodType);
|
if (globalRef == null || !globalRef.tagMatches(tag)) {
|
||||||
} else if (e.refKind < CONSTANT_GroupFirst) {
|
throw new IllegalArgumentException(
|
||||||
assert(e.refKind == globalRef.getTag());
|
"Bad constant, expected type=" +
|
||||||
|
ConstantPool.tagName(tag) + " got " + got);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out.putRef(bandIndex, globalRef);
|
out.putRef(bandIndex, globalRef);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2013, 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
|
||||||
@ -54,6 +54,7 @@ class ClassReader {
|
|||||||
Package pkg;
|
Package pkg;
|
||||||
Class cls;
|
Class cls;
|
||||||
long inPos;
|
long inPos;
|
||||||
|
long constantPoolLimit = -1;
|
||||||
DataInputStream in;
|
DataInputStream in;
|
||||||
Map<Attribute.Layout, Attribute> attrDefs;
|
Map<Attribute.Layout, Attribute> attrDefs;
|
||||||
Map<Attribute.Layout, String> attrCommands;
|
Map<Attribute.Layout, String> attrCommands;
|
||||||
@ -117,15 +118,33 @@ class ClassReader {
|
|||||||
|
|
||||||
private Entry readRef(byte tag) throws IOException {
|
private Entry readRef(byte tag) throws IOException {
|
||||||
Entry e = readRef();
|
Entry e = readRef();
|
||||||
assert(e != null);
|
|
||||||
assert(!(e instanceof UnresolvedEntry));
|
assert(!(e instanceof UnresolvedEntry));
|
||||||
assert(e.tagMatches(tag));
|
checkTag(e, tag);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Throw a ClassFormatException if the entry does not match the expected tag type. */
|
||||||
|
private Entry checkTag(Entry e, byte tag) throws ClassFormatException {
|
||||||
|
if (e == null || !e.tagMatches(tag)) {
|
||||||
|
String where = (inPos == constantPoolLimit
|
||||||
|
? " in constant pool"
|
||||||
|
: " at pos: " + inPos);
|
||||||
|
String got = (e == null
|
||||||
|
? "null CP index"
|
||||||
|
: "type=" + ConstantPool.tagName(e.tag));
|
||||||
|
throw new ClassFormatException("Bad constant, expected type=" +
|
||||||
|
ConstantPool.tagName(tag) +
|
||||||
|
" got "+ got + ", in File: " + cls.file.nameString + where);
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
private Entry checkTag(Entry e, byte tag, boolean nullOK) throws ClassFormatException {
|
||||||
|
return nullOK && e == null ? null : checkTag(e, tag);
|
||||||
|
}
|
||||||
|
|
||||||
private Entry readRefOrNull(byte tag) throws IOException {
|
private Entry readRefOrNull(byte tag) throws IOException {
|
||||||
Entry e = readRef();
|
Entry e = readRef();
|
||||||
assert(e == null || e.tagMatches(tag));
|
checkTag(e, tag, true);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,8 +162,10 @@ class ClassReader {
|
|||||||
|
|
||||||
private SignatureEntry readSignatureRef() throws IOException {
|
private SignatureEntry readSignatureRef() throws IOException {
|
||||||
// The class file stores a Utf8, but we want a Signature.
|
// The class file stores a Utf8, but we want a Signature.
|
||||||
Entry e = readRef(CONSTANT_Utf8);
|
Entry e = readRef(CONSTANT_Signature);
|
||||||
return ConstantPool.getSignatureEntry(e.stringValue());
|
return (e != null && e.getTag() == CONSTANT_Utf8)
|
||||||
|
? ConstantPool.getSignatureEntry(e.stringValue())
|
||||||
|
: (SignatureEntry) e;
|
||||||
}
|
}
|
||||||
|
|
||||||
void read() throws IOException {
|
void read() throws IOException {
|
||||||
@ -279,6 +300,7 @@ class ClassReader {
|
|||||||
" at pos: " + inPos);
|
" at pos: " + inPos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
constantPoolLimit = inPos;
|
||||||
|
|
||||||
// Fix up refs, which might be out of order.
|
// Fix up refs, which might be out of order.
|
||||||
while (fptr > 0) {
|
while (fptr > 0) {
|
||||||
@ -311,25 +333,25 @@ class ClassReader {
|
|||||||
case CONSTANT_Fieldref:
|
case CONSTANT_Fieldref:
|
||||||
case CONSTANT_Methodref:
|
case CONSTANT_Methodref:
|
||||||
case CONSTANT_InterfaceMethodref:
|
case CONSTANT_InterfaceMethodref:
|
||||||
ClassEntry mclass = (ClassEntry) cpMap[ref];
|
ClassEntry mclass = (ClassEntry) checkTag(cpMap[ref], CONSTANT_Class);
|
||||||
DescriptorEntry mdescr = (DescriptorEntry) cpMap[ref2];
|
DescriptorEntry mdescr = (DescriptorEntry) checkTag(cpMap[ref2], CONSTANT_NameandType);
|
||||||
cpMap[cpi] = ConstantPool.getMemberEntry((byte)tag, mclass, mdescr);
|
cpMap[cpi] = ConstantPool.getMemberEntry((byte)tag, mclass, mdescr);
|
||||||
break;
|
break;
|
||||||
case CONSTANT_NameandType:
|
case CONSTANT_NameandType:
|
||||||
Utf8Entry mname = (Utf8Entry) cpMap[ref];
|
Utf8Entry mname = (Utf8Entry) checkTag(cpMap[ref], CONSTANT_Utf8);
|
||||||
Utf8Entry mtype = (Utf8Entry) cpMap[ref2];
|
Utf8Entry mtype = (Utf8Entry) checkTag(cpMap[ref2], CONSTANT_Signature);
|
||||||
cpMap[cpi] = ConstantPool.getDescriptorEntry(mname, mtype);
|
cpMap[cpi] = ConstantPool.getDescriptorEntry(mname, mtype);
|
||||||
break;
|
break;
|
||||||
case CONSTANT_MethodType:
|
case CONSTANT_MethodType:
|
||||||
cpMap[cpi] = ConstantPool.getMethodTypeEntry((Utf8Entry) cpMap[ref]);
|
cpMap[cpi] = ConstantPool.getMethodTypeEntry((Utf8Entry) checkTag(cpMap[ref], CONSTANT_Signature));
|
||||||
break;
|
break;
|
||||||
case CONSTANT_MethodHandle:
|
case CONSTANT_MethodHandle:
|
||||||
byte refKind = (byte)(-1 ^ ref);
|
byte refKind = (byte)(-1 ^ ref);
|
||||||
MemberEntry memRef = (MemberEntry) cpMap[ref2];
|
MemberEntry memRef = (MemberEntry) checkTag(cpMap[ref2], CONSTANT_AnyMember);
|
||||||
cpMap[cpi] = ConstantPool.getMethodHandleEntry(refKind, memRef);
|
cpMap[cpi] = ConstantPool.getMethodHandleEntry(refKind, memRef);
|
||||||
break;
|
break;
|
||||||
case CONSTANT_InvokeDynamic:
|
case CONSTANT_InvokeDynamic:
|
||||||
DescriptorEntry idescr = (DescriptorEntry) cpMap[ref2];
|
DescriptorEntry idescr = (DescriptorEntry) checkTag(cpMap[ref2], CONSTANT_NameandType);
|
||||||
cpMap[cpi] = new UnresolvedEntry((byte)tag, (-1 ^ ref), idescr);
|
cpMap[cpi] = new UnresolvedEntry((byte)tag, (-1 ^ ref), idescr);
|
||||||
// Note that ref must be resolved later, using the BootstrapMethods attribute.
|
// Note that ref must be resolved later, using the BootstrapMethods attribute.
|
||||||
break;
|
break;
|
||||||
@ -541,7 +563,8 @@ class ClassReader {
|
|||||||
code.max_locals = readUnsignedShort();
|
code.max_locals = readUnsignedShort();
|
||||||
code.bytes = new byte[readInt()];
|
code.bytes = new byte[readInt()];
|
||||||
in.readFully(code.bytes);
|
in.readFully(code.bytes);
|
||||||
Instruction.opcodeChecker(code.bytes);
|
Entry[] cpMap = cls.getCPMap();
|
||||||
|
Instruction.opcodeChecker(code.bytes, cpMap);
|
||||||
int nh = readUnsignedShort();
|
int nh = readUnsignedShort();
|
||||||
code.setHandlerCount(nh);
|
code.setHandlerCount(nh);
|
||||||
for (int i = 0; i < nh; i++) {
|
for (int i = 0; i < nh; i++) {
|
||||||
@ -559,7 +582,7 @@ class ClassReader {
|
|||||||
MethodHandleEntry bsmRef = (MethodHandleEntry) readRef(CONSTANT_MethodHandle);
|
MethodHandleEntry bsmRef = (MethodHandleEntry) readRef(CONSTANT_MethodHandle);
|
||||||
Entry[] argRefs = new Entry[readUnsignedShort()];
|
Entry[] argRefs = new Entry[readUnsignedShort()];
|
||||||
for (int j = 0; j < argRefs.length; j++) {
|
for (int j = 0; j < argRefs.length; j++) {
|
||||||
argRefs[j] = readRef();
|
argRefs[j] = readRef(CONSTANT_LoadableValue);
|
||||||
}
|
}
|
||||||
bsms[i] = ConstantPool.getBootstrapMethodEntry(bsmRef, argRefs);
|
bsms[i] = ConstantPool.getBootstrapMethodEntry(bsmRef, argRefs);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2013, 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
|
||||||
@ -243,8 +243,32 @@ class ConstantPool {
|
|||||||
return tag == CONSTANT_Double || tag == CONSTANT_Long;
|
return tag == CONSTANT_Double || tag == CONSTANT_Long;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean tagMatches(int tag) {
|
public final boolean tagMatches(int matchTag) {
|
||||||
return (this.tag == tag);
|
if (tag == matchTag)
|
||||||
|
return true;
|
||||||
|
byte[] allowedTags;
|
||||||
|
switch (matchTag) {
|
||||||
|
case CONSTANT_All:
|
||||||
|
return true;
|
||||||
|
case CONSTANT_Signature:
|
||||||
|
return tag == CONSTANT_Utf8; // format check also?
|
||||||
|
case CONSTANT_LoadableValue:
|
||||||
|
allowedTags = LOADABLE_VALUE_TAGS;
|
||||||
|
break;
|
||||||
|
case CONSTANT_AnyMember:
|
||||||
|
allowedTags = ANY_MEMBER_TAGS;
|
||||||
|
break;
|
||||||
|
case CONSTANT_FieldSpecific:
|
||||||
|
allowedTags = FIELD_SPECIFIC_TAGS;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (byte b : allowedTags) {
|
||||||
|
if (b == tag)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2013, 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
|
||||||
@ -647,7 +647,7 @@ class Instruction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void opcodeChecker(byte[] code) throws FormatException {
|
public static void opcodeChecker(byte[] code, ConstantPool.Entry[] cpMap) throws FormatException {
|
||||||
Instruction i = at(code, 0);
|
Instruction i = at(code, 0);
|
||||||
while (i != null) {
|
while (i != null) {
|
||||||
int opcode = i.getBC();
|
int opcode = i.getBC();
|
||||||
@ -655,6 +655,16 @@ class Instruction {
|
|||||||
String message = "illegal opcode: " + opcode + " " + i;
|
String message = "illegal opcode: " + opcode + " " + i;
|
||||||
throw new FormatException(message);
|
throw new FormatException(message);
|
||||||
}
|
}
|
||||||
|
ConstantPool.Entry e = i.getCPRef(cpMap);
|
||||||
|
if (e != null) {
|
||||||
|
byte tag = i.getCPTag();
|
||||||
|
if (!e.tagMatches(tag)) {
|
||||||
|
String message = "illegal reference, expected type=" +
|
||||||
|
ConstantPool.tagName(tag) + ": " +
|
||||||
|
i.toString(cpMap);
|
||||||
|
throw new FormatException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
i = i.next();
|
i = i.next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1618,6 +1618,16 @@ class PackageWriter extends BandStructure {
|
|||||||
bc_which = null;
|
bc_which = null;
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
if (ref != null && bc_which.index != null && !bc_which.index.contains(ref)) {
|
||||||
|
// Crash and burn with a complaint if there are funny
|
||||||
|
// references for this bytecode instruction.
|
||||||
|
// Example: invokestatic of a CONSTANT_InterfaceMethodref.
|
||||||
|
String complaint = code.getMethod() +
|
||||||
|
" contains a bytecode " + i +
|
||||||
|
" with an unsupported constant reference; please use the pass-file option on this class.";
|
||||||
|
Utils.log.warning(complaint);
|
||||||
|
throw new IOException(complaint);
|
||||||
|
}
|
||||||
bc_codes.putByte(vbc);
|
bc_codes.putByte(vbc);
|
||||||
bc_which.putRef(ref);
|
bc_which.putRef(ref);
|
||||||
// handle trailing junk
|
// handle trailing junk
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2013, 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
|
||||||
@ -180,6 +180,15 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer {
|
|||||||
}
|
}
|
||||||
unknownAttrCommand = uaMode.intern();
|
unknownAttrCommand = uaMode.intern();
|
||||||
}
|
}
|
||||||
|
final String classFormatCommand;
|
||||||
|
{
|
||||||
|
String fmtMode = props.getProperty(Utils.CLASS_FORMAT_ERROR, Pack200.Packer.PASS);
|
||||||
|
if (!(Pack200.Packer.PASS.equals(fmtMode) ||
|
||||||
|
Pack200.Packer.ERROR.equals(fmtMode))) {
|
||||||
|
throw new RuntimeException("Bad option: " + Utils.CLASS_FORMAT_ERROR + " = " + fmtMode);
|
||||||
|
}
|
||||||
|
classFormatCommand = fmtMode.intern();
|
||||||
|
}
|
||||||
|
|
||||||
final Map<Attribute.Layout, Attribute> attrDefs;
|
final Map<Attribute.Layout, Attribute> attrDefs;
|
||||||
final Map<Attribute.Layout, String> attrCommands;
|
final Map<Attribute.Layout, String> attrCommands;
|
||||||
@ -505,8 +514,7 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer {
|
|||||||
}
|
}
|
||||||
} else if (ioe instanceof ClassReader.ClassFormatException) {
|
} else if (ioe instanceof ClassReader.ClassFormatException) {
|
||||||
ClassReader.ClassFormatException ce = (ClassReader.ClassFormatException) ioe;
|
ClassReader.ClassFormatException ce = (ClassReader.ClassFormatException) ioe;
|
||||||
// %% TODO: Do we invent a new property for this or reuse %%
|
if (classFormatCommand.equals(Pack200.Packer.PASS)) {
|
||||||
if (unknownAttrCommand.equals(Pack200.Packer.PASS)) {
|
|
||||||
Utils.log.info(ce.toString());
|
Utils.log.info(ce.toString());
|
||||||
Utils.log.warning(message + " unknown class format: " +
|
Utils.log.warning(message + " unknown class format: " +
|
||||||
fname);
|
fname);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2013, 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
|
||||||
@ -112,6 +112,11 @@ final class PropMap implements SortedMap<String, String> {
|
|||||||
// Pass through files with unrecognized attributes by default.
|
// Pass through files with unrecognized attributes by default.
|
||||||
props.put(Pack200.Packer.UNKNOWN_ATTRIBUTE, Pack200.Packer.PASS);
|
props.put(Pack200.Packer.UNKNOWN_ATTRIBUTE, Pack200.Packer.PASS);
|
||||||
|
|
||||||
|
// Pass through files with unrecognized format by default, also
|
||||||
|
// allow system property to be set
|
||||||
|
props.put(Utils.CLASS_FORMAT_ERROR,
|
||||||
|
System.getProperty(Utils.CLASS_FORMAT_ERROR, Pack200.Packer.PASS));
|
||||||
|
|
||||||
// Default effort is 5, midway between 1 and 9.
|
// Default effort is 5, midway between 1 and 9.
|
||||||
props.put(Pack200.Packer.EFFORT, "5");
|
props.put(Pack200.Packer.EFFORT, "5");
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2013, 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
|
||||||
@ -122,6 +122,12 @@ class Utils {
|
|||||||
*/
|
*/
|
||||||
static final String PACK_ZIP_ARCHIVE_MARKER_COMMENT = "PACK200";
|
static final String PACK_ZIP_ARCHIVE_MARKER_COMMENT = "PACK200";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* behaviour when we hit a class format error, but not necessarily
|
||||||
|
* an unknown attribute, by default it is allowed to PASS.
|
||||||
|
*/
|
||||||
|
static final String CLASS_FORMAT_ERROR = COM_PREFIX+"class.format.error";
|
||||||
|
|
||||||
// Keep a TLS point to the global data and environment.
|
// Keep a TLS point to the global data and environment.
|
||||||
// This makes it simpler to supply environmental options
|
// This makes it simpler to supply environmental options
|
||||||
// to the engine code, especially the native code.
|
// to the engine code, especially the native code.
|
||||||
|
@ -50,8 +50,6 @@ import javax.management.MBeanInfo;
|
|||||||
import javax.management.NotCompliantMBeanException;
|
import javax.management.NotCompliantMBeanException;
|
||||||
|
|
||||||
import com.sun.jmx.remote.util.EnvHelp;
|
import com.sun.jmx.remote.util.EnvHelp;
|
||||||
import java.beans.BeanInfo;
|
|
||||||
import java.beans.PropertyDescriptor;
|
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import javax.management.AttributeNotFoundException;
|
import javax.management.AttributeNotFoundException;
|
||||||
|
@ -29,12 +29,14 @@ import java.lang.reflect.Array;
|
|||||||
import java.lang.reflect.GenericArrayType;
|
import java.lang.reflect.GenericArrayType;
|
||||||
import java.lang.reflect.Member;
|
import java.lang.reflect.Member;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Executable;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.lang.reflect.TypeVariable;
|
import java.lang.reflect.TypeVariable;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.AnnotatedType;
|
||||||
import java.lang.ref.SoftReference;
|
import java.lang.ref.SoftReference;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.ObjectStreamField;
|
import java.io.ObjectStreamField;
|
||||||
@ -2325,6 +2327,11 @@ public final
|
|||||||
|
|
||||||
// Annotations handling
|
// Annotations handling
|
||||||
private native byte[] getRawAnnotations();
|
private native byte[] getRawAnnotations();
|
||||||
|
// Since 1.8
|
||||||
|
native byte[] getRawTypeAnnotations();
|
||||||
|
static byte[] getExecutableTypeAnnotationBytes(Executable ex) {
|
||||||
|
return getReflectionFactory().getExecutableTypeAnnotationBytes(ex);
|
||||||
|
}
|
||||||
|
|
||||||
native ConstantPool getConstantPool();
|
native ConstantPool getConstantPool();
|
||||||
|
|
||||||
@ -3068,21 +3075,12 @@ public final
|
|||||||
* @throws NullPointerException {@inheritDoc}
|
* @throws NullPointerException {@inheritDoc}
|
||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
|
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
|
||||||
Objects.requireNonNull(annotationClass);
|
Objects.requireNonNull(annotationClass);
|
||||||
|
|
||||||
initAnnotationsIfNecessary();
|
initAnnotationsIfNecessary();
|
||||||
return AnnotationSupport.getOneAnnotation(annotations, annotationClass);
|
return (A) annotations.get(annotationClass);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws NullPointerException {@inheritDoc}
|
|
||||||
* @since 1.5
|
|
||||||
*/
|
|
||||||
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
|
|
||||||
Objects.requireNonNull(annotationClass);
|
|
||||||
|
|
||||||
return getAnnotation(annotationClass) != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3101,18 +3099,19 @@ public final
|
|||||||
*/
|
*/
|
||||||
public Annotation[] getAnnotations() {
|
public Annotation[] getAnnotations() {
|
||||||
initAnnotationsIfNecessary();
|
initAnnotationsIfNecessary();
|
||||||
return AnnotationSupport.unpackToArray(annotations);
|
return AnnotationParser.toArray(annotations);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws NullPointerException {@inheritDoc}
|
* @throws NullPointerException {@inheritDoc}
|
||||||
* @since 1.8
|
* @since 1.8
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) {
|
public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) {
|
||||||
Objects.requireNonNull(annotationClass);
|
Objects.requireNonNull(annotationClass);
|
||||||
|
|
||||||
initAnnotationsIfNecessary();
|
initAnnotationsIfNecessary();
|
||||||
return AnnotationSupport.getOneAnnotation(declaredAnnotations, annotationClass);
|
return (A) declaredAnnotations.get(annotationClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3131,17 +3130,7 @@ public final
|
|||||||
*/
|
*/
|
||||||
public Annotation[] getDeclaredAnnotations() {
|
public Annotation[] getDeclaredAnnotations() {
|
||||||
initAnnotationsIfNecessary();
|
initAnnotationsIfNecessary();
|
||||||
return AnnotationSupport.unpackToArray(declaredAnnotations);
|
return AnnotationParser.toArray(declaredAnnotations);
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns one "directly" present annotation or null */
|
|
||||||
<A extends Annotation> A getDirectDeclaredAnnotation(Class<A> annotationClass) {
|
|
||||||
Objects.requireNonNull(annotationClass);
|
|
||||||
|
|
||||||
initAnnotationsIfNecessary();
|
|
||||||
@SuppressWarnings("unchecked") // TODO check safe
|
|
||||||
A ret = (A)declaredAnnotations.get(annotationClass);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Annotations cache
|
// Annotations cache
|
||||||
@ -3196,4 +3185,53 @@ public final
|
|||||||
* Maintained by the ClassValue class.
|
* Maintained by the ClassValue class.
|
||||||
*/
|
*/
|
||||||
transient ClassValue.ClassValueMap classValueMap;
|
transient ClassValue.ClassValueMap classValueMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an AnnotatedType object that represents the use of a type to specify
|
||||||
|
* the superclass of the entity represented by this Class. (The <em>use</em> of type
|
||||||
|
* Foo to specify the superclass in '... extends Foo' is distinct from the
|
||||||
|
* <em>declaration</em> of type Foo.)
|
||||||
|
*
|
||||||
|
* If this Class represents a class type whose declaration does not explicitly
|
||||||
|
* indicate an annotated superclass, the return value is null.
|
||||||
|
*
|
||||||
|
* If this Class represents either the Object class, an interface type, an
|
||||||
|
* array type, a primitive type, or void, the return value is null.
|
||||||
|
*
|
||||||
|
* @since 1.8
|
||||||
|
*/
|
||||||
|
public AnnotatedType getAnnotatedSuperclass() {
|
||||||
|
return TypeAnnotationParser.buildAnnotatedSuperclass(getRawTypeAnnotations(), getConstantPool(), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of AnnotatedType objects that represent the use of types to
|
||||||
|
* specify superinterfaces of the entity represented by this Class. (The <em>use</em>
|
||||||
|
* of type Foo to specify a superinterface in '... implements Foo' is
|
||||||
|
* distinct from the <em>declaration</em> of type Foo.)
|
||||||
|
*
|
||||||
|
* If this Class represents a class, the return value is an array
|
||||||
|
* containing objects representing the uses of interface types to specify
|
||||||
|
* interfaces implemented by the class. The order of the objects in the
|
||||||
|
* array corresponds to the order of the interface types used in the
|
||||||
|
* 'implements' clause of the declaration of this Class.
|
||||||
|
*
|
||||||
|
* If this Class represents an interface, the return value is an array
|
||||||
|
* containing objects representing the uses of interface types to specify
|
||||||
|
* interfaces directly extended by the interface. The order of the objects in
|
||||||
|
* the array corresponds to the order of the interface types used in the
|
||||||
|
* 'extends' clause of the declaration of this Class.
|
||||||
|
*
|
||||||
|
* If this Class represents a class or interface whose declaration does not
|
||||||
|
* explicitly indicate any annotated superinterfaces, the return value is an
|
||||||
|
* array of length 0.
|
||||||
|
*
|
||||||
|
* If this Class represents either the Object class, an array type, a
|
||||||
|
* primitive type, or void, the return value is an array of length 0.
|
||||||
|
*
|
||||||
|
* @since 1.8
|
||||||
|
*/
|
||||||
|
public AnnotatedType[] getAnnotatedInterfaces() {
|
||||||
|
return TypeAnnotationParser.buildAnnotatedInterfaces(getRawTypeAnnotations(), getConstantPool(), this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1994, 2013, 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
|
||||||
@ -289,7 +289,7 @@ public final class Double extends Number implements Comparable<Double> {
|
|||||||
return Double.toString(d);
|
return Double.toString(d);
|
||||||
else {
|
else {
|
||||||
// Initialized to maximum size of output.
|
// Initialized to maximum size of output.
|
||||||
StringBuffer answer = new StringBuffer(24);
|
StringBuilder answer = new StringBuilder(24);
|
||||||
|
|
||||||
if (Math.copySign(1.0, d) == -1.0) // value is negative,
|
if (Math.copySign(1.0, d) == -1.0) // value is negative,
|
||||||
answer.append("-"); // so append sign info
|
answer.append("-"); // so append sign info
|
||||||
@ -300,8 +300,7 @@ public final class Double extends Number implements Comparable<Double> {
|
|||||||
|
|
||||||
if(d == 0.0) {
|
if(d == 0.0) {
|
||||||
answer.append("0.0p0");
|
answer.append("0.0p0");
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
boolean subnormal = (d < DoubleConsts.MIN_NORMAL);
|
boolean subnormal = (d < DoubleConsts.MIN_NORMAL);
|
||||||
|
|
||||||
// Isolate significand bits and OR in a high-order bit
|
// Isolate significand bits and OR in a high-order bit
|
||||||
@ -324,13 +323,14 @@ public final class Double extends Number implements Comparable<Double> {
|
|||||||
"0":
|
"0":
|
||||||
signif.replaceFirst("0{1,12}$", ""));
|
signif.replaceFirst("0{1,12}$", ""));
|
||||||
|
|
||||||
|
answer.append('p');
|
||||||
// If the value is subnormal, use the E_min exponent
|
// If the value is subnormal, use the E_min exponent
|
||||||
// value for double; otherwise, extract and report d's
|
// value for double; otherwise, extract and report d's
|
||||||
// exponent (the representation of a subnormal uses
|
// exponent (the representation of a subnormal uses
|
||||||
// E_min -1).
|
// E_min -1).
|
||||||
answer.append("p" + (subnormal ?
|
answer.append(subnormal ?
|
||||||
DoubleConsts.MIN_EXPONENT:
|
DoubleConsts.MIN_EXPONENT:
|
||||||
Math.getExponent(d) ));
|
Math.getExponent(d));
|
||||||
}
|
}
|
||||||
return answer.toString();
|
return answer.toString();
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2013, 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
|
||||||
@ -385,15 +385,6 @@ public class Package implements java.lang.reflect.AnnotatedElement {
|
|||||||
return getPackageInfo().getAnnotation(annotationClass);
|
return getPackageInfo().getAnnotation(annotationClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws NullPointerException {@inheritDoc}
|
|
||||||
* @since 1.5
|
|
||||||
*/
|
|
||||||
public boolean isAnnotationPresent(
|
|
||||||
Class<? extends Annotation> annotationClass) {
|
|
||||||
return getPackageInfo().isAnnotationPresent(annotationClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws NullPointerException {@inheritDoc}
|
* @throws NullPointerException {@inheritDoc}
|
||||||
* @since 1.8
|
* @since 1.8
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1994, 2013, 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,7 +25,7 @@
|
|||||||
package java.lang;
|
package java.lang;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.reflect.Executable;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.PropertyPermission;
|
import java.util.PropertyPermission;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
@ -1196,8 +1196,11 @@ public final class System {
|
|||||||
public AnnotationType getAnnotationType(Class<?> klass) {
|
public AnnotationType getAnnotationType(Class<?> klass) {
|
||||||
return klass.getAnnotationType();
|
return klass.getAnnotationType();
|
||||||
}
|
}
|
||||||
public <A extends Annotation> A getDirectDeclaredAnnotation(Class<?> klass, Class<A> anno) {
|
public byte[] getRawClassTypeAnnotations(Class<?> klass) {
|
||||||
return klass.getDirectDeclaredAnnotation(anno);
|
return klass.getRawTypeAnnotations();
|
||||||
|
}
|
||||||
|
public byte[] getRawExecutableTypeAnnotations(Executable executable) {
|
||||||
|
return Class.getExecutableTypeAnnotationBytes(executable);
|
||||||
}
|
}
|
||||||
public <E extends Enum<E>>
|
public <E extends Enum<E>>
|
||||||
E[] getEnumConstantsShared(Class<E> klass) {
|
E[] getEnumConstantsShared(Class<E> klass) {
|
||||||
|
@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2012, 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. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package java.lang.annotation;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The annotation type {@code java.lang.annotation.ContainedBy} is
|
|
||||||
* used to indicate that the annotation type whose declaration it
|
|
||||||
* (meta-)annotates is <em>repeatable</em>. The value of
|
|
||||||
* {@code @ContainedBy} indicates the <em>containing annotation
|
|
||||||
* type</em> for the repeatable annotation type.
|
|
||||||
*
|
|
||||||
* <p>The pair of annotation types {@code @ContainedBy} and
|
|
||||||
* {@link java.lang.annotation.ContainerFor @ContainerFor} are used to
|
|
||||||
* indicate that annotation types are repeatable. Specifically:
|
|
||||||
*
|
|
||||||
* <ul>
|
|
||||||
* <li>The annotation type {@code @ContainedBy} is used on the
|
|
||||||
* declaration of a repeatable annotation type (JLS 9.6) to indicate
|
|
||||||
* its containing annotation type.
|
|
||||||
*
|
|
||||||
* <li>The annotation type {@code @ContainerFor} is used on the
|
|
||||||
* declaration of a containing annotation type (JLS 9.6) to indicate
|
|
||||||
* the repeatable annotation type for which it serves as the
|
|
||||||
* containing annotation type.
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* An inconsistent pair of {@code @ContainedBy} and
|
|
||||||
* {@code @ContainerFor} annotations on a repeatable annotation type
|
|
||||||
* and its containing annotation type (JLS 9.6) will lead to
|
|
||||||
* compile-time errors and runtime exceptions when using reflection to
|
|
||||||
* read annotations of a repeatable type.
|
|
||||||
*
|
|
||||||
* @see java.lang.annotation.ContainerFor
|
|
||||||
* @since 1.8
|
|
||||||
* @jls 9.6 Annotation Types
|
|
||||||
* @jls 9.7 Annotations
|
|
||||||
*/
|
|
||||||
@Documented
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(ElementType.ANNOTATION_TYPE)
|
|
||||||
public @interface ContainedBy {
|
|
||||||
/**
|
|
||||||
* Indicates the <em>containing annotation type</em> for the
|
|
||||||
* repeatable annotation type.
|
|
||||||
*/
|
|
||||||
Class<? extends Annotation> value();
|
|
||||||
}
|
|
@ -1,73 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2012, 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. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package java.lang.annotation;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The annotation type {@code java.lang.annotation.ContainerFor} is
|
|
||||||
* used to indicate that the annotation type whose declaration it
|
|
||||||
* (meta-)annotates is a <em>containing annotation type</em>. The
|
|
||||||
* value of {@code @ContainerFor} indicates the <em>repeatable
|
|
||||||
* annotation type</em> for the containing annotation type.
|
|
||||||
*
|
|
||||||
* <p>The pair of annotation types {@link
|
|
||||||
* java.lang.annotation.ContainedBy @ContainedBy} and
|
|
||||||
* {@code @ContainerFor} are used to indicate that annotation types
|
|
||||||
* are repeatable. Specifically:
|
|
||||||
*
|
|
||||||
* <ul>
|
|
||||||
* <li>The annotation type {@code @ContainedBy} is used on the
|
|
||||||
* declaration of a repeatable annotation type (JLS 9.6) to indicate
|
|
||||||
* its containing annotation type.
|
|
||||||
*
|
|
||||||
* <li>The annotation type {@code @ContainerFor} is used on the
|
|
||||||
* declaration of a containing annotation type (JLS 9.6) to indicate
|
|
||||||
* the repeatable annotation type for which it serves as the
|
|
||||||
* containing annotation type.
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* An inconsistent pair of {@code @ContainedBy} and
|
|
||||||
* {@code @ContainerFor} annotations on a repeatable annotation type
|
|
||||||
* and its containing annotation type (JLS 9.6) will lead to
|
|
||||||
* compile-time errors and runtime exceptions when using reflection to
|
|
||||||
* read annotations of a repeatable type.
|
|
||||||
*
|
|
||||||
* @see java.lang.annotation.ContainedBy
|
|
||||||
* @since 1.8
|
|
||||||
* @jls 9.6 Annotation Types
|
|
||||||
* @jls 9.7 Annotations
|
|
||||||
*/
|
|
||||||
@Documented
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(ElementType.ANNOTATION_TYPE)
|
|
||||||
public @interface ContainerFor {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates the repeatable annotation type for the containing
|
|
||||||
* annotation type.
|
|
||||||
*/
|
|
||||||
Class<? extends Annotation> value();
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2013, 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
|
||||||
@ -27,10 +27,9 @@ package java.lang.annotation;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thrown to indicate that an annotation type whose declaration is
|
* Thrown to indicate that an annotation type expected to act as a
|
||||||
* (meta-)annotated with a {@link ContainerFor} annotation is not, in
|
* container for another annotation type by virture of an @Repeatable
|
||||||
* fact, the <em>containing annotation type of the type named by {@link
|
* annotation, does not act as a container.
|
||||||
* ContainerFor}</em>.
|
|
||||||
*
|
*
|
||||||
* @see java.lang.reflect.AnnotatedElement
|
* @see java.lang.reflect.AnnotatedElement
|
||||||
* @since 1.8
|
* @since 1.8
|
||||||
|
@ -180,14 +180,6 @@ public class AccessibleObject implements AnnotatedElement {
|
|||||||
throw new AssertionError("All subclasses should override this method");
|
throw new AssertionError("All subclasses should override this method");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws NullPointerException {@inheritDoc}
|
|
||||||
* @since 1.5
|
|
||||||
*/
|
|
||||||
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
|
|
||||||
return getAnnotation(annotationClass) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws NullPointerException {@inheritDoc}
|
* @throws NullPointerException {@inheritDoc}
|
||||||
* @since 1.8
|
* @since 1.8
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 2013, 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. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package java.lang.reflect;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AnnotatedArrayType represents the use of an array type, whose component
|
||||||
|
* type may itself represent the annotated use of a type.
|
||||||
|
*
|
||||||
|
* @since 1.8
|
||||||
|
*/
|
||||||
|
public interface AnnotatedArrayType extends AnnotatedType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the annotated generic component type of this array type.
|
||||||
|
*
|
||||||
|
* @return the annotated generic component type of this array type
|
||||||
|
*/
|
||||||
|
AnnotatedType getAnnotatedGenericComponentType();
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2013, 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
|
||||||
@ -35,6 +35,24 @@ import java.lang.annotation.Annotation;
|
|||||||
* arrays returned by accessors for array-valued enum members; it will
|
* arrays returned by accessors for array-valued enum members; it will
|
||||||
* have no affect on the arrays returned to other callers.
|
* have no affect on the arrays returned to other callers.
|
||||||
*
|
*
|
||||||
|
* <p>An annotation A is <em>directly present</em> on an element E if the
|
||||||
|
* RuntimeVisibleAnnotations or RuntimeVisibleParameterAnnotations attribute
|
||||||
|
* associated with E either:
|
||||||
|
* <ul>
|
||||||
|
* <li>contains A; or
|
||||||
|
* <li>for invocations of get[Declared]Annotations(Class<T>),
|
||||||
|
* contains A or exactly one annotation C whose type is the containing
|
||||||
|
* annotation type of A's type (JLS 9.6) and whose value element contains A
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>An annotation A is <em>present</em> on an element E if either:
|
||||||
|
* <ul>
|
||||||
|
* <li>A is <em>directly present</em> on E; or
|
||||||
|
* <li>There are no annotations of A's type which are <em>directly present</em>
|
||||||
|
* on E, and E is a class, and A's type is inheritable (JLS 9.6.3.3), and A is
|
||||||
|
* present on the superclass of E
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
* <p>If an annotation returned by a method in this interface contains
|
* <p>If an annotation returned by a method in this interface contains
|
||||||
* (directly or indirectly) a {@link Class}-valued member referring to
|
* (directly or indirectly) a {@link Class}-valued member referring to
|
||||||
* a class that is not accessible in this VM, attempting to read the class
|
* a class that is not accessible in this VM, attempting to read the class
|
||||||
@ -50,7 +68,7 @@ import java.lang.annotation.Annotation;
|
|||||||
* containing annotation type of T will result in an
|
* containing annotation type of T will result in an
|
||||||
* InvalidContainerAnnotationError.
|
* InvalidContainerAnnotationError.
|
||||||
*
|
*
|
||||||
* <p>Finally, Attempting to read a member whose definition has evolved
|
* <p>Finally, attempting to read a member whose definition has evolved
|
||||||
* incompatibly will result in a {@link
|
* incompatibly will result in a {@link
|
||||||
* java.lang.annotation.AnnotationTypeMismatchException} or an
|
* java.lang.annotation.AnnotationTypeMismatchException} or an
|
||||||
* {@link java.lang.annotation.IncompleteAnnotationException}.
|
* {@link java.lang.annotation.IncompleteAnnotationException}.
|
||||||
@ -70,6 +88,12 @@ public interface AnnotatedElement {
|
|||||||
* is present on this element, else false. This method
|
* is present on this element, else false. This method
|
||||||
* is designed primarily for convenient access to marker annotations.
|
* is designed primarily for convenient access to marker annotations.
|
||||||
*
|
*
|
||||||
|
* <p>The truth value returned by this method is equivalent to:
|
||||||
|
* {@code getAnnotation(annotationClass) != null}
|
||||||
|
*
|
||||||
|
* <p>The body of the default method is specified to be the code
|
||||||
|
* above.
|
||||||
|
*
|
||||||
* @param annotationClass the Class object corresponding to the
|
* @param annotationClass the Class object corresponding to the
|
||||||
* annotation type
|
* annotation type
|
||||||
* @return true if an annotation for the specified annotation
|
* @return true if an annotation for the specified annotation
|
||||||
@ -77,7 +101,9 @@ public interface AnnotatedElement {
|
|||||||
* @throws NullPointerException if the given annotation class is null
|
* @throws NullPointerException if the given annotation class is null
|
||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass);
|
default boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
|
||||||
|
return getAnnotation(annotationClass) != null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns this element's annotation for the specified type if
|
* Returns this element's annotation for the specified type if
|
||||||
@ -110,12 +136,15 @@ public interface AnnotatedElement {
|
|||||||
<T extends Annotation> T[] getAnnotations(Class<T> annotationClass);
|
<T extends Annotation> T[] getAnnotations(Class<T> annotationClass);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all annotations present on this element. (Returns an array
|
* Returns annotations that are <em>present</em> on this element.
|
||||||
* of length zero if this element has no annotations.) The caller of
|
|
||||||
* this method is free to modify the returned array; it will have no
|
|
||||||
* effect on the arrays returned to other callers.
|
|
||||||
*
|
*
|
||||||
* @return all annotations present on this element
|
* If there are no annotations <em>present</em> on this element, the return
|
||||||
|
* value is an array of length 0.
|
||||||
|
*
|
||||||
|
* The caller of this method is free to modify the returned array; it will
|
||||||
|
* have no effect on the arrays returned to other callers.
|
||||||
|
*
|
||||||
|
* @return annotations present on this element
|
||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
Annotation[] getAnnotations();
|
Annotation[] getAnnotations();
|
||||||
@ -157,14 +186,16 @@ public interface AnnotatedElement {
|
|||||||
<T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass);
|
<T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all annotations that are directly present on this
|
* Returns annotations that are <em>directly present</em> on this element.
|
||||||
* element. This method ignores inherited annotations. (Returns
|
* This method ignores inherited annotations.
|
||||||
* an array of length zero if no annotations are directly present
|
|
||||||
* on this element.) The caller of this method is free to modify
|
|
||||||
* the returned array; it will have no effect on the arrays
|
|
||||||
* returned to other callers.
|
|
||||||
*
|
*
|
||||||
* @return All annotations directly present on this element
|
* If there are no annotations <em>directly present</em> on this element,
|
||||||
|
* the return value is an array of length 0.
|
||||||
|
*
|
||||||
|
* The caller of this method is free to modify the returned array; it will
|
||||||
|
* have no effect on the arrays returned to other callers.
|
||||||
|
*
|
||||||
|
* @return annotations directly present on this element
|
||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
Annotation[] getDeclaredAnnotations();
|
Annotation[] getDeclaredAnnotations();
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 2013, 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. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package java.lang.reflect;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AnnotatedParameterizedType represents the use of a parameterized type,
|
||||||
|
* whose type arguments may themselves represent annotated uses of types.
|
||||||
|
*
|
||||||
|
* @since 1.8
|
||||||
|
*/
|
||||||
|
public interface AnnotatedParameterizedType extends AnnotatedType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the annotated actual type arguments of this parameterized type.
|
||||||
|
*
|
||||||
|
* @return the annotated actual type arguments of this parameterized type
|
||||||
|
*/
|
||||||
|
AnnotatedType[] getAnnotatedActualTypeArguments();
|
||||||
|
}
|
44
jdk/src/share/classes/java/lang/reflect/AnnotatedType.java
Normal file
44
jdk/src/share/classes/java/lang/reflect/AnnotatedType.java
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 2013, 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. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package java.lang.reflect;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AnnotatedType represents the annotated use of a type in the program
|
||||||
|
* currently running in this VM. The use may be of any type in the Java
|
||||||
|
* programming language, including an array type, a parameterized type, a type
|
||||||
|
* variable, or a wildcard type.
|
||||||
|
*
|
||||||
|
* @since 1.8
|
||||||
|
*/
|
||||||
|
public interface AnnotatedType extends AnnotatedElement {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the underlying type that this annotated type represents.
|
||||||
|
*
|
||||||
|
* @return the type this annotated type represents
|
||||||
|
*/
|
||||||
|
public Type getType();
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 2013, 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. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package java.lang.reflect;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AnnotatedTypeVariable represents the use of a type variable, whose
|
||||||
|
* declaration may have bounds which themselves represent annotated uses of
|
||||||
|
* types.
|
||||||
|
*
|
||||||
|
* @since 1.8
|
||||||
|
*/
|
||||||
|
public interface AnnotatedTypeVariable extends AnnotatedType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the annotated bounds of this type variable.
|
||||||
|
*
|
||||||
|
* @return the annotated bounds of this type variable
|
||||||
|
*/
|
||||||
|
AnnotatedType[] getAnnotatedBounds();
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 2013, 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. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package java.lang.reflect;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AnnotatedWildcardType represents the use of a wildcard type argument, whose
|
||||||
|
* upper or lower bounds may themselves represent annotated uses of types.
|
||||||
|
*
|
||||||
|
* @since 1.8
|
||||||
|
*/
|
||||||
|
public interface AnnotatedWildcardType extends AnnotatedType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the annotated lower bounds of this wildcard type.
|
||||||
|
*
|
||||||
|
* @return the annotated lower bounds of this wildcard type
|
||||||
|
*/
|
||||||
|
AnnotatedType[] getAnnotatedLowerBounds();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the annotated upper bounds of this wildcard type.
|
||||||
|
*
|
||||||
|
* @return the annotated upper bounds of this wildcard type
|
||||||
|
*/
|
||||||
|
AnnotatedType[] getAnnotatedUpperBounds();
|
||||||
|
}
|
@ -154,6 +154,10 @@ public final class Constructor<T> extends Executable {
|
|||||||
byte[] getAnnotationBytes() {
|
byte[] getAnnotationBytes() {
|
||||||
return annotations;
|
return annotations;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
byte[] getTypeAnnotationBytes() {
|
||||||
|
return typeAnnotations;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
@ -523,4 +527,12 @@ public final class Constructor<T> extends Executable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* @since 1.8
|
||||||
|
*/
|
||||||
|
public AnnotatedType getAnnotatedReturnType() {
|
||||||
|
return getAnnotatedReturnType0(getDeclaringClass());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2013, 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
|
||||||
@ -26,11 +26,12 @@
|
|||||||
package java.lang.reflect;
|
package java.lang.reflect;
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import sun.reflect.annotation.AnnotationParser;
|
import sun.reflect.annotation.AnnotationParser;
|
||||||
import sun.reflect.annotation.AnnotationSupport;
|
import sun.reflect.annotation.AnnotationSupport;
|
||||||
|
import sun.reflect.annotation.TypeAnnotationParser;
|
||||||
|
import sun.reflect.annotation.TypeAnnotation;
|
||||||
import sun.reflect.generics.repository.ConstructorRepository;
|
import sun.reflect.generics.repository.ConstructorRepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,6 +51,7 @@ public abstract class Executable extends AccessibleObject
|
|||||||
* Accessor method to allow code sharing
|
* Accessor method to allow code sharing
|
||||||
*/
|
*/
|
||||||
abstract byte[] getAnnotationBytes();
|
abstract byte[] getAnnotationBytes();
|
||||||
|
abstract byte[] getTypeAnnotationBytes();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does the Executable have generic information.
|
* Does the Executable have generic information.
|
||||||
@ -435,8 +437,7 @@ public abstract class Executable extends AccessibleObject
|
|||||||
*/
|
*/
|
||||||
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
|
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
|
||||||
Objects.requireNonNull(annotationClass);
|
Objects.requireNonNull(annotationClass);
|
||||||
|
return annotationClass.cast(declaredAnnotations().get(annotationClass));
|
||||||
return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -454,7 +455,7 @@ public abstract class Executable extends AccessibleObject
|
|||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public Annotation[] getDeclaredAnnotations() {
|
public Annotation[] getDeclaredAnnotations() {
|
||||||
return AnnotationSupport.unpackToArray(declaredAnnotations());
|
return AnnotationParser.toArray(declaredAnnotations());
|
||||||
}
|
}
|
||||||
|
|
||||||
private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
|
private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
|
||||||
@ -470,4 +471,86 @@ public abstract class Executable extends AccessibleObject
|
|||||||
return declaredAnnotations;
|
return declaredAnnotations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Helper for subclasses of Executable.
|
||||||
|
*
|
||||||
|
* Returns an AnnotatedType object that represents the use of a type to
|
||||||
|
* specify the return type of the method/constructor represented by this
|
||||||
|
* Executable.
|
||||||
|
*
|
||||||
|
* @since 1.8
|
||||||
|
*/
|
||||||
|
AnnotatedType getAnnotatedReturnType0(Type returnType) {
|
||||||
|
return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes(),
|
||||||
|
sun.misc.SharedSecrets.getJavaLangAccess().
|
||||||
|
getConstantPool(getDeclaringClass()),
|
||||||
|
this,
|
||||||
|
getDeclaringClass(),
|
||||||
|
returnType,
|
||||||
|
TypeAnnotation.TypeAnnotationTarget.METHOD_RETURN_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an AnnotatedType object that represents the use of a type to
|
||||||
|
* specify the receiver type of the method/constructor represented by this
|
||||||
|
* Executable. The receiver type of a method/constructor is available only
|
||||||
|
* if the method/constructor declares a formal parameter called 'this'.
|
||||||
|
*
|
||||||
|
* Returns null if this Executable represents a constructor or instance
|
||||||
|
* method that either declares no formal parameter called 'this', or
|
||||||
|
* declares a formal parameter called 'this' with no annotations on its
|
||||||
|
* type.
|
||||||
|
*
|
||||||
|
* Returns null if this Executable represents a static method.
|
||||||
|
*
|
||||||
|
* @since 1.8
|
||||||
|
*/
|
||||||
|
public AnnotatedType getAnnotatedReceiverType() {
|
||||||
|
return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes(),
|
||||||
|
sun.misc.SharedSecrets.getJavaLangAccess().
|
||||||
|
getConstantPool(getDeclaringClass()),
|
||||||
|
this,
|
||||||
|
getDeclaringClass(),
|
||||||
|
getDeclaringClass(),
|
||||||
|
TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of AnnotatedType objects that represent the use of
|
||||||
|
* types to specify formal parameter types of the method/constructor
|
||||||
|
* represented by this Executable. The order of the objects in the array
|
||||||
|
* corresponds to the order of the formal parameter types in the
|
||||||
|
* declaration of the method/constructor.
|
||||||
|
*
|
||||||
|
* Returns an array of length 0 if the method/constructor declares no
|
||||||
|
* parameters.
|
||||||
|
*
|
||||||
|
* @since 1.8
|
||||||
|
*/
|
||||||
|
public AnnotatedType[] getAnnotatedParameterTypes() {
|
||||||
|
throw new UnsupportedOperationException("Not yet");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of AnnotatedType objects that represent the use of
|
||||||
|
* types to specify the declared exceptions of the method/constructor
|
||||||
|
* represented by this Executable. The order of the objects in the array
|
||||||
|
* corresponds to the order of the exception types in the declaration of
|
||||||
|
* the method/constructor.
|
||||||
|
*
|
||||||
|
* Returns an array of length 0 if the method/constructor declares no
|
||||||
|
* exceptions.
|
||||||
|
*
|
||||||
|
* @since 1.8
|
||||||
|
*/
|
||||||
|
public AnnotatedType[] getAnnotatedExceptionTypes() {
|
||||||
|
return TypeAnnotationParser.buildAnnotatedTypes(getTypeAnnotationBytes(),
|
||||||
|
sun.misc.SharedSecrets.getJavaLangAccess().
|
||||||
|
getConstantPool(getDeclaringClass()),
|
||||||
|
this,
|
||||||
|
getDeclaringClass(),
|
||||||
|
getGenericExceptionTypes(),
|
||||||
|
TypeAnnotation.TypeAnnotationTarget.THROWS);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1996, 2013, 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
|
||||||
@ -36,7 +36,8 @@ import java.util.Map;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import sun.reflect.annotation.AnnotationParser;
|
import sun.reflect.annotation.AnnotationParser;
|
||||||
import sun.reflect.annotation.AnnotationSupport;
|
import sun.reflect.annotation.AnnotationSupport;
|
||||||
|
import sun.reflect.annotation.TypeAnnotation;
|
||||||
|
import sun.reflect.annotation.TypeAnnotationParser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@code Field} provides information about, and dynamic access to, a
|
* A {@code Field} provides information about, and dynamic access to, a
|
||||||
@ -1020,8 +1021,7 @@ class Field extends AccessibleObject implements Member {
|
|||||||
*/
|
*/
|
||||||
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
|
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
|
||||||
Objects.requireNonNull(annotationClass);
|
Objects.requireNonNull(annotationClass);
|
||||||
|
return annotationClass.cast(declaredAnnotations().get(annotationClass));
|
||||||
return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1039,7 +1039,7 @@ class Field extends AccessibleObject implements Member {
|
|||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public Annotation[] getDeclaredAnnotations() {
|
public Annotation[] getDeclaredAnnotations() {
|
||||||
return AnnotationSupport.unpackToArray(declaredAnnotations());
|
return AnnotationParser.toArray(declaredAnnotations());
|
||||||
}
|
}
|
||||||
|
|
||||||
private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
|
private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
|
||||||
@ -1053,4 +1053,20 @@ class Field extends AccessibleObject implements Member {
|
|||||||
}
|
}
|
||||||
return declaredAnnotations;
|
return declaredAnnotations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an AnnotatedType object that represents the use of a type to specify
|
||||||
|
* the declared type of the field represented by this Field.
|
||||||
|
*
|
||||||
|
* @since 1.8
|
||||||
|
*/
|
||||||
|
public AnnotatedType getAnnotatedType() {
|
||||||
|
return TypeAnnotationParser.buildAnnotatedType(typeAnnotations,
|
||||||
|
sun.misc.SharedSecrets.getJavaLangAccess().
|
||||||
|
getConstantPool(getDeclaringClass()),
|
||||||
|
this,
|
||||||
|
getDeclaringClass(),
|
||||||
|
getGenericType(),
|
||||||
|
TypeAnnotation.TypeAnnotationTarget.FIELD_TYPE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,6 +165,10 @@ public final class Method extends Executable {
|
|||||||
byte[] getAnnotationBytes() {
|
byte[] getAnnotationBytes() {
|
||||||
return annotations;
|
return annotations;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
byte[] getTypeAnnotationBytes() {
|
||||||
|
return typeAnnotations;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
@ -621,6 +625,14 @@ public final class Method extends Executable {
|
|||||||
return sharedGetParameterAnnotations(parameterTypes, parameterAnnotations);
|
return sharedGetParameterAnnotations(parameterTypes, parameterAnnotations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* @since 1.8
|
||||||
|
*/
|
||||||
|
public AnnotatedType getAnnotatedReturnType() {
|
||||||
|
return getAnnotatedReturnType0(getGenericReturnType());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void handleParameterNumberMismatch(int resultLength, int numParameters) {
|
void handleParameterNumberMismatch(int resultLength, int numParameters) {
|
||||||
throw new AnnotationFormatError("Parameter annotations don't match number of parameters");
|
throw new AnnotationFormatError("Parameter annotations don't match number of parameters");
|
||||||
|
@ -233,8 +233,7 @@ public final class Parameter implements AnnotatedElement {
|
|||||||
*/
|
*/
|
||||||
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
|
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
|
||||||
Objects.requireNonNull(annotationClass);
|
Objects.requireNonNull(annotationClass);
|
||||||
|
return annotationClass.cast(declaredAnnotations().get(annotationClass));
|
||||||
return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -281,14 +280,6 @@ public final class Parameter implements AnnotatedElement {
|
|||||||
return getDeclaredAnnotations();
|
return getDeclaredAnnotations();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws NullPointerException {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public boolean isAnnotationPresent(
|
|
||||||
Class<? extends Annotation> annotationClass) {
|
|
||||||
return getAnnotation(annotationClass) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
|
private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
|
||||||
|
|
||||||
private synchronized Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
|
private synchronized Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2013, 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
|
||||||
@ -128,6 +128,10 @@ class ReflectAccess implements sun.reflect.LangReflectAccess {
|
|||||||
return c.getRawParameterAnnotations();
|
return c.getRawParameterAnnotations();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte[] getExecutableTypeAnnotationBytes(Executable ex) {
|
||||||
|
return ex.getTypeAnnotationBytes();
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Copying routines, needed to quickly fabricate new Field,
|
// Copying routines, needed to quickly fabricate new Field,
|
||||||
// Method, and Constructor objects from templates
|
// Method, and Constructor objects from templates
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2013, 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
|
||||||
@ -86,4 +86,16 @@ public interface TypeVariable<D extends GenericDeclaration> extends Type, Annota
|
|||||||
* @return the name of this type variable, as it appears in the source code
|
* @return the name of this type variable, as it appears in the source code
|
||||||
*/
|
*/
|
||||||
String getName();
|
String getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of AnnotatedType objects that represent the use of
|
||||||
|
* types to denote the upper bounds of the type parameter represented by
|
||||||
|
* this TypeVariable. The order of the objects in the array corresponds to
|
||||||
|
* the order of the bounds in the declaration of the type parameter.
|
||||||
|
*
|
||||||
|
* Returns an array of length 0 if the type parameter declares no bounds.
|
||||||
|
*
|
||||||
|
* @since 1.8
|
||||||
|
*/
|
||||||
|
AnnotatedType[] getAnnotatedBounds();
|
||||||
}
|
}
|
||||||
|
@ -3537,13 +3537,25 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
|||||||
else
|
else
|
||||||
return expandBigIntegerTenPowers(n);
|
return expandBigIntegerTenPowers(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (n < 1024*524288) {
|
||||||
// BigInteger.pow is slow, so make 10**n by constructing a
|
// BigInteger.pow is slow, so make 10**n by constructing a
|
||||||
// BigInteger from a character string (still not very fast)
|
// BigInteger from a character string (still not very fast)
|
||||||
|
// which occupies no more than 1GB (!) of memory.
|
||||||
char tenpow[] = new char[n + 1];
|
char tenpow[] = new char[n + 1];
|
||||||
tenpow[0] = '1';
|
tenpow[0] = '1';
|
||||||
for (int i = 1; i <= n; i++)
|
for (int i = 1; i <= n; i++) {
|
||||||
tenpow[i] = '0';
|
tenpow[i] = '0';
|
||||||
return new BigInteger(tenpow,1, tenpow.length);
|
}
|
||||||
|
return new BigInteger(tenpow, 1, tenpow.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((n & 0x1) == 0x1) {
|
||||||
|
return BigInteger.TEN.multiply(bigTenToThe(n - 1));
|
||||||
|
} else {
|
||||||
|
BigInteger tmp = bigTenToThe(n/2);
|
||||||
|
return tmp.multiply(tmp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -64,7 +64,8 @@ import java.nio.charset.StandardCharsets;
|
|||||||
* RFC 2045 for encoding and decoding operation. The encoded output
|
* RFC 2045 for encoding and decoding operation. The encoded output
|
||||||
* must be represented in lines of no more than 76 characters each
|
* must be represented in lines of no more than 76 characters each
|
||||||
* and uses a carriage return {@code '\r'} followed immediately by
|
* and uses a carriage return {@code '\r'} followed immediately by
|
||||||
* a linefeed {@code '\n'} as the line separator. All line separators
|
* a linefeed {@code '\n'} as the line separator. No line separator
|
||||||
|
* is added to the end of the encoded output. All line separators
|
||||||
* or other characters not found in the base64 alphabet table are
|
* or other characters not found in the base64 alphabet table are
|
||||||
* ignored in decoding operation.</p></li>
|
* ignored in decoding operation.</p></li>
|
||||||
* </ul>
|
* </ul>
|
||||||
@ -413,6 +414,7 @@ public class Base64 {
|
|||||||
* specified Base64 encoded format
|
* specified Base64 encoded format
|
||||||
*/
|
*/
|
||||||
public OutputStream wrap(OutputStream os) {
|
public OutputStream wrap(OutputStream os) {
|
||||||
|
Objects.requireNonNull(os);
|
||||||
return new EncOutputStream(os, isURL ? toBase64URL : toBase64,
|
return new EncOutputStream(os, isURL ? toBase64URL : toBase64,
|
||||||
newline, linemax);
|
newline, linemax);
|
||||||
}
|
}
|
||||||
@ -613,6 +615,13 @@ public class Base64 {
|
|||||||
* This class implements a decoder for decoding byte data using the
|
* This class implements a decoder for decoding byte data using the
|
||||||
* Base64 encoding scheme as specified in RFC 4648 and RFC 2045.
|
* Base64 encoding scheme as specified in RFC 4648 and RFC 2045.
|
||||||
*
|
*
|
||||||
|
* <p> The Base64 padding character {@code '='} is accepted and
|
||||||
|
* interpreted as the end of the encoded byte data, but is not
|
||||||
|
* required. So if the final unit of the encoded byte data only has
|
||||||
|
* two or three Base64 characters (without the corresponding padding
|
||||||
|
* character(s) padded), they are decoded as if followed by padding
|
||||||
|
* character(s).
|
||||||
|
*
|
||||||
* <p> Instances of {@link Decoder} class are safe for use by
|
* <p> Instances of {@link Decoder} class are safe for use by
|
||||||
* multiple concurrent threads.
|
* multiple concurrent threads.
|
||||||
*
|
*
|
||||||
@ -695,7 +704,7 @@ public class Base64 {
|
|||||||
* using the {@link Base64} encoding scheme.
|
* using the {@link Base64} encoding scheme.
|
||||||
*
|
*
|
||||||
* <p> An invocation of this method has exactly the same effect as invoking
|
* <p> An invocation of this method has exactly the same effect as invoking
|
||||||
* {@code return decode(src.getBytes(StandardCharsets.ISO_8859_1))}
|
* {@code decode(src.getBytes(StandardCharsets.ISO_8859_1))}
|
||||||
*
|
*
|
||||||
* @param src
|
* @param src
|
||||||
* the string to decode
|
* the string to decode
|
||||||
@ -856,6 +865,9 @@ public class Base64 {
|
|||||||
/**
|
/**
|
||||||
* Returns an input stream for decoding {@link Base64} encoded byte stream.
|
* Returns an input stream for decoding {@link Base64} encoded byte stream.
|
||||||
*
|
*
|
||||||
|
* <p> The {@code read} methods of the returned {@code InputStream} will
|
||||||
|
* throw {@code IOException} when reading bytes that cannot be decoded.
|
||||||
|
*
|
||||||
* <p> Closing the returned input stream will close the underlying
|
* <p> Closing the returned input stream will close the underlying
|
||||||
* input stream.
|
* input stream.
|
||||||
*
|
*
|
||||||
@ -866,6 +878,7 @@ public class Base64 {
|
|||||||
* byte stream
|
* byte stream
|
||||||
*/
|
*/
|
||||||
public InputStream wrap(InputStream is) {
|
public InputStream wrap(InputStream is) {
|
||||||
|
Objects.requireNonNull(is);
|
||||||
return new DecInputStream(is, isURL ? fromBase64URL : fromBase64, isMIME);
|
return new DecInputStream(is, isURL ? fromBase64URL : fromBase64, isMIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -881,13 +894,16 @@ public class Base64 {
|
|||||||
int dl = dst.arrayOffset() + dst.limit();
|
int dl = dst.arrayOffset() + dst.limit();
|
||||||
int dp0 = dp;
|
int dp0 = dp;
|
||||||
int mark = sp;
|
int mark = sp;
|
||||||
boolean padding = false;
|
|
||||||
try {
|
try {
|
||||||
while (sp < sl) {
|
while (sp < sl) {
|
||||||
int b = sa[sp++] & 0xff;
|
int b = sa[sp++] & 0xff;
|
||||||
if ((b = base64[b]) < 0) {
|
if ((b = base64[b]) < 0) {
|
||||||
if (b == -2) { // padding byte
|
if (b == -2) { // padding byte
|
||||||
padding = true;
|
if (shiftto == 6 && (sp == sl || sa[sp++] != '=') ||
|
||||||
|
shiftto == 18) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Input byte array has wrong 4-byte ending unit");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (isMIME) // skip if for rfc2045
|
if (isMIME) // skip if for rfc2045
|
||||||
@ -913,24 +929,23 @@ public class Base64 {
|
|||||||
if (shiftto == 6) {
|
if (shiftto == 6) {
|
||||||
if (dl - dp < 1)
|
if (dl - dp < 1)
|
||||||
return dp - dp0;
|
return dp - dp0;
|
||||||
if (padding && (sp + 1 != sl || sa[sp++] != '='))
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Input buffer has wrong 4-byte ending unit");
|
|
||||||
da[dp++] = (byte)(bits >> 16);
|
da[dp++] = (byte)(bits >> 16);
|
||||||
mark = sp;
|
|
||||||
} else if (shiftto == 0) {
|
} else if (shiftto == 0) {
|
||||||
if (dl - dp < 2)
|
if (dl - dp < 2)
|
||||||
return dp - dp0;
|
return dp - dp0;
|
||||||
if (padding && sp != sl)
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Input buffer has wrong 4-byte ending unit");
|
|
||||||
da[dp++] = (byte)(bits >> 16);
|
da[dp++] = (byte)(bits >> 16);
|
||||||
da[dp++] = (byte)(bits >> 8);
|
da[dp++] = (byte)(bits >> 8);
|
||||||
mark = sp;
|
} else if (shiftto == 12) {
|
||||||
} else if (padding || shiftto != 18) {
|
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Last unit does not have enough valid bits");
|
"Last unit does not have enough valid bits");
|
||||||
}
|
}
|
||||||
|
while (sp < sl) {
|
||||||
|
if (isMIME && base64[sa[sp++]] < 0)
|
||||||
|
continue;
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Input byte array has incorrect ending byte at " + sp);
|
||||||
|
}
|
||||||
|
mark = sp;
|
||||||
return dp - dp0;
|
return dp - dp0;
|
||||||
} finally {
|
} finally {
|
||||||
src.position(mark);
|
src.position(mark);
|
||||||
@ -948,14 +963,16 @@ public class Base64 {
|
|||||||
int dl = dst.limit();
|
int dl = dst.limit();
|
||||||
int dp0 = dp;
|
int dp0 = dp;
|
||||||
int mark = sp;
|
int mark = sp;
|
||||||
boolean padding = false;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
while (sp < sl) {
|
while (sp < sl) {
|
||||||
int b = src.get(sp++) & 0xff;
|
int b = src.get(sp++) & 0xff;
|
||||||
if ((b = base64[b]) < 0) {
|
if ((b = base64[b]) < 0) {
|
||||||
if (b == -2) { // padding byte
|
if (b == -2) { // padding byte
|
||||||
padding = true;
|
if (shiftto == 6 && (sp == sl || src.get(sp++) != '=') ||
|
||||||
|
shiftto == 18) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Input byte array has wrong 4-byte ending unit");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (isMIME) // skip if for rfc2045
|
if (isMIME) // skip if for rfc2045
|
||||||
@ -981,24 +998,23 @@ public class Base64 {
|
|||||||
if (shiftto == 6) {
|
if (shiftto == 6) {
|
||||||
if (dl - dp < 1)
|
if (dl - dp < 1)
|
||||||
return dp - dp0;
|
return dp - dp0;
|
||||||
if (padding && (sp + 1 != sl || src.get(sp++) != '='))
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Input buffer has wrong 4-byte ending unit");
|
|
||||||
dst.put(dp++, (byte)(bits >> 16));
|
dst.put(dp++, (byte)(bits >> 16));
|
||||||
mark = sp;
|
|
||||||
} else if (shiftto == 0) {
|
} else if (shiftto == 0) {
|
||||||
if (dl - dp < 2)
|
if (dl - dp < 2)
|
||||||
return dp - dp0;
|
return dp - dp0;
|
||||||
if (padding && sp != sl)
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Input buffer has wrong 4-byte ending unit");
|
|
||||||
dst.put(dp++, (byte)(bits >> 16));
|
dst.put(dp++, (byte)(bits >> 16));
|
||||||
dst.put(dp++, (byte)(bits >> 8));
|
dst.put(dp++, (byte)(bits >> 8));
|
||||||
mark = sp;
|
} else if (shiftto == 12) {
|
||||||
} else if (padding || shiftto != 18) {
|
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Last unit does not have enough valid bits");
|
"Last unit does not have enough valid bits");
|
||||||
}
|
}
|
||||||
|
while (sp < sl) {
|
||||||
|
if (isMIME && base64[src.get(sp++)] < 0)
|
||||||
|
continue;
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Input byte array has incorrect ending byte at " + sp);
|
||||||
|
}
|
||||||
|
mark = sp;
|
||||||
return dp - dp0;
|
return dp - dp0;
|
||||||
} finally {
|
} finally {
|
||||||
src.position(mark);
|
src.position(mark);
|
||||||
@ -1012,9 +1028,12 @@ public class Base64 {
|
|||||||
int len = sl - sp;
|
int len = sl - sp;
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return 0;
|
return 0;
|
||||||
if (len < 2)
|
if (len < 2) {
|
||||||
|
if (isMIME && base64[0] == -1)
|
||||||
|
return 0;
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Input byte[] should at least have 2 bytes for base64 bytes");
|
"Input byte[] should at least have 2 bytes for base64 bytes");
|
||||||
|
}
|
||||||
if (src[sl - 1] == '=') {
|
if (src[sl - 1] == '=') {
|
||||||
paddings++;
|
paddings++;
|
||||||
if (src[sl - 2] == '=')
|
if (src[sl - 2] == '=')
|
||||||
@ -1043,12 +1062,20 @@ public class Base64 {
|
|||||||
int dp = 0;
|
int dp = 0;
|
||||||
int bits = 0;
|
int bits = 0;
|
||||||
int shiftto = 18; // pos of first byte of 4-byte atom
|
int shiftto = 18; // pos of first byte of 4-byte atom
|
||||||
boolean padding = false;
|
|
||||||
while (sp < sl) {
|
while (sp < sl) {
|
||||||
int b = src[sp++] & 0xff;
|
int b = src[sp++] & 0xff;
|
||||||
if ((b = base64[b]) < 0) {
|
if ((b = base64[b]) < 0) {
|
||||||
if (b == -2) { // padding byte
|
if (b == -2) { // padding byte '='
|
||||||
padding = true;
|
// xx= shiftto==6&&sp==sl missing last =
|
||||||
|
// xx=y shiftto==6 last is not =
|
||||||
|
// = shiftto==18 unnecessary padding
|
||||||
|
// x= shiftto==12 be taken care later
|
||||||
|
// together with single x, invalid anyway
|
||||||
|
if (shiftto == 6 && (sp == sl || src[sp++] != '=') ||
|
||||||
|
shiftto == 18) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Input byte array has wrong 4-byte ending unit");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (isMIME) // skip if for rfc2045
|
if (isMIME) // skip if for rfc2045
|
||||||
@ -1068,22 +1095,23 @@ public class Base64 {
|
|||||||
bits = 0;
|
bits = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// reach end of byte arry or hit padding '=' characters.
|
// reached end of byte array or hit padding '=' characters.
|
||||||
// if '=' presents, they must be the last one or two.
|
if (shiftto == 6) {
|
||||||
if (shiftto == 6) { // xx==
|
|
||||||
if (padding && (sp + 1 != sl || src[sp] != '='))
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Input byte array has wrong 4-byte ending unit");
|
|
||||||
dst[dp++] = (byte)(bits >> 16);
|
dst[dp++] = (byte)(bits >> 16);
|
||||||
} else if (shiftto == 0) { // xxx=
|
} else if (shiftto == 0) {
|
||||||
if (padding && sp != sl)
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Input byte array has wrong 4-byte ending unit");
|
|
||||||
dst[dp++] = (byte)(bits >> 16);
|
dst[dp++] = (byte)(bits >> 16);
|
||||||
dst[dp++] = (byte)(bits >> 8);
|
dst[dp++] = (byte)(bits >> 8);
|
||||||
} else if (padding || shiftto != 18) {
|
} else if (shiftto == 12) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"last unit does not have enough bytes");
|
"Last unit does not have enough valid bits");
|
||||||
|
}
|
||||||
|
// anything left is invalid, if is not MIME.
|
||||||
|
// if MIME, ignore all non-base64 character
|
||||||
|
while (sp < sl) {
|
||||||
|
if (isMIME && base64[src[sp++]] < 0)
|
||||||
|
continue;
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Input byte array has incorrect ending byte at " + sp);
|
||||||
}
|
}
|
||||||
return dp;
|
return dp;
|
||||||
}
|
}
|
||||||
@ -1247,8 +1275,22 @@ public class Base64 {
|
|||||||
int v = is.read();
|
int v = is.read();
|
||||||
if (v == -1) {
|
if (v == -1) {
|
||||||
eof = true;
|
eof = true;
|
||||||
if (nextin != 18)
|
if (nextin != 18) {
|
||||||
throw new IOException("Base64 stream has un-decoded dangling byte(s).");
|
if (nextin == 12)
|
||||||
|
throw new IOException("Base64 stream has one un-decoded dangling byte.");
|
||||||
|
// treat ending xx/xxx without padding character legal.
|
||||||
|
// same logic as v == 'v' below
|
||||||
|
b[off++] = (byte)(bits >> (16));
|
||||||
|
len--;
|
||||||
|
if (nextin == 0) { // only one padding byte
|
||||||
|
if (len == 0) { // no enough output space
|
||||||
|
bits >>= 8; // shift to lowest byte
|
||||||
|
nextout = 0;
|
||||||
|
} else {
|
||||||
|
b[off++] = (byte) (bits >> 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (off == oldOff)
|
if (off == oldOff)
|
||||||
return -1;
|
return -1;
|
||||||
else
|
else
|
||||||
|
@ -351,7 +351,9 @@ import sun.misc.FormattedFloatingDecimal;
|
|||||||
* <tr><td valign="top">{@code 'a'}, {@code 'A'}
|
* <tr><td valign="top">{@code 'a'}, {@code 'A'}
|
||||||
* <td valign="top"> floating point
|
* <td valign="top"> floating point
|
||||||
* <td> The result is formatted as a hexadecimal floating-point number with
|
* <td> The result is formatted as a hexadecimal floating-point number with
|
||||||
* a significand and an exponent
|
* a significand and an exponent. This conversion is <b>not</b> supported
|
||||||
|
* for the {@code BigDecimal} type despite the latter's being in the
|
||||||
|
* <i>floating point</i> argument category.
|
||||||
*
|
*
|
||||||
* <tr><td valign="top">{@code 't'}, {@code 'T'}
|
* <tr><td valign="top">{@code 't'}, {@code 'T'}
|
||||||
* <td valign="top"> date/time
|
* <td valign="top"> date/time
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
* or visit www.oracle.com if you need additional information or have any
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package sun.management;
|
package sun.management;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
@ -31,34 +30,36 @@ import java.io.FileInputStream;
|
|||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.management.ManagementFactory;
|
import java.net.InetAddress;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
|
|
||||||
import java.util.MissingResourceException;
|
import java.util.MissingResourceException;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
import javax.management.remote.JMXConnectorServer;
|
import javax.management.remote.JMXConnectorServer;
|
||||||
|
import javax.management.remote.JMXServiceURL;
|
||||||
|
|
||||||
import static sun.management.AgentConfigurationError.*;
|
import static sun.management.AgentConfigurationError.*;
|
||||||
import sun.management.jmxremote.ConnectorBootstrap;
|
import sun.management.jmxremote.ConnectorBootstrap;
|
||||||
|
import sun.management.jdp.JdpController;
|
||||||
|
import sun.management.jdp.JdpException;
|
||||||
import sun.misc.VMSupport;
|
import sun.misc.VMSupport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This Agent is started by the VM when -Dcom.sun.management.snmp
|
* This Agent is started by the VM when -Dcom.sun.management.snmp or
|
||||||
* or -Dcom.sun.management.jmxremote is set. This class will be
|
* -Dcom.sun.management.jmxremote is set. This class will be loaded by the
|
||||||
* loaded by the system class loader. Also jmx framework could
|
* system class loader. Also jmx framework could be started by jcmd
|
||||||
* be started by jcmd
|
|
||||||
*/
|
*/
|
||||||
public class Agent {
|
public class Agent {
|
||||||
// management properties
|
// management properties
|
||||||
|
|
||||||
private static Properties mgmtProps;
|
private static Properties mgmtProps;
|
||||||
private static ResourceBundle messageRB;
|
private static ResourceBundle messageRB;
|
||||||
|
|
||||||
private static final String CONFIG_FILE =
|
private static final String CONFIG_FILE =
|
||||||
"com.sun.management.config.file";
|
"com.sun.management.config.file";
|
||||||
private static final String SNMP_PORT =
|
private static final String SNMP_PORT =
|
||||||
@ -67,21 +68,25 @@ public class Agent {
|
|||||||
"com.sun.management.jmxremote";
|
"com.sun.management.jmxremote";
|
||||||
private static final String JMXREMOTE_PORT =
|
private static final String JMXREMOTE_PORT =
|
||||||
"com.sun.management.jmxremote.port";
|
"com.sun.management.jmxremote.port";
|
||||||
|
private static final String RMI_PORT =
|
||||||
|
"com.sun.management.jmxremote.rmi.port";
|
||||||
private static final String ENABLE_THREAD_CONTENTION_MONITORING =
|
private static final String ENABLE_THREAD_CONTENTION_MONITORING =
|
||||||
"com.sun.management.enableThreadContentionMonitoring";
|
"com.sun.management.enableThreadContentionMonitoring";
|
||||||
private static final String LOCAL_CONNECTOR_ADDRESS_PROP =
|
private static final String LOCAL_CONNECTOR_ADDRESS_PROP =
|
||||||
"com.sun.management.jmxremote.localConnectorAddress";
|
"com.sun.management.jmxremote.localConnectorAddress";
|
||||||
|
|
||||||
private static final String SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME =
|
private static final String SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME =
|
||||||
"sun.management.snmp.AdaptorBootstrap";
|
"sun.management.snmp.AdaptorBootstrap";
|
||||||
|
|
||||||
|
private static final String JDP_DEFAULT_ADDRESS = "239.255.255.225";
|
||||||
|
private static final int JDP_DEFAULT_PORT = 7095;
|
||||||
|
|
||||||
// The only active agent allowed
|
// The only active agent allowed
|
||||||
private static JMXConnectorServer jmxServer = null;
|
private static JMXConnectorServer jmxServer = null;
|
||||||
|
|
||||||
// Parse string com.sun.management.prop=xxx,com.sun.management.prop=yyyy
|
// Parse string com.sun.management.prop=xxx,com.sun.management.prop=yyyy
|
||||||
// and return property set if args is null or empty
|
// and return property set if args is null or empty
|
||||||
// return empty property set
|
// return empty property set
|
||||||
private static Properties parseString(String args){
|
private static Properties parseString(String args) {
|
||||||
Properties argProps = new Properties();
|
Properties argProps = new Properties();
|
||||||
if (args != null) {
|
if (args != null) {
|
||||||
for (String option : args.split(",")) {
|
for (String option : args.split(",")) {
|
||||||
@ -100,7 +105,6 @@ public class Agent {
|
|||||||
return argProps;
|
return argProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// invoked by -javaagent or -Dcom.sun.management.agent.class
|
// invoked by -javaagent or -Dcom.sun.management.agent.class
|
||||||
public static void premain(String args) throws Exception {
|
public static void premain(String args) throws Exception {
|
||||||
agentmain(args);
|
agentmain(args);
|
||||||
@ -126,7 +130,7 @@ public class Agent {
|
|||||||
|
|
||||||
// jcmd ManagementAgent.start_local entry point
|
// jcmd ManagementAgent.start_local entry point
|
||||||
// Also called due to command-line via startAgent()
|
// Also called due to command-line via startAgent()
|
||||||
private static synchronized void startLocalManagementAgent(){
|
private static synchronized void startLocalManagementAgent() {
|
||||||
Properties agentProps = VMSupport.getAgentProperties();
|
Properties agentProps = VMSupport.getAgentProperties();
|
||||||
|
|
||||||
// start local connector if not started
|
// start local connector if not started
|
||||||
@ -169,7 +173,7 @@ public class Agent {
|
|||||||
// management properties can be overridden by system properties
|
// management properties can be overridden by system properties
|
||||||
// which take precedence
|
// which take precedence
|
||||||
Properties sysProps = System.getProperties();
|
Properties sysProps = System.getProperties();
|
||||||
synchronized(sysProps){
|
synchronized (sysProps) {
|
||||||
configProps.putAll(sysProps);
|
configProps.putAll(sysProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,10 +205,15 @@ public class Agent {
|
|||||||
if (jmxremotePort != null) {
|
if (jmxremotePort != null) {
|
||||||
jmxServer = ConnectorBootstrap.
|
jmxServer = ConnectorBootstrap.
|
||||||
startRemoteConnectorServer(jmxremotePort, configProps);
|
startRemoteConnectorServer(jmxremotePort, configProps);
|
||||||
|
|
||||||
|
startDiscoveryService(configProps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static synchronized void stopRemoteManagementAgent() throws Exception {
|
private static synchronized void stopRemoteManagementAgent() throws Exception {
|
||||||
|
|
||||||
|
JdpController.stopDiscoveryService();
|
||||||
|
|
||||||
if (jmxServer != null) {
|
if (jmxServer != null) {
|
||||||
ConnectorBootstrap.unexportRegistry();
|
ConnectorBootstrap.unexportRegistry();
|
||||||
|
|
||||||
@ -246,6 +255,7 @@ public class Agent {
|
|||||||
if (jmxremotePort != null) {
|
if (jmxremotePort != null) {
|
||||||
jmxServer = ConnectorBootstrap.
|
jmxServer = ConnectorBootstrap.
|
||||||
startRemoteConnectorServer(jmxremotePort, props);
|
startRemoteConnectorServer(jmxremotePort, props);
|
||||||
|
startDiscoveryService(props);
|
||||||
}
|
}
|
||||||
startLocalManagementAgent();
|
startLocalManagementAgent();
|
||||||
}
|
}
|
||||||
@ -257,6 +267,73 @@ public class Agent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void startDiscoveryService(Properties props)
|
||||||
|
throws IOException {
|
||||||
|
// Start discovery service if requested
|
||||||
|
String discoveryPort = props.getProperty("com.sun.management.jdp.port");
|
||||||
|
String discoveryAddress = props.getProperty("com.sun.management.jdp.address");
|
||||||
|
String discoveryShouldStart = props.getProperty("com.sun.management.jmxremote.autodiscovery");
|
||||||
|
|
||||||
|
// Decide whether we should start autodicovery service.
|
||||||
|
// To start autodiscovery following conditions should be met:
|
||||||
|
// autodiscovery==true OR (autodicovery==null AND jdp.port != NULL)
|
||||||
|
|
||||||
|
boolean shouldStart = false;
|
||||||
|
if (discoveryShouldStart == null){
|
||||||
|
shouldStart = (discoveryPort != null);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
try{
|
||||||
|
shouldStart = Boolean.parseBoolean(discoveryShouldStart);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new AgentConfigurationError("Couldn't parse autodiscovery argument");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldStart) {
|
||||||
|
// port and address are required arguments and have no default values
|
||||||
|
InetAddress address;
|
||||||
|
try {
|
||||||
|
address = (discoveryAddress == null) ?
|
||||||
|
InetAddress.getByName(JDP_DEFAULT_ADDRESS) : InetAddress.getByName(discoveryAddress);
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
throw new AgentConfigurationError("Unable to broadcast to requested address", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
int port = JDP_DEFAULT_PORT;
|
||||||
|
if (discoveryPort != null) {
|
||||||
|
try {
|
||||||
|
port = Integer.parseInt(discoveryPort);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new AgentConfigurationError("Couldn't parse JDP port argument");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rebuilding service URL to broadcast it
|
||||||
|
String jmxremotePort = props.getProperty(JMXREMOTE_PORT);
|
||||||
|
String rmiPort = props.getProperty(RMI_PORT);
|
||||||
|
|
||||||
|
JMXServiceURL url = jmxServer.getAddress();
|
||||||
|
String hostname = url.getHost();
|
||||||
|
|
||||||
|
String jmxUrlStr = (rmiPort != null)
|
||||||
|
? String.format(
|
||||||
|
"service:jmx:rmi://%s:%s/jndi/rmi://%s:%s/jmxrmi",
|
||||||
|
hostname, rmiPort, hostname, jmxremotePort)
|
||||||
|
: String.format(
|
||||||
|
"service:jmx:rmi:///jndi/rmi://%s:%s/jmxrmi", hostname, jmxremotePort);
|
||||||
|
|
||||||
|
String instanceName = System.getProperty("com.sun.management.jdp.name");
|
||||||
|
|
||||||
|
try{
|
||||||
|
JdpController.startDiscoveryService(address, port, instanceName, jmxUrlStr);
|
||||||
|
}
|
||||||
|
catch(JdpException e){
|
||||||
|
throw new AgentConfigurationError("Couldn't start JDP service", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static Properties loadManagementProperties() {
|
public static Properties loadManagementProperties() {
|
||||||
Properties props = new Properties();
|
Properties props = new Properties();
|
||||||
|
|
||||||
@ -268,7 +345,7 @@ public class Agent {
|
|||||||
// management properties can be overridden by system properties
|
// management properties can be overridden by system properties
|
||||||
// which take precedence
|
// which take precedence
|
||||||
Properties sysProps = System.getProperties();
|
Properties sysProps = System.getProperties();
|
||||||
synchronized(sysProps){
|
synchronized (sysProps) {
|
||||||
props.putAll(sysProps);
|
props.putAll(sysProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,8 +359,8 @@ public class Agent {
|
|||||||
String jmxremote = System.getProperty(JMXREMOTE);
|
String jmxremote = System.getProperty(JMXREMOTE);
|
||||||
String jmxremotePort = System.getProperty(JMXREMOTE_PORT);
|
String jmxremotePort = System.getProperty(JMXREMOTE_PORT);
|
||||||
|
|
||||||
if (configFile == null && snmpPort == null &&
|
if (configFile == null && snmpPort == null
|
||||||
jmxremote == null && jmxremotePort == null) {
|
&& jmxremote == null && jmxremotePort == null) {
|
||||||
// return if out-of-the-management option is not specified
|
// return if out-of-the-management option is not specified
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -297,22 +374,23 @@ public class Agent {
|
|||||||
// invoke the following through reflection:
|
// invoke the following through reflection:
|
||||||
// AdaptorBootstrap.initialize(snmpPort, props);
|
// AdaptorBootstrap.initialize(snmpPort, props);
|
||||||
final Class<?> adaptorClass =
|
final Class<?> adaptorClass =
|
||||||
Class.forName(SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME,true,null);
|
Class.forName(SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME, true, null);
|
||||||
final Method initializeMethod =
|
final Method initializeMethod =
|
||||||
adaptorClass.getMethod("initialize",
|
adaptorClass.getMethod("initialize",
|
||||||
String.class, Properties.class);
|
String.class, Properties.class);
|
||||||
initializeMethod.invoke(null,snmpPort,props);
|
initializeMethod.invoke(null, snmpPort, props);
|
||||||
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException x) {
|
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException x) {
|
||||||
// snmp runtime doesn't exist - initialization fails
|
// snmp runtime doesn't exist - initialization fails
|
||||||
throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT,x);
|
throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT, x);
|
||||||
} catch (InvocationTargetException x) {
|
} catch (InvocationTargetException x) {
|
||||||
final Throwable cause = x.getCause();
|
final Throwable cause = x.getCause();
|
||||||
if (cause instanceof RuntimeException)
|
if (cause instanceof RuntimeException) {
|
||||||
throw (RuntimeException) cause;
|
throw (RuntimeException) cause;
|
||||||
else if (cause instanceof Error)
|
} else if (cause instanceof Error) {
|
||||||
throw (Error) cause;
|
throw (Error) cause;
|
||||||
|
}
|
||||||
// should not happen...
|
// should not happen...
|
||||||
throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT,cause);
|
throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT, cause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,9 +467,9 @@ public class Agent {
|
|||||||
// invoke the premain(String args) method
|
// invoke the premain(String args) method
|
||||||
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(cname);
|
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(cname);
|
||||||
Method premain = clz.getMethod("premain",
|
Method premain = clz.getMethod("premain",
|
||||||
new Class<?>[] { String.class });
|
new Class<?>[]{String.class});
|
||||||
premain.invoke(null, /* static */
|
premain.invoke(null, /* static */
|
||||||
new Object[] { args });
|
new Object[]{args});
|
||||||
} catch (ClassNotFoundException ex) {
|
} catch (ClassNotFoundException ex) {
|
||||||
error(AGENT_CLASS_NOT_FOUND, "\"" + cname + "\"");
|
error(AGENT_CLASS_NOT_FOUND, "\"" + cname + "\"");
|
||||||
} catch (NoSuchMethodException ex) {
|
} catch (NoSuchMethodException ex) {
|
||||||
@ -425,7 +503,6 @@ public class Agent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void error(String key, String message) {
|
public static void error(String key, String message) {
|
||||||
String keyText = getText(key);
|
String keyText = getText(key);
|
||||||
System.err.print(getText("agent.err.error") + ": " + keyText);
|
System.err.print(getText("agent.err.error") + ": " + keyText);
|
||||||
@ -470,10 +547,9 @@ public class Agent {
|
|||||||
}
|
}
|
||||||
String format = messageRB.getString(key);
|
String format = messageRB.getString(key);
|
||||||
if (format == null) {
|
if (format == null) {
|
||||||
format = "missing resource key: key = \"" + key + "\", " +
|
format = "missing resource key: key = \"" + key + "\", "
|
||||||
"arguments = \"{0}\", \"{1}\", \"{2}\"";
|
+ "arguments = \"{0}\", \"{1}\", \"{2}\"";
|
||||||
}
|
}
|
||||||
return MessageFormat.format(format, (Object[]) args);
|
return MessageFormat.format(format, (Object[]) args);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
124
jdk/src/share/classes/sun/management/jdp/JdpBroadcaster.java
Normal file
124
jdk/src/share/classes/sun/management/jdp/JdpBroadcaster.java
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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.
|
||||||
|
*/
|
||||||
|
package sun.management.jdp;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.Inet6Address;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.NetworkInterface;
|
||||||
|
import java.net.ProtocolFamily;
|
||||||
|
import java.net.StandardProtocolFamily;
|
||||||
|
import java.net.StandardSocketOptions;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.channels.DatagramChannel;
|
||||||
|
import java.nio.channels.UnsupportedAddressTypeException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JdpBroadcaster is responsible for sending pre-built JDP packet across a Net
|
||||||
|
*
|
||||||
|
* <p> Multicast group address, port number and ttl have to be chosen on upper
|
||||||
|
* level and passed to broadcaster constructor. Also it's possible to specify
|
||||||
|
* source address to broadcast from. </p>
|
||||||
|
*
|
||||||
|
* <p>JdpBradcaster doesn't perform any validation on a supplied {@code port} and {@code ttl} because
|
||||||
|
* the allowed values depend on an operating system setup</p>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public final class JdpBroadcaster {
|
||||||
|
|
||||||
|
private final InetAddress addr;
|
||||||
|
private final int port;
|
||||||
|
private final DatagramChannel channel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new broadcaster
|
||||||
|
*
|
||||||
|
* @param address - multicast group address
|
||||||
|
* @param srcAddress - address of interface we should use to broadcast.
|
||||||
|
* @param port - udp port to use
|
||||||
|
* @param ttl - packet ttl
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public JdpBroadcaster(InetAddress address, InetAddress srcAddress, int port, int ttl)
|
||||||
|
throws IOException, JdpException {
|
||||||
|
this.addr = address;
|
||||||
|
this.port = port;
|
||||||
|
|
||||||
|
ProtocolFamily family = (address instanceof Inet6Address)
|
||||||
|
? StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
|
||||||
|
|
||||||
|
channel = DatagramChannel.open(family);
|
||||||
|
channel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
|
||||||
|
channel.setOption(StandardSocketOptions.IP_MULTICAST_TTL, ttl);
|
||||||
|
|
||||||
|
// with srcAddress equal to null, this constructor do exactly the same as
|
||||||
|
// if srcAddress is not passed
|
||||||
|
if (srcAddress != null) {
|
||||||
|
// User requests particular interface to bind to
|
||||||
|
NetworkInterface interf = NetworkInterface.getByInetAddress(srcAddress);
|
||||||
|
try {
|
||||||
|
channel.bind(new InetSocketAddress(srcAddress, 0));
|
||||||
|
} catch (UnsupportedAddressTypeException ex) {
|
||||||
|
throw new JdpException("Unable to bind to source address");
|
||||||
|
}
|
||||||
|
channel.setOption(StandardSocketOptions.IP_MULTICAST_IF, interf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new broadcaster
|
||||||
|
*
|
||||||
|
* @param address - multicast group address
|
||||||
|
* @param port - udp port to use
|
||||||
|
* @param ttl - packet ttl
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public JdpBroadcaster(InetAddress address, int port, int ttl)
|
||||||
|
throws IOException, JdpException {
|
||||||
|
this(address, null, port, ttl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Broadcast pre-built packet
|
||||||
|
*
|
||||||
|
* @param packet - instance of JdpPacket
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public void sendPacket(JdpPacket packet)
|
||||||
|
throws IOException {
|
||||||
|
byte[] data = packet.getPacketData();
|
||||||
|
// Unlike allocate/put wrap don't need a flip afterward
|
||||||
|
ByteBuffer b = ByteBuffer.wrap(data);
|
||||||
|
channel.send(b, new InetSocketAddress(addr, port));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shutdown broadcaster and close underlying socket channel
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public void shutdown() throws IOException {
|
||||||
|
channel.close();
|
||||||
|
}
|
||||||
|
}
|
196
jdk/src/share/classes/sun/management/jdp/JdpController.java
Normal file
196
jdk/src/share/classes/sun/management/jdp/JdpController.java
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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.
|
||||||
|
*/
|
||||||
|
package sun.management.jdp;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JdpController is responsible to create and manage a broadcast loop
|
||||||
|
*
|
||||||
|
* <p> Other part of code has no access to broadcast loop and have to use
|
||||||
|
* provided static methods
|
||||||
|
* {@link #startDiscoveryService(InetAddress,int,String,String) startDiscoveryService}
|
||||||
|
* and {@link #stopDiscoveryService() stopDiscoveryService}</p>
|
||||||
|
* <p>{@link #startDiscoveryService(InetAddress,int,String,String) startDiscoveryService} could be called multiple
|
||||||
|
* times as it stops the running service if it is necessary. Call to {@link #stopDiscoveryService() stopDiscoveryService}
|
||||||
|
* ignored if service isn't run</p>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p> System properties below could be used to control broadcast loop behavior.
|
||||||
|
* Property below have to be set explicitly in command line. It's not possible to
|
||||||
|
* set it in management.config file. Careless changes of these properties could
|
||||||
|
* lead to security or network issues.
|
||||||
|
* <ul>
|
||||||
|
* <li>com.sun.management.jdp.ttl - set ttl for broadcast packet</li>
|
||||||
|
* <li>com.sun.management.jdp.pause - set broadcast interval in seconds</li>
|
||||||
|
* <li>com.sun.management.jdp.source_addr - an address of interface to use for broadcast</li>
|
||||||
|
* </ul>
|
||||||
|
</p>
|
||||||
|
* <p>null parameters values are filtered out on {@link JdpPacketWriter} level and
|
||||||
|
* corresponding keys are not placed to packet.</p>
|
||||||
|
*/
|
||||||
|
public final class JdpController {
|
||||||
|
|
||||||
|
private static class JDPControllerRunner implements Runnable {
|
||||||
|
|
||||||
|
private final JdpJmxPacket packet;
|
||||||
|
private final JdpBroadcaster bcast;
|
||||||
|
private final int pause;
|
||||||
|
private volatile boolean shutdown = false;
|
||||||
|
|
||||||
|
private JDPControllerRunner(JdpBroadcaster bcast, JdpJmxPacket packet, int pause) {
|
||||||
|
this.bcast = bcast;
|
||||||
|
this.packet = packet;
|
||||||
|
this.pause = pause;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
while (!shutdown) {
|
||||||
|
bcast.sendPacket(packet);
|
||||||
|
try {
|
||||||
|
Thread.sleep(this.pause);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
// pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
// It's not possible to re-use controller,
|
||||||
|
// nevertheless reset shutdown variable
|
||||||
|
try {
|
||||||
|
stop();
|
||||||
|
bcast.shutdown();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
// pass - ignore IOException during shutdown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
shutdown = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static JDPControllerRunner controller = null;
|
||||||
|
|
||||||
|
private JdpController(){
|
||||||
|
// Don't allow to instantiate this class.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Utility to handle optional system properties
|
||||||
|
// Parse an integer from string or return default if provided string is null
|
||||||
|
private static int getInteger(String val, int dflt, String msg) throws JdpException {
|
||||||
|
try {
|
||||||
|
return (val == null) ? dflt : Integer.parseInt(val);
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
throw new JdpException(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse an inet address from string or return default if provided string is null
|
||||||
|
private static InetAddress getInetAddress(String val, InetAddress dflt, String msg) throws JdpException {
|
||||||
|
try {
|
||||||
|
return (val == null) ? dflt : InetAddress.getByName(val);
|
||||||
|
} catch (UnknownHostException ex) {
|
||||||
|
throw new JdpException(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts discovery service
|
||||||
|
*
|
||||||
|
* @param address - multicast group address
|
||||||
|
* @param port - udp port to use
|
||||||
|
* @param instanceName - name of running JVM instance
|
||||||
|
* @param url - JMX service url
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static synchronized void startDiscoveryService(InetAddress address, int port, String instanceName, String url)
|
||||||
|
throws IOException, JdpException {
|
||||||
|
|
||||||
|
// Limit packet to local subnet by default
|
||||||
|
int ttl = getInteger(
|
||||||
|
System.getProperty("com.sun.management.jdp.ttl"), 1,
|
||||||
|
"Invalid jdp packet ttl");
|
||||||
|
|
||||||
|
// Broadcast once a 5 seconds by default
|
||||||
|
int pause = getInteger(
|
||||||
|
System.getProperty("com.sun.management.jdp.pause"), 5,
|
||||||
|
"Invalid jdp pause");
|
||||||
|
|
||||||
|
// Converting seconds to milliseconds
|
||||||
|
pause = pause * 1000;
|
||||||
|
|
||||||
|
// Allow OS to choose broadcast source
|
||||||
|
InetAddress sourceAddress = getInetAddress(
|
||||||
|
System.getProperty("com.sun.management.jdp.source_addr"), null,
|
||||||
|
"Invalid source address provided");
|
||||||
|
|
||||||
|
// Generate session id
|
||||||
|
UUID id = UUID.randomUUID();
|
||||||
|
|
||||||
|
JdpJmxPacket packet = new JdpJmxPacket(id, url);
|
||||||
|
|
||||||
|
// Don't broadcast whole command line for security reason.
|
||||||
|
// Strip everything after first space
|
||||||
|
String javaCommand = System.getProperty("sun.java.command");
|
||||||
|
if (javaCommand != null) {
|
||||||
|
String[] arr = javaCommand.split(" ", 2);
|
||||||
|
packet.setMainClass(arr[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put optional explicit java instance name to packet, if user doesn't specify
|
||||||
|
// it the key is skipped. PacketWriter is responsible to skip keys having null value.
|
||||||
|
packet.setInstanceName(instanceName);
|
||||||
|
|
||||||
|
JdpBroadcaster bcast = new JdpBroadcaster(address, sourceAddress, port, ttl);
|
||||||
|
|
||||||
|
// Stop discovery service if it's already running
|
||||||
|
stopDiscoveryService();
|
||||||
|
|
||||||
|
controller = new JDPControllerRunner(bcast, packet, pause);
|
||||||
|
|
||||||
|
Thread t = new Thread(controller, "JDP broadcaster");
|
||||||
|
t.setDaemon(true);
|
||||||
|
t.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop running discovery service,
|
||||||
|
* it's safe to attempt to stop not started service
|
||||||
|
*/
|
||||||
|
public static synchronized void stopDiscoveryService() {
|
||||||
|
if ( controller != null ){
|
||||||
|
controller.stop();
|
||||||
|
controller = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
40
jdk/src/share/classes/sun/management/jdp/JdpException.java
Normal file
40
jdk/src/share/classes/sun/management/jdp/JdpException.java
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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.
|
||||||
|
*/
|
||||||
|
package sun.management.jdp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An Exception thrown if a JDP implementation encounters a problem.
|
||||||
|
*/
|
||||||
|
public final class JdpException extends Exception {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new JDP exception with a meaningful message
|
||||||
|
*
|
||||||
|
* @param msg - message
|
||||||
|
*/
|
||||||
|
public JdpException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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.
|
||||||
|
*/
|
||||||
|
package sun.management.jdp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JdpGenericPacket responsible to provide fields
|
||||||
|
* common for all Jdp packets
|
||||||
|
*/
|
||||||
|
public abstract class JdpGenericPacket implements JdpPacket {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JDP protocol magic. Magic allows a reader to quickly select
|
||||||
|
* JDP packets from a bunch of broadcast packets addressed to the same port
|
||||||
|
* and broadcast group. Any packet intended to be parsed by JDP client
|
||||||
|
* has to start from this magic.
|
||||||
|
*/
|
||||||
|
private static final int MAGIC = 0xC0FFEE42;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current version of protocol. Any implementation of this protocol has to
|
||||||
|
* conform with the packet structure and the flow described in JEP-168
|
||||||
|
*/
|
||||||
|
private static final short PROTOCOL_VERSION = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default do-nothing constructor
|
||||||
|
*/
|
||||||
|
protected JdpGenericPacket(){
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate protocol header magic field
|
||||||
|
*
|
||||||
|
* @param magic - value to validate
|
||||||
|
* @throws JdpException
|
||||||
|
*/
|
||||||
|
public static void checkMagic(int magic)
|
||||||
|
throws JdpException {
|
||||||
|
if (magic != MAGIC) {
|
||||||
|
throw new JdpException("Invalid JDP magic header: " + magic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate protocol header version field
|
||||||
|
*
|
||||||
|
* @param version - value to validate
|
||||||
|
* @throws JdpException
|
||||||
|
*/
|
||||||
|
public static void checkVersion(short version)
|
||||||
|
throws JdpException {
|
||||||
|
|
||||||
|
if (version > PROTOCOL_VERSION) {
|
||||||
|
throw new JdpException("Unsupported protocol version: " + version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return protocol magic
|
||||||
|
*/
|
||||||
|
public static int getMagic() {
|
||||||
|
return MAGIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return current protocol version
|
||||||
|
*/
|
||||||
|
public static short getVersion() {
|
||||||
|
return PROTOCOL_VERSION;
|
||||||
|
}
|
||||||
|
}
|
196
jdk/src/share/classes/sun/management/jdp/JdpJmxPacket.java
Normal file
196
jdk/src/share/classes/sun/management/jdp/JdpJmxPacket.java
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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.
|
||||||
|
*/
|
||||||
|
package sun.management.jdp;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A packet to broadcasts JMX URL
|
||||||
|
*
|
||||||
|
* Fields:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>UUID - broadcast session ID, changed every time when we start/stop
|
||||||
|
* discovery service</li>
|
||||||
|
* <li>JMX_URL - URL to connect to JMX service</li>
|
||||||
|
* <li>MAIN_CLASS - optional name of main class, filled from sun.java.command stripped for
|
||||||
|
* security reason to first space</li>
|
||||||
|
* <li>INSTANCE_NAME - optional custom name of particular instance as provided by customer</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public final class JdpJmxPacket
|
||||||
|
extends JdpGenericPacket
|
||||||
|
implements JdpPacket {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Session ID
|
||||||
|
*/
|
||||||
|
public final static String UUID_KEY = "DISCOVERABLE_SESSION_UUID";
|
||||||
|
/**
|
||||||
|
* Name of main class
|
||||||
|
*/
|
||||||
|
public final static String MAIN_CLASS_KEY = "MAIN_CLASS";
|
||||||
|
/**
|
||||||
|
* JMX service URL
|
||||||
|
*/
|
||||||
|
public final static String JMX_SERVICE_URL_KEY = "JMX_SERVICE_URL";
|
||||||
|
/**
|
||||||
|
* Name of Java instance
|
||||||
|
*/
|
||||||
|
public final static String INSTANCE_NAME_KEY = "INSTANCE_NAME";
|
||||||
|
|
||||||
|
private UUID id;
|
||||||
|
private String mainClass;
|
||||||
|
private String jmxServiceUrl;
|
||||||
|
private String instanceName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new instance from user provided data. Set mandatory fields
|
||||||
|
*
|
||||||
|
* @param id - java instance id
|
||||||
|
* @param jmxServiceUrl - JMX service url
|
||||||
|
*/
|
||||||
|
public JdpJmxPacket(UUID id, String jmxServiceUrl) {
|
||||||
|
this.id = id;
|
||||||
|
this.jmxServiceUrl = jmxServiceUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new instance from network data Parse packet and set fields.
|
||||||
|
*
|
||||||
|
* @param data - raw packet data as it came from a Net
|
||||||
|
* @throws JdpException
|
||||||
|
*/
|
||||||
|
public JdpJmxPacket(byte[] data)
|
||||||
|
throws JdpException {
|
||||||
|
JdpPacketReader reader;
|
||||||
|
|
||||||
|
reader = new JdpPacketReader(data);
|
||||||
|
Map<String, String> p = reader.getDiscoveryDataAsMap();
|
||||||
|
|
||||||
|
String sId = p.get(UUID_KEY);
|
||||||
|
this.id = (sId == null) ? null : UUID.fromString(sId);
|
||||||
|
this.jmxServiceUrl = p.get(JMX_SERVICE_URL_KEY);
|
||||||
|
this.mainClass = p.get(MAIN_CLASS_KEY);
|
||||||
|
this.instanceName = p.get(INSTANCE_NAME_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set main class field
|
||||||
|
*
|
||||||
|
* @param mainClass - main class of running app
|
||||||
|
*/
|
||||||
|
public void setMainClass(String mainClass) {
|
||||||
|
this.mainClass = mainClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set instance name field
|
||||||
|
*
|
||||||
|
* @param instanceName - name of instance as provided by customer
|
||||||
|
*/
|
||||||
|
public void setInstanceName(String instanceName) {
|
||||||
|
this.instanceName = instanceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return id of discovery session
|
||||||
|
*/
|
||||||
|
public UUID getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return main class field
|
||||||
|
*/
|
||||||
|
public String getMainClass() {
|
||||||
|
return mainClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return JMX service URL
|
||||||
|
*/
|
||||||
|
public String getJmxServiceUrl() {
|
||||||
|
return jmxServiceUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return instance name
|
||||||
|
*/
|
||||||
|
public String getInstanceName() {
|
||||||
|
return instanceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return assembled packet ready to be sent across a Net
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public byte[] getPacketData() throws IOException {
|
||||||
|
// Assemble packet from fields to byte array
|
||||||
|
JdpPacketWriter writer;
|
||||||
|
writer = new JdpPacketWriter();
|
||||||
|
writer.addEntry(UUID_KEY, (id == null) ? null : id.toString());
|
||||||
|
writer.addEntry(MAIN_CLASS_KEY, mainClass);
|
||||||
|
writer.addEntry(JMX_SERVICE_URL_KEY, jmxServiceUrl);
|
||||||
|
writer.addEntry(INSTANCE_NAME_KEY, instanceName);
|
||||||
|
return writer.getPacketBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return packet hash code
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 1;
|
||||||
|
hash = hash * 31 + id.hashCode();
|
||||||
|
hash = hash * 31 + jmxServiceUrl.hashCode();
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare two packets
|
||||||
|
*
|
||||||
|
* @param o - packet to compare
|
||||||
|
* @return either packet equals or not
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
|
||||||
|
if (o == null || ! (o instanceof JdpJmxPacket) ){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
JdpJmxPacket p = (JdpJmxPacket) o;
|
||||||
|
return Objects.equals(id, p.getId()) && Objects.equals(jmxServiceUrl, p.getJmxServiceUrl());
|
||||||
|
}
|
||||||
|
}
|
63
jdk/src/share/classes/sun/management/jdp/JdpPacket.java
Normal file
63
jdk/src/share/classes/sun/management/jdp/JdpPacket.java
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sun.management.jdp;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Packet to broadcast
|
||||||
|
*
|
||||||
|
* <p>Each packet have to contain MAGIC and PROTOCOL_VERSION in order to be
|
||||||
|
* recognized as a valid JDP packet.</p>
|
||||||
|
*
|
||||||
|
* <p>Default implementation build packet as a set of UTF-8 encoded Key/Value pairs
|
||||||
|
* are stored as an ordered list of values, and are sent to the server
|
||||||
|
* in that order.</p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Packet structure:
|
||||||
|
*
|
||||||
|
* 4 bytes JDP magic (0xC0FFE42)
|
||||||
|
* 2 bytes JDP protocol version (01)
|
||||||
|
*
|
||||||
|
* 2 bytes size of key
|
||||||
|
* x bytes key (UTF-8 encoded)
|
||||||
|
* 2 bytes size of value
|
||||||
|
* x bytes value (UTF-8 encoded)
|
||||||
|
*
|
||||||
|
* repeat as many times as necessary ...
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public interface JdpPacket {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method responsible to assemble packet and return a byte array
|
||||||
|
* ready to be sent across a Net.
|
||||||
|
*
|
||||||
|
* @return assembled packet as an array of bytes
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public byte[] getPacketData() throws IOException;
|
||||||
|
|
||||||
|
}
|
139
jdk/src/share/classes/sun/management/jdp/JdpPacketReader.java
Normal file
139
jdk/src/share/classes/sun/management/jdp/JdpPacketReader.java
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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.
|
||||||
|
*/
|
||||||
|
package sun.management.jdp;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.EOFException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JdpPacketReader responsible for reading a packet <p>This class gets a byte
|
||||||
|
* array as it came from a Net, validates it and breaks a part </p>
|
||||||
|
*/
|
||||||
|
public final class JdpPacketReader {
|
||||||
|
|
||||||
|
private final DataInputStream pkt;
|
||||||
|
private Map<String, String> pmap = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create packet reader, extract and check magic and version
|
||||||
|
*
|
||||||
|
* @param packet - packet received from a Net
|
||||||
|
* @throws JdpException
|
||||||
|
*/
|
||||||
|
public JdpPacketReader(byte[] packet)
|
||||||
|
throws JdpException {
|
||||||
|
ByteArrayInputStream bais = new ByteArrayInputStream(packet);
|
||||||
|
pkt = new DataInputStream(bais);
|
||||||
|
|
||||||
|
try {
|
||||||
|
int magic = pkt.readInt();
|
||||||
|
JdpGenericPacket.checkMagic(magic);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new JdpException("Invalid JDP packet received, bad magic");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
short version = pkt.readShort();
|
||||||
|
JdpGenericPacket.checkVersion(version);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new JdpException("Invalid JDP packet received, bad protocol version");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get next entry from packet
|
||||||
|
*
|
||||||
|
* @return the entry
|
||||||
|
* @throws EOFException
|
||||||
|
* @throws JdpException
|
||||||
|
*/
|
||||||
|
public String getEntry()
|
||||||
|
throws EOFException, JdpException {
|
||||||
|
|
||||||
|
try {
|
||||||
|
short len = pkt.readShort();
|
||||||
|
// Artificial setting the "len" field to Short.MAX_VALUE may cause a reader to allocate
|
||||||
|
// to much memory. Prevent this possible DOS attack.
|
||||||
|
if (len < 1 && len > pkt.available()) {
|
||||||
|
throw new JdpException("Broken JDP packet. Invalid entry length field.");
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] b = new byte[len];
|
||||||
|
if (pkt.read(b) != len) {
|
||||||
|
throw new JdpException("Broken JDP packet. Unable to read entry.");
|
||||||
|
}
|
||||||
|
return new String(b, "UTF-8");
|
||||||
|
|
||||||
|
} catch (EOFException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (UnsupportedEncodingException ex) {
|
||||||
|
throw new JdpException("Broken JDP packet. Unable to decode entry.");
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new JdpException("Broken JDP packet. Unable to read entry.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return packet content as a key/value map
|
||||||
|
*
|
||||||
|
* @return map containing packet entries pair of entries treated as
|
||||||
|
* key,value
|
||||||
|
* @throws IOException
|
||||||
|
* @throws JdpException
|
||||||
|
*/
|
||||||
|
public Map<String, String> getDiscoveryDataAsMap()
|
||||||
|
throws JdpException {
|
||||||
|
// return cached map if possible
|
||||||
|
if (pmap != null) {
|
||||||
|
return pmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
String key = null, value = null;
|
||||||
|
|
||||||
|
final Map<String, String> tmpMap = new HashMap<>();
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
key = getEntry();
|
||||||
|
value = getEntry();
|
||||||
|
tmpMap.put(key, value);
|
||||||
|
}
|
||||||
|
} catch (EOFException e) {
|
||||||
|
// EOF reached on reading value, report broken packet
|
||||||
|
// otherwise ignore it.
|
||||||
|
if (value == null) {
|
||||||
|
throw new JdpException("Broken JDP packet. Key without value." + key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pmap = Collections.unmodifiableMap(tmpMap);
|
||||||
|
return pmap;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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.
|
||||||
|
*/
|
||||||
|
package sun.management.jdp;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JdpPacketWriter responsible for writing a packet
|
||||||
|
* <p>This class assembles a set of key/value pairs to valid JDP packet,
|
||||||
|
* ready to be sent across a Net</p>
|
||||||
|
*/
|
||||||
|
public final class JdpPacketWriter {
|
||||||
|
|
||||||
|
private final ByteArrayOutputStream baos;
|
||||||
|
private final DataOutputStream pkt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a JDP packet, add mandatory magic and version headers
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public JdpPacketWriter()
|
||||||
|
throws IOException {
|
||||||
|
baos = new ByteArrayOutputStream();
|
||||||
|
pkt = new DataOutputStream(baos);
|
||||||
|
|
||||||
|
pkt.writeInt(JdpGenericPacket.getMagic());
|
||||||
|
pkt.writeShort(JdpGenericPacket.getVersion());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put string entry to packet
|
||||||
|
*
|
||||||
|
* @param entry - string to put (utf-8 encoded)
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public void addEntry(String entry)
|
||||||
|
throws IOException {
|
||||||
|
pkt.writeShort(entry.length());
|
||||||
|
byte[] b = entry.getBytes("UTF-8");
|
||||||
|
pkt.write(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put key/value pair to packet
|
||||||
|
*
|
||||||
|
* @param key - key to put (utf-8 encoded)
|
||||||
|
* @param val - value to put (utf-8 encoded)
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public void addEntry(String key, String val)
|
||||||
|
throws IOException {
|
||||||
|
/* Silently skip key if value is null.
|
||||||
|
* We don't need to distinguish between key missing
|
||||||
|
* and key has no value cases
|
||||||
|
*/
|
||||||
|
if (val != null) {
|
||||||
|
addEntry(key);
|
||||||
|
addEntry(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return assembled packet as a byte array
|
||||||
|
*
|
||||||
|
* @return packet bytes
|
||||||
|
*/
|
||||||
|
public byte[] getPacketBytes() {
|
||||||
|
return baos.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
55
jdk/src/share/classes/sun/management/jdp/package-info.java
Normal file
55
jdk/src/share/classes/sun/management/jdp/package-info.java
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/**
|
||||||
|
* Summary
|
||||||
|
* -------
|
||||||
|
*
|
||||||
|
* Define a lightweight network protocol for discovering running and
|
||||||
|
* manageable Java processes within a network subnet.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Description
|
||||||
|
* -----------
|
||||||
|
*
|
||||||
|
* The protocol is lightweight multicast based, and works like a beacon,
|
||||||
|
* broadcasting the JMXService URL needed to connect to the external JMX
|
||||||
|
* agent if an application is started with appropriate parameters.
|
||||||
|
*
|
||||||
|
* The payload is structured like this:
|
||||||
|
*
|
||||||
|
* 4 bytes JDP magic (0xC0FFEE42)
|
||||||
|
* 2 bytes JDP protocol version (1)
|
||||||
|
* 2 bytes size of the next entry
|
||||||
|
* x bytes next entry (UTF-8 encoded)
|
||||||
|
* 2 bytes size of next entry
|
||||||
|
* ... Rinse and repeat...
|
||||||
|
*
|
||||||
|
* The payload will be parsed as even entries being keys, odd entries being
|
||||||
|
* values.
|
||||||
|
*
|
||||||
|
* The standard JDP packet contains four entries:
|
||||||
|
*
|
||||||
|
* - `DISCOVERABLE_SESSION_UUID` -- Unique id of the instance; this id changes every time
|
||||||
|
* the discovery protocol starts and stops
|
||||||
|
*
|
||||||
|
* - `MAIN_CLASS` -- The value of the `sun.java.command` property
|
||||||
|
*
|
||||||
|
* - `JMX_SERVICE_URL` -- The URL to connect to the JMX agent
|
||||||
|
*
|
||||||
|
* - `INSTANCE_NAME` -- The user-provided name of the running instance
|
||||||
|
*
|
||||||
|
* The protocol sends packets to 239.255.255.225:7095 by default.
|
||||||
|
*
|
||||||
|
* The protocol uses system properties to control it's behaviour:
|
||||||
|
* - `com.sun.management.jdp.port` -- override default port
|
||||||
|
*
|
||||||
|
* - `com.sun.management.jdp.address` -- override default address
|
||||||
|
*
|
||||||
|
* - `com.sun.management.jmxremote.autodiscovery` -- whether we should start autodiscovery or
|
||||||
|
* not. Autodiscovery starts if and only if following conditions are met: (autodiscovery is
|
||||||
|
* true OR (autodiscovery is not set AND jdp.port is set))
|
||||||
|
*
|
||||||
|
* - `com.sun.management.jdp.ttl` -- set ttl for broadcast packet, default is 1
|
||||||
|
* - `com.sun.management.jdp.pause` -- set broadcast interval in seconds default is 5
|
||||||
|
* - `com.sun.management.jdp.source_addr` -- an address of interface to use for broadcast
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sun.management.jdp;
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2013, 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
|
||||||
@ -26,6 +26,7 @@
|
|||||||
package sun.misc;
|
package sun.misc;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.reflect.Executable;
|
||||||
import sun.reflect.ConstantPool;
|
import sun.reflect.ConstantPool;
|
||||||
import sun.reflect.annotation.AnnotationType;
|
import sun.reflect.annotation.AnnotationType;
|
||||||
import sun.nio.ch.Interruptible;
|
import sun.nio.ch.Interruptible;
|
||||||
@ -46,6 +47,18 @@ public interface JavaLangAccess {
|
|||||||
*/
|
*/
|
||||||
AnnotationType getAnnotationType(Class<?> klass);
|
AnnotationType getAnnotationType(Class<?> klass);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the array of bytes that is the class-file representation
|
||||||
|
* of this Class' type annotations.
|
||||||
|
*/
|
||||||
|
byte[] getRawClassTypeAnnotations(Class<?> klass);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the array of bytes that is the class-file representation
|
||||||
|
* of this Executable's type annotations.
|
||||||
|
*/
|
||||||
|
byte[] getRawExecutableTypeAnnotations(Executable executable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the elements of an enum class or null if the
|
* Returns the elements of an enum class or null if the
|
||||||
* Class object does not represent an enum type;
|
* Class object does not represent an enum type;
|
||||||
@ -84,9 +97,4 @@ public interface JavaLangAccess {
|
|||||||
* Returns the ith StackTraceElement for the given throwable.
|
* Returns the ith StackTraceElement for the given throwable.
|
||||||
*/
|
*/
|
||||||
StackTraceElement getStackTraceElement(Throwable t, int i);
|
StackTraceElement getStackTraceElement(Throwable t, int i);
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a directly present annotation.
|
|
||||||
*/
|
|
||||||
public <A extends Annotation> A getDirectDeclaredAnnotation(Class<?> klass, Class<A> anno);
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2013, 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
|
||||||
@ -81,6 +81,9 @@ public interface LangReflectAccess {
|
|||||||
public void setConstructorAccessor(Constructor<?> c,
|
public void setConstructorAccessor(Constructor<?> c,
|
||||||
ConstructorAccessor accessor);
|
ConstructorAccessor accessor);
|
||||||
|
|
||||||
|
/** Gets the byte[] that encodes TypeAnnotations on an Executable. */
|
||||||
|
public byte[] getExecutableTypeAnnotationBytes(Executable ex);
|
||||||
|
|
||||||
/** Gets the "slot" field from a Constructor (used for serialization) */
|
/** Gets the "slot" field from a Constructor (used for serialization) */
|
||||||
public int getConstructorSlot(Constructor<?> c);
|
public int getConstructorSlot(Constructor<?> c);
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2013, 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
|
||||||
@ -26,6 +26,7 @@
|
|||||||
package sun.reflect;
|
package sun.reflect;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Executable;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
@ -314,6 +315,12 @@ public class ReflectionFactory {
|
|||||||
return langReflectAccess().copyConstructor(arg);
|
return langReflectAccess().copyConstructor(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Gets the byte[] that encodes TypeAnnotations on an executable.
|
||||||
|
*/
|
||||||
|
public byte[] getExecutableTypeAnnotationBytes(Executable ex) {
|
||||||
|
return langReflectAccess().getExecutableTypeAnnotationBytes(ex);
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Routines used by serialization
|
// Routines used by serialization
|
||||||
|
@ -0,0 +1,315 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013, 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. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sun.reflect.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static sun.reflect.annotation.TypeAnnotation.*;
|
||||||
|
|
||||||
|
public class AnnotatedTypeFactory {
|
||||||
|
/**
|
||||||
|
* Create an AnnotatedType.
|
||||||
|
*
|
||||||
|
* @param type the type this AnnotatedType corresponds to
|
||||||
|
* @param currentLoc the location this AnnotatedType corresponds to
|
||||||
|
* @param actualTypeAnnos the type annotations this AnnotatedType has
|
||||||
|
* @param allOnSameTarget all type annotation on the same TypeAnnotationTarget
|
||||||
|
* as the AnnotatedType being built
|
||||||
|
* @param decl the declaration having the type use this AnnotatedType
|
||||||
|
* corresponds to
|
||||||
|
*/
|
||||||
|
public static AnnotatedType buildAnnotatedType(Type type,
|
||||||
|
LocationInfo currentLoc,
|
||||||
|
TypeAnnotation[] actualTypeAnnos,
|
||||||
|
TypeAnnotation[] allOnSameTarget,
|
||||||
|
AnnotatedElement decl) {
|
||||||
|
if (type == null) {
|
||||||
|
return EMPTY_ANNOTATED_TYPE;
|
||||||
|
}
|
||||||
|
if (isArray(type))
|
||||||
|
return new AnnotatedArrayTypeImpl(type,
|
||||||
|
currentLoc,
|
||||||
|
actualTypeAnnos,
|
||||||
|
allOnSameTarget,
|
||||||
|
decl);
|
||||||
|
if (type instanceof Class) {
|
||||||
|
return new AnnotatedTypeBaseImpl(type,
|
||||||
|
addNesting(type, currentLoc),
|
||||||
|
actualTypeAnnos,
|
||||||
|
allOnSameTarget,
|
||||||
|
decl);
|
||||||
|
} else if (type instanceof TypeVariable) {
|
||||||
|
return new AnnotatedTypeVariableImpl((TypeVariable)type,
|
||||||
|
currentLoc,
|
||||||
|
actualTypeAnnos,
|
||||||
|
allOnSameTarget,
|
||||||
|
decl);
|
||||||
|
} else if (type instanceof ParameterizedType) {
|
||||||
|
return new AnnotatedParameterizedTypeImpl((ParameterizedType)type,
|
||||||
|
addNesting(type, currentLoc),
|
||||||
|
actualTypeAnnos,
|
||||||
|
allOnSameTarget,
|
||||||
|
decl);
|
||||||
|
} else if (type instanceof WildcardType) {
|
||||||
|
return new AnnotatedWildcardTypeImpl((WildcardType) type,
|
||||||
|
currentLoc,
|
||||||
|
actualTypeAnnos,
|
||||||
|
allOnSameTarget,
|
||||||
|
decl);
|
||||||
|
}
|
||||||
|
throw new AssertionError("Unknown instance of Type: " + type + "\nThis should not happen.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LocationInfo addNesting(Type type, LocationInfo addTo) {
|
||||||
|
if (isArray(type))
|
||||||
|
return addTo;
|
||||||
|
if (type instanceof Class) {
|
||||||
|
Class<?> clz = (Class)type;
|
||||||
|
if (clz.getEnclosingClass() == null)
|
||||||
|
return addTo;
|
||||||
|
return addNesting(clz.getEnclosingClass(), addTo.pushInner());
|
||||||
|
} else if (type instanceof ParameterizedType) {
|
||||||
|
ParameterizedType t = (ParameterizedType)type;
|
||||||
|
if (t.getOwnerType() == null)
|
||||||
|
return addTo;
|
||||||
|
return addNesting(t.getOwnerType(), addTo.pushInner());
|
||||||
|
}
|
||||||
|
return addTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isArray(Type t) {
|
||||||
|
if (t instanceof Class) {
|
||||||
|
Class<?> c = (Class)t;
|
||||||
|
if (c.isArray())
|
||||||
|
return true;
|
||||||
|
} else if (t instanceof GenericArrayType) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static final AnnotatedType EMPTY_ANNOTATED_TYPE = new AnnotatedTypeBaseImpl(null, LocationInfo.BASE_LOCATION,
|
||||||
|
new TypeAnnotation[0], new TypeAnnotation[0], null);
|
||||||
|
|
||||||
|
private static class AnnotatedTypeBaseImpl implements AnnotatedType {
|
||||||
|
private final Type type;
|
||||||
|
private final AnnotatedElement decl;
|
||||||
|
private final LocationInfo location;
|
||||||
|
private final TypeAnnotation[] allOnSameTargetTypeAnnotations;
|
||||||
|
private final Map<Class <? extends Annotation>, Annotation> annotations;
|
||||||
|
|
||||||
|
AnnotatedTypeBaseImpl(Type type, LocationInfo location,
|
||||||
|
TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
|
||||||
|
AnnotatedElement decl) {
|
||||||
|
this.type = type;
|
||||||
|
this.decl = decl;
|
||||||
|
this.location = location;
|
||||||
|
this.allOnSameTargetTypeAnnotations = allOnSameTargetTypeAnnotations;
|
||||||
|
this.annotations = TypeAnnotationParser.mapTypeAnnotations(location.filter(actualTypeAnnotations));
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnnotatedElement
|
||||||
|
@Override
|
||||||
|
public final Annotation[] getAnnotations() {
|
||||||
|
return getDeclaredAnnotations();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final <T extends Annotation> T getAnnotation(Class<T> annotation) {
|
||||||
|
return getDeclaredAnnotation(annotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final <T extends Annotation> T[] getAnnotations(Class<T> annotation) {
|
||||||
|
return getDeclaredAnnotations(annotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Annotation[] getDeclaredAnnotations() {
|
||||||
|
return annotations.values().toArray(new Annotation[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotation) {
|
||||||
|
return (T)annotations.get(annotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotation) {
|
||||||
|
return AnnotationSupport.getMultipleAnnotations(annotations, annotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnnotatedType
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implementation details
|
||||||
|
LocationInfo getLocation() {
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
TypeAnnotation[] getTypeAnnotations() {
|
||||||
|
return allOnSameTargetTypeAnnotations;
|
||||||
|
}
|
||||||
|
AnnotatedElement getDecl() {
|
||||||
|
return decl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class AnnotatedArrayTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedArrayType {
|
||||||
|
AnnotatedArrayTypeImpl(Type type, LocationInfo location,
|
||||||
|
TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
|
||||||
|
AnnotatedElement decl) {
|
||||||
|
super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AnnotatedType getAnnotatedGenericComponentType() {
|
||||||
|
return AnnotatedTypeFactory.buildAnnotatedType(getComponentType(),
|
||||||
|
getLocation().pushArray(),
|
||||||
|
getTypeAnnotations(),
|
||||||
|
getTypeAnnotations(),
|
||||||
|
getDecl());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Type getComponentType() {
|
||||||
|
Type t = getType();
|
||||||
|
if (t instanceof Class) {
|
||||||
|
Class<?> c = (Class)t;
|
||||||
|
return c.getComponentType();
|
||||||
|
}
|
||||||
|
return ((GenericArrayType)t).getGenericComponentType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class AnnotatedTypeVariableImpl extends AnnotatedTypeBaseImpl implements AnnotatedTypeVariable {
|
||||||
|
AnnotatedTypeVariableImpl(TypeVariable<?> type, LocationInfo location,
|
||||||
|
TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
|
||||||
|
AnnotatedElement decl) {
|
||||||
|
super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AnnotatedType[] getAnnotatedBounds() {
|
||||||
|
return getTypeVariable().getAnnotatedBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
private TypeVariable<?> getTypeVariable() {
|
||||||
|
return (TypeVariable)getType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class AnnotatedParameterizedTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedParameterizedType {
|
||||||
|
AnnotatedParameterizedTypeImpl(ParameterizedType type, LocationInfo location,
|
||||||
|
TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
|
||||||
|
AnnotatedElement decl) {
|
||||||
|
super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AnnotatedType[] getAnnotatedActualTypeArguments() {
|
||||||
|
Type[] arguments = getParameterizedType().getActualTypeArguments();
|
||||||
|
AnnotatedType[] res = new AnnotatedType[arguments.length];
|
||||||
|
Arrays.fill(res, EMPTY_ANNOTATED_TYPE);
|
||||||
|
int initialCapacity = getTypeAnnotations().length;
|
||||||
|
for (int i = 0; i < res.length; i++) {
|
||||||
|
List<TypeAnnotation> l = new ArrayList<>(initialCapacity);
|
||||||
|
LocationInfo newLoc = getLocation().pushTypeArg((byte)i);
|
||||||
|
for (TypeAnnotation t : getTypeAnnotations())
|
||||||
|
if (t.getLocationInfo().isSameLocationInfo(newLoc))
|
||||||
|
l.add(t);
|
||||||
|
res[i] = buildAnnotatedType(arguments[i],
|
||||||
|
newLoc,
|
||||||
|
l.toArray(new TypeAnnotation[0]),
|
||||||
|
getTypeAnnotations(),
|
||||||
|
getDecl());
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ParameterizedType getParameterizedType() {
|
||||||
|
return (ParameterizedType)getType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class AnnotatedWildcardTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedWildcardType {
|
||||||
|
private final boolean hasUpperBounds;
|
||||||
|
AnnotatedWildcardTypeImpl(WildcardType type, LocationInfo location,
|
||||||
|
TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
|
||||||
|
AnnotatedElement decl) {
|
||||||
|
super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
|
||||||
|
hasUpperBounds = (type.getLowerBounds().length == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AnnotatedType[] getAnnotatedUpperBounds() {
|
||||||
|
if (!hasUpperBounds())
|
||||||
|
return new AnnotatedType[0];
|
||||||
|
return getAnnotatedBounds(getWildcardType().getUpperBounds());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AnnotatedType[] getAnnotatedLowerBounds() {
|
||||||
|
if (hasUpperBounds)
|
||||||
|
return new AnnotatedType[0];
|
||||||
|
return getAnnotatedBounds(getWildcardType().getLowerBounds());
|
||||||
|
}
|
||||||
|
|
||||||
|
private AnnotatedType[] getAnnotatedBounds(Type[] bounds) {
|
||||||
|
AnnotatedType[] res = new AnnotatedType[bounds.length];
|
||||||
|
Arrays.fill(res, EMPTY_ANNOTATED_TYPE);
|
||||||
|
LocationInfo newLoc = getLocation().pushWildcard();
|
||||||
|
int initialCapacity = getTypeAnnotations().length;
|
||||||
|
for (int i = 0; i < res.length; i++) {
|
||||||
|
List<TypeAnnotation> l = new ArrayList<>(initialCapacity);
|
||||||
|
for (TypeAnnotation t : getTypeAnnotations())
|
||||||
|
if (t.getLocationInfo().isSameLocationInfo(newLoc))
|
||||||
|
l.add(t);
|
||||||
|
res[i] = buildAnnotatedType(bounds[i],
|
||||||
|
newLoc,
|
||||||
|
l.toArray(new TypeAnnotation[0]),
|
||||||
|
getTypeAnnotations(),
|
||||||
|
getDecl());
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
private WildcardType getWildcardType() {
|
||||||
|
return (WildcardType)getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasUpperBounds() {
|
||||||
|
return hasUpperBounds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2013, 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
|
||||||
@ -188,7 +188,7 @@ public class AnnotationParser {
|
|||||||
* available at runtime
|
* available at runtime
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static Annotation parseAnnotation(ByteBuffer buf,
|
static Annotation parseAnnotation(ByteBuffer buf,
|
||||||
ConstantPool constPool,
|
ConstantPool constPool,
|
||||||
Class<?> container,
|
Class<?> container,
|
||||||
boolean exceptionOnMissingAnnotationClass) {
|
boolean exceptionOnMissingAnnotationClass) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2013, 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
|
||||||
@ -27,63 +27,29 @@ package sun.reflect.annotation;
|
|||||||
|
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
|
||||||
import sun.reflect.Reflection;
|
|
||||||
import sun.misc.JavaLangAccess;
|
|
||||||
|
|
||||||
public final class AnnotationSupport {
|
public final class AnnotationSupport {
|
||||||
private static final JavaLangAccess javaLangAccess = sun.misc.SharedSecrets.getJavaLangAccess();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds and returns _one_ annotation of the type indicated by
|
|
||||||
* {@code annotationClass} from the {@code Map} {@code
|
|
||||||
* annotationMap}. Looks into containers of the {@code
|
|
||||||
* annotationClass} (as specified by an the {@code
|
|
||||||
* annotationClass} type being meta-annotated with an {@code
|
|
||||||
* ContainedBy} annotation).
|
|
||||||
*
|
|
||||||
* @param annotationMap the {@code Map} used to store annotations and indexed by their type
|
|
||||||
* @param annotationClass the type of annotation to search for
|
|
||||||
*
|
|
||||||
* @return in instance of {@code annotationClass} or {@code null} if none were found
|
|
||||||
*/
|
|
||||||
public static <A extends Annotation> A getOneAnnotation(final Map<Class<? extends Annotation>, Annotation> annotationMap,
|
|
||||||
final Class<A> annotationClass) {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final A candidate = (A)annotationMap.get(annotationClass);
|
|
||||||
if (candidate != null) {
|
|
||||||
return candidate;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Class<? extends Annotation> containerClass = getContainer(annotationClass);
|
|
||||||
if (containerClass != null) {
|
|
||||||
return unpackOne(annotationMap.get(containerClass), annotationClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null; // found none
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds and returns all annotation of the type indicated by
|
* Finds and returns all annotation of the type indicated by
|
||||||
* {@code annotationClass} from the {@code Map} {@code
|
* {@code annotationClass} from the {@code Map} {@code
|
||||||
* annotationMap}. Looks into containers of the {@code
|
* annotationMap}. Looks into containers of the {@code
|
||||||
* annotationClass} (as specified by an the {@code
|
* annotationClass} (as specified by an the {@code
|
||||||
* annotationClass} type being meta-annotated with an {@code
|
* annotationClass} type being meta-annotated with an {@code
|
||||||
* ContainedBy} annotation).
|
* Repeatable} annotation).
|
||||||
*
|
*
|
||||||
* @param annotationMap the {@code Map} used to store annotations indexed by their type
|
* @param annotationMap the {@code Map} used to store annotations indexed by their type
|
||||||
* @param annotationClass the type of annotation to search for
|
* @param annotationClass the type of annotation to search for
|
||||||
*
|
*
|
||||||
* @return an array of instances of {@code annotationClass} or an empty array if none were found
|
* @return an array of instances of {@code annotationClass} or an empty array if none were found
|
||||||
*/
|
*/
|
||||||
public static <A extends Annotation> A[] getMultipleAnnotations(final Map<Class<? extends Annotation>, Annotation> annotationMap,
|
public static <A extends Annotation> A[] getMultipleAnnotations(
|
||||||
|
final Map<Class<? extends Annotation>, Annotation> annotationMap,
|
||||||
final Class<A> annotationClass) {
|
final Class<A> annotationClass) {
|
||||||
final ArrayList<A> res = new ArrayList<A>();
|
final List<A> res = new ArrayList<A>();
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final A candidate = (A)annotationMap.get(annotationClass);
|
final A candidate = (A)annotationMap.get(annotationClass);
|
||||||
@ -101,49 +67,10 @@ public final class AnnotationSupport {
|
|||||||
return res.isEmpty() ? emptyTemplateArray : res.toArray(emptyTemplateArray);
|
return res.isEmpty() ? emptyTemplateArray : res.toArray(emptyTemplateArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Unpacks the {@code annotationMap} parameter into an array of
|
|
||||||
* {@code Annotation}s. This method will unpack all repeating
|
|
||||||
* annotations containers (once). An annotation type is marked as a
|
|
||||||
* container by meta-annotating it the with the {@code
|
|
||||||
* ContainerFor} annotation.
|
|
||||||
*
|
|
||||||
* @param annotationMap the {@code Map} from where the annotations are unpacked
|
|
||||||
*
|
|
||||||
* @return an array of Annotation
|
|
||||||
*/
|
|
||||||
public static Annotation[] unpackToArray(Map<Class<? extends Annotation>, Annotation> annotationMap) {
|
|
||||||
List<Annotation> res = new ArrayList<>();
|
|
||||||
for (Map.Entry<Class<? extends Annotation>, Annotation> e : annotationMap.entrySet()) {
|
|
||||||
Class<? extends Annotation> annotationClass = e.getKey();
|
|
||||||
Annotation annotationInstance = e.getValue();
|
|
||||||
Class<? extends Annotation> containee = getContainee(e.getKey());
|
|
||||||
boolean isContainer = javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainerFor.class) != null;
|
|
||||||
|
|
||||||
if (isContainer) {
|
|
||||||
res.addAll(unpackAll(annotationInstance, containee));
|
|
||||||
} else {
|
|
||||||
res.add(annotationInstance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.isEmpty()
|
|
||||||
? AnnotationParser.getEmptyAnnotationArray()
|
|
||||||
: res.toArray(AnnotationParser.getEmptyAnnotationArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Helper to get the container, or null if none, of an annotation. */
|
/** Helper to get the container, or null if none, of an annotation. */
|
||||||
private static <A extends Annotation> Class<? extends Annotation> getContainer(Class<A> annotationClass) {
|
private static <A extends Annotation> Class<? extends Annotation> getContainer(Class<A> annotationClass) {
|
||||||
ContainedBy containerAnnotation =
|
Repeatable containingAnnotation = annotationClass.getDeclaredAnnotation(Repeatable.class);
|
||||||
javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainedBy.class);
|
return (containingAnnotation == null) ? null : containingAnnotation.value();
|
||||||
return (containerAnnotation == null) ? null : containerAnnotation.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Helper to get the containee, or null if this isn't a container, of a possible container annotation. */
|
|
||||||
private static <A extends Annotation> Class<? extends Annotation> getContainee(Class<A> annotationClass) {
|
|
||||||
ContainerFor containerAnnotation =
|
|
||||||
javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainerFor.class);
|
|
||||||
return (containerAnnotation == null) ? null : containerAnnotation.value();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Reflectively look up and get the returned array from the the
|
/** Reflectively look up and get the returned array from the the
|
||||||
@ -156,14 +83,15 @@ public final class AnnotationSupport {
|
|||||||
// value element. Get the AnnotationType, get the "value" element
|
// value element. Get the AnnotationType, get the "value" element
|
||||||
// and invoke it to get the contents.
|
// and invoke it to get the contents.
|
||||||
|
|
||||||
Class<?> containerClass = containerInstance.annotationType();
|
Class<? extends Annotation> containerClass = containerInstance.annotationType();
|
||||||
AnnotationType annoType = javaLangAccess.getAnnotationType(containerClass);
|
AnnotationType annoType = AnnotationType.getInstance(containerClass);
|
||||||
if (annoType == null)
|
if (annoType == null)
|
||||||
throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations");
|
throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations");
|
||||||
|
|
||||||
Method m = annoType.members().get("value");
|
Method m = annoType.members().get("value");
|
||||||
if (m == null)
|
if (m == null)
|
||||||
throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations");
|
throw new InvalidContainerAnnotationError(containerInstance +
|
||||||
|
" is an invalid container for repeating annotations");
|
||||||
m.setAccessible(true);
|
m.setAccessible(true);
|
||||||
|
|
||||||
@SuppressWarnings("unchecked") // not provably safe, but we catch the ClassCastException
|
@SuppressWarnings("unchecked") // not provably safe, but we catch the ClassCastException
|
||||||
@ -175,53 +103,34 @@ public final class AnnotationSupport {
|
|||||||
IllegalArgumentException | // parameters doesn't match
|
IllegalArgumentException | // parameters doesn't match
|
||||||
InvocationTargetException | // the value method threw an exception
|
InvocationTargetException | // the value method threw an exception
|
||||||
ClassCastException e) { // well, a cast failed ...
|
ClassCastException e) { // well, a cast failed ...
|
||||||
throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations",
|
throw new InvalidContainerAnnotationError(
|
||||||
|
containerInstance + " is an invalid container for repeating annotations",
|
||||||
e,
|
e,
|
||||||
containerInstance,
|
containerInstance,
|
||||||
null);
|
null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sanity check type of and return the first annotation instance
|
|
||||||
* of type {@code annotationClass} from {@code
|
|
||||||
* containerInstance}.
|
|
||||||
*/
|
|
||||||
private static <A extends Annotation> A unpackOne(Annotation containerInstance, Class<A> annotationClass) {
|
|
||||||
if (containerInstance == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return annotationClass.cast(getValueArray(containerInstance)[0]);
|
|
||||||
} catch (ArrayIndexOutOfBoundsException | // empty array
|
|
||||||
ClassCastException | // well, a cast failed ...
|
|
||||||
NullPointerException e) { // can this NP? for good meassure
|
|
||||||
throw new InvalidContainerAnnotationError(String.format("%s is an invalid container for repeating annotations of type: %s",
|
|
||||||
containerInstance, annotationClass),
|
|
||||||
e,
|
|
||||||
containerInstance,
|
|
||||||
annotationClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sanity check type of and return a list of all the annotation
|
/* Sanity check type of and return a list of all the annotation
|
||||||
* instances of type {@code annotationClass} from {@code
|
* instances of type {@code annotationClass} from {@code
|
||||||
* containerInstance}.
|
* containerInstance}.
|
||||||
*/
|
*/
|
||||||
private static <A extends Annotation> List<A> unpackAll(Annotation containerInstance, Class<A> annotationClass) {
|
private static <A extends Annotation> List<A> unpackAll(Annotation containerInstance,
|
||||||
|
Class<A> annotationClass) {
|
||||||
if (containerInstance == null) {
|
if (containerInstance == null) {
|
||||||
return Collections.emptyList(); // container not present
|
return Collections.emptyList(); // container not present
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
A[] a = getValueArray(containerInstance);
|
A[] a = getValueArray(containerInstance);
|
||||||
ArrayList<A> l = new ArrayList<>(a.length);
|
List<A> l = new ArrayList<>(a.length);
|
||||||
for (int i = 0; i < a.length; i++)
|
for (int i = 0; i < a.length; i++)
|
||||||
l.add(annotationClass.cast(a[i]));
|
l.add(annotationClass.cast(a[i]));
|
||||||
return l;
|
return l;
|
||||||
} catch (ClassCastException |
|
} catch (ClassCastException |
|
||||||
NullPointerException e) {
|
NullPointerException e) {
|
||||||
throw new InvalidContainerAnnotationError(String.format("%s is an invalid container for repeating annotations of type: %s",
|
throw new InvalidContainerAnnotationError(
|
||||||
|
String.format("%s is an invalid container for repeating annotations of type: %s",
|
||||||
containerInstance, annotationClass),
|
containerInstance, annotationClass),
|
||||||
e,
|
e,
|
||||||
containerInstance,
|
containerInstance,
|
||||||
|
227
jdk/src/share/classes/sun/reflect/annotation/TypeAnnotation.java
Normal file
227
jdk/src/share/classes/sun/reflect/annotation/TypeAnnotation.java
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013, 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. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
package sun.reflect.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.annotation.AnnotationFormatError;
|
||||||
|
import java.lang.reflect.AnnotatedElement;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A TypeAnnotation contains all the information needed to transform type
|
||||||
|
* annotations on declarations in the class file to actual Annotations in
|
||||||
|
* AnnotatedType instances.
|
||||||
|
*
|
||||||
|
* TypeAnnotaions contain a base Annotation, location info (which lets you
|
||||||
|
* distinguish between '@A Inner.@B Outer' in for example nested types),
|
||||||
|
* target info and the declaration the TypeAnnotaiton was parsed from.
|
||||||
|
*/
|
||||||
|
public class TypeAnnotation {
|
||||||
|
private final TypeAnnotationTargetInfo targetInfo;
|
||||||
|
private final LocationInfo loc;
|
||||||
|
private final Annotation annotation;
|
||||||
|
private final AnnotatedElement baseDeclaration;
|
||||||
|
|
||||||
|
public TypeAnnotation(TypeAnnotationTargetInfo targetInfo,
|
||||||
|
LocationInfo loc,
|
||||||
|
Annotation annotation,
|
||||||
|
AnnotatedElement baseDeclaration) {
|
||||||
|
this.targetInfo = targetInfo;
|
||||||
|
this.loc = loc;
|
||||||
|
this.annotation = annotation;
|
||||||
|
this.baseDeclaration = baseDeclaration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeAnnotationTargetInfo getTargetInfo() {
|
||||||
|
return targetInfo;
|
||||||
|
}
|
||||||
|
public Annotation getAnnotation() {
|
||||||
|
return annotation;
|
||||||
|
}
|
||||||
|
public AnnotatedElement getBaseDeclaration() {
|
||||||
|
return baseDeclaration;
|
||||||
|
}
|
||||||
|
public LocationInfo getLocationInfo() {
|
||||||
|
return loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<TypeAnnotation> filter(TypeAnnotation[] typeAnnotations,
|
||||||
|
TypeAnnotationTarget predicate) {
|
||||||
|
ArrayList<TypeAnnotation> typeAnnos = new ArrayList<>(typeAnnotations.length);
|
||||||
|
for (TypeAnnotation t : typeAnnotations)
|
||||||
|
if (t.getTargetInfo().getTarget() == predicate)
|
||||||
|
typeAnnos.add(t);
|
||||||
|
typeAnnos.trimToSize();
|
||||||
|
return typeAnnos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static enum TypeAnnotationTarget {
|
||||||
|
CLASS_TYPE_PARAMETER,
|
||||||
|
METHOD_TYPE_PARAMETER,
|
||||||
|
CLASS_EXTENDS,
|
||||||
|
CLASS_IMPLEMENTS,
|
||||||
|
CLASS_PARAMETER_BOUND,
|
||||||
|
METHOD_PARAMETER_BOUND,
|
||||||
|
METHOD_RETURN_TYPE,
|
||||||
|
METHOD_RECEIVER_TYPE,
|
||||||
|
FIELD_TYPE,
|
||||||
|
THROWS;
|
||||||
|
}
|
||||||
|
public static class TypeAnnotationTargetInfo {
|
||||||
|
private final TypeAnnotationTarget target;
|
||||||
|
private final int count;
|
||||||
|
private final int secondaryIndex;
|
||||||
|
private static final int UNUSED_INDEX = -2; // this is not a valid index in the 308 spec
|
||||||
|
|
||||||
|
public TypeAnnotationTargetInfo(TypeAnnotationTarget target) {
|
||||||
|
this(target, UNUSED_INDEX, UNUSED_INDEX);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeAnnotationTargetInfo(TypeAnnotationTarget target,
|
||||||
|
int count) {
|
||||||
|
this(target, count, UNUSED_INDEX);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeAnnotationTargetInfo(TypeAnnotationTarget target,
|
||||||
|
int count,
|
||||||
|
int secondaryIndex) {
|
||||||
|
this.target = target;
|
||||||
|
this.count = count;
|
||||||
|
this.secondaryIndex = secondaryIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeAnnotationTarget getTarget() {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
public int getCount() {
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
public int getSecondaryIndex() {
|
||||||
|
return secondaryIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "" + target + ": " + count + ", " + secondaryIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class LocationInfo {
|
||||||
|
private final int depth;
|
||||||
|
private final Location[] locations;
|
||||||
|
|
||||||
|
private LocationInfo() {
|
||||||
|
this(0, new Location[0]);
|
||||||
|
}
|
||||||
|
private LocationInfo(int depth, Location[] locations) {
|
||||||
|
this.depth = depth;
|
||||||
|
this.locations = locations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final LocationInfo BASE_LOCATION = new LocationInfo();
|
||||||
|
|
||||||
|
public static LocationInfo parseLocationInfo(ByteBuffer buf) {
|
||||||
|
int depth = buf.get();
|
||||||
|
if (depth == 0)
|
||||||
|
return BASE_LOCATION;
|
||||||
|
Location[] locations = new Location[depth];
|
||||||
|
for (int i = 0; i < depth; i++) {
|
||||||
|
byte tag = buf.get();
|
||||||
|
byte index = buf.get();
|
||||||
|
if (!(tag == 0 || tag == 1 | tag == 2 || tag == 3))
|
||||||
|
throw new AnnotationFormatError("Bad Location encoding in Type Annotation");
|
||||||
|
if (tag != 3 && index != 0)
|
||||||
|
throw new AnnotationFormatError("Bad Location encoding in Type Annotation");
|
||||||
|
locations[i] = new Location(tag, index);
|
||||||
|
}
|
||||||
|
return new LocationInfo(depth, locations);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocationInfo pushArray() {
|
||||||
|
return pushLocation((byte)0, (byte)0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocationInfo pushInner() {
|
||||||
|
return pushLocation((byte)1, (byte)0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocationInfo pushWildcard() {
|
||||||
|
return pushLocation((byte) 2, (byte) 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocationInfo pushTypeArg(byte index) {
|
||||||
|
return pushLocation((byte) 3, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocationInfo pushLocation(byte tag, byte index) {
|
||||||
|
int newDepth = this.depth + 1;
|
||||||
|
Location[] res = new Location[newDepth];
|
||||||
|
System.arraycopy(this.locations, 0, res, 0, depth);
|
||||||
|
res[newDepth - 1] = new Location(tag, index);
|
||||||
|
return new LocationInfo(newDepth, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeAnnotation[] filter(TypeAnnotation[] ta) {
|
||||||
|
ArrayList<TypeAnnotation> l = new ArrayList<>(ta.length);
|
||||||
|
for (TypeAnnotation t : ta) {
|
||||||
|
if (isSameLocationInfo(t.getLocationInfo()))
|
||||||
|
l.add(t);
|
||||||
|
}
|
||||||
|
return l.toArray(new TypeAnnotation[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isSameLocationInfo(LocationInfo other) {
|
||||||
|
if (depth != other.depth)
|
||||||
|
return false;
|
||||||
|
for (int i = 0; i < depth; i++)
|
||||||
|
if (!locations[i].isSameLocation(other.locations[i]))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Location {
|
||||||
|
public final byte tag;
|
||||||
|
public final byte index;
|
||||||
|
|
||||||
|
boolean isSameLocation(Location other) {
|
||||||
|
return tag == other.tag && index == other.index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location(byte tag, byte index) {
|
||||||
|
this.tag = tag;
|
||||||
|
this.index = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return annotation.toString() + " with Targetnfo: " +
|
||||||
|
targetInfo.toString() + " on base declaration: " +
|
||||||
|
baseDeclaration.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,491 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013, 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. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sun.reflect.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.BufferUnderflowException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import sun.misc.JavaLangAccess;
|
||||||
|
import sun.reflect.ConstantPool;
|
||||||
|
import static sun.reflect.annotation.TypeAnnotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TypeAnnotationParser implements the logic needed to parse
|
||||||
|
* TypeAnnotations from an array of bytes.
|
||||||
|
*/
|
||||||
|
public class TypeAnnotationParser {
|
||||||
|
private static final TypeAnnotation[] EMPTY_TYPE_ANNOTATION_ARRAY = new TypeAnnotation[0];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build an AnnotatedType from the parameters supplied.
|
||||||
|
*
|
||||||
|
* This method and {@code buildAnnotatedTypes} are probably
|
||||||
|
* the entry points you are looking for.
|
||||||
|
*
|
||||||
|
* @param rawAnnotations the byte[] encoding of all type annotations on this declaration
|
||||||
|
* @param cp the ConstantPool needed to parse the embedded Annotation
|
||||||
|
* @param decl the dclaration this type annotation is on
|
||||||
|
* @param container the Class this type annotation is on (may be the same as decl)
|
||||||
|
* @param type the type the AnnotatedType corresponds to
|
||||||
|
* @param filter the type annotation targets included in this AnnotatedType
|
||||||
|
*/
|
||||||
|
public static AnnotatedType buildAnnotatedType(byte[] rawAnnotations,
|
||||||
|
ConstantPool cp,
|
||||||
|
AnnotatedElement decl,
|
||||||
|
Class<?> container,
|
||||||
|
Type type,
|
||||||
|
TypeAnnotationTarget filter) {
|
||||||
|
TypeAnnotation[] tas = parseTypeAnnotations(rawAnnotations,
|
||||||
|
cp,
|
||||||
|
decl,
|
||||||
|
container);
|
||||||
|
List<TypeAnnotation> l = new ArrayList<>(tas.length);
|
||||||
|
for (TypeAnnotation t : tas) {
|
||||||
|
TypeAnnotationTargetInfo ti = t.getTargetInfo();
|
||||||
|
if (ti.getTarget() == filter)
|
||||||
|
l.add(t);
|
||||||
|
}
|
||||||
|
TypeAnnotation[] typeAnnotations = l.toArray(new TypeAnnotation[0]);
|
||||||
|
return AnnotatedTypeFactory.buildAnnotatedType(type,
|
||||||
|
LocationInfo.BASE_LOCATION,
|
||||||
|
typeAnnotations,
|
||||||
|
typeAnnotations,
|
||||||
|
decl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build an array of AnnotatedTypes from the parameters supplied.
|
||||||
|
*
|
||||||
|
* This method and {@code buildAnnotatedType} are probably
|
||||||
|
* the entry points you are looking for.
|
||||||
|
*
|
||||||
|
* @param rawAnnotations the byte[] encoding of all type annotations on this declaration
|
||||||
|
* @param cp the ConstantPool needed to parse the embedded Annotation
|
||||||
|
* @param decl the declaration this type annotation is on
|
||||||
|
* @param container the Class this type annotation is on (may be the same as decl)
|
||||||
|
* @param types the Types the AnnotatedTypes corresponds to
|
||||||
|
* @param filter the type annotation targets that included in this AnnotatedType
|
||||||
|
*/
|
||||||
|
public static AnnotatedType[] buildAnnotatedTypes(byte[] rawAnnotations,
|
||||||
|
ConstantPool cp,
|
||||||
|
AnnotatedElement decl,
|
||||||
|
Class<?> container,
|
||||||
|
Type[] types,
|
||||||
|
TypeAnnotationTarget filter) {
|
||||||
|
int size = types.length;
|
||||||
|
AnnotatedType[] result = new AnnotatedType[size];
|
||||||
|
Arrays.fill(result, AnnotatedTypeFactory.EMPTY_ANNOTATED_TYPE);
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
ArrayList[] l = new ArrayList[size]; // array of ArrayList<TypeAnnotation>
|
||||||
|
|
||||||
|
TypeAnnotation[] tas = parseTypeAnnotations(rawAnnotations,
|
||||||
|
cp,
|
||||||
|
decl,
|
||||||
|
container);
|
||||||
|
for (TypeAnnotation t : tas) {
|
||||||
|
TypeAnnotationTargetInfo ti = t.getTargetInfo();
|
||||||
|
if (ti.getTarget() == filter) {
|
||||||
|
int pos = ti.getCount();
|
||||||
|
if (l[pos] == null) {
|
||||||
|
ArrayList<TypeAnnotation> tmp = new ArrayList<>(tas.length);
|
||||||
|
l[pos] = tmp;
|
||||||
|
}
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
ArrayList<TypeAnnotation> tmp = l[pos];
|
||||||
|
tmp.add(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
ArrayList<TypeAnnotation> list = l[i];
|
||||||
|
if (list != null) {
|
||||||
|
TypeAnnotation[] typeAnnotations = list.toArray(new TypeAnnotation[0]);
|
||||||
|
result[i] = AnnotatedTypeFactory.buildAnnotatedType(types[i],
|
||||||
|
LocationInfo.BASE_LOCATION,
|
||||||
|
typeAnnotations,
|
||||||
|
typeAnnotations,
|
||||||
|
decl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Class helpers
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build an AnnotatedType for the class decl's supertype.
|
||||||
|
*
|
||||||
|
* @param rawAnnotations the byte[] encoding of all type annotations on this declaration
|
||||||
|
* @param cp the ConstantPool needed to parse the embedded Annotation
|
||||||
|
* @param decl the Class which annotated supertype is being built
|
||||||
|
*/
|
||||||
|
public static AnnotatedType buildAnnotatedSuperclass(byte[] rawAnnotations,
|
||||||
|
ConstantPool cp,
|
||||||
|
Class<?> decl) {
|
||||||
|
Type supertype = decl.getGenericSuperclass();
|
||||||
|
if (supertype == null)
|
||||||
|
return AnnotatedTypeFactory.EMPTY_ANNOTATED_TYPE;
|
||||||
|
return buildAnnotatedType(rawAnnotations,
|
||||||
|
cp,
|
||||||
|
decl,
|
||||||
|
decl,
|
||||||
|
supertype,
|
||||||
|
TypeAnnotationTarget.CLASS_EXTENDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build an array of AnnotatedTypes for the class decl's implemented
|
||||||
|
* interfaces.
|
||||||
|
*
|
||||||
|
* @param rawAnnotations the byte[] encoding of all type annotations on this declaration
|
||||||
|
* @param cp the ConstantPool needed to parse the embedded Annotation
|
||||||
|
* @param decl the Class whose annotated implemented interfaces is being built
|
||||||
|
*/
|
||||||
|
public static AnnotatedType[] buildAnnotatedInterfaces(byte[] rawAnnotations,
|
||||||
|
ConstantPool cp,
|
||||||
|
Class<?> decl) {
|
||||||
|
return buildAnnotatedTypes(rawAnnotations,
|
||||||
|
cp,
|
||||||
|
decl,
|
||||||
|
decl,
|
||||||
|
decl.getGenericInterfaces(),
|
||||||
|
TypeAnnotationTarget.CLASS_IMPLEMENTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TypeVariable helpers
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse regular annotations on a TypeVariable declared on genericDecl.
|
||||||
|
*
|
||||||
|
* Regular Annotations on TypeVariables are stored in the type
|
||||||
|
* annotation byte[] in the class file.
|
||||||
|
*
|
||||||
|
* @param genericsDecl the declaration declaring the type variable
|
||||||
|
* @param typeVarIndex the 0-based index of this type variable in the declaration
|
||||||
|
*/
|
||||||
|
public static <D extends GenericDeclaration> Annotation[] parseTypeVariableAnnotations(D genericDecl,
|
||||||
|
int typeVarIndex) {
|
||||||
|
AnnotatedElement decl;
|
||||||
|
TypeAnnotationTarget predicate;
|
||||||
|
if (genericDecl instanceof Class) {
|
||||||
|
decl = (Class<?>)genericDecl;
|
||||||
|
predicate = TypeAnnotationTarget.CLASS_TYPE_PARAMETER;
|
||||||
|
} else if (genericDecl instanceof Executable) {
|
||||||
|
decl = (Executable)genericDecl;
|
||||||
|
predicate = TypeAnnotationTarget.METHOD_TYPE_PARAMETER;
|
||||||
|
} else {
|
||||||
|
throw new AssertionError("Unknown GenericDeclaration " + genericDecl + "\nthis should not happen.");
|
||||||
|
}
|
||||||
|
List<TypeAnnotation> typeVarAnnos = TypeAnnotation.filter(parseAllTypeAnnotations(decl),
|
||||||
|
predicate);
|
||||||
|
List<Annotation> res = new ArrayList<>(typeVarAnnos.size());
|
||||||
|
for (TypeAnnotation t : typeVarAnnos)
|
||||||
|
if (t.getTargetInfo().getCount() == typeVarIndex)
|
||||||
|
res.add(t.getAnnotation());
|
||||||
|
return res.toArray(new Annotation[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build an array of AnnotatedTypes for the declaration decl's bounds.
|
||||||
|
*
|
||||||
|
* @param bounds the bounds corresponding to the annotated bounds
|
||||||
|
* @param decl the declaration whose annotated bounds is being built
|
||||||
|
* @param typeVarIndex the index of this type variable on the decl
|
||||||
|
*/
|
||||||
|
public static <D extends GenericDeclaration> AnnotatedType[] parseAnnotatedBounds(Type[] bounds,
|
||||||
|
D decl,
|
||||||
|
int typeVarIndex) {
|
||||||
|
return parseAnnotatedBounds(bounds, decl, typeVarIndex, LocationInfo.BASE_LOCATION);
|
||||||
|
}
|
||||||
|
//helper for above
|
||||||
|
static <D extends GenericDeclaration> AnnotatedType[] parseAnnotatedBounds(Type[] bounds,
|
||||||
|
D decl,
|
||||||
|
int typeVarIndex,
|
||||||
|
LocationInfo loc) {
|
||||||
|
List<TypeAnnotation> candidates = fetchBounds(decl);
|
||||||
|
if (bounds != null) {
|
||||||
|
int startIndex = 0;
|
||||||
|
AnnotatedType[] res = new AnnotatedType[bounds.length];
|
||||||
|
Arrays.fill(res, AnnotatedTypeFactory.EMPTY_ANNOTATED_TYPE);
|
||||||
|
|
||||||
|
// Adjust bounds index
|
||||||
|
//
|
||||||
|
// Figure out if the type annotations for this bound starts with 0
|
||||||
|
// or 1. The spec says within a bound the 0:th type annotation will
|
||||||
|
// always be on an bound of a Class type (not Interface type). So
|
||||||
|
// if the programmer starts with an Interface type for the first
|
||||||
|
// (and following) bound(s) the implicit Object bound is considered
|
||||||
|
// the first (that is 0:th) bound and type annotations start on
|
||||||
|
// index 1.
|
||||||
|
if (bounds.length > 0) {
|
||||||
|
Type b0 = bounds[0];
|
||||||
|
if (!(b0 instanceof Class<?>)) {
|
||||||
|
startIndex = 1;
|
||||||
|
} else {
|
||||||
|
Class<?> c = (Class<?>)b0;
|
||||||
|
if (c.isInterface()) {
|
||||||
|
startIndex = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < bounds.length; i++) {
|
||||||
|
List<TypeAnnotation> l = new ArrayList<>(candidates.size());
|
||||||
|
for (TypeAnnotation t : candidates) {
|
||||||
|
TypeAnnotationTargetInfo tInfo = t.getTargetInfo();
|
||||||
|
if (tInfo.getSecondaryIndex() == i + startIndex &&
|
||||||
|
tInfo.getCount() == typeVarIndex) {
|
||||||
|
l.add(t);
|
||||||
|
}
|
||||||
|
res[i] = AnnotatedTypeFactory.buildAnnotatedType(bounds[i],
|
||||||
|
loc,
|
||||||
|
l.toArray(new TypeAnnotation[0]),
|
||||||
|
candidates.toArray(new TypeAnnotation[0]),
|
||||||
|
(AnnotatedElement)decl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return new AnnotatedType[0];
|
||||||
|
}
|
||||||
|
private static <D extends GenericDeclaration> List<TypeAnnotation> fetchBounds(D decl) {
|
||||||
|
AnnotatedElement boundsDecl;
|
||||||
|
TypeAnnotationTarget target;
|
||||||
|
if (decl instanceof Class) {
|
||||||
|
target = TypeAnnotationTarget.CLASS_PARAMETER_BOUND;
|
||||||
|
boundsDecl = (Class)decl;
|
||||||
|
} else {
|
||||||
|
target = TypeAnnotationTarget.METHOD_PARAMETER_BOUND;
|
||||||
|
boundsDecl = (Executable)decl;
|
||||||
|
}
|
||||||
|
return TypeAnnotation.filter(TypeAnnotationParser.parseAllTypeAnnotations(boundsDecl), target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse all type annotations on the declaration supplied. This is needed
|
||||||
|
* when you go from for example an annotated return type on a method that
|
||||||
|
* is a type variable declared on the class. In this case you need to
|
||||||
|
* 'jump' to the decl of the class and parse all type annotations there to
|
||||||
|
* find the ones that are applicable to the type variable.
|
||||||
|
*/
|
||||||
|
static TypeAnnotation[] parseAllTypeAnnotations(AnnotatedElement decl) {
|
||||||
|
Class<?> container;
|
||||||
|
byte[] rawBytes;
|
||||||
|
JavaLangAccess javaLangAccess = sun.misc.SharedSecrets.getJavaLangAccess();
|
||||||
|
if (decl instanceof Class) {
|
||||||
|
container = (Class<?>)decl;
|
||||||
|
rawBytes = javaLangAccess.getRawClassTypeAnnotations(container);
|
||||||
|
} else if (decl instanceof Executable) {
|
||||||
|
container = ((Executable)decl).getDeclaringClass();
|
||||||
|
rawBytes = javaLangAccess.getRawExecutableTypeAnnotations((Executable)decl);
|
||||||
|
} else {
|
||||||
|
// Should not reach here. Assert?
|
||||||
|
return EMPTY_TYPE_ANNOTATION_ARRAY;
|
||||||
|
}
|
||||||
|
return parseTypeAnnotations(rawBytes, javaLangAccess.getConstantPool(container),
|
||||||
|
decl, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse type annotations encoded as an array of bytes */
|
||||||
|
private static TypeAnnotation[] parseTypeAnnotations(byte[] rawAnnotations,
|
||||||
|
ConstantPool cp,
|
||||||
|
AnnotatedElement baseDecl,
|
||||||
|
Class<?> container) {
|
||||||
|
if (rawAnnotations == null)
|
||||||
|
return EMPTY_TYPE_ANNOTATION_ARRAY;
|
||||||
|
|
||||||
|
ByteBuffer buf = ByteBuffer.wrap(rawAnnotations);
|
||||||
|
int annotationCount = buf.getShort() & 0xFFFF;
|
||||||
|
List<TypeAnnotation> typeAnnotations = new ArrayList<>(annotationCount);
|
||||||
|
|
||||||
|
// Parse each TypeAnnotation
|
||||||
|
for (int i = 0; i < annotationCount; i++) {
|
||||||
|
TypeAnnotation ta = parseTypeAnnotation(buf, cp, baseDecl, container);
|
||||||
|
if (ta != null)
|
||||||
|
typeAnnotations.add(ta);
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeAnnotations.toArray(EMPTY_TYPE_ANNOTATION_ARRAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Helper
|
||||||
|
static Map<Class<? extends Annotation>, Annotation> mapTypeAnnotations(TypeAnnotation[] typeAnnos) {
|
||||||
|
Map<Class<? extends Annotation>, Annotation> result =
|
||||||
|
new LinkedHashMap<>();
|
||||||
|
for (TypeAnnotation t : typeAnnos) {
|
||||||
|
Annotation a = t.getAnnotation();
|
||||||
|
Class<? extends Annotation> klass = a.annotationType();
|
||||||
|
AnnotationType type = AnnotationType.getInstance(klass);
|
||||||
|
if (type.retention() == RetentionPolicy.RUNTIME)
|
||||||
|
if (result.put(klass, a) != null)
|
||||||
|
throw new AnnotationFormatError("Duplicate annotation for class: "+klass+": " + a);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Position codes
|
||||||
|
// Regular type parameter annotations
|
||||||
|
private static final byte CLASS_TYPE_PARAMETER = 0x00;
|
||||||
|
private static final byte METHOD_TYPE_PARAMETER = 0x01;
|
||||||
|
// Type Annotations outside method bodies
|
||||||
|
private static final byte CLASS_EXTENDS = 0x10;
|
||||||
|
private static final byte CLASS_TYPE_PARAMETER_BOUND = 0x11;
|
||||||
|
private static final byte METHOD_TYPE_PARAMETER_BOUND = 0x12;
|
||||||
|
private static final byte FIELD = 0x13;
|
||||||
|
private static final byte METHOD_RETURN = 0x14;
|
||||||
|
private static final byte METHOD_RECEIVER = 0x15;
|
||||||
|
private static final byte METHOD_FORMAL_PARAMETER = 0x16;
|
||||||
|
private static final byte THROWS = 0x17;
|
||||||
|
// Type Annotations inside method bodies
|
||||||
|
private static final byte LOCAL_VARIABLE = (byte)0x40;
|
||||||
|
private static final byte RESOURCE_VARIABLE = (byte)0x41;
|
||||||
|
private static final byte EXCEPTION_PARAMETER = (byte)0x42;
|
||||||
|
private static final byte CAST = (byte)0x43;
|
||||||
|
private static final byte INSTANCEOF = (byte)0x44;
|
||||||
|
private static final byte NEW = (byte)0x45;
|
||||||
|
private static final byte CONSTRUCTOR_REFERENCE_RECEIVER = (byte)0x46;
|
||||||
|
private static final byte METHOD_REFERENCE_RECEIVER = (byte)0x47;
|
||||||
|
private static final byte LAMBDA_FORMAL_PARAMETER = (byte)0x48;
|
||||||
|
private static final byte METHOD_REFERENCE = (byte)0x49;
|
||||||
|
private static final byte METHOD_REFERENCE_TYPE_ARGUMENT = (byte)0x50;
|
||||||
|
|
||||||
|
private static TypeAnnotation parseTypeAnnotation(ByteBuffer buf,
|
||||||
|
ConstantPool cp,
|
||||||
|
AnnotatedElement baseDecl,
|
||||||
|
Class<?> container) {
|
||||||
|
TypeAnnotationTargetInfo ti = parseTargetInfo(buf);
|
||||||
|
LocationInfo locationInfo = LocationInfo.parseLocationInfo(buf);
|
||||||
|
Annotation a = AnnotationParser.parseAnnotation(buf, cp, container, false);
|
||||||
|
if (ti == null) // Inside a method for example
|
||||||
|
return null;
|
||||||
|
return new TypeAnnotation(ti, locationInfo, a, baseDecl);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TypeAnnotationTargetInfo parseTargetInfo(ByteBuffer buf) {
|
||||||
|
byte posCode = buf.get();
|
||||||
|
switch(posCode) {
|
||||||
|
case CLASS_TYPE_PARAMETER:
|
||||||
|
case METHOD_TYPE_PARAMETER: {
|
||||||
|
byte index = buf.get();
|
||||||
|
TypeAnnotationTargetInfo res;
|
||||||
|
if (posCode == CLASS_TYPE_PARAMETER)
|
||||||
|
res = new TypeAnnotationTargetInfo(TypeAnnotationTarget.CLASS_TYPE_PARAMETER,
|
||||||
|
index);
|
||||||
|
else
|
||||||
|
res = new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_TYPE_PARAMETER,
|
||||||
|
index);
|
||||||
|
return res;
|
||||||
|
} // unreachable break;
|
||||||
|
case CLASS_EXTENDS: {
|
||||||
|
short index = buf.getShort();
|
||||||
|
if (index == -1) {
|
||||||
|
return new TypeAnnotationTargetInfo(TypeAnnotationTarget.CLASS_EXTENDS);
|
||||||
|
} else if (index >= 0) {
|
||||||
|
TypeAnnotationTargetInfo res = new TypeAnnotationTargetInfo(TypeAnnotationTarget.CLASS_IMPLEMENTS,
|
||||||
|
index);
|
||||||
|
return res;
|
||||||
|
}} break;
|
||||||
|
case CLASS_TYPE_PARAMETER_BOUND:
|
||||||
|
return parse2ByteTarget(TypeAnnotationTarget.CLASS_PARAMETER_BOUND, buf);
|
||||||
|
case METHOD_TYPE_PARAMETER_BOUND:
|
||||||
|
return parse2ByteTarget(TypeAnnotationTarget.METHOD_PARAMETER_BOUND, buf);
|
||||||
|
case FIELD:
|
||||||
|
return new TypeAnnotationTargetInfo(TypeAnnotationTarget.FIELD_TYPE);
|
||||||
|
case METHOD_RETURN:
|
||||||
|
return new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_RETURN_TYPE);
|
||||||
|
case METHOD_RECEIVER:
|
||||||
|
return new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_RECEIVER_TYPE);
|
||||||
|
case METHOD_FORMAL_PARAMETER: {
|
||||||
|
// Todo
|
||||||
|
byte index = buf.get();
|
||||||
|
} break;
|
||||||
|
case THROWS:
|
||||||
|
return parseShortTarget(TypeAnnotationTarget.THROWS, buf);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The ones below are inside method bodies, we don't care about them for core reflection
|
||||||
|
* other than adjusting for them in the byte stream.
|
||||||
|
*/
|
||||||
|
case LOCAL_VARIABLE:
|
||||||
|
case RESOURCE_VARIABLE:
|
||||||
|
short length = buf.getShort();
|
||||||
|
for (int i = 0; i < length; ++i) {
|
||||||
|
short offset = buf.getShort();
|
||||||
|
short varLength = buf.getShort();
|
||||||
|
short index = buf.getShort();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EXCEPTION_PARAMETER: {
|
||||||
|
byte index = buf.get();
|
||||||
|
} break;
|
||||||
|
case CAST:
|
||||||
|
case INSTANCEOF:
|
||||||
|
case NEW: {
|
||||||
|
short offset = buf.getShort();
|
||||||
|
} break;
|
||||||
|
case CONSTRUCTOR_REFERENCE_RECEIVER:
|
||||||
|
case METHOD_REFERENCE_RECEIVER: {
|
||||||
|
short offset = buf.getShort();
|
||||||
|
byte index = buf.get();
|
||||||
|
} break;
|
||||||
|
case LAMBDA_FORMAL_PARAMETER: {
|
||||||
|
byte index = buf.get();
|
||||||
|
} break;
|
||||||
|
case METHOD_REFERENCE:
|
||||||
|
// This one isn't in the spec yet
|
||||||
|
break;
|
||||||
|
case METHOD_REFERENCE_TYPE_ARGUMENT: {
|
||||||
|
short offset = buf.getShort();
|
||||||
|
byte index = buf.get();
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// will throw error below
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
throw new AnnotationFormatError("Could not parse bytes for type annotations");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TypeAnnotationTargetInfo parseShortTarget(TypeAnnotationTarget target, ByteBuffer buf) {
|
||||||
|
short index = buf.getShort();
|
||||||
|
return new TypeAnnotationTargetInfo(target, index);
|
||||||
|
}
|
||||||
|
private static TypeAnnotationTargetInfo parse2ByteTarget(TypeAnnotationTarget target, ByteBuffer buf) {
|
||||||
|
byte count = buf.get();
|
||||||
|
byte secondaryIndex = buf.get();
|
||||||
|
return new TypeAnnotationTargetInfo(target,
|
||||||
|
count,
|
||||||
|
secondaryIndex);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2013, 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,13 +25,18 @@
|
|||||||
|
|
||||||
package sun.reflect.generics.reflectiveObjects;
|
package sun.reflect.generics.reflectiveObjects;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.*;
|
||||||
|
import java.lang.reflect.AnnotatedType;
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.GenericDeclaration;
|
import java.lang.reflect.GenericDeclaration;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.lang.reflect.TypeVariable;
|
import java.lang.reflect.TypeVariable;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import sun.reflect.annotation.AnnotationSupport;
|
||||||
|
import sun.reflect.annotation.TypeAnnotationParser;
|
||||||
|
import sun.reflect.annotation.AnnotationType;
|
||||||
import sun.reflect.generics.factory.GenericsFactory;
|
import sun.reflect.generics.factory.GenericsFactory;
|
||||||
import sun.reflect.generics.tree.FieldTypeSignature;
|
import sun.reflect.generics.tree.FieldTypeSignature;
|
||||||
import sun.reflect.generics.visitor.Reifier;
|
import sun.reflect.generics.visitor.Reifier;
|
||||||
@ -182,45 +187,70 @@ public class TypeVariableImpl<D extends GenericDeclaration>
|
|||||||
return genericDeclaration.hashCode() ^ name.hashCode();
|
return genericDeclaration.hashCode() ^ name.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Currently vacuous implementations of AnnotatedElement methods.
|
// Implementations of AnnotatedElement methods.
|
||||||
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
|
@SuppressWarnings("unchecked")
|
||||||
Objects.requireNonNull(annotationClass);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
|
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
|
||||||
Objects.requireNonNull(annotationClass);
|
Objects.requireNonNull(annotationClass);
|
||||||
return null;
|
// T is an Annotation type, the return value of get will be an annotation
|
||||||
|
return (T)mapAnnotations(getAnnotations()).get(annotationClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
|
public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
|
||||||
Objects.requireNonNull(annotationClass);
|
Objects.requireNonNull(annotationClass);
|
||||||
return null;
|
return getAnnotation(annotationClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T extends Annotation> T[] getAnnotations(Class<T> annotationClass) {
|
public <T extends Annotation> T[] getAnnotations(Class<T> annotationClass) {
|
||||||
Objects.requireNonNull(annotationClass);
|
Objects.requireNonNull(annotationClass);
|
||||||
// safe because annotationClass is the class for T
|
return AnnotationSupport.getMultipleAnnotations(mapAnnotations(getAnnotations()), annotationClass);
|
||||||
return (T[])Array.newInstance(annotationClass, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass) {
|
public <T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass) {
|
||||||
Objects.requireNonNull(annotationClass);
|
Objects.requireNonNull(annotationClass);
|
||||||
// safe because annotationClass is the class for T
|
return getAnnotations(annotationClass);
|
||||||
return (T[])Array.newInstance(annotationClass, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Annotation[] getAnnotations() {
|
public Annotation[] getAnnotations() {
|
||||||
// Since zero-length, don't need defensive clone
|
int myIndex = typeVarIndex();
|
||||||
return EMPTY_ANNOTATION_ARRAY;
|
if (myIndex < 0)
|
||||||
|
throw new AssertionError("Index must be non-negative.");
|
||||||
|
return TypeAnnotationParser.parseTypeVariableAnnotations(getGenericDeclaration(), myIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Annotation[] getDeclaredAnnotations() {
|
public Annotation[] getDeclaredAnnotations() {
|
||||||
// Since zero-length, don't need defensive clone
|
return getAnnotations();
|
||||||
return EMPTY_ANNOTATION_ARRAY;
|
}
|
||||||
|
|
||||||
|
public AnnotatedType[] getAnnotatedBounds() {
|
||||||
|
return TypeAnnotationParser.parseAnnotatedBounds(getBounds(),
|
||||||
|
getGenericDeclaration(),
|
||||||
|
typeVarIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
|
private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
|
||||||
|
|
||||||
|
// Helpers for annotation methods
|
||||||
|
private int typeVarIndex() {
|
||||||
|
TypeVariable<?>[] tVars = getGenericDeclaration().getTypeParameters();
|
||||||
|
int i = -1;
|
||||||
|
for (TypeVariable<?> v : tVars) {
|
||||||
|
i++;
|
||||||
|
if (equals(v))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<Class<? extends Annotation>, Annotation> mapAnnotations(Annotation[] annos) {
|
||||||
|
Map<Class<? extends Annotation>, Annotation> result =
|
||||||
|
new LinkedHashMap<>();
|
||||||
|
for (Annotation a : annos) {
|
||||||
|
Class<? extends Annotation> klass = a.annotationType();
|
||||||
|
AnnotationType type = AnnotationType.getInstance(klass);
|
||||||
|
if (type.retention() == RetentionPolicy.RUNTIME)
|
||||||
|
if (result.put(klass, a) != null)
|
||||||
|
throw new AnnotationFormatError("Duplicate annotation for class: "+klass+": " + a);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1116,7 +1116,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
|||||||
if (privateKeyCount > 0 || secretKeyCount > 0) {
|
if (privateKeyCount > 0 || secretKeyCount > 0) {
|
||||||
|
|
||||||
if (debug != null) {
|
if (debug != null) {
|
||||||
debug.println("Storing " + privateKeyCount +
|
debug.println("Storing " + (privateKeyCount + secretKeyCount) +
|
||||||
" protected key(s) in a PKCS#7 data content-type");
|
" protected key(s) in a PKCS#7 data content-type");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2122,6 +2122,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
|||||||
SecretKeyEntry kEntry = new SecretKeyEntry();
|
SecretKeyEntry kEntry = new SecretKeyEntry();
|
||||||
kEntry.protectedSecretKey = secretValue.getOctetString();
|
kEntry.protectedSecretKey = secretValue.getOctetString();
|
||||||
bagItem = kEntry;
|
bagItem = kEntry;
|
||||||
|
secretKeyCount++;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (debug != null) {
|
if (debug != null) {
|
||||||
@ -2220,6 +2221,10 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
|||||||
if (bagItem instanceof PrivateKeyEntry) {
|
if (bagItem instanceof PrivateKeyEntry) {
|
||||||
keyList.add((PrivateKeyEntry) entry);
|
keyList.add((PrivateKeyEntry) entry);
|
||||||
}
|
}
|
||||||
|
if (entry.attributes == null) {
|
||||||
|
entry.attributes = new HashSet<>();
|
||||||
|
}
|
||||||
|
entry.attributes.addAll(attributes);
|
||||||
if (alias == null) {
|
if (alias == null) {
|
||||||
alias = getUnfriendlyName();
|
alias = getUnfriendlyName();
|
||||||
}
|
}
|
||||||
|
@ -465,6 +465,12 @@ JVM_GetClassSignature(JNIEnv *env, jclass cls);
|
|||||||
JNIEXPORT jbyteArray JNICALL
|
JNIEXPORT jbyteArray JNICALL
|
||||||
JVM_GetClassAnnotations(JNIEnv *env, jclass cls);
|
JVM_GetClassAnnotations(JNIEnv *env, jclass cls);
|
||||||
|
|
||||||
|
/* Type use annotations support (JDK 1.8) */
|
||||||
|
|
||||||
|
JNIEXPORT jbyteArray JNICALL
|
||||||
|
JVM_GetClassTypeAnnotations(JNIEnv *env, jclass cls);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* New (JDK 1.4) reflection implementation
|
* New (JDK 1.4) reflection implementation
|
||||||
*/
|
*/
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1994, 2013, 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
|
||||||
@ -75,7 +75,8 @@ static JNINativeMethod methods[] = {
|
|||||||
{"getRawAnnotations", "()" BA, (void *)&JVM_GetClassAnnotations},
|
{"getRawAnnotations", "()" BA, (void *)&JVM_GetClassAnnotations},
|
||||||
{"getConstantPool", "()" CPL, (void *)&JVM_GetClassConstantPool},
|
{"getConstantPool", "()" CPL, (void *)&JVM_GetClassConstantPool},
|
||||||
{"desiredAssertionStatus0","("CLS")Z",(void *)&JVM_DesiredAssertionStatus},
|
{"desiredAssertionStatus0","("CLS")Z",(void *)&JVM_DesiredAssertionStatus},
|
||||||
{"getEnclosingMethod0", "()[" OBJ, (void *)&JVM_GetEnclosingMethodInfo}
|
{"getEnclosingMethod0", "()[" OBJ, (void *)&JVM_GetEnclosingMethodInfo},
|
||||||
|
{"getRawTypeAnnotations", "()" BA, (void *)&JVM_GetClassTypeAnnotations},
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef OBJ
|
#undef OBJ
|
||||||
|
@ -191,17 +191,6 @@ static int closefd(int fd1, int fd2) {
|
|||||||
pthread_mutex_lock(&(fdEntry->lock));
|
pthread_mutex_lock(&(fdEntry->lock));
|
||||||
|
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* Send a wakeup signal to all threads blocked on this
|
|
||||||
* file descriptor.
|
|
||||||
*/
|
|
||||||
threadEntry_t *curr = fdEntry->threads;
|
|
||||||
while (curr != NULL) {
|
|
||||||
curr->intr = 1;
|
|
||||||
pthread_kill( curr->thr, sigWakeup );
|
|
||||||
curr = curr->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* And close/dup the file descriptor
|
* And close/dup the file descriptor
|
||||||
* (restart if interrupted by signal)
|
* (restart if interrupted by signal)
|
||||||
@ -214,6 +203,16 @@ static int closefd(int fd1, int fd2) {
|
|||||||
}
|
}
|
||||||
} while (rv == -1 && errno == EINTR);
|
} while (rv == -1 && errno == EINTR);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send a wakeup signal to all threads blocked on this
|
||||||
|
* file descriptor.
|
||||||
|
*/
|
||||||
|
threadEntry_t *curr = fdEntry->threads;
|
||||||
|
while (curr != NULL) {
|
||||||
|
curr->intr = 1;
|
||||||
|
pthread_kill( curr->thr, sigWakeup );
|
||||||
|
curr = curr->next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2013, 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
|
||||||
@ -104,6 +104,11 @@ static char* next_arg(char* cmdline, char* arg, jboolean* wildcard) {
|
|||||||
|
|
||||||
case ' ':
|
case ' ':
|
||||||
case '\t':
|
case '\t':
|
||||||
|
if (prev == '\\') {
|
||||||
|
for (i = 0 ; i < slashes; i++) {
|
||||||
|
*dest++ = prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (quotes % 2 == 1) {
|
if (quotes % 2 == 1) {
|
||||||
*dest++ = ch;
|
*dest++ = ch;
|
||||||
} else {
|
} else {
|
||||||
@ -591,6 +596,12 @@ int main(int argc, char* argv[]) {
|
|||||||
// v->disable();
|
// v->disable();
|
||||||
vectors[i++] = v;
|
vectors[i++] = v;
|
||||||
|
|
||||||
|
v= new Vector(argv[0], "a b\\\\ d");
|
||||||
|
v->add("a", FALSE);
|
||||||
|
v->add("b\\\\", FALSE);
|
||||||
|
v->add("d", FALSE);
|
||||||
|
vectors[i++] = v;
|
||||||
|
|
||||||
dotest(vectors);
|
dotest(vectors);
|
||||||
printf("All tests pass [%d]\n", i);
|
printf("All tests pass [%d]\n", i);
|
||||||
doexit(0);
|
doexit(0);
|
||||||
|
@ -321,12 +321,12 @@ sun/jvmstat/monitor/MonitoredVm/CR6672135.java generic-all
|
|||||||
tools/pack200/CommandLineTests.java generic-all
|
tools/pack200/CommandLineTests.java generic-all
|
||||||
tools/pack200/Pack200Test.java generic-all
|
tools/pack200/Pack200Test.java generic-all
|
||||||
|
|
||||||
# 8001163
|
|
||||||
tools/pack200/AttributeTests.java generic-all
|
|
||||||
|
|
||||||
# 7150569
|
# 7150569
|
||||||
tools/launcher/UnicodeTest.java macosx-all
|
tools/launcher/UnicodeTest.java macosx-all
|
||||||
|
|
||||||
|
# 8007410
|
||||||
|
tools/launcher/FXLauncherTest.java linux-all
|
||||||
|
|
||||||
############################################################################
|
############################################################################
|
||||||
|
|
||||||
# jdk_jdi
|
# jdk_jdi
|
||||||
|
428
jdk/test/java/lang/annotation/TypeAnnotationReflection.java
Normal file
428
jdk/test/java/lang/annotation/TypeAnnotationReflection.java
Normal file
@ -0,0 +1,428 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013, 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 8004698
|
||||||
|
* @summary Unit test for type annotations
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class TypeAnnotationReflection {
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
testSuper();
|
||||||
|
testInterfaces();
|
||||||
|
testReturnType();
|
||||||
|
testNested();
|
||||||
|
testArray();
|
||||||
|
testRunException();
|
||||||
|
testClassTypeVarBounds();
|
||||||
|
testMethodTypeVarBounds();
|
||||||
|
testFields();
|
||||||
|
testClassTypeVar();
|
||||||
|
testMethodTypeVar();
|
||||||
|
testParameterizedType();
|
||||||
|
testNestedParameterizedType();
|
||||||
|
testWildcardType();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void check(boolean b) {
|
||||||
|
if (!b)
|
||||||
|
throw new RuntimeException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testSuper() throws Exception {
|
||||||
|
check(Object.class.getAnnotatedSuperclass().getAnnotations().length == 0);
|
||||||
|
check(Class.class.getAnnotatedSuperclass().getAnnotations().length == 0);
|
||||||
|
|
||||||
|
AnnotatedType a;
|
||||||
|
a = TestClassArray.class.getAnnotatedSuperclass();
|
||||||
|
Annotation[] annos = a.getAnnotations();
|
||||||
|
check(annos.length == 2);
|
||||||
|
check(annos[0].annotationType().equals(TypeAnno.class));
|
||||||
|
check(annos[1].annotationType().equals(TypeAnno2.class));
|
||||||
|
check(((TypeAnno)annos[0]).value().equals("extends"));
|
||||||
|
check(((TypeAnno2)annos[1]).value().equals("extends2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testInterfaces() throws Exception {
|
||||||
|
AnnotatedType[] as;
|
||||||
|
as = TestClassArray.class.getAnnotatedInterfaces();
|
||||||
|
check(as.length == 3);
|
||||||
|
check(as[1].getAnnotations().length == 0);
|
||||||
|
|
||||||
|
Annotation[] annos;
|
||||||
|
annos = as[0].getAnnotations();
|
||||||
|
check(annos.length == 2);
|
||||||
|
check(annos[0].annotationType().equals(TypeAnno.class));
|
||||||
|
check(annos[1].annotationType().equals(TypeAnno2.class));
|
||||||
|
check(((TypeAnno)annos[0]).value().equals("implements serializable"));
|
||||||
|
check(((TypeAnno2)annos[1]).value().equals("implements2 serializable"));
|
||||||
|
|
||||||
|
annos = as[2].getAnnotations();
|
||||||
|
check(annos.length == 2);
|
||||||
|
check(annos[0].annotationType().equals(TypeAnno.class));
|
||||||
|
check(annos[1].annotationType().equals(TypeAnno2.class));
|
||||||
|
check(((TypeAnno)annos[0]).value().equals("implements cloneable"));
|
||||||
|
check(((TypeAnno2)annos[1]).value().equals("implements2 cloneable"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testReturnType() throws Exception {
|
||||||
|
Method m = TestClassArray.class.getDeclaredMethod("foo", (Class<?>[])null);
|
||||||
|
Annotation[] annos = m.getAnnotatedReturnType().getAnnotations();
|
||||||
|
check(annos.length == 1);
|
||||||
|
check(annos[0].annotationType().equals(TypeAnno.class));
|
||||||
|
check(((TypeAnno)annos[0]).value().equals("return1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testNested() throws Exception {
|
||||||
|
Method m = TestClassNested.class.getDeclaredMethod("foo", (Class<?>[])null);
|
||||||
|
Annotation[] annos = m.getAnnotatedReturnType().getAnnotations();
|
||||||
|
check(annos.length == 1);
|
||||||
|
check(annos[0].annotationType().equals(TypeAnno.class));
|
||||||
|
check(((TypeAnno)annos[0]).value().equals("array"));
|
||||||
|
|
||||||
|
AnnotatedType t = m.getAnnotatedReturnType();
|
||||||
|
t = ((AnnotatedArrayType)t).getAnnotatedGenericComponentType();
|
||||||
|
annos = t.getAnnotations();
|
||||||
|
check(annos.length == 1);
|
||||||
|
check(annos[0].annotationType().equals(TypeAnno.class));
|
||||||
|
check(((TypeAnno)annos[0]).value().equals("Inner"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testArray() throws Exception {
|
||||||
|
Method m = TestClassArray.class.getDeclaredMethod("foo", (Class<?>[])null);
|
||||||
|
AnnotatedArrayType t = (AnnotatedArrayType) m.getAnnotatedReturnType();
|
||||||
|
Annotation[] annos = t.getAnnotations();
|
||||||
|
check(annos.length == 1);
|
||||||
|
check(annos[0].annotationType().equals(TypeAnno.class));
|
||||||
|
check(((TypeAnno)annos[0]).value().equals("return1"));
|
||||||
|
|
||||||
|
t = (AnnotatedArrayType)t.getAnnotatedGenericComponentType();
|
||||||
|
annos = t.getAnnotations();
|
||||||
|
check(annos.length == 0);
|
||||||
|
|
||||||
|
t = (AnnotatedArrayType)t.getAnnotatedGenericComponentType();
|
||||||
|
annos = t.getAnnotations();
|
||||||
|
check(annos.length == 1);
|
||||||
|
check(annos[0].annotationType().equals(TypeAnno.class));
|
||||||
|
check(((TypeAnno)annos[0]).value().equals("return3"));
|
||||||
|
|
||||||
|
AnnotatedType tt = t.getAnnotatedGenericComponentType();
|
||||||
|
check(!(tt instanceof AnnotatedArrayType));
|
||||||
|
annos = tt.getAnnotations();
|
||||||
|
check(annos.length == 1);
|
||||||
|
check(annos[0].annotationType().equals(TypeAnno.class));
|
||||||
|
check(((TypeAnno)annos[0]).value().equals("return4"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testRunException() throws Exception {
|
||||||
|
Method m = TestClassException.class.getDeclaredMethod("foo", (Class<?>[])null);
|
||||||
|
AnnotatedType[] ts = m.getAnnotatedExceptionTypes();
|
||||||
|
check(ts.length == 3);
|
||||||
|
|
||||||
|
AnnotatedType t;
|
||||||
|
Annotation[] annos;
|
||||||
|
t = ts[0];
|
||||||
|
annos = t.getAnnotations();
|
||||||
|
check(annos.length == 2);
|
||||||
|
check(annos[0].annotationType().equals(TypeAnno.class));
|
||||||
|
check(annos[1].annotationType().equals(TypeAnno2.class));
|
||||||
|
check(((TypeAnno)annos[0]).value().equals("RE"));
|
||||||
|
check(((TypeAnno2)annos[1]).value().equals("RE2"));
|
||||||
|
|
||||||
|
t = ts[1];
|
||||||
|
annos = t.getAnnotations();
|
||||||
|
check(annos.length == 0);
|
||||||
|
|
||||||
|
t = ts[2];
|
||||||
|
annos = t.getAnnotations();
|
||||||
|
check(annos.length == 1);
|
||||||
|
check(annos[0].annotationType().equals(TypeAnno.class));
|
||||||
|
check(((TypeAnno)annos[0]).value().equals("AIOOBE"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testClassTypeVarBounds() throws Exception {
|
||||||
|
Method m = TestClassTypeVarAndField.class.getDeclaredMethod("foo", (Class<?>[])null);
|
||||||
|
AnnotatedType ret = m.getAnnotatedReturnType();
|
||||||
|
Annotation[] annos = ret.getAnnotations();
|
||||||
|
check(annos.length == 2);
|
||||||
|
|
||||||
|
AnnotatedType[] annotatedBounds = ((AnnotatedTypeVariable)ret).getAnnotatedBounds();
|
||||||
|
check(annotatedBounds.length == 2);
|
||||||
|
|
||||||
|
annos = annotatedBounds[0].getAnnotations();
|
||||||
|
check(annos.length == 1);
|
||||||
|
check(annos[0].annotationType().equals(TypeAnno.class));
|
||||||
|
check(((TypeAnno)annos[0]).value().equals("Object1"));
|
||||||
|
|
||||||
|
annos = annotatedBounds[1].getAnnotations();
|
||||||
|
check(annos.length == 2);
|
||||||
|
check(annos[0].annotationType().equals(TypeAnno.class));
|
||||||
|
check(annos[1].annotationType().equals(TypeAnno2.class));
|
||||||
|
check(((TypeAnno)annos[0]).value().equals("Runnable1"));
|
||||||
|
check(((TypeAnno2)annos[1]).value().equals("Runnable2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testMethodTypeVarBounds() throws Exception {
|
||||||
|
Method m2 = TestClassTypeVarAndField.class.getDeclaredMethod("foo2", (Class<?>[])null);
|
||||||
|
AnnotatedType ret2 = m2.getAnnotatedReturnType();
|
||||||
|
AnnotatedType[] annotatedBounds2 = ((AnnotatedTypeVariable)ret2).getAnnotatedBounds();
|
||||||
|
check(annotatedBounds2.length == 1);
|
||||||
|
|
||||||
|
Annotation[] annos = annotatedBounds2[0].getAnnotations();
|
||||||
|
check(annos.length == 1);
|
||||||
|
check(annos[0].annotationType().equals(TypeAnno.class));
|
||||||
|
check(((TypeAnno)annos[0]).value().equals("M Runnable"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testFields() throws Exception {
|
||||||
|
Field f1 = TestClassTypeVarAndField.class.getDeclaredField("field1");
|
||||||
|
AnnotatedType at;
|
||||||
|
Annotation[] annos;
|
||||||
|
|
||||||
|
at = f1.getAnnotatedType();
|
||||||
|
annos = at.getAnnotations();
|
||||||
|
check(annos.length == 2);
|
||||||
|
check(annos[0].annotationType().equals(TypeAnno.class));
|
||||||
|
check(annos[1].annotationType().equals(TypeAnno2.class));
|
||||||
|
check(((TypeAnno)annos[0]).value().equals("T1 field"));
|
||||||
|
check(((TypeAnno2)annos[1]).value().equals("T2 field"));
|
||||||
|
|
||||||
|
Field f2 = TestClassTypeVarAndField.class.getDeclaredField("field2");
|
||||||
|
at = f2.getAnnotatedType();
|
||||||
|
annos = at.getAnnotations();
|
||||||
|
check(annos.length == 0);
|
||||||
|
|
||||||
|
Field f3 = TestClassTypeVarAndField.class.getDeclaredField("field3");
|
||||||
|
at = f3.getAnnotatedType();
|
||||||
|
annos = at.getAnnotations();
|
||||||
|
check(annos.length == 1);
|
||||||
|
check(annos[0].annotationType().equals(TypeAnno.class));
|
||||||
|
check(((TypeAnno)annos[0]).value().equals("Object field"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testClassTypeVar() throws Exception {
|
||||||
|
TypeVariable[] typeVars = TestClassTypeVarAndField.class.getTypeParameters();
|
||||||
|
Annotation[] annos;
|
||||||
|
check(typeVars.length == 2);
|
||||||
|
|
||||||
|
// First TypeVar
|
||||||
|
AnnotatedType[] annotatedBounds = typeVars[0].getAnnotatedBounds();
|
||||||
|
check(annotatedBounds.length == 2);
|
||||||
|
|
||||||
|
annos = annotatedBounds[0].getAnnotations();
|
||||||
|
check(annos.length == 1);
|
||||||
|
check(annos[0].annotationType().equals(TypeAnno.class));
|
||||||
|
check(((TypeAnno)annos[0]).value().equals("Object1"));
|
||||||
|
|
||||||
|
annos = annotatedBounds[1].getAnnotations();
|
||||||
|
check(annos.length == 2);
|
||||||
|
check(annos[0].annotationType().equals(TypeAnno.class));
|
||||||
|
check(annos[1].annotationType().equals(TypeAnno2.class));
|
||||||
|
check(((TypeAnno)annos[0]).value().equals("Runnable1"));
|
||||||
|
check(((TypeAnno2)annos[1]).value().equals("Runnable2"));
|
||||||
|
|
||||||
|
// second TypeVar regular anno
|
||||||
|
Annotation[] regularAnnos = typeVars[1].getAnnotations();
|
||||||
|
check(regularAnnos.length == 1);
|
||||||
|
check(typeVars[1].getAnnotation(TypeAnno.class).value().equals("EE"));
|
||||||
|
|
||||||
|
// second TypeVar
|
||||||
|
annotatedBounds = typeVars[1].getAnnotatedBounds();
|
||||||
|
check(annotatedBounds.length == 1);
|
||||||
|
|
||||||
|
annos = annotatedBounds[0].getAnnotations();
|
||||||
|
check(annos.length == 1);
|
||||||
|
check(annos[0].annotationType().equals(TypeAnno2.class));
|
||||||
|
check(((TypeAnno2)annos[0]).value().equals("EEBound"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testMethodTypeVar() throws Exception {
|
||||||
|
Method m2 = TestClassTypeVarAndField.class.getDeclaredMethod("foo2", (Class<?>[])null);
|
||||||
|
TypeVariable[] t = m2.getTypeParameters();
|
||||||
|
check(t.length == 1);
|
||||||
|
Annotation[] annos = t[0].getAnnotations();
|
||||||
|
check(annos.length == 0);
|
||||||
|
|
||||||
|
AnnotatedType[] annotatedBounds2 = t[0].getAnnotatedBounds();
|
||||||
|
check(annotatedBounds2.length == 1);
|
||||||
|
|
||||||
|
annos = annotatedBounds2[0].getAnnotations();
|
||||||
|
check(annos.length == 1);
|
||||||
|
check(annos[0].annotationType().equals(TypeAnno.class));
|
||||||
|
check(((TypeAnno)annos[0]).value().equals("M Runnable"));
|
||||||
|
|
||||||
|
// Second method
|
||||||
|
m2 = TestClassTypeVarAndField.class.getDeclaredMethod("foo3", (Class<?>[])null);
|
||||||
|
t = m2.getTypeParameters();
|
||||||
|
check(t.length == 1);
|
||||||
|
annos = t[0].getAnnotations();
|
||||||
|
check(annos.length == 1);
|
||||||
|
check(annos[0].annotationType().equals(TypeAnno.class));
|
||||||
|
check(((TypeAnno)annos[0]).value().equals("K"));
|
||||||
|
|
||||||
|
annotatedBounds2 = t[0].getAnnotatedBounds();
|
||||||
|
check(annotatedBounds2.length == 1);
|
||||||
|
|
||||||
|
annos = annotatedBounds2[0].getAnnotations();
|
||||||
|
check(annos.length == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testParameterizedType() {
|
||||||
|
// Base
|
||||||
|
AnnotatedType[] as;
|
||||||
|
as = TestParameterizedType.class.getAnnotatedInterfaces();
|
||||||
|
check(as.length == 1);
|
||||||
|
check(as[0].getAnnotations().length == 1);
|
||||||
|
check(as[0].getAnnotation(TypeAnno.class).value().equals("M"));
|
||||||
|
|
||||||
|
Annotation[] annos;
|
||||||
|
as = ((AnnotatedParameterizedType)as[0]).getAnnotatedActualTypeArguments();
|
||||||
|
check(as.length == 2);
|
||||||
|
annos = as[0].getAnnotations();
|
||||||
|
check(annos.length == 1);
|
||||||
|
check(as[0].getAnnotation(TypeAnno.class).value().equals("S"));
|
||||||
|
check(as[0].getAnnotation(TypeAnno2.class) == null);
|
||||||
|
|
||||||
|
annos = as[1].getAnnotations();
|
||||||
|
check(annos.length == 2);
|
||||||
|
check(((TypeAnno)annos[0]).value().equals("I"));
|
||||||
|
check(as[1].getAnnotation(TypeAnno2.class).value().equals("I2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testNestedParameterizedType() throws Exception {
|
||||||
|
Method m = TestParameterizedType.class.getDeclaredMethod("foo2", (Class<?>[])null);
|
||||||
|
AnnotatedType ret = m.getAnnotatedReturnType();
|
||||||
|
Annotation[] annos;
|
||||||
|
annos = ret.getAnnotations();
|
||||||
|
check(annos.length == 1);
|
||||||
|
check(((TypeAnno)annos[0]).value().equals("I"));
|
||||||
|
|
||||||
|
AnnotatedType[] args = ((AnnotatedParameterizedType)ret).getAnnotatedActualTypeArguments();
|
||||||
|
check(args.length == 1);
|
||||||
|
annos = args[0].getAnnotations();
|
||||||
|
check(annos.length == 2);
|
||||||
|
check(((TypeAnno)annos[0]).value().equals("I1"));
|
||||||
|
check(args[0].getAnnotation(TypeAnno2.class).value().equals("I2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testWildcardType() throws Exception {
|
||||||
|
Method m = TestWildcardType.class.getDeclaredMethod("foo", (Class<?>[])null);
|
||||||
|
AnnotatedType ret = m.getAnnotatedReturnType();
|
||||||
|
AnnotatedType[] t;
|
||||||
|
t = ((AnnotatedParameterizedType)ret).getAnnotatedActualTypeArguments();
|
||||||
|
check(t.length == 1);
|
||||||
|
ret = t[0];
|
||||||
|
|
||||||
|
Field f = TestWildcardType.class.getDeclaredField("f1");
|
||||||
|
AnnotatedWildcardType w = (AnnotatedWildcardType)((AnnotatedParameterizedType)f
|
||||||
|
.getAnnotatedType()).getAnnotatedActualTypeArguments()[0];
|
||||||
|
t = w.getAnnotatedLowerBounds();
|
||||||
|
check(t.length == 0);
|
||||||
|
t = w.getAnnotatedUpperBounds();
|
||||||
|
check(t.length == 1);
|
||||||
|
Annotation[] annos;
|
||||||
|
annos = t[0].getAnnotations();
|
||||||
|
check(annos.length == 1);
|
||||||
|
check(((TypeAnno)annos[0]).value().equals("2"));
|
||||||
|
|
||||||
|
f = TestWildcardType.class.getDeclaredField("f2");
|
||||||
|
w = (AnnotatedWildcardType)((AnnotatedParameterizedType)f
|
||||||
|
.getAnnotatedType()).getAnnotatedActualTypeArguments()[0];
|
||||||
|
t = w.getAnnotatedUpperBounds();
|
||||||
|
check(t.length == 0);
|
||||||
|
t = w.getAnnotatedLowerBounds();
|
||||||
|
check(t.length == 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class TestWildcardType {
|
||||||
|
public <T> List<? super T> foo() { return null;}
|
||||||
|
public Class<@TypeAnno("1") ? extends @TypeAnno("2") Annotation> f1;
|
||||||
|
public Class<@TypeAnno("3") ? super @TypeAnno("4") Annotation> f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class TestParameterizedType implements @TypeAnno("M") Map<@TypeAnno("S")String, @TypeAnno("I") @TypeAnno2("I2")Integer> {
|
||||||
|
public ParameterizedOuter<String>.ParameterizedInner<Integer> foo() {return null;}
|
||||||
|
public @TypeAnno("O") ParameterizedOuter<@TypeAnno("S1") @TypeAnno2("S2") String>.
|
||||||
|
@TypeAnno("I") ParameterizedInner<@TypeAnno("I1") @TypeAnno2("I2")Integer> foo2() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ParameterizedOuter <T> {
|
||||||
|
class ParameterizedInner <U> {}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class TestClassArray extends @TypeAnno("extends") @TypeAnno2("extends2") Object
|
||||||
|
implements @TypeAnno("implements serializable") @TypeAnno2("implements2 serializable") Serializable,
|
||||||
|
Readable,
|
||||||
|
@TypeAnno("implements cloneable") @TypeAnno2("implements2 cloneable") Cloneable {
|
||||||
|
public @TypeAnno("return4") Object @TypeAnno("return1") [][] @TypeAnno("return3")[] foo() { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class TestClassNested {
|
||||||
|
public @TypeAnno("Outer") Outer.@TypeAnno("Inner")Inner @TypeAnno("array")[] foo() { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
class Outer {
|
||||||
|
class Inner {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class TestClassException {
|
||||||
|
public Object foo() throws @TypeAnno("RE") @TypeAnno2("RE2") RuntimeException,
|
||||||
|
NullPointerException,
|
||||||
|
@TypeAnno("AIOOBE") ArrayIndexOutOfBoundsException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class TestClassTypeVarAndField <T extends @TypeAnno("Object1") Object
|
||||||
|
& @TypeAnno("Runnable1") @TypeAnno2("Runnable2") Runnable,
|
||||||
|
@TypeAnno("EE")EE extends @TypeAnno2("EEBound") Runnable > {
|
||||||
|
@TypeAnno("T1 field") @TypeAnno2("T2 field") T field1;
|
||||||
|
T field2;
|
||||||
|
@TypeAnno("Object field") Object field3;
|
||||||
|
|
||||||
|
public @TypeAnno("t1") @TypeAnno2("t2") T foo(){ return null; }
|
||||||
|
public <M extends @TypeAnno("M Runnable") Runnable> M foo2() {return null;}
|
||||||
|
public <@TypeAnno("K") K extends Cloneable> K foo3() {return null;}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Target(ElementType.TYPE_USE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@interface TypeAnno {
|
||||||
|
String value();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Target(ElementType.TYPE_USE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@interface TypeAnno2 {
|
||||||
|
String value();
|
||||||
|
}
|
120
jdk/test/java/lang/annotation/TypeParamAnnotation.java
Normal file
120
jdk/test/java/lang/annotation/TypeParamAnnotation.java
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013, 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 8004698
|
||||||
|
* @summary Unit test for annotations on TypeVariables
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class TypeParamAnnotation {
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
testOnClass();
|
||||||
|
testOnMethod();
|
||||||
|
testGetAnno();
|
||||||
|
testGetAnnos();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void check(boolean b) {
|
||||||
|
if (!b)
|
||||||
|
throw new RuntimeException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testOnClass() {
|
||||||
|
TypeVariable<?>[] ts = TypeParam.class.getTypeParameters();
|
||||||
|
check(ts.length == 3);
|
||||||
|
|
||||||
|
Annotation[] as;
|
||||||
|
|
||||||
|
as = ts[0].getAnnotations();
|
||||||
|
check(as.length == 2);
|
||||||
|
check(((ParamAnno)as[0]).value().equals("t"));
|
||||||
|
check(((ParamAnno2)as[1]).value() == 1);
|
||||||
|
|
||||||
|
as = ts[1].getAnnotations();
|
||||||
|
check(as.length == 0);
|
||||||
|
|
||||||
|
as = ts[2].getAnnotations();
|
||||||
|
check(as.length == 2);
|
||||||
|
check(((ParamAnno)as[0]).value().equals("v"));
|
||||||
|
check(((ParamAnno2)as[1]).value() == 2);
|
||||||
|
}
|
||||||
|
private static void testOnMethod() throws Exception {
|
||||||
|
TypeVariable<?>[] ts = TypeParam.class.getDeclaredMethod("foo").getTypeParameters();
|
||||||
|
check(ts.length == 3);
|
||||||
|
|
||||||
|
Annotation[] as;
|
||||||
|
|
||||||
|
as = ts[0].getAnnotations();
|
||||||
|
check(as.length == 2);
|
||||||
|
check(((ParamAnno)as[0]).value().equals("x"));
|
||||||
|
check(((ParamAnno2)as[1]).value() == 3);
|
||||||
|
|
||||||
|
as = ts[1].getAnnotations();
|
||||||
|
check(as.length == 0);
|
||||||
|
|
||||||
|
as = ts[2].getAnnotations();
|
||||||
|
check(as.length == 2);
|
||||||
|
check(((ParamAnno)as[0]).value().equals("z"));
|
||||||
|
check(((ParamAnno2)as[1]).value() == 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testGetAnno() {
|
||||||
|
TypeVariable<?>[] ts = TypeParam.class.getTypeParameters();
|
||||||
|
ParamAnno a;
|
||||||
|
a = ts[0].getAnnotation(ParamAnno.class);
|
||||||
|
check(a.value().equals("t"));
|
||||||
|
}
|
||||||
|
private static void testGetAnnos() throws Exception {
|
||||||
|
TypeVariable<?>[] ts = TypeParam.class.getDeclaredMethod("foo").getTypeParameters();
|
||||||
|
ParamAnno2[] as;
|
||||||
|
as = ts[0].getAnnotations(ParamAnno2.class);
|
||||||
|
check(as.length == 1);
|
||||||
|
check(as[0].value() == 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TypeParam <@ParamAnno("t") @ParamAnno2(1) T,
|
||||||
|
U,
|
||||||
|
@ParamAnno("v") @ParamAnno2(2) V extends Runnable> {
|
||||||
|
public <@ParamAnno("x") @ParamAnno2(3) X,
|
||||||
|
Y,
|
||||||
|
@ParamAnno("z") @ParamAnno2(4) Z extends Cloneable> void foo() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Target(ElementType.TYPE_PARAMETER)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@interface ParamAnno {
|
||||||
|
String value();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Target(ElementType.TYPE_PARAMETER)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@interface ParamAnno2 {
|
||||||
|
int value();
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2013, 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 7154390
|
* @bug 7154390 8005712
|
||||||
* @summary Unit test for repeated annotation reflection
|
* @summary Unit test for repeated annotation reflection
|
||||||
*
|
*
|
||||||
* @compile RepeatedUnitTest.java subpackage/package-info.java subpackage/Container.java subpackage/Containee.java subpackage/NonRepeated.java subpackage/InheritedContainee.java subpackage/InheritedContainer.java subpackage/InheritedNonRepeated.java
|
* @compile RepeatedUnitTest.java subpackage/package-info.java subpackage/Container.java subpackage/Containee.java subpackage/NonRepeated.java subpackage/InheritedContainee.java subpackage/InheritedContainer.java subpackage/InheritedNonRepeated.java
|
||||||
@ -58,7 +58,7 @@ public class RepeatedUnitTest {
|
|||||||
checkMultiplier(Me1.class.getField("foo"), 1);
|
checkMultiplier(Me1.class.getField("foo"), 1);
|
||||||
|
|
||||||
// METHOD
|
// METHOD
|
||||||
checkMultiplier(Me1.class.getDeclaredMethod("mee", null), 100);
|
checkMultiplier(Me1.class.getDeclaredMethod("mee", (Class<?>[])null), 100);
|
||||||
|
|
||||||
// INNER CLASS
|
// INNER CLASS
|
||||||
checkMultiplier(Me1.MiniMee.class, 1000);
|
checkMultiplier(Me1.MiniMee.class, 1000);
|
||||||
@ -84,8 +84,7 @@ public class RepeatedUnitTest {
|
|||||||
|
|
||||||
static void packageRepeated(AnnotatedElement e) {
|
static void packageRepeated(AnnotatedElement e) {
|
||||||
Containee c = e.getAnnotation(Containee.class);
|
Containee c = e.getAnnotation(Containee.class);
|
||||||
check(c.value() == 1);
|
check(c == null);
|
||||||
|
|
||||||
check(2 == countAnnotation(e, Containee.class));
|
check(2 == countAnnotation(e, Containee.class));
|
||||||
|
|
||||||
c = e.getAnnotations(Containee.class)[0];
|
c = e.getAnnotations(Containee.class)[0];
|
||||||
@ -93,7 +92,7 @@ public class RepeatedUnitTest {
|
|||||||
c = e.getAnnotations(Containee.class)[1];
|
c = e.getAnnotations(Containee.class)[1];
|
||||||
check(c.value() == 2);
|
check(c.value() == 2);
|
||||||
|
|
||||||
check(2 == containsAnnotationOfType(e.getAnnotations(), Containee.class));
|
check(0 == containsAnnotationOfType(e.getAnnotations(), Containee.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void packageContainer(AnnotatedElement e) {
|
static void packageContainer(AnnotatedElement e) {
|
||||||
@ -161,14 +160,26 @@ public class RepeatedUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void checkMultiplier(AnnotatedElement e, int m) {
|
static void checkMultiplier(AnnotatedElement e, int m) {
|
||||||
|
// Basic sanity of non-repeating getAnnotation(Class)
|
||||||
check(e.getAnnotation(NonRepeated.class).value() == 5 * m);
|
check(e.getAnnotation(NonRepeated.class).value() == 5 * m);
|
||||||
|
|
||||||
|
// Check count of annotations returned from getAnnotations(Class)
|
||||||
check(4 == countAnnotation(e, Containee.class));
|
check(4 == countAnnotation(e, Containee.class));
|
||||||
check(1 == countAnnotation(e, Container.class));
|
check(1 == countAnnotation(e, Container.class));
|
||||||
check(1 == countAnnotation(e, NonRepeated.class));
|
check(1 == countAnnotation(e, NonRepeated.class));
|
||||||
|
|
||||||
|
// Check contents of array returned from getAnnotations(Class)
|
||||||
check(e.getAnnotations(Containee.class)[2].value() == 3 * m);
|
check(e.getAnnotations(Containee.class)[2].value() == 3 * m);
|
||||||
check(e.getAnnotations(NonRepeated.class)[0].value() == 5 * m);
|
check(e.getAnnotations(NonRepeated.class)[0].value() == 5 * m);
|
||||||
|
|
||||||
|
// Check getAnnotation(Class)
|
||||||
|
check(e.getAnnotation(Containee.class) == null);
|
||||||
|
check(e.getAnnotation(Container.class) != null);
|
||||||
|
|
||||||
|
// Check count of annotations returned from getAnnotations()
|
||||||
|
check(0 == containsAnnotationOfType(e.getAnnotations(), Containee.class));
|
||||||
|
check(1 == containsAnnotationOfType(e.getAnnotations(), Container.class));
|
||||||
|
check(1 == containsAnnotationOfType(e.getAnnotations(), NonRepeated.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check(Boolean b) {
|
static void check(Boolean b) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2013, 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
|
||||||
@ -26,7 +26,6 @@ package subpackage;
|
|||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@ContainedBy(Container.class)
|
|
||||||
@Repeatable(Container.class)
|
@Repeatable(Container.class)
|
||||||
public @interface Containee {
|
public @interface Containee {
|
||||||
int value();
|
int value();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2013, 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
|
||||||
@ -26,7 +26,6 @@ package subpackage;
|
|||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@ContainerFor(Containee.class)
|
|
||||||
public @interface Container {
|
public @interface Container {
|
||||||
Containee[] value();
|
Containee[] value();
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2013, 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
|
||||||
@ -27,7 +27,6 @@ import java.lang.annotation.*;
|
|||||||
|
|
||||||
@Inherited
|
@Inherited
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@ContainedBy(InheritedContainer.class)
|
|
||||||
@Repeatable(InheritedContainer.class)
|
@Repeatable(InheritedContainer.class)
|
||||||
public @interface InheritedContainee {
|
public @interface InheritedContainee {
|
||||||
int value();
|
int value();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2013, 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
|
||||||
@ -27,7 +27,6 @@ import java.lang.annotation.*;
|
|||||||
|
|
||||||
@Inherited
|
@Inherited
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@ContainerFor(InheritedContainee.class)
|
|
||||||
public @interface InheritedContainer {
|
public @interface InheritedContainer {
|
||||||
InheritedContainee[] value();
|
InheritedContainee[] value();
|
||||||
}
|
}
|
||||||
|
@ -23,163 +23,152 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
|
* @bug 8004729
|
||||||
* @summary javac should generate method parameters correctly.
|
* @summary javac should generate method parameters correctly.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.lang.*;
|
import java.lang.*;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
|
import java.lang.annotation.*;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static java.lang.annotation.ElementType.*;
|
||||||
|
|
||||||
public class WithoutParameters {
|
public class WithoutParameters {
|
||||||
|
int errors = 0;
|
||||||
|
|
||||||
private static final Class<?>[] qux_types = {
|
private WithoutParameters() {}
|
||||||
int.class,
|
|
||||||
Foo.class,
|
|
||||||
List.class,
|
|
||||||
List.class,
|
|
||||||
List.class,
|
|
||||||
String[].class
|
|
||||||
};
|
|
||||||
|
|
||||||
public static void main(String argv[]) throws Exception {
|
public static void main(String argv[]) throws Exception {
|
||||||
int error = 0;
|
WithoutParameters wp = new WithoutParameters();
|
||||||
Method[] methods = Foo.class.getMethods();
|
wp.runTests(Foo.class.getMethods());
|
||||||
for(Method m : methods) {
|
wp.runTests(Foo.Inner.class.getConstructors());
|
||||||
System.err.println("Inspecting method " + m);
|
wp.checkForErrors();
|
||||||
Parameter[] parameters = m.getParameters();
|
|
||||||
if(parameters == null)
|
|
||||||
throw new Exception("getParameters should never be null");
|
|
||||||
for(int i = 0; i < parameters.length; i++) {
|
|
||||||
Parameter p = parameters[i];
|
|
||||||
if(!p.getDeclaringExecutable().equals(m)) {
|
|
||||||
System.err.println(p + ".getDeclaringExecutable != " + m);
|
|
||||||
error++;
|
|
||||||
}
|
|
||||||
if(null == p.getType()) {
|
|
||||||
System.err.println(p + ".getType() == null");
|
|
||||||
error++;
|
|
||||||
}
|
|
||||||
if(null == p.getParameterizedType()) {
|
|
||||||
System.err.println(p + ".getParameterizedType == null");
|
|
||||||
error++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(m.getName().equals("qux")) {
|
|
||||||
if(6 != parameters.length) {
|
|
||||||
System.err.println("Wrong number of parameters for qux");
|
|
||||||
error++;
|
|
||||||
}
|
|
||||||
for(int i = 0; i < parameters.length; i++) {
|
|
||||||
Parameter p = parameters[i];
|
|
||||||
// The getType family work with or without
|
|
||||||
// parameter attributes compiled in.
|
|
||||||
if(!parameters[i].getType().equals(qux_types[i])) {
|
|
||||||
System.err.println("Wrong parameter type for " + parameters[0] + ": expected " + qux_types[i] + ", but got " + parameters[i].getType());
|
|
||||||
error++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!parameters[0].getParameterizedType().equals(int.class)) {
|
|
||||||
System.err.println("getParameterizedType for quux is wrong");
|
|
||||||
error++;
|
|
||||||
}
|
|
||||||
if(!parameters[1].getParameterizedType().equals(Foo.class)) {
|
|
||||||
System.err.println("getParameterizedType for quux is wrong");
|
|
||||||
error++;
|
|
||||||
}
|
|
||||||
if(!(parameters[2].getParameterizedType() instanceof
|
|
||||||
ParameterizedType)) {
|
|
||||||
System.err.println("getParameterizedType for l is wrong");
|
|
||||||
error++;
|
|
||||||
} else {
|
|
||||||
ParameterizedType pt =
|
|
||||||
(ParameterizedType) parameters[2].getParameterizedType();
|
|
||||||
if(!pt.getRawType().equals(List.class)) {
|
|
||||||
System.err.println("Raw type for l is wrong");
|
|
||||||
error++;
|
|
||||||
}
|
|
||||||
if(1 != pt.getActualTypeArguments().length) {
|
|
||||||
System.err.println("Number of type parameters for l is wrong");
|
|
||||||
error++;
|
|
||||||
}
|
|
||||||
if(!(pt.getActualTypeArguments()[0] instanceof WildcardType)) {
|
|
||||||
System.err.println("Type parameter for l is wrong");
|
|
||||||
error++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!(parameters[3].getParameterizedType() instanceof
|
|
||||||
ParameterizedType)) {
|
|
||||||
System.err.println("getParameterizedType for l2 is wrong");
|
|
||||||
error++;
|
|
||||||
} else {
|
|
||||||
ParameterizedType pt =
|
|
||||||
(ParameterizedType) parameters[3].getParameterizedType();
|
|
||||||
if(!pt.getRawType().equals(List.class)) {
|
|
||||||
System.err.println("Raw type for l2 is wrong");
|
|
||||||
error++;
|
|
||||||
}
|
|
||||||
if(1 != pt.getActualTypeArguments().length) {
|
|
||||||
System.err.println("Number of type parameters for l2 is wrong");
|
|
||||||
error++;
|
|
||||||
}
|
|
||||||
if(!(pt.getActualTypeArguments()[0].equals(Foo.class))) {
|
|
||||||
System.err.println("Type parameter for l2 is wrong");
|
|
||||||
error++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!(parameters[4].getParameterizedType() instanceof
|
|
||||||
ParameterizedType)) {
|
|
||||||
System.err.println("getParameterizedType for l3 is wrong");
|
|
||||||
error++;
|
|
||||||
} else {
|
|
||||||
ParameterizedType pt =
|
|
||||||
(ParameterizedType) parameters[4].getParameterizedType();
|
|
||||||
if(!pt.getRawType().equals(List.class)) {
|
|
||||||
System.err.println("Raw type for l3 is wrong");
|
|
||||||
error++;
|
|
||||||
}
|
|
||||||
if(1 != pt.getActualTypeArguments().length) {
|
|
||||||
System.err.println("Number of type parameters for l3 is wrong");
|
|
||||||
error++;
|
|
||||||
}
|
|
||||||
if(!(pt.getActualTypeArguments()[0] instanceof WildcardType)) {
|
|
||||||
System.err.println("Type parameter for l3 is wrong");
|
|
||||||
error++;
|
|
||||||
} else {
|
|
||||||
WildcardType wt = (WildcardType)
|
|
||||||
pt.getActualTypeArguments()[0];
|
|
||||||
if(!wt.getUpperBounds()[0].equals(Foo.class)) {
|
|
||||||
System.err.println("Upper bounds on type parameter fol l3 is wrong");
|
|
||||||
error++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!parameters[5].isVarArgs()) {
|
|
||||||
System.err.println("isVarArg for rest is wrong");
|
|
||||||
error++;
|
|
||||||
}
|
|
||||||
if(!(parameters[5].getParameterizedType().equals(String[].class))) {
|
|
||||||
System.err.println("getParameterizedType for rest is wrong");
|
|
||||||
error++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void runTests(Method[] methods) throws Exception {
|
||||||
|
for(Method m : methods) {runTest(m);}
|
||||||
|
}
|
||||||
|
|
||||||
|
void runTests(Constructor[] constructors) throws Exception {
|
||||||
|
for(Constructor c : constructors) {runTest(c);}
|
||||||
|
}
|
||||||
|
|
||||||
|
void runTest(Executable e) throws Exception {
|
||||||
|
System.err.println("Inspecting executable " + e);
|
||||||
|
Parameter[] parameters = e.getParameters();
|
||||||
|
Objects.requireNonNull(parameters, "getParameters should never be null");
|
||||||
|
|
||||||
|
ExpectedParameterInfo epi = e.getAnnotation(ExpectedParameterInfo.class);
|
||||||
|
if (epi != null) {
|
||||||
|
abortIfTrue(epi.parameterCount() != e.getParameterCount(), "Bad parameter count for "+ e);
|
||||||
|
abortIfTrue(epi.isVarArgs() != e.isVarArgs(),"Bad varargs value for "+ e);
|
||||||
|
}
|
||||||
|
abortIfTrue(e.getParameterCount() != parameters.length, "Mismatched of parameter counts.");
|
||||||
|
|
||||||
|
for(int i = 0; i < parameters.length; i++) {
|
||||||
|
Parameter p = parameters[i];
|
||||||
|
errorIfTrue(!p.getDeclaringExecutable().equals(e), p + ".getDeclaringExecutable != " + e);
|
||||||
|
Objects.requireNonNull(p.getType(), "getType() should not be null");
|
||||||
|
Objects.requireNonNull(p.getParameterizedType(), "getParameterizedType() should not be null");
|
||||||
|
|
||||||
|
if (epi != null) {
|
||||||
|
Class<?> expectedParameterType = epi.parameterTypes()[i];
|
||||||
|
errorIfTrue(!p.getType().equals(expectedParameterType),
|
||||||
|
"Wrong parameter type for " + p + ": expected " + expectedParameterType +
|
||||||
|
", but got " + p.getType());
|
||||||
|
|
||||||
|
ParameterizedInfo[] expectedParameterizedTypes = epi.parameterizedTypes();
|
||||||
|
if (expectedParameterizedTypes.length > 0) {
|
||||||
|
Type parameterizedType = p.getParameterizedType();
|
||||||
|
Class<? extends Type> expectedParameterziedTypeType = expectedParameterizedTypes[i].value();
|
||||||
|
errorIfTrue(!expectedParameterziedTypeType.isAssignableFrom(parameterizedType.getClass()),
|
||||||
|
"Wrong class of parameteried type of " + p + ": expected " + expectedParameterziedTypeType +
|
||||||
|
", but got " + parameterizedType.getClass());
|
||||||
|
|
||||||
|
if (expectedParameterziedTypeType.equals(Class.class)) {
|
||||||
|
errorIfTrue(!parameterizedType.equals(expectedParameterType),
|
||||||
|
"Wrong parameteried type for " + p + ": expected " + expectedParameterType +
|
||||||
|
", but got " + parameterizedType);
|
||||||
|
} else {
|
||||||
|
if (expectedParameterziedTypeType.equals(ParameterizedType.class)) {
|
||||||
|
ParameterizedType ptype = (ParameterizedType)parameterizedType;
|
||||||
|
errorIfTrue(!ptype.getRawType().equals(expectedParameterType),
|
||||||
|
"Wrong raw type for " + p + ": expected " + expectedParameterType +
|
||||||
|
", but got " + ptype.getRawType());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check string representation
|
||||||
|
String expectedStringOfType = epi.parameterizedTypes()[i].string();
|
||||||
|
errorIfTrue(!expectedStringOfType.equals(parameterizedType.toString()),
|
||||||
|
"Bad type string" + p + ": expected " + expectedStringOfType +
|
||||||
|
", but got " + parameterizedType.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(0 != error)
|
}
|
||||||
throw new Exception("Failed " + error + " tests");
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkForErrors() {
|
||||||
|
if (errors > 0)
|
||||||
|
throw new RuntimeException("Failed " + errors + " tests");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void errorIfTrue(boolean predicate, String errMessage) {
|
||||||
|
if (predicate) {
|
||||||
|
errors++;
|
||||||
|
System.err.println(errMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void abortIfTrue(boolean predicate, String errMessage) {
|
||||||
|
if (predicate) {
|
||||||
|
throw new RuntimeException(errMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({METHOD, CONSTRUCTOR})
|
||||||
|
@interface ExpectedParameterInfo {
|
||||||
|
int parameterCount() default 0;
|
||||||
|
Class<?>[] parameterTypes() default {};
|
||||||
|
ParameterizedInfo[] parameterizedTypes() default {};
|
||||||
|
boolean isVarArgs() default false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Target({})
|
||||||
|
@interface ParameterizedInfo {
|
||||||
|
Class<? extends Type> value() default Class.class;
|
||||||
|
String string() default "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Foo {
|
public class Foo {
|
||||||
int thing;
|
int thing;
|
||||||
|
@ExpectedParameterInfo(parameterCount = 6,
|
||||||
|
parameterTypes =
|
||||||
|
{int.class, Foo.class,
|
||||||
|
List.class, List.class,
|
||||||
|
List.class, String[].class},
|
||||||
|
parameterizedTypes =
|
||||||
|
{@ParameterizedInfo(Class.class),
|
||||||
|
@ParameterizedInfo(Class.class),
|
||||||
|
@ParameterizedInfo(value=ParameterizedType.class, string="java.util.List<?>"),
|
||||||
|
@ParameterizedInfo(value=ParameterizedType.class, string="java.util.List<WithoutParameters$Foo>"),
|
||||||
|
@ParameterizedInfo(value=ParameterizedType.class, string="java.util.List<? extends WithoutParameters$Foo>"),
|
||||||
|
@ParameterizedInfo(Class.class)},
|
||||||
|
isVarArgs = true)
|
||||||
public void qux(int quux, Foo quuux,
|
public void qux(int quux, Foo quuux,
|
||||||
List<?> l, List<Foo> l2,
|
List<?> l, List<Foo> l2,
|
||||||
List<? extends Foo> l3,
|
List<? extends Foo> l3,
|
||||||
String... rest) {}
|
String... rest) {}
|
||||||
public class Inner {
|
public class Inner {
|
||||||
int thang;
|
int thang;
|
||||||
|
@ExpectedParameterInfo(parameterCount = 2,
|
||||||
|
parameterTypes = {Foo.class, int.class})
|
||||||
public Inner(int theng) {
|
public Inner(int theng) {
|
||||||
thang = theng + thing;
|
thang = theng + thing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
77
jdk/test/java/net/Socket/asyncClose/Race.java
Normal file
77
jdk/test/java/net/Socket/asyncClose/Race.java
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013, 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 8006395
|
||||||
|
* @summary Race in async socket close on Linux
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.ServerSocket;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.net.SocketException;
|
||||||
|
import java.util.concurrent.Phaser;
|
||||||
|
|
||||||
|
// Racey test, will not always fail, but if it does then we have a problem.
|
||||||
|
|
||||||
|
public class Race {
|
||||||
|
final static int THREADS = 100;
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
try (ServerSocket ss = new ServerSocket(0)) {
|
||||||
|
final int port = ss.getLocalPort();
|
||||||
|
final Phaser phaser = new Phaser(THREADS + 1);
|
||||||
|
for (int i=0; i<100; i++) {
|
||||||
|
final Socket s = new Socket("localhost", port);
|
||||||
|
s.setSoLinger(false, 0);
|
||||||
|
try (Socket sa = ss.accept()) {
|
||||||
|
sa.setSoLinger(false, 0);
|
||||||
|
final InputStream is = s.getInputStream();
|
||||||
|
Thread[] threads = new Thread[THREADS];
|
||||||
|
for (int j=0; j<THREADS; j++) {
|
||||||
|
threads[j] = new Thread() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
phaser.arriveAndAwaitAdvance();
|
||||||
|
while (is.read() != -1)
|
||||||
|
Thread.sleep(50);
|
||||||
|
} catch (Exception x) {
|
||||||
|
if (!(x instanceof SocketException
|
||||||
|
&& x.getMessage().equals("Socket closed")))
|
||||||
|
x.printStackTrace();
|
||||||
|
// ok, expect Socket closed
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
for (int j=0; j<100; j++)
|
||||||
|
threads[j].start();
|
||||||
|
phaser.arriveAndAwaitAdvance();
|
||||||
|
s.close();
|
||||||
|
for (int j=0; j<100; j++)
|
||||||
|
threads[j].join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1998, 2002, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1998, 2013, 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
|
||||||
@ -21,71 +21,235 @@
|
|||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* This is no longer run directly. See runconstructor.sh
|
/*
|
||||||
*
|
* @test
|
||||||
*
|
* @bug 4393671
|
||||||
*
|
* @summary URL constructor URL(URL context, String spec) FAILED with specific input
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
* This program tests the URL parser in the URL constructor. It
|
* This program tests the URL parser in the URL constructor. It
|
||||||
* tries to construct a variety of valid URLs with a given context
|
* tries to construct a variety of valid URLs with a given context
|
||||||
* (which may be null) and a variety of specs. It then compares the
|
* (which may be null) and a variety of specs. It then compares the
|
||||||
* result with an expected value.
|
* result with an expected value.
|
||||||
*
|
|
||||||
* It expects that a data file named "urls" be available in the
|
|
||||||
* current directory, from which it will get its testing data. The
|
|
||||||
* format of the file is:
|
|
||||||
*
|
|
||||||
* URL: null
|
|
||||||
* spec: jar:http://www.foo.com/dir1/jar.jar!/
|
|
||||||
* expected: jar:http://www.foo.com/dir1/jar.jar!/
|
|
||||||
*
|
|
||||||
* where URL is the context, spec is the spec and expected is the
|
|
||||||
* expected result. The first : must be followed by a space. Each test
|
|
||||||
* entry should be followed by a blank line.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.*;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class Constructor {
|
public class Constructor {
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
URL url = null;
|
List<Entry> entries = new ArrayList<>();
|
||||||
String urls = "jar_urls";
|
entries.addAll(Arrays.asList(fileURLs));
|
||||||
if (args.length > 0 && args[0] != null) {
|
entries.addAll(Arrays.asList(jarURLs));
|
||||||
urls = args[0];
|
entries.addAll(Arrays.asList(normalHttpURLs));
|
||||||
}
|
entries.addAll(Arrays.asList(abnormalHttpURLs));
|
||||||
|
if (hasFtp())
|
||||||
|
entries.addAll(Arrays.asList(ftpURLs));
|
||||||
|
URL url;
|
||||||
|
|
||||||
File f = new File(urls);
|
for (Entry e : entries) {
|
||||||
InputStream file = new FileInputStream(f);
|
if (e.context == null)
|
||||||
BufferedReader in = new BufferedReader(new InputStreamReader(file));
|
url = new URL(e.spec);
|
||||||
while(true) {
|
else
|
||||||
String context = in.readLine();
|
url = new URL(new URL(e.context), e.spec);
|
||||||
if (context == null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
context = getValue(context);
|
|
||||||
String spec = getValue(in.readLine());
|
|
||||||
String expected = getValue(in.readLine());
|
|
||||||
|
|
||||||
if (context.equals("null")) {
|
if (!(url.toString().equals(e.expected))) {
|
||||||
url = new URL(spec);
|
throw new RuntimeException("error for: \n\tURL:" + e.context +
|
||||||
} else {
|
"\n\tspec: " + e.spec +
|
||||||
url = new URL(new URL(context), spec);
|
"\n\texpected: " + e.expected +
|
||||||
}
|
|
||||||
if (!(url.toString().equals(expected))) {
|
|
||||||
throw new RuntimeException("error for: \n\tURL:" + context +
|
|
||||||
"\n\tspec: " + spec +
|
|
||||||
"\n\texpected: " + expected +
|
|
||||||
"\n\tactual: " + url.toString());
|
"\n\tactual: " + url.toString());
|
||||||
} else {
|
} else {
|
||||||
System.out.println("success for: " + url + "\n");
|
//debug
|
||||||
|
//System.out.println("success for: " + url);
|
||||||
}
|
}
|
||||||
in.readLine();
|
|
||||||
}
|
}
|
||||||
in.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getValue(String value) {
|
private static boolean hasFtp() {
|
||||||
return value.substring(value.indexOf(':') + 2);
|
try {
|
||||||
|
return new java.net.URL("ftp://") != null;
|
||||||
|
} catch (java.net.MalformedURLException x) {
|
||||||
|
System.out.println("FTP not supported by this runtime.");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Entry {
|
||||||
|
final String context;
|
||||||
|
final String spec;
|
||||||
|
final String expected;
|
||||||
|
Entry(String context, String spec, String expected) {
|
||||||
|
this.context = context;
|
||||||
|
this.spec =spec;
|
||||||
|
this.expected = expected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Entry[] fileURLs = new Entry[] {
|
||||||
|
new Entry(null,
|
||||||
|
"file://JavaSoft/Test",
|
||||||
|
"file://JavaSoft/Test"),
|
||||||
|
new Entry(null,
|
||||||
|
"file:///JavaSoft/Test",
|
||||||
|
"file:/JavaSoft/Test"),
|
||||||
|
new Entry(null,
|
||||||
|
"file:/JavaSoft/Test",
|
||||||
|
"file:/JavaSoft/Test"),
|
||||||
|
new Entry(null,
|
||||||
|
"file:/c:/JavaSoft/Test",
|
||||||
|
"file:/c:/JavaSoft/Test"),
|
||||||
|
new Entry(null,
|
||||||
|
"file:/c:/JavaSoft/Test:something",
|
||||||
|
"file:/c:/JavaSoft/Test:something"),
|
||||||
|
new Entry(null,
|
||||||
|
"file:/c:/JavaSoft/Test#anchor",
|
||||||
|
"file:/c:/JavaSoft/Test#anchor"),
|
||||||
|
new Entry("file://JavaSoft/Test",
|
||||||
|
"Test#bar",
|
||||||
|
"file://JavaSoft/Test#bar"),
|
||||||
|
new Entry("file://codrus/c:/jdk/eng/index.html",
|
||||||
|
"pulsar.html",
|
||||||
|
"file://codrus/c:/jdk/eng/pulsar.html"),
|
||||||
|
new Entry("file:///c:/jdk/eng/index.html",
|
||||||
|
"pulsar.html",
|
||||||
|
"file:/c:/jdk/eng/pulsar.html"),
|
||||||
|
new Entry("file:///jdk/eng/index.html",
|
||||||
|
"pulsar.html",
|
||||||
|
"file:/jdk/eng/pulsar.html"),
|
||||||
|
new Entry("file://JavaSoft/Test",
|
||||||
|
"file://radartoad.com/Test#bar",
|
||||||
|
"file://radartoad.com/Test#bar"),
|
||||||
|
new Entry("file://JavaSoft/Test",
|
||||||
|
"/c:/Test#bar",
|
||||||
|
"file://JavaSoft/c:/Test#bar"),
|
||||||
|
};
|
||||||
|
|
||||||
|
static Entry[] jarURLs = new Entry[] {
|
||||||
|
new Entry(null,
|
||||||
|
"jar:http://www.foo.com/dir1/jar.jar!/dir2/entry.txt",
|
||||||
|
"jar:http://www.foo.com/dir1/jar.jar!/dir2/entry.txt"),
|
||||||
|
new Entry(null,
|
||||||
|
"jar:http://www.foo.com/dir1/jar.jar!/",
|
||||||
|
"jar:http://www.foo.com/dir1/jar.jar!/"),
|
||||||
|
new Entry(null,
|
||||||
|
"jar:http://www.foo.com/dir1/jar.jar!/",
|
||||||
|
"jar:http://www.foo.com/dir1/jar.jar!/"),
|
||||||
|
new Entry("jar:http://www.foo.com/dir1/jar.jar!/",
|
||||||
|
"entry.txt",
|
||||||
|
"jar:http://www.foo.com/dir1/jar.jar!/entry.txt"),
|
||||||
|
new Entry("jar:http://www.foo.com/dir1/jar.jar!/",
|
||||||
|
"/entry.txt",
|
||||||
|
"jar:http://www.foo.com/dir1/jar.jar!/entry.txt"),
|
||||||
|
new Entry("jar:http://www.foo.com/dir1/jar.jar!/",
|
||||||
|
"dir1/entry.txt",
|
||||||
|
"jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt"),
|
||||||
|
new Entry("jar:http://www.foo.com/dir1/jar.jar!/",
|
||||||
|
"/dir1/entry.txt",
|
||||||
|
"jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt"),
|
||||||
|
new Entry("jar:http://www.foo.com/dir1/jar.jar!/",
|
||||||
|
"entry.txt",
|
||||||
|
"jar:http://www.foo.com/dir1/jar.jar!/entry.txt"),
|
||||||
|
new Entry("jar:http://www.foo.com/dir1/jar.jar!/",
|
||||||
|
"/entry.txt",
|
||||||
|
"jar:http://www.foo.com/dir1/jar.jar!/entry.txt"),
|
||||||
|
new Entry("jar:http://www.foo.com/dir1/jar.jar!/",
|
||||||
|
"/entry.txt",
|
||||||
|
"jar:http://www.foo.com/dir1/jar.jar!/entry.txt"),
|
||||||
|
new Entry("jar:http://www.foo.com/dir1/jar.jar!/dir1/",
|
||||||
|
"entry.txt",
|
||||||
|
"jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt"),
|
||||||
|
new Entry("jar:http://www.foo.com/dir1/jar.jar!/dir2/dir3/entry2.txt",
|
||||||
|
"/dir1/entry.txt",
|
||||||
|
"jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt"),
|
||||||
|
new Entry("jar:http://www.foo.com/dir1/jar.jar!/",
|
||||||
|
"/dir1/foo/entry.txt",
|
||||||
|
"jar:http://www.foo.com/dir1/jar.jar!/dir1/foo/entry.txt"),
|
||||||
|
new Entry("jar:http://www.foo.com/dir1/jar.jar!/dir1/dir2/dir3/",
|
||||||
|
"dir4/foo/entry.txt",
|
||||||
|
"jar:http://www.foo.com/dir1/jar.jar!/dir1/dir2/dir3/dir4/foo/entry.txt"),
|
||||||
|
new Entry("jar:http://www.foo.com/dir1/jar.jar!/",
|
||||||
|
"/dir1/foo/entry.txt",
|
||||||
|
"jar:http://www.foo.com/dir1/jar.jar!/dir1/foo/entry.txt"),
|
||||||
|
new Entry(null,
|
||||||
|
"jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor",
|
||||||
|
"jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor"),
|
||||||
|
new Entry("jar:http://www.foo.com/dir1/jar.jar!/foo.txt",
|
||||||
|
"#anchor",
|
||||||
|
"jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor"),
|
||||||
|
new Entry("jar:http://www.foo.com/dir1/jar.jar!/foo/bar/",
|
||||||
|
"baz/quux#anchor",
|
||||||
|
"jar:http://www.foo.com/dir1/jar.jar!/foo/bar/baz/quux#anchor"),
|
||||||
|
new Entry("jar:http://balloo.com/olle.jar!/",
|
||||||
|
"p2",
|
||||||
|
"jar:http://balloo.com/olle.jar!/p2")
|
||||||
|
};
|
||||||
|
|
||||||
|
static Entry[] normalHttpURLs = new Entry[] {
|
||||||
|
new Entry("http://a/b/c/d;p?q", "g", "http://a/b/c/g"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "./g", "http://a/b/c/g"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "g/", "http://a/b/c/g/"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "/g", "http://a/g"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "//g", "http://g"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "?y", "http://a/b/c/?y"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "g?y", "http://a/b/c/g?y"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "g#s", "http://a/b/c/g#s"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "g?y#s", "http://a/b/c/g?y#s"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", ";x", "http://a/b/c/;x"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "g;x", "http://a/b/c/g;x"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "g;x?y#s", "http://a/b/c/g;x?y#s"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", ".", "http://a/b/c/"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "./", "http://a/b/c/"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "..", "http://a/b/"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "../", "http://a/b/"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "../g", "http://a/b/g"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "../..", "http://a/"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "../../", "http://a/"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "../../g", "http://a/g"),
|
||||||
|
new Entry(null,
|
||||||
|
"http://www.javasoft.com/jdc/community/chat/index.html#javalive?frontpage-jdc",
|
||||||
|
"http://www.javasoft.com/jdc/community/chat/index.html#javalive?frontpage-jdc")
|
||||||
|
};
|
||||||
|
|
||||||
|
static Entry[] abnormalHttpURLs = new Entry[] {
|
||||||
|
new Entry("http://a/b/c/d;p?q", "../../../g", "http://a/../g"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "../../../../g", "http://a/../../g"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "/./g", "http://a/./g"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "/../g", "http://a/../g"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", ".g", "http://a/b/c/.g"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "g.", "http://a/b/c/g."),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "./../g", "http://a/b/g"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "./g/.", "http://a/b/c/g/"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "g/./h", "http://a/b/c/g/h"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "g;x=1/./y", "http://a/b/c/g;x=1/y"),
|
||||||
|
new Entry("http://a/b/c/d;p?q", "g;x=1/../y", "http://a/b/c/y")
|
||||||
|
};
|
||||||
|
|
||||||
|
static Entry[] ftpURLs = new Entry[] {
|
||||||
|
new Entry(null,
|
||||||
|
"ftp://ftp.foo.com/dir1/entry.txt",
|
||||||
|
"ftp://ftp.foo.com/dir1/entry.txt"),
|
||||||
|
new Entry(null,
|
||||||
|
"ftp://br:pwd@ftp.foo.com/dir1/jar.jar",
|
||||||
|
"ftp://br:pwd@ftp.foo.com/dir1/jar.jar"),
|
||||||
|
new Entry("ftp://ftp.foo.com/dir1/foo.txt",
|
||||||
|
"bar.txt",
|
||||||
|
"ftp://ftp.foo.com/dir1/bar.txt"),
|
||||||
|
new Entry("ftp://ftp.foo.com/dir1/jar.jar",
|
||||||
|
"/entry.txt",
|
||||||
|
"ftp://ftp.foo.com/entry.txt"),
|
||||||
|
new Entry("ftp://ftp.foo.com/dir1/jar.jar",
|
||||||
|
"dir1/entry.txt",
|
||||||
|
"ftp://ftp.foo.com/dir1/dir1/entry.txt"),
|
||||||
|
new Entry("ftp://ftp.foo.com/dir1/jar.jar",
|
||||||
|
"/dir1/entry.txt",
|
||||||
|
"ftp://ftp.foo.com/dir1/entry.txt"),
|
||||||
|
new Entry("ftp://br:pwd@ftp.foo.com/dir1/jar.jar",
|
||||||
|
"/dir1/entry.txt",
|
||||||
|
"ftp://br:pwd@ftp.foo.com/dir1/entry.txt")
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ public class HandlerLoop {
|
|||||||
public static void main(String args[]) throws Exception {
|
public static void main(String args[]) throws Exception {
|
||||||
URL.setURLStreamHandlerFactory(
|
URL.setURLStreamHandlerFactory(
|
||||||
new HandlerFactory("sun.net.www.protocol"));
|
new HandlerFactory("sun.net.www.protocol"));
|
||||||
URL url = new URL("file://bogus/index.html");
|
URL url = new URL("file:///bogus/index.html");
|
||||||
System.out.println("url = " + url);
|
System.out.println("url = " + url);
|
||||||
url.openConnection();
|
url.openConnection();
|
||||||
}
|
}
|
||||||
|
@ -310,7 +310,14 @@ public class Test {
|
|||||||
throw new RuntimeException("Test failed");
|
throw new RuntimeException("Test failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean hasFtp() {
|
||||||
|
try {
|
||||||
|
return new java.net.URL("ftp://") != null;
|
||||||
|
} catch (java.net.MalformedURLException x) {
|
||||||
|
System.out.println("FTP not supported by this runtime.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// -- Tests --
|
// -- Tests --
|
||||||
|
|
||||||
@ -319,6 +326,7 @@ public class Test {
|
|||||||
|
|
||||||
header("RFC2396: Basic examples");
|
header("RFC2396: Basic examples");
|
||||||
|
|
||||||
|
if (hasFtp())
|
||||||
test("ftp://ftp.is.co.za/rfc/rfc1808.txt")
|
test("ftp://ftp.is.co.za/rfc/rfc1808.txt")
|
||||||
.s("ftp").h("ftp.is.co.za").p("/rfc/rfc1808.txt").z();
|
.s("ftp").h("ftp.is.co.za").p("/rfc/rfc1808.txt").z();
|
||||||
|
|
||||||
@ -328,6 +336,7 @@ public class Test {
|
|||||||
test("http://www.w3.org/Addressing/")
|
test("http://www.w3.org/Addressing/")
|
||||||
.s("http").h("www.w3.org").p("/Addressing/").z();
|
.s("http").h("www.w3.org").p("/Addressing/").z();
|
||||||
|
|
||||||
|
if (hasFtp())
|
||||||
test("ftp://ds.internic.net/rfc/")
|
test("ftp://ds.internic.net/rfc/")
|
||||||
.s("ftp").h("ds.internic.net").p("/rfc/").z();
|
.s("ftp").h("ds.internic.net").p("/rfc/").z();
|
||||||
|
|
||||||
|
@ -28,20 +28,22 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class URIToURLTest {
|
public class URIToURLTest {
|
||||||
public static void main(String args[]) throws Exception {
|
public static void main(String args[]) throws Exception {
|
||||||
String[] uris = {
|
List<String> uris = new ArrayList<>();
|
||||||
"http://jag:cafebabe@java.sun.com:94/b/c/d?q#g",
|
uris.add("http://jag:cafebabe@java.sun.com:94/b/c/d?q#g");
|
||||||
"http://[1080:0:0:0:8:800:200C:417A]/index.html",
|
uris.add("http://[1080:0:0:0:8:800:200C:417A]/index.html");
|
||||||
"http://a/b/c/d;p?q",
|
uris.add("http://a/b/c/d;p?q");
|
||||||
"ftp://ftp.is.co.za/rfc/rfc1808.txt",
|
uris.add("mailto:mduerst@ifi.unizh.ch");
|
||||||
"mailto:mduerst@ifi.unizh.ch", // opaque url
|
uris.add("http:comp.infosystems.www.servers.unix");
|
||||||
"http:comp.infosystems.www.servers.unix" //opaque url
|
if (hasFtp())
|
||||||
};
|
uris.add("ftp://ftp.is.co.za/rfc/rfc1808.txt");
|
||||||
|
|
||||||
for (int i = 0; i < uris.length; i++) {
|
for (String uriStr : uris) {
|
||||||
URI uri = new URI(uris[i]);
|
URI uri = new URI(uriStr);
|
||||||
URL url = uri.toURL();
|
URL url = uri.toURL();
|
||||||
String scheme = uri.getScheme();
|
String scheme = uri.getScheme();
|
||||||
boolean schemeCheck = scheme == null? url.getProtocol() == null :
|
boolean schemeCheck = scheme == null? url.getProtocol() == null :
|
||||||
@ -111,4 +113,13 @@ public class URIToURLTest {
|
|||||||
url.getRef());
|
url.getRef());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean hasFtp() {
|
||||||
|
try {
|
||||||
|
return new java.net.URL("ftp://") != null;
|
||||||
|
} catch (java.net.MalformedURLException x) {
|
||||||
|
System.out.println("FTP not supported by this runtime.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: ../../../g
|
|
||||||
expected: http://a/../g
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: ../../../../g
|
|
||||||
expected: http://a/../../g
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: /./g
|
|
||||||
expected: http://a/./g
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: /../g
|
|
||||||
expected: http://a/../g
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: .g
|
|
||||||
expected: http://a/b/c/.g
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: g.
|
|
||||||
expected: http://a/b/c/g.
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: ./../g
|
|
||||||
expected: http://a/b/g
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: ./g/.
|
|
||||||
expected: http://a/b/c/g/
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: g/./h
|
|
||||||
expected: http://a/b/c/g/h
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: g;x=1/./y
|
|
||||||
expected: http://a/b/c/g;x=1/y
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: g;x=1/../y
|
|
||||||
expected: http://a/b/c/y
|
|
@ -1,27 +0,0 @@
|
|||||||
URL: null
|
|
||||||
spec: ftp://ftp.foo.com/dir1/entry.txt
|
|
||||||
expected: ftp://ftp.foo.com/dir1/entry.txt
|
|
||||||
|
|
||||||
URL: null
|
|
||||||
spec: ftp://br:pwd@ftp.foo.com/dir1/jar.jar
|
|
||||||
expected: ftp://br:pwd@ftp.foo.com/dir1/jar.jar
|
|
||||||
|
|
||||||
URL: ftp://ftp.foo.com/dir1/foo.txt
|
|
||||||
spec: bar.txt
|
|
||||||
expected: ftp://ftp.foo.com/dir1/bar.txt
|
|
||||||
|
|
||||||
URL: ftp://ftp.foo.com/dir1/jar.jar
|
|
||||||
spec: /entry.txt
|
|
||||||
expected: ftp://ftp.foo.com/entry.txt
|
|
||||||
|
|
||||||
URL: ftp://ftp.foo.com/dir1/jar.jar
|
|
||||||
spec: dir1/entry.txt
|
|
||||||
expected: ftp://ftp.foo.com/dir1/dir1/entry.txt
|
|
||||||
|
|
||||||
URL: ftp://ftp.foo.com/dir1/jar.jar
|
|
||||||
spec: /dir1/entry.txt
|
|
||||||
expected: ftp://ftp.foo.com/dir1/entry.txt
|
|
||||||
|
|
||||||
URL: ftp://br:pwd@ftp.foo.com/dir1/jar.jar
|
|
||||||
spec: /dir1/entry.txt
|
|
||||||
expected: ftp://br:pwd@ftp.foo.com/dir1/entry.txt
|
|
@ -1,75 +0,0 @@
|
|||||||
URL: null
|
|
||||||
spec: jar:http://www.foo.com/dir1/jar.jar!/dir2/entry.txt
|
|
||||||
expected: jar:http://www.foo.com/dir1/jar.jar!/dir2/entry.txt
|
|
||||||
|
|
||||||
URL: null
|
|
||||||
spec: jar:http://www.foo.com/dir1/jar.jar!/
|
|
||||||
expected: jar:http://www.foo.com/dir1/jar.jar!/
|
|
||||||
|
|
||||||
URL: null
|
|
||||||
spec: jar:http://www.foo.com/dir1/jar.jar!/
|
|
||||||
expected: jar:http://www.foo.com/dir1/jar.jar!/
|
|
||||||
|
|
||||||
URL: jar:http://www.foo.com/dir1/jar.jar!/
|
|
||||||
spec: entry.txt
|
|
||||||
expected: jar:http://www.foo.com/dir1/jar.jar!/entry.txt
|
|
||||||
|
|
||||||
URL: jar:http://www.foo.com/dir1/jar.jar!/
|
|
||||||
spec: /entry.txt
|
|
||||||
expected: jar:http://www.foo.com/dir1/jar.jar!/entry.txt
|
|
||||||
|
|
||||||
URL: jar:http://www.foo.com/dir1/jar.jar!/
|
|
||||||
spec: dir1/entry.txt
|
|
||||||
expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt
|
|
||||||
|
|
||||||
URL: jar:http://www.foo.com/dir1/jar.jar!/
|
|
||||||
spec: /dir1/entry.txt
|
|
||||||
expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt
|
|
||||||
|
|
||||||
URL: jar:http://www.foo.com/dir1/jar.jar!/
|
|
||||||
spec: entry.txt
|
|
||||||
expected: jar:http://www.foo.com/dir1/jar.jar!/entry.txt
|
|
||||||
|
|
||||||
URL: jar:http://www.foo.com/dir1/jar.jar!/
|
|
||||||
spec: /entry.txt
|
|
||||||
expected: jar:http://www.foo.com/dir1/jar.jar!/entry.txt
|
|
||||||
|
|
||||||
URL: jar:http://www.foo.com/dir1/jar.jar!/
|
|
||||||
spec: /entry.txt
|
|
||||||
expected: jar:http://www.foo.com/dir1/jar.jar!/entry.txt
|
|
||||||
|
|
||||||
URL: jar:http://www.foo.com/dir1/jar.jar!/dir1/
|
|
||||||
spec: entry.txt
|
|
||||||
expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt
|
|
||||||
|
|
||||||
URL: jar:http://www.foo.com/dir1/jar.jar!/dir2/dir3/entry2.txt
|
|
||||||
spec: /dir1/entry.txt
|
|
||||||
expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt
|
|
||||||
|
|
||||||
URL: jar:http://www.foo.com/dir1/jar.jar!/
|
|
||||||
spec: /dir1/foo/entry.txt
|
|
||||||
expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/foo/entry.txt
|
|
||||||
|
|
||||||
URL: jar:http://www.foo.com/dir1/jar.jar!/dir1/dir2/dir3/
|
|
||||||
spec: dir4/foo/entry.txt
|
|
||||||
expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/dir2/dir3/dir4/foo/entry.txt
|
|
||||||
|
|
||||||
URL: jar:http://www.foo.com/dir1/jar.jar!/
|
|
||||||
spec: /dir1/foo/entry.txt
|
|
||||||
expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/foo/entry.txt
|
|
||||||
|
|
||||||
URL: null
|
|
||||||
spec: jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor
|
|
||||||
expected: jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor
|
|
||||||
|
|
||||||
URL: jar:http://www.foo.com/dir1/jar.jar!/foo.txt
|
|
||||||
spec: #anchor
|
|
||||||
expected: jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor
|
|
||||||
|
|
||||||
URL: jar:http://www.foo.com/dir1/jar.jar!/foo/bar/
|
|
||||||
spec: baz/quux#anchor
|
|
||||||
expected: jar:http://www.foo.com/dir1/jar.jar!/foo/bar/baz/quux#anchor
|
|
||||||
|
|
||||||
URL: jar:http://balloo.com/olle.jar!/
|
|
||||||
spec: p2
|
|
||||||
expected: jar:http://balloo.com/olle.jar!/p2
|
|
@ -1,83 +0,0 @@
|
|||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: g
|
|
||||||
expected: http://a/b/c/g
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: ./g
|
|
||||||
expected: http://a/b/c/g
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: g/
|
|
||||||
expected: http://a/b/c/g/
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: /g
|
|
||||||
expected: http://a/g
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: //g
|
|
||||||
expected: http://g
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: ?y
|
|
||||||
expected: http://a/b/c/?y
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: g?y
|
|
||||||
expected: http://a/b/c/g?y
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: g#s
|
|
||||||
expected: http://a/b/c/g#s
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: g?y#s
|
|
||||||
expected: http://a/b/c/g?y#s
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: ;x
|
|
||||||
expected: http://a/b/c/;x
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: g;x
|
|
||||||
expected: http://a/b/c/g;x
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: g;x?y#s
|
|
||||||
expected: http://a/b/c/g;x?y#s
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: .
|
|
||||||
expected: http://a/b/c/
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: ./
|
|
||||||
expected: http://a/b/c/
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: ..
|
|
||||||
expected: http://a/b/
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: ../
|
|
||||||
expected: http://a/b/
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: ../g
|
|
||||||
expected: http://a/b/g
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: ../..
|
|
||||||
expected: http://a/
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: ../../
|
|
||||||
expected: http://a/
|
|
||||||
|
|
||||||
URL: http://a/b/c/d;p?q
|
|
||||||
spec: ../../g
|
|
||||||
expected: http://a/g
|
|
||||||
|
|
||||||
URL: null
|
|
||||||
spec: http://www.javasoft.com/jdc/community/chat/index.html#javalive?frontpage-jdc
|
|
||||||
expected: http://www.javasoft.com/jdc/community/chat/index.html#javalive?frontpage-jdc
|
|
@ -1,67 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright (c) 2000, 2012, 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 4393671
|
|
||||||
# @summary URL constructor URL(URL context, String spec) FAILED with specific input in merlin
|
|
||||||
#
|
|
||||||
OS=`uname -s`
|
|
||||||
case "$OS" in
|
|
||||||
SunOS | Linux | Darwin )
|
|
||||||
PS=":"
|
|
||||||
FS="/"
|
|
||||||
;;
|
|
||||||
CYGWIN* )
|
|
||||||
PS=";"
|
|
||||||
FS="/"
|
|
||||||
;;
|
|
||||||
Windows* )
|
|
||||||
PS=";"
|
|
||||||
FS="\\"
|
|
||||||
;;
|
|
||||||
* )
|
|
||||||
echo "Unrecognized system!"
|
|
||||||
exit 1;
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . \
|
|
||||||
${TESTSRC}${FS}Constructor.java
|
|
||||||
|
|
||||||
failures=0
|
|
||||||
|
|
||||||
go() {
|
|
||||||
echo ''
|
|
||||||
${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} Constructor $1
|
|
||||||
if [ $? != 0 ]; then failures=`expr $failures + 1`; fi
|
|
||||||
}
|
|
||||||
|
|
||||||
go ${TESTSRC}${FS}share_file_urls
|
|
||||||
go ${TESTSRC}${FS}jar_urls
|
|
||||||
go ${TESTSRC}${FS}normal_http_urls
|
|
||||||
go ${TESTSRC}${FS}ftp_urls
|
|
||||||
go ${TESTSRC}${FS}abnormal_http_urls
|
|
||||||
|
|
||||||
if [ "$failures" != "0" ]; then
|
|
||||||
echo $failures tests failed
|
|
||||||
exit 1;
|
|
||||||
fi
|
|
@ -1,51 +0,0 @@
|
|||||||
URL: null
|
|
||||||
spec: file://JavaSoft/Test
|
|
||||||
expected: file://JavaSoft/Test
|
|
||||||
|
|
||||||
URL: null
|
|
||||||
spec: file:///JavaSoft/Test
|
|
||||||
expected: file:/JavaSoft/Test
|
|
||||||
|
|
||||||
URL: null
|
|
||||||
spec: file:/JavaSoft/Test
|
|
||||||
expected: file:/JavaSoft/Test
|
|
||||||
|
|
||||||
URL: null
|
|
||||||
spec: file:/c:/JavaSoft/Test
|
|
||||||
expected: file:/c:/JavaSoft/Test
|
|
||||||
|
|
||||||
URL: null
|
|
||||||
spec: file:/c:/JavaSoft/Test:something
|
|
||||||
expected: file:/c:/JavaSoft/Test:something
|
|
||||||
|
|
||||||
URL: null
|
|
||||||
spec: file:/c:/JavaSoft/Test#anchor
|
|
||||||
expected: file:/c:/JavaSoft/Test#anchor
|
|
||||||
|
|
||||||
URL: null
|
|
||||||
spec: file:/JavaSoft/Test
|
|
||||||
expected: file:/JavaSoft/Test
|
|
||||||
|
|
||||||
URL: file://JavaSoft/Test
|
|
||||||
spec: Test#bar
|
|
||||||
expected: file://JavaSoft/Test#bar
|
|
||||||
|
|
||||||
URL: file://codrus/c:/jdk/eng/index.html
|
|
||||||
spec: pulsar.html
|
|
||||||
expected: file://codrus/c:/jdk/eng/pulsar.html
|
|
||||||
|
|
||||||
URL: file:///c:/jdk/eng/index.html
|
|
||||||
spec: pulsar.html
|
|
||||||
expected: file:/c:/jdk/eng/pulsar.html
|
|
||||||
|
|
||||||
URL: file:///jdk/eng/index.html
|
|
||||||
spec: pulsar.html
|
|
||||||
expected: file:/jdk/eng/pulsar.html
|
|
||||||
|
|
||||||
URL: file://JavaSoft/Test
|
|
||||||
spec: file://radartoad.com/Test#bar
|
|
||||||
expected: file://radartoad.com/Test#bar
|
|
||||||
|
|
||||||
URL: file://JavaSoft/Test
|
|
||||||
spec: /c:/Test#bar
|
|
||||||
expected: file://JavaSoft/c:/Test#bar
|
|
@ -1,15 +0,0 @@
|
|||||||
URL: null
|
|
||||||
spec: file://c:\JavaSoft\Test
|
|
||||||
expected: file://c:/JavaSoft/Test
|
|
||||||
|
|
||||||
URL: null
|
|
||||||
spec: file:/c:\JavaSoft\Test
|
|
||||||
expected: file:/c:/JavaSoft/Test
|
|
||||||
|
|
||||||
URL: null
|
|
||||||
spec: file:/c:\JavaSoft\Test:something#anchor
|
|
||||||
expected: file:/c:/JavaSoft/Test:something#anchor
|
|
||||||
|
|
||||||
URL: file:///c:\jdk\eng\index.html
|
|
||||||
spec: pulsar.html
|
|
||||||
expected: file:/c:/jdk/eng/pulsar.html
|
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2013 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
|
||||||
@ -28,90 +28,55 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class RequestProperties {
|
public class RequestProperties {
|
||||||
|
static int failed;
|
||||||
|
|
||||||
public static void main (String args[]) throws Exception {
|
public static void main (String args[]) throws Exception {
|
||||||
URL url0 = new URL ("http://foo.com/bar/");
|
List<String> urls = new ArrayList<>();
|
||||||
URL url1 = new URL ("file:/etc/passwd");
|
urls.add("http://foo.com/bar/");
|
||||||
URL url2 = new URL ("ftp://foo:bar@foobar.com/etc/passwd");
|
urls.add("jar:http://foo.com/bar.html!/foo/bar");
|
||||||
URL url3 = new URL ("jar:http://foo.com/bar.html!/foo/bar");
|
urls.add("file:/etc/passwd");
|
||||||
URLConnection urlc0 = url0.openConnection ();
|
if (hasFtp())
|
||||||
URLConnection urlc1 = url1.openConnection ();
|
urls.add("ftp://foo:bar@foobar.com/etc/passwd");
|
||||||
URLConnection urlc2 = url2.openConnection ();
|
|
||||||
URLConnection urlc3 = url3.openConnection ();
|
for (String urlStr : urls)
|
||||||
int count = 0;
|
test(new URL(urlStr));
|
||||||
String s = null;
|
|
||||||
try {
|
if (failed != 0)
|
||||||
urlc0.setRequestProperty (null, null);
|
throw new RuntimeException(failed + " errors") ;
|
||||||
System.out.println ("http: setRequestProperty (null,) did not throw NPE");
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
count ++;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
urlc0.addRequestProperty (null, null);
|
|
||||||
System.out.println ("http: addRequestProperty (null,) did not throw NPE");
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
count ++;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
urlc1.setRequestProperty (null, null);
|
|
||||||
System.out.println ("file: setRequestProperty (null,) did not throw NPE");
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
count ++;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
urlc1.addRequestProperty (null, null);
|
|
||||||
System.out.println ("file: addRequestProperty (null,) did not throw NPE");
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
count ++;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
urlc2.setRequestProperty (null, null);
|
|
||||||
System.out.println ("ftp: setRequestProperty (null,) did not throw NPE");
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
count ++;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
urlc2.addRequestProperty (null, null);
|
|
||||||
System.out.println ("ftp: addRequestProperty (null,) did not throw NPE");
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
count ++;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
urlc3.setRequestProperty (null, null);
|
|
||||||
System.out.println ("jar: setRequestProperty (null,) did not throw NPE");
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
count ++;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
urlc3.addRequestProperty (null, null);
|
|
||||||
System.out.println ("jar: addRequestProperty (null,) did not throw NPE");
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
count ++;
|
|
||||||
}
|
|
||||||
if (urlc0.getRequestProperty (null) != null) {
|
|
||||||
System.out.println ("http: getRequestProperty (null,) did not return null");
|
|
||||||
} else {
|
|
||||||
count ++;
|
|
||||||
}
|
|
||||||
if (urlc1.getRequestProperty (null) != null) {
|
|
||||||
System.out.println ("file: getRequestProperty (null,) did not return null");
|
|
||||||
} else {
|
|
||||||
count ++;
|
|
||||||
}
|
|
||||||
if (urlc2.getRequestProperty (null) != null) {
|
|
||||||
System.out.println ("ftp: getRequestProperty (null,) did not return null");
|
|
||||||
} else {
|
|
||||||
count ++;
|
|
||||||
}
|
|
||||||
if (urlc2.getRequestProperty (null) != null) {
|
|
||||||
System.out.println ("jar: getRequestProperty (null,) did not return null");
|
|
||||||
} else {
|
|
||||||
count ++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count != 12) {
|
static void test(URL url) throws Exception {
|
||||||
throw new RuntimeException ((12 -count) + " errors") ;
|
URLConnection urlc = url.openConnection();
|
||||||
|
try {
|
||||||
|
urlc.setRequestProperty(null, null);
|
||||||
|
System.out.println(url.getProtocol()
|
||||||
|
+ ": setRequestProperty(null,) did not throw NPE");
|
||||||
|
failed++;
|
||||||
|
} catch (NullPointerException e) { /* Expected */ }
|
||||||
|
try {
|
||||||
|
urlc.addRequestProperty(null, null);
|
||||||
|
System.out.println(url.getProtocol()
|
||||||
|
+ ": addRequestProperty(null,) did not throw NPE");
|
||||||
|
failed++;
|
||||||
|
} catch (NullPointerException e) { /* Expected */ }
|
||||||
|
|
||||||
|
if (urlc.getRequestProperty(null) != null) {
|
||||||
|
System.out.println(url.getProtocol()
|
||||||
|
+ ": getRequestProperty(null,) did not return null");
|
||||||
|
failed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasFtp() {
|
||||||
|
try {
|
||||||
|
return new java.net.URL("ftp://") != null;
|
||||||
|
} catch (java.net.MalformedURLException x) {
|
||||||
|
System.out.println("FTP not supported by this runtime.");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,8 +27,11 @@
|
|||||||
* @summary Test URLConnection Request Proterties
|
* @summary Test URLConnection Request Proterties
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLConnection;
|
import java.net.URLConnection;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Part1:
|
* Part1:
|
||||||
@ -45,28 +48,29 @@ public class RequestPropertyValues {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void part1() throws Exception {
|
public static void part1() throws Exception {
|
||||||
URL[] urls = { new URL("http://localhost:8088"),
|
List<URL> urls = new ArrayList<>();
|
||||||
new URL("file:/etc/passwd"),
|
urls.add(new URL("http://localhost:8088"));
|
||||||
new URL("ftp://foo:bar@foobar.com/etc/passwd"),
|
urls.add(new URL("file:/etc/passwd"));
|
||||||
new URL("jar:http://foo.com/bar.html!/foo/bar")
|
urls.add(new URL("jar:http://foo.com/bar.html!/foo/bar"));
|
||||||
};
|
if (hasFtp())
|
||||||
|
urls.add(new URL("ftp://foo:bar@foobar.com/etc/passwd"));
|
||||||
|
|
||||||
boolean failed = false;
|
boolean failed = false;
|
||||||
|
|
||||||
for (int proto = 0; proto < urls.length; proto++) {
|
for (URL url : urls) {
|
||||||
URLConnection uc = (URLConnection) urls[proto].openConnection();
|
URLConnection uc = url.openConnection();
|
||||||
try {
|
try {
|
||||||
uc.setRequestProperty("TestHeader", null);
|
uc.setRequestProperty("TestHeader", null);
|
||||||
} catch (NullPointerException npe) {
|
} catch (NullPointerException npe) {
|
||||||
System.out.println("setRequestProperty is throwing NPE" +
|
System.out.println("setRequestProperty is throwing NPE" +
|
||||||
" for url: " + urls[proto]);
|
" for url: " + url);
|
||||||
failed = true;
|
failed = true;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
uc.addRequestProperty("TestHeader", null);
|
uc.addRequestProperty("TestHeader", null);
|
||||||
} catch (NullPointerException npe) {
|
} catch (NullPointerException npe) {
|
||||||
System.out.println("addRequestProperty is throwing NPE" +
|
System.out.println("addRequestProperty is throwing NPE" +
|
||||||
" for url: " + urls[proto]);
|
" for url: " + url);
|
||||||
failed = true;
|
failed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -110,4 +114,12 @@ public class RequestPropertyValues {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean hasFtp() {
|
||||||
|
try {
|
||||||
|
return new java.net.URL("ftp://") != null;
|
||||||
|
} catch (java.net.MalformedURLException x) {
|
||||||
|
System.out.println("FTP not supported by this runtime.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,6 @@ public class PBETest {
|
|||||||
|
|
||||||
new File(NEW_KEYSTORE).delete();
|
new File(NEW_KEYSTORE).delete();
|
||||||
|
|
||||||
try {
|
|
||||||
KeyStore keystore = load(KEYSTORE_TYPE, KEYSTORE, PASSWORD);
|
KeyStore keystore = load(KEYSTORE_TYPE, KEYSTORE, PASSWORD);
|
||||||
KeyStore.Entry entry =
|
KeyStore.Entry entry =
|
||||||
keystore.getEntry(ALIAS,
|
keystore.getEntry(ALIAS,
|
||||||
@ -73,30 +72,32 @@ public class PBETest {
|
|||||||
new IvParameterSpec(IV))));
|
new IvParameterSpec(IV))));
|
||||||
System.out.println("Encrypted entry using: " + PBE_ALGO);
|
System.out.println("Encrypted entry using: " + PBE_ALGO);
|
||||||
|
|
||||||
|
try (FileOutputStream outStream = new FileOutputStream(NEW_KEYSTORE)) {
|
||||||
System.out.println("Storing keystore to: " + NEW_KEYSTORE);
|
System.out.println("Storing keystore to: " + NEW_KEYSTORE);
|
||||||
keystore2.store(new FileOutputStream(NEW_KEYSTORE), PASSWORD);
|
keystore2.store(outStream, PASSWORD);
|
||||||
|
}
|
||||||
|
|
||||||
keystore2 = load(NEW_KEYSTORE_TYPE, NEW_KEYSTORE, PASSWORD);
|
keystore2 = load(NEW_KEYSTORE_TYPE, NEW_KEYSTORE, PASSWORD);
|
||||||
entry = keystore2.getEntry(ALIAS,
|
entry = keystore2.getEntry(ALIAS,
|
||||||
new KeyStore.PasswordProtection(PASSWORD));
|
new KeyStore.PasswordProtection(PASSWORD));
|
||||||
System.out.println("Retrieved entry named '" + ALIAS + "'");
|
System.out.println("Retrieved entry named '" + ALIAS + "'");
|
||||||
|
|
||||||
} finally {
|
|
||||||
new File(NEW_KEYSTORE).delete();
|
|
||||||
System.out.println("Deleted keystore: " + NEW_KEYSTORE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static KeyStore load(String type, String path, char[] password)
|
private static KeyStore load(String type, String path, char[] password)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
FileInputStream stream = null;
|
|
||||||
if (path != null) {
|
|
||||||
stream = new FileInputStream(path);
|
|
||||||
}
|
|
||||||
KeyStore keystore = KeyStore.getInstance(type);
|
KeyStore keystore = KeyStore.getInstance(type);
|
||||||
|
|
||||||
|
if (path != null) {
|
||||||
|
|
||||||
|
try (FileInputStream inStream = new FileInputStream(path)) {
|
||||||
System.out.println("Loading keystore from: " + path);
|
System.out.println("Loading keystore from: " + path);
|
||||||
keystore.load(stream, password);
|
keystore.load(inStream, password);
|
||||||
|
System.out.println("Loaded keystore with " + keystore.size() +
|
||||||
|
" entries");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
keystore.load(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
return keystore;
|
return keystore;
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test 4235519 8004212
|
* @test 4235519 8004212 8005394 8007298 8006295 8006315 8006530
|
||||||
* @summary tests java.util.Base64
|
* @summary tests java.util.Base64
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -109,6 +109,15 @@ public class TestBase64 {
|
|||||||
|
|
||||||
// test return value from decode(ByteBuffer, ByteBuffer)
|
// test return value from decode(ByteBuffer, ByteBuffer)
|
||||||
testDecBufRet();
|
testDecBufRet();
|
||||||
|
|
||||||
|
// test single-non-base64 character for mime decoding
|
||||||
|
testSingleNonBase64MimeDec();
|
||||||
|
|
||||||
|
// test decoding of unpadded data
|
||||||
|
testDecodeUnpadded();
|
||||||
|
|
||||||
|
// test mime decoding with ignored character after padding
|
||||||
|
testDecodeIgnoredAfterPadding();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static sun.misc.BASE64Encoder sunmisc = new sun.misc.BASE64Encoder();
|
private static sun.misc.BASE64Encoder sunmisc = new sun.misc.BASE64Encoder();
|
||||||
@ -295,6 +304,7 @@ public class TestBase64 {
|
|||||||
checkNull(new Runnable() { public void run() { enc.encode(bb_null); }});
|
checkNull(new Runnable() { public void run() { enc.encode(bb_null); }});
|
||||||
checkNull(new Runnable() { public void run() { enc.encode(bb_null, ByteBuffer.allocate(10), 0); }});
|
checkNull(new Runnable() { public void run() { enc.encode(bb_null, ByteBuffer.allocate(10), 0); }});
|
||||||
checkNull(new Runnable() { public void run() { enc.encode(ByteBuffer.allocate(10), bb_null, 0); }});
|
checkNull(new Runnable() { public void run() { enc.encode(ByteBuffer.allocate(10), bb_null, 0); }});
|
||||||
|
checkNull(new Runnable() { public void run() { enc.wrap(null); }});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void testNull(final Base64.Decoder dec) {
|
private static void testNull(final Base64.Decoder dec) {
|
||||||
@ -305,6 +315,7 @@ public class TestBase64 {
|
|||||||
checkNull(new Runnable() { public void run() { dec.decode(bb_null); }});
|
checkNull(new Runnable() { public void run() { dec.decode(bb_null); }});
|
||||||
checkNull(new Runnable() { public void run() { dec.decode(bb_null, ByteBuffer.allocate(10)); }});
|
checkNull(new Runnable() { public void run() { dec.decode(bb_null, ByteBuffer.allocate(10)); }});
|
||||||
checkNull(new Runnable() { public void run() { dec.decode(ByteBuffer.allocate(10), bb_null); }});
|
checkNull(new Runnable() { public void run() { dec.decode(ByteBuffer.allocate(10), bb_null); }});
|
||||||
|
checkNull(new Runnable() { public void run() { dec.wrap(null); }});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static interface Testable {
|
private static interface Testable {
|
||||||
@ -354,6 +365,94 @@ public class TestBase64 {
|
|||||||
} catch (IllegalArgumentException iae) {}
|
} catch (IllegalArgumentException iae) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void testDecodeIgnoredAfterPadding() throws Throwable {
|
||||||
|
for (byte nonBase64 : new byte[] {'#', '(', '!', '\\', '-', '_', '\n', '\r'}) {
|
||||||
|
byte[][] src = new byte[][] {
|
||||||
|
"A".getBytes("ascii"),
|
||||||
|
"AB".getBytes("ascii"),
|
||||||
|
"ABC".getBytes("ascii"),
|
||||||
|
"ABCD".getBytes("ascii"),
|
||||||
|
"ABCDE".getBytes("ascii")
|
||||||
|
};
|
||||||
|
Base64.Encoder encM = Base64.getMimeEncoder();
|
||||||
|
Base64.Decoder decM = Base64.getMimeDecoder();
|
||||||
|
Base64.Encoder enc = Base64.getEncoder();
|
||||||
|
Base64.Decoder dec = Base64.getDecoder();
|
||||||
|
for (int i = 0; i < src.length; i++) {
|
||||||
|
// decode(byte[])
|
||||||
|
byte[] encoded = encM.encode(src[i]);
|
||||||
|
encoded = Arrays.copyOf(encoded, encoded.length + 1);
|
||||||
|
encoded[encoded.length - 1] = nonBase64;
|
||||||
|
checkEqual(decM.decode(encoded), src[i], "Non-base64 char is not ignored");
|
||||||
|
try {
|
||||||
|
dec.decode(encoded);
|
||||||
|
throw new RuntimeException("No IAE for non-base64 char");
|
||||||
|
} catch (IllegalArgumentException iae) {}
|
||||||
|
|
||||||
|
// decode(ByteBuffer[], ByteBuffer[])
|
||||||
|
ByteBuffer encodedBB = ByteBuffer.wrap(encoded);
|
||||||
|
ByteBuffer decodedBB = ByteBuffer.allocate(100);
|
||||||
|
int ret = decM.decode(encodedBB, decodedBB);
|
||||||
|
byte[] buf = new byte[ret];
|
||||||
|
decodedBB.flip();
|
||||||
|
decodedBB.get(buf);
|
||||||
|
checkEqual(buf, src[i], "Non-base64 char is not ignored");
|
||||||
|
try {
|
||||||
|
encodedBB.rewind();
|
||||||
|
decodedBB.clear();
|
||||||
|
dec.decode(encodedBB, decodedBB);
|
||||||
|
throw new RuntimeException("No IAE for non-base64 char");
|
||||||
|
} catch (IllegalArgumentException iae) {}
|
||||||
|
// direct
|
||||||
|
encodedBB.rewind();
|
||||||
|
decodedBB = ByteBuffer.allocateDirect(100);
|
||||||
|
ret = decM.decode(encodedBB, decodedBB);
|
||||||
|
buf = new byte[ret];
|
||||||
|
decodedBB.flip();
|
||||||
|
decodedBB.get(buf);
|
||||||
|
checkEqual(buf, src[i], "Non-base64 char is not ignored");
|
||||||
|
try {
|
||||||
|
encodedBB.rewind();
|
||||||
|
decodedBB.clear();
|
||||||
|
dec.decode(encodedBB, decodedBB);
|
||||||
|
throw new RuntimeException("No IAE for non-base64 char");
|
||||||
|
} catch (IllegalArgumentException iae) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testDecodeUnpadded() throws Throwable {
|
||||||
|
byte[] srcA = new byte[] { 'Q', 'Q' };
|
||||||
|
byte[] srcAA = new byte[] { 'Q', 'Q', 'E'};
|
||||||
|
Base64.Decoder dec = Base64.getDecoder();
|
||||||
|
byte[] ret = dec.decode(srcA);
|
||||||
|
if (ret[0] != 'A')
|
||||||
|
throw new RuntimeException("Decoding unpadding input A failed");
|
||||||
|
ret = dec.decode(srcAA);
|
||||||
|
if (ret[0] != 'A' && ret[1] != 'A')
|
||||||
|
throw new RuntimeException("Decoding unpadding input AA failed");
|
||||||
|
ret = new byte[10];
|
||||||
|
if (dec.wrap(new ByteArrayInputStream(srcA)).read(ret) != 1 &&
|
||||||
|
ret[0] != 'A')
|
||||||
|
throw new RuntimeException("Decoding unpadding input A from stream failed");
|
||||||
|
if (dec.wrap(new ByteArrayInputStream(srcA)).read(ret) != 2 &&
|
||||||
|
ret[0] != 'A' && ret[1] != 'A')
|
||||||
|
throw new RuntimeException("Decoding unpadding input AA from stream failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
// single-non-base64-char should be ignored for mime decoding, but
|
||||||
|
// iae for basic decoding
|
||||||
|
private static void testSingleNonBase64MimeDec() throws Throwable {
|
||||||
|
for (String nonBase64 : new String[] {"#", "(", "!", "\\", "-", "_"}) {
|
||||||
|
if (Base64.getMimeDecoder().decode(nonBase64).length != 0) {
|
||||||
|
throw new RuntimeException("non-base64 char is not ignored");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Base64.getDecoder().decode(nonBase64);
|
||||||
|
throw new RuntimeException("No IAE for single non-base64 char");
|
||||||
|
} catch (IllegalArgumentException iae) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void testDecBufRet() throws Throwable {
|
private static void testDecBufRet() throws Throwable {
|
||||||
Random rnd = new java.util.Random();
|
Random rnd = new java.util.Random();
|
||||||
|
@ -1103,6 +1103,15 @@ public class Basic$Type$ extends Basic {
|
|||||||
test("%.5f", "1.99999", val);
|
test("%.5f", "1.99999", val);
|
||||||
test("%.6f", "1.999990", val);
|
test("%.6f", "1.999990", val);
|
||||||
|
|
||||||
|
val = new BigDecimal(0.9996);
|
||||||
|
test("%.0f", "1", val);
|
||||||
|
test("%.1f", "1.0", val);
|
||||||
|
test("%.2f", "1.00", val);
|
||||||
|
test("%.3f", "1.000", val);
|
||||||
|
test("%.4f", "0.9996", val);
|
||||||
|
test("%.5f", "0.99960", val);
|
||||||
|
test("%.6f", "0.999600", val);
|
||||||
|
|
||||||
#end[BigDecimal]
|
#end[BigDecimal]
|
||||||
|
|
||||||
#if[float]
|
#if[float]
|
||||||
|
@ -1102,6 +1102,15 @@ public class BasicBigDecimal extends Basic {
|
|||||||
test("%.4f", "2.0000", val);
|
test("%.4f", "2.0000", val);
|
||||||
test("%.5f", "1.99999", val);
|
test("%.5f", "1.99999", val);
|
||||||
test("%.6f", "1.999990", val);
|
test("%.6f", "1.999990", val);
|
||||||
|
|
||||||
|
val = new BigDecimal(0.9996);
|
||||||
|
test("%.0f", "1", val);
|
||||||
|
test("%.1f", "1.0", val);
|
||||||
|
test("%.2f", "1.00", val);
|
||||||
|
test("%.3f", "1.000", val);
|
||||||
|
test("%.4f", "0.9996", val);
|
||||||
|
test("%.5f", "0.99960", val);
|
||||||
|
test("%.6f", "0.999600", val);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
70
jdk/test/java/util/HashMap/HashMapCloneLeak.java
Normal file
70
jdk/test/java/util/HashMap/HashMapCloneLeak.java
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013, 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 7042126
|
||||||
|
* @summary Verify that we do not leak contents when we clone a HashMap
|
||||||
|
* @author david.buck@oracle.com
|
||||||
|
* @run main/othervm HashMapCloneLeak
|
||||||
|
* @run main/othervm -XX:+AggressiveOpts HashMapCloneLeak
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
public class HashMapCloneLeak {
|
||||||
|
|
||||||
|
static WeakReference<Object> wr = null;
|
||||||
|
|
||||||
|
// helper method to keep testObject and map out of main method's scope
|
||||||
|
private static HashMap<Integer, Object> makeMap() {
|
||||||
|
HashMap<Integer, Object> map = new HashMap<Integer, Object>();
|
||||||
|
Object testObject = new Object();
|
||||||
|
wr = new WeakReference<Object>(testObject);
|
||||||
|
map.put(42, testObject);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
HashMap<Integer, Object> hm = makeMap();
|
||||||
|
hm = (HashMap<Integer, Object>)hm.clone();
|
||||||
|
hm.clear();
|
||||||
|
// There should no longer be a strong reference to testObject
|
||||||
|
// the WeakReference should be nulled out by GC. If not,
|
||||||
|
// we will hang here until timed out by the test harness.
|
||||||
|
Object[] chain = null;
|
||||||
|
while (wr.get() != null) {
|
||||||
|
try {
|
||||||
|
Object[] allocate = new Object[1000000];
|
||||||
|
allocate[0] = chain;
|
||||||
|
chain = allocate;
|
||||||
|
} catch (OutOfMemoryError oome) {
|
||||||
|
chain = null;
|
||||||
|
}
|
||||||
|
System.gc();
|
||||||
|
Thread.sleep(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -31,6 +31,7 @@
|
|||||||
import com.sun.jmx.remote.internal.ServerNotifForwarder;
|
import com.sun.jmx.remote.internal.ServerNotifForwarder;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.management.ManagementFactory;
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -86,20 +87,26 @@ public class DeadListenerTest {
|
|||||||
Map<ObjectName, Set<?>> listenerMap = (Map<ObjectName, Set<?>>) listenerMapF.get(serverNotifForwarder);
|
Map<ObjectName, Set<?>> listenerMap = (Map<ObjectName, Set<?>>) listenerMapF.get(serverNotifForwarder);
|
||||||
assertTrue("Server listenerMap initially empty", mapWithoutKey(listenerMap, delegateName).isEmpty());
|
assertTrue("Server listenerMap initially empty", mapWithoutKey(listenerMap, delegateName).isEmpty());
|
||||||
|
|
||||||
CountListener count1 = new CountListener();
|
final AtomicInteger count1Val = new AtomicInteger();
|
||||||
|
CountListener count1 = new CountListener(count1Val);
|
||||||
mbsc.addNotificationListener(name, count1, null, null);
|
mbsc.addNotificationListener(name, count1, null, null);
|
||||||
|
WeakReference<CountListener> count1Ref = new WeakReference<>(count1);
|
||||||
|
count1 = null;
|
||||||
|
|
||||||
CountListener count2 = new CountListener();
|
final AtomicInteger count2Val = new AtomicInteger();
|
||||||
|
CountListener count2 = new CountListener(count2Val);
|
||||||
NotificationFilterSupport dummyFilter = new NotificationFilterSupport();
|
NotificationFilterSupport dummyFilter = new NotificationFilterSupport();
|
||||||
dummyFilter.enableType("");
|
dummyFilter.enableType("");
|
||||||
mbsc.addNotificationListener(name, count2, dummyFilter, "noddy");
|
mbsc.addNotificationListener(name, count2, dummyFilter, "noddy");
|
||||||
|
WeakReference<CountListener> count2Ref = new WeakReference<>(count2);
|
||||||
|
count2 = null;
|
||||||
|
|
||||||
assertTrue("One entry in listenerMap for two listeners on same MBean", mapWithoutKey(listenerMap, delegateName).size() == 1);
|
assertTrue("One entry in listenerMap for two listeners on same MBean", mapWithoutKey(listenerMap, delegateName).size() == 1);
|
||||||
Set<?> set = listenerMap.get(name);
|
Set<?> set = listenerMap.get(name);
|
||||||
assertTrue("Set in listenerMap for MBean has two elements", set != null && set.size() == 2);
|
assertTrue("Set in listenerMap for MBean has two elements", set != null && set.size() == 2);
|
||||||
|
|
||||||
assertTrue("Initial value of count1 == 0", count1.count() == 0);
|
assertTrue("Initial value of count1 == 0", count1Val.get() == 0);
|
||||||
assertTrue("Initial value of count2 == 0", count2.count() == 0);
|
assertTrue("Initial value of count2 == 0", count2Val.get() == 0);
|
||||||
|
|
||||||
Notification notif = new Notification("type", name, 0);
|
Notification notif = new Notification("type", name, 0);
|
||||||
|
|
||||||
@ -107,11 +114,11 @@ public class DeadListenerTest {
|
|||||||
|
|
||||||
// Make sure notifs are working normally.
|
// Make sure notifs are working normally.
|
||||||
long deadline = System.currentTimeMillis() + 2000;
|
long deadline = System.currentTimeMillis() + 2000;
|
||||||
while ((count1.count() != 1 || count2.count() != 1) && System.currentTimeMillis() < deadline) {
|
while ((count1Val.get() != 1 || count2Val.get() != 1) && System.currentTimeMillis() < deadline) {
|
||||||
Thread.sleep(10);
|
Thread.sleep(10);
|
||||||
}
|
}
|
||||||
assertTrue("New value of count1 == 1", count1.count() == 1);
|
assertTrue("New value of count1 == 1", count1Val.get() == 1);
|
||||||
assertTrue("Initial value of count2 == 1", count2.count() == 1);
|
assertTrue("Initial value of count2 == 1", count2Val.get() == 1);
|
||||||
|
|
||||||
// Make sure that removing a nonexistent listener from an existent MBean produces ListenerNotFoundException
|
// Make sure that removing a nonexistent listener from an existent MBean produces ListenerNotFoundException
|
||||||
CountListener count3 = new CountListener();
|
CountListener count3 = new CountListener();
|
||||||
@ -136,28 +143,29 @@ public class DeadListenerTest {
|
|||||||
mbs.unregisterMBean(name);
|
mbs.unregisterMBean(name);
|
||||||
mbean.sendNotification(notif);
|
mbean.sendNotification(notif);
|
||||||
Thread.sleep(200);
|
Thread.sleep(200);
|
||||||
assertTrue("New value of count1 == 1", count1.count() == 1);
|
|
||||||
assertTrue("Initial value of count2 == 1", count2.count() == 1);
|
assertTrue("New value of count1 == 1", count1Val.get() == 1);
|
||||||
|
assertTrue("Initial value of count2 == 1", count2Val.get() == 1);
|
||||||
|
|
||||||
|
// wait for the listener cleanup to take place upon processing notifications
|
||||||
|
int countdown = 50; // waiting max. 5 secs
|
||||||
|
while (countdown-- > 0 &&
|
||||||
|
(count1Ref.get() != null ||
|
||||||
|
count2Ref.get() != null)) {
|
||||||
|
System.gc();
|
||||||
|
Thread.sleep(100);
|
||||||
|
System.gc();
|
||||||
|
}
|
||||||
|
// listener has been removed or the wait has timed out
|
||||||
|
|
||||||
|
assertTrue("count1 notification listener has not been cleaned up", count1Ref.get() == null);
|
||||||
|
assertTrue("count2 notification listener has not been cleaned up", count2Ref.get() == null);
|
||||||
|
|
||||||
// Check that there is no trace of the listeners any more in ServerNotifForwarder.listenerMap.
|
// Check that there is no trace of the listeners any more in ServerNotifForwarder.listenerMap.
|
||||||
// THIS DEPENDS ON JMX IMPLEMENTATION DETAILS.
|
// THIS DEPENDS ON JMX IMPLEMENTATION DETAILS.
|
||||||
// If the JMX implementation changes, the code here may have to change too.
|
// If the JMX implementation changes, the code here may have to change too.
|
||||||
Set<?> setForUnreg = listenerMap.get(name);
|
Set<?> setForUnreg = listenerMap.get(name);
|
||||||
assertTrue("No trace of unregistered MBean: " + setForUnreg, setForUnreg == null);
|
assertTrue("No trace of unregistered MBean: " + setForUnreg, setForUnreg == null);
|
||||||
|
|
||||||
// Remove attempts should fail.
|
|
||||||
try {
|
|
||||||
mbsc.removeNotificationListener(name, count1);
|
|
||||||
assertTrue("Remove of count1 listener should have failed", false);
|
|
||||||
} catch (ListenerNotFoundException e) {
|
|
||||||
// OK: expected
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
mbsc.removeNotificationListener(name, count2, dummyFilter, "noddy");
|
|
||||||
assertTrue("Remove of count2 listener should have failed", false);
|
|
||||||
} catch (ListenerNotFoundException e) {
|
|
||||||
// OK: expected
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <K, V> Map<K, V> mapWithoutKey(Map<K, V> map, K key) {
|
private static <K, V> Map<K, V> mapWithoutKey(Map<K, V> map, K key) {
|
||||||
@ -173,6 +181,10 @@ public class DeadListenerTest {
|
|||||||
public static class CountListener implements NotificationListener {
|
public static class CountListener implements NotificationListener {
|
||||||
final AtomicInteger count;
|
final AtomicInteger count;
|
||||||
|
|
||||||
|
public CountListener(AtomicInteger i) {
|
||||||
|
count = i;
|
||||||
|
}
|
||||||
|
|
||||||
public CountListener() {
|
public CountListener() {
|
||||||
this.count = new AtomicInteger();
|
this.count = new AtomicInteger();
|
||||||
}
|
}
|
||||||
|
160
jdk/test/sun/management/jdp/JdpClient.java
Normal file
160
jdk/test/sun/management/jdp/JdpClient.java
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.Inet6Address;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.NetworkInterface;
|
||||||
|
import java.net.ProtocolFamily;
|
||||||
|
import java.net.StandardProtocolFamily;
|
||||||
|
import java.net.StandardSocketOptions;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.channels.DatagramChannel;
|
||||||
|
import java.nio.channels.SelectionKey;
|
||||||
|
import java.nio.channels.Selector;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import sun.management.jdp.JdpException;
|
||||||
|
import sun.management.jdp.JdpJmxPacket;
|
||||||
|
|
||||||
|
public class JdpClient {
|
||||||
|
|
||||||
|
private static class PacketListener implements Runnable {
|
||||||
|
|
||||||
|
private static final int BUFFER_LENGTH = 4096;
|
||||||
|
private final DatagramChannel channel;
|
||||||
|
private static int maxPacketCount = 1;
|
||||||
|
private static int maxEmptyPacketCount = 10;
|
||||||
|
|
||||||
|
|
||||||
|
PacketListener(DatagramChannel channel) {
|
||||||
|
this.channel = channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@java.lang.Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
Selector sel;
|
||||||
|
sel = Selector.open();
|
||||||
|
channel.configureBlocking(false);
|
||||||
|
channel.register(sel, SelectionKey.OP_READ);
|
||||||
|
ByteBuffer buf = ByteBuffer.allocate(1024);
|
||||||
|
|
||||||
|
int count = 1;
|
||||||
|
int emptyPacketsCount = 1;
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
|
||||||
|
sel.selectedKeys().clear();
|
||||||
|
buf.rewind();
|
||||||
|
|
||||||
|
sel.select(10 * 1000);
|
||||||
|
channel.receive(buf);
|
||||||
|
|
||||||
|
if (buf.position() == 0 ){
|
||||||
|
if (JdpDoSomething.getVerbose()){
|
||||||
|
System.err.println("Empty packet received");
|
||||||
|
}
|
||||||
|
if (++emptyPacketsCount > maxEmptyPacketCount){
|
||||||
|
throw new RuntimeException("Test failed, maxEmptyPacketCount reached");
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.flip();
|
||||||
|
byte[] dgramData = new byte[buf.remaining()];
|
||||||
|
buf.get(dgramData);
|
||||||
|
|
||||||
|
try {
|
||||||
|
JdpJmxPacket packet = new JdpJmxPacket(dgramData);
|
||||||
|
JdpDoSomething.printJdpPacket(packet);
|
||||||
|
if(++count > maxPacketCount){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (JdpException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new RuntimeException("Test failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("OK: Test passed");
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
sel.close();
|
||||||
|
channel.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new RuntimeException("Test failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
try {
|
||||||
|
String discoveryPort = System.getProperty("com.sun.management.jdp.port");
|
||||||
|
String discoveryAddress = System.getProperty("com.sun.management.jdp.address");
|
||||||
|
if (discoveryAddress == null || discoveryPort == null) {
|
||||||
|
System.out.println("Test failed. address and port must be specified");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int port = Integer.parseInt(discoveryPort);
|
||||||
|
InetAddress address = InetAddress.getByName(discoveryAddress);
|
||||||
|
|
||||||
|
|
||||||
|
ProtocolFamily family = (address instanceof Inet6Address)
|
||||||
|
? StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
|
||||||
|
|
||||||
|
DatagramChannel channel;
|
||||||
|
|
||||||
|
channel = DatagramChannel.open(family);
|
||||||
|
channel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
|
||||||
|
channel.bind(new InetSocketAddress(port));
|
||||||
|
|
||||||
|
Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
|
||||||
|
for (NetworkInterface interf : Collections.list(nets)) {
|
||||||
|
if (interf.supportsMulticast()) {
|
||||||
|
try {
|
||||||
|
channel.join(address, interf);
|
||||||
|
} catch (IOException e) {
|
||||||
|
// Skip not configured interfaces
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PacketListener listener = new PacketListener(channel);
|
||||||
|
new Thread(listener, "Jdp Client").start();
|
||||||
|
|
||||||
|
} catch (RuntimeException e){
|
||||||
|
System.out.println("Test failed.");
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
System.out.println("Test failed. unexpected error " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
103
jdk/test/sun/management/jdp/JdpDoSomething.java
Normal file
103
jdk/test/sun/management/jdp/JdpDoSomething.java
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.RandomAccessFile;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import sun.management.jdp.JdpJmxPacket;
|
||||||
|
import sun.management.jdp.JdpException;
|
||||||
|
|
||||||
|
public class JdpDoSomething {
|
||||||
|
|
||||||
|
private static final String lockFileName = "JdpDoSomething.lck";
|
||||||
|
private static final boolean verbose=false;
|
||||||
|
|
||||||
|
public static boolean getVerbose(){
|
||||||
|
return verbose;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void printJdpPacket(JdpJmxPacket p) {
|
||||||
|
if (getVerbose()) {
|
||||||
|
try {
|
||||||
|
RandomAccessFile f = new RandomAccessFile("out.dmp", "rw");
|
||||||
|
f.write(p.getPacketData());
|
||||||
|
f.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.out.println("Can't write a dump file: " + e);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("Id: " + p.getId());
|
||||||
|
System.out.println("Jmx: " + p.getJmxServiceUrl());
|
||||||
|
System.out.println("Main: " + p.getMainClass());
|
||||||
|
System.out.println("InstanceName: " + p.getInstanceName());
|
||||||
|
|
||||||
|
System.out.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void compaireJdpPacketEx(JdpJmxPacket p1, JdpJmxPacket p2)
|
||||||
|
throws JdpException {
|
||||||
|
|
||||||
|
if (!Objects.equals(p1, p1)) {
|
||||||
|
throw new JdpException("Packet mismatch error");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Objects.equals(p1.getMainClass(), p2.getMainClass())) {
|
||||||
|
throw new JdpException("Packet mismatch error (main class)");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Objects.equals(p1.getInstanceName(), p2.getInstanceName())) {
|
||||||
|
throw new JdpException("Packet mismatch error (instance name)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void doSomething() {
|
||||||
|
try {
|
||||||
|
File lockFile = new File(lockFileName);
|
||||||
|
lockFile.createNewFile();
|
||||||
|
|
||||||
|
while (lockFile.exists()) {
|
||||||
|
long datetime = lockFile.lastModified();
|
||||||
|
long epoch = System.currentTimeMillis() / 1000;
|
||||||
|
|
||||||
|
// Don't allow test app to run more than an hour
|
||||||
|
if (epoch - datetime > 3600) {
|
||||||
|
System.err.println("Lock is too old. Aborting");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Thread.sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Throwable e) {
|
||||||
|
System.err.println("Something bad happens:" + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String args[]) throws Exception {
|
||||||
|
System.err.println("main enter");
|
||||||
|
doSomething();
|
||||||
|
System.err.println("main exit");
|
||||||
|
}
|
||||||
|
}
|
323
jdk/test/sun/management/jdp/JdpTest.sh
Normal file
323
jdk/test/sun/management/jdp/JdpTest.sh
Normal file
@ -0,0 +1,323 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Copyright (c) 2011, 2012 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 7169888
|
||||||
|
# @build JdpUnitTest JdpClient JdpDoSomething
|
||||||
|
# @run shell JdpTest.sh --jtreg --no-compile
|
||||||
|
# @summary No word Failed expected in the test output
|
||||||
|
|
||||||
|
_verbose=no
|
||||||
|
_jtreg=no
|
||||||
|
_compile=yes
|
||||||
|
|
||||||
|
# temporary disable jcmd related tests
|
||||||
|
# _testsuite="01,02,03,04,05"
|
||||||
|
_testsuite="01,02,04"
|
||||||
|
|
||||||
|
_pwd=`pwd`
|
||||||
|
|
||||||
|
_testclasses=".classes"
|
||||||
|
_testsrc="${_pwd}"
|
||||||
|
_lockFileName="JdpDoSomething.lck"
|
||||||
|
|
||||||
|
_logname=".classes/output.txt"
|
||||||
|
_last_pid=""
|
||||||
|
|
||||||
|
|
||||||
|
_compile(){
|
||||||
|
|
||||||
|
if [ ! -e ${_testclasses} ]
|
||||||
|
then
|
||||||
|
mkdir -p ${_testclasses}
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f ${_testclasses}/*.class
|
||||||
|
|
||||||
|
# Compile testcase
|
||||||
|
${TESTJAVA}/bin/javac -d ${_testclasses} JdpUnitTest.java \
|
||||||
|
JdpDoSomething.java \
|
||||||
|
JdpClient.java
|
||||||
|
|
||||||
|
|
||||||
|
if [ ! -e ${_testclasses}/JdpDoSomething.class -o ! -e ${_testclasses}/JdpClient.class -o ! -e ${_testclasses}/JdpUnitTest.class ]
|
||||||
|
then
|
||||||
|
echo "ERROR: Can't compile"
|
||||||
|
exit -1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_app_start(){
|
||||||
|
|
||||||
|
testappname=$1
|
||||||
|
shift
|
||||||
|
|
||||||
|
${TESTJAVA}/bin/java -server $* -cp ${_testclasses} ${testappname} >> ${_logname} 2>&1 &
|
||||||
|
_last_pid=$!
|
||||||
|
|
||||||
|
npid=`_get_pid`
|
||||||
|
if [ "${npid}" = "" ]
|
||||||
|
then
|
||||||
|
echo "ERROR: Test app not started"
|
||||||
|
if [ "${_jtreg}" = "yes" ]
|
||||||
|
then
|
||||||
|
exit -1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_get_pid(){
|
||||||
|
${TESTJAVA}/bin/jps | sed -n "/Jdp/s/ .*//p"
|
||||||
|
}
|
||||||
|
|
||||||
|
_app_stop(){
|
||||||
|
rm ${_lockFileName}
|
||||||
|
|
||||||
|
# wait until VM is actually shuts down
|
||||||
|
while true
|
||||||
|
do
|
||||||
|
npid=`_get_pid`
|
||||||
|
if [ "${npid}" = "" ]
|
||||||
|
then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
_testme(){
|
||||||
|
${TESTJAVA}/bin/java \
|
||||||
|
-cp ${_testclasses} \
|
||||||
|
$* \
|
||||||
|
-Dcom.sun.management.jdp.port=7095 \
|
||||||
|
-Dcom.sun.management.jdp.address=239.255.255.225 \
|
||||||
|
JdpClient
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_jcmd(){
|
||||||
|
${TESTJAVA}/bin/jcmd JdpDoSomething $* > /dev/null 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_echo(){
|
||||||
|
echo "$*"
|
||||||
|
echo "$*" >> ${_logname}
|
||||||
|
}
|
||||||
|
|
||||||
|
# ============= TESTS ======================================
|
||||||
|
|
||||||
|
test_01(){
|
||||||
|
|
||||||
|
_echo "**** Test one ****"
|
||||||
|
|
||||||
|
_app_start JdpUnitTest \
|
||||||
|
-Dcom.sun.management.jdp.port=7095 \
|
||||||
|
-Dcom.sun.management.jdp.address=239.255.255.225 \
|
||||||
|
-Dcom.sun.management.jdp.pause=5
|
||||||
|
|
||||||
|
res=`_testme`
|
||||||
|
|
||||||
|
case "${res}" in
|
||||||
|
OK*)
|
||||||
|
_echo "Passed"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
_echo "Failed!"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
_app_stop
|
||||||
|
}
|
||||||
|
|
||||||
|
test_02(){
|
||||||
|
|
||||||
|
_echo "**** Test two ****"
|
||||||
|
|
||||||
|
_app_start JdpDoSomething \
|
||||||
|
-Dcom.sun.management.jdp.port=7095 \
|
||||||
|
-Dcom.sun.management.jdp.address=239.255.255.225 \
|
||||||
|
-Dcom.sun.management.jdp.pause=5 \
|
||||||
|
-Dcom.sun.management.jmxremote.port=4545 \
|
||||||
|
-Dcom.sun.management.jmxremote.authenticate=false \
|
||||||
|
-Dcom.sun.management.jmxremote.ssl=false
|
||||||
|
|
||||||
|
res=`_testme`
|
||||||
|
|
||||||
|
case "${res}" in
|
||||||
|
OK*)
|
||||||
|
_echo "Passed"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
_echo "Failed!"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
_app_stop
|
||||||
|
}
|
||||||
|
|
||||||
|
test_03(){
|
||||||
|
|
||||||
|
_echo "**** Test three ****"
|
||||||
|
|
||||||
|
_app_start JdpDoSomething
|
||||||
|
|
||||||
|
_jcmd ManagementAgent.start\
|
||||||
|
jdp.port=7095 \
|
||||||
|
jdp.address=239.255.255.225 \
|
||||||
|
jdp.pause=5 \
|
||||||
|
jmxremote.port=4545 \
|
||||||
|
jmxremote.authenticate=false \
|
||||||
|
jmxremote.ssl=false
|
||||||
|
|
||||||
|
res=`_testme`
|
||||||
|
|
||||||
|
case "${res}" in
|
||||||
|
OK*)
|
||||||
|
_echo "Passed"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
_echo "Failed!"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
_app_stop
|
||||||
|
}
|
||||||
|
|
||||||
|
test_04(){
|
||||||
|
|
||||||
|
_echo "**** Test four ****"
|
||||||
|
|
||||||
|
_app_start JdpDoSomething \
|
||||||
|
-Dcom.sun.management.jmxremote.autodiscovery=true \
|
||||||
|
-Dcom.sun.management.jmxremote.port=4545 \
|
||||||
|
-Dcom.sun.management.jmxremote.authenticate=false \
|
||||||
|
-Dcom.sun.management.jmxremote.ssl=false
|
||||||
|
|
||||||
|
res=`_testme`
|
||||||
|
|
||||||
|
case "${res}" in
|
||||||
|
OK*)
|
||||||
|
_echo "Passed"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
_echo "Failed!"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
_app_stop
|
||||||
|
}
|
||||||
|
|
||||||
|
test_05(){
|
||||||
|
|
||||||
|
_echo "**** Test five ****"
|
||||||
|
|
||||||
|
_app_start JdpDoSomething
|
||||||
|
|
||||||
|
_jcmd ManagementAgent.start\
|
||||||
|
jmxremote.autodiscovery=true \
|
||||||
|
jmxremote.port=4545 \
|
||||||
|
jmxremote.authenticate=false \
|
||||||
|
jmxremote.ssl=false
|
||||||
|
|
||||||
|
|
||||||
|
res=`_testme`
|
||||||
|
|
||||||
|
case "${res}" in
|
||||||
|
OK*)
|
||||||
|
_echo "Passed"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
_echo "Failed!"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
_app_stop
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# ============= MAIN =======================================
|
||||||
|
|
||||||
|
if [ "x${TESTJAVA}" = "x" ]
|
||||||
|
then
|
||||||
|
echo "TESTJAVA env have to be set"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# reading parameters
|
||||||
|
|
||||||
|
for parm in "$@"
|
||||||
|
do
|
||||||
|
case $parm in
|
||||||
|
--verbose) _verbose=yes ;;
|
||||||
|
--jtreg) _jtreg=yes ;;
|
||||||
|
--no-compile) _compile=no ;;
|
||||||
|
--testsuite=*) _testsuite=`_echo $parm | sed "s,^--.*=\(.*\),\1,"` ;;
|
||||||
|
*)
|
||||||
|
echo "Undefined parameter $parm. Try --help for help"
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ ${_compile} = "yes" ]
|
||||||
|
then
|
||||||
|
_compile
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ${_jtreg} = "yes" ]
|
||||||
|
then
|
||||||
|
_testclasses=${TESTCLASSES}
|
||||||
|
_testsrc=${TESTSRC}
|
||||||
|
_logname="output.txt"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Make sure _tesclasses is absolute path
|
||||||
|
tt=`echo ${_testclasses} | sed -e 's,/,,'`
|
||||||
|
if [ ${tt} = ${_testclasses} ]
|
||||||
|
then
|
||||||
|
_testclasses="${_pwd}/${_testclasses}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_policyname="${_testclasses}/policy"
|
||||||
|
|
||||||
|
rm -f ${_logname}
|
||||||
|
rm -f ${_policyname}
|
||||||
|
|
||||||
|
if [ -e ${_testsrc}/policy.tpl ]
|
||||||
|
then
|
||||||
|
|
||||||
|
cat ${_testsrc}/policy.tpl | \
|
||||||
|
sed -e "s,@_TESTCLASSES@,${_testclasses},g" -e "s,@TESTJAVA@,${TESTJAVA},g" \
|
||||||
|
> ${_policyname}
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Local mode tests
|
||||||
|
for i in `echo ${_testsuite} | sed -e "s/,/ /g"`
|
||||||
|
do
|
||||||
|
test_${i}
|
||||||
|
done
|
90
jdk/test/sun/management/jdp/JdpUnitTest.java
Normal file
90
jdk/test/sun/management/jdp/JdpUnitTest.java
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import sun.management.jdp.JdpController;
|
||||||
|
import sun.management.jdp.JdpPacket;
|
||||||
|
import sun.management.jdp.JdpJmxPacket;
|
||||||
|
import sun.management.jdp.JdpException;
|
||||||
|
|
||||||
|
public class JdpUnitTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test tests that complete packet is build correctly
|
||||||
|
*/
|
||||||
|
public static void PacketBuilderTest()
|
||||||
|
throws IOException, JdpException {
|
||||||
|
|
||||||
|
/* Complete packet test */
|
||||||
|
{
|
||||||
|
JdpJmxPacket p1 = new JdpJmxPacket(UUID.randomUUID(), "fake://unit-test");
|
||||||
|
p1.setMainClass("FakeUnitTest");
|
||||||
|
p1.setInstanceName("Fake");
|
||||||
|
byte[] b = p1.getPacketData();
|
||||||
|
|
||||||
|
JdpJmxPacket p2 = new JdpJmxPacket(b);
|
||||||
|
JdpDoSomething.printJdpPacket(p1);
|
||||||
|
JdpDoSomething.compaireJdpPacketEx(p1, p2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Missed field packet test*/
|
||||||
|
{
|
||||||
|
JdpJmxPacket p1 = new JdpJmxPacket(UUID.randomUUID(), "fake://unit-test");
|
||||||
|
p1.setMainClass("FakeUnitTest");
|
||||||
|
p1.setInstanceName(null);
|
||||||
|
byte[] b = p1.getPacketData();
|
||||||
|
|
||||||
|
JdpJmxPacket p2 = new JdpJmxPacket(b);
|
||||||
|
JdpDoSomething.printJdpPacket(p1);
|
||||||
|
JdpDoSomething.compaireJdpPacketEx(p1, p2);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("OK: Test passed");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void startFakeDiscoveryService()
|
||||||
|
throws IOException, JdpException {
|
||||||
|
|
||||||
|
String discoveryPort = System.getProperty("com.sun.management.jdp.port");
|
||||||
|
String discoveryAddress = System.getProperty("com.sun.management.jdp.address");
|
||||||
|
InetAddress address = InetAddress.getByName(discoveryAddress);
|
||||||
|
int port = Integer.parseInt(discoveryPort);
|
||||||
|
JdpController.startDiscoveryService(address, port, "FakeDiscovery", "fake://unit-test");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
try {
|
||||||
|
PacketBuilderTest();
|
||||||
|
startFakeDiscoveryService();
|
||||||
|
JdpDoSomething.doSomething();
|
||||||
|
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
System.out.println("Test failed. unexpected error " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -161,8 +161,18 @@ public class ProxyTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean hasFtp() {
|
||||||
|
try {
|
||||||
|
return new java.net.URL("ftp://") != null;
|
||||||
|
} catch (java.net.MalformedURLException x) {
|
||||||
|
System.out.println("FTP not supported by this runtime.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
ProxyTest test = new ProxyTest();
|
if (hasFtp())
|
||||||
|
new ProxyTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProxyTest() throws Exception {
|
public ProxyTest() throws Exception {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user