This commit is contained in:
Lana Steuck 2013-02-05 11:11:53 -08:00
commit bab241d2e7
110 changed files with 5618 additions and 1632 deletions

View File

@ -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

View File

@ -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

View File

@ -39,11 +39,11 @@
<classpath mode="boot">${bootstrap.jdk}/jre/lib/rt.jar</classpath> <classpath mode="boot">${bootstrap.jdk}/jre/lib/rt.jar</classpath>
<built-to>${root}/build/${platform}-${arch}/classes</built-to> <built-to>${root}/build/${platform}-${arch}/classes</built-to>
<javadoc-built-to>${root}/build/${platform}-${arch}/docs/api</javadoc-built-to> <javadoc-built-to>${root}/build/${platform}-${arch}/docs/api</javadoc-built-to>
<source-level>1.7</source-level> <source-level>1.8</source-level>
</compilation-unit> </compilation-unit>
<compilation-unit> <compilation-unit>
<package-root>${root}/test</package-root> <package-root>${root}/test</package-root>
<unit-tests/> <unit-tests/>
<source-level>1.7</source-level> <source-level>1.8</source-level>
</compilation-unit> </compilation-unit>
</java-data> </java-data>

View File

@ -37,11 +37,11 @@
<classpath mode="boot">${bootstrap.jdk}/jre/lib/rt.jar</classpath> <classpath mode="boot">${bootstrap.jdk}/jre/lib/rt.jar</classpath>
<built-to>${root}/build/${platform}-${arch}/classes</built-to> <built-to>${root}/build/${platform}-${arch}/classes</built-to>
<javadoc-built-to>${root}/build/${platform}-${arch}/docs/api</javadoc-built-to> <javadoc-built-to>${root}/build/${platform}-${arch}/docs/api</javadoc-built-to>
<source-level>1.7</source-level> <source-level>1.8</source-level>
</compilation-unit> </compilation-unit>
<compilation-unit> <compilation-unit>
<package-root>${root}/test</package-root> <package-root>${root}/test</package-root>
<unit-tests/> <unit-tests/>
<source-level>1.7</source-level> <source-level>1.8</source-level>
</compilation-unit> </compilation-unit>
</java-data> </java-data>

View File

@ -33,7 +33,7 @@
<project name="make" basedir=".."> <project name="make" basedir="..">
<target name="-make.init" depends="-init,-pre-init.linux,-pre-init.solaris,-pre-init.windows"> <target name="-make.init" depends="-init,-pre-init.linux,-pre-init.macosx,-pre-init.solaris,-pre-init.windows,-pre-init.macosx">
<property name="make.options" value=""/> <!-- default, can be overridden per user or per project --> <property name="make.options" value=""/> <!-- default, can be overridden per user or per project -->
</target> </target>
@ -42,6 +42,11 @@
<property name="make" value="make"/> <property name="make" value="make"/>
</target> </target>
<target name="-pre-init.macosx" if="os.macosx">
<property name="platform" value="macosx"/>
<property name="make" value="make"/>
</target>
<target name="-pre-init.solaris" if="os.solaris"> <target name="-pre-init.solaris" if="os.solaris">
<property name="platform" value="solaris"/> <property name="platform" value="solaris"/>
<property name="make" value="gmake"/> <property name="make" value="gmake"/>

View File

@ -85,6 +85,9 @@
<property name="includes" value="(nothing)"/> <property name="includes" value="(nothing)"/>
<property name="excludes" value=""/> <property name="excludes" value=""/>
<property name="javadoc.dir" location="${build.dir}/javadoc/${ant.project.name}"/> <property name="javadoc.dir" location="${build.dir}/javadoc/${ant.project.name}"/>
<condition property="os.macosx">
<os family="mac"/>
</condition>
<condition property="os.linux"> <condition property="os.linux">
<os name="linux"/> <os name="linux"/>
</condition> </condition>
@ -126,10 +129,6 @@
<javac srcdir="@{srcdir}" includes="@{includes}" excludes="@{excludes}" sourcepath="" <javac srcdir="@{srcdir}" includes="@{includes}" excludes="@{excludes}" sourcepath=""
destdir="@{classesdir}" fork="true" executable="${bootstrap.javac}" destdir="@{classesdir}" fork="true" executable="${bootstrap.javac}"
debug="${javac.debug}" debuglevel="${javac.debuglevel}"> debug="${javac.debug}" debuglevel="${javac.debuglevel}">
<compilerarg value="-source"/>
<compilerarg value="1.5"/>
<compilerarg value="-target"/>
<compilerarg value="1.6"/> <!-- for usability of JDK 6 as snapshot; change to 1.7 when JSR 294 put back -->
<!-- Mandatory for compiling partial JDK sources against a snapshot; should NEVER be used for any other purpose: --> <!-- Mandatory for compiling partial JDK sources against a snapshot; should NEVER be used for any other purpose: -->
<compilerarg value="-XDignore.symbol.file=true"/> <compilerarg value="-XDignore.symbol.file=true"/>
<compilerarg line="${javac.options}"/> <compilerarg line="${javac.options}"/>

View File

@ -1287,19 +1287,24 @@ class Attribute implements Comparable<Attribute> {
if (localRef == 0) { if (localRef == 0) {
globalRef = null; // N.B. global null reference is -1 globalRef = null; // N.B. global null reference is -1
} else { } else {
globalRef = holder.getCPMap()[localRef]; Entry[] cpMap = holder.getCPMap();
if (e.refKind == CONSTANT_Signature globalRef = (localRef >= 0 && localRef < cpMap.length
? cpMap[localRef]
: null);
byte tag = e.refKind;
if (globalRef != null && tag == CONSTANT_Signature
&& globalRef.getTag() == CONSTANT_Utf8) { && globalRef.getTag() == CONSTANT_Utf8) {
// Cf. ClassReader.readSignatureRef. // Cf. ClassReader.readSignatureRef.
String typeName = globalRef.stringValue(); String typeName = globalRef.stringValue();
globalRef = ConstantPool.getSignatureEntry(typeName); globalRef = ConstantPool.getSignatureEntry(typeName);
} else if (e.refKind == CONSTANT_FieldSpecific) { }
assert(globalRef.getTag() >= CONSTANT_Integer); String got = (globalRef == null
assert(globalRef.getTag() <= CONSTANT_String || ? "invalid CP index"
globalRef.getTag() >= CONSTANT_MethodHandle); : "type=" + ConstantPool.tagName(globalRef.tag));
assert(globalRef.getTag() <= CONSTANT_MethodType); if (globalRef == null || !globalRef.tagMatches(tag)) {
} else if (e.refKind < CONSTANT_GroupFirst) { throw new IllegalArgumentException(
assert(e.refKind == globalRef.getTag()); "Bad constant, expected type=" +
ConstantPool.tagName(tag) + " got " + got);
} }
} }
out.putRef(bandIndex, globalRef); out.putRef(bandIndex, globalRef);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -54,6 +54,7 @@ class ClassReader {
Package pkg; Package pkg;
Class cls; Class cls;
long inPos; long inPos;
long constantPoolLimit = -1;
DataInputStream in; DataInputStream in;
Map<Attribute.Layout, Attribute> attrDefs; Map<Attribute.Layout, Attribute> attrDefs;
Map<Attribute.Layout, String> attrCommands; Map<Attribute.Layout, String> attrCommands;
@ -117,15 +118,33 @@ class ClassReader {
private Entry readRef(byte tag) throws IOException { private Entry readRef(byte tag) throws IOException {
Entry e = readRef(); Entry e = readRef();
assert(e != null);
assert(!(e instanceof UnresolvedEntry)); assert(!(e instanceof UnresolvedEntry));
assert(e.tagMatches(tag)); checkTag(e, tag);
return e; return e;
} }
/** Throw a ClassFormatException if the entry does not match the expected tag type. */
private Entry checkTag(Entry e, byte tag) throws ClassFormatException {
if (e == null || !e.tagMatches(tag)) {
String where = (inPos == constantPoolLimit
? " in constant pool"
: " at pos: " + inPos);
String got = (e == null
? "null CP index"
: "type=" + ConstantPool.tagName(e.tag));
throw new ClassFormatException("Bad constant, expected type=" +
ConstantPool.tagName(tag) +
" got "+ got + ", in File: " + cls.file.nameString + where);
}
return e;
}
private Entry checkTag(Entry e, byte tag, boolean nullOK) throws ClassFormatException {
return nullOK && e == null ? null : checkTag(e, tag);
}
private Entry readRefOrNull(byte tag) throws IOException { private Entry readRefOrNull(byte tag) throws IOException {
Entry e = readRef(); Entry e = readRef();
assert(e == null || e.tagMatches(tag)); checkTag(e, tag, true);
return e; return e;
} }
@ -143,8 +162,10 @@ class ClassReader {
private SignatureEntry readSignatureRef() throws IOException { private SignatureEntry readSignatureRef() throws IOException {
// The class file stores a Utf8, but we want a Signature. // The class file stores a Utf8, but we want a Signature.
Entry e = readRef(CONSTANT_Utf8); Entry e = readRef(CONSTANT_Signature);
return ConstantPool.getSignatureEntry(e.stringValue()); return (e != null && e.getTag() == CONSTANT_Utf8)
? ConstantPool.getSignatureEntry(e.stringValue())
: (SignatureEntry) e;
} }
void read() throws IOException { void read() throws IOException {
@ -279,6 +300,7 @@ class ClassReader {
" at pos: " + inPos); " at pos: " + inPos);
} }
} }
constantPoolLimit = inPos;
// Fix up refs, which might be out of order. // Fix up refs, which might be out of order.
while (fptr > 0) { while (fptr > 0) {
@ -311,25 +333,25 @@ class ClassReader {
case CONSTANT_Fieldref: case CONSTANT_Fieldref:
case CONSTANT_Methodref: case CONSTANT_Methodref:
case CONSTANT_InterfaceMethodref: case CONSTANT_InterfaceMethodref:
ClassEntry mclass = (ClassEntry) cpMap[ref]; ClassEntry mclass = (ClassEntry) checkTag(cpMap[ref], CONSTANT_Class);
DescriptorEntry mdescr = (DescriptorEntry) cpMap[ref2]; DescriptorEntry mdescr = (DescriptorEntry) checkTag(cpMap[ref2], CONSTANT_NameandType);
cpMap[cpi] = ConstantPool.getMemberEntry((byte)tag, mclass, mdescr); cpMap[cpi] = ConstantPool.getMemberEntry((byte)tag, mclass, mdescr);
break; break;
case CONSTANT_NameandType: case CONSTANT_NameandType:
Utf8Entry mname = (Utf8Entry) cpMap[ref]; Utf8Entry mname = (Utf8Entry) checkTag(cpMap[ref], CONSTANT_Utf8);
Utf8Entry mtype = (Utf8Entry) cpMap[ref2]; Utf8Entry mtype = (Utf8Entry) checkTag(cpMap[ref2], CONSTANT_Signature);
cpMap[cpi] = ConstantPool.getDescriptorEntry(mname, mtype); cpMap[cpi] = ConstantPool.getDescriptorEntry(mname, mtype);
break; break;
case CONSTANT_MethodType: case CONSTANT_MethodType:
cpMap[cpi] = ConstantPool.getMethodTypeEntry((Utf8Entry) cpMap[ref]); cpMap[cpi] = ConstantPool.getMethodTypeEntry((Utf8Entry) checkTag(cpMap[ref], CONSTANT_Signature));
break; break;
case CONSTANT_MethodHandle: case CONSTANT_MethodHandle:
byte refKind = (byte)(-1 ^ ref); byte refKind = (byte)(-1 ^ ref);
MemberEntry memRef = (MemberEntry) cpMap[ref2]; MemberEntry memRef = (MemberEntry) checkTag(cpMap[ref2], CONSTANT_AnyMember);
cpMap[cpi] = ConstantPool.getMethodHandleEntry(refKind, memRef); cpMap[cpi] = ConstantPool.getMethodHandleEntry(refKind, memRef);
break; break;
case CONSTANT_InvokeDynamic: case CONSTANT_InvokeDynamic:
DescriptorEntry idescr = (DescriptorEntry) cpMap[ref2]; DescriptorEntry idescr = (DescriptorEntry) checkTag(cpMap[ref2], CONSTANT_NameandType);
cpMap[cpi] = new UnresolvedEntry((byte)tag, (-1 ^ ref), idescr); cpMap[cpi] = new UnresolvedEntry((byte)tag, (-1 ^ ref), idescr);
// Note that ref must be resolved later, using the BootstrapMethods attribute. // Note that ref must be resolved later, using the BootstrapMethods attribute.
break; break;
@ -541,7 +563,8 @@ class ClassReader {
code.max_locals = readUnsignedShort(); code.max_locals = readUnsignedShort();
code.bytes = new byte[readInt()]; code.bytes = new byte[readInt()];
in.readFully(code.bytes); in.readFully(code.bytes);
Instruction.opcodeChecker(code.bytes); Entry[] cpMap = cls.getCPMap();
Instruction.opcodeChecker(code.bytes, cpMap);
int nh = readUnsignedShort(); int nh = readUnsignedShort();
code.setHandlerCount(nh); code.setHandlerCount(nh);
for (int i = 0; i < nh; i++) { for (int i = 0; i < nh; i++) {
@ -559,7 +582,7 @@ class ClassReader {
MethodHandleEntry bsmRef = (MethodHandleEntry) readRef(CONSTANT_MethodHandle); MethodHandleEntry bsmRef = (MethodHandleEntry) readRef(CONSTANT_MethodHandle);
Entry[] argRefs = new Entry[readUnsignedShort()]; Entry[] argRefs = new Entry[readUnsignedShort()];
for (int j = 0; j < argRefs.length; j++) { for (int j = 0; j < argRefs.length; j++) {
argRefs[j] = readRef(); argRefs[j] = readRef(CONSTANT_LoadableValue);
} }
bsms[i] = ConstantPool.getBootstrapMethodEntry(bsmRef, argRefs); bsms[i] = ConstantPool.getBootstrapMethodEntry(bsmRef, argRefs);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -243,8 +243,32 @@ class ConstantPool {
return tag == CONSTANT_Double || tag == CONSTANT_Long; return tag == CONSTANT_Double || tag == CONSTANT_Long;
} }
public final boolean tagMatches(int tag) { public final boolean tagMatches(int matchTag) {
return (this.tag == tag); if (tag == matchTag)
return true;
byte[] allowedTags;
switch (matchTag) {
case CONSTANT_All:
return true;
case CONSTANT_Signature:
return tag == CONSTANT_Utf8; // format check also?
case CONSTANT_LoadableValue:
allowedTags = LOADABLE_VALUE_TAGS;
break;
case CONSTANT_AnyMember:
allowedTags = ANY_MEMBER_TAGS;
break;
case CONSTANT_FieldSpecific:
allowedTags = FIELD_SPECIFIC_TAGS;
break;
default:
return false;
}
for (byte b : allowedTags) {
if (b == tag)
return true;
}
return false;
} }
public String toString() { public String toString() {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -647,7 +647,7 @@ class Instruction {
} }
} }
public static void opcodeChecker(byte[] code) throws FormatException { public static void opcodeChecker(byte[] code, ConstantPool.Entry[] cpMap) throws FormatException {
Instruction i = at(code, 0); Instruction i = at(code, 0);
while (i != null) { while (i != null) {
int opcode = i.getBC(); int opcode = i.getBC();
@ -655,6 +655,16 @@ class Instruction {
String message = "illegal opcode: " + opcode + " " + i; String message = "illegal opcode: " + opcode + " " + i;
throw new FormatException(message); throw new FormatException(message);
} }
ConstantPool.Entry e = i.getCPRef(cpMap);
if (e != null) {
byte tag = i.getCPTag();
if (!e.tagMatches(tag)) {
String message = "illegal reference, expected type=" +
ConstantPool.tagName(tag) + ": " +
i.toString(cpMap);
throw new FormatException(message);
}
}
i = i.next(); i = i.next();
} }
} }

View File

@ -1618,6 +1618,16 @@ class PackageWriter extends BandStructure {
bc_which = null; bc_which = null;
assert(false); assert(false);
} }
if (ref != null && bc_which.index != null && !bc_which.index.contains(ref)) {
// Crash and burn with a complaint if there are funny
// references for this bytecode instruction.
// Example: invokestatic of a CONSTANT_InterfaceMethodref.
String complaint = code.getMethod() +
" contains a bytecode " + i +
" with an unsupported constant reference; please use the pass-file option on this class.";
Utils.log.warning(complaint);
throw new IOException(complaint);
}
bc_codes.putByte(vbc); bc_codes.putByte(vbc);
bc_which.putRef(ref); bc_which.putRef(ref);
// handle trailing junk // handle trailing junk

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -180,6 +180,15 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer {
} }
unknownAttrCommand = uaMode.intern(); unknownAttrCommand = uaMode.intern();
} }
final String classFormatCommand;
{
String fmtMode = props.getProperty(Utils.CLASS_FORMAT_ERROR, Pack200.Packer.PASS);
if (!(Pack200.Packer.PASS.equals(fmtMode) ||
Pack200.Packer.ERROR.equals(fmtMode))) {
throw new RuntimeException("Bad option: " + Utils.CLASS_FORMAT_ERROR + " = " + fmtMode);
}
classFormatCommand = fmtMode.intern();
}
final Map<Attribute.Layout, Attribute> attrDefs; final Map<Attribute.Layout, Attribute> attrDefs;
final Map<Attribute.Layout, String> attrCommands; final Map<Attribute.Layout, String> attrCommands;
@ -505,8 +514,7 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer {
} }
} else if (ioe instanceof ClassReader.ClassFormatException) { } else if (ioe instanceof ClassReader.ClassFormatException) {
ClassReader.ClassFormatException ce = (ClassReader.ClassFormatException) ioe; ClassReader.ClassFormatException ce = (ClassReader.ClassFormatException) ioe;
// %% TODO: Do we invent a new property for this or reuse %% if (classFormatCommand.equals(Pack200.Packer.PASS)) {
if (unknownAttrCommand.equals(Pack200.Packer.PASS)) {
Utils.log.info(ce.toString()); Utils.log.info(ce.toString());
Utils.log.warning(message + " unknown class format: " + Utils.log.warning(message + " unknown class format: " +
fname); fname);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -112,6 +112,11 @@ final class PropMap implements SortedMap<String, String> {
// Pass through files with unrecognized attributes by default. // Pass through files with unrecognized attributes by default.
props.put(Pack200.Packer.UNKNOWN_ATTRIBUTE, Pack200.Packer.PASS); props.put(Pack200.Packer.UNKNOWN_ATTRIBUTE, Pack200.Packer.PASS);
// Pass through files with unrecognized format by default, also
// allow system property to be set
props.put(Utils.CLASS_FORMAT_ERROR,
System.getProperty(Utils.CLASS_FORMAT_ERROR, Pack200.Packer.PASS));
// Default effort is 5, midway between 1 and 9. // Default effort is 5, midway between 1 and 9.
props.put(Pack200.Packer.EFFORT, "5"); props.put(Pack200.Packer.EFFORT, "5");

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -122,6 +122,12 @@ class Utils {
*/ */
static final String PACK_ZIP_ARCHIVE_MARKER_COMMENT = "PACK200"; static final String PACK_ZIP_ARCHIVE_MARKER_COMMENT = "PACK200";
/*
* behaviour when we hit a class format error, but not necessarily
* an unknown attribute, by default it is allowed to PASS.
*/
static final String CLASS_FORMAT_ERROR = COM_PREFIX+"class.format.error";
// Keep a TLS point to the global data and environment. // Keep a TLS point to the global data and environment.
// This makes it simpler to supply environmental options // This makes it simpler to supply environmental options
// to the engine code, especially the native code. // to the engine code, especially the native code.

View File

@ -50,8 +50,6 @@ import javax.management.MBeanInfo;
import javax.management.NotCompliantMBeanException; import javax.management.NotCompliantMBeanException;
import com.sun.jmx.remote.util.EnvHelp; import com.sun.jmx.remote.util.EnvHelp;
import java.beans.BeanInfo;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import javax.management.AttributeNotFoundException; import javax.management.AttributeNotFoundException;

View File

@ -29,12 +29,14 @@ import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType; import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Executable;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable; import java.lang.reflect.TypeVariable;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.AnnotatedType;
import java.lang.ref.SoftReference; import java.lang.ref.SoftReference;
import java.io.InputStream; import java.io.InputStream;
import java.io.ObjectStreamField; import java.io.ObjectStreamField;
@ -2325,6 +2327,11 @@ public final
// Annotations handling // Annotations handling
private native byte[] getRawAnnotations(); private native byte[] getRawAnnotations();
// Since 1.8
native byte[] getRawTypeAnnotations();
static byte[] getExecutableTypeAnnotationBytes(Executable ex) {
return getReflectionFactory().getExecutableTypeAnnotationBytes(ex);
}
native ConstantPool getConstantPool(); native ConstantPool getConstantPool();
@ -3068,21 +3075,12 @@ public final
* @throws NullPointerException {@inheritDoc} * @throws NullPointerException {@inheritDoc}
* @since 1.5 * @since 1.5
*/ */
@SuppressWarnings("unchecked")
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) { public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
Objects.requireNonNull(annotationClass); Objects.requireNonNull(annotationClass);
initAnnotationsIfNecessary(); initAnnotationsIfNecessary();
return AnnotationSupport.getOneAnnotation(annotations, annotationClass); return (A) annotations.get(annotationClass);
}
/**
* @throws NullPointerException {@inheritDoc}
* @since 1.5
*/
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
Objects.requireNonNull(annotationClass);
return getAnnotation(annotationClass) != null;
} }
/** /**
@ -3101,18 +3099,19 @@ public final
*/ */
public Annotation[] getAnnotations() { public Annotation[] getAnnotations() {
initAnnotationsIfNecessary(); initAnnotationsIfNecessary();
return AnnotationSupport.unpackToArray(annotations); return AnnotationParser.toArray(annotations);
} }
/** /**
* @throws NullPointerException {@inheritDoc} * @throws NullPointerException {@inheritDoc}
* @since 1.8 * @since 1.8
*/ */
@SuppressWarnings("unchecked")
public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) { public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) {
Objects.requireNonNull(annotationClass); Objects.requireNonNull(annotationClass);
initAnnotationsIfNecessary(); initAnnotationsIfNecessary();
return AnnotationSupport.getOneAnnotation(declaredAnnotations, annotationClass); return (A) declaredAnnotations.get(annotationClass);
} }
/** /**
@ -3131,17 +3130,7 @@ public final
*/ */
public Annotation[] getDeclaredAnnotations() { public Annotation[] getDeclaredAnnotations() {
initAnnotationsIfNecessary(); initAnnotationsIfNecessary();
return AnnotationSupport.unpackToArray(declaredAnnotations); return AnnotationParser.toArray(declaredAnnotations);
}
/** Returns one "directly" present annotation or null */
<A extends Annotation> A getDirectDeclaredAnnotation(Class<A> annotationClass) {
Objects.requireNonNull(annotationClass);
initAnnotationsIfNecessary();
@SuppressWarnings("unchecked") // TODO check safe
A ret = (A)declaredAnnotations.get(annotationClass);
return ret;
} }
// Annotations cache // Annotations cache
@ -3196,4 +3185,53 @@ public final
* Maintained by the ClassValue class. * Maintained by the ClassValue class.
*/ */
transient ClassValue.ClassValueMap classValueMap; transient ClassValue.ClassValueMap classValueMap;
/**
* Returns an AnnotatedType object that represents the use of a type to specify
* the superclass of the entity represented by this Class. (The <em>use</em> of type
* Foo to specify the superclass in '... extends Foo' is distinct from the
* <em>declaration</em> of type Foo.)
*
* If this Class represents a class type whose declaration does not explicitly
* indicate an annotated superclass, the return value is null.
*
* If this Class represents either the Object class, an interface type, an
* array type, a primitive type, or void, the return value is null.
*
* @since 1.8
*/
public AnnotatedType getAnnotatedSuperclass() {
return TypeAnnotationParser.buildAnnotatedSuperclass(getRawTypeAnnotations(), getConstantPool(), this);
}
/**
* Returns an array of AnnotatedType objects that represent the use of types to
* specify superinterfaces of the entity represented by this Class. (The <em>use</em>
* of type Foo to specify a superinterface in '... implements Foo' is
* distinct from the <em>declaration</em> of type Foo.)
*
* If this Class represents a class, the return value is an array
* containing objects representing the uses of interface types to specify
* interfaces implemented by the class. The order of the objects in the
* array corresponds to the order of the interface types used in the
* 'implements' clause of the declaration of this Class.
*
* If this Class represents an interface, the return value is an array
* containing objects representing the uses of interface types to specify
* interfaces directly extended by the interface. The order of the objects in
* the array corresponds to the order of the interface types used in the
* 'extends' clause of the declaration of this Class.
*
* If this Class represents a class or interface whose declaration does not
* explicitly indicate any annotated superinterfaces, the return value is an
* array of length 0.
*
* If this Class represents either the Object class, an array type, a
* primitive type, or void, the return value is an array of length 0.
*
* @since 1.8
*/
public AnnotatedType[] getAnnotatedInterfaces() {
return TypeAnnotationParser.buildAnnotatedInterfaces(getRawTypeAnnotations(), getConstantPool(), this);
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -289,7 +289,7 @@ public final class Double extends Number implements Comparable<Double> {
return Double.toString(d); return Double.toString(d);
else { else {
// Initialized to maximum size of output. // Initialized to maximum size of output.
StringBuffer answer = new StringBuffer(24); StringBuilder answer = new StringBuilder(24);
if (Math.copySign(1.0, d) == -1.0) // value is negative, if (Math.copySign(1.0, d) == -1.0) // value is negative,
answer.append("-"); // so append sign info answer.append("-"); // so append sign info
@ -300,8 +300,7 @@ public final class Double extends Number implements Comparable<Double> {
if(d == 0.0) { if(d == 0.0) {
answer.append("0.0p0"); answer.append("0.0p0");
} } else {
else {
boolean subnormal = (d < DoubleConsts.MIN_NORMAL); boolean subnormal = (d < DoubleConsts.MIN_NORMAL);
// Isolate significand bits and OR in a high-order bit // Isolate significand bits and OR in a high-order bit
@ -324,13 +323,14 @@ public final class Double extends Number implements Comparable<Double> {
"0": "0":
signif.replaceFirst("0{1,12}$", "")); signif.replaceFirst("0{1,12}$", ""));
answer.append('p');
// If the value is subnormal, use the E_min exponent // If the value is subnormal, use the E_min exponent
// value for double; otherwise, extract and report d's // value for double; otherwise, extract and report d's
// exponent (the representation of a subnormal uses // exponent (the representation of a subnormal uses
// E_min -1). // E_min -1).
answer.append("p" + (subnormal ? answer.append(subnormal ?
DoubleConsts.MIN_EXPONENT: DoubleConsts.MIN_EXPONENT:
Math.getExponent(d) )); Math.getExponent(d));
} }
return answer.toString(); return answer.toString();
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -385,15 +385,6 @@ public class Package implements java.lang.reflect.AnnotatedElement {
return getPackageInfo().getAnnotation(annotationClass); return getPackageInfo().getAnnotation(annotationClass);
} }
/**
* @throws NullPointerException {@inheritDoc}
* @since 1.5
*/
public boolean isAnnotationPresent(
Class<? extends Annotation> annotationClass) {
return getPackageInfo().isAnnotationPresent(annotationClass);
}
/** /**
* @throws NullPointerException {@inheritDoc} * @throws NullPointerException {@inheritDoc}
* @since 1.8 * @since 1.8

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,7 +25,7 @@
package java.lang; package java.lang;
import java.io.*; import java.io.*;
import java.lang.annotation.Annotation; import java.lang.reflect.Executable;
import java.util.Properties; import java.util.Properties;
import java.util.PropertyPermission; import java.util.PropertyPermission;
import java.util.StringTokenizer; import java.util.StringTokenizer;
@ -1196,8 +1196,11 @@ public final class System {
public AnnotationType getAnnotationType(Class<?> klass) { public AnnotationType getAnnotationType(Class<?> klass) {
return klass.getAnnotationType(); return klass.getAnnotationType();
} }
public <A extends Annotation> A getDirectDeclaredAnnotation(Class<?> klass, Class<A> anno) { public byte[] getRawClassTypeAnnotations(Class<?> klass) {
return klass.getDirectDeclaredAnnotation(anno); return klass.getRawTypeAnnotations();
}
public byte[] getRawExecutableTypeAnnotations(Executable executable) {
return Class.getExecutableTypeAnnotationBytes(executable);
} }
public <E extends Enum<E>> public <E extends Enum<E>>
E[] getEnumConstantsShared(Class<E> klass) { E[] getEnumConstantsShared(Class<E> klass) {

View File

@ -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();
}

View File

@ -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();
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -27,10 +27,9 @@ package java.lang.annotation;
import java.util.Objects; import java.util.Objects;
/** /**
* Thrown to indicate that an annotation type whose declaration is * Thrown to indicate that an annotation type expected to act as a
* (meta-)annotated with a {@link ContainerFor} annotation is not, in * container for another annotation type by virture of an @Repeatable
* fact, the <em>containing annotation type of the type named by {@link * annotation, does not act as a container.
* ContainerFor}</em>.
* *
* @see java.lang.reflect.AnnotatedElement * @see java.lang.reflect.AnnotatedElement
* @since 1.8 * @since 1.8

View File

@ -180,14 +180,6 @@ public class AccessibleObject implements AnnotatedElement {
throw new AssertionError("All subclasses should override this method"); throw new AssertionError("All subclasses should override this method");
} }
/**
* @throws NullPointerException {@inheritDoc}
* @since 1.5
*/
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
return getAnnotation(annotationClass) != null;
}
/** /**
* @throws NullPointerException {@inheritDoc} * @throws NullPointerException {@inheritDoc}
* @since 1.8 * @since 1.8

View File

@ -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();
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -35,6 +35,24 @@ import java.lang.annotation.Annotation;
* arrays returned by accessors for array-valued enum members; it will * arrays returned by accessors for array-valued enum members; it will
* have no affect on the arrays returned to other callers. * have no affect on the arrays returned to other callers.
* *
* <p>An annotation A is <em>directly present</em> on an element E if the
* RuntimeVisibleAnnotations or RuntimeVisibleParameterAnnotations attribute
* associated with E either:
* <ul>
* <li>contains A; or
* <li>for invocations of get[Declared]Annotations(Class<T>),
* contains A or exactly one annotation C whose type is the containing
* annotation type of A's type (JLS 9.6) and whose value element contains A
* </ul>
*
* <p>An annotation A is <em>present</em> on an element E if either:
* <ul>
* <li>A is <em>directly present</em> on E; or
* <li>There are no annotations of A's type which are <em>directly present</em>
* on E, and E is a class, and A's type is inheritable (JLS 9.6.3.3), and A is
* present on the superclass of E
* </ul>
*
* <p>If an annotation returned by a method in this interface contains * <p>If an annotation returned by a method in this interface contains
* (directly or indirectly) a {@link Class}-valued member referring to * (directly or indirectly) a {@link Class}-valued member referring to
* a class that is not accessible in this VM, attempting to read the class * a class that is not accessible in this VM, attempting to read the class
@ -50,7 +68,7 @@ import java.lang.annotation.Annotation;
* containing annotation type of T will result in an * containing annotation type of T will result in an
* InvalidContainerAnnotationError. * InvalidContainerAnnotationError.
* *
* <p>Finally, Attempting to read a member whose definition has evolved * <p>Finally, attempting to read a member whose definition has evolved
* incompatibly will result in a {@link * incompatibly will result in a {@link
* java.lang.annotation.AnnotationTypeMismatchException} or an * java.lang.annotation.AnnotationTypeMismatchException} or an
* {@link java.lang.annotation.IncompleteAnnotationException}. * {@link java.lang.annotation.IncompleteAnnotationException}.
@ -70,6 +88,12 @@ public interface AnnotatedElement {
* is present on this element, else false. This method * is present on this element, else false. This method
* is designed primarily for convenient access to marker annotations. * is designed primarily for convenient access to marker annotations.
* *
* <p>The truth value returned by this method is equivalent to:
* {@code getAnnotation(annotationClass) != null}
*
* <p>The body of the default method is specified to be the code
* above.
*
* @param annotationClass the Class object corresponding to the * @param annotationClass the Class object corresponding to the
* annotation type * annotation type
* @return true if an annotation for the specified annotation * @return true if an annotation for the specified annotation
@ -77,7 +101,9 @@ public interface AnnotatedElement {
* @throws NullPointerException if the given annotation class is null * @throws NullPointerException if the given annotation class is null
* @since 1.5 * @since 1.5
*/ */
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass); default boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
return getAnnotation(annotationClass) != null;
}
/** /**
* Returns this element's annotation for the specified type if * Returns this element's annotation for the specified type if
@ -110,12 +136,15 @@ public interface AnnotatedElement {
<T extends Annotation> T[] getAnnotations(Class<T> annotationClass); <T extends Annotation> T[] getAnnotations(Class<T> annotationClass);
/** /**
* Returns all annotations present on this element. (Returns an array * Returns annotations that are <em>present</em> on this element.
* of length zero if this element has no annotations.) The caller of
* this method is free to modify the returned array; it will have no
* effect on the arrays returned to other callers.
* *
* @return all annotations present on this element * If there are no annotations <em>present</em> on this element, the return
* value is an array of length 0.
*
* The caller of this method is free to modify the returned array; it will
* have no effect on the arrays returned to other callers.
*
* @return annotations present on this element
* @since 1.5 * @since 1.5
*/ */
Annotation[] getAnnotations(); Annotation[] getAnnotations();
@ -157,14 +186,16 @@ public interface AnnotatedElement {
<T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass); <T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass);
/** /**
* Returns all annotations that are directly present on this * Returns annotations that are <em>directly present</em> on this element.
* element. This method ignores inherited annotations. (Returns * This method ignores inherited annotations.
* an array of length zero if no annotations are directly present
* on this element.) The caller of this method is free to modify
* the returned array; it will have no effect on the arrays
* returned to other callers.
* *
* @return All annotations directly present on this element * If there are no annotations <em>directly present</em> on this element,
* the return value is an array of length 0.
*
* The caller of this method is free to modify the returned array; it will
* have no effect on the arrays returned to other callers.
*
* @return annotations directly present on this element
* @since 1.5 * @since 1.5
*/ */
Annotation[] getDeclaredAnnotations(); Annotation[] getDeclaredAnnotations();

View File

@ -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();
}

View 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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -154,6 +154,10 @@ public final class Constructor<T> extends Executable {
byte[] getAnnotationBytes() { byte[] getAnnotationBytes() {
return annotations; return annotations;
} }
@Override
byte[] getTypeAnnotationBytes() {
return typeAnnotations;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
@ -523,4 +527,12 @@ public final class Constructor<T> extends Executable {
} }
} }
} }
/**
* {@inheritDoc}
* @since 1.8
*/
public AnnotatedType getAnnotatedReturnType() {
return getAnnotatedReturnType0(getDeclaringClass());
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,11 +26,12 @@
package java.lang.reflect; package java.lang.reflect;
import java.lang.annotation.*; import java.lang.annotation.*;
import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import sun.reflect.annotation.AnnotationParser; import sun.reflect.annotation.AnnotationParser;
import sun.reflect.annotation.AnnotationSupport; import sun.reflect.annotation.AnnotationSupport;
import sun.reflect.annotation.TypeAnnotationParser;
import sun.reflect.annotation.TypeAnnotation;
import sun.reflect.generics.repository.ConstructorRepository; import sun.reflect.generics.repository.ConstructorRepository;
/** /**
@ -50,6 +51,7 @@ public abstract class Executable extends AccessibleObject
* Accessor method to allow code sharing * Accessor method to allow code sharing
*/ */
abstract byte[] getAnnotationBytes(); abstract byte[] getAnnotationBytes();
abstract byte[] getTypeAnnotationBytes();
/** /**
* Does the Executable have generic information. * Does the Executable have generic information.
@ -435,8 +437,7 @@ public abstract class Executable extends AccessibleObject
*/ */
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass); Objects.requireNonNull(annotationClass);
return annotationClass.cast(declaredAnnotations().get(annotationClass));
return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass);
} }
/** /**
@ -454,7 +455,7 @@ public abstract class Executable extends AccessibleObject
* {@inheritDoc} * {@inheritDoc}
*/ */
public Annotation[] getDeclaredAnnotations() { public Annotation[] getDeclaredAnnotations() {
return AnnotationSupport.unpackToArray(declaredAnnotations()); return AnnotationParser.toArray(declaredAnnotations());
} }
private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations; private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
@ -470,4 +471,86 @@ public abstract class Executable extends AccessibleObject
return declaredAnnotations; return declaredAnnotations;
} }
/* Helper for subclasses of Executable.
*
* Returns an AnnotatedType object that represents the use of a type to
* specify the return type of the method/constructor represented by this
* Executable.
*
* @since 1.8
*/
AnnotatedType getAnnotatedReturnType0(Type returnType) {
return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes(),
sun.misc.SharedSecrets.getJavaLangAccess().
getConstantPool(getDeclaringClass()),
this,
getDeclaringClass(),
returnType,
TypeAnnotation.TypeAnnotationTarget.METHOD_RETURN_TYPE);
}
/**
* Returns an AnnotatedType object that represents the use of a type to
* specify the receiver type of the method/constructor represented by this
* Executable. The receiver type of a method/constructor is available only
* if the method/constructor declares a formal parameter called 'this'.
*
* Returns null if this Executable represents a constructor or instance
* method that either declares no formal parameter called 'this', or
* declares a formal parameter called 'this' with no annotations on its
* type.
*
* Returns null if this Executable represents a static method.
*
* @since 1.8
*/
public AnnotatedType getAnnotatedReceiverType() {
return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes(),
sun.misc.SharedSecrets.getJavaLangAccess().
getConstantPool(getDeclaringClass()),
this,
getDeclaringClass(),
getDeclaringClass(),
TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER_TYPE);
}
/**
* Returns an array of AnnotatedType objects that represent the use of
* types to specify formal parameter types of the method/constructor
* represented by this Executable. The order of the objects in the array
* corresponds to the order of the formal parameter types in the
* declaration of the method/constructor.
*
* Returns an array of length 0 if the method/constructor declares no
* parameters.
*
* @since 1.8
*/
public AnnotatedType[] getAnnotatedParameterTypes() {
throw new UnsupportedOperationException("Not yet");
}
/**
* Returns an array of AnnotatedType objects that represent the use of
* types to specify the declared exceptions of the method/constructor
* represented by this Executable. The order of the objects in the array
* corresponds to the order of the exception types in the declaration of
* the method/constructor.
*
* Returns an array of length 0 if the method/constructor declares no
* exceptions.
*
* @since 1.8
*/
public AnnotatedType[] getAnnotatedExceptionTypes() {
return TypeAnnotationParser.buildAnnotatedTypes(getTypeAnnotationBytes(),
sun.misc.SharedSecrets.getJavaLangAccess().
getConstantPool(getDeclaringClass()),
this,
getDeclaringClass(),
getGenericExceptionTypes(),
TypeAnnotation.TypeAnnotationTarget.THROWS);
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -36,7 +36,8 @@ import java.util.Map;
import java.util.Objects; import java.util.Objects;
import sun.reflect.annotation.AnnotationParser; import sun.reflect.annotation.AnnotationParser;
import sun.reflect.annotation.AnnotationSupport; import sun.reflect.annotation.AnnotationSupport;
import sun.reflect.annotation.TypeAnnotation;
import sun.reflect.annotation.TypeAnnotationParser;
/** /**
* A {@code Field} provides information about, and dynamic access to, a * A {@code Field} provides information about, and dynamic access to, a
@ -1020,8 +1021,7 @@ class Field extends AccessibleObject implements Member {
*/ */
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass); Objects.requireNonNull(annotationClass);
return annotationClass.cast(declaredAnnotations().get(annotationClass));
return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass);
} }
/** /**
@ -1039,7 +1039,7 @@ class Field extends AccessibleObject implements Member {
* {@inheritDoc} * {@inheritDoc}
*/ */
public Annotation[] getDeclaredAnnotations() { public Annotation[] getDeclaredAnnotations() {
return AnnotationSupport.unpackToArray(declaredAnnotations()); return AnnotationParser.toArray(declaredAnnotations());
} }
private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations; private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
@ -1053,4 +1053,20 @@ class Field extends AccessibleObject implements Member {
} }
return declaredAnnotations; return declaredAnnotations;
} }
/**
* Returns an AnnotatedType object that represents the use of a type to specify
* the declared type of the field represented by this Field.
*
* @since 1.8
*/
public AnnotatedType getAnnotatedType() {
return TypeAnnotationParser.buildAnnotatedType(typeAnnotations,
sun.misc.SharedSecrets.getJavaLangAccess().
getConstantPool(getDeclaringClass()),
this,
getDeclaringClass(),
getGenericType(),
TypeAnnotation.TypeAnnotationTarget.FIELD_TYPE);
}
} }

View File

@ -165,6 +165,10 @@ public final class Method extends Executable {
byte[] getAnnotationBytes() { byte[] getAnnotationBytes() {
return annotations; return annotations;
} }
@Override
byte[] getTypeAnnotationBytes() {
return typeAnnotations;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
@ -621,6 +625,14 @@ public final class Method extends Executable {
return sharedGetParameterAnnotations(parameterTypes, parameterAnnotations); return sharedGetParameterAnnotations(parameterTypes, parameterAnnotations);
} }
/**
* {@inheritDoc}
* @since 1.8
*/
public AnnotatedType getAnnotatedReturnType() {
return getAnnotatedReturnType0(getGenericReturnType());
}
@Override @Override
void handleParameterNumberMismatch(int resultLength, int numParameters) { void handleParameterNumberMismatch(int resultLength, int numParameters) {
throw new AnnotationFormatError("Parameter annotations don't match number of parameters"); throw new AnnotationFormatError("Parameter annotations don't match number of parameters");

View File

@ -233,8 +233,7 @@ public final class Parameter implements AnnotatedElement {
*/ */
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass); Objects.requireNonNull(annotationClass);
return annotationClass.cast(declaredAnnotations().get(annotationClass));
return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass);
} }
/** /**
@ -281,14 +280,6 @@ public final class Parameter implements AnnotatedElement {
return getDeclaredAnnotations(); return getDeclaredAnnotations();
} }
/**
* @throws NullPointerException {@inheritDoc}
*/
public boolean isAnnotationPresent(
Class<? extends Annotation> annotationClass) {
return getAnnotation(annotationClass) != null;
}
private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations; private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
private synchronized Map<Class<? extends Annotation>, Annotation> declaredAnnotations() { private synchronized Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -128,6 +128,10 @@ class ReflectAccess implements sun.reflect.LangReflectAccess {
return c.getRawParameterAnnotations(); return c.getRawParameterAnnotations();
} }
public byte[] getExecutableTypeAnnotationBytes(Executable ex) {
return ex.getTypeAnnotationBytes();
}
// //
// Copying routines, needed to quickly fabricate new Field, // Copying routines, needed to quickly fabricate new Field,
// Method, and Constructor objects from templates // Method, and Constructor objects from templates

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -86,4 +86,16 @@ public interface TypeVariable<D extends GenericDeclaration> extends Type, Annota
* @return the name of this type variable, as it appears in the source code * @return the name of this type variable, as it appears in the source code
*/ */
String getName(); String getName();
/**
* Returns an array of AnnotatedType objects that represent the use of
* types to denote the upper bounds of the type parameter represented by
* this TypeVariable. The order of the objects in the array corresponds to
* the order of the bounds in the declaration of the type parameter.
*
* Returns an array of length 0 if the type parameter declares no bounds.
*
* @since 1.8
*/
AnnotatedType[] getAnnotatedBounds();
} }

View File

@ -3537,13 +3537,25 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
else else
return expandBigIntegerTenPowers(n); return expandBigIntegerTenPowers(n);
} }
if (n < 1024*524288) {
// BigInteger.pow is slow, so make 10**n by constructing a // BigInteger.pow is slow, so make 10**n by constructing a
// BigInteger from a character string (still not very fast) // BigInteger from a character string (still not very fast)
// which occupies no more than 1GB (!) of memory.
char tenpow[] = new char[n + 1]; char tenpow[] = new char[n + 1];
tenpow[0] = '1'; tenpow[0] = '1';
for (int i = 1; i <= n; i++) for (int i = 1; i <= n; i++) {
tenpow[i] = '0'; tenpow[i] = '0';
return new BigInteger(tenpow,1, tenpow.length); }
return new BigInteger(tenpow, 1, tenpow.length);
}
if ((n & 0x1) == 0x1) {
return BigInteger.TEN.multiply(bigTenToThe(n - 1));
} else {
BigInteger tmp = bigTenToThe(n/2);
return tmp.multiply(tmp);
}
} }
/** /**

View File

@ -64,7 +64,8 @@ import java.nio.charset.StandardCharsets;
* RFC 2045 for encoding and decoding operation. The encoded output * RFC 2045 for encoding and decoding operation. The encoded output
* must be represented in lines of no more than 76 characters each * must be represented in lines of no more than 76 characters each
* and uses a carriage return {@code '\r'} followed immediately by * and uses a carriage return {@code '\r'} followed immediately by
* a linefeed {@code '\n'} as the line separator. All line separators * a linefeed {@code '\n'} as the line separator. No line separator
* is added to the end of the encoded output. All line separators
* or other characters not found in the base64 alphabet table are * or other characters not found in the base64 alphabet table are
* ignored in decoding operation.</p></li> * ignored in decoding operation.</p></li>
* </ul> * </ul>
@ -413,6 +414,7 @@ public class Base64 {
* specified Base64 encoded format * specified Base64 encoded format
*/ */
public OutputStream wrap(OutputStream os) { public OutputStream wrap(OutputStream os) {
Objects.requireNonNull(os);
return new EncOutputStream(os, isURL ? toBase64URL : toBase64, return new EncOutputStream(os, isURL ? toBase64URL : toBase64,
newline, linemax); newline, linemax);
} }
@ -613,6 +615,13 @@ public class Base64 {
* This class implements a decoder for decoding byte data using the * This class implements a decoder for decoding byte data using the
* Base64 encoding scheme as specified in RFC 4648 and RFC 2045. * Base64 encoding scheme as specified in RFC 4648 and RFC 2045.
* *
* <p> The Base64 padding character {@code '='} is accepted and
* interpreted as the end of the encoded byte data, but is not
* required. So if the final unit of the encoded byte data only has
* two or three Base64 characters (without the corresponding padding
* character(s) padded), they are decoded as if followed by padding
* character(s).
*
* <p> Instances of {@link Decoder} class are safe for use by * <p> Instances of {@link Decoder} class are safe for use by
* multiple concurrent threads. * multiple concurrent threads.
* *
@ -695,7 +704,7 @@ public class Base64 {
* using the {@link Base64} encoding scheme. * using the {@link Base64} encoding scheme.
* *
* <p> An invocation of this method has exactly the same effect as invoking * <p> An invocation of this method has exactly the same effect as invoking
* {@code return decode(src.getBytes(StandardCharsets.ISO_8859_1))} * {@code decode(src.getBytes(StandardCharsets.ISO_8859_1))}
* *
* @param src * @param src
* the string to decode * the string to decode
@ -856,6 +865,9 @@ public class Base64 {
/** /**
* Returns an input stream for decoding {@link Base64} encoded byte stream. * Returns an input stream for decoding {@link Base64} encoded byte stream.
* *
* <p> The {@code read} methods of the returned {@code InputStream} will
* throw {@code IOException} when reading bytes that cannot be decoded.
*
* <p> Closing the returned input stream will close the underlying * <p> Closing the returned input stream will close the underlying
* input stream. * input stream.
* *
@ -866,6 +878,7 @@ public class Base64 {
* byte stream * byte stream
*/ */
public InputStream wrap(InputStream is) { public InputStream wrap(InputStream is) {
Objects.requireNonNull(is);
return new DecInputStream(is, isURL ? fromBase64URL : fromBase64, isMIME); return new DecInputStream(is, isURL ? fromBase64URL : fromBase64, isMIME);
} }
@ -881,13 +894,16 @@ public class Base64 {
int dl = dst.arrayOffset() + dst.limit(); int dl = dst.arrayOffset() + dst.limit();
int dp0 = dp; int dp0 = dp;
int mark = sp; int mark = sp;
boolean padding = false;
try { try {
while (sp < sl) { while (sp < sl) {
int b = sa[sp++] & 0xff; int b = sa[sp++] & 0xff;
if ((b = base64[b]) < 0) { if ((b = base64[b]) < 0) {
if (b == -2) { // padding byte if (b == -2) { // padding byte
padding = true; if (shiftto == 6 && (sp == sl || sa[sp++] != '=') ||
shiftto == 18) {
throw new IllegalArgumentException(
"Input byte array has wrong 4-byte ending unit");
}
break; break;
} }
if (isMIME) // skip if for rfc2045 if (isMIME) // skip if for rfc2045
@ -913,24 +929,23 @@ public class Base64 {
if (shiftto == 6) { if (shiftto == 6) {
if (dl - dp < 1) if (dl - dp < 1)
return dp - dp0; return dp - dp0;
if (padding && (sp + 1 != sl || sa[sp++] != '='))
throw new IllegalArgumentException(
"Input buffer has wrong 4-byte ending unit");
da[dp++] = (byte)(bits >> 16); da[dp++] = (byte)(bits >> 16);
mark = sp;
} else if (shiftto == 0) { } else if (shiftto == 0) {
if (dl - dp < 2) if (dl - dp < 2)
return dp - dp0; return dp - dp0;
if (padding && sp != sl)
throw new IllegalArgumentException(
"Input buffer has wrong 4-byte ending unit");
da[dp++] = (byte)(bits >> 16); da[dp++] = (byte)(bits >> 16);
da[dp++] = (byte)(bits >> 8); da[dp++] = (byte)(bits >> 8);
mark = sp; } else if (shiftto == 12) {
} else if (padding || shiftto != 18) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Last unit does not have enough valid bits"); "Last unit does not have enough valid bits");
} }
while (sp < sl) {
if (isMIME && base64[sa[sp++]] < 0)
continue;
throw new IllegalArgumentException(
"Input byte array has incorrect ending byte at " + sp);
}
mark = sp;
return dp - dp0; return dp - dp0;
} finally { } finally {
src.position(mark); src.position(mark);
@ -948,14 +963,16 @@ public class Base64 {
int dl = dst.limit(); int dl = dst.limit();
int dp0 = dp; int dp0 = dp;
int mark = sp; int mark = sp;
boolean padding = false;
try { try {
while (sp < sl) { while (sp < sl) {
int b = src.get(sp++) & 0xff; int b = src.get(sp++) & 0xff;
if ((b = base64[b]) < 0) { if ((b = base64[b]) < 0) {
if (b == -2) { // padding byte if (b == -2) { // padding byte
padding = true; if (shiftto == 6 && (sp == sl || src.get(sp++) != '=') ||
shiftto == 18) {
throw new IllegalArgumentException(
"Input byte array has wrong 4-byte ending unit");
}
break; break;
} }
if (isMIME) // skip if for rfc2045 if (isMIME) // skip if for rfc2045
@ -981,24 +998,23 @@ public class Base64 {
if (shiftto == 6) { if (shiftto == 6) {
if (dl - dp < 1) if (dl - dp < 1)
return dp - dp0; return dp - dp0;
if (padding && (sp + 1 != sl || src.get(sp++) != '='))
throw new IllegalArgumentException(
"Input buffer has wrong 4-byte ending unit");
dst.put(dp++, (byte)(bits >> 16)); dst.put(dp++, (byte)(bits >> 16));
mark = sp;
} else if (shiftto == 0) { } else if (shiftto == 0) {
if (dl - dp < 2) if (dl - dp < 2)
return dp - dp0; return dp - dp0;
if (padding && sp != sl)
throw new IllegalArgumentException(
"Input buffer has wrong 4-byte ending unit");
dst.put(dp++, (byte)(bits >> 16)); dst.put(dp++, (byte)(bits >> 16));
dst.put(dp++, (byte)(bits >> 8)); dst.put(dp++, (byte)(bits >> 8));
mark = sp; } else if (shiftto == 12) {
} else if (padding || shiftto != 18) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Last unit does not have enough valid bits"); "Last unit does not have enough valid bits");
} }
while (sp < sl) {
if (isMIME && base64[src.get(sp++)] < 0)
continue;
throw new IllegalArgumentException(
"Input byte array has incorrect ending byte at " + sp);
}
mark = sp;
return dp - dp0; return dp - dp0;
} finally { } finally {
src.position(mark); src.position(mark);
@ -1012,9 +1028,12 @@ public class Base64 {
int len = sl - sp; int len = sl - sp;
if (len == 0) if (len == 0)
return 0; return 0;
if (len < 2) if (len < 2) {
if (isMIME && base64[0] == -1)
return 0;
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Input byte[] should at least have 2 bytes for base64 bytes"); "Input byte[] should at least have 2 bytes for base64 bytes");
}
if (src[sl - 1] == '=') { if (src[sl - 1] == '=') {
paddings++; paddings++;
if (src[sl - 2] == '=') if (src[sl - 2] == '=')
@ -1043,12 +1062,20 @@ public class Base64 {
int dp = 0; int dp = 0;
int bits = 0; int bits = 0;
int shiftto = 18; // pos of first byte of 4-byte atom int shiftto = 18; // pos of first byte of 4-byte atom
boolean padding = false;
while (sp < sl) { while (sp < sl) {
int b = src[sp++] & 0xff; int b = src[sp++] & 0xff;
if ((b = base64[b]) < 0) { if ((b = base64[b]) < 0) {
if (b == -2) { // padding byte if (b == -2) { // padding byte '='
padding = true; // xx= shiftto==6&&sp==sl missing last =
// xx=y shiftto==6 last is not =
// = shiftto==18 unnecessary padding
// x= shiftto==12 be taken care later
// together with single x, invalid anyway
if (shiftto == 6 && (sp == sl || src[sp++] != '=') ||
shiftto == 18) {
throw new IllegalArgumentException(
"Input byte array has wrong 4-byte ending unit");
}
break; break;
} }
if (isMIME) // skip if for rfc2045 if (isMIME) // skip if for rfc2045
@ -1068,22 +1095,23 @@ public class Base64 {
bits = 0; bits = 0;
} }
} }
// reach end of byte arry or hit padding '=' characters. // reached end of byte array or hit padding '=' characters.
// if '=' presents, they must be the last one or two. if (shiftto == 6) {
if (shiftto == 6) { // xx==
if (padding && (sp + 1 != sl || src[sp] != '='))
throw new IllegalArgumentException(
"Input byte array has wrong 4-byte ending unit");
dst[dp++] = (byte)(bits >> 16); dst[dp++] = (byte)(bits >> 16);
} else if (shiftto == 0) { // xxx= } else if (shiftto == 0) {
if (padding && sp != sl)
throw new IllegalArgumentException(
"Input byte array has wrong 4-byte ending unit");
dst[dp++] = (byte)(bits >> 16); dst[dp++] = (byte)(bits >> 16);
dst[dp++] = (byte)(bits >> 8); dst[dp++] = (byte)(bits >> 8);
} else if (padding || shiftto != 18) { } else if (shiftto == 12) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"last unit does not have enough bytes"); "Last unit does not have enough valid bits");
}
// anything left is invalid, if is not MIME.
// if MIME, ignore all non-base64 character
while (sp < sl) {
if (isMIME && base64[src[sp++]] < 0)
continue;
throw new IllegalArgumentException(
"Input byte array has incorrect ending byte at " + sp);
} }
return dp; return dp;
} }
@ -1247,8 +1275,22 @@ public class Base64 {
int v = is.read(); int v = is.read();
if (v == -1) { if (v == -1) {
eof = true; eof = true;
if (nextin != 18) if (nextin != 18) {
throw new IOException("Base64 stream has un-decoded dangling byte(s)."); if (nextin == 12)
throw new IOException("Base64 stream has one un-decoded dangling byte.");
// treat ending xx/xxx without padding character legal.
// same logic as v == 'v' below
b[off++] = (byte)(bits >> (16));
len--;
if (nextin == 0) { // only one padding byte
if (len == 0) { // no enough output space
bits >>= 8; // shift to lowest byte
nextout = 0;
} else {
b[off++] = (byte) (bits >> 8);
}
}
}
if (off == oldOff) if (off == oldOff)
return -1; return -1;
else else

View File

@ -351,7 +351,9 @@ import sun.misc.FormattedFloatingDecimal;
* <tr><td valign="top">{@code 'a'}, {@code 'A'} * <tr><td valign="top">{@code 'a'}, {@code 'A'}
* <td valign="top"> floating point * <td valign="top"> floating point
* <td> The result is formatted as a hexadecimal floating-point number with * <td> The result is formatted as a hexadecimal floating-point number with
* a significand and an exponent * a significand and an exponent. This conversion is <b>not</b> supported
* for the {@code BigDecimal} type despite the latter's being in the
* <i>floating point</i> argument category.
* *
* <tr><td valign="top">{@code 't'}, {@code 'T'} * <tr><td valign="top">{@code 't'}, {@code 'T'}
* <td valign="top"> date/time * <td valign="top"> date/time

View File

@ -22,7 +22,6 @@
* or visit www.oracle.com if you need additional information or have any * or visit www.oracle.com if you need additional information or have any
* questions. * questions.
*/ */
package sun.management; package sun.management;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
@ -31,34 +30,36 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.lang.management.ManagementFactory;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.management.ManagementFactory; import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.MissingResourceException; import java.util.MissingResourceException;
import java.util.Properties; import java.util.Properties;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXServiceURL;
import static sun.management.AgentConfigurationError.*; import static sun.management.AgentConfigurationError.*;
import sun.management.jmxremote.ConnectorBootstrap; import sun.management.jmxremote.ConnectorBootstrap;
import sun.management.jdp.JdpController;
import sun.management.jdp.JdpException;
import sun.misc.VMSupport; import sun.misc.VMSupport;
/** /**
* This Agent is started by the VM when -Dcom.sun.management.snmp * This Agent is started by the VM when -Dcom.sun.management.snmp or
* or -Dcom.sun.management.jmxremote is set. This class will be * -Dcom.sun.management.jmxremote is set. This class will be loaded by the
* loaded by the system class loader. Also jmx framework could * system class loader. Also jmx framework could be started by jcmd
* be started by jcmd
*/ */
public class Agent { public class Agent {
// management properties // management properties
private static Properties mgmtProps; private static Properties mgmtProps;
private static ResourceBundle messageRB; private static ResourceBundle messageRB;
private static final String CONFIG_FILE = private static final String CONFIG_FILE =
"com.sun.management.config.file"; "com.sun.management.config.file";
private static final String SNMP_PORT = private static final String SNMP_PORT =
@ -67,21 +68,25 @@ public class Agent {
"com.sun.management.jmxremote"; "com.sun.management.jmxremote";
private static final String JMXREMOTE_PORT = private static final String JMXREMOTE_PORT =
"com.sun.management.jmxremote.port"; "com.sun.management.jmxremote.port";
private static final String RMI_PORT =
"com.sun.management.jmxremote.rmi.port";
private static final String ENABLE_THREAD_CONTENTION_MONITORING = private static final String ENABLE_THREAD_CONTENTION_MONITORING =
"com.sun.management.enableThreadContentionMonitoring"; "com.sun.management.enableThreadContentionMonitoring";
private static final String LOCAL_CONNECTOR_ADDRESS_PROP = private static final String LOCAL_CONNECTOR_ADDRESS_PROP =
"com.sun.management.jmxremote.localConnectorAddress"; "com.sun.management.jmxremote.localConnectorAddress";
private static final String SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME = private static final String SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME =
"sun.management.snmp.AdaptorBootstrap"; "sun.management.snmp.AdaptorBootstrap";
private static final String JDP_DEFAULT_ADDRESS = "239.255.255.225";
private static final int JDP_DEFAULT_PORT = 7095;
// The only active agent allowed // The only active agent allowed
private static JMXConnectorServer jmxServer = null; private static JMXConnectorServer jmxServer = null;
// Parse string com.sun.management.prop=xxx,com.sun.management.prop=yyyy // Parse string com.sun.management.prop=xxx,com.sun.management.prop=yyyy
// and return property set if args is null or empty // and return property set if args is null or empty
// return empty property set // return empty property set
private static Properties parseString(String args){ private static Properties parseString(String args) {
Properties argProps = new Properties(); Properties argProps = new Properties();
if (args != null) { if (args != null) {
for (String option : args.split(",")) { for (String option : args.split(",")) {
@ -100,7 +105,6 @@ public class Agent {
return argProps; return argProps;
} }
// invoked by -javaagent or -Dcom.sun.management.agent.class // invoked by -javaagent or -Dcom.sun.management.agent.class
public static void premain(String args) throws Exception { public static void premain(String args) throws Exception {
agentmain(args); agentmain(args);
@ -126,7 +130,7 @@ public class Agent {
// jcmd ManagementAgent.start_local entry point // jcmd ManagementAgent.start_local entry point
// Also called due to command-line via startAgent() // Also called due to command-line via startAgent()
private static synchronized void startLocalManagementAgent(){ private static synchronized void startLocalManagementAgent() {
Properties agentProps = VMSupport.getAgentProperties(); Properties agentProps = VMSupport.getAgentProperties();
// start local connector if not started // start local connector if not started
@ -169,7 +173,7 @@ public class Agent {
// management properties can be overridden by system properties // management properties can be overridden by system properties
// which take precedence // which take precedence
Properties sysProps = System.getProperties(); Properties sysProps = System.getProperties();
synchronized(sysProps){ synchronized (sysProps) {
configProps.putAll(sysProps); configProps.putAll(sysProps);
} }
@ -201,10 +205,15 @@ public class Agent {
if (jmxremotePort != null) { if (jmxremotePort != null) {
jmxServer = ConnectorBootstrap. jmxServer = ConnectorBootstrap.
startRemoteConnectorServer(jmxremotePort, configProps); startRemoteConnectorServer(jmxremotePort, configProps);
startDiscoveryService(configProps);
} }
} }
private static synchronized void stopRemoteManagementAgent() throws Exception { private static synchronized void stopRemoteManagementAgent() throws Exception {
JdpController.stopDiscoveryService();
if (jmxServer != null) { if (jmxServer != null) {
ConnectorBootstrap.unexportRegistry(); ConnectorBootstrap.unexportRegistry();
@ -246,6 +255,7 @@ public class Agent {
if (jmxremotePort != null) { if (jmxremotePort != null) {
jmxServer = ConnectorBootstrap. jmxServer = ConnectorBootstrap.
startRemoteConnectorServer(jmxremotePort, props); startRemoteConnectorServer(jmxremotePort, props);
startDiscoveryService(props);
} }
startLocalManagementAgent(); startLocalManagementAgent();
} }
@ -257,6 +267,73 @@ public class Agent {
} }
} }
private static void startDiscoveryService(Properties props)
throws IOException {
// Start discovery service if requested
String discoveryPort = props.getProperty("com.sun.management.jdp.port");
String discoveryAddress = props.getProperty("com.sun.management.jdp.address");
String discoveryShouldStart = props.getProperty("com.sun.management.jmxremote.autodiscovery");
// Decide whether we should start autodicovery service.
// To start autodiscovery following conditions should be met:
// autodiscovery==true OR (autodicovery==null AND jdp.port != NULL)
boolean shouldStart = false;
if (discoveryShouldStart == null){
shouldStart = (discoveryPort != null);
}
else{
try{
shouldStart = Boolean.parseBoolean(discoveryShouldStart);
} catch (NumberFormatException e) {
throw new AgentConfigurationError("Couldn't parse autodiscovery argument");
}
}
if (shouldStart) {
// port and address are required arguments and have no default values
InetAddress address;
try {
address = (discoveryAddress == null) ?
InetAddress.getByName(JDP_DEFAULT_ADDRESS) : InetAddress.getByName(discoveryAddress);
} catch (UnknownHostException e) {
throw new AgentConfigurationError("Unable to broadcast to requested address", e);
}
int port = JDP_DEFAULT_PORT;
if (discoveryPort != null) {
try {
port = Integer.parseInt(discoveryPort);
} catch (NumberFormatException e) {
throw new AgentConfigurationError("Couldn't parse JDP port argument");
}
}
// Rebuilding service URL to broadcast it
String jmxremotePort = props.getProperty(JMXREMOTE_PORT);
String rmiPort = props.getProperty(RMI_PORT);
JMXServiceURL url = jmxServer.getAddress();
String hostname = url.getHost();
String jmxUrlStr = (rmiPort != null)
? String.format(
"service:jmx:rmi://%s:%s/jndi/rmi://%s:%s/jmxrmi",
hostname, rmiPort, hostname, jmxremotePort)
: String.format(
"service:jmx:rmi:///jndi/rmi://%s:%s/jmxrmi", hostname, jmxremotePort);
String instanceName = System.getProperty("com.sun.management.jdp.name");
try{
JdpController.startDiscoveryService(address, port, instanceName, jmxUrlStr);
}
catch(JdpException e){
throw new AgentConfigurationError("Couldn't start JDP service", e);
}
}
}
public static Properties loadManagementProperties() { public static Properties loadManagementProperties() {
Properties props = new Properties(); Properties props = new Properties();
@ -268,7 +345,7 @@ public class Agent {
// management properties can be overridden by system properties // management properties can be overridden by system properties
// which take precedence // which take precedence
Properties sysProps = System.getProperties(); Properties sysProps = System.getProperties();
synchronized(sysProps){ synchronized (sysProps) {
props.putAll(sysProps); props.putAll(sysProps);
} }
@ -282,8 +359,8 @@ public class Agent {
String jmxremote = System.getProperty(JMXREMOTE); String jmxremote = System.getProperty(JMXREMOTE);
String jmxremotePort = System.getProperty(JMXREMOTE_PORT); String jmxremotePort = System.getProperty(JMXREMOTE_PORT);
if (configFile == null && snmpPort == null && if (configFile == null && snmpPort == null
jmxremote == null && jmxremotePort == null) { && jmxremote == null && jmxremotePort == null) {
// return if out-of-the-management option is not specified // return if out-of-the-management option is not specified
return null; return null;
} }
@ -297,22 +374,23 @@ public class Agent {
// invoke the following through reflection: // invoke the following through reflection:
// AdaptorBootstrap.initialize(snmpPort, props); // AdaptorBootstrap.initialize(snmpPort, props);
final Class<?> adaptorClass = final Class<?> adaptorClass =
Class.forName(SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME,true,null); Class.forName(SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME, true, null);
final Method initializeMethod = final Method initializeMethod =
adaptorClass.getMethod("initialize", adaptorClass.getMethod("initialize",
String.class, Properties.class); String.class, Properties.class);
initializeMethod.invoke(null,snmpPort,props); initializeMethod.invoke(null, snmpPort, props);
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException x) { } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException x) {
// snmp runtime doesn't exist - initialization fails // snmp runtime doesn't exist - initialization fails
throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT,x); throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT, x);
} catch (InvocationTargetException x) { } catch (InvocationTargetException x) {
final Throwable cause = x.getCause(); final Throwable cause = x.getCause();
if (cause instanceof RuntimeException) if (cause instanceof RuntimeException) {
throw (RuntimeException) cause; throw (RuntimeException) cause;
else if (cause instanceof Error) } else if (cause instanceof Error) {
throw (Error) cause; throw (Error) cause;
}
// should not happen... // should not happen...
throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT,cause); throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT, cause);
} }
} }
@ -389,9 +467,9 @@ public class Agent {
// invoke the premain(String args) method // invoke the premain(String args) method
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(cname); Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(cname);
Method premain = clz.getMethod("premain", Method premain = clz.getMethod("premain",
new Class<?>[] { String.class }); new Class<?>[]{String.class});
premain.invoke(null, /* static */ premain.invoke(null, /* static */
new Object[] { args }); new Object[]{args});
} catch (ClassNotFoundException ex) { } catch (ClassNotFoundException ex) {
error(AGENT_CLASS_NOT_FOUND, "\"" + cname + "\""); error(AGENT_CLASS_NOT_FOUND, "\"" + cname + "\"");
} catch (NoSuchMethodException ex) { } catch (NoSuchMethodException ex) {
@ -425,7 +503,6 @@ public class Agent {
} }
} }
public static void error(String key, String message) { public static void error(String key, String message) {
String keyText = getText(key); String keyText = getText(key);
System.err.print(getText("agent.err.error") + ": " + keyText); System.err.print(getText("agent.err.error") + ": " + keyText);
@ -470,10 +547,9 @@ public class Agent {
} }
String format = messageRB.getString(key); String format = messageRB.getString(key);
if (format == null) { if (format == null) {
format = "missing resource key: key = \"" + key + "\", " + format = "missing resource key: key = \"" + key + "\", "
"arguments = \"{0}\", \"{1}\", \"{2}\""; + "arguments = \"{0}\", \"{1}\", \"{2}\"";
} }
return MessageFormat.format(format, (Object[]) args); return MessageFormat.format(format, (Object[]) args);
} }
} }

View 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();
}
}

View 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;
}
}
}

View 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);
}
}

View File

@ -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;
}
}

View 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());
}
}

View 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;
}

View 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;
}
}

View File

@ -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();
}
}

View 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;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,6 +26,7 @@
package sun.misc; package sun.misc;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.reflect.Executable;
import sun.reflect.ConstantPool; import sun.reflect.ConstantPool;
import sun.reflect.annotation.AnnotationType; import sun.reflect.annotation.AnnotationType;
import sun.nio.ch.Interruptible; import sun.nio.ch.Interruptible;
@ -46,6 +47,18 @@ public interface JavaLangAccess {
*/ */
AnnotationType getAnnotationType(Class<?> klass); AnnotationType getAnnotationType(Class<?> klass);
/**
* Get the array of bytes that is the class-file representation
* of this Class' type annotations.
*/
byte[] getRawClassTypeAnnotations(Class<?> klass);
/**
* Get the array of bytes that is the class-file representation
* of this Executable's type annotations.
*/
byte[] getRawExecutableTypeAnnotations(Executable executable);
/** /**
* Returns the elements of an enum class or null if the * Returns the elements of an enum class or null if the
* Class object does not represent an enum type; * Class object does not represent an enum type;
@ -84,9 +97,4 @@ public interface JavaLangAccess {
* Returns the ith StackTraceElement for the given throwable. * Returns the ith StackTraceElement for the given throwable.
*/ */
StackTraceElement getStackTraceElement(Throwable t, int i); StackTraceElement getStackTraceElement(Throwable t, int i);
/**
* Returns a directly present annotation.
*/
public <A extends Annotation> A getDirectDeclaredAnnotation(Class<?> klass, Class<A> anno);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -81,6 +81,9 @@ public interface LangReflectAccess {
public void setConstructorAccessor(Constructor<?> c, public void setConstructorAccessor(Constructor<?> c,
ConstructorAccessor accessor); ConstructorAccessor accessor);
/** Gets the byte[] that encodes TypeAnnotations on an Executable. */
public byte[] getExecutableTypeAnnotationBytes(Executable ex);
/** Gets the "slot" field from a Constructor (used for serialization) */ /** Gets the "slot" field from a Constructor (used for serialization) */
public int getConstructorSlot(Constructor<?> c); public int getConstructorSlot(Constructor<?> c);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,6 +26,7 @@
package sun.reflect; package sun.reflect;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Executable;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
@ -314,6 +315,12 @@ public class ReflectionFactory {
return langReflectAccess().copyConstructor(arg); return langReflectAccess().copyConstructor(arg);
} }
/** Gets the byte[] that encodes TypeAnnotations on an executable.
*/
public byte[] getExecutableTypeAnnotationBytes(Executable ex) {
return langReflectAccess().getExecutableTypeAnnotationBytes(ex);
}
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
// //
// Routines used by serialization // Routines used by serialization

View File

@ -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;
}
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -188,7 +188,7 @@ public class AnnotationParser {
* available at runtime * available at runtime
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private static Annotation parseAnnotation(ByteBuffer buf, static Annotation parseAnnotation(ByteBuffer buf,
ConstantPool constPool, ConstantPool constPool,
Class<?> container, Class<?> container,
boolean exceptionOnMissingAnnotationClass) { boolean exceptionOnMissingAnnotationClass) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -27,63 +27,29 @@ package sun.reflect.annotation;
import java.lang.annotation.*; import java.lang.annotation.*;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.Arrays;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import sun.reflect.Reflection;
import sun.misc.JavaLangAccess;
public final class AnnotationSupport { public final class AnnotationSupport {
private static final JavaLangAccess javaLangAccess = sun.misc.SharedSecrets.getJavaLangAccess();
/**
* Finds and returns _one_ annotation of the type indicated by
* {@code annotationClass} from the {@code Map} {@code
* annotationMap}. Looks into containers of the {@code
* annotationClass} (as specified by an the {@code
* annotationClass} type being meta-annotated with an {@code
* ContainedBy} annotation).
*
* @param annotationMap the {@code Map} used to store annotations and indexed by their type
* @param annotationClass the type of annotation to search for
*
* @return in instance of {@code annotationClass} or {@code null} if none were found
*/
public static <A extends Annotation> A getOneAnnotation(final Map<Class<? extends Annotation>, Annotation> annotationMap,
final Class<A> annotationClass) {
@SuppressWarnings("unchecked")
final A candidate = (A)annotationMap.get(annotationClass);
if (candidate != null) {
return candidate;
}
final Class<? extends Annotation> containerClass = getContainer(annotationClass);
if (containerClass != null) {
return unpackOne(annotationMap.get(containerClass), annotationClass);
}
return null; // found none
}
/** /**
* Finds and returns all annotation of the type indicated by * Finds and returns all annotation of the type indicated by
* {@code annotationClass} from the {@code Map} {@code * {@code annotationClass} from the {@code Map} {@code
* annotationMap}. Looks into containers of the {@code * annotationMap}. Looks into containers of the {@code
* annotationClass} (as specified by an the {@code * annotationClass} (as specified by an the {@code
* annotationClass} type being meta-annotated with an {@code * annotationClass} type being meta-annotated with an {@code
* ContainedBy} annotation). * Repeatable} annotation).
* *
* @param annotationMap the {@code Map} used to store annotations indexed by their type * @param annotationMap the {@code Map} used to store annotations indexed by their type
* @param annotationClass the type of annotation to search for * @param annotationClass the type of annotation to search for
* *
* @return an array of instances of {@code annotationClass} or an empty array if none were found * @return an array of instances of {@code annotationClass} or an empty array if none were found
*/ */
public static <A extends Annotation> A[] getMultipleAnnotations(final Map<Class<? extends Annotation>, Annotation> annotationMap, public static <A extends Annotation> A[] getMultipleAnnotations(
final Map<Class<? extends Annotation>, Annotation> annotationMap,
final Class<A> annotationClass) { final Class<A> annotationClass) {
final ArrayList<A> res = new ArrayList<A>(); final List<A> res = new ArrayList<A>();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final A candidate = (A)annotationMap.get(annotationClass); final A candidate = (A)annotationMap.get(annotationClass);
@ -101,49 +67,10 @@ public final class AnnotationSupport {
return res.isEmpty() ? emptyTemplateArray : res.toArray(emptyTemplateArray); return res.isEmpty() ? emptyTemplateArray : res.toArray(emptyTemplateArray);
} }
/**
* Unpacks the {@code annotationMap} parameter into an array of
* {@code Annotation}s. This method will unpack all repeating
* annotations containers (once). An annotation type is marked as a
* container by meta-annotating it the with the {@code
* ContainerFor} annotation.
*
* @param annotationMap the {@code Map} from where the annotations are unpacked
*
* @return an array of Annotation
*/
public static Annotation[] unpackToArray(Map<Class<? extends Annotation>, Annotation> annotationMap) {
List<Annotation> res = new ArrayList<>();
for (Map.Entry<Class<? extends Annotation>, Annotation> e : annotationMap.entrySet()) {
Class<? extends Annotation> annotationClass = e.getKey();
Annotation annotationInstance = e.getValue();
Class<? extends Annotation> containee = getContainee(e.getKey());
boolean isContainer = javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainerFor.class) != null;
if (isContainer) {
res.addAll(unpackAll(annotationInstance, containee));
} else {
res.add(annotationInstance);
}
}
return res.isEmpty()
? AnnotationParser.getEmptyAnnotationArray()
: res.toArray(AnnotationParser.getEmptyAnnotationArray());
}
/** Helper to get the container, or null if none, of an annotation. */ /** Helper to get the container, or null if none, of an annotation. */
private static <A extends Annotation> Class<? extends Annotation> getContainer(Class<A> annotationClass) { private static <A extends Annotation> Class<? extends Annotation> getContainer(Class<A> annotationClass) {
ContainedBy containerAnnotation = Repeatable containingAnnotation = annotationClass.getDeclaredAnnotation(Repeatable.class);
javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainedBy.class); return (containingAnnotation == null) ? null : containingAnnotation.value();
return (containerAnnotation == null) ? null : containerAnnotation.value();
}
/** Helper to get the containee, or null if this isn't a container, of a possible container annotation. */
private static <A extends Annotation> Class<? extends Annotation> getContainee(Class<A> annotationClass) {
ContainerFor containerAnnotation =
javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainerFor.class);
return (containerAnnotation == null) ? null : containerAnnotation.value();
} }
/** Reflectively look up and get the returned array from the the /** Reflectively look up and get the returned array from the the
@ -156,14 +83,15 @@ public final class AnnotationSupport {
// value element. Get the AnnotationType, get the "value" element // value element. Get the AnnotationType, get the "value" element
// and invoke it to get the contents. // and invoke it to get the contents.
Class<?> containerClass = containerInstance.annotationType(); Class<? extends Annotation> containerClass = containerInstance.annotationType();
AnnotationType annoType = javaLangAccess.getAnnotationType(containerClass); AnnotationType annoType = AnnotationType.getInstance(containerClass);
if (annoType == null) if (annoType == null)
throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations"); throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations");
Method m = annoType.members().get("value"); Method m = annoType.members().get("value");
if (m == null) if (m == null)
throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations"); throw new InvalidContainerAnnotationError(containerInstance +
" is an invalid container for repeating annotations");
m.setAccessible(true); m.setAccessible(true);
@SuppressWarnings("unchecked") // not provably safe, but we catch the ClassCastException @SuppressWarnings("unchecked") // not provably safe, but we catch the ClassCastException
@ -175,53 +103,34 @@ public final class AnnotationSupport {
IllegalArgumentException | // parameters doesn't match IllegalArgumentException | // parameters doesn't match
InvocationTargetException | // the value method threw an exception InvocationTargetException | // the value method threw an exception
ClassCastException e) { // well, a cast failed ... ClassCastException e) { // well, a cast failed ...
throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations", throw new InvalidContainerAnnotationError(
containerInstance + " is an invalid container for repeating annotations",
e, e,
containerInstance, containerInstance,
null); null);
} }
} }
/* Sanity check type of and return the first annotation instance
* of type {@code annotationClass} from {@code
* containerInstance}.
*/
private static <A extends Annotation> A unpackOne(Annotation containerInstance, Class<A> annotationClass) {
if (containerInstance == null) {
return null;
}
try {
return annotationClass.cast(getValueArray(containerInstance)[0]);
} catch (ArrayIndexOutOfBoundsException | // empty array
ClassCastException | // well, a cast failed ...
NullPointerException e) { // can this NP? for good meassure
throw new InvalidContainerAnnotationError(String.format("%s is an invalid container for repeating annotations of type: %s",
containerInstance, annotationClass),
e,
containerInstance,
annotationClass);
}
}
/* Sanity check type of and return a list of all the annotation /* Sanity check type of and return a list of all the annotation
* instances of type {@code annotationClass} from {@code * instances of type {@code annotationClass} from {@code
* containerInstance}. * containerInstance}.
*/ */
private static <A extends Annotation> List<A> unpackAll(Annotation containerInstance, Class<A> annotationClass) { private static <A extends Annotation> List<A> unpackAll(Annotation containerInstance,
Class<A> annotationClass) {
if (containerInstance == null) { if (containerInstance == null) {
return Collections.emptyList(); // container not present return Collections.emptyList(); // container not present
} }
try { try {
A[] a = getValueArray(containerInstance); A[] a = getValueArray(containerInstance);
ArrayList<A> l = new ArrayList<>(a.length); List<A> l = new ArrayList<>(a.length);
for (int i = 0; i < a.length; i++) for (int i = 0; i < a.length; i++)
l.add(annotationClass.cast(a[i])); l.add(annotationClass.cast(a[i]));
return l; return l;
} catch (ClassCastException | } catch (ClassCastException |
NullPointerException e) { NullPointerException e) {
throw new InvalidContainerAnnotationError(String.format("%s is an invalid container for repeating annotations of type: %s", throw new InvalidContainerAnnotationError(
String.format("%s is an invalid container for repeating annotations of type: %s",
containerInstance, annotationClass), containerInstance, annotationClass),
e, e,
containerInstance, containerInstance,

View 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();
}
}

View File

@ -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);
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,13 +25,18 @@
package sun.reflect.generics.reflectiveObjects; package sun.reflect.generics.reflectiveObjects;
import java.lang.annotation.Annotation; import java.lang.annotation.*;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.lang.reflect.GenericDeclaration; import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable; import java.lang.reflect.TypeVariable;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import sun.reflect.annotation.AnnotationSupport;
import sun.reflect.annotation.TypeAnnotationParser;
import sun.reflect.annotation.AnnotationType;
import sun.reflect.generics.factory.GenericsFactory; import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.tree.FieldTypeSignature; import sun.reflect.generics.tree.FieldTypeSignature;
import sun.reflect.generics.visitor.Reifier; import sun.reflect.generics.visitor.Reifier;
@ -182,45 +187,70 @@ public class TypeVariableImpl<D extends GenericDeclaration>
return genericDeclaration.hashCode() ^ name.hashCode(); return genericDeclaration.hashCode() ^ name.hashCode();
} }
// Currently vacuous implementations of AnnotatedElement methods. // Implementations of AnnotatedElement methods.
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) { @SuppressWarnings("unchecked")
Objects.requireNonNull(annotationClass);
return false;
}
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass); Objects.requireNonNull(annotationClass);
return null; // T is an Annotation type, the return value of get will be an annotation
return (T)mapAnnotations(getAnnotations()).get(annotationClass);
} }
public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) { public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass); Objects.requireNonNull(annotationClass);
return null; return getAnnotation(annotationClass);
} }
@SuppressWarnings("unchecked")
public <T extends Annotation> T[] getAnnotations(Class<T> annotationClass) { public <T extends Annotation> T[] getAnnotations(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass); Objects.requireNonNull(annotationClass);
// safe because annotationClass is the class for T return AnnotationSupport.getMultipleAnnotations(mapAnnotations(getAnnotations()), annotationClass);
return (T[])Array.newInstance(annotationClass, 0);
} }
@SuppressWarnings("unchecked")
public <T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass) { public <T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass); Objects.requireNonNull(annotationClass);
// safe because annotationClass is the class for T return getAnnotations(annotationClass);
return (T[])Array.newInstance(annotationClass, 0);
} }
public Annotation[] getAnnotations() { public Annotation[] getAnnotations() {
// Since zero-length, don't need defensive clone int myIndex = typeVarIndex();
return EMPTY_ANNOTATION_ARRAY; if (myIndex < 0)
throw new AssertionError("Index must be non-negative.");
return TypeAnnotationParser.parseTypeVariableAnnotations(getGenericDeclaration(), myIndex);
} }
public Annotation[] getDeclaredAnnotations() { public Annotation[] getDeclaredAnnotations() {
// Since zero-length, don't need defensive clone return getAnnotations();
return EMPTY_ANNOTATION_ARRAY; }
public AnnotatedType[] getAnnotatedBounds() {
return TypeAnnotationParser.parseAnnotatedBounds(getBounds(),
getGenericDeclaration(),
typeVarIndex());
} }
private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0]; private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
// Helpers for annotation methods
private int typeVarIndex() {
TypeVariable<?>[] tVars = getGenericDeclaration().getTypeParameters();
int i = -1;
for (TypeVariable<?> v : tVars) {
i++;
if (equals(v))
return i;
}
return -1;
}
private static Map<Class<? extends Annotation>, Annotation> mapAnnotations(Annotation[] annos) {
Map<Class<? extends Annotation>, Annotation> result =
new LinkedHashMap<>();
for (Annotation a : annos) {
Class<? extends Annotation> klass = a.annotationType();
AnnotationType type = AnnotationType.getInstance(klass);
if (type.retention() == RetentionPolicy.RUNTIME)
if (result.put(klass, a) != null)
throw new AnnotationFormatError("Duplicate annotation for class: "+klass+": " + a);
}
return result;
}
} }

View File

@ -1116,7 +1116,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
if (privateKeyCount > 0 || secretKeyCount > 0) { if (privateKeyCount > 0 || secretKeyCount > 0) {
if (debug != null) { if (debug != null) {
debug.println("Storing " + privateKeyCount + debug.println("Storing " + (privateKeyCount + secretKeyCount) +
" protected key(s) in a PKCS#7 data content-type"); " protected key(s) in a PKCS#7 data content-type");
} }
@ -2122,6 +2122,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
SecretKeyEntry kEntry = new SecretKeyEntry(); SecretKeyEntry kEntry = new SecretKeyEntry();
kEntry.protectedSecretKey = secretValue.getOctetString(); kEntry.protectedSecretKey = secretValue.getOctetString();
bagItem = kEntry; bagItem = kEntry;
secretKeyCount++;
} else { } else {
if (debug != null) { if (debug != null) {
@ -2220,6 +2221,10 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
if (bagItem instanceof PrivateKeyEntry) { if (bagItem instanceof PrivateKeyEntry) {
keyList.add((PrivateKeyEntry) entry); keyList.add((PrivateKeyEntry) entry);
} }
if (entry.attributes == null) {
entry.attributes = new HashSet<>();
}
entry.attributes.addAll(attributes);
if (alias == null) { if (alias == null) {
alias = getUnfriendlyName(); alias = getUnfriendlyName();
} }

View File

@ -465,6 +465,12 @@ JVM_GetClassSignature(JNIEnv *env, jclass cls);
JNIEXPORT jbyteArray JNICALL JNIEXPORT jbyteArray JNICALL
JVM_GetClassAnnotations(JNIEnv *env, jclass cls); JVM_GetClassAnnotations(JNIEnv *env, jclass cls);
/* Type use annotations support (JDK 1.8) */
JNIEXPORT jbyteArray JNICALL
JVM_GetClassTypeAnnotations(JNIEnv *env, jclass cls);
/* /*
* New (JDK 1.4) reflection implementation * New (JDK 1.4) reflection implementation
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -75,7 +75,8 @@ static JNINativeMethod methods[] = {
{"getRawAnnotations", "()" BA, (void *)&JVM_GetClassAnnotations}, {"getRawAnnotations", "()" BA, (void *)&JVM_GetClassAnnotations},
{"getConstantPool", "()" CPL, (void *)&JVM_GetClassConstantPool}, {"getConstantPool", "()" CPL, (void *)&JVM_GetClassConstantPool},
{"desiredAssertionStatus0","("CLS")Z",(void *)&JVM_DesiredAssertionStatus}, {"desiredAssertionStatus0","("CLS")Z",(void *)&JVM_DesiredAssertionStatus},
{"getEnclosingMethod0", "()[" OBJ, (void *)&JVM_GetEnclosingMethodInfo} {"getEnclosingMethod0", "()[" OBJ, (void *)&JVM_GetEnclosingMethodInfo},
{"getRawTypeAnnotations", "()" BA, (void *)&JVM_GetClassTypeAnnotations},
}; };
#undef OBJ #undef OBJ

View File

@ -191,17 +191,6 @@ static int closefd(int fd1, int fd2) {
pthread_mutex_lock(&(fdEntry->lock)); pthread_mutex_lock(&(fdEntry->lock));
{ {
/*
* Send a wakeup signal to all threads blocked on this
* file descriptor.
*/
threadEntry_t *curr = fdEntry->threads;
while (curr != NULL) {
curr->intr = 1;
pthread_kill( curr->thr, sigWakeup );
curr = curr->next;
}
/* /*
* And close/dup the file descriptor * And close/dup the file descriptor
* (restart if interrupted by signal) * (restart if interrupted by signal)
@ -214,6 +203,16 @@ static int closefd(int fd1, int fd2) {
} }
} while (rv == -1 && errno == EINTR); } while (rv == -1 && errno == EINTR);
/*
* Send a wakeup signal to all threads blocked on this
* file descriptor.
*/
threadEntry_t *curr = fdEntry->threads;
while (curr != NULL) {
curr->intr = 1;
pthread_kill( curr->thr, sigWakeup );
curr = curr->next;
}
} }
/* /*

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -104,6 +104,11 @@ static char* next_arg(char* cmdline, char* arg, jboolean* wildcard) {
case ' ': case ' ':
case '\t': case '\t':
if (prev == '\\') {
for (i = 0 ; i < slashes; i++) {
*dest++ = prev;
}
}
if (quotes % 2 == 1) { if (quotes % 2 == 1) {
*dest++ = ch; *dest++ = ch;
} else { } else {
@ -591,6 +596,12 @@ int main(int argc, char* argv[]) {
// v->disable(); // v->disable();
vectors[i++] = v; vectors[i++] = v;
v= new Vector(argv[0], "a b\\\\ d");
v->add("a", FALSE);
v->add("b\\\\", FALSE);
v->add("d", FALSE);
vectors[i++] = v;
dotest(vectors); dotest(vectors);
printf("All tests pass [%d]\n", i); printf("All tests pass [%d]\n", i);
doexit(0); doexit(0);

View File

@ -321,12 +321,12 @@ sun/jvmstat/monitor/MonitoredVm/CR6672135.java generic-all
tools/pack200/CommandLineTests.java generic-all tools/pack200/CommandLineTests.java generic-all
tools/pack200/Pack200Test.java generic-all tools/pack200/Pack200Test.java generic-all
# 8001163
tools/pack200/AttributeTests.java generic-all
# 7150569 # 7150569
tools/launcher/UnicodeTest.java macosx-all tools/launcher/UnicodeTest.java macosx-all
# 8007410
tools/launcher/FXLauncherTest.java linux-all
############################################################################ ############################################################################
# jdk_jdi # jdk_jdi

View 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();
}

View 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();
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,7 +23,7 @@
/* /*
* @test * @test
* @bug 7154390 * @bug 7154390 8005712
* @summary Unit test for repeated annotation reflection * @summary Unit test for repeated annotation reflection
* *
* @compile RepeatedUnitTest.java subpackage/package-info.java subpackage/Container.java subpackage/Containee.java subpackage/NonRepeated.java subpackage/InheritedContainee.java subpackage/InheritedContainer.java subpackage/InheritedNonRepeated.java * @compile RepeatedUnitTest.java subpackage/package-info.java subpackage/Container.java subpackage/Containee.java subpackage/NonRepeated.java subpackage/InheritedContainee.java subpackage/InheritedContainer.java subpackage/InheritedNonRepeated.java
@ -58,7 +58,7 @@ public class RepeatedUnitTest {
checkMultiplier(Me1.class.getField("foo"), 1); checkMultiplier(Me1.class.getField("foo"), 1);
// METHOD // METHOD
checkMultiplier(Me1.class.getDeclaredMethod("mee", null), 100); checkMultiplier(Me1.class.getDeclaredMethod("mee", (Class<?>[])null), 100);
// INNER CLASS // INNER CLASS
checkMultiplier(Me1.MiniMee.class, 1000); checkMultiplier(Me1.MiniMee.class, 1000);
@ -84,8 +84,7 @@ public class RepeatedUnitTest {
static void packageRepeated(AnnotatedElement e) { static void packageRepeated(AnnotatedElement e) {
Containee c = e.getAnnotation(Containee.class); Containee c = e.getAnnotation(Containee.class);
check(c.value() == 1); check(c == null);
check(2 == countAnnotation(e, Containee.class)); check(2 == countAnnotation(e, Containee.class));
c = e.getAnnotations(Containee.class)[0]; c = e.getAnnotations(Containee.class)[0];
@ -93,7 +92,7 @@ public class RepeatedUnitTest {
c = e.getAnnotations(Containee.class)[1]; c = e.getAnnotations(Containee.class)[1];
check(c.value() == 2); check(c.value() == 2);
check(2 == containsAnnotationOfType(e.getAnnotations(), Containee.class)); check(0 == containsAnnotationOfType(e.getAnnotations(), Containee.class));
} }
static void packageContainer(AnnotatedElement e) { static void packageContainer(AnnotatedElement e) {
@ -161,14 +160,26 @@ public class RepeatedUnitTest {
} }
static void checkMultiplier(AnnotatedElement e, int m) { static void checkMultiplier(AnnotatedElement e, int m) {
// Basic sanity of non-repeating getAnnotation(Class)
check(e.getAnnotation(NonRepeated.class).value() == 5 * m); check(e.getAnnotation(NonRepeated.class).value() == 5 * m);
// Check count of annotations returned from getAnnotations(Class)
check(4 == countAnnotation(e, Containee.class)); check(4 == countAnnotation(e, Containee.class));
check(1 == countAnnotation(e, Container.class)); check(1 == countAnnotation(e, Container.class));
check(1 == countAnnotation(e, NonRepeated.class)); check(1 == countAnnotation(e, NonRepeated.class));
// Check contents of array returned from getAnnotations(Class)
check(e.getAnnotations(Containee.class)[2].value() == 3 * m); check(e.getAnnotations(Containee.class)[2].value() == 3 * m);
check(e.getAnnotations(NonRepeated.class)[0].value() == 5 * m); check(e.getAnnotations(NonRepeated.class)[0].value() == 5 * m);
// Check getAnnotation(Class)
check(e.getAnnotation(Containee.class) == null);
check(e.getAnnotation(Container.class) != null);
// Check count of annotations returned from getAnnotations()
check(0 == containsAnnotationOfType(e.getAnnotations(), Containee.class));
check(1 == containsAnnotationOfType(e.getAnnotations(), Container.class));
check(1 == containsAnnotationOfType(e.getAnnotations(), NonRepeated.class));
} }
static void check(Boolean b) { static void check(Boolean b) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,7 +26,6 @@ package subpackage;
import java.lang.annotation.*; import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@ContainedBy(Container.class)
@Repeatable(Container.class) @Repeatable(Container.class)
public @interface Containee { public @interface Containee {
int value(); int value();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,7 +26,6 @@ package subpackage;
import java.lang.annotation.*; import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@ContainerFor(Containee.class)
public @interface Container { public @interface Container {
Containee[] value(); Containee[] value();
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -27,7 +27,6 @@ import java.lang.annotation.*;
@Inherited @Inherited
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@ContainedBy(InheritedContainer.class)
@Repeatable(InheritedContainer.class) @Repeatable(InheritedContainer.class)
public @interface InheritedContainee { public @interface InheritedContainee {
int value(); int value();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -27,7 +27,6 @@ import java.lang.annotation.*;
@Inherited @Inherited
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@ContainerFor(InheritedContainee.class)
public @interface InheritedContainer { public @interface InheritedContainer {
InheritedContainee[] value(); InheritedContainee[] value();
} }

View File

@ -23,163 +23,152 @@
/* /*
* @test * @test
* @bug 8004729
* @summary javac should generate method parameters correctly. * @summary javac should generate method parameters correctly.
*/ */
import java.lang.*; import java.lang.*;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.lang.annotation.*;
import java.util.List; import java.util.List;
import java.util.Objects;
import static java.lang.annotation.ElementType.*;
public class WithoutParameters { public class WithoutParameters {
int errors = 0;
private static final Class<?>[] qux_types = { private WithoutParameters() {}
int.class,
Foo.class,
List.class,
List.class,
List.class,
String[].class
};
public static void main(String argv[]) throws Exception { public static void main(String argv[]) throws Exception {
int error = 0; WithoutParameters wp = new WithoutParameters();
Method[] methods = Foo.class.getMethods(); wp.runTests(Foo.class.getMethods());
for(Method m : methods) { wp.runTests(Foo.Inner.class.getConstructors());
System.err.println("Inspecting method " + m); wp.checkForErrors();
Parameter[] parameters = m.getParameters();
if(parameters == null)
throw new Exception("getParameters should never be null");
for(int i = 0; i < parameters.length; i++) {
Parameter p = parameters[i];
if(!p.getDeclaringExecutable().equals(m)) {
System.err.println(p + ".getDeclaringExecutable != " + m);
error++;
}
if(null == p.getType()) {
System.err.println(p + ".getType() == null");
error++;
}
if(null == p.getParameterizedType()) {
System.err.println(p + ".getParameterizedType == null");
error++;
}
}
if(m.getName().equals("qux")) {
if(6 != parameters.length) {
System.err.println("Wrong number of parameters for qux");
error++;
}
for(int i = 0; i < parameters.length; i++) {
Parameter p = parameters[i];
// The getType family work with or without
// parameter attributes compiled in.
if(!parameters[i].getType().equals(qux_types[i])) {
System.err.println("Wrong parameter type for " + parameters[0] + ": expected " + qux_types[i] + ", but got " + parameters[i].getType());
error++;
}
}
if(!parameters[0].getParameterizedType().equals(int.class)) {
System.err.println("getParameterizedType for quux is wrong");
error++;
}
if(!parameters[1].getParameterizedType().equals(Foo.class)) {
System.err.println("getParameterizedType for quux is wrong");
error++;
}
if(!(parameters[2].getParameterizedType() instanceof
ParameterizedType)) {
System.err.println("getParameterizedType for l is wrong");
error++;
} else {
ParameterizedType pt =
(ParameterizedType) parameters[2].getParameterizedType();
if(!pt.getRawType().equals(List.class)) {
System.err.println("Raw type for l is wrong");
error++;
}
if(1 != pt.getActualTypeArguments().length) {
System.err.println("Number of type parameters for l is wrong");
error++;
}
if(!(pt.getActualTypeArguments()[0] instanceof WildcardType)) {
System.err.println("Type parameter for l is wrong");
error++;
}
}
if(!(parameters[3].getParameterizedType() instanceof
ParameterizedType)) {
System.err.println("getParameterizedType for l2 is wrong");
error++;
} else {
ParameterizedType pt =
(ParameterizedType) parameters[3].getParameterizedType();
if(!pt.getRawType().equals(List.class)) {
System.err.println("Raw type for l2 is wrong");
error++;
}
if(1 != pt.getActualTypeArguments().length) {
System.err.println("Number of type parameters for l2 is wrong");
error++;
}
if(!(pt.getActualTypeArguments()[0].equals(Foo.class))) {
System.err.println("Type parameter for l2 is wrong");
error++;
}
}
if(!(parameters[4].getParameterizedType() instanceof
ParameterizedType)) {
System.err.println("getParameterizedType for l3 is wrong");
error++;
} else {
ParameterizedType pt =
(ParameterizedType) parameters[4].getParameterizedType();
if(!pt.getRawType().equals(List.class)) {
System.err.println("Raw type for l3 is wrong");
error++;
}
if(1 != pt.getActualTypeArguments().length) {
System.err.println("Number of type parameters for l3 is wrong");
error++;
}
if(!(pt.getActualTypeArguments()[0] instanceof WildcardType)) {
System.err.println("Type parameter for l3 is wrong");
error++;
} else {
WildcardType wt = (WildcardType)
pt.getActualTypeArguments()[0];
if(!wt.getUpperBounds()[0].equals(Foo.class)) {
System.err.println("Upper bounds on type parameter fol l3 is wrong");
error++;
}
}
}
if(!parameters[5].isVarArgs()) {
System.err.println("isVarArg for rest is wrong");
error++;
}
if(!(parameters[5].getParameterizedType().equals(String[].class))) {
System.err.println("getParameterizedType for rest is wrong");
error++;
} }
void runTests(Method[] methods) throws Exception {
for(Method m : methods) {runTest(m);}
}
void runTests(Constructor[] constructors) throws Exception {
for(Constructor c : constructors) {runTest(c);}
}
void runTest(Executable e) throws Exception {
System.err.println("Inspecting executable " + e);
Parameter[] parameters = e.getParameters();
Objects.requireNonNull(parameters, "getParameters should never be null");
ExpectedParameterInfo epi = e.getAnnotation(ExpectedParameterInfo.class);
if (epi != null) {
abortIfTrue(epi.parameterCount() != e.getParameterCount(), "Bad parameter count for "+ e);
abortIfTrue(epi.isVarArgs() != e.isVarArgs(),"Bad varargs value for "+ e);
}
abortIfTrue(e.getParameterCount() != parameters.length, "Mismatched of parameter counts.");
for(int i = 0; i < parameters.length; i++) {
Parameter p = parameters[i];
errorIfTrue(!p.getDeclaringExecutable().equals(e), p + ".getDeclaringExecutable != " + e);
Objects.requireNonNull(p.getType(), "getType() should not be null");
Objects.requireNonNull(p.getParameterizedType(), "getParameterizedType() should not be null");
if (epi != null) {
Class<?> expectedParameterType = epi.parameterTypes()[i];
errorIfTrue(!p.getType().equals(expectedParameterType),
"Wrong parameter type for " + p + ": expected " + expectedParameterType +
", but got " + p.getType());
ParameterizedInfo[] expectedParameterizedTypes = epi.parameterizedTypes();
if (expectedParameterizedTypes.length > 0) {
Type parameterizedType = p.getParameterizedType();
Class<? extends Type> expectedParameterziedTypeType = expectedParameterizedTypes[i].value();
errorIfTrue(!expectedParameterziedTypeType.isAssignableFrom(parameterizedType.getClass()),
"Wrong class of parameteried type of " + p + ": expected " + expectedParameterziedTypeType +
", but got " + parameterizedType.getClass());
if (expectedParameterziedTypeType.equals(Class.class)) {
errorIfTrue(!parameterizedType.equals(expectedParameterType),
"Wrong parameteried type for " + p + ": expected " + expectedParameterType +
", but got " + parameterizedType);
} else {
if (expectedParameterziedTypeType.equals(ParameterizedType.class)) {
ParameterizedType ptype = (ParameterizedType)parameterizedType;
errorIfTrue(!ptype.getRawType().equals(expectedParameterType),
"Wrong raw type for " + p + ": expected " + expectedParameterType +
", but got " + ptype.getRawType());
}
// Check string representation
String expectedStringOfType = epi.parameterizedTypes()[i].string();
errorIfTrue(!expectedStringOfType.equals(parameterizedType.toString()),
"Bad type string" + p + ": expected " + expectedStringOfType +
", but got " + parameterizedType.toString());
} }
} }
if(0 != error) }
throw new Exception("Failed " + error + " tests"); }
}
private void checkForErrors() {
if (errors > 0)
throw new RuntimeException("Failed " + errors + " tests");
}
private void errorIfTrue(boolean predicate, String errMessage) {
if (predicate) {
errors++;
System.err.println(errMessage);
}
}
private void abortIfTrue(boolean predicate, String errMessage) {
if (predicate) {
throw new RuntimeException(errMessage);
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target({METHOD, CONSTRUCTOR})
@interface ExpectedParameterInfo {
int parameterCount() default 0;
Class<?>[] parameterTypes() default {};
ParameterizedInfo[] parameterizedTypes() default {};
boolean isVarArgs() default false;
}
@Target({})
@interface ParameterizedInfo {
Class<? extends Type> value() default Class.class;
String string() default "";
} }
public class Foo { public class Foo {
int thing; int thing;
@ExpectedParameterInfo(parameterCount = 6,
parameterTypes =
{int.class, Foo.class,
List.class, List.class,
List.class, String[].class},
parameterizedTypes =
{@ParameterizedInfo(Class.class),
@ParameterizedInfo(Class.class),
@ParameterizedInfo(value=ParameterizedType.class, string="java.util.List<?>"),
@ParameterizedInfo(value=ParameterizedType.class, string="java.util.List<WithoutParameters$Foo>"),
@ParameterizedInfo(value=ParameterizedType.class, string="java.util.List<? extends WithoutParameters$Foo>"),
@ParameterizedInfo(Class.class)},
isVarArgs = true)
public void qux(int quux, Foo quuux, public void qux(int quux, Foo quuux,
List<?> l, List<Foo> l2, List<?> l, List<Foo> l2,
List<? extends Foo> l3, List<? extends Foo> l3,
String... rest) {} String... rest) {}
public class Inner { public class Inner {
int thang; int thang;
@ExpectedParameterInfo(parameterCount = 2,
parameterTypes = {Foo.class, int.class})
public Inner(int theng) { public Inner(int theng) {
thang = theng + thing; thang = theng + thing;
} }
} }
} }
} }

View 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();
}
}
}
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998, 2002, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -21,71 +21,235 @@
* questions. * questions.
*/ */
/* This is no longer run directly. See runconstructor.sh /*
* * @test
* * @bug 4393671
* * @summary URL constructor URL(URL context, String spec) FAILED with specific input
*/
/*
* This program tests the URL parser in the URL constructor. It * This program tests the URL parser in the URL constructor. It
* tries to construct a variety of valid URLs with a given context * tries to construct a variety of valid URLs with a given context
* (which may be null) and a variety of specs. It then compares the * (which may be null) and a variety of specs. It then compares the
* result with an expected value. * result with an expected value.
*
* It expects that a data file named "urls" be available in the
* current directory, from which it will get its testing data. The
* format of the file is:
*
* URL: null
* spec: jar:http://www.foo.com/dir1/jar.jar!/
* expected: jar:http://www.foo.com/dir1/jar.jar!/
*
* where URL is the context, spec is the spec and expected is the
* expected result. The first : must be followed by a space. Each test
* entry should be followed by a blank line.
*/ */
import java.io.*; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Constructor { public class Constructor {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
URL url = null; List<Entry> entries = new ArrayList<>();
String urls = "jar_urls"; entries.addAll(Arrays.asList(fileURLs));
if (args.length > 0 && args[0] != null) { entries.addAll(Arrays.asList(jarURLs));
urls = args[0]; entries.addAll(Arrays.asList(normalHttpURLs));
} entries.addAll(Arrays.asList(abnormalHttpURLs));
if (hasFtp())
entries.addAll(Arrays.asList(ftpURLs));
URL url;
File f = new File(urls); for (Entry e : entries) {
InputStream file = new FileInputStream(f); if (e.context == null)
BufferedReader in = new BufferedReader(new InputStreamReader(file)); url = new URL(e.spec);
while(true) { else
String context = in.readLine(); url = new URL(new URL(e.context), e.spec);
if (context == null) {
break;
}
context = getValue(context);
String spec = getValue(in.readLine());
String expected = getValue(in.readLine());
if (context.equals("null")) { if (!(url.toString().equals(e.expected))) {
url = new URL(spec); throw new RuntimeException("error for: \n\tURL:" + e.context +
} else { "\n\tspec: " + e.spec +
url = new URL(new URL(context), spec); "\n\texpected: " + e.expected +
}
if (!(url.toString().equals(expected))) {
throw new RuntimeException("error for: \n\tURL:" + context +
"\n\tspec: " + spec +
"\n\texpected: " + expected +
"\n\tactual: " + url.toString()); "\n\tactual: " + url.toString());
} else { } else {
System.out.println("success for: " + url + "\n"); //debug
//System.out.println("success for: " + url);
} }
in.readLine();
} }
in.close();
} }
private static String getValue(String value) { private static boolean hasFtp() {
return value.substring(value.indexOf(':') + 2); try {
return new java.net.URL("ftp://") != null;
} catch (java.net.MalformedURLException x) {
System.out.println("FTP not supported by this runtime.");
return false;
} }
}
static class Entry {
final String context;
final String spec;
final String expected;
Entry(String context, String spec, String expected) {
this.context = context;
this.spec =spec;
this.expected = expected;
}
}
static Entry[] fileURLs = new Entry[] {
new Entry(null,
"file://JavaSoft/Test",
"file://JavaSoft/Test"),
new Entry(null,
"file:///JavaSoft/Test",
"file:/JavaSoft/Test"),
new Entry(null,
"file:/JavaSoft/Test",
"file:/JavaSoft/Test"),
new Entry(null,
"file:/c:/JavaSoft/Test",
"file:/c:/JavaSoft/Test"),
new Entry(null,
"file:/c:/JavaSoft/Test:something",
"file:/c:/JavaSoft/Test:something"),
new Entry(null,
"file:/c:/JavaSoft/Test#anchor",
"file:/c:/JavaSoft/Test#anchor"),
new Entry("file://JavaSoft/Test",
"Test#bar",
"file://JavaSoft/Test#bar"),
new Entry("file://codrus/c:/jdk/eng/index.html",
"pulsar.html",
"file://codrus/c:/jdk/eng/pulsar.html"),
new Entry("file:///c:/jdk/eng/index.html",
"pulsar.html",
"file:/c:/jdk/eng/pulsar.html"),
new Entry("file:///jdk/eng/index.html",
"pulsar.html",
"file:/jdk/eng/pulsar.html"),
new Entry("file://JavaSoft/Test",
"file://radartoad.com/Test#bar",
"file://radartoad.com/Test#bar"),
new Entry("file://JavaSoft/Test",
"/c:/Test#bar",
"file://JavaSoft/c:/Test#bar"),
};
static Entry[] jarURLs = new Entry[] {
new Entry(null,
"jar:http://www.foo.com/dir1/jar.jar!/dir2/entry.txt",
"jar:http://www.foo.com/dir1/jar.jar!/dir2/entry.txt"),
new Entry(null,
"jar:http://www.foo.com/dir1/jar.jar!/",
"jar:http://www.foo.com/dir1/jar.jar!/"),
new Entry(null,
"jar:http://www.foo.com/dir1/jar.jar!/",
"jar:http://www.foo.com/dir1/jar.jar!/"),
new Entry("jar:http://www.foo.com/dir1/jar.jar!/",
"entry.txt",
"jar:http://www.foo.com/dir1/jar.jar!/entry.txt"),
new Entry("jar:http://www.foo.com/dir1/jar.jar!/",
"/entry.txt",
"jar:http://www.foo.com/dir1/jar.jar!/entry.txt"),
new Entry("jar:http://www.foo.com/dir1/jar.jar!/",
"dir1/entry.txt",
"jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt"),
new Entry("jar:http://www.foo.com/dir1/jar.jar!/",
"/dir1/entry.txt",
"jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt"),
new Entry("jar:http://www.foo.com/dir1/jar.jar!/",
"entry.txt",
"jar:http://www.foo.com/dir1/jar.jar!/entry.txt"),
new Entry("jar:http://www.foo.com/dir1/jar.jar!/",
"/entry.txt",
"jar:http://www.foo.com/dir1/jar.jar!/entry.txt"),
new Entry("jar:http://www.foo.com/dir1/jar.jar!/",
"/entry.txt",
"jar:http://www.foo.com/dir1/jar.jar!/entry.txt"),
new Entry("jar:http://www.foo.com/dir1/jar.jar!/dir1/",
"entry.txt",
"jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt"),
new Entry("jar:http://www.foo.com/dir1/jar.jar!/dir2/dir3/entry2.txt",
"/dir1/entry.txt",
"jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt"),
new Entry("jar:http://www.foo.com/dir1/jar.jar!/",
"/dir1/foo/entry.txt",
"jar:http://www.foo.com/dir1/jar.jar!/dir1/foo/entry.txt"),
new Entry("jar:http://www.foo.com/dir1/jar.jar!/dir1/dir2/dir3/",
"dir4/foo/entry.txt",
"jar:http://www.foo.com/dir1/jar.jar!/dir1/dir2/dir3/dir4/foo/entry.txt"),
new Entry("jar:http://www.foo.com/dir1/jar.jar!/",
"/dir1/foo/entry.txt",
"jar:http://www.foo.com/dir1/jar.jar!/dir1/foo/entry.txt"),
new Entry(null,
"jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor",
"jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor"),
new Entry("jar:http://www.foo.com/dir1/jar.jar!/foo.txt",
"#anchor",
"jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor"),
new Entry("jar:http://www.foo.com/dir1/jar.jar!/foo/bar/",
"baz/quux#anchor",
"jar:http://www.foo.com/dir1/jar.jar!/foo/bar/baz/quux#anchor"),
new Entry("jar:http://balloo.com/olle.jar!/",
"p2",
"jar:http://balloo.com/olle.jar!/p2")
};
static Entry[] normalHttpURLs = new Entry[] {
new Entry("http://a/b/c/d;p?q", "g", "http://a/b/c/g"),
new Entry("http://a/b/c/d;p?q", "./g", "http://a/b/c/g"),
new Entry("http://a/b/c/d;p?q", "g/", "http://a/b/c/g/"),
new Entry("http://a/b/c/d;p?q", "/g", "http://a/g"),
new Entry("http://a/b/c/d;p?q", "//g", "http://g"),
new Entry("http://a/b/c/d;p?q", "?y", "http://a/b/c/?y"),
new Entry("http://a/b/c/d;p?q", "g?y", "http://a/b/c/g?y"),
new Entry("http://a/b/c/d;p?q", "g#s", "http://a/b/c/g#s"),
new Entry("http://a/b/c/d;p?q", "g?y#s", "http://a/b/c/g?y#s"),
new Entry("http://a/b/c/d;p?q", ";x", "http://a/b/c/;x"),
new Entry("http://a/b/c/d;p?q", "g;x", "http://a/b/c/g;x"),
new Entry("http://a/b/c/d;p?q", "g;x?y#s", "http://a/b/c/g;x?y#s"),
new Entry("http://a/b/c/d;p?q", ".", "http://a/b/c/"),
new Entry("http://a/b/c/d;p?q", "./", "http://a/b/c/"),
new Entry("http://a/b/c/d;p?q", "..", "http://a/b/"),
new Entry("http://a/b/c/d;p?q", "../", "http://a/b/"),
new Entry("http://a/b/c/d;p?q", "../g", "http://a/b/g"),
new Entry("http://a/b/c/d;p?q", "../..", "http://a/"),
new Entry("http://a/b/c/d;p?q", "../../", "http://a/"),
new Entry("http://a/b/c/d;p?q", "../../g", "http://a/g"),
new Entry(null,
"http://www.javasoft.com/jdc/community/chat/index.html#javalive?frontpage-jdc",
"http://www.javasoft.com/jdc/community/chat/index.html#javalive?frontpage-jdc")
};
static Entry[] abnormalHttpURLs = new Entry[] {
new Entry("http://a/b/c/d;p?q", "../../../g", "http://a/../g"),
new Entry("http://a/b/c/d;p?q", "../../../../g", "http://a/../../g"),
new Entry("http://a/b/c/d;p?q", "/./g", "http://a/./g"),
new Entry("http://a/b/c/d;p?q", "/../g", "http://a/../g"),
new Entry("http://a/b/c/d;p?q", ".g", "http://a/b/c/.g"),
new Entry("http://a/b/c/d;p?q", "g.", "http://a/b/c/g."),
new Entry("http://a/b/c/d;p?q", "./../g", "http://a/b/g"),
new Entry("http://a/b/c/d;p?q", "./g/.", "http://a/b/c/g/"),
new Entry("http://a/b/c/d;p?q", "g/./h", "http://a/b/c/g/h"),
new Entry("http://a/b/c/d;p?q", "g;x=1/./y", "http://a/b/c/g;x=1/y"),
new Entry("http://a/b/c/d;p?q", "g;x=1/../y", "http://a/b/c/y")
};
static Entry[] ftpURLs = new Entry[] {
new Entry(null,
"ftp://ftp.foo.com/dir1/entry.txt",
"ftp://ftp.foo.com/dir1/entry.txt"),
new Entry(null,
"ftp://br:pwd@ftp.foo.com/dir1/jar.jar",
"ftp://br:pwd@ftp.foo.com/dir1/jar.jar"),
new Entry("ftp://ftp.foo.com/dir1/foo.txt",
"bar.txt",
"ftp://ftp.foo.com/dir1/bar.txt"),
new Entry("ftp://ftp.foo.com/dir1/jar.jar",
"/entry.txt",
"ftp://ftp.foo.com/entry.txt"),
new Entry("ftp://ftp.foo.com/dir1/jar.jar",
"dir1/entry.txt",
"ftp://ftp.foo.com/dir1/dir1/entry.txt"),
new Entry("ftp://ftp.foo.com/dir1/jar.jar",
"/dir1/entry.txt",
"ftp://ftp.foo.com/dir1/entry.txt"),
new Entry("ftp://br:pwd@ftp.foo.com/dir1/jar.jar",
"/dir1/entry.txt",
"ftp://br:pwd@ftp.foo.com/dir1/entry.txt")
};
} }

View File

@ -36,7 +36,7 @@ public class HandlerLoop {
public static void main(String args[]) throws Exception { public static void main(String args[]) throws Exception {
URL.setURLStreamHandlerFactory( URL.setURLStreamHandlerFactory(
new HandlerFactory("sun.net.www.protocol")); new HandlerFactory("sun.net.www.protocol"));
URL url = new URL("file://bogus/index.html"); URL url = new URL("file:///bogus/index.html");
System.out.println("url = " + url); System.out.println("url = " + url);
url.openConnection(); url.openConnection();
} }

View File

@ -310,7 +310,14 @@ public class Test {
throw new RuntimeException("Test failed"); throw new RuntimeException("Test failed");
} }
private static boolean hasFtp() {
try {
return new java.net.URL("ftp://") != null;
} catch (java.net.MalformedURLException x) {
System.out.println("FTP not supported by this runtime.");
return false;
}
}
// -- Tests -- // -- Tests --
@ -319,6 +326,7 @@ public class Test {
header("RFC2396: Basic examples"); header("RFC2396: Basic examples");
if (hasFtp())
test("ftp://ftp.is.co.za/rfc/rfc1808.txt") test("ftp://ftp.is.co.za/rfc/rfc1808.txt")
.s("ftp").h("ftp.is.co.za").p("/rfc/rfc1808.txt").z(); .s("ftp").h("ftp.is.co.za").p("/rfc/rfc1808.txt").z();
@ -328,6 +336,7 @@ public class Test {
test("http://www.w3.org/Addressing/") test("http://www.w3.org/Addressing/")
.s("http").h("www.w3.org").p("/Addressing/").z(); .s("http").h("www.w3.org").p("/Addressing/").z();
if (hasFtp())
test("ftp://ds.internic.net/rfc/") test("ftp://ds.internic.net/rfc/")
.s("ftp").h("ds.internic.net").p("/rfc/").z(); .s("ftp").h("ds.internic.net").p("/rfc/").z();

View File

@ -28,20 +28,22 @@
*/ */
import java.net.*; import java.net.*;
import java.util.ArrayList;
import java.util.List;
public class URIToURLTest { public class URIToURLTest {
public static void main(String args[]) throws Exception { public static void main(String args[]) throws Exception {
String[] uris = { List<String> uris = new ArrayList<>();
"http://jag:cafebabe@java.sun.com:94/b/c/d?q#g", uris.add("http://jag:cafebabe@java.sun.com:94/b/c/d?q#g");
"http://[1080:0:0:0:8:800:200C:417A]/index.html", uris.add("http://[1080:0:0:0:8:800:200C:417A]/index.html");
"http://a/b/c/d;p?q", uris.add("http://a/b/c/d;p?q");
"ftp://ftp.is.co.za/rfc/rfc1808.txt", uris.add("mailto:mduerst@ifi.unizh.ch");
"mailto:mduerst@ifi.unizh.ch", // opaque url uris.add("http:comp.infosystems.www.servers.unix");
"http:comp.infosystems.www.servers.unix" //opaque url if (hasFtp())
}; uris.add("ftp://ftp.is.co.za/rfc/rfc1808.txt");
for (int i = 0; i < uris.length; i++) { for (String uriStr : uris) {
URI uri = new URI(uris[i]); URI uri = new URI(uriStr);
URL url = uri.toURL(); URL url = uri.toURL();
String scheme = uri.getScheme(); String scheme = uri.getScheme();
boolean schemeCheck = scheme == null? url.getProtocol() == null : boolean schemeCheck = scheme == null? url.getProtocol() == null :
@ -111,4 +113,13 @@ public class URIToURLTest {
url.getRef()); url.getRef());
} }
} }
private static boolean hasFtp() {
try {
return new java.net.URL("ftp://") != null;
} catch (java.net.MalformedURLException x) {
System.out.println("FTP not supported by this runtime.");
return false;
}
}
} }

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2013 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -28,90 +28,55 @@
*/ */
import java.net.*; import java.net.*;
import java.util.ArrayList;
import java.util.List;
public class RequestProperties { public class RequestProperties {
static int failed;
public static void main (String args[]) throws Exception { public static void main (String args[]) throws Exception {
URL url0 = new URL ("http://foo.com/bar/"); List<String> urls = new ArrayList<>();
URL url1 = new URL ("file:/etc/passwd"); urls.add("http://foo.com/bar/");
URL url2 = new URL ("ftp://foo:bar@foobar.com/etc/passwd"); urls.add("jar:http://foo.com/bar.html!/foo/bar");
URL url3 = new URL ("jar:http://foo.com/bar.html!/foo/bar"); urls.add("file:/etc/passwd");
URLConnection urlc0 = url0.openConnection (); if (hasFtp())
URLConnection urlc1 = url1.openConnection (); urls.add("ftp://foo:bar@foobar.com/etc/passwd");
URLConnection urlc2 = url2.openConnection ();
URLConnection urlc3 = url3.openConnection (); for (String urlStr : urls)
int count = 0; test(new URL(urlStr));
String s = null;
try { if (failed != 0)
urlc0.setRequestProperty (null, null); throw new RuntimeException(failed + " errors") ;
System.out.println ("http: setRequestProperty (null,) did not throw NPE");
} catch (NullPointerException e) {
count ++;
}
try {
urlc0.addRequestProperty (null, null);
System.out.println ("http: addRequestProperty (null,) did not throw NPE");
} catch (NullPointerException e) {
count ++;
}
try {
urlc1.setRequestProperty (null, null);
System.out.println ("file: setRequestProperty (null,) did not throw NPE");
} catch (NullPointerException e) {
count ++;
}
try {
urlc1.addRequestProperty (null, null);
System.out.println ("file: addRequestProperty (null,) did not throw NPE");
} catch (NullPointerException e) {
count ++;
}
try {
urlc2.setRequestProperty (null, null);
System.out.println ("ftp: setRequestProperty (null,) did not throw NPE");
} catch (NullPointerException e) {
count ++;
}
try {
urlc2.addRequestProperty (null, null);
System.out.println ("ftp: addRequestProperty (null,) did not throw NPE");
} catch (NullPointerException e) {
count ++;
}
try {
urlc3.setRequestProperty (null, null);
System.out.println ("jar: setRequestProperty (null,) did not throw NPE");
} catch (NullPointerException e) {
count ++;
}
try {
urlc3.addRequestProperty (null, null);
System.out.println ("jar: addRequestProperty (null,) did not throw NPE");
} catch (NullPointerException e) {
count ++;
}
if (urlc0.getRequestProperty (null) != null) {
System.out.println ("http: getRequestProperty (null,) did not return null");
} else {
count ++;
}
if (urlc1.getRequestProperty (null) != null) {
System.out.println ("file: getRequestProperty (null,) did not return null");
} else {
count ++;
}
if (urlc2.getRequestProperty (null) != null) {
System.out.println ("ftp: getRequestProperty (null,) did not return null");
} else {
count ++;
}
if (urlc2.getRequestProperty (null) != null) {
System.out.println ("jar: getRequestProperty (null,) did not return null");
} else {
count ++;
} }
if (count != 12) { static void test(URL url) throws Exception {
throw new RuntimeException ((12 -count) + " errors") ; URLConnection urlc = url.openConnection();
try {
urlc.setRequestProperty(null, null);
System.out.println(url.getProtocol()
+ ": setRequestProperty(null,) did not throw NPE");
failed++;
} catch (NullPointerException e) { /* Expected */ }
try {
urlc.addRequestProperty(null, null);
System.out.println(url.getProtocol()
+ ": addRequestProperty(null,) did not throw NPE");
failed++;
} catch (NullPointerException e) { /* Expected */ }
if (urlc.getRequestProperty(null) != null) {
System.out.println(url.getProtocol()
+ ": getRequestProperty(null,) did not return null");
failed++;
}
}
private static boolean hasFtp() {
try {
return new java.net.URL("ftp://") != null;
} catch (java.net.MalformedURLException x) {
System.out.println("FTP not supported by this runtime.");
return false;
} }
} }
} }

View File

@ -27,8 +27,11 @@
* @summary Test URLConnection Request Proterties * @summary Test URLConnection Request Proterties
*/ */
import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
/** /**
* Part1: * Part1:
@ -45,28 +48,29 @@ public class RequestPropertyValues {
} }
public static void part1() throws Exception { public static void part1() throws Exception {
URL[] urls = { new URL("http://localhost:8088"), List<URL> urls = new ArrayList<>();
new URL("file:/etc/passwd"), urls.add(new URL("http://localhost:8088"));
new URL("ftp://foo:bar@foobar.com/etc/passwd"), urls.add(new URL("file:/etc/passwd"));
new URL("jar:http://foo.com/bar.html!/foo/bar") urls.add(new URL("jar:http://foo.com/bar.html!/foo/bar"));
}; if (hasFtp())
urls.add(new URL("ftp://foo:bar@foobar.com/etc/passwd"));
boolean failed = false; boolean failed = false;
for (int proto = 0; proto < urls.length; proto++) { for (URL url : urls) {
URLConnection uc = (URLConnection) urls[proto].openConnection(); URLConnection uc = url.openConnection();
try { try {
uc.setRequestProperty("TestHeader", null); uc.setRequestProperty("TestHeader", null);
} catch (NullPointerException npe) { } catch (NullPointerException npe) {
System.out.println("setRequestProperty is throwing NPE" + System.out.println("setRequestProperty is throwing NPE" +
" for url: " + urls[proto]); " for url: " + url);
failed = true; failed = true;
} }
try { try {
uc.addRequestProperty("TestHeader", null); uc.addRequestProperty("TestHeader", null);
} catch (NullPointerException npe) { } catch (NullPointerException npe) {
System.out.println("addRequestProperty is throwing NPE" + System.out.println("addRequestProperty is throwing NPE" +
" for url: " + urls[proto]); " for url: " + url);
failed = true; failed = true;
} }
} }
@ -110,4 +114,12 @@ public class RequestPropertyValues {
} }
} }
private static boolean hasFtp() {
try {
return new java.net.URL("ftp://") != null;
} catch (java.net.MalformedURLException x) {
System.out.println("FTP not supported by this runtime.");
return false;
}
}
} }

View File

@ -58,7 +58,6 @@ public class PBETest {
new File(NEW_KEYSTORE).delete(); new File(NEW_KEYSTORE).delete();
try {
KeyStore keystore = load(KEYSTORE_TYPE, KEYSTORE, PASSWORD); KeyStore keystore = load(KEYSTORE_TYPE, KEYSTORE, PASSWORD);
KeyStore.Entry entry = KeyStore.Entry entry =
keystore.getEntry(ALIAS, keystore.getEntry(ALIAS,
@ -73,30 +72,32 @@ public class PBETest {
new IvParameterSpec(IV)))); new IvParameterSpec(IV))));
System.out.println("Encrypted entry using: " + PBE_ALGO); System.out.println("Encrypted entry using: " + PBE_ALGO);
try (FileOutputStream outStream = new FileOutputStream(NEW_KEYSTORE)) {
System.out.println("Storing keystore to: " + NEW_KEYSTORE); System.out.println("Storing keystore to: " + NEW_KEYSTORE);
keystore2.store(new FileOutputStream(NEW_KEYSTORE), PASSWORD); keystore2.store(outStream, PASSWORD);
}
keystore2 = load(NEW_KEYSTORE_TYPE, NEW_KEYSTORE, PASSWORD); keystore2 = load(NEW_KEYSTORE_TYPE, NEW_KEYSTORE, PASSWORD);
entry = keystore2.getEntry(ALIAS, entry = keystore2.getEntry(ALIAS,
new KeyStore.PasswordProtection(PASSWORD)); new KeyStore.PasswordProtection(PASSWORD));
System.out.println("Retrieved entry named '" + ALIAS + "'"); System.out.println("Retrieved entry named '" + ALIAS + "'");
} finally {
new File(NEW_KEYSTORE).delete();
System.out.println("Deleted keystore: " + NEW_KEYSTORE);
}
} }
private static KeyStore load(String type, String path, char[] password) private static KeyStore load(String type, String path, char[] password)
throws Exception { throws Exception {
FileInputStream stream = null;
if (path != null) {
stream = new FileInputStream(path);
}
KeyStore keystore = KeyStore.getInstance(type); KeyStore keystore = KeyStore.getInstance(type);
if (path != null) {
try (FileInputStream inStream = new FileInputStream(path)) {
System.out.println("Loading keystore from: " + path); System.out.println("Loading keystore from: " + path);
keystore.load(stream, password); keystore.load(inStream, password);
System.out.println("Loaded keystore with " + keystore.size() +
" entries");
}
} else {
keystore.load(null, null);
}
return keystore; return keystore;
} }

View File

@ -22,7 +22,7 @@
*/ */
/** /**
* @test 4235519 8004212 * @test 4235519 8004212 8005394 8007298 8006295 8006315 8006530
* @summary tests java.util.Base64 * @summary tests java.util.Base64
*/ */
@ -109,6 +109,15 @@ public class TestBase64 {
// test return value from decode(ByteBuffer, ByteBuffer) // test return value from decode(ByteBuffer, ByteBuffer)
testDecBufRet(); testDecBufRet();
// test single-non-base64 character for mime decoding
testSingleNonBase64MimeDec();
// test decoding of unpadded data
testDecodeUnpadded();
// test mime decoding with ignored character after padding
testDecodeIgnoredAfterPadding();
} }
private static sun.misc.BASE64Encoder sunmisc = new sun.misc.BASE64Encoder(); private static sun.misc.BASE64Encoder sunmisc = new sun.misc.BASE64Encoder();
@ -295,6 +304,7 @@ public class TestBase64 {
checkNull(new Runnable() { public void run() { enc.encode(bb_null); }}); checkNull(new Runnable() { public void run() { enc.encode(bb_null); }});
checkNull(new Runnable() { public void run() { enc.encode(bb_null, ByteBuffer.allocate(10), 0); }}); checkNull(new Runnable() { public void run() { enc.encode(bb_null, ByteBuffer.allocate(10), 0); }});
checkNull(new Runnable() { public void run() { enc.encode(ByteBuffer.allocate(10), bb_null, 0); }}); checkNull(new Runnable() { public void run() { enc.encode(ByteBuffer.allocate(10), bb_null, 0); }});
checkNull(new Runnable() { public void run() { enc.wrap(null); }});
} }
private static void testNull(final Base64.Decoder dec) { private static void testNull(final Base64.Decoder dec) {
@ -305,6 +315,7 @@ public class TestBase64 {
checkNull(new Runnable() { public void run() { dec.decode(bb_null); }}); checkNull(new Runnable() { public void run() { dec.decode(bb_null); }});
checkNull(new Runnable() { public void run() { dec.decode(bb_null, ByteBuffer.allocate(10)); }}); checkNull(new Runnable() { public void run() { dec.decode(bb_null, ByteBuffer.allocate(10)); }});
checkNull(new Runnable() { public void run() { dec.decode(ByteBuffer.allocate(10), bb_null); }}); checkNull(new Runnable() { public void run() { dec.decode(ByteBuffer.allocate(10), bb_null); }});
checkNull(new Runnable() { public void run() { dec.wrap(null); }});
} }
private static interface Testable { private static interface Testable {
@ -354,6 +365,94 @@ public class TestBase64 {
} catch (IllegalArgumentException iae) {} } catch (IllegalArgumentException iae) {}
} }
private static void testDecodeIgnoredAfterPadding() throws Throwable {
for (byte nonBase64 : new byte[] {'#', '(', '!', '\\', '-', '_', '\n', '\r'}) {
byte[][] src = new byte[][] {
"A".getBytes("ascii"),
"AB".getBytes("ascii"),
"ABC".getBytes("ascii"),
"ABCD".getBytes("ascii"),
"ABCDE".getBytes("ascii")
};
Base64.Encoder encM = Base64.getMimeEncoder();
Base64.Decoder decM = Base64.getMimeDecoder();
Base64.Encoder enc = Base64.getEncoder();
Base64.Decoder dec = Base64.getDecoder();
for (int i = 0; i < src.length; i++) {
// decode(byte[])
byte[] encoded = encM.encode(src[i]);
encoded = Arrays.copyOf(encoded, encoded.length + 1);
encoded[encoded.length - 1] = nonBase64;
checkEqual(decM.decode(encoded), src[i], "Non-base64 char is not ignored");
try {
dec.decode(encoded);
throw new RuntimeException("No IAE for non-base64 char");
} catch (IllegalArgumentException iae) {}
// decode(ByteBuffer[], ByteBuffer[])
ByteBuffer encodedBB = ByteBuffer.wrap(encoded);
ByteBuffer decodedBB = ByteBuffer.allocate(100);
int ret = decM.decode(encodedBB, decodedBB);
byte[] buf = new byte[ret];
decodedBB.flip();
decodedBB.get(buf);
checkEqual(buf, src[i], "Non-base64 char is not ignored");
try {
encodedBB.rewind();
decodedBB.clear();
dec.decode(encodedBB, decodedBB);
throw new RuntimeException("No IAE for non-base64 char");
} catch (IllegalArgumentException iae) {}
// direct
encodedBB.rewind();
decodedBB = ByteBuffer.allocateDirect(100);
ret = decM.decode(encodedBB, decodedBB);
buf = new byte[ret];
decodedBB.flip();
decodedBB.get(buf);
checkEqual(buf, src[i], "Non-base64 char is not ignored");
try {
encodedBB.rewind();
decodedBB.clear();
dec.decode(encodedBB, decodedBB);
throw new RuntimeException("No IAE for non-base64 char");
} catch (IllegalArgumentException iae) {}
}
}
}
private static void testDecodeUnpadded() throws Throwable {
byte[] srcA = new byte[] { 'Q', 'Q' };
byte[] srcAA = new byte[] { 'Q', 'Q', 'E'};
Base64.Decoder dec = Base64.getDecoder();
byte[] ret = dec.decode(srcA);
if (ret[0] != 'A')
throw new RuntimeException("Decoding unpadding input A failed");
ret = dec.decode(srcAA);
if (ret[0] != 'A' && ret[1] != 'A')
throw new RuntimeException("Decoding unpadding input AA failed");
ret = new byte[10];
if (dec.wrap(new ByteArrayInputStream(srcA)).read(ret) != 1 &&
ret[0] != 'A')
throw new RuntimeException("Decoding unpadding input A from stream failed");
if (dec.wrap(new ByteArrayInputStream(srcA)).read(ret) != 2 &&
ret[0] != 'A' && ret[1] != 'A')
throw new RuntimeException("Decoding unpadding input AA from stream failed");
}
// single-non-base64-char should be ignored for mime decoding, but
// iae for basic decoding
private static void testSingleNonBase64MimeDec() throws Throwable {
for (String nonBase64 : new String[] {"#", "(", "!", "\\", "-", "_"}) {
if (Base64.getMimeDecoder().decode(nonBase64).length != 0) {
throw new RuntimeException("non-base64 char is not ignored");
}
try {
Base64.getDecoder().decode(nonBase64);
throw new RuntimeException("No IAE for single non-base64 char");
} catch (IllegalArgumentException iae) {}
}
}
private static void testDecBufRet() throws Throwable { private static void testDecBufRet() throws Throwable {
Random rnd = new java.util.Random(); Random rnd = new java.util.Random();

View File

@ -1103,6 +1103,15 @@ public class Basic$Type$ extends Basic {
test("%.5f", "1.99999", val); test("%.5f", "1.99999", val);
test("%.6f", "1.999990", val); test("%.6f", "1.999990", val);
val = new BigDecimal(0.9996);
test("%.0f", "1", val);
test("%.1f", "1.0", val);
test("%.2f", "1.00", val);
test("%.3f", "1.000", val);
test("%.4f", "0.9996", val);
test("%.5f", "0.99960", val);
test("%.6f", "0.999600", val);
#end[BigDecimal] #end[BigDecimal]
#if[float] #if[float]

View File

@ -1102,6 +1102,15 @@ public class BasicBigDecimal extends Basic {
test("%.4f", "2.0000", val); test("%.4f", "2.0000", val);
test("%.5f", "1.99999", val); test("%.5f", "1.99999", val);
test("%.6f", "1.999990", val); test("%.6f", "1.999990", val);
val = new BigDecimal(0.9996);
test("%.0f", "1", val);
test("%.1f", "1.0", val);
test("%.2f", "1.00", val);
test("%.3f", "1.000", val);
test("%.4f", "0.9996", val);
test("%.5f", "0.99960", val);
test("%.6f", "0.999600", val);

View 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);
}
}
}

View File

@ -31,6 +31,7 @@
import com.sun.jmx.remote.internal.ServerNotifForwarder; import com.sun.jmx.remote.internal.ServerNotifForwarder;
import java.io.IOException; import java.io.IOException;
import java.lang.management.ManagementFactory; import java.lang.management.ManagementFactory;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
@ -86,20 +87,26 @@ public class DeadListenerTest {
Map<ObjectName, Set<?>> listenerMap = (Map<ObjectName, Set<?>>) listenerMapF.get(serverNotifForwarder); Map<ObjectName, Set<?>> listenerMap = (Map<ObjectName, Set<?>>) listenerMapF.get(serverNotifForwarder);
assertTrue("Server listenerMap initially empty", mapWithoutKey(listenerMap, delegateName).isEmpty()); assertTrue("Server listenerMap initially empty", mapWithoutKey(listenerMap, delegateName).isEmpty());
CountListener count1 = new CountListener(); final AtomicInteger count1Val = new AtomicInteger();
CountListener count1 = new CountListener(count1Val);
mbsc.addNotificationListener(name, count1, null, null); mbsc.addNotificationListener(name, count1, null, null);
WeakReference<CountListener> count1Ref = new WeakReference<>(count1);
count1 = null;
CountListener count2 = new CountListener(); final AtomicInteger count2Val = new AtomicInteger();
CountListener count2 = new CountListener(count2Val);
NotificationFilterSupport dummyFilter = new NotificationFilterSupport(); NotificationFilterSupport dummyFilter = new NotificationFilterSupport();
dummyFilter.enableType(""); dummyFilter.enableType("");
mbsc.addNotificationListener(name, count2, dummyFilter, "noddy"); mbsc.addNotificationListener(name, count2, dummyFilter, "noddy");
WeakReference<CountListener> count2Ref = new WeakReference<>(count2);
count2 = null;
assertTrue("One entry in listenerMap for two listeners on same MBean", mapWithoutKey(listenerMap, delegateName).size() == 1); assertTrue("One entry in listenerMap for two listeners on same MBean", mapWithoutKey(listenerMap, delegateName).size() == 1);
Set<?> set = listenerMap.get(name); Set<?> set = listenerMap.get(name);
assertTrue("Set in listenerMap for MBean has two elements", set != null && set.size() == 2); assertTrue("Set in listenerMap for MBean has two elements", set != null && set.size() == 2);
assertTrue("Initial value of count1 == 0", count1.count() == 0); assertTrue("Initial value of count1 == 0", count1Val.get() == 0);
assertTrue("Initial value of count2 == 0", count2.count() == 0); assertTrue("Initial value of count2 == 0", count2Val.get() == 0);
Notification notif = new Notification("type", name, 0); Notification notif = new Notification("type", name, 0);
@ -107,11 +114,11 @@ public class DeadListenerTest {
// Make sure notifs are working normally. // Make sure notifs are working normally.
long deadline = System.currentTimeMillis() + 2000; long deadline = System.currentTimeMillis() + 2000;
while ((count1.count() != 1 || count2.count() != 1) && System.currentTimeMillis() < deadline) { while ((count1Val.get() != 1 || count2Val.get() != 1) && System.currentTimeMillis() < deadline) {
Thread.sleep(10); Thread.sleep(10);
} }
assertTrue("New value of count1 == 1", count1.count() == 1); assertTrue("New value of count1 == 1", count1Val.get() == 1);
assertTrue("Initial value of count2 == 1", count2.count() == 1); assertTrue("Initial value of count2 == 1", count2Val.get() == 1);
// Make sure that removing a nonexistent listener from an existent MBean produces ListenerNotFoundException // Make sure that removing a nonexistent listener from an existent MBean produces ListenerNotFoundException
CountListener count3 = new CountListener(); CountListener count3 = new CountListener();
@ -136,28 +143,29 @@ public class DeadListenerTest {
mbs.unregisterMBean(name); mbs.unregisterMBean(name);
mbean.sendNotification(notif); mbean.sendNotification(notif);
Thread.sleep(200); Thread.sleep(200);
assertTrue("New value of count1 == 1", count1.count() == 1);
assertTrue("Initial value of count2 == 1", count2.count() == 1); assertTrue("New value of count1 == 1", count1Val.get() == 1);
assertTrue("Initial value of count2 == 1", count2Val.get() == 1);
// wait for the listener cleanup to take place upon processing notifications
int countdown = 50; // waiting max. 5 secs
while (countdown-- > 0 &&
(count1Ref.get() != null ||
count2Ref.get() != null)) {
System.gc();
Thread.sleep(100);
System.gc();
}
// listener has been removed or the wait has timed out
assertTrue("count1 notification listener has not been cleaned up", count1Ref.get() == null);
assertTrue("count2 notification listener has not been cleaned up", count2Ref.get() == null);
// Check that there is no trace of the listeners any more in ServerNotifForwarder.listenerMap. // Check that there is no trace of the listeners any more in ServerNotifForwarder.listenerMap.
// THIS DEPENDS ON JMX IMPLEMENTATION DETAILS. // THIS DEPENDS ON JMX IMPLEMENTATION DETAILS.
// If the JMX implementation changes, the code here may have to change too. // If the JMX implementation changes, the code here may have to change too.
Set<?> setForUnreg = listenerMap.get(name); Set<?> setForUnreg = listenerMap.get(name);
assertTrue("No trace of unregistered MBean: " + setForUnreg, setForUnreg == null); assertTrue("No trace of unregistered MBean: " + setForUnreg, setForUnreg == null);
// Remove attempts should fail.
try {
mbsc.removeNotificationListener(name, count1);
assertTrue("Remove of count1 listener should have failed", false);
} catch (ListenerNotFoundException e) {
// OK: expected
}
try {
mbsc.removeNotificationListener(name, count2, dummyFilter, "noddy");
assertTrue("Remove of count2 listener should have failed", false);
} catch (ListenerNotFoundException e) {
// OK: expected
}
} }
private static <K, V> Map<K, V> mapWithoutKey(Map<K, V> map, K key) { private static <K, V> Map<K, V> mapWithoutKey(Map<K, V> map, K key) {
@ -173,6 +181,10 @@ public class DeadListenerTest {
public static class CountListener implements NotificationListener { public static class CountListener implements NotificationListener {
final AtomicInteger count; final AtomicInteger count;
public CountListener(AtomicInteger i) {
count = i;
}
public CountListener() { public CountListener() {
this.count = new AtomicInteger(); this.count = new AtomicInteger();
} }

View 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);
}
}
}

View 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");
}
}

View 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

View 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);
}
}
}

View File

@ -161,8 +161,18 @@ public class ProxyTest {
} }
} }
private static boolean hasFtp() {
try {
return new java.net.URL("ftp://") != null;
} catch (java.net.MalformedURLException x) {
System.out.println("FTP not supported by this runtime.");
return false;
}
}
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
ProxyTest test = new ProxyTest(); if (hasFtp())
new ProxyTest();
} }
public ProxyTest() throws Exception { public ProxyTest() throws Exception {

Some files were not shown because too many files have changed in this diff Show More