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>
|
||||
<built-to>${root}/build/${platform}-${arch}/classes</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>
|
||||
<package-root>${root}/test</package-root>
|
||||
<unit-tests/>
|
||||
<source-level>1.7</source-level>
|
||||
<source-level>1.8</source-level>
|
||||
</compilation-unit>
|
||||
</java-data>
|
||||
|
@ -37,11 +37,11 @@
|
||||
<classpath mode="boot">${bootstrap.jdk}/jre/lib/rt.jar</classpath>
|
||||
<built-to>${root}/build/${platform}-${arch}/classes</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>
|
||||
<package-root>${root}/test</package-root>
|
||||
<unit-tests/>
|
||||
<source-level>1.7</source-level>
|
||||
<source-level>1.8</source-level>
|
||||
</compilation-unit>
|
||||
</java-data>
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
<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 -->
|
||||
</target>
|
||||
|
||||
@ -42,6 +42,11 @@
|
||||
<property name="make" value="make"/>
|
||||
</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">
|
||||
<property name="platform" value="solaris"/>
|
||||
<property name="make" value="gmake"/>
|
||||
|
@ -85,6 +85,9 @@
|
||||
<property name="includes" value="(nothing)"/>
|
||||
<property name="excludes" value=""/>
|
||||
<property name="javadoc.dir" location="${build.dir}/javadoc/${ant.project.name}"/>
|
||||
<condition property="os.macosx">
|
||||
<os family="mac"/>
|
||||
</condition>
|
||||
<condition property="os.linux">
|
||||
<os name="linux"/>
|
||||
</condition>
|
||||
@ -126,10 +129,6 @@
|
||||
<javac srcdir="@{srcdir}" includes="@{includes}" excludes="@{excludes}" sourcepath=""
|
||||
destdir="@{classesdir}" fork="true" executable="${bootstrap.javac}"
|
||||
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: -->
|
||||
<compilerarg value="-XDignore.symbol.file=true"/>
|
||||
<compilerarg line="${javac.options}"/>
|
||||
|
@ -1287,19 +1287,24 @@ class Attribute implements Comparable<Attribute> {
|
||||
if (localRef == 0) {
|
||||
globalRef = null; // N.B. global null reference is -1
|
||||
} else {
|
||||
globalRef = holder.getCPMap()[localRef];
|
||||
if (e.refKind == CONSTANT_Signature
|
||||
Entry[] cpMap = holder.getCPMap();
|
||||
globalRef = (localRef >= 0 && localRef < cpMap.length
|
||||
? cpMap[localRef]
|
||||
: null);
|
||||
byte tag = e.refKind;
|
||||
if (globalRef != null && tag == CONSTANT_Signature
|
||||
&& globalRef.getTag() == CONSTANT_Utf8) {
|
||||
// Cf. ClassReader.readSignatureRef.
|
||||
String typeName = globalRef.stringValue();
|
||||
globalRef = ConstantPool.getSignatureEntry(typeName);
|
||||
} else if (e.refKind == CONSTANT_FieldSpecific) {
|
||||
assert(globalRef.getTag() >= CONSTANT_Integer);
|
||||
assert(globalRef.getTag() <= CONSTANT_String ||
|
||||
globalRef.getTag() >= CONSTANT_MethodHandle);
|
||||
assert(globalRef.getTag() <= CONSTANT_MethodType);
|
||||
} else if (e.refKind < CONSTANT_GroupFirst) {
|
||||
assert(e.refKind == globalRef.getTag());
|
||||
}
|
||||
String got = (globalRef == null
|
||||
? "invalid CP index"
|
||||
: "type=" + ConstantPool.tagName(globalRef.tag));
|
||||
if (globalRef == null || !globalRef.tagMatches(tag)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Bad constant, expected type=" +
|
||||
ConstantPool.tagName(tag) + " got " + got);
|
||||
}
|
||||
}
|
||||
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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -54,6 +54,7 @@ class ClassReader {
|
||||
Package pkg;
|
||||
Class cls;
|
||||
long inPos;
|
||||
long constantPoolLimit = -1;
|
||||
DataInputStream in;
|
||||
Map<Attribute.Layout, Attribute> attrDefs;
|
||||
Map<Attribute.Layout, String> attrCommands;
|
||||
@ -117,15 +118,33 @@ class ClassReader {
|
||||
|
||||
private Entry readRef(byte tag) throws IOException {
|
||||
Entry e = readRef();
|
||||
assert(e != null);
|
||||
assert(!(e instanceof UnresolvedEntry));
|
||||
assert(e.tagMatches(tag));
|
||||
checkTag(e, tag);
|
||||
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 {
|
||||
Entry e = readRef();
|
||||
assert(e == null || e.tagMatches(tag));
|
||||
checkTag(e, tag, true);
|
||||
return e;
|
||||
}
|
||||
|
||||
@ -143,8 +162,10 @@ class ClassReader {
|
||||
|
||||
private SignatureEntry readSignatureRef() throws IOException {
|
||||
// The class file stores a Utf8, but we want a Signature.
|
||||
Entry e = readRef(CONSTANT_Utf8);
|
||||
return ConstantPool.getSignatureEntry(e.stringValue());
|
||||
Entry e = readRef(CONSTANT_Signature);
|
||||
return (e != null && e.getTag() == CONSTANT_Utf8)
|
||||
? ConstantPool.getSignatureEntry(e.stringValue())
|
||||
: (SignatureEntry) e;
|
||||
}
|
||||
|
||||
void read() throws IOException {
|
||||
@ -279,6 +300,7 @@ class ClassReader {
|
||||
" at pos: " + inPos);
|
||||
}
|
||||
}
|
||||
constantPoolLimit = inPos;
|
||||
|
||||
// Fix up refs, which might be out of order.
|
||||
while (fptr > 0) {
|
||||
@ -311,25 +333,25 @@ class ClassReader {
|
||||
case CONSTANT_Fieldref:
|
||||
case CONSTANT_Methodref:
|
||||
case CONSTANT_InterfaceMethodref:
|
||||
ClassEntry mclass = (ClassEntry) cpMap[ref];
|
||||
DescriptorEntry mdescr = (DescriptorEntry) cpMap[ref2];
|
||||
ClassEntry mclass = (ClassEntry) checkTag(cpMap[ref], CONSTANT_Class);
|
||||
DescriptorEntry mdescr = (DescriptorEntry) checkTag(cpMap[ref2], CONSTANT_NameandType);
|
||||
cpMap[cpi] = ConstantPool.getMemberEntry((byte)tag, mclass, mdescr);
|
||||
break;
|
||||
case CONSTANT_NameandType:
|
||||
Utf8Entry mname = (Utf8Entry) cpMap[ref];
|
||||
Utf8Entry mtype = (Utf8Entry) cpMap[ref2];
|
||||
Utf8Entry mname = (Utf8Entry) checkTag(cpMap[ref], CONSTANT_Utf8);
|
||||
Utf8Entry mtype = (Utf8Entry) checkTag(cpMap[ref2], CONSTANT_Signature);
|
||||
cpMap[cpi] = ConstantPool.getDescriptorEntry(mname, mtype);
|
||||
break;
|
||||
case CONSTANT_MethodType:
|
||||
cpMap[cpi] = ConstantPool.getMethodTypeEntry((Utf8Entry) cpMap[ref]);
|
||||
cpMap[cpi] = ConstantPool.getMethodTypeEntry((Utf8Entry) checkTag(cpMap[ref], CONSTANT_Signature));
|
||||
break;
|
||||
case CONSTANT_MethodHandle:
|
||||
byte refKind = (byte)(-1 ^ ref);
|
||||
MemberEntry memRef = (MemberEntry) cpMap[ref2];
|
||||
MemberEntry memRef = (MemberEntry) checkTag(cpMap[ref2], CONSTANT_AnyMember);
|
||||
cpMap[cpi] = ConstantPool.getMethodHandleEntry(refKind, memRef);
|
||||
break;
|
||||
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);
|
||||
// Note that ref must be resolved later, using the BootstrapMethods attribute.
|
||||
break;
|
||||
@ -541,7 +563,8 @@ class ClassReader {
|
||||
code.max_locals = readUnsignedShort();
|
||||
code.bytes = new byte[readInt()];
|
||||
in.readFully(code.bytes);
|
||||
Instruction.opcodeChecker(code.bytes);
|
||||
Entry[] cpMap = cls.getCPMap();
|
||||
Instruction.opcodeChecker(code.bytes, cpMap);
|
||||
int nh = readUnsignedShort();
|
||||
code.setHandlerCount(nh);
|
||||
for (int i = 0; i < nh; i++) {
|
||||
@ -559,7 +582,7 @@ class ClassReader {
|
||||
MethodHandleEntry bsmRef = (MethodHandleEntry) readRef(CONSTANT_MethodHandle);
|
||||
Entry[] argRefs = new Entry[readUnsignedShort()];
|
||||
for (int j = 0; j < argRefs.length; j++) {
|
||||
argRefs[j] = readRef();
|
||||
argRefs[j] = readRef(CONSTANT_LoadableValue);
|
||||
}
|
||||
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.
|
||||
*
|
||||
* 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;
|
||||
}
|
||||
|
||||
public final boolean tagMatches(int tag) {
|
||||
return (this.tag == tag);
|
||||
public final boolean tagMatches(int matchTag) {
|
||||
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() {
|
||||
|
@ -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.
|
||||
*
|
||||
* 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);
|
||||
while (i != null) {
|
||||
int opcode = i.getBC();
|
||||
@ -655,6 +655,16 @@ class Instruction {
|
||||
String message = "illegal opcode: " + opcode + " " + i;
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -1618,6 +1618,16 @@ class PackageWriter extends BandStructure {
|
||||
bc_which = null;
|
||||
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_which.putRef(ref);
|
||||
// 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.
|
||||
*
|
||||
* 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();
|
||||
}
|
||||
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, String> attrCommands;
|
||||
@ -505,8 +514,7 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer {
|
||||
}
|
||||
} else if (ioe instanceof ClassReader.ClassFormatException) {
|
||||
ClassReader.ClassFormatException ce = (ClassReader.ClassFormatException) ioe;
|
||||
// %% TODO: Do we invent a new property for this or reuse %%
|
||||
if (unknownAttrCommand.equals(Pack200.Packer.PASS)) {
|
||||
if (classFormatCommand.equals(Pack200.Packer.PASS)) {
|
||||
Utils.log.info(ce.toString());
|
||||
Utils.log.warning(message + " unknown class format: " +
|
||||
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.
|
||||
*
|
||||
* 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.
|
||||
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.
|
||||
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.
|
||||
*
|
||||
* 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";
|
||||
|
||||
/*
|
||||
* 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.
|
||||
// This makes it simpler to supply environmental options
|
||||
// to the engine code, especially the native code.
|
||||
|
@ -50,8 +50,6 @@ import javax.management.MBeanInfo;
|
||||
import javax.management.NotCompliantMBeanException;
|
||||
|
||||
import com.sun.jmx.remote.util.EnvHelp;
|
||||
import java.beans.BeanInfo;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import javax.management.AttributeNotFoundException;
|
||||
|
@ -29,12 +29,14 @@ import java.lang.reflect.Array;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Executable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectStreamField;
|
||||
@ -2325,6 +2327,11 @@ public final
|
||||
|
||||
// Annotations handling
|
||||
private native byte[] getRawAnnotations();
|
||||
// Since 1.8
|
||||
native byte[] getRawTypeAnnotations();
|
||||
static byte[] getExecutableTypeAnnotationBytes(Executable ex) {
|
||||
return getReflectionFactory().getExecutableTypeAnnotationBytes(ex);
|
||||
}
|
||||
|
||||
native ConstantPool getConstantPool();
|
||||
|
||||
@ -3068,21 +3075,12 @@ public final
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @since 1.5
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
|
||||
Objects.requireNonNull(annotationClass);
|
||||
|
||||
initAnnotationsIfNecessary();
|
||||
return AnnotationSupport.getOneAnnotation(annotations, annotationClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @since 1.5
|
||||
*/
|
||||
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
|
||||
Objects.requireNonNull(annotationClass);
|
||||
|
||||
return getAnnotation(annotationClass) != null;
|
||||
return (A) annotations.get(annotationClass);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3101,18 +3099,19 @@ public final
|
||||
*/
|
||||
public Annotation[] getAnnotations() {
|
||||
initAnnotationsIfNecessary();
|
||||
return AnnotationSupport.unpackToArray(annotations);
|
||||
return AnnotationParser.toArray(annotations);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @since 1.8
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) {
|
||||
Objects.requireNonNull(annotationClass);
|
||||
|
||||
initAnnotationsIfNecessary();
|
||||
return AnnotationSupport.getOneAnnotation(declaredAnnotations, annotationClass);
|
||||
return (A) declaredAnnotations.get(annotationClass);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3131,17 +3130,7 @@ public final
|
||||
*/
|
||||
public Annotation[] getDeclaredAnnotations() {
|
||||
initAnnotationsIfNecessary();
|
||||
return AnnotationSupport.unpackToArray(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;
|
||||
return AnnotationParser.toArray(declaredAnnotations);
|
||||
}
|
||||
|
||||
// Annotations cache
|
||||
@ -3196,4 +3185,53 @@ public final
|
||||
* Maintained by the ClassValue class.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* 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);
|
||||
else {
|
||||
// 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,
|
||||
answer.append("-"); // so append sign info
|
||||
@ -300,8 +300,7 @@ public final class Double extends Number implements Comparable<Double> {
|
||||
|
||||
if(d == 0.0) {
|
||||
answer.append("0.0p0");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
boolean subnormal = (d < DoubleConsts.MIN_NORMAL);
|
||||
|
||||
// Isolate significand bits and OR in a high-order bit
|
||||
@ -324,13 +323,14 @@ public final class Double extends Number implements Comparable<Double> {
|
||||
"0":
|
||||
signif.replaceFirst("0{1,12}$", ""));
|
||||
|
||||
answer.append('p');
|
||||
// If the value is subnormal, use the E_min exponent
|
||||
// value for double; otherwise, extract and report d's
|
||||
// exponent (the representation of a subnormal uses
|
||||
// E_min -1).
|
||||
answer.append("p" + (subnormal ?
|
||||
DoubleConsts.MIN_EXPONENT:
|
||||
Math.getExponent(d) ));
|
||||
answer.append(subnormal ?
|
||||
DoubleConsts.MIN_EXPONENT:
|
||||
Math.getExponent(d));
|
||||
}
|
||||
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.
|
||||
*
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @since 1.5
|
||||
*/
|
||||
public boolean isAnnotationPresent(
|
||||
Class<? extends Annotation> annotationClass) {
|
||||
return getPackageInfo().isAnnotationPresent(annotationClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,7 +25,7 @@
|
||||
package java.lang;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Executable;
|
||||
import java.util.Properties;
|
||||
import java.util.PropertyPermission;
|
||||
import java.util.StringTokenizer;
|
||||
@ -1196,8 +1196,11 @@ public final class System {
|
||||
public AnnotationType getAnnotationType(Class<?> klass) {
|
||||
return klass.getAnnotationType();
|
||||
}
|
||||
public <A extends Annotation> A getDirectDeclaredAnnotation(Class<?> klass, Class<A> anno) {
|
||||
return klass.getDirectDeclaredAnnotation(anno);
|
||||
public byte[] getRawClassTypeAnnotations(Class<?> klass) {
|
||||
return klass.getRawTypeAnnotations();
|
||||
}
|
||||
public byte[] getRawExecutableTypeAnnotations(Executable executable) {
|
||||
return Class.getExecutableTypeAnnotationBytes(executable);
|
||||
}
|
||||
public <E extends Enum<E>>
|
||||
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.
|
||||
*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Thrown to indicate that an annotation type whose declaration is
|
||||
* (meta-)annotated with a {@link ContainerFor} annotation is not, in
|
||||
* fact, the <em>containing annotation type of the type named by {@link
|
||||
* ContainerFor}</em>.
|
||||
* Thrown to indicate that an annotation type expected to act as a
|
||||
* container for another annotation type by virture of an @Repeatable
|
||||
* annotation, does not act as a container.
|
||||
*
|
||||
* @see java.lang.reflect.AnnotatedElement
|
||||
* @since 1.8
|
||||
|
@ -180,14 +180,6 @@ public class AccessibleObject implements AnnotatedElement {
|
||||
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}
|
||||
* @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.
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
* (directly or indirectly) a {@link Class}-valued member referring to
|
||||
* 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
|
||||
* 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
|
||||
* java.lang.annotation.AnnotationTypeMismatchException} or an
|
||||
* {@link java.lang.annotation.IncompleteAnnotationException}.
|
||||
@ -70,6 +88,12 @@ public interface AnnotatedElement {
|
||||
* is present on this element, else false. This method
|
||||
* 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
|
||||
* annotation type
|
||||
* @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
|
||||
* @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
|
||||
@ -110,12 +136,15 @@ public interface AnnotatedElement {
|
||||
<T extends Annotation> T[] getAnnotations(Class<T> annotationClass);
|
||||
|
||||
/**
|
||||
* Returns all annotations present on this element. (Returns an array
|
||||
* 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.
|
||||
* Returns annotations that are <em>present</em> on this element.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
Annotation[] getAnnotations();
|
||||
@ -157,14 +186,16 @@ public interface AnnotatedElement {
|
||||
<T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass);
|
||||
|
||||
/**
|
||||
* Returns all annotations that are directly present on this
|
||||
* element. This method ignores inherited annotations. (Returns
|
||||
* 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.
|
||||
* Returns annotations that are <em>directly present</em> on this element.
|
||||
* This method ignores inherited annotations.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
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() {
|
||||
return annotations;
|
||||
}
|
||||
@Override
|
||||
byte[] getTypeAnnotationBytes() {
|
||||
return typeAnnotations;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,11 +26,12 @@
|
||||
package java.lang.reflect;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import sun.reflect.annotation.AnnotationParser;
|
||||
import sun.reflect.annotation.AnnotationSupport;
|
||||
import sun.reflect.annotation.TypeAnnotationParser;
|
||||
import sun.reflect.annotation.TypeAnnotation;
|
||||
import sun.reflect.generics.repository.ConstructorRepository;
|
||||
|
||||
/**
|
||||
@ -50,6 +51,7 @@ public abstract class Executable extends AccessibleObject
|
||||
* Accessor method to allow code sharing
|
||||
*/
|
||||
abstract byte[] getAnnotationBytes();
|
||||
abstract byte[] getTypeAnnotationBytes();
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
Objects.requireNonNull(annotationClass);
|
||||
|
||||
return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass);
|
||||
return annotationClass.cast(declaredAnnotations().get(annotationClass));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -454,7 +455,7 @@ public abstract class Executable extends AccessibleObject
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Annotation[] getDeclaredAnnotations() {
|
||||
return AnnotationSupport.unpackToArray(declaredAnnotations());
|
||||
return AnnotationParser.toArray(declaredAnnotations());
|
||||
}
|
||||
|
||||
private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
|
||||
@ -470,4 +471,86 @@ public abstract class Executable extends AccessibleObject
|
||||
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.
|
||||
*
|
||||
* 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 sun.reflect.annotation.AnnotationParser;
|
||||
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
|
||||
@ -1020,8 +1021,7 @@ class Field extends AccessibleObject implements Member {
|
||||
*/
|
||||
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
|
||||
Objects.requireNonNull(annotationClass);
|
||||
|
||||
return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass);
|
||||
return annotationClass.cast(declaredAnnotations().get(annotationClass));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1039,7 +1039,7 @@ class Field extends AccessibleObject implements Member {
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Annotation[] getDeclaredAnnotations() {
|
||||
return AnnotationSupport.unpackToArray(declaredAnnotations());
|
||||
return AnnotationParser.toArray(declaredAnnotations());
|
||||
}
|
||||
|
||||
private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
|
||||
@ -1053,4 +1053,20 @@ class Field extends AccessibleObject implements Member {
|
||||
}
|
||||
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() {
|
||||
return annotations;
|
||||
}
|
||||
@Override
|
||||
byte[] getTypeAnnotationBytes() {
|
||||
return typeAnnotations;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
@ -621,6 +625,14 @@ public final class Method extends Executable {
|
||||
return sharedGetParameterAnnotations(parameterTypes, parameterAnnotations);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.8
|
||||
*/
|
||||
public AnnotatedType getAnnotatedReturnType() {
|
||||
return getAnnotatedReturnType0(getGenericReturnType());
|
||||
}
|
||||
|
||||
@Override
|
||||
void handleParameterNumberMismatch(int resultLength, int numParameters) {
|
||||
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) {
|
||||
Objects.requireNonNull(annotationClass);
|
||||
|
||||
return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass);
|
||||
return annotationClass.cast(declaredAnnotations().get(annotationClass));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -281,14 +280,6 @@ public final class Parameter implements AnnotatedElement {
|
||||
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 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.
|
||||
*
|
||||
* 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();
|
||||
}
|
||||
|
||||
public byte[] getExecutableTypeAnnotationBytes(Executable ex) {
|
||||
return ex.getTypeAnnotationBytes();
|
||||
}
|
||||
|
||||
//
|
||||
// Copying routines, needed to quickly fabricate new Field,
|
||||
// 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.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
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
|
||||
return expandBigIntegerTenPowers(n);
|
||||
}
|
||||
// BigInteger.pow is slow, so make 10**n by constructing a
|
||||
// BigInteger from a character string (still not very fast)
|
||||
char tenpow[] = new char[n + 1];
|
||||
tenpow[0] = '1';
|
||||
for (int i = 1; i <= n; i++)
|
||||
tenpow[i] = '0';
|
||||
return new BigInteger(tenpow,1, tenpow.length);
|
||||
|
||||
if (n < 1024*524288) {
|
||||
// BigInteger.pow is slow, so make 10**n by constructing a
|
||||
// BigInteger from a character string (still not very fast)
|
||||
// which occupies no more than 1GB (!) of memory.
|
||||
char tenpow[] = new char[n + 1];
|
||||
tenpow[0] = '1';
|
||||
for (int i = 1; i <= n; i++) {
|
||||
tenpow[i] = '0';
|
||||
}
|
||||
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
|
||||
* must be represented in lines of no more than 76 characters each
|
||||
* 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
|
||||
* ignored in decoding operation.</p></li>
|
||||
* </ul>
|
||||
@ -413,6 +414,7 @@ public class Base64 {
|
||||
* specified Base64 encoded format
|
||||
*/
|
||||
public OutputStream wrap(OutputStream os) {
|
||||
Objects.requireNonNull(os);
|
||||
return new EncOutputStream(os, isURL ? toBase64URL : toBase64,
|
||||
newline, linemax);
|
||||
}
|
||||
@ -613,6 +615,13 @@ public class Base64 {
|
||||
* This class implements a decoder for decoding byte data using the
|
||||
* 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
|
||||
* multiple concurrent threads.
|
||||
*
|
||||
@ -695,7 +704,7 @@ public class Base64 {
|
||||
* using the {@link Base64} encoding scheme.
|
||||
*
|
||||
* <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
|
||||
* the string to decode
|
||||
@ -856,6 +865,9 @@ public class Base64 {
|
||||
/**
|
||||
* 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
|
||||
* input stream.
|
||||
*
|
||||
@ -866,6 +878,7 @@ public class Base64 {
|
||||
* byte stream
|
||||
*/
|
||||
public InputStream wrap(InputStream is) {
|
||||
Objects.requireNonNull(is);
|
||||
return new DecInputStream(is, isURL ? fromBase64URL : fromBase64, isMIME);
|
||||
}
|
||||
|
||||
@ -881,13 +894,16 @@ public class Base64 {
|
||||
int dl = dst.arrayOffset() + dst.limit();
|
||||
int dp0 = dp;
|
||||
int mark = sp;
|
||||
boolean padding = false;
|
||||
try {
|
||||
while (sp < sl) {
|
||||
int b = sa[sp++] & 0xff;
|
||||
if ((b = base64[b]) < 0) {
|
||||
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;
|
||||
}
|
||||
if (isMIME) // skip if for rfc2045
|
||||
@ -913,24 +929,23 @@ public class Base64 {
|
||||
if (shiftto == 6) {
|
||||
if (dl - dp < 1)
|
||||
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);
|
||||
mark = sp;
|
||||
} else if (shiftto == 0) {
|
||||
if (dl - dp < 2)
|
||||
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 >> 8);
|
||||
mark = sp;
|
||||
} else if (padding || shiftto != 18) {
|
||||
} else if (shiftto == 12) {
|
||||
throw new IllegalArgumentException(
|
||||
"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;
|
||||
} finally {
|
||||
src.position(mark);
|
||||
@ -948,14 +963,16 @@ public class Base64 {
|
||||
int dl = dst.limit();
|
||||
int dp0 = dp;
|
||||
int mark = sp;
|
||||
boolean padding = false;
|
||||
|
||||
try {
|
||||
while (sp < sl) {
|
||||
int b = src.get(sp++) & 0xff;
|
||||
if ((b = base64[b]) < 0) {
|
||||
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;
|
||||
}
|
||||
if (isMIME) // skip if for rfc2045
|
||||
@ -981,24 +998,23 @@ public class Base64 {
|
||||
if (shiftto == 6) {
|
||||
if (dl - dp < 1)
|
||||
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));
|
||||
mark = sp;
|
||||
} else if (shiftto == 0) {
|
||||
if (dl - dp < 2)
|
||||
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 >> 8));
|
||||
mark = sp;
|
||||
} else if (padding || shiftto != 18) {
|
||||
} else if (shiftto == 12) {
|
||||
throw new IllegalArgumentException(
|
||||
"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;
|
||||
} finally {
|
||||
src.position(mark);
|
||||
@ -1012,9 +1028,12 @@ public class Base64 {
|
||||
int len = sl - sp;
|
||||
if (len == 0)
|
||||
return 0;
|
||||
if (len < 2)
|
||||
if (len < 2) {
|
||||
if (isMIME && base64[0] == -1)
|
||||
return 0;
|
||||
throw new IllegalArgumentException(
|
||||
"Input byte[] should at least have 2 bytes for base64 bytes");
|
||||
}
|
||||
if (src[sl - 1] == '=') {
|
||||
paddings++;
|
||||
if (src[sl - 2] == '=')
|
||||
@ -1043,12 +1062,20 @@ public class Base64 {
|
||||
int dp = 0;
|
||||
int bits = 0;
|
||||
int shiftto = 18; // pos of first byte of 4-byte atom
|
||||
boolean padding = false;
|
||||
while (sp < sl) {
|
||||
int b = src[sp++] & 0xff;
|
||||
if ((b = base64[b]) < 0) {
|
||||
if (b == -2) { // padding byte
|
||||
padding = true;
|
||||
if (b == -2) { // padding byte '='
|
||||
// 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;
|
||||
}
|
||||
if (isMIME) // skip if for rfc2045
|
||||
@ -1068,22 +1095,23 @@ public class Base64 {
|
||||
bits = 0;
|
||||
}
|
||||
}
|
||||
// reach end of byte arry or hit padding '=' characters.
|
||||
// if '=' presents, they must be the last one or two.
|
||||
if (shiftto == 6) { // xx==
|
||||
if (padding && (sp + 1 != sl || src[sp] != '='))
|
||||
throw new IllegalArgumentException(
|
||||
"Input byte array has wrong 4-byte ending unit");
|
||||
// reached end of byte array or hit padding '=' characters.
|
||||
if (shiftto == 6) {
|
||||
dst[dp++] = (byte)(bits >> 16);
|
||||
} else if (shiftto == 0) { // xxx=
|
||||
if (padding && sp != sl)
|
||||
throw new IllegalArgumentException(
|
||||
"Input byte array has wrong 4-byte ending unit");
|
||||
} else if (shiftto == 0) {
|
||||
dst[dp++] = (byte)(bits >> 16);
|
||||
dst[dp++] = (byte)(bits >> 8);
|
||||
} else if (padding || shiftto != 18) {
|
||||
throw new IllegalArgumentException(
|
||||
"last unit does not have enough bytes");
|
||||
} else if (shiftto == 12) {
|
||||
throw new IllegalArgumentException(
|
||||
"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;
|
||||
}
|
||||
@ -1247,8 +1275,22 @@ public class Base64 {
|
||||
int v = is.read();
|
||||
if (v == -1) {
|
||||
eof = true;
|
||||
if (nextin != 18)
|
||||
throw new IOException("Base64 stream has un-decoded dangling byte(s).");
|
||||
if (nextin != 18) {
|
||||
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)
|
||||
return -1;
|
||||
else
|
||||
|
@ -351,7 +351,9 @@ import sun.misc.FormattedFloatingDecimal;
|
||||
* <tr><td valign="top">{@code 'a'}, {@code 'A'}
|
||||
* <td valign="top"> floating point
|
||||
* <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'}
|
||||
* <td valign="top"> date/time
|
||||
|
@ -22,7 +22,6 @@
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.management;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
@ -31,49 +30,55 @@ import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
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.util.MissingResourceException;
|
||||
import java.util.Properties;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import javax.management.remote.JMXConnectorServer;
|
||||
import javax.management.remote.JMXServiceURL;
|
||||
|
||||
import static sun.management.AgentConfigurationError.*;
|
||||
import sun.management.jmxremote.ConnectorBootstrap;
|
||||
import sun.management.jdp.JdpController;
|
||||
import sun.management.jdp.JdpException;
|
||||
import sun.misc.VMSupport;
|
||||
|
||||
/**
|
||||
* This Agent is started by the VM when -Dcom.sun.management.snmp
|
||||
* or -Dcom.sun.management.jmxremote is set. This class will be
|
||||
* loaded by the system class loader. Also jmx framework could
|
||||
* be started by jcmd
|
||||
* This Agent is started by the VM when -Dcom.sun.management.snmp or
|
||||
* -Dcom.sun.management.jmxremote is set. This class will be loaded by the
|
||||
* system class loader. Also jmx framework could be started by jcmd
|
||||
*/
|
||||
public class Agent {
|
||||
// management properties
|
||||
|
||||
private static Properties mgmtProps;
|
||||
private static ResourceBundle messageRB;
|
||||
|
||||
private static final String CONFIG_FILE =
|
||||
"com.sun.management.config.file";
|
||||
"com.sun.management.config.file";
|
||||
private static final String SNMP_PORT =
|
||||
"com.sun.management.snmp.port";
|
||||
"com.sun.management.snmp.port";
|
||||
private static final String JMXREMOTE =
|
||||
"com.sun.management.jmxremote";
|
||||
"com.sun.management.jmxremote";
|
||||
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 =
|
||||
"com.sun.management.enableThreadContentionMonitoring";
|
||||
"com.sun.management.enableThreadContentionMonitoring";
|
||||
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 =
|
||||
"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
|
||||
private static JMXConnectorServer jmxServer = null;
|
||||
@ -81,26 +86,25 @@ public class Agent {
|
||||
// Parse string com.sun.management.prop=xxx,com.sun.management.prop=yyyy
|
||||
// and return property set if args is null or empty
|
||||
// return empty property set
|
||||
private static Properties parseString(String args){
|
||||
private static Properties parseString(String args) {
|
||||
Properties argProps = new Properties();
|
||||
if (args != null) {
|
||||
for (String option : args.split(",")) {
|
||||
String s[] = option.split("=", 2);
|
||||
String name = s[0].trim();
|
||||
String value = (s.length > 1) ? s[1].trim() : "";
|
||||
for (String option : args.split(",")) {
|
||||
String s[] = option.split("=", 2);
|
||||
String name = s[0].trim();
|
||||
String value = (s.length > 1) ? s[1].trim() : "";
|
||||
|
||||
if (!name.startsWith("com.sun.management.")) {
|
||||
error(INVALID_OPTION, name);
|
||||
}
|
||||
if (!name.startsWith("com.sun.management.")) {
|
||||
error(INVALID_OPTION, name);
|
||||
}
|
||||
|
||||
argProps.setProperty(name, value);
|
||||
}
|
||||
argProps.setProperty(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
return argProps;
|
||||
}
|
||||
|
||||
|
||||
// invoked by -javaagent or -Dcom.sun.management.agent.class
|
||||
public static void premain(String args) throws Exception {
|
||||
agentmain(args);
|
||||
@ -115,18 +119,18 @@ public class Agent {
|
||||
Properties arg_props = parseString(args);
|
||||
|
||||
// Read properties from the config file
|
||||
Properties config_props = new Properties();
|
||||
String fname = arg_props.getProperty(CONFIG_FILE);
|
||||
readConfiguration(fname, config_props);
|
||||
Properties config_props = new Properties();
|
||||
String fname = arg_props.getProperty(CONFIG_FILE);
|
||||
readConfiguration(fname, config_props);
|
||||
|
||||
// Arguments override config file
|
||||
config_props.putAll(arg_props);
|
||||
startAgent(config_props);
|
||||
// Arguments override config file
|
||||
config_props.putAll(arg_props);
|
||||
startAgent(config_props);
|
||||
}
|
||||
|
||||
// jcmd ManagementAgent.start_local entry point
|
||||
// Also called due to command-line via startAgent()
|
||||
private static synchronized void startLocalManagementAgent(){
|
||||
private static synchronized void startLocalManagementAgent() {
|
||||
Properties agentProps = VMSupport.getAgentProperties();
|
||||
|
||||
// start local connector if not started
|
||||
@ -156,7 +160,7 @@ public class Agent {
|
||||
throw new RuntimeException(getText(INVALID_STATE, "Agent already started"));
|
||||
}
|
||||
|
||||
Properties argProps = parseString(args);
|
||||
Properties argProps = parseString(args);
|
||||
Properties configProps = new Properties();
|
||||
|
||||
// Load the management properties from the config file
|
||||
@ -169,7 +173,7 @@ public class Agent {
|
||||
// management properties can be overridden by system properties
|
||||
// which take precedence
|
||||
Properties sysProps = System.getProperties();
|
||||
synchronized(sysProps){
|
||||
synchronized (sysProps) {
|
||||
configProps.putAll(sysProps);
|
||||
}
|
||||
|
||||
@ -190,21 +194,26 @@ public class Agent {
|
||||
// can specify this property inside config file, so enable optional
|
||||
// monitoring functionality if this property is set
|
||||
final String enableThreadContentionMonitoring =
|
||||
configProps.getProperty(ENABLE_THREAD_CONTENTION_MONITORING);
|
||||
configProps.getProperty(ENABLE_THREAD_CONTENTION_MONITORING);
|
||||
|
||||
if (enableThreadContentionMonitoring != null) {
|
||||
ManagementFactory.getThreadMXBean().
|
||||
setThreadContentionMonitoringEnabled(true);
|
||||
setThreadContentionMonitoringEnabled(true);
|
||||
}
|
||||
|
||||
String jmxremotePort = configProps.getProperty(JMXREMOTE_PORT);
|
||||
if (jmxremotePort != null) {
|
||||
jmxServer = ConnectorBootstrap.
|
||||
startRemoteConnectorServer(jmxremotePort, configProps);
|
||||
startRemoteConnectorServer(jmxremotePort, configProps);
|
||||
|
||||
startDiscoveryService(configProps);
|
||||
}
|
||||
}
|
||||
|
||||
private static synchronized void stopRemoteManagementAgent() throws Exception {
|
||||
|
||||
JdpController.stopDiscoveryService();
|
||||
|
||||
if (jmxServer != null) {
|
||||
ConnectorBootstrap.unexportRegistry();
|
||||
|
||||
@ -222,15 +231,15 @@ public class Agent {
|
||||
|
||||
// Enable optional monitoring functionality if requested
|
||||
final String enableThreadContentionMonitoring =
|
||||
props.getProperty(ENABLE_THREAD_CONTENTION_MONITORING);
|
||||
props.getProperty(ENABLE_THREAD_CONTENTION_MONITORING);
|
||||
if (enableThreadContentionMonitoring != null) {
|
||||
ManagementFactory.getThreadMXBean().
|
||||
setThreadContentionMonitoringEnabled(true);
|
||||
setThreadContentionMonitoringEnabled(true);
|
||||
}
|
||||
|
||||
try {
|
||||
if (snmpPort != null) {
|
||||
loadSnmpAgent(snmpPort, props);
|
||||
loadSnmpAgent(snmpPort, props);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -242,13 +251,14 @@ public class Agent {
|
||||
* of this "local" server is exported as a counter to the jstat
|
||||
* instrumentation buffer.
|
||||
*/
|
||||
if (jmxremote != null || jmxremotePort != null) {
|
||||
if (jmxremote != null || jmxremotePort != null) {
|
||||
if (jmxremotePort != null) {
|
||||
jmxServer = ConnectorBootstrap.
|
||||
startRemoteConnectorServer(jmxremotePort, props);
|
||||
jmxServer = ConnectorBootstrap.
|
||||
startRemoteConnectorServer(jmxremotePort, props);
|
||||
startDiscoveryService(props);
|
||||
}
|
||||
startLocalManagementAgent();
|
||||
}
|
||||
}
|
||||
|
||||
} catch (AgentConfigurationError e) {
|
||||
error(e.getError(), e.getParams());
|
||||
@ -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() {
|
||||
Properties props = new Properties();
|
||||
|
||||
@ -268,22 +345,22 @@ public class Agent {
|
||||
// management properties can be overridden by system properties
|
||||
// which take precedence
|
||||
Properties sysProps = System.getProperties();
|
||||
synchronized(sysProps){
|
||||
synchronized (sysProps) {
|
||||
props.putAll(sysProps);
|
||||
}
|
||||
|
||||
return props;
|
||||
}
|
||||
}
|
||||
|
||||
public static synchronized Properties getManagementProperties() {
|
||||
public static synchronized Properties getManagementProperties() {
|
||||
if (mgmtProps == null) {
|
||||
String configFile = System.getProperty(CONFIG_FILE);
|
||||
String snmpPort = System.getProperty(SNMP_PORT);
|
||||
String jmxremote = System.getProperty(JMXREMOTE);
|
||||
String jmxremotePort = System.getProperty(JMXREMOTE_PORT);
|
||||
|
||||
if (configFile == null && snmpPort == null &&
|
||||
jmxremote == null && jmxremotePort == null) {
|
||||
if (configFile == null && snmpPort == null
|
||||
&& jmxremote == null && jmxremotePort == null) {
|
||||
// return if out-of-the-management option is not specified
|
||||
return null;
|
||||
}
|
||||
@ -297,22 +374,23 @@ public class Agent {
|
||||
// invoke the following through reflection:
|
||||
// AdaptorBootstrap.initialize(snmpPort, props);
|
||||
final Class<?> adaptorClass =
|
||||
Class.forName(SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME,true,null);
|
||||
Class.forName(SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME, true, null);
|
||||
final Method initializeMethod =
|
||||
adaptorClass.getMethod("initialize",
|
||||
String.class, Properties.class);
|
||||
initializeMethod.invoke(null,snmpPort,props);
|
||||
String.class, Properties.class);
|
||||
initializeMethod.invoke(null, snmpPort, props);
|
||||
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException x) {
|
||||
// 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) {
|
||||
final Throwable cause = x.getCause();
|
||||
if (cause instanceof RuntimeException)
|
||||
if (cause instanceof RuntimeException) {
|
||||
throw (RuntimeException) cause;
|
||||
else if (cause instanceof Error)
|
||||
} else if (cause instanceof Error) {
|
||||
throw (Error) cause;
|
||||
}
|
||||
// should not happen...
|
||||
throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT,cause);
|
||||
throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT, cause);
|
||||
}
|
||||
}
|
||||
|
||||
@ -353,8 +431,8 @@ public class Agent {
|
||||
} catch (IOException e) {
|
||||
error(CONFIG_FILE_CLOSE_FAILED, fname);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void startAgent() throws Exception {
|
||||
@ -389,9 +467,9 @@ public class Agent {
|
||||
// invoke the premain(String args) method
|
||||
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(cname);
|
||||
Method premain = clz.getMethod("premain",
|
||||
new Class<?>[] { String.class });
|
||||
new Class<?>[]{String.class});
|
||||
premain.invoke(null, /* static */
|
||||
new Object[] { args });
|
||||
new Object[]{args});
|
||||
} catch (ClassNotFoundException ex) {
|
||||
error(AGENT_CLASS_NOT_FOUND, "\"" + cname + "\"");
|
||||
} catch (NoSuchMethodException ex) {
|
||||
@ -400,8 +478,8 @@ public class Agent {
|
||||
error(AGENT_CLASS_ACCESS_DENIED);
|
||||
} catch (Exception ex) {
|
||||
String msg = (ex.getCause() == null
|
||||
? ex.getMessage()
|
||||
: ex.getCause().getMessage());
|
||||
? ex.getMessage()
|
||||
: ex.getCause().getMessage());
|
||||
error(AGENT_CLASS_FAILED, msg);
|
||||
}
|
||||
}
|
||||
@ -425,7 +503,6 @@ public class Agent {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void error(String key, String message) {
|
||||
String keyText = getText(key);
|
||||
System.err.print(getText("agent.err.error") + ": " + keyText);
|
||||
@ -447,7 +524,7 @@ public class Agent {
|
||||
private static void initResource() {
|
||||
try {
|
||||
messageRB =
|
||||
ResourceBundle.getBundle("sun.management.resources.agent");
|
||||
ResourceBundle.getBundle("sun.management.resources.agent");
|
||||
} catch (MissingResourceException e) {
|
||||
throw new Error("Fatal: Resource for management agent is missing");
|
||||
}
|
||||
@ -470,10 +547,9 @@ public class Agent {
|
||||
}
|
||||
String format = messageRB.getString(key);
|
||||
if (format == null) {
|
||||
format = "missing resource key: key = \"" + key + "\", " +
|
||||
"arguments = \"{0}\", \"{1}\", \"{2}\"";
|
||||
format = "missing resource key: key = \"" + key + "\", "
|
||||
+ "arguments = \"{0}\", \"{1}\", \"{2}\"";
|
||||
}
|
||||
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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,6 +26,7 @@
|
||||
package sun.misc;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Executable;
|
||||
import sun.reflect.ConstantPool;
|
||||
import sun.reflect.annotation.AnnotationType;
|
||||
import sun.nio.ch.Interruptible;
|
||||
@ -46,6 +47,18 @@ public interface JavaLangAccess {
|
||||
*/
|
||||
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
|
||||
* Class object does not represent an enum type;
|
||||
@ -84,9 +97,4 @@ public interface JavaLangAccess {
|
||||
* Returns the ith StackTraceElement for the given throwable.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* 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,
|
||||
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) */
|
||||
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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,6 +26,7 @@
|
||||
package sun.reflect;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Executable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Modifier;
|
||||
@ -314,6 +315,12 @@ public class ReflectionFactory {
|
||||
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
|
||||
|
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -188,7 +188,7 @@ public class AnnotationParser {
|
||||
* available at runtime
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Annotation parseAnnotation(ByteBuffer buf,
|
||||
static Annotation parseAnnotation(ByteBuffer buf,
|
||||
ConstantPool constPool,
|
||||
Class<?> container,
|
||||
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.
|
||||
*
|
||||
* 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.reflect.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import sun.reflect.Reflection;
|
||||
import sun.misc.JavaLangAccess;
|
||||
|
||||
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
|
||||
* {@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).
|
||||
* Repeatable} annotation).
|
||||
*
|
||||
* @param annotationMap the {@code Map} used to store annotations indexed by their type
|
||||
* @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
|
||||
*/
|
||||
public static <A extends Annotation> A[] getMultipleAnnotations(final Map<Class<? extends Annotation>, Annotation> annotationMap,
|
||||
final Class<A> annotationClass) {
|
||||
final ArrayList<A> res = new ArrayList<A>();
|
||||
public static <A extends Annotation> A[] getMultipleAnnotations(
|
||||
final Map<Class<? extends Annotation>, Annotation> annotationMap,
|
||||
final Class<A> annotationClass) {
|
||||
final List<A> res = new ArrayList<A>();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final A candidate = (A)annotationMap.get(annotationClass);
|
||||
@ -101,49 +67,10 @@ public final class AnnotationSupport {
|
||||
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. */
|
||||
private static <A extends Annotation> Class<? extends Annotation> getContainer(Class<A> annotationClass) {
|
||||
ContainedBy containerAnnotation =
|
||||
javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainedBy.class);
|
||||
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();
|
||||
Repeatable containingAnnotation = annotationClass.getDeclaredAnnotation(Repeatable.class);
|
||||
return (containingAnnotation == null) ? null : containingAnnotation.value();
|
||||
}
|
||||
|
||||
/** 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
|
||||
// and invoke it to get the contents.
|
||||
|
||||
Class<?> containerClass = containerInstance.annotationType();
|
||||
AnnotationType annoType = javaLangAccess.getAnnotationType(containerClass);
|
||||
Class<? extends Annotation> containerClass = containerInstance.annotationType();
|
||||
AnnotationType annoType = AnnotationType.getInstance(containerClass);
|
||||
if (annoType == null)
|
||||
throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations");
|
||||
|
||||
Method m = annoType.members().get("value");
|
||||
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);
|
||||
|
||||
@SuppressWarnings("unchecked") // not provably safe, but we catch the ClassCastException
|
||||
@ -175,32 +103,11 @@ public final class AnnotationSupport {
|
||||
IllegalArgumentException | // parameters doesn't match
|
||||
InvocationTargetException | // the value method threw an exception
|
||||
ClassCastException e) { // well, a cast failed ...
|
||||
throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations",
|
||||
e,
|
||||
containerInstance,
|
||||
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);
|
||||
throw new InvalidContainerAnnotationError(
|
||||
containerInstance + " is an invalid container for repeating annotations",
|
||||
e,
|
||||
containerInstance,
|
||||
null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -208,24 +115,26 @@ public final class AnnotationSupport {
|
||||
* instances of type {@code annotationClass} from {@code
|
||||
* 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) {
|
||||
return Collections.emptyList(); // container not present
|
||||
}
|
||||
|
||||
try {
|
||||
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++)
|
||||
l.add(annotationClass.cast(a[i]));
|
||||
return l;
|
||||
} catch (ClassCastException |
|
||||
NullPointerException e) {
|
||||
throw new InvalidContainerAnnotationError(String.format("%s is an invalid container for repeating annotations of type: %s",
|
||||
containerInstance, annotationClass),
|
||||
e,
|
||||
containerInstance,
|
||||
annotationClass);
|
||||
throw new InvalidContainerAnnotationError(
|
||||
String.format("%s is an invalid container for repeating annotations of type: %s",
|
||||
containerInstance, annotationClass),
|
||||
e,
|
||||
containerInstance,
|
||||
annotationClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,13 +25,18 @@
|
||||
|
||||
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.GenericDeclaration;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
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.tree.FieldTypeSignature;
|
||||
import sun.reflect.generics.visitor.Reifier;
|
||||
@ -182,45 +187,70 @@ public class TypeVariableImpl<D extends GenericDeclaration>
|
||||
return genericDeclaration.hashCode() ^ name.hashCode();
|
||||
}
|
||||
|
||||
// Currently vacuous implementations of AnnotatedElement methods.
|
||||
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
|
||||
Objects.requireNonNull(annotationClass);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Implementations of AnnotatedElement methods.
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends Annotation> T getAnnotation(Class<T> 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) {
|
||||
Objects.requireNonNull(annotationClass);
|
||||
return null;
|
||||
return getAnnotation(annotationClass);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends Annotation> T[] getAnnotations(Class<T> annotationClass) {
|
||||
Objects.requireNonNull(annotationClass);
|
||||
// safe because annotationClass is the class for T
|
||||
return (T[])Array.newInstance(annotationClass, 0);
|
||||
return AnnotationSupport.getMultipleAnnotations(mapAnnotations(getAnnotations()), annotationClass);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass) {
|
||||
Objects.requireNonNull(annotationClass);
|
||||
// safe because annotationClass is the class for T
|
||||
return (T[])Array.newInstance(annotationClass, 0);
|
||||
return getAnnotations(annotationClass);
|
||||
}
|
||||
|
||||
public Annotation[] getAnnotations() {
|
||||
// Since zero-length, don't need defensive clone
|
||||
return EMPTY_ANNOTATION_ARRAY;
|
||||
int myIndex = typeVarIndex();
|
||||
if (myIndex < 0)
|
||||
throw new AssertionError("Index must be non-negative.");
|
||||
return TypeAnnotationParser.parseTypeVariableAnnotations(getGenericDeclaration(), myIndex);
|
||||
}
|
||||
|
||||
public Annotation[] getDeclaredAnnotations() {
|
||||
// Since zero-length, don't need defensive clone
|
||||
return EMPTY_ANNOTATION_ARRAY;
|
||||
return getAnnotations();
|
||||
}
|
||||
|
||||
public AnnotatedType[] getAnnotatedBounds() {
|
||||
return TypeAnnotationParser.parseAnnotatedBounds(getBounds(),
|
||||
getGenericDeclaration(),
|
||||
typeVarIndex());
|
||||
}
|
||||
|
||||
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 (debug != null) {
|
||||
debug.println("Storing " + privateKeyCount +
|
||||
debug.println("Storing " + (privateKeyCount + secretKeyCount) +
|
||||
" protected key(s) in a PKCS#7 data content-type");
|
||||
}
|
||||
|
||||
@ -2122,6 +2122,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
||||
SecretKeyEntry kEntry = new SecretKeyEntry();
|
||||
kEntry.protectedSecretKey = secretValue.getOctetString();
|
||||
bagItem = kEntry;
|
||||
secretKeyCount++;
|
||||
} else {
|
||||
|
||||
if (debug != null) {
|
||||
@ -2220,6 +2221,10 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
||||
if (bagItem instanceof PrivateKeyEntry) {
|
||||
keyList.add((PrivateKeyEntry) entry);
|
||||
}
|
||||
if (entry.attributes == null) {
|
||||
entry.attributes = new HashSet<>();
|
||||
}
|
||||
entry.attributes.addAll(attributes);
|
||||
if (alias == null) {
|
||||
alias = getUnfriendlyName();
|
||||
}
|
||||
|
@ -465,6 +465,12 @@ JVM_GetClassSignature(JNIEnv *env, jclass cls);
|
||||
JNIEXPORT jbyteArray JNICALL
|
||||
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
|
||||
*/
|
||||
|
@ -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.
|
||||
*
|
||||
* 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},
|
||||
{"getConstantPool", "()" CPL, (void *)&JVM_GetClassConstantPool},
|
||||
{"desiredAssertionStatus0","("CLS")Z",(void *)&JVM_DesiredAssertionStatus},
|
||||
{"getEnclosingMethod0", "()[" OBJ, (void *)&JVM_GetEnclosingMethodInfo}
|
||||
{"getEnclosingMethod0", "()[" OBJ, (void *)&JVM_GetEnclosingMethodInfo},
|
||||
{"getRawTypeAnnotations", "()" BA, (void *)&JVM_GetClassTypeAnnotations},
|
||||
};
|
||||
|
||||
#undef OBJ
|
||||
|
@ -191,17 +191,6 @@ static int closefd(int fd1, int fd2) {
|
||||
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
|
||||
* (restart if interrupted by signal)
|
||||
@ -214,6 +203,16 @@ static int closefd(int fd1, int fd2) {
|
||||
}
|
||||
} 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.
|
||||
*
|
||||
* 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 '\t':
|
||||
if (prev == '\\') {
|
||||
for (i = 0 ; i < slashes; i++) {
|
||||
*dest++ = prev;
|
||||
}
|
||||
}
|
||||
if (quotes % 2 == 1) {
|
||||
*dest++ = ch;
|
||||
} else {
|
||||
@ -591,6 +596,12 @@ int main(int argc, char* argv[]) {
|
||||
// v->disable();
|
||||
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);
|
||||
printf("All tests pass [%d]\n", i);
|
||||
doexit(0);
|
||||
|
@ -321,12 +321,12 @@ sun/jvmstat/monitor/MonitoredVm/CR6672135.java generic-all
|
||||
tools/pack200/CommandLineTests.java generic-all
|
||||
tools/pack200/Pack200Test.java generic-all
|
||||
|
||||
# 8001163
|
||||
tools/pack200/AttributeTests.java generic-all
|
||||
|
||||
# 7150569
|
||||
tools/launcher/UnicodeTest.java macosx-all
|
||||
|
||||
# 8007410
|
||||
tools/launcher/FXLauncherTest.java linux-all
|
||||
|
||||
############################################################################
|
||||
|
||||
# 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 7154390
|
||||
* @bug 7154390 8005712
|
||||
* @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
|
||||
@ -58,7 +58,7 @@ public class RepeatedUnitTest {
|
||||
checkMultiplier(Me1.class.getField("foo"), 1);
|
||||
|
||||
// METHOD
|
||||
checkMultiplier(Me1.class.getDeclaredMethod("mee", null), 100);
|
||||
checkMultiplier(Me1.class.getDeclaredMethod("mee", (Class<?>[])null), 100);
|
||||
|
||||
// INNER CLASS
|
||||
checkMultiplier(Me1.MiniMee.class, 1000);
|
||||
@ -84,8 +84,7 @@ public class RepeatedUnitTest {
|
||||
|
||||
static void packageRepeated(AnnotatedElement e) {
|
||||
Containee c = e.getAnnotation(Containee.class);
|
||||
check(c.value() == 1);
|
||||
|
||||
check(c == null);
|
||||
check(2 == countAnnotation(e, Containee.class));
|
||||
|
||||
c = e.getAnnotations(Containee.class)[0];
|
||||
@ -93,7 +92,7 @@ public class RepeatedUnitTest {
|
||||
c = e.getAnnotations(Containee.class)[1];
|
||||
check(c.value() == 2);
|
||||
|
||||
check(2 == containsAnnotationOfType(e.getAnnotations(), Containee.class));
|
||||
check(0 == containsAnnotationOfType(e.getAnnotations(), Containee.class));
|
||||
}
|
||||
|
||||
static void packageContainer(AnnotatedElement e) {
|
||||
@ -161,14 +160,26 @@ public class RepeatedUnitTest {
|
||||
}
|
||||
|
||||
static void checkMultiplier(AnnotatedElement e, int m) {
|
||||
// Basic sanity of non-repeating getAnnotation(Class)
|
||||
check(e.getAnnotation(NonRepeated.class).value() == 5 * m);
|
||||
|
||||
// Check count of annotations returned from getAnnotations(Class)
|
||||
check(4 == countAnnotation(e, Containee.class));
|
||||
check(1 == countAnnotation(e, Container.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(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) {
|
||||
|
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,7 +26,6 @@ package subpackage;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ContainedBy(Container.class)
|
||||
@Repeatable(Container.class)
|
||||
public @interface Containee {
|
||||
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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,7 +26,6 @@ package subpackage;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ContainerFor(Containee.class)
|
||||
public @interface Container {
|
||||
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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,7 +27,6 @@ import java.lang.annotation.*;
|
||||
|
||||
@Inherited
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ContainedBy(InheritedContainer.class)
|
||||
@Repeatable(InheritedContainer.class)
|
||||
public @interface InheritedContainee {
|
||||
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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,7 +27,6 @@ import java.lang.annotation.*;
|
||||
|
||||
@Inherited
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ContainerFor(InheritedContainee.class)
|
||||
public @interface InheritedContainer {
|
||||
InheritedContainee[] value();
|
||||
}
|
||||
|
@ -23,163 +23,152 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8004729
|
||||
* @summary javac should generate method parameters correctly.
|
||||
*/
|
||||
|
||||
import java.lang.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.lang.annotation.*;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
|
||||
public class WithoutParameters {
|
||||
int errors = 0;
|
||||
|
||||
private static final Class<?>[] qux_types = {
|
||||
int.class,
|
||||
Foo.class,
|
||||
List.class,
|
||||
List.class,
|
||||
List.class,
|
||||
String[].class
|
||||
};
|
||||
private WithoutParameters() {}
|
||||
|
||||
public static void main(String argv[]) throws Exception {
|
||||
int error = 0;
|
||||
Method[] methods = Foo.class.getMethods();
|
||||
for(Method m : methods) {
|
||||
System.err.println("Inspecting method " + m);
|
||||
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++;
|
||||
}
|
||||
WithoutParameters wp = new WithoutParameters();
|
||||
wp.runTests(Foo.class.getMethods());
|
||||
wp.runTests(Foo.Inner.class.getConstructors());
|
||||
wp.checkForErrors();
|
||||
}
|
||||
|
||||
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 {
|
||||
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,
|
||||
List<?> l, List<Foo> l2,
|
||||
List<? extends Foo> l3,
|
||||
String... rest) {}
|
||||
public class Inner {
|
||||
int thang;
|
||||
@ExpectedParameterInfo(parameterCount = 2,
|
||||
parameterTypes = {Foo.class, int.class})
|
||||
public Inner(int theng) {
|
||||
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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -21,71 +21,235 @@
|
||||
* 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
|
||||
* 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
|
||||
* 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.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class Constructor {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
URL url = null;
|
||||
String urls = "jar_urls";
|
||||
if (args.length > 0 && args[0] != null) {
|
||||
urls = args[0];
|
||||
}
|
||||
List<Entry> entries = new ArrayList<>();
|
||||
entries.addAll(Arrays.asList(fileURLs));
|
||||
entries.addAll(Arrays.asList(jarURLs));
|
||||
entries.addAll(Arrays.asList(normalHttpURLs));
|
||||
entries.addAll(Arrays.asList(abnormalHttpURLs));
|
||||
if (hasFtp())
|
||||
entries.addAll(Arrays.asList(ftpURLs));
|
||||
URL url;
|
||||
|
||||
File f = new File(urls);
|
||||
InputStream file = new FileInputStream(f);
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(file));
|
||||
while(true) {
|
||||
String context = in.readLine();
|
||||
if (context == null) {
|
||||
break;
|
||||
}
|
||||
context = getValue(context);
|
||||
String spec = getValue(in.readLine());
|
||||
String expected = getValue(in.readLine());
|
||||
for (Entry e : entries) {
|
||||
if (e.context == null)
|
||||
url = new URL(e.spec);
|
||||
else
|
||||
url = new URL(new URL(e.context), e.spec);
|
||||
|
||||
if (context.equals("null")) {
|
||||
url = new URL(spec);
|
||||
} else {
|
||||
url = new URL(new URL(context), spec);
|
||||
}
|
||||
if (!(url.toString().equals(expected))) {
|
||||
throw new RuntimeException("error for: \n\tURL:" + context +
|
||||
"\n\tspec: " + spec +
|
||||
"\n\texpected: " + expected +
|
||||
if (!(url.toString().equals(e.expected))) {
|
||||
throw new RuntimeException("error for: \n\tURL:" + e.context +
|
||||
"\n\tspec: " + e.spec +
|
||||
"\n\texpected: " + e.expected +
|
||||
"\n\tactual: " + url.toString());
|
||||
} 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) {
|
||||
return value.substring(value.indexOf(':') + 2);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
URL.setURLStreamHandlerFactory(
|
||||
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);
|
||||
url.openConnection();
|
||||
}
|
||||
|
@ -310,7 +310,14 @@ public class Test {
|
||||
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 --
|
||||
|
||||
@ -319,8 +326,9 @@ public class Test {
|
||||
|
||||
header("RFC2396: Basic examples");
|
||||
|
||||
test("ftp://ftp.is.co.za/rfc/rfc1808.txt")
|
||||
.s("ftp").h("ftp.is.co.za").p("/rfc/rfc1808.txt").z();
|
||||
if (hasFtp())
|
||||
test("ftp://ftp.is.co.za/rfc/rfc1808.txt")
|
||||
.s("ftp").h("ftp.is.co.za").p("/rfc/rfc1808.txt").z();
|
||||
|
||||
test("http://www.math.uio.no/faq/compression-faq/part1.html")
|
||||
.s("http").h("www.math.uio.no").p("/faq/compression-faq/part1.html").z();
|
||||
@ -328,8 +336,9 @@ public class Test {
|
||||
test("http://www.w3.org/Addressing/")
|
||||
.s("http").h("www.w3.org").p("/Addressing/").z();
|
||||
|
||||
test("ftp://ds.internic.net/rfc/")
|
||||
.s("ftp").h("ds.internic.net").p("/rfc/").z();
|
||||
if (hasFtp())
|
||||
test("ftp://ds.internic.net/rfc/")
|
||||
.s("ftp").h("ds.internic.net").p("/rfc/").z();
|
||||
|
||||
test("http://www.ics.uci.edu/pub/ietf/url/historical.html#WARNING")
|
||||
.s("http").h("www.ics.uci.edu").p("/pub/ietf/url/historical.html")
|
||||
|
@ -28,20 +28,22 @@
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class URIToURLTest {
|
||||
public static void main(String args[]) throws Exception {
|
||||
String[] uris = {
|
||||
"http://jag:cafebabe@java.sun.com:94/b/c/d?q#g",
|
||||
"http://[1080:0:0:0:8:800:200C:417A]/index.html",
|
||||
"http://a/b/c/d;p?q",
|
||||
"ftp://ftp.is.co.za/rfc/rfc1808.txt",
|
||||
"mailto:mduerst@ifi.unizh.ch", // opaque url
|
||||
"http:comp.infosystems.www.servers.unix" //opaque url
|
||||
};
|
||||
List<String> uris = new ArrayList<>();
|
||||
uris.add("http://jag:cafebabe@java.sun.com:94/b/c/d?q#g");
|
||||
uris.add("http://[1080:0:0:0:8:800:200C:417A]/index.html");
|
||||
uris.add("http://a/b/c/d;p?q");
|
||||
uris.add("mailto:mduerst@ifi.unizh.ch");
|
||||
uris.add("http:comp.infosystems.www.servers.unix");
|
||||
if (hasFtp())
|
||||
uris.add("ftp://ftp.is.co.za/rfc/rfc1808.txt");
|
||||
|
||||
for (int i = 0; i < uris.length; i++) {
|
||||
URI uri = new URI(uris[i]);
|
||||
for (String uriStr : uris) {
|
||||
URI uri = new URI(uriStr);
|
||||
URL url = uri.toURL();
|
||||
String scheme = uri.getScheme();
|
||||
boolean schemeCheck = scheme == null? url.getProtocol() == null :
|
||||
@ -111,4 +113,13 @@ public class URIToURLTest {
|
||||
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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -28,90 +28,55 @@
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class RequestProperties {
|
||||
public static void main (String args[]) throws Exception {
|
||||
URL url0 = new URL ("http://foo.com/bar/");
|
||||
URL url1 = new URL ("file:/etc/passwd");
|
||||
URL url2 = new URL ("ftp://foo:bar@foobar.com/etc/passwd");
|
||||
URL url3 = new URL ("jar:http://foo.com/bar.html!/foo/bar");
|
||||
URLConnection urlc0 = url0.openConnection ();
|
||||
URLConnection urlc1 = url1.openConnection ();
|
||||
URLConnection urlc2 = url2.openConnection ();
|
||||
URLConnection urlc3 = url3.openConnection ();
|
||||
int count = 0;
|
||||
String s = null;
|
||||
try {
|
||||
urlc0.setRequestProperty (null, null);
|
||||
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 ++;
|
||||
}
|
||||
static int failed;
|
||||
|
||||
if (count != 12) {
|
||||
throw new RuntimeException ((12 -count) + " errors") ;
|
||||
public static void main (String args[]) throws Exception {
|
||||
List<String> urls = new ArrayList<>();
|
||||
urls.add("http://foo.com/bar/");
|
||||
urls.add("jar:http://foo.com/bar.html!/foo/bar");
|
||||
urls.add("file:/etc/passwd");
|
||||
if (hasFtp())
|
||||
urls.add("ftp://foo:bar@foobar.com/etc/passwd");
|
||||
|
||||
for (String urlStr : urls)
|
||||
test(new URL(urlStr));
|
||||
|
||||
if (failed != 0)
|
||||
throw new RuntimeException(failed + " errors") ;
|
||||
}
|
||||
|
||||
static void test(URL url) throws Exception {
|
||||
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
|
||||
*/
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Part1:
|
||||
@ -45,28 +48,29 @@ public class RequestPropertyValues {
|
||||
}
|
||||
|
||||
public static void part1() throws Exception {
|
||||
URL[] urls = { new URL("http://localhost:8088"),
|
||||
new URL("file:/etc/passwd"),
|
||||
new URL("ftp://foo:bar@foobar.com/etc/passwd"),
|
||||
new URL("jar:http://foo.com/bar.html!/foo/bar")
|
||||
};
|
||||
List<URL> urls = new ArrayList<>();
|
||||
urls.add(new URL("http://localhost:8088"));
|
||||
urls.add(new URL("file:/etc/passwd"));
|
||||
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;
|
||||
|
||||
for (int proto = 0; proto < urls.length; proto++) {
|
||||
URLConnection uc = (URLConnection) urls[proto].openConnection();
|
||||
for (URL url : urls) {
|
||||
URLConnection uc = url.openConnection();
|
||||
try {
|
||||
uc.setRequestProperty("TestHeader", null);
|
||||
} catch (NullPointerException npe) {
|
||||
System.out.println("setRequestProperty is throwing NPE" +
|
||||
" for url: " + urls[proto]);
|
||||
" for url: " + url);
|
||||
failed = true;
|
||||
}
|
||||
try {
|
||||
uc.addRequestProperty("TestHeader", null);
|
||||
} catch (NullPointerException npe) {
|
||||
System.out.println("addRequestProperty is throwing NPE" +
|
||||
" for url: " + urls[proto]);
|
||||
" for url: " + url);
|
||||
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,45 +58,46 @@ public class PBETest {
|
||||
|
||||
new File(NEW_KEYSTORE).delete();
|
||||
|
||||
try {
|
||||
KeyStore keystore = load(KEYSTORE_TYPE, KEYSTORE, PASSWORD);
|
||||
KeyStore.Entry entry =
|
||||
keystore.getEntry(ALIAS,
|
||||
new KeyStore.PasswordProtection(PASSWORD));
|
||||
System.out.println("Retrieved entry named '" + ALIAS + "'");
|
||||
|
||||
// Set entry
|
||||
KeyStore keystore2 = load(NEW_KEYSTORE_TYPE, null, null);
|
||||
keystore2.setEntry(ALIAS, entry,
|
||||
new KeyStore.PasswordProtection(PASSWORD, PBE_ALGO,
|
||||
new PBEParameterSpec(SALT, ITERATION_COUNT,
|
||||
new IvParameterSpec(IV))));
|
||||
System.out.println("Encrypted entry using: " + PBE_ALGO);
|
||||
|
||||
System.out.println("Storing keystore to: " + NEW_KEYSTORE);
|
||||
keystore2.store(new FileOutputStream(NEW_KEYSTORE), PASSWORD);
|
||||
|
||||
keystore2 = load(NEW_KEYSTORE_TYPE, NEW_KEYSTORE, PASSWORD);
|
||||
entry = keystore2.getEntry(ALIAS,
|
||||
KeyStore keystore = load(KEYSTORE_TYPE, KEYSTORE, PASSWORD);
|
||||
KeyStore.Entry entry =
|
||||
keystore.getEntry(ALIAS,
|
||||
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);
|
||||
// Set entry
|
||||
KeyStore keystore2 = load(NEW_KEYSTORE_TYPE, null, null);
|
||||
keystore2.setEntry(ALIAS, entry,
|
||||
new KeyStore.PasswordProtection(PASSWORD, PBE_ALGO,
|
||||
new PBEParameterSpec(SALT, ITERATION_COUNT,
|
||||
new IvParameterSpec(IV))));
|
||||
System.out.println("Encrypted entry using: " + PBE_ALGO);
|
||||
|
||||
try (FileOutputStream outStream = new FileOutputStream(NEW_KEYSTORE)) {
|
||||
System.out.println("Storing keystore to: " + NEW_KEYSTORE);
|
||||
keystore2.store(outStream, PASSWORD);
|
||||
}
|
||||
|
||||
keystore2 = load(NEW_KEYSTORE_TYPE, NEW_KEYSTORE, PASSWORD);
|
||||
entry = keystore2.getEntry(ALIAS,
|
||||
new KeyStore.PasswordProtection(PASSWORD));
|
||||
System.out.println("Retrieved entry named '" + ALIAS + "'");
|
||||
}
|
||||
|
||||
private static KeyStore load(String type, String path, char[] password)
|
||||
throws Exception {
|
||||
|
||||
FileInputStream stream = null;
|
||||
if (path != null) {
|
||||
stream = new FileInputStream(path);
|
||||
}
|
||||
KeyStore keystore = KeyStore.getInstance(type);
|
||||
System.out.println("Loading keystore from: " + path);
|
||||
keystore.load(stream, password);
|
||||
|
||||
if (path != null) {
|
||||
|
||||
try (FileInputStream inStream = new FileInputStream(path)) {
|
||||
System.out.println("Loading keystore from: " + path);
|
||||
keystore.load(inStream, password);
|
||||
System.out.println("Loaded keystore with " + keystore.size() +
|
||||
" entries");
|
||||
}
|
||||
} else {
|
||||
keystore.load(null, null);
|
||||
}
|
||||
|
||||
return keystore;
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test 4235519 8004212
|
||||
* @test 4235519 8004212 8005394 8007298 8006295 8006315 8006530
|
||||
* @summary tests java.util.Base64
|
||||
*/
|
||||
|
||||
@ -109,6 +109,15 @@ public class TestBase64 {
|
||||
|
||||
// test return value from decode(ByteBuffer, ByteBuffer)
|
||||
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();
|
||||
@ -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, 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.wrap(null); }});
|
||||
}
|
||||
|
||||
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, ByteBuffer.allocate(10)); }});
|
||||
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 {
|
||||
@ -354,6 +365,94 @@ public class TestBase64 {
|
||||
} 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 {
|
||||
Random rnd = new java.util.Random();
|
||||
|
@ -1103,6 +1103,15 @@ public class Basic$Type$ extends Basic {
|
||||
test("%.5f", "1.99999", 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]
|
||||
|
||||
#if[float]
|
||||
|
@ -1102,6 +1102,15 @@ public class BasicBigDecimal extends Basic {
|
||||
test("%.4f", "2.0000", val);
|
||||
test("%.5f", "1.99999", 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 java.io.IOException;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
@ -86,20 +87,26 @@ public class DeadListenerTest {
|
||||
Map<ObjectName, Set<?>> listenerMap = (Map<ObjectName, Set<?>>) listenerMapF.get(serverNotifForwarder);
|
||||
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);
|
||||
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();
|
||||
dummyFilter.enableType("");
|
||||
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);
|
||||
Set<?> set = listenerMap.get(name);
|
||||
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 count2 == 0", count2.count() == 0);
|
||||
assertTrue("Initial value of count1 == 0", count1Val.get() == 0);
|
||||
assertTrue("Initial value of count2 == 0", count2Val.get() == 0);
|
||||
|
||||
Notification notif = new Notification("type", name, 0);
|
||||
|
||||
@ -107,11 +114,11 @@ public class DeadListenerTest {
|
||||
|
||||
// Make sure notifs are working normally.
|
||||
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);
|
||||
}
|
||||
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);
|
||||
|
||||
// Make sure that removing a nonexistent listener from an existent MBean produces ListenerNotFoundException
|
||||
CountListener count3 = new CountListener();
|
||||
@ -136,28 +143,29 @@ public class DeadListenerTest {
|
||||
mbs.unregisterMBean(name);
|
||||
mbean.sendNotification(notif);
|
||||
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.
|
||||
// THIS DEPENDS ON JMX IMPLEMENTATION DETAILS.
|
||||
// If the JMX implementation changes, the code here may have to change too.
|
||||
Set<?> setForUnreg = listenerMap.get(name);
|
||||
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) {
|
||||
@ -173,6 +181,10 @@ public class DeadListenerTest {
|
||||
public static class CountListener implements NotificationListener {
|
||||
final AtomicInteger count;
|
||||
|
||||
public CountListener(AtomicInteger i) {
|
||||
count = i;
|
||||
}
|
||||
|
||||
public CountListener() {
|
||||
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 {
|
||||
ProxyTest test = new ProxyTest();
|
||||
if (hasFtp())
|
||||
new ProxyTest();
|
||||
}
|
||||
|
||||
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