--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/netbeans/common/architectures/arch-x86_64.properties Tue Feb 05 11:11:53 2013 -0800
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/netbeans/common/architectures/name-Macosx.properties Tue Feb 05 11:11:53 2013 -0800
@@ -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
--- a/jdk/make/netbeans/common/java-data-native.ent Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/make/netbeans/common/java-data-native.ent Tue Feb 05 11:11:53 2013 -0800
@@ -39,11 +39,11 @@
<classpath mode="boot">${bootstrap.jdk}/jre/lib/rt.jar</classpath>
<built-to>${root}/build/${platform}-${arch}/classes</built-to>
<javadoc-built-to>${root}/build/${platform}-${arch}/docs/api</javadoc-built-to>
- <source-level>1.7</source-level>
+ <source-level>1.8</source-level>
</compilation-unit>
<compilation-unit>
<package-root>${root}/test</package-root>
<unit-tests/>
- <source-level>1.7</source-level>
+ <source-level>1.8</source-level>
</compilation-unit>
</java-data>
--- a/jdk/make/netbeans/common/java-data-no-native.ent Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/make/netbeans/common/java-data-no-native.ent Tue Feb 05 11:11:53 2013 -0800
@@ -37,11 +37,11 @@
<classpath mode="boot">${bootstrap.jdk}/jre/lib/rt.jar</classpath>
<built-to>${root}/build/${platform}-${arch}/classes</built-to>
<javadoc-built-to>${root}/build/${platform}-${arch}/docs/api</javadoc-built-to>
- <source-level>1.7</source-level>
+ <source-level>1.8</source-level>
</compilation-unit>
<compilation-unit>
<package-root>${root}/test</package-root>
<unit-tests/>
- <source-level>1.7</source-level>
+ <source-level>1.8</source-level>
</compilation-unit>
</java-data>
--- a/jdk/make/netbeans/common/make.xml Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/make/netbeans/common/make.xml Tue Feb 05 11:11:53 2013 -0800
@@ -33,7 +33,7 @@
<project name="make" basedir="..">
- <target name="-make.init" depends="-init,-pre-init.linux,-pre-init.solaris,-pre-init.windows">
+ <target name="-make.init" depends="-init,-pre-init.linux,-pre-init.macosx,-pre-init.solaris,-pre-init.windows,-pre-init.macosx">
<property name="make.options" value=""/> <!-- default, can be overridden per user or per project -->
</target>
@@ -42,6 +42,11 @@
<property name="make" value="make"/>
</target>
+ <target name="-pre-init.macosx" if="os.macosx">
+ <property name="platform" value="macosx"/>
+ <property name="make" value="make"/>
+ </target>
+
<target name="-pre-init.solaris" if="os.solaris">
<property name="platform" value="solaris"/>
<property name="make" value="gmake"/>
--- a/jdk/make/netbeans/common/shared.xml Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/make/netbeans/common/shared.xml Tue Feb 05 11:11:53 2013 -0800
@@ -85,6 +85,9 @@
<property name="includes" value="(nothing)"/>
<property name="excludes" value=""/>
<property name="javadoc.dir" location="${build.dir}/javadoc/${ant.project.name}"/>
+ <condition property="os.macosx">
+ <os family="mac"/>
+ </condition>
<condition property="os.linux">
<os name="linux"/>
</condition>
@@ -126,10 +129,6 @@
<javac srcdir="@{srcdir}" includes="@{includes}" excludes="@{excludes}" sourcepath=""
destdir="@{classesdir}" fork="true" executable="${bootstrap.javac}"
debug="${javac.debug}" debuglevel="${javac.debuglevel}">
- <compilerarg value="-source"/>
- <compilerarg value="1.5"/>
- <compilerarg value="-target"/>
- <compilerarg value="1.6"/> <!-- for usability of JDK 6 as snapshot; change to 1.7 when JSR 294 put back -->
<!-- Mandatory for compiling partial JDK sources against a snapshot; should NEVER be used for any other purpose: -->
<compilerarg value="-XDignore.symbol.file=true"/>
<compilerarg line="${javac.options}"/>
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java Tue Feb 05 11:11:53 2013 -0800
@@ -1287,19 +1287,24 @@
if (localRef == 0) {
globalRef = null; // N.B. global null reference is -1
} else {
- globalRef = holder.getCPMap()[localRef];
- if (e.refKind == CONSTANT_Signature
+ Entry[] cpMap = holder.getCPMap();
+ globalRef = (localRef >= 0 && localRef < cpMap.length
+ ? cpMap[localRef]
+ : null);
+ byte tag = e.refKind;
+ if (globalRef != null && tag == CONSTANT_Signature
&& globalRef.getTag() == CONSTANT_Utf8) {
// Cf. ClassReader.readSignatureRef.
String typeName = globalRef.stringValue();
globalRef = ConstantPool.getSignatureEntry(typeName);
- } else if (e.refKind == CONSTANT_FieldSpecific) {
- assert(globalRef.getTag() >= CONSTANT_Integer);
- assert(globalRef.getTag() <= CONSTANT_String ||
- globalRef.getTag() >= CONSTANT_MethodHandle);
- assert(globalRef.getTag() <= CONSTANT_MethodType);
- } else if (e.refKind < CONSTANT_GroupFirst) {
- assert(e.refKind == globalRef.getTag());
+ }
+ String got = (globalRef == null
+ ? "invalid CP index"
+ : "type=" + ConstantPool.tagName(globalRef.tag));
+ if (globalRef == null || !globalRef.tagMatches(tag)) {
+ throw new IllegalArgumentException(
+ "Bad constant, expected type=" +
+ ConstantPool.tagName(tag) + " got " + got);
}
}
out.putRef(bandIndex, globalRef);
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -54,6 +54,7 @@
Package pkg;
Class cls;
long inPos;
+ long constantPoolLimit = -1;
DataInputStream in;
Map<Attribute.Layout, Attribute> attrDefs;
Map<Attribute.Layout, String> attrCommands;
@@ -117,15 +118,33 @@
private Entry readRef(byte tag) throws IOException {
Entry e = readRef();
- assert(e != null);
assert(!(e instanceof UnresolvedEntry));
- assert(e.tagMatches(tag));
+ checkTag(e, tag);
return e;
}
+ /** Throw a ClassFormatException if the entry does not match the expected tag type. */
+ private Entry checkTag(Entry e, byte tag) throws ClassFormatException {
+ if (e == null || !e.tagMatches(tag)) {
+ String where = (inPos == constantPoolLimit
+ ? " in constant pool"
+ : " at pos: " + inPos);
+ String got = (e == null
+ ? "null CP index"
+ : "type=" + ConstantPool.tagName(e.tag));
+ throw new ClassFormatException("Bad constant, expected type=" +
+ ConstantPool.tagName(tag) +
+ " got "+ got + ", in File: " + cls.file.nameString + where);
+ }
+ return e;
+ }
+ private Entry checkTag(Entry e, byte tag, boolean nullOK) throws ClassFormatException {
+ return nullOK && e == null ? null : checkTag(e, tag);
+ }
+
private Entry readRefOrNull(byte tag) throws IOException {
Entry e = readRef();
- assert(e == null || e.tagMatches(tag));
+ checkTag(e, tag, true);
return e;
}
@@ -143,8 +162,10 @@
private SignatureEntry readSignatureRef() throws IOException {
// The class file stores a Utf8, but we want a Signature.
- Entry e = readRef(CONSTANT_Utf8);
- return ConstantPool.getSignatureEntry(e.stringValue());
+ Entry e = readRef(CONSTANT_Signature);
+ return (e != null && e.getTag() == CONSTANT_Utf8)
+ ? ConstantPool.getSignatureEntry(e.stringValue())
+ : (SignatureEntry) e;
}
void read() throws IOException {
@@ -279,6 +300,7 @@
" at pos: " + inPos);
}
}
+ constantPoolLimit = inPos;
// Fix up refs, which might be out of order.
while (fptr > 0) {
@@ -311,25 +333,25 @@
case CONSTANT_Fieldref:
case CONSTANT_Methodref:
case CONSTANT_InterfaceMethodref:
- ClassEntry mclass = (ClassEntry) cpMap[ref];
- DescriptorEntry mdescr = (DescriptorEntry) cpMap[ref2];
+ ClassEntry mclass = (ClassEntry) checkTag(cpMap[ref], CONSTANT_Class);
+ DescriptorEntry mdescr = (DescriptorEntry) checkTag(cpMap[ref2], CONSTANT_NameandType);
cpMap[cpi] = ConstantPool.getMemberEntry((byte)tag, mclass, mdescr);
break;
case CONSTANT_NameandType:
- Utf8Entry mname = (Utf8Entry) cpMap[ref];
- Utf8Entry mtype = (Utf8Entry) cpMap[ref2];
+ Utf8Entry mname = (Utf8Entry) checkTag(cpMap[ref], CONSTANT_Utf8);
+ Utf8Entry mtype = (Utf8Entry) checkTag(cpMap[ref2], CONSTANT_Signature);
cpMap[cpi] = ConstantPool.getDescriptorEntry(mname, mtype);
break;
case CONSTANT_MethodType:
- cpMap[cpi] = ConstantPool.getMethodTypeEntry((Utf8Entry) cpMap[ref]);
+ cpMap[cpi] = ConstantPool.getMethodTypeEntry((Utf8Entry) checkTag(cpMap[ref], CONSTANT_Signature));
break;
case CONSTANT_MethodHandle:
byte refKind = (byte)(-1 ^ ref);
- MemberEntry memRef = (MemberEntry) cpMap[ref2];
+ MemberEntry memRef = (MemberEntry) checkTag(cpMap[ref2], CONSTANT_AnyMember);
cpMap[cpi] = ConstantPool.getMethodHandleEntry(refKind, memRef);
break;
case CONSTANT_InvokeDynamic:
- DescriptorEntry idescr = (DescriptorEntry) cpMap[ref2];
+ DescriptorEntry idescr = (DescriptorEntry) checkTag(cpMap[ref2], CONSTANT_NameandType);
cpMap[cpi] = new UnresolvedEntry((byte)tag, (-1 ^ ref), idescr);
// Note that ref must be resolved later, using the BootstrapMethods attribute.
break;
@@ -541,7 +563,8 @@
code.max_locals = readUnsignedShort();
code.bytes = new byte[readInt()];
in.readFully(code.bytes);
- Instruction.opcodeChecker(code.bytes);
+ Entry[] cpMap = cls.getCPMap();
+ Instruction.opcodeChecker(code.bytes, cpMap);
int nh = readUnsignedShort();
code.setHandlerCount(nh);
for (int i = 0; i < nh; i++) {
@@ -559,7 +582,7 @@
MethodHandleEntry bsmRef = (MethodHandleEntry) readRef(CONSTANT_MethodHandle);
Entry[] argRefs = new Entry[readUnsignedShort()];
for (int j = 0; j < argRefs.length; j++) {
- argRefs[j] = readRef();
+ argRefs[j] = readRef(CONSTANT_LoadableValue);
}
bsms[i] = ConstantPool.getBootstrapMethodEntry(bsmRef, argRefs);
}
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -243,8 +243,32 @@
return tag == CONSTANT_Double || tag == CONSTANT_Long;
}
- public final boolean tagMatches(int tag) {
- return (this.tag == tag);
+ public final boolean tagMatches(int matchTag) {
+ if (tag == matchTag)
+ return true;
+ byte[] allowedTags;
+ switch (matchTag) {
+ case CONSTANT_All:
+ return true;
+ case CONSTANT_Signature:
+ return tag == CONSTANT_Utf8; // format check also?
+ case CONSTANT_LoadableValue:
+ allowedTags = LOADABLE_VALUE_TAGS;
+ break;
+ case CONSTANT_AnyMember:
+ allowedTags = ANY_MEMBER_TAGS;
+ break;
+ case CONSTANT_FieldSpecific:
+ allowedTags = FIELD_SPECIFIC_TAGS;
+ break;
+ default:
+ return false;
+ }
+ for (byte b : allowedTags) {
+ if (b == tag)
+ return true;
+ }
+ return false;
}
public String toString() {
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -647,7 +647,7 @@
}
}
- public static void opcodeChecker(byte[] code) throws FormatException {
+ public static void opcodeChecker(byte[] code, ConstantPool.Entry[] cpMap) throws FormatException {
Instruction i = at(code, 0);
while (i != null) {
int opcode = i.getBC();
@@ -655,6 +655,16 @@
String message = "illegal opcode: " + opcode + " " + i;
throw new FormatException(message);
}
+ ConstantPool.Entry e = i.getCPRef(cpMap);
+ if (e != null) {
+ byte tag = i.getCPTag();
+ if (!e.tagMatches(tag)) {
+ String message = "illegal reference, expected type=" +
+ ConstantPool.tagName(tag) + ": " +
+ i.toString(cpMap);
+ throw new FormatException(message);
+ }
+ }
i = i.next();
}
}
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java Tue Feb 05 11:11:53 2013 -0800
@@ -1618,6 +1618,16 @@
bc_which = null;
assert(false);
}
+ if (ref != null && bc_which.index != null && !bc_which.index.contains(ref)) {
+ // Crash and burn with a complaint if there are funny
+ // references for this bytecode instruction.
+ // Example: invokestatic of a CONSTANT_InterfaceMethodref.
+ String complaint = code.getMethod() +
+ " contains a bytecode " + i +
+ " with an unsupported constant reference; please use the pass-file option on this class.";
+ Utils.log.warning(complaint);
+ throw new IOException(complaint);
+ }
bc_codes.putByte(vbc);
bc_which.putRef(ref);
// handle trailing junk
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -180,6 +180,15 @@
}
unknownAttrCommand = uaMode.intern();
}
+ final String classFormatCommand;
+ {
+ String fmtMode = props.getProperty(Utils.CLASS_FORMAT_ERROR, Pack200.Packer.PASS);
+ if (!(Pack200.Packer.PASS.equals(fmtMode) ||
+ Pack200.Packer.ERROR.equals(fmtMode))) {
+ throw new RuntimeException("Bad option: " + Utils.CLASS_FORMAT_ERROR + " = " + fmtMode);
+ }
+ classFormatCommand = fmtMode.intern();
+ }
final Map<Attribute.Layout, Attribute> attrDefs;
final Map<Attribute.Layout, String> attrCommands;
@@ -505,8 +514,7 @@
}
} else if (ioe instanceof ClassReader.ClassFormatException) {
ClassReader.ClassFormatException ce = (ClassReader.ClassFormatException) ioe;
- // %% TODO: Do we invent a new property for this or reuse %%
- if (unknownAttrCommand.equals(Pack200.Packer.PASS)) {
+ if (classFormatCommand.equals(Pack200.Packer.PASS)) {
Utils.log.info(ce.toString());
Utils.log.warning(message + " unknown class format: " +
fname);
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PropMap.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PropMap.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -112,6 +112,11 @@
// Pass through files with unrecognized attributes by default.
props.put(Pack200.Packer.UNKNOWN_ATTRIBUTE, Pack200.Packer.PASS);
+ // Pass through files with unrecognized format by default, also
+ // allow system property to be set
+ props.put(Utils.CLASS_FORMAT_ERROR,
+ System.getProperty(Utils.CLASS_FORMAT_ERROR, Pack200.Packer.PASS));
+
// Default effort is 5, midway between 1 and 9.
props.put(Pack200.Packer.EFFORT, "5");
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -122,6 +122,12 @@
*/
static final String PACK_ZIP_ARCHIVE_MARKER_COMMENT = "PACK200";
+ /*
+ * behaviour when we hit a class format error, but not necessarily
+ * an unknown attribute, by default it is allowed to PASS.
+ */
+ static final String CLASS_FORMAT_ERROR = COM_PREFIX+"class.format.error";
+
// Keep a TLS point to the global data and environment.
// This makes it simpler to supply environmental options
// to the engine code, especially the native code.
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java Tue Feb 05 11:11:53 2013 -0800
@@ -50,8 +50,6 @@
import javax.management.NotCompliantMBeanException;
import com.sun.jmx.remote.util.EnvHelp;
-import java.beans.BeanInfo;
-import java.beans.PropertyDescriptor;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import javax.management.AttributeNotFoundException;
--- a/jdk/src/share/classes/java/lang/Class.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/java/lang/Class.java Tue Feb 05 11:11:53 2013 -0800
@@ -29,12 +29,14 @@
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Member;
import java.lang.reflect.Field;
+import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.AnnotatedType;
import java.lang.ref.SoftReference;
import java.io.InputStream;
import java.io.ObjectStreamField;
@@ -2325,6 +2327,11 @@
// Annotations handling
private native byte[] getRawAnnotations();
+ // Since 1.8
+ native byte[] getRawTypeAnnotations();
+ static byte[] getExecutableTypeAnnotationBytes(Executable ex) {
+ return getReflectionFactory().getExecutableTypeAnnotationBytes(ex);
+ }
native ConstantPool getConstantPool();
@@ -3068,21 +3075,12 @@
* @throws NullPointerException {@inheritDoc}
* @since 1.5
*/
+ @SuppressWarnings("unchecked")
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
Objects.requireNonNull(annotationClass);
initAnnotationsIfNecessary();
- return AnnotationSupport.getOneAnnotation(annotations, annotationClass);
- }
-
- /**
- * @throws NullPointerException {@inheritDoc}
- * @since 1.5
- */
- public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
- Objects.requireNonNull(annotationClass);
-
- return getAnnotation(annotationClass) != null;
+ return (A) annotations.get(annotationClass);
}
/**
@@ -3101,18 +3099,19 @@
*/
public Annotation[] getAnnotations() {
initAnnotationsIfNecessary();
- return AnnotationSupport.unpackToArray(annotations);
+ return AnnotationParser.toArray(annotations);
}
/**
* @throws NullPointerException {@inheritDoc}
* @since 1.8
*/
+ @SuppressWarnings("unchecked")
public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) {
Objects.requireNonNull(annotationClass);
initAnnotationsIfNecessary();
- return AnnotationSupport.getOneAnnotation(declaredAnnotations, annotationClass);
+ return (A) declaredAnnotations.get(annotationClass);
}
/**
@@ -3131,17 +3130,7 @@
*/
public Annotation[] getDeclaredAnnotations() {
initAnnotationsIfNecessary();
- return AnnotationSupport.unpackToArray(declaredAnnotations);
- }
-
- /** Returns one "directly" present annotation or null */
- <A extends Annotation> A getDirectDeclaredAnnotation(Class<A> annotationClass) {
- Objects.requireNonNull(annotationClass);
-
- initAnnotationsIfNecessary();
- @SuppressWarnings("unchecked") // TODO check safe
- A ret = (A)declaredAnnotations.get(annotationClass);
- return ret;
+ return AnnotationParser.toArray(declaredAnnotations);
}
// Annotations cache
@@ -3196,4 +3185,53 @@
* Maintained by the ClassValue class.
*/
transient ClassValue.ClassValueMap classValueMap;
+
+ /**
+ * Returns an AnnotatedType object that represents the use of a type to specify
+ * the superclass of the entity represented by this Class. (The <em>use</em> of type
+ * Foo to specify the superclass in '... extends Foo' is distinct from the
+ * <em>declaration</em> of type Foo.)
+ *
+ * If this Class represents a class type whose declaration does not explicitly
+ * indicate an annotated superclass, the return value is null.
+ *
+ * If this Class represents either the Object class, an interface type, an
+ * array type, a primitive type, or void, the return value is null.
+ *
+ * @since 1.8
+ */
+ public AnnotatedType getAnnotatedSuperclass() {
+ return TypeAnnotationParser.buildAnnotatedSuperclass(getRawTypeAnnotations(), getConstantPool(), this);
}
+
+ /**
+ * Returns an array of AnnotatedType objects that represent the use of types to
+ * specify superinterfaces of the entity represented by this Class. (The <em>use</em>
+ * of type Foo to specify a superinterface in '... implements Foo' is
+ * distinct from the <em>declaration</em> of type Foo.)
+ *
+ * If this Class represents a class, the return value is an array
+ * containing objects representing the uses of interface types to specify
+ * interfaces implemented by the class. The order of the objects in the
+ * array corresponds to the order of the interface types used in the
+ * 'implements' clause of the declaration of this Class.
+ *
+ * If this Class represents an interface, the return value is an array
+ * containing objects representing the uses of interface types to specify
+ * interfaces directly extended by the interface. The order of the objects in
+ * the array corresponds to the order of the interface types used in the
+ * 'extends' clause of the declaration of this Class.
+ *
+ * If this Class represents a class or interface whose declaration does not
+ * explicitly indicate any annotated superinterfaces, the return value is an
+ * array of length 0.
+ *
+ * If this Class represents either the Object class, an array type, a
+ * primitive type, or void, the return value is an array of length 0.
+ *
+ * @since 1.8
+ */
+ public AnnotatedType[] getAnnotatedInterfaces() {
+ return TypeAnnotationParser.buildAnnotatedInterfaces(getRawTypeAnnotations(), getConstantPool(), this);
+ }
+}
--- a/jdk/src/share/classes/java/lang/Double.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/java/lang/Double.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -289,7 +289,7 @@
return Double.toString(d);
else {
// Initialized to maximum size of output.
- StringBuffer answer = new StringBuffer(24);
+ StringBuilder answer = new StringBuilder(24);
if (Math.copySign(1.0, d) == -1.0) // value is negative,
answer.append("-"); // so append sign info
@@ -300,8 +300,7 @@
if(d == 0.0) {
answer.append("0.0p0");
- }
- else {
+ } else {
boolean subnormal = (d < DoubleConsts.MIN_NORMAL);
// Isolate significand bits and OR in a high-order bit
@@ -324,13 +323,14 @@
"0":
signif.replaceFirst("0{1,12}$", ""));
+ answer.append('p');
// If the value is subnormal, use the E_min exponent
// value for double; otherwise, extract and report d's
// exponent (the representation of a subnormal uses
// E_min -1).
- answer.append("p" + (subnormal ?
- DoubleConsts.MIN_EXPONENT:
- Math.getExponent(d) ));
+ answer.append(subnormal ?
+ DoubleConsts.MIN_EXPONENT:
+ Math.getExponent(d));
}
return answer.toString();
}
--- a/jdk/src/share/classes/java/lang/Package.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/java/lang/Package.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -387,15 +387,6 @@
/**
* @throws NullPointerException {@inheritDoc}
- * @since 1.5
- */
- public boolean isAnnotationPresent(
- Class<? extends Annotation> annotationClass) {
- return getPackageInfo().isAnnotationPresent(annotationClass);
- }
-
- /**
- * @throws NullPointerException {@inheritDoc}
* @since 1.8
*/
public <A extends Annotation> A[] getAnnotations(Class<A> annotationClass) {
--- a/jdk/src/share/classes/java/lang/System.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/java/lang/System.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
package java.lang;
import java.io.*;
-import java.lang.annotation.Annotation;
+import java.lang.reflect.Executable;
import java.util.Properties;
import java.util.PropertyPermission;
import java.util.StringTokenizer;
@@ -1196,8 +1196,11 @@
public AnnotationType getAnnotationType(Class<?> klass) {
return klass.getAnnotationType();
}
- public <A extends Annotation> A getDirectDeclaredAnnotation(Class<?> klass, Class<A> anno) {
- return klass.getDirectDeclaredAnnotation(anno);
+ public byte[] getRawClassTypeAnnotations(Class<?> klass) {
+ return klass.getRawTypeAnnotations();
+ }
+ public byte[] getRawExecutableTypeAnnotations(Executable executable) {
+ return Class.getExecutableTypeAnnotationBytes(executable);
}
public <E extends Enum<E>>
E[] getEnumConstantsShared(Class<E> klass) {
--- a/jdk/src/share/classes/java/lang/annotation/ContainedBy.java Tue Feb 05 11:10:07 2013 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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();
-}
--- a/jdk/src/share/classes/java/lang/annotation/ContainerFor.java Tue Feb 05 11:10:07 2013 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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();
-}
--- a/jdk/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,10 +27,9 @@
import java.util.Objects;
/**
- * Thrown to indicate that an annotation type whose declaration is
- * (meta-)annotated with a {@link ContainerFor} annotation is not, in
- * fact, the <em>containing annotation type of the type named by {@link
- * ContainerFor}</em>.
+ * Thrown to indicate that an annotation type expected to act as a
+ * container for another annotation type by virture of an @Repeatable
+ * annotation, does not act as a container.
*
* @see java.lang.reflect.AnnotatedElement
* @since 1.8
--- a/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java Tue Feb 05 11:11:53 2013 -0800
@@ -182,14 +182,6 @@
/**
* @throws NullPointerException {@inheritDoc}
- * @since 1.5
- */
- public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
- return getAnnotation(annotationClass) != null;
- }
-
- /**
- * @throws NullPointerException {@inheritDoc}
* @since 1.8
*/
public <T extends Annotation> T[] getAnnotations(Class<T> annotationClass) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedArrayType.java Tue Feb 05 11:11:53 2013 -0800
@@ -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();
+}
--- a/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,24 @@
* arrays returned by accessors for array-valued enum members; it will
* have no affect on the arrays returned to other callers.
*
+ * <p>An annotation A is <em>directly present</em> on an element E if the
+ * RuntimeVisibleAnnotations or RuntimeVisibleParameterAnnotations attribute
+ * associated with E either:
+ * <ul>
+ * <li>contains A; or
+ * <li>for invocations of get[Declared]Annotations(Class<T>),
+ * contains A or exactly one annotation C whose type is the containing
+ * annotation type of A's type (JLS 9.6) and whose value element contains A
+ * </ul>
+ *
+ * <p>An annotation A is <em>present</em> on an element E if either:
+ * <ul>
+ * <li>A is <em>directly present</em> on E; or
+ * <li>There are no annotations of A's type which are <em>directly present</em>
+ * on E, and E is a class, and A's type is inheritable (JLS 9.6.3.3), and A is
+ * present on the superclass of E
+ * </ul>
+ *
* <p>If an annotation returned by a method in this interface contains
* (directly or indirectly) a {@link Class}-valued member referring to
* a class that is not accessible in this VM, attempting to read the class
@@ -50,7 +68,7 @@
* containing annotation type of T will result in an
* InvalidContainerAnnotationError.
*
- * <p>Finally, Attempting to read a member whose definition has evolved
+ * <p>Finally, attempting to read a member whose definition has evolved
* incompatibly will result in a {@link
* java.lang.annotation.AnnotationTypeMismatchException} or an
* {@link java.lang.annotation.IncompleteAnnotationException}.
@@ -70,6 +88,12 @@
* is present on this element, else false. This method
* is designed primarily for convenient access to marker annotations.
*
+ * <p>The truth value returned by this method is equivalent to:
+ * {@code getAnnotation(annotationClass) != null}
+ *
+ * <p>The body of the default method is specified to be the code
+ * above.
+ *
* @param annotationClass the Class object corresponding to the
* annotation type
* @return true if an annotation for the specified annotation
@@ -77,7 +101,9 @@
* @throws NullPointerException if the given annotation class is null
* @since 1.5
*/
- boolean isAnnotationPresent(Class<? extends Annotation> annotationClass);
+ default boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
+ return getAnnotation(annotationClass) != null;
+ }
/**
* Returns this element's annotation for the specified type if
@@ -110,12 +136,15 @@
<T extends Annotation> T[] getAnnotations(Class<T> annotationClass);
/**
- * Returns all annotations present on this element. (Returns an array
- * of length zero if this element has no annotations.) The caller of
- * this method is free to modify the returned array; it will have no
- * effect on the arrays returned to other callers.
+ * Returns annotations that are <em>present</em> on this element.
+ *
+ * If there are no annotations <em>present</em> on this element, the return
+ * value is an array of length 0.
*
- * @return all annotations 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 annotations present on this element
* @since 1.5
*/
Annotation[] getAnnotations();
@@ -157,14 +186,16 @@
<T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass);
/**
- * Returns all annotations that are directly present on this
- * element. This method ignores inherited annotations. (Returns
- * an array of length zero if no annotations are directly present
- * on this element.) The caller of this method is free to modify
- * the returned array; it will have no effect on the arrays
- * returned to other callers.
+ * Returns annotations that are <em>directly present</em> on this element.
+ * This method ignores inherited annotations.
*
- * @return All annotations directly present on this element
+ * If there are no annotations <em>directly present</em> on this element,
+ * the return value is an array of length 0.
+ *
+ * The caller of this method is free to modify the returned array; it will
+ * have no effect on the arrays returned to other callers.
+ *
+ * @return annotations directly present on this element
* @since 1.5
*/
Annotation[] getDeclaredAnnotations();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedParameterizedType.java Tue Feb 05 11:11:53 2013 -0800
@@ -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();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedType.java Tue Feb 05 11:11:53 2013 -0800
@@ -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();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedTypeVariable.java Tue Feb 05 11:11:53 2013 -0800
@@ -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();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedWildcardType.java Tue Feb 05 11:11:53 2013 -0800
@@ -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();
+}
--- a/jdk/src/share/classes/java/lang/reflect/Constructor.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/java/lang/reflect/Constructor.java Tue Feb 05 11:11:53 2013 -0800
@@ -154,6 +154,10 @@
byte[] getAnnotationBytes() {
return annotations;
}
+ @Override
+ byte[] getTypeAnnotationBytes() {
+ return typeAnnotations;
+ }
/**
* {@inheritDoc}
@@ -523,4 +527,12 @@
}
}
}
+
+ /**
+ * {@inheritDoc}
+ * @since 1.8
+ */
+ public AnnotatedType getAnnotatedReturnType() {
+ return getAnnotatedReturnType0(getDeclaringClass());
+ }
}
--- a/jdk/src/share/classes/java/lang/reflect/Executable.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/java/lang/reflect/Executable.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,11 +26,12 @@
package java.lang.reflect;
import java.lang.annotation.*;
-import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import sun.reflect.annotation.AnnotationParser;
import sun.reflect.annotation.AnnotationSupport;
+import sun.reflect.annotation.TypeAnnotationParser;
+import sun.reflect.annotation.TypeAnnotation;
import sun.reflect.generics.repository.ConstructorRepository;
/**
@@ -50,6 +51,7 @@
* Accessor method to allow code sharing
*/
abstract byte[] getAnnotationBytes();
+ abstract byte[] getTypeAnnotationBytes();
/**
* Does the Executable have generic information.
@@ -435,8 +437,7 @@
*/
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass);
-
- return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass);
+ return annotationClass.cast(declaredAnnotations().get(annotationClass));
}
/**
@@ -454,7 +455,7 @@
* {@inheritDoc}
*/
public Annotation[] getDeclaredAnnotations() {
- return AnnotationSupport.unpackToArray(declaredAnnotations());
+ return AnnotationParser.toArray(declaredAnnotations());
}
private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
@@ -470,4 +471,86 @@
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);
+ }
+
}
--- a/jdk/src/share/classes/java/lang/reflect/Field.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/java/lang/reflect/Field.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,7 +36,8 @@
import java.util.Objects;
import sun.reflect.annotation.AnnotationParser;
import sun.reflect.annotation.AnnotationSupport;
-
+import sun.reflect.annotation.TypeAnnotation;
+import sun.reflect.annotation.TypeAnnotationParser;
/**
* A {@code Field} provides information about, and dynamic access to, a
@@ -1020,8 +1021,7 @@
*/
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass);
-
- return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass);
+ return annotationClass.cast(declaredAnnotations().get(annotationClass));
}
/**
@@ -1039,7 +1039,7 @@
* {@inheritDoc}
*/
public Annotation[] getDeclaredAnnotations() {
- return AnnotationSupport.unpackToArray(declaredAnnotations());
+ return AnnotationParser.toArray(declaredAnnotations());
}
private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
@@ -1053,4 +1053,20 @@
}
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);
}
+}
--- a/jdk/src/share/classes/java/lang/reflect/Method.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/java/lang/reflect/Method.java Tue Feb 05 11:11:53 2013 -0800
@@ -165,6 +165,10 @@
byte[] getAnnotationBytes() {
return annotations;
}
+ @Override
+ byte[] getTypeAnnotationBytes() {
+ return typeAnnotations;
+ }
/**
* {@inheritDoc}
@@ -621,6 +625,14 @@
return sharedGetParameterAnnotations(parameterTypes, parameterAnnotations);
}
+ /**
+ * {@inheritDoc}
+ * @since 1.8
+ */
+ public AnnotatedType getAnnotatedReturnType() {
+ return getAnnotatedReturnType0(getGenericReturnType());
+ }
+
@Override
void handleParameterNumberMismatch(int resultLength, int numParameters) {
throw new AnnotationFormatError("Parameter annotations don't match number of parameters");
--- a/jdk/src/share/classes/java/lang/reflect/Parameter.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/java/lang/reflect/Parameter.java Tue Feb 05 11:11:53 2013 -0800
@@ -233,8 +233,7 @@
*/
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass);
-
- return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass);
+ return annotationClass.cast(declaredAnnotations().get(annotationClass));
}
/**
@@ -281,14 +280,6 @@
return getDeclaredAnnotations();
}
- /**
- * @throws NullPointerException {@inheritDoc}
- */
- public boolean isAnnotationPresent(
- Class<? extends Annotation> annotationClass) {
- return getAnnotation(annotationClass) != null;
- }
-
private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
private synchronized Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
--- a/jdk/src/share/classes/java/lang/reflect/ReflectAccess.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/java/lang/reflect/ReflectAccess.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -128,6 +128,10 @@
return c.getRawParameterAnnotations();
}
+ public byte[] getExecutableTypeAnnotationBytes(Executable ex) {
+ return ex.getTypeAnnotationBytes();
+ }
+
//
// Copying routines, needed to quickly fabricate new Field,
// Method, and Constructor objects from templates
--- a/jdk/src/share/classes/java/lang/reflect/TypeVariable.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/java/lang/reflect/TypeVariable.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -86,4 +86,16 @@
* @return the name of this type variable, as it appears in the source code
*/
String getName();
+
+ /**
+ * Returns an array of AnnotatedType objects that represent the use of
+ * types to denote the upper bounds of the type parameter represented by
+ * this TypeVariable. The order of the objects in the array corresponds to
+ * the order of the bounds in the declaration of the type parameter.
+ *
+ * Returns an array of length 0 if the type parameter declares no bounds.
+ *
+ * @since 1.8
+ */
+ AnnotatedType[] getAnnotatedBounds();
}
--- a/jdk/src/share/classes/java/math/BigDecimal.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/java/math/BigDecimal.java Tue Feb 05 11:11:53 2013 -0800
@@ -3537,13 +3537,25 @@
else
return expandBigIntegerTenPowers(n);
}
- // BigInteger.pow is slow, so make 10**n by constructing a
- // BigInteger from a character string (still not very fast)
- char tenpow[] = new char[n + 1];
- tenpow[0] = '1';
- for (int i = 1; i <= n; i++)
- tenpow[i] = '0';
- return new BigInteger(tenpow,1, tenpow.length);
+
+ if (n < 1024*524288) {
+ // BigInteger.pow is slow, so make 10**n by constructing a
+ // BigInteger from a character string (still not very fast)
+ // which occupies no more than 1GB (!) of memory.
+ char tenpow[] = new char[n + 1];
+ tenpow[0] = '1';
+ for (int i = 1; i <= n; i++) {
+ tenpow[i] = '0';
+ }
+ return new BigInteger(tenpow, 1, tenpow.length);
+ }
+
+ if ((n & 0x1) == 0x1) {
+ return BigInteger.TEN.multiply(bigTenToThe(n - 1));
+ } else {
+ BigInteger tmp = bigTenToThe(n/2);
+ return tmp.multiply(tmp);
+ }
}
/**
--- a/jdk/src/share/classes/java/util/Base64.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/java/util/Base64.java Tue Feb 05 11:11:53 2013 -0800
@@ -64,7 +64,8 @@
* RFC 2045 for encoding and decoding operation. The encoded output
* must be represented in lines of no more than 76 characters each
* and uses a carriage return {@code '\r'} followed immediately by
- * a linefeed {@code '\n'} as the line separator. All line separators
+ * a linefeed {@code '\n'} as the line separator. No line separator
+ * is added to the end of the encoded output. All line separators
* or other characters not found in the base64 alphabet table are
* ignored in decoding operation.</p></li>
* </ul>
@@ -413,6 +414,7 @@
* specified Base64 encoded format
*/
public OutputStream wrap(OutputStream os) {
+ Objects.requireNonNull(os);
return new EncOutputStream(os, isURL ? toBase64URL : toBase64,
newline, linemax);
}
@@ -613,6 +615,13 @@
* This class implements a decoder for decoding byte data using the
* Base64 encoding scheme as specified in RFC 4648 and RFC 2045.
*
+ * <p> The Base64 padding character {@code '='} is accepted and
+ * interpreted as the end of the encoded byte data, but is not
+ * required. So if the final unit of the encoded byte data only has
+ * two or three Base64 characters (without the corresponding padding
+ * character(s) padded), they are decoded as if followed by padding
+ * character(s).
+ *
* <p> Instances of {@link Decoder} class are safe for use by
* multiple concurrent threads.
*
@@ -695,7 +704,7 @@
* using the {@link Base64} encoding scheme.
*
* <p> An invocation of this method has exactly the same effect as invoking
- * {@code return decode(src.getBytes(StandardCharsets.ISO_8859_1))}
+ * {@code decode(src.getBytes(StandardCharsets.ISO_8859_1))}
*
* @param src
* the string to decode
@@ -856,6 +865,9 @@
/**
* Returns an input stream for decoding {@link Base64} encoded byte stream.
*
+ * <p> The {@code read} methods of the returned {@code InputStream} will
+ * throw {@code IOException} when reading bytes that cannot be decoded.
+ *
* <p> Closing the returned input stream will close the underlying
* input stream.
*
@@ -866,6 +878,7 @@
* byte stream
*/
public InputStream wrap(InputStream is) {
+ Objects.requireNonNull(is);
return new DecInputStream(is, isURL ? fromBase64URL : fromBase64, isMIME);
}
@@ -881,13 +894,16 @@
int dl = dst.arrayOffset() + dst.limit();
int dp0 = dp;
int mark = sp;
- boolean padding = false;
try {
while (sp < sl) {
int b = sa[sp++] & 0xff;
if ((b = base64[b]) < 0) {
if (b == -2) { // padding byte
- padding = true;
+ if (shiftto == 6 && (sp == sl || sa[sp++] != '=') ||
+ shiftto == 18) {
+ throw new IllegalArgumentException(
+ "Input byte array has wrong 4-byte ending unit");
+ }
break;
}
if (isMIME) // skip if for rfc2045
@@ -913,24 +929,23 @@
if (shiftto == 6) {
if (dl - dp < 1)
return dp - dp0;
- if (padding && (sp + 1 != sl || sa[sp++] != '='))
- throw new IllegalArgumentException(
- "Input buffer has wrong 4-byte ending unit");
da[dp++] = (byte)(bits >> 16);
- mark = sp;
} else if (shiftto == 0) {
if (dl - dp < 2)
return dp - dp0;
- if (padding && sp != sl)
- throw new IllegalArgumentException(
- "Input buffer has wrong 4-byte ending unit");
da[dp++] = (byte)(bits >> 16);
da[dp++] = (byte)(bits >> 8);
- mark = sp;
- } else if (padding || shiftto != 18) {
+ } else if (shiftto == 12) {
throw new IllegalArgumentException(
"Last unit does not have enough valid bits");
}
+ while (sp < sl) {
+ if (isMIME && base64[sa[sp++]] < 0)
+ continue;
+ throw new IllegalArgumentException(
+ "Input byte array has incorrect ending byte at " + sp);
+ }
+ mark = sp;
return dp - dp0;
} finally {
src.position(mark);
@@ -948,14 +963,16 @@
int dl = dst.limit();
int dp0 = dp;
int mark = sp;
- boolean padding = false;
-
try {
while (sp < sl) {
int b = src.get(sp++) & 0xff;
if ((b = base64[b]) < 0) {
if (b == -2) { // padding byte
- padding = true;
+ if (shiftto == 6 && (sp == sl || src.get(sp++) != '=') ||
+ shiftto == 18) {
+ throw new IllegalArgumentException(
+ "Input byte array has wrong 4-byte ending unit");
+ }
break;
}
if (isMIME) // skip if for rfc2045
@@ -981,24 +998,23 @@
if (shiftto == 6) {
if (dl - dp < 1)
return dp - dp0;
- if (padding && (sp + 1 != sl || src.get(sp++) != '='))
- throw new IllegalArgumentException(
- "Input buffer has wrong 4-byte ending unit");
dst.put(dp++, (byte)(bits >> 16));
- mark = sp;
} else if (shiftto == 0) {
if (dl - dp < 2)
return dp - dp0;
- if (padding && sp != sl)
- throw new IllegalArgumentException(
- "Input buffer has wrong 4-byte ending unit");
dst.put(dp++, (byte)(bits >> 16));
dst.put(dp++, (byte)(bits >> 8));
- mark = sp;
- } else if (padding || shiftto != 18) {
+ } else if (shiftto == 12) {
throw new IllegalArgumentException(
"Last unit does not have enough valid bits");
}
+ while (sp < sl) {
+ if (isMIME && base64[src.get(sp++)] < 0)
+ continue;
+ throw new IllegalArgumentException(
+ "Input byte array has incorrect ending byte at " + sp);
+ }
+ mark = sp;
return dp - dp0;
} finally {
src.position(mark);
@@ -1012,9 +1028,12 @@
int len = sl - sp;
if (len == 0)
return 0;
- if (len < 2)
+ if (len < 2) {
+ if (isMIME && base64[0] == -1)
+ return 0;
throw new IllegalArgumentException(
"Input byte[] should at least have 2 bytes for base64 bytes");
+ }
if (src[sl - 1] == '=') {
paddings++;
if (src[sl - 2] == '=')
@@ -1043,12 +1062,20 @@
int dp = 0;
int bits = 0;
int shiftto = 18; // pos of first byte of 4-byte atom
- boolean padding = false;
while (sp < sl) {
int b = src[sp++] & 0xff;
if ((b = base64[b]) < 0) {
- if (b == -2) { // padding byte
- padding = true;
+ if (b == -2) { // padding byte '='
+ // xx= shiftto==6&&sp==sl missing last =
+ // xx=y shiftto==6 last is not =
+ // = shiftto==18 unnecessary padding
+ // x= shiftto==12 be taken care later
+ // together with single x, invalid anyway
+ if (shiftto == 6 && (sp == sl || src[sp++] != '=') ||
+ shiftto == 18) {
+ throw new IllegalArgumentException(
+ "Input byte array has wrong 4-byte ending unit");
+ }
break;
}
if (isMIME) // skip if for rfc2045
@@ -1068,22 +1095,23 @@
bits = 0;
}
}
- // reach end of byte arry or hit padding '=' characters.
- // if '=' presents, they must be the last one or two.
- if (shiftto == 6) { // xx==
- if (padding && (sp + 1 != sl || src[sp] != '='))
- throw new IllegalArgumentException(
- "Input byte array has wrong 4-byte ending unit");
+ // reached end of byte array or hit padding '=' characters.
+ if (shiftto == 6) {
dst[dp++] = (byte)(bits >> 16);
- } else if (shiftto == 0) { // xxx=
- if (padding && sp != sl)
- throw new IllegalArgumentException(
- "Input byte array has wrong 4-byte ending unit");
+ } else if (shiftto == 0) {
dst[dp++] = (byte)(bits >> 16);
dst[dp++] = (byte)(bits >> 8);
- } else if (padding || shiftto != 18) {
- throw new IllegalArgumentException(
- "last unit does not have enough bytes");
+ } else if (shiftto == 12) {
+ throw new IllegalArgumentException(
+ "Last unit does not have enough valid bits");
+ }
+ // anything left is invalid, if is not MIME.
+ // if MIME, ignore all non-base64 character
+ while (sp < sl) {
+ if (isMIME && base64[src[sp++]] < 0)
+ continue;
+ throw new IllegalArgumentException(
+ "Input byte array has incorrect ending byte at " + sp);
}
return dp;
}
@@ -1247,8 +1275,22 @@
int v = is.read();
if (v == -1) {
eof = true;
- if (nextin != 18)
- throw new IOException("Base64 stream has un-decoded dangling byte(s).");
+ if (nextin != 18) {
+ if (nextin == 12)
+ throw new IOException("Base64 stream has one un-decoded dangling byte.");
+ // treat ending xx/xxx without padding character legal.
+ // same logic as v == 'v' below
+ b[off++] = (byte)(bits >> (16));
+ len--;
+ if (nextin == 0) { // only one padding byte
+ if (len == 0) { // no enough output space
+ bits >>= 8; // shift to lowest byte
+ nextout = 0;
+ } else {
+ b[off++] = (byte) (bits >> 8);
+ }
+ }
+ }
if (off == oldOff)
return -1;
else
--- a/jdk/src/share/classes/java/util/Formatter.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/java/util/Formatter.java Tue Feb 05 11:11:53 2013 -0800
@@ -351,7 +351,9 @@
* <tr><td valign="top">{@code 'a'}, {@code 'A'}
* <td valign="top"> floating point
* <td> The result is formatted as a hexadecimal floating-point number with
- * a significand and an exponent
+ * a significand and an exponent. This conversion is <b>not</b> supported
+ * for the {@code BigDecimal} type despite the latter's being in the
+ * <i>floating point</i> argument category.
*
* <tr><td valign="top">{@code 't'}, {@code 'T'}
* <td valign="top"> date/time
--- a/jdk/src/share/classes/sun/management/Agent.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/sun/management/Agent.java Tue Feb 05 11:11:53 2013 -0800
@@ -22,7 +22,6 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
package sun.management;
import java.io.BufferedInputStream;
@@ -31,49 +30,55 @@
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
-
+import java.lang.management.ManagementFactory;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.lang.management.ManagementFactory;
-
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
import java.text.MessageFormat;
-
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.ResourceBundle;
import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXServiceURL;
import static sun.management.AgentConfigurationError.*;
import sun.management.jmxremote.ConnectorBootstrap;
+import sun.management.jdp.JdpController;
+import sun.management.jdp.JdpException;
import sun.misc.VMSupport;
/**
- * This Agent is started by the VM when -Dcom.sun.management.snmp
- * or -Dcom.sun.management.jmxremote is set. This class will be
- * loaded by the system class loader. Also jmx framework could
- * be started by jcmd
+ * This Agent is started by the VM when -Dcom.sun.management.snmp or
+ * -Dcom.sun.management.jmxremote is set. This class will be loaded by the
+ * system class loader. Also jmx framework could be started by jcmd
*/
public class Agent {
// management properties
+
private static Properties mgmtProps;
private static ResourceBundle messageRB;
-
private static final String CONFIG_FILE =
- "com.sun.management.config.file";
+ "com.sun.management.config.file";
private static final String SNMP_PORT =
- "com.sun.management.snmp.port";
+ "com.sun.management.snmp.port";
private static final String JMXREMOTE =
- "com.sun.management.jmxremote";
+ "com.sun.management.jmxremote";
private static final String JMXREMOTE_PORT =
- "com.sun.management.jmxremote.port";
+ "com.sun.management.jmxremote.port";
+ private static final String RMI_PORT =
+ "com.sun.management.jmxremote.rmi.port";
private static final String ENABLE_THREAD_CONTENTION_MONITORING =
- "com.sun.management.enableThreadContentionMonitoring";
+ "com.sun.management.enableThreadContentionMonitoring";
private static final String LOCAL_CONNECTOR_ADDRESS_PROP =
- "com.sun.management.jmxremote.localConnectorAddress";
+ "com.sun.management.jmxremote.localConnectorAddress";
+ private static final String SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME =
+ "sun.management.snmp.AdaptorBootstrap";
- private static final String SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME =
- "sun.management.snmp.AdaptorBootstrap";
+ private static final String JDP_DEFAULT_ADDRESS = "239.255.255.225";
+ private static final int JDP_DEFAULT_PORT = 7095;
// The only active agent allowed
private static JMXConnectorServer jmxServer = null;
@@ -81,26 +86,25 @@
// Parse string com.sun.management.prop=xxx,com.sun.management.prop=yyyy
// and return property set if args is null or empty
// return empty property set
- private static Properties parseString(String args){
+ private static Properties parseString(String args) {
Properties argProps = new Properties();
if (args != null) {
- for (String option : args.split(",")) {
- String s[] = option.split("=", 2);
- String name = s[0].trim();
- String value = (s.length > 1) ? s[1].trim() : "";
+ for (String option : args.split(",")) {
+ String s[] = option.split("=", 2);
+ String name = s[0].trim();
+ String value = (s.length > 1) ? s[1].trim() : "";
- if (!name.startsWith("com.sun.management.")) {
- error(INVALID_OPTION, name);
- }
+ if (!name.startsWith("com.sun.management.")) {
+ error(INVALID_OPTION, name);
+ }
- argProps.setProperty(name, value);
- }
+ argProps.setProperty(name, value);
+ }
}
return argProps;
}
-
// invoked by -javaagent or -Dcom.sun.management.agent.class
public static void premain(String args) throws Exception {
agentmain(args);
@@ -115,18 +119,18 @@
Properties arg_props = parseString(args);
// Read properties from the config file
- Properties config_props = new Properties();
- String fname = arg_props.getProperty(CONFIG_FILE);
- readConfiguration(fname, config_props);
+ Properties config_props = new Properties();
+ String fname = arg_props.getProperty(CONFIG_FILE);
+ readConfiguration(fname, config_props);
- // Arguments override config file
- config_props.putAll(arg_props);
- startAgent(config_props);
+ // Arguments override config file
+ config_props.putAll(arg_props);
+ startAgent(config_props);
}
// jcmd ManagementAgent.start_local entry point
// Also called due to command-line via startAgent()
- private static synchronized void startLocalManagementAgent(){
+ private static synchronized void startLocalManagementAgent() {
Properties agentProps = VMSupport.getAgentProperties();
// start local connector if not started
@@ -156,7 +160,7 @@
throw new RuntimeException(getText(INVALID_STATE, "Agent already started"));
}
- Properties argProps = parseString(args);
+ Properties argProps = parseString(args);
Properties configProps = new Properties();
// Load the management properties from the config file
@@ -169,7 +173,7 @@
// management properties can be overridden by system properties
// which take precedence
Properties sysProps = System.getProperties();
- synchronized(sysProps){
+ synchronized (sysProps) {
configProps.putAll(sysProps);
}
@@ -190,21 +194,26 @@
// can specify this property inside config file, so enable optional
// monitoring functionality if this property is set
final String enableThreadContentionMonitoring =
- configProps.getProperty(ENABLE_THREAD_CONTENTION_MONITORING);
+ configProps.getProperty(ENABLE_THREAD_CONTENTION_MONITORING);
if (enableThreadContentionMonitoring != null) {
ManagementFactory.getThreadMXBean().
- setThreadContentionMonitoringEnabled(true);
+ setThreadContentionMonitoringEnabled(true);
}
String jmxremotePort = configProps.getProperty(JMXREMOTE_PORT);
if (jmxremotePort != null) {
jmxServer = ConnectorBootstrap.
- startRemoteConnectorServer(jmxremotePort, configProps);
+ startRemoteConnectorServer(jmxremotePort, configProps);
+
+ startDiscoveryService(configProps);
}
}
private static synchronized void stopRemoteManagementAgent() throws Exception {
+
+ JdpController.stopDiscoveryService();
+
if (jmxServer != null) {
ConnectorBootstrap.unexportRegistry();
@@ -222,15 +231,15 @@
// Enable optional monitoring functionality if requested
final String enableThreadContentionMonitoring =
- props.getProperty(ENABLE_THREAD_CONTENTION_MONITORING);
+ props.getProperty(ENABLE_THREAD_CONTENTION_MONITORING);
if (enableThreadContentionMonitoring != null) {
ManagementFactory.getThreadMXBean().
- setThreadContentionMonitoringEnabled(true);
+ setThreadContentionMonitoringEnabled(true);
}
try {
if (snmpPort != null) {
- loadSnmpAgent(snmpPort, props);
+ loadSnmpAgent(snmpPort, props);
}
/*
@@ -242,13 +251,14 @@
* of this "local" server is exported as a counter to the jstat
* instrumentation buffer.
*/
- if (jmxremote != null || jmxremotePort != null) {
+ if (jmxremote != null || jmxremotePort != null) {
if (jmxremotePort != null) {
- jmxServer = ConnectorBootstrap.
- startRemoteConnectorServer(jmxremotePort, props);
+ jmxServer = ConnectorBootstrap.
+ startRemoteConnectorServer(jmxremotePort, props);
+ startDiscoveryService(props);
}
startLocalManagementAgent();
- }
+ }
} catch (AgentConfigurationError e) {
error(e.getError(), e.getParams());
@@ -257,6 +267,73 @@
}
}
+ private static void startDiscoveryService(Properties props)
+ throws IOException {
+ // Start discovery service if requested
+ String discoveryPort = props.getProperty("com.sun.management.jdp.port");
+ String discoveryAddress = props.getProperty("com.sun.management.jdp.address");
+ String discoveryShouldStart = props.getProperty("com.sun.management.jmxremote.autodiscovery");
+
+ // Decide whether we should start autodicovery service.
+ // To start autodiscovery following conditions should be met:
+ // autodiscovery==true OR (autodicovery==null AND jdp.port != NULL)
+
+ boolean shouldStart = false;
+ if (discoveryShouldStart == null){
+ shouldStart = (discoveryPort != null);
+ }
+ else{
+ try{
+ shouldStart = Boolean.parseBoolean(discoveryShouldStart);
+ } catch (NumberFormatException e) {
+ throw new AgentConfigurationError("Couldn't parse autodiscovery argument");
+ }
+ }
+
+ if (shouldStart) {
+ // port and address are required arguments and have no default values
+ InetAddress address;
+ try {
+ address = (discoveryAddress == null) ?
+ InetAddress.getByName(JDP_DEFAULT_ADDRESS) : InetAddress.getByName(discoveryAddress);
+ } catch (UnknownHostException e) {
+ throw new AgentConfigurationError("Unable to broadcast to requested address", e);
+ }
+
+ int port = JDP_DEFAULT_PORT;
+ if (discoveryPort != null) {
+ try {
+ port = Integer.parseInt(discoveryPort);
+ } catch (NumberFormatException e) {
+ throw new AgentConfigurationError("Couldn't parse JDP port argument");
+ }
+ }
+
+ // Rebuilding service URL to broadcast it
+ String jmxremotePort = props.getProperty(JMXREMOTE_PORT);
+ String rmiPort = props.getProperty(RMI_PORT);
+
+ JMXServiceURL url = jmxServer.getAddress();
+ String hostname = url.getHost();
+
+ String jmxUrlStr = (rmiPort != null)
+ ? String.format(
+ "service:jmx:rmi://%s:%s/jndi/rmi://%s:%s/jmxrmi",
+ hostname, rmiPort, hostname, jmxremotePort)
+ : String.format(
+ "service:jmx:rmi:///jndi/rmi://%s:%s/jmxrmi", hostname, jmxremotePort);
+
+ String instanceName = System.getProperty("com.sun.management.jdp.name");
+
+ try{
+ JdpController.startDiscoveryService(address, port, instanceName, jmxUrlStr);
+ }
+ catch(JdpException e){
+ throw new AgentConfigurationError("Couldn't start JDP service", e);
+ }
+ }
+ }
+
public static Properties loadManagementProperties() {
Properties props = new Properties();
@@ -268,22 +345,22 @@
// management properties can be overridden by system properties
// which take precedence
Properties sysProps = System.getProperties();
- synchronized(sysProps){
+ synchronized (sysProps) {
props.putAll(sysProps);
}
return props;
- }
+ }
- public static synchronized Properties getManagementProperties() {
+ public static synchronized Properties getManagementProperties() {
if (mgmtProps == null) {
String configFile = System.getProperty(CONFIG_FILE);
String snmpPort = System.getProperty(SNMP_PORT);
String jmxremote = System.getProperty(JMXREMOTE);
String jmxremotePort = System.getProperty(JMXREMOTE_PORT);
- if (configFile == null && snmpPort == null &&
- jmxremote == null && jmxremotePort == null) {
+ if (configFile == null && snmpPort == null
+ && jmxremote == null && jmxremotePort == null) {
// return if out-of-the-management option is not specified
return null;
}
@@ -297,22 +374,23 @@
// invoke the following through reflection:
// AdaptorBootstrap.initialize(snmpPort, props);
final Class<?> adaptorClass =
- Class.forName(SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME,true,null);
+ Class.forName(SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME, true, null);
final Method initializeMethod =
adaptorClass.getMethod("initialize",
- String.class, Properties.class);
- initializeMethod.invoke(null,snmpPort,props);
+ String.class, Properties.class);
+ initializeMethod.invoke(null, snmpPort, props);
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException x) {
// snmp runtime doesn't exist - initialization fails
- throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT,x);
+ throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT, x);
} catch (InvocationTargetException x) {
final Throwable cause = x.getCause();
- if (cause instanceof RuntimeException)
+ if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
- else if (cause instanceof Error)
+ } else if (cause instanceof Error) {
throw (Error) cause;
+ }
// should not happen...
- throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT,cause);
+ throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT, cause);
}
}
@@ -353,8 +431,8 @@
} catch (IOException e) {
error(CONFIG_FILE_CLOSE_FAILED, fname);
}
- }
- }
+ }
+ }
}
public static void startAgent() throws Exception {
@@ -389,9 +467,9 @@
// invoke the premain(String args) method
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(cname);
Method premain = clz.getMethod("premain",
- new Class<?>[] { String.class });
+ new Class<?>[]{String.class});
premain.invoke(null, /* static */
- new Object[] { args });
+ new Object[]{args});
} catch (ClassNotFoundException ex) {
error(AGENT_CLASS_NOT_FOUND, "\"" + cname + "\"");
} catch (NoSuchMethodException ex) {
@@ -400,8 +478,8 @@
error(AGENT_CLASS_ACCESS_DENIED);
} catch (Exception ex) {
String msg = (ex.getCause() == null
- ? ex.getMessage()
- : ex.getCause().getMessage());
+ ? ex.getMessage()
+ : ex.getCause().getMessage());
error(AGENT_CLASS_FAILED, msg);
}
}
@@ -425,7 +503,6 @@
}
}
-
public static void error(String key, String message) {
String keyText = getText(key);
System.err.print(getText("agent.err.error") + ": " + keyText);
@@ -447,7 +524,7 @@
private static void initResource() {
try {
messageRB =
- ResourceBundle.getBundle("sun.management.resources.agent");
+ ResourceBundle.getBundle("sun.management.resources.agent");
} catch (MissingResourceException e) {
throw new Error("Fatal: Resource for management agent is missing");
}
@@ -470,10 +547,9 @@
}
String format = messageRB.getString(key);
if (format == null) {
- format = "missing resource key: key = \"" + key + "\", " +
- "arguments = \"{0}\", \"{1}\", \"{2}\"";
+ format = "missing resource key: key = \"" + key + "\", "
+ + "arguments = \"{0}\", \"{1}\", \"{2}\"";
}
return MessageFormat.format(format, (Object[]) args);
}
-
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/management/jdp/JdpBroadcaster.java Tue Feb 05 11:11:53 2013 -0800
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/management/jdp/JdpController.java Tue Feb 05 11:11:53 2013 -0800
@@ -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;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/management/jdp/JdpException.java Tue Feb 05 11:11:53 2013 -0800
@@ -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);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/management/jdp/JdpGenericPacket.java Tue Feb 05 11:11:53 2013 -0800
@@ -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;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/management/jdp/JdpJmxPacket.java Tue Feb 05 11:11:53 2013 -0800
@@ -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());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/management/jdp/JdpPacket.java Tue Feb 05 11:11:53 2013 -0800
@@ -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;
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/management/jdp/JdpPacketReader.java Tue Feb 05 11:11:53 2013 -0800
@@ -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;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/management/jdp/JdpPacketWriter.java Tue Feb 05 11:11:53 2013 -0800
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/management/jdp/package-info.java Tue Feb 05 11:11:53 2013 -0800
@@ -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;
--- a/jdk/src/share/classes/sun/misc/JavaLangAccess.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/sun/misc/JavaLangAccess.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
package sun.misc;
import java.lang.annotation.Annotation;
+import java.lang.reflect.Executable;
import sun.reflect.ConstantPool;
import sun.reflect.annotation.AnnotationType;
import sun.nio.ch.Interruptible;
@@ -47,6 +48,18 @@
AnnotationType getAnnotationType(Class<?> klass);
/**
+ * Get the array of bytes that is the class-file representation
+ * of this Class' type annotations.
+ */
+ byte[] getRawClassTypeAnnotations(Class<?> klass);
+
+ /**
+ * Get the array of bytes that is the class-file representation
+ * of this Executable's type annotations.
+ */
+ byte[] getRawExecutableTypeAnnotations(Executable executable);
+
+ /**
* Returns the elements of an enum class or null if the
* Class object does not represent an enum type;
* the result is uncloned, cached, and shared by all callers.
@@ -84,9 +97,4 @@
* Returns the ith StackTraceElement for the given throwable.
*/
StackTraceElement getStackTraceElement(Throwable t, int i);
-
- /**
- * Returns a directly present annotation.
- */
- public <A extends Annotation> A getDirectDeclaredAnnotation(Class<?> klass, Class<A> anno);
}
--- a/jdk/src/share/classes/sun/reflect/LangReflectAccess.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/sun/reflect/LangReflectAccess.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -81,6 +81,9 @@
public void setConstructorAccessor(Constructor<?> c,
ConstructorAccessor accessor);
+ /** Gets the byte[] that encodes TypeAnnotations on an Executable. */
+ public byte[] getExecutableTypeAnnotationBytes(Executable ex);
+
/** Gets the "slot" field from a Constructor (used for serialization) */
public int getConstructorSlot(Constructor<?> c);
--- a/jdk/src/share/classes/sun/reflect/ReflectionFactory.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/sun/reflect/ReflectionFactory.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
package sun.reflect;
import java.lang.reflect.Field;
+import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
@@ -314,6 +315,12 @@
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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java Tue Feb 05 11:11:53 2013 -0800
@@ -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;
+ }
+ }
+}
--- a/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -188,7 +188,7 @@
* available at runtime
*/
@SuppressWarnings("unchecked")
- private static Annotation parseAnnotation(ByteBuffer buf,
+ static Annotation parseAnnotation(ByteBuffer buf,
ConstantPool constPool,
Class<?> container,
boolean exceptionOnMissingAnnotationClass) {
--- a/jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,63 +27,29 @@
import java.lang.annotation.*;
import java.lang.reflect.*;
-import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
-import sun.reflect.Reflection;
-import sun.misc.JavaLangAccess;
public final class AnnotationSupport {
- private static final JavaLangAccess javaLangAccess = sun.misc.SharedSecrets.getJavaLangAccess();
-
- /**
- * Finds and returns _one_ annotation of the type indicated by
- * {@code annotationClass} from the {@code Map} {@code
- * annotationMap}. Looks into containers of the {@code
- * annotationClass} (as specified by an the {@code
- * annotationClass} type being meta-annotated with an {@code
- * ContainedBy} annotation).
- *
- * @param annotationMap the {@code Map} used to store annotations and indexed by their type
- * @param annotationClass the type of annotation to search for
- *
- * @return in instance of {@code annotationClass} or {@code null} if none were found
- */
- public static <A extends Annotation> A getOneAnnotation(final Map<Class<? extends Annotation>, Annotation> annotationMap,
- final Class<A> annotationClass) {
- @SuppressWarnings("unchecked")
- final A candidate = (A)annotationMap.get(annotationClass);
- if (candidate != null) {
- return candidate;
- }
-
- final Class<? extends Annotation> containerClass = getContainer(annotationClass);
- if (containerClass != null) {
- return unpackOne(annotationMap.get(containerClass), annotationClass);
- }
-
- return null; // found none
- }
-
/**
* Finds and returns all annotation of the type indicated by
* {@code annotationClass} from the {@code Map} {@code
* annotationMap}. Looks into containers of the {@code
* annotationClass} (as specified by an the {@code
* annotationClass} type being meta-annotated with an {@code
- * ContainedBy} annotation).
+ * Repeatable} annotation).
*
* @param annotationMap the {@code Map} used to store annotations indexed by their type
* @param annotationClass the type of annotation to search for
*
* @return an array of instances of {@code annotationClass} or an empty array if none were found
*/
- public static <A extends Annotation> A[] getMultipleAnnotations(final Map<Class<? extends Annotation>, Annotation> annotationMap,
- final Class<A> annotationClass) {
- final ArrayList<A> res = new ArrayList<A>();
+ public static <A extends Annotation> A[] getMultipleAnnotations(
+ final Map<Class<? extends Annotation>, Annotation> annotationMap,
+ final Class<A> annotationClass) {
+ final List<A> res = new ArrayList<A>();
@SuppressWarnings("unchecked")
final A candidate = (A)annotationMap.get(annotationClass);
@@ -101,49 +67,10 @@
return res.isEmpty() ? emptyTemplateArray : res.toArray(emptyTemplateArray);
}
- /**
- * Unpacks the {@code annotationMap} parameter into an array of
- * {@code Annotation}s. This method will unpack all repeating
- * annotations containers (once). An annotation type is marked as a
- * container by meta-annotating it the with the {@code
- * ContainerFor} annotation.
- *
- * @param annotationMap the {@code Map} from where the annotations are unpacked
- *
- * @return an array of Annotation
- */
- public static Annotation[] unpackToArray(Map<Class<? extends Annotation>, Annotation> annotationMap) {
- List<Annotation> res = new ArrayList<>();
- for (Map.Entry<Class<? extends Annotation>, Annotation> e : annotationMap.entrySet()) {
- Class<? extends Annotation> annotationClass = e.getKey();
- Annotation annotationInstance = e.getValue();
- Class<? extends Annotation> containee = getContainee(e.getKey());
- boolean isContainer = javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainerFor.class) != null;
-
- if (isContainer) {
- res.addAll(unpackAll(annotationInstance, containee));
- } else {
- res.add(annotationInstance);
- }
- }
-
- return res.isEmpty()
- ? AnnotationParser.getEmptyAnnotationArray()
- : res.toArray(AnnotationParser.getEmptyAnnotationArray());
- }
-
/** Helper to get the container, or null if none, of an annotation. */
private static <A extends Annotation> Class<? extends Annotation> getContainer(Class<A> annotationClass) {
- ContainedBy containerAnnotation =
- javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainedBy.class);
- return (containerAnnotation == null) ? null : containerAnnotation.value();
- }
-
- /** Helper to get the containee, or null if this isn't a container, of a possible container annotation. */
- private static <A extends Annotation> Class<? extends Annotation> getContainee(Class<A> annotationClass) {
- ContainerFor containerAnnotation =
- javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainerFor.class);
- return (containerAnnotation == null) ? null : containerAnnotation.value();
+ Repeatable containingAnnotation = annotationClass.getDeclaredAnnotation(Repeatable.class);
+ return (containingAnnotation == null) ? null : containingAnnotation.value();
}
/** Reflectively look up and get the returned array from the the
@@ -156,14 +83,15 @@
// value element. Get the AnnotationType, get the "value" element
// and invoke it to get the contents.
- Class<?> containerClass = containerInstance.annotationType();
- AnnotationType annoType = javaLangAccess.getAnnotationType(containerClass);
+ Class<? extends Annotation> containerClass = containerInstance.annotationType();
+ AnnotationType annoType = AnnotationType.getInstance(containerClass);
if (annoType == null)
throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations");
Method m = annoType.members().get("value");
if (m == null)
- throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations");
+ throw new InvalidContainerAnnotationError(containerInstance +
+ " is an invalid container for repeating annotations");
m.setAccessible(true);
@SuppressWarnings("unchecked") // not provably safe, but we catch the ClassCastException
@@ -175,32 +103,11 @@
IllegalArgumentException | // parameters doesn't match
InvocationTargetException | // the value method threw an exception
ClassCastException e) { // well, a cast failed ...
- throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations",
- e,
- containerInstance,
- null);
- }
- }
-
- /* Sanity check type of and return the first annotation instance
- * of type {@code annotationClass} from {@code
- * containerInstance}.
- */
- private static <A extends Annotation> A unpackOne(Annotation containerInstance, Class<A> annotationClass) {
- if (containerInstance == null) {
- return null;
- }
-
- try {
- return annotationClass.cast(getValueArray(containerInstance)[0]);
- } catch (ArrayIndexOutOfBoundsException | // empty array
- ClassCastException | // well, a cast failed ...
- NullPointerException e) { // can this NP? for good meassure
- throw new InvalidContainerAnnotationError(String.format("%s is an invalid container for repeating annotations of type: %s",
- containerInstance, annotationClass),
- e,
- containerInstance,
- annotationClass);
+ throw new InvalidContainerAnnotationError(
+ containerInstance + " is an invalid container for repeating annotations",
+ e,
+ containerInstance,
+ null);
}
}
@@ -208,24 +115,26 @@
* instances of type {@code annotationClass} from {@code
* containerInstance}.
*/
- private static <A extends Annotation> List<A> unpackAll(Annotation containerInstance, Class<A> annotationClass) {
+ private static <A extends Annotation> List<A> unpackAll(Annotation containerInstance,
+ Class<A> annotationClass) {
if (containerInstance == null) {
return Collections.emptyList(); // container not present
}
try {
A[] a = getValueArray(containerInstance);
- ArrayList<A> l = new ArrayList<>(a.length);
+ List<A> l = new ArrayList<>(a.length);
for (int i = 0; i < a.length; i++)
l.add(annotationClass.cast(a[i]));
return l;
} catch (ClassCastException |
NullPointerException e) {
- throw new InvalidContainerAnnotationError(String.format("%s is an invalid container for repeating annotations of type: %s",
- containerInstance, annotationClass),
- e,
- containerInstance,
- annotationClass);
+ throw new InvalidContainerAnnotationError(
+ String.format("%s is an invalid container for repeating annotations of type: %s",
+ containerInstance, annotationClass),
+ e,
+ containerInstance,
+ annotationClass);
}
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotation.java Tue Feb 05 11:11:53 2013 -0800
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java Tue Feb 05 11:11:53 2013 -0800
@@ -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);
+ }
+}
--- a/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,13 +25,18 @@
package sun.reflect.generics.reflectiveObjects;
-import java.lang.annotation.Annotation;
+import java.lang.annotation.*;
+import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Array;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
+import java.util.LinkedHashMap;
+import java.util.Map;
import java.util.Objects;
-
+import sun.reflect.annotation.AnnotationSupport;
+import sun.reflect.annotation.TypeAnnotationParser;
+import sun.reflect.annotation.AnnotationType;
import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.tree.FieldTypeSignature;
import sun.reflect.generics.visitor.Reifier;
@@ -182,45 +187,70 @@
return genericDeclaration.hashCode() ^ name.hashCode();
}
- // Currently vacuous implementations of AnnotatedElement methods.
- public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
- Objects.requireNonNull(annotationClass);
- return false;
- }
-
+ // Implementations of AnnotatedElement methods.
+ @SuppressWarnings("unchecked")
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass);
- return null;
+ // T is an Annotation type, the return value of get will be an annotation
+ return (T)mapAnnotations(getAnnotations()).get(annotationClass);
}
public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass);
- return null;
+ return getAnnotation(annotationClass);
}
- @SuppressWarnings("unchecked")
public <T extends Annotation> T[] getAnnotations(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass);
- // safe because annotationClass is the class for T
- return (T[])Array.newInstance(annotationClass, 0);
+ return AnnotationSupport.getMultipleAnnotations(mapAnnotations(getAnnotations()), annotationClass);
}
- @SuppressWarnings("unchecked")
public <T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass);
- // safe because annotationClass is the class for T
- return (T[])Array.newInstance(annotationClass, 0);
+ return getAnnotations(annotationClass);
}
public Annotation[] getAnnotations() {
- // Since zero-length, don't need defensive clone
- return EMPTY_ANNOTATION_ARRAY;
+ int myIndex = typeVarIndex();
+ if (myIndex < 0)
+ throw new AssertionError("Index must be non-negative.");
+ return TypeAnnotationParser.parseTypeVariableAnnotations(getGenericDeclaration(), myIndex);
}
public Annotation[] getDeclaredAnnotations() {
- // Since zero-length, don't need defensive clone
- return EMPTY_ANNOTATION_ARRAY;
+ return getAnnotations();
+ }
+
+ public AnnotatedType[] getAnnotatedBounds() {
+ return TypeAnnotationParser.parseAnnotatedBounds(getBounds(),
+ getGenericDeclaration(),
+ typeVarIndex());
}
private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
+
+ // Helpers for annotation methods
+ private int typeVarIndex() {
+ TypeVariable<?>[] tVars = getGenericDeclaration().getTypeParameters();
+ int i = -1;
+ for (TypeVariable<?> v : tVars) {
+ i++;
+ if (equals(v))
+ return i;
+ }
+ return -1;
+ }
+
+ private static Map<Class<? extends Annotation>, Annotation> mapAnnotations(Annotation[] annos) {
+ Map<Class<? extends Annotation>, Annotation> result =
+ new LinkedHashMap<>();
+ for (Annotation a : annos) {
+ Class<? extends Annotation> klass = a.annotationType();
+ AnnotationType type = AnnotationType.getInstance(klass);
+ if (type.retention() == RetentionPolicy.RUNTIME)
+ if (result.put(klass, a) != null)
+ throw new AnnotationFormatError("Duplicate annotation for class: "+klass+": " + a);
+ }
+ return result;
+ }
}
--- a/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java Tue Feb 05 11:11:53 2013 -0800
@@ -1116,7 +1116,7 @@
if (privateKeyCount > 0 || secretKeyCount > 0) {
if (debug != null) {
- debug.println("Storing " + privateKeyCount +
+ debug.println("Storing " + (privateKeyCount + secretKeyCount) +
" protected key(s) in a PKCS#7 data content-type");
}
@@ -2122,6 +2122,7 @@
SecretKeyEntry kEntry = new SecretKeyEntry();
kEntry.protectedSecretKey = secretValue.getOctetString();
bagItem = kEntry;
+ secretKeyCount++;
} else {
if (debug != null) {
@@ -2220,6 +2221,10 @@
if (bagItem instanceof PrivateKeyEntry) {
keyList.add((PrivateKeyEntry) entry);
}
+ if (entry.attributes == null) {
+ entry.attributes = new HashSet<>();
+ }
+ entry.attributes.addAll(attributes);
if (alias == null) {
alias = getUnfriendlyName();
}
--- a/jdk/src/share/javavm/export/jvm.h Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/javavm/export/jvm.h Tue Feb 05 11:11:53 2013 -0800
@@ -465,6 +465,12 @@
JNIEXPORT jbyteArray JNICALL
JVM_GetClassAnnotations(JNIEnv *env, jclass cls);
+/* Type use annotations support (JDK 1.8) */
+
+JNIEXPORT jbyteArray JNICALL
+JVM_GetClassTypeAnnotations(JNIEnv *env, jclass cls);
+
+
/*
* New (JDK 1.4) reflection implementation
*/
--- a/jdk/src/share/native/java/lang/Class.c Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/share/native/java/lang/Class.c Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -75,7 +75,8 @@
{"getRawAnnotations", "()" BA, (void *)&JVM_GetClassAnnotations},
{"getConstantPool", "()" CPL, (void *)&JVM_GetClassConstantPool},
{"desiredAssertionStatus0","("CLS")Z",(void *)&JVM_DesiredAssertionStatus},
- {"getEnclosingMethod0", "()[" OBJ, (void *)&JVM_GetEnclosingMethodInfo}
+ {"getEnclosingMethod0", "()[" OBJ, (void *)&JVM_GetEnclosingMethodInfo},
+ {"getRawTypeAnnotations", "()" BA, (void *)&JVM_GetClassTypeAnnotations},
};
#undef OBJ
--- a/jdk/src/solaris/native/java/net/linux_close.c Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/solaris/native/java/net/linux_close.c Tue Feb 05 11:11:53 2013 -0800
@@ -192,17 +192,6 @@
{
/*
- * Send a wakeup signal to all threads blocked on this
- * file descriptor.
- */
- threadEntry_t *curr = fdEntry->threads;
- while (curr != NULL) {
- curr->intr = 1;
- pthread_kill( curr->thr, sigWakeup );
- curr = curr->next;
- }
-
- /*
* And close/dup the file descriptor
* (restart if interrupted by signal)
*/
@@ -214,6 +203,16 @@
}
} 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;
+ }
}
/*
--- a/jdk/src/windows/bin/cmdtoargs.c Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/src/windows/bin/cmdtoargs.c Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -104,6 +104,11 @@
case ' ':
case '\t':
+ if (prev == '\\') {
+ for (i = 0 ; i < slashes; i++) {
+ *dest++ = prev;
+ }
+ }
if (quotes % 2 == 1) {
*dest++ = ch;
} else {
@@ -591,6 +596,12 @@
// v->disable();
vectors[i++] = v;
+ v= new Vector(argv[0], "a b\\\\ d");
+ v->add("a", FALSE);
+ v->add("b\\\\", FALSE);
+ v->add("d", FALSE);
+ vectors[i++] = v;
+
dotest(vectors);
printf("All tests pass [%d]\n", i);
doexit(0);
--- a/jdk/test/ProblemList.txt Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/test/ProblemList.txt Tue Feb 05 11:11:53 2013 -0800
@@ -321,12 +321,12 @@
tools/pack200/CommandLineTests.java generic-all
tools/pack200/Pack200Test.java generic-all
-# 8001163
-tools/pack200/AttributeTests.java generic-all
-
# 7150569
tools/launcher/UnicodeTest.java macosx-all
+# 8007410
+tools/launcher/FXLauncherTest.java linux-all
+
############################################################################
# jdk_jdi
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/TypeAnnotationReflection.java Tue Feb 05 11:11:53 2013 -0800
@@ -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();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/TypeParamAnnotation.java Tue Feb 05 11:11:53 2013 -0800
@@ -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();
+}
--- a/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 7154390
+ * @bug 7154390 8005712
* @summary Unit test for repeated annotation reflection
*
* @compile RepeatedUnitTest.java subpackage/package-info.java subpackage/Container.java subpackage/Containee.java subpackage/NonRepeated.java subpackage/InheritedContainee.java subpackage/InheritedContainer.java subpackage/InheritedNonRepeated.java
@@ -58,7 +58,7 @@
checkMultiplier(Me1.class.getField("foo"), 1);
// METHOD
- checkMultiplier(Me1.class.getDeclaredMethod("mee", null), 100);
+ checkMultiplier(Me1.class.getDeclaredMethod("mee", (Class<?>[])null), 100);
// INNER CLASS
checkMultiplier(Me1.MiniMee.class, 1000);
@@ -84,8 +84,7 @@
static void packageRepeated(AnnotatedElement e) {
Containee c = e.getAnnotation(Containee.class);
- check(c.value() == 1);
-
+ check(c == null);
check(2 == countAnnotation(e, Containee.class));
c = e.getAnnotations(Containee.class)[0];
@@ -93,7 +92,7 @@
c = e.getAnnotations(Containee.class)[1];
check(c.value() == 2);
- check(2 == containsAnnotationOfType(e.getAnnotations(), Containee.class));
+ check(0 == containsAnnotationOfType(e.getAnnotations(), Containee.class));
}
static void packageContainer(AnnotatedElement e) {
@@ -161,14 +160,26 @@
}
static void checkMultiplier(AnnotatedElement e, int m) {
+ // Basic sanity of non-repeating getAnnotation(Class)
check(e.getAnnotation(NonRepeated.class).value() == 5 * m);
+ // Check count of annotations returned from getAnnotations(Class)
check(4 == countAnnotation(e, Containee.class));
check(1 == countAnnotation(e, Container.class));
check(1 == countAnnotation(e, NonRepeated.class));
+ // Check contents of array returned from getAnnotations(Class)
check(e.getAnnotations(Containee.class)[2].value() == 3 * m);
check(e.getAnnotations(NonRepeated.class)[0].value() == 5 * m);
+
+ // Check getAnnotation(Class)
+ check(e.getAnnotation(Containee.class) == null);
+ check(e.getAnnotation(Container.class) != null);
+
+ // Check count of annotations returned from getAnnotations()
+ check(0 == containsAnnotationOfType(e.getAnnotations(), Containee.class));
+ check(1 == containsAnnotationOfType(e.getAnnotations(), Container.class));
+ check(1 == containsAnnotationOfType(e.getAnnotations(), NonRepeated.class));
}
static void check(Boolean b) {
--- a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Containee.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Containee.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,6 @@
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
-@ContainedBy(Container.class)
@Repeatable(Container.class)
public @interface Containee {
int value();
--- a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Container.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Container.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,6 @@
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
-@ContainerFor(Containee.class)
public @interface Container {
Containee[] value();
}
--- a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainee.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainee.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,6 @@
@Inherited
@Retention(RetentionPolicy.RUNTIME)
-@ContainedBy(InheritedContainer.class)
@Repeatable(InheritedContainer.class)
public @interface InheritedContainee {
int value();
--- a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainer.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainer.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,6 @@
@Inherited
@Retention(RetentionPolicy.RUNTIME)
-@ContainerFor(InheritedContainee.class)
public @interface InheritedContainer {
InheritedContainee[] value();
}
--- a/jdk/test/java/lang/reflect/Parameter/WithoutParameters.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/test/java/lang/reflect/Parameter/WithoutParameters.java Tue Feb 05 11:11:53 2013 -0800
@@ -23,163 +23,152 @@
/*
* @test
+ * @bug 8004729
* @summary javac should generate method parameters correctly.
*/
import java.lang.*;
import java.lang.reflect.*;
+import java.lang.annotation.*;
import java.util.List;
+import java.util.Objects;
+
+import static java.lang.annotation.ElementType.*;
public class WithoutParameters {
+ int errors = 0;
- private static final Class<?>[] qux_types = {
- int.class,
- Foo.class,
- List.class,
- List.class,
- List.class,
- String[].class
- };
+ private WithoutParameters() {}
public static void main(String argv[]) throws Exception {
- int error = 0;
- Method[] methods = Foo.class.getMethods();
- for(Method m : methods) {
- System.err.println("Inspecting method " + m);
- Parameter[] parameters = m.getParameters();
- if(parameters == null)
- throw new Exception("getParameters should never be null");
- for(int i = 0; i < parameters.length; i++) {
- Parameter p = parameters[i];
- if(!p.getDeclaringExecutable().equals(m)) {
- System.err.println(p + ".getDeclaringExecutable != " + m);
- error++;
- }
- if(null == p.getType()) {
- System.err.println(p + ".getType() == null");
- error++;
- }
- if(null == p.getParameterizedType()) {
- System.err.println(p + ".getParameterizedType == null");
- error++;
- }
- }
- if(m.getName().equals("qux")) {
- if(6 != parameters.length) {
- System.err.println("Wrong number of parameters for qux");
- error++;
- }
- for(int i = 0; i < parameters.length; i++) {
- Parameter p = parameters[i];
- // The getType family work with or without
- // parameter attributes compiled in.
- if(!parameters[i].getType().equals(qux_types[i])) {
- System.err.println("Wrong parameter type for " + parameters[0] + ": expected " + qux_types[i] + ", but got " + parameters[i].getType());
- error++;
+ WithoutParameters wp = new WithoutParameters();
+ wp.runTests(Foo.class.getMethods());
+ wp.runTests(Foo.Inner.class.getConstructors());
+ wp.checkForErrors();
+ }
+
+ void runTests(Method[] methods) throws Exception {
+ for(Method m : methods) {runTest(m);}
+ }
+
+ void runTests(Constructor[] constructors) throws Exception {
+ for(Constructor c : constructors) {runTest(c);}
+ }
+
+ void runTest(Executable e) throws Exception {
+ System.err.println("Inspecting executable " + e);
+ Parameter[] parameters = e.getParameters();
+ Objects.requireNonNull(parameters, "getParameters should never be null");
+
+ ExpectedParameterInfo epi = e.getAnnotation(ExpectedParameterInfo.class);
+ if (epi != null) {
+ abortIfTrue(epi.parameterCount() != e.getParameterCount(), "Bad parameter count for "+ e);
+ abortIfTrue(epi.isVarArgs() != e.isVarArgs(),"Bad varargs value for "+ e);
+ }
+ abortIfTrue(e.getParameterCount() != parameters.length, "Mismatched of parameter counts.");
+
+ for(int i = 0; i < parameters.length; i++) {
+ Parameter p = parameters[i];
+ errorIfTrue(!p.getDeclaringExecutable().equals(e), p + ".getDeclaringExecutable != " + e);
+ Objects.requireNonNull(p.getType(), "getType() should not be null");
+ Objects.requireNonNull(p.getParameterizedType(), "getParameterizedType() should not be null");
+
+ if (epi != null) {
+ Class<?> expectedParameterType = epi.parameterTypes()[i];
+ errorIfTrue(!p.getType().equals(expectedParameterType),
+ "Wrong parameter type for " + p + ": expected " + expectedParameterType +
+ ", but got " + p.getType());
+
+ ParameterizedInfo[] expectedParameterizedTypes = epi.parameterizedTypes();
+ if (expectedParameterizedTypes.length > 0) {
+ Type parameterizedType = p.getParameterizedType();
+ Class<? extends Type> expectedParameterziedTypeType = expectedParameterizedTypes[i].value();
+ errorIfTrue(!expectedParameterziedTypeType.isAssignableFrom(parameterizedType.getClass()),
+ "Wrong class of parameteried type of " + p + ": expected " + expectedParameterziedTypeType +
+ ", but got " + parameterizedType.getClass());
+
+ if (expectedParameterziedTypeType.equals(Class.class)) {
+ errorIfTrue(!parameterizedType.equals(expectedParameterType),
+ "Wrong parameteried type for " + p + ": expected " + expectedParameterType +
+ ", but got " + parameterizedType);
+ } else {
+ if (expectedParameterziedTypeType.equals(ParameterizedType.class)) {
+ ParameterizedType ptype = (ParameterizedType)parameterizedType;
+ errorIfTrue(!ptype.getRawType().equals(expectedParameterType),
+ "Wrong raw type for " + p + ": expected " + expectedParameterType +
+ ", but got " + ptype.getRawType());
+ }
+
+ // Check string representation
+ String expectedStringOfType = epi.parameterizedTypes()[i].string();
+ errorIfTrue(!expectedStringOfType.equals(parameterizedType.toString()),
+ "Bad type string" + p + ": expected " + expectedStringOfType +
+ ", but got " + parameterizedType.toString());
}
}
- if(!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++;
- }
-
}
}
- if(0 != error)
- throw new Exception("Failed " + error + " tests");
+ }
+
+ private void checkForErrors() {
+ if (errors > 0)
+ throw new RuntimeException("Failed " + errors + " tests");
+ }
+
+ private void errorIfTrue(boolean predicate, String errMessage) {
+ if (predicate) {
+ errors++;
+ System.err.println(errMessage);
+ }
+ }
+
+ private void abortIfTrue(boolean predicate, String errMessage) {
+ if (predicate) {
+ throw new RuntimeException(errMessage);
+ }
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({METHOD, CONSTRUCTOR})
+ @interface ExpectedParameterInfo {
+ int parameterCount() default 0;
+ Class<?>[] parameterTypes() default {};
+ ParameterizedInfo[] parameterizedTypes() default {};
+ boolean isVarArgs() default false;
+ }
+
+ @Target({})
+ @interface ParameterizedInfo {
+ Class<? extends Type> value() default Class.class;
+ String string() default "";
}
public class Foo {
int thing;
+ @ExpectedParameterInfo(parameterCount = 6,
+ parameterTypes =
+ {int.class, Foo.class,
+ List.class, List.class,
+ List.class, String[].class},
+ parameterizedTypes =
+ {@ParameterizedInfo(Class.class),
+ @ParameterizedInfo(Class.class),
+ @ParameterizedInfo(value=ParameterizedType.class, string="java.util.List<?>"),
+ @ParameterizedInfo(value=ParameterizedType.class, string="java.util.List<WithoutParameters$Foo>"),
+ @ParameterizedInfo(value=ParameterizedType.class, string="java.util.List<? extends WithoutParameters$Foo>"),
+ @ParameterizedInfo(Class.class)},
+ isVarArgs = true)
public void qux(int quux, Foo quuux,
List<?> l, List<Foo> l2,
List<? extends Foo> l3,
String... rest) {}
public class Inner {
int thang;
+ @ExpectedParameterInfo(parameterCount = 2,
+ parameterTypes = {Foo.class, int.class})
public Inner(int theng) {
thang = theng + thing;
}
}
}
-
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/Socket/asyncClose/Race.java Tue Feb 05 11:11:53 2013 -0800
@@ -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();
+ }
+ }
+ }
+ }
+}
--- a/jdk/test/java/net/URL/Constructor.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/test/java/net/URL/Constructor.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -21,71 +21,235 @@
* questions.
*/
-/* This is no longer run directly. See runconstructor.sh
- *
- *
- *
+/*
+ * @test
+ * @bug 4393671
+ * @summary URL constructor URL(URL context, String spec) FAILED with specific input
+ */
+
+/*
* This program tests the URL parser in the URL constructor. It
* tries to construct a variety of valid URLs with a given context
* (which may be null) and a variety of specs. It then compares the
* result with an expected value.
- *
- * It expects that a data file named "urls" be available in the
- * current directory, from which it will get its testing data. The
- * format of the file is:
- *
- * URL: null
- * spec: jar:http://www.foo.com/dir1/jar.jar!/
- * expected: jar:http://www.foo.com/dir1/jar.jar!/
- *
- * where URL is the context, spec is the spec and expected is the
- * expected result. The first : must be followed by a space. Each test
- * entry should be followed by a blank line.
*/
-import java.io.*;
+import java.net.MalformedURLException;
import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
public class Constructor {
public static void main(String[] args) throws Exception {
- URL url = null;
- String urls = "jar_urls";
- if (args.length > 0 && args[0] != null) {
- urls = args[0];
- }
+ List<Entry> entries = new ArrayList<>();
+ entries.addAll(Arrays.asList(fileURLs));
+ entries.addAll(Arrays.asList(jarURLs));
+ entries.addAll(Arrays.asList(normalHttpURLs));
+ entries.addAll(Arrays.asList(abnormalHttpURLs));
+ if (hasFtp())
+ entries.addAll(Arrays.asList(ftpURLs));
+ URL url;
- File f = new File(urls);
- InputStream file = new FileInputStream(f);
- BufferedReader in = new BufferedReader(new InputStreamReader(file));
- while(true) {
- String context = in.readLine();
- if (context == null) {
- break;
- }
- context = getValue(context);
- String spec = getValue(in.readLine());
- String expected = getValue(in.readLine());
+ for (Entry e : entries) {
+ if (e.context == null)
+ url = new URL(e.spec);
+ else
+ url = new URL(new URL(e.context), e.spec);
- if (context.equals("null")) {
- url = new URL(spec);
- } else {
- url = new URL(new URL(context), spec);
- }
- if (!(url.toString().equals(expected))) {
- throw new RuntimeException("error for: \n\tURL:" + context +
- "\n\tspec: " + spec +
- "\n\texpected: " + expected +
+ if (!(url.toString().equals(e.expected))) {
+ throw new RuntimeException("error for: \n\tURL:" + e.context +
+ "\n\tspec: " + e.spec +
+ "\n\texpected: " + e.expected +
"\n\tactual: " + url.toString());
} else {
- System.out.println("success for: " + url + "\n");
+ //debug
+ //System.out.println("success for: " + url);
}
- in.readLine();
+ }
+ }
+
+ 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;
}
- in.close();
+ }
+
+ 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;
+ }
}
- private static String getValue(String value) {
- return value.substring(value.indexOf(':') + 2);
- }
+ 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")
+ };
}
--- a/jdk/test/java/net/URL/HandlerLoop.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/test/java/net/URL/HandlerLoop.java Tue Feb 05 11:11:53 2013 -0800
@@ -36,7 +36,7 @@
public static void main(String args[]) throws Exception {
URL.setURLStreamHandlerFactory(
new HandlerFactory("sun.net.www.protocol"));
- URL url = new URL("file://bogus/index.html");
+ URL url = new URL("file:///bogus/index.html");
System.out.println("url = " + url);
url.openConnection();
}
--- a/jdk/test/java/net/URL/Test.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/test/java/net/URL/Test.java Tue Feb 05 11:11:53 2013 -0800
@@ -310,7 +310,14 @@
throw new RuntimeException("Test failed");
}
-
+ private static boolean hasFtp() {
+ try {
+ return new java.net.URL("ftp://") != null;
+ } catch (java.net.MalformedURLException x) {
+ System.out.println("FTP not supported by this runtime.");
+ return false;
+ }
+ }
// -- Tests --
@@ -319,8 +326,9 @@
header("RFC2396: Basic examples");
- test("ftp://ftp.is.co.za/rfc/rfc1808.txt")
- .s("ftp").h("ftp.is.co.za").p("/rfc/rfc1808.txt").z();
+ if (hasFtp())
+ test("ftp://ftp.is.co.za/rfc/rfc1808.txt")
+ .s("ftp").h("ftp.is.co.za").p("/rfc/rfc1808.txt").z();
test("http://www.math.uio.no/faq/compression-faq/part1.html")
.s("http").h("www.math.uio.no").p("/faq/compression-faq/part1.html").z();
@@ -328,8 +336,9 @@
test("http://www.w3.org/Addressing/")
.s("http").h("www.w3.org").p("/Addressing/").z();
- test("ftp://ds.internic.net/rfc/")
- .s("ftp").h("ds.internic.net").p("/rfc/").z();
+ if (hasFtp())
+ test("ftp://ds.internic.net/rfc/")
+ .s("ftp").h("ds.internic.net").p("/rfc/").z();
test("http://www.ics.uci.edu/pub/ietf/url/historical.html#WARNING")
.s("http").h("www.ics.uci.edu").p("/pub/ietf/url/historical.html")
--- a/jdk/test/java/net/URL/URIToURLTest.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/test/java/net/URL/URIToURLTest.java Tue Feb 05 11:11:53 2013 -0800
@@ -28,20 +28,22 @@
*/
import java.net.*;
+import java.util.ArrayList;
+import java.util.List;
public class URIToURLTest {
public static void main(String args[]) throws Exception {
- String[] uris = {
- "http://jag:cafebabe@java.sun.com:94/b/c/d?q#g",
- "http://[1080:0:0:0:8:800:200C:417A]/index.html",
- "http://a/b/c/d;p?q",
- "ftp://ftp.is.co.za/rfc/rfc1808.txt",
- "mailto:mduerst@ifi.unizh.ch", // opaque url
- "http:comp.infosystems.www.servers.unix" //opaque url
- };
+ List<String> uris = new ArrayList<>();
+ uris.add("http://jag:cafebabe@java.sun.com:94/b/c/d?q#g");
+ uris.add("http://[1080:0:0:0:8:800:200C:417A]/index.html");
+ uris.add("http://a/b/c/d;p?q");
+ uris.add("mailto:mduerst@ifi.unizh.ch");
+ uris.add("http:comp.infosystems.www.servers.unix");
+ if (hasFtp())
+ uris.add("ftp://ftp.is.co.za/rfc/rfc1808.txt");
- for (int i = 0; i < uris.length; i++) {
- URI uri = new URI(uris[i]);
+ for (String uriStr : uris) {
+ URI uri = new URI(uriStr);
URL url = uri.toURL();
String scheme = uri.getScheme();
boolean schemeCheck = scheme == null? url.getProtocol() == null :
@@ -111,4 +113,13 @@
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;
+ }
+ }
}
--- a/jdk/test/java/net/URL/abnormal_http_urls Tue Feb 05 11:10:07 2013 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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
--- a/jdk/test/java/net/URL/ftp_urls Tue Feb 05 11:10:07 2013 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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
--- a/jdk/test/java/net/URL/jar_urls Tue Feb 05 11:10:07 2013 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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
--- a/jdk/test/java/net/URL/normal_http_urls Tue Feb 05 11:10:07 2013 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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
--- a/jdk/test/java/net/URL/runconstructor.sh Tue Feb 05 11:10:07 2013 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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
--- a/jdk/test/java/net/URL/share_file_urls Tue Feb 05 11:10:07 2013 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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
\ No newline at end of file
--- a/jdk/test/java/net/URL/win32_file_urls Tue Feb 05 11:10:07 2013 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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
\ No newline at end of file
--- a/jdk/test/java/net/URLConnection/RequestProperties.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/test/java/net/URLConnection/RequestProperties.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,90 +28,55 @@
*/
import java.net.*;
+import java.util.ArrayList;
+import java.util.List;
public class RequestProperties {
+ static int failed;
+
public static void main (String args[]) throws Exception {
- URL url0 = new URL ("http://foo.com/bar/");
- URL url1 = new URL ("file:/etc/passwd");
- URL url2 = new URL ("ftp://foo:bar@foobar.com/etc/passwd");
- URL url3 = new URL ("jar:http://foo.com/bar.html!/foo/bar");
- URLConnection urlc0 = url0.openConnection ();
- URLConnection urlc1 = url1.openConnection ();
- URLConnection urlc2 = url2.openConnection ();
- URLConnection urlc3 = url3.openConnection ();
- int count = 0;
- String s = null;
- try {
- urlc0.setRequestProperty (null, null);
- System.out.println ("http: setRequestProperty (null,) did not throw NPE");
- } catch (NullPointerException e) {
- count ++;
- }
+ List<String> urls = new ArrayList<>();
+ urls.add("http://foo.com/bar/");
+ urls.add("jar:http://foo.com/bar.html!/foo/bar");
+ urls.add("file:/etc/passwd");
+ if (hasFtp())
+ urls.add("ftp://foo:bar@foobar.com/etc/passwd");
+
+ for (String urlStr : urls)
+ test(new URL(urlStr));
+
+ if (failed != 0)
+ throw new RuntimeException(failed + " errors") ;
+ }
+
+ static void test(URL url) throws Exception {
+ URLConnection urlc = url.openConnection();
try {
- urlc0.addRequestProperty (null, null);
- System.out.println ("http: addRequestProperty (null,) did not throw NPE");
- } catch (NullPointerException e) {
- count ++;
- }
+ urlc.setRequestProperty(null, null);
+ System.out.println(url.getProtocol()
+ + ": setRequestProperty(null,) did not throw NPE");
+ failed++;
+ } catch (NullPointerException e) { /* Expected */ }
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 ++;
+ 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++;
}
- 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 ++;
- }
+ }
+
+ private static boolean hasFtp() {
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) {
- throw new RuntimeException ((12 -count) + " errors") ;
+ return new java.net.URL("ftp://") != null;
+ } catch (java.net.MalformedURLException x) {
+ System.out.println("FTP not supported by this runtime.");
+ return false;
}
}
}
--- a/jdk/test/java/net/URLConnection/RequestPropertyValues.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/test/java/net/URLConnection/RequestPropertyValues.java Tue Feb 05 11:11:53 2013 -0800
@@ -27,8 +27,11 @@
* @summary Test URLConnection Request Proterties
*/
+import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.List;
/**
* Part1:
@@ -45,28 +48,29 @@
}
public static void part1() throws Exception {
- URL[] urls = { new URL("http://localhost:8088"),
- new URL("file:/etc/passwd"),
- new URL("ftp://foo:bar@foobar.com/etc/passwd"),
- new URL("jar:http://foo.com/bar.html!/foo/bar")
- };
+ List<URL> urls = new ArrayList<>();
+ urls.add(new URL("http://localhost:8088"));
+ urls.add(new URL("file:/etc/passwd"));
+ urls.add(new URL("jar:http://foo.com/bar.html!/foo/bar"));
+ if (hasFtp())
+ urls.add(new URL("ftp://foo:bar@foobar.com/etc/passwd"));
boolean failed = false;
- for (int proto = 0; proto < urls.length; proto++) {
- URLConnection uc = (URLConnection) urls[proto].openConnection();
+ for (URL url : urls) {
+ URLConnection uc = url.openConnection();
try {
uc.setRequestProperty("TestHeader", null);
} catch (NullPointerException npe) {
System.out.println("setRequestProperty is throwing NPE" +
- " for url: " + urls[proto]);
+ " for url: " + url);
failed = true;
}
try {
uc.addRequestProperty("TestHeader", null);
} catch (NullPointerException npe) {
System.out.println("addRequestProperty is throwing NPE" +
- " for url: " + urls[proto]);
+ " for url: " + url);
failed = true;
}
}
@@ -110,4 +114,12 @@
}
}
+ 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;
+ }
+ }
}
--- a/jdk/test/java/security/KeyStore/PBETest.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/test/java/security/KeyStore/PBETest.java Tue Feb 05 11:11:53 2013 -0800
@@ -58,45 +58,46 @@
new File(NEW_KEYSTORE).delete();
- try {
- KeyStore keystore = load(KEYSTORE_TYPE, KEYSTORE, PASSWORD);
- KeyStore.Entry entry =
- keystore.getEntry(ALIAS,
- new KeyStore.PasswordProtection(PASSWORD));
- System.out.println("Retrieved entry named '" + ALIAS + "'");
+ KeyStore keystore = load(KEYSTORE_TYPE, KEYSTORE, PASSWORD);
+ KeyStore.Entry entry =
+ keystore.getEntry(ALIAS,
+ new KeyStore.PasswordProtection(PASSWORD));
+ System.out.println("Retrieved entry named '" + ALIAS + "'");
- // Set entry
- KeyStore keystore2 = load(NEW_KEYSTORE_TYPE, null, null);
- keystore2.setEntry(ALIAS, entry,
- new KeyStore.PasswordProtection(PASSWORD, PBE_ALGO,
- new PBEParameterSpec(SALT, ITERATION_COUNT,
- new IvParameterSpec(IV))));
- System.out.println("Encrypted entry using: " + PBE_ALGO);
+ // Set entry
+ KeyStore keystore2 = load(NEW_KEYSTORE_TYPE, null, null);
+ keystore2.setEntry(ALIAS, entry,
+ new KeyStore.PasswordProtection(PASSWORD, PBE_ALGO,
+ new PBEParameterSpec(SALT, ITERATION_COUNT,
+ new IvParameterSpec(IV))));
+ System.out.println("Encrypted entry using: " + PBE_ALGO);
+ try (FileOutputStream outStream = new FileOutputStream(NEW_KEYSTORE)) {
System.out.println("Storing keystore to: " + NEW_KEYSTORE);
- keystore2.store(new FileOutputStream(NEW_KEYSTORE), PASSWORD);
+ keystore2.store(outStream, PASSWORD);
+ }
- keystore2 = load(NEW_KEYSTORE_TYPE, NEW_KEYSTORE, PASSWORD);
- entry = keystore2.getEntry(ALIAS,
- new KeyStore.PasswordProtection(PASSWORD));
- System.out.println("Retrieved entry named '" + ALIAS + "'");
-
- } finally {
- new File(NEW_KEYSTORE).delete();
- System.out.println("Deleted keystore: " + NEW_KEYSTORE);
- }
+ keystore2 = load(NEW_KEYSTORE_TYPE, NEW_KEYSTORE, PASSWORD);
+ entry = keystore2.getEntry(ALIAS,
+ new KeyStore.PasswordProtection(PASSWORD));
+ System.out.println("Retrieved entry named '" + ALIAS + "'");
}
private static KeyStore load(String type, String path, char[] password)
throws Exception {
+ KeyStore keystore = KeyStore.getInstance(type);
- FileInputStream stream = null;
if (path != null) {
- stream = new FileInputStream(path);
+
+ try (FileInputStream inStream = new FileInputStream(path)) {
+ System.out.println("Loading keystore from: " + path);
+ keystore.load(inStream, password);
+ System.out.println("Loaded keystore with " + keystore.size() +
+ " entries");
+ }
+ } else {
+ keystore.load(null, null);
}
- KeyStore keystore = KeyStore.getInstance(type);
- System.out.println("Loading keystore from: " + path);
- keystore.load(stream, password);
return keystore;
}
--- a/jdk/test/java/util/Base64/TestBase64.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/test/java/util/Base64/TestBase64.java Tue Feb 05 11:11:53 2013 -0800
@@ -22,7 +22,7 @@
*/
/**
- * @test 4235519 8004212
+ * @test 4235519 8004212 8005394 8007298 8006295 8006315 8006530
* @summary tests java.util.Base64
*/
@@ -109,6 +109,15 @@
// test return value from decode(ByteBuffer, ByteBuffer)
testDecBufRet();
+
+ // test single-non-base64 character for mime decoding
+ testSingleNonBase64MimeDec();
+
+ // test decoding of unpadded data
+ testDecodeUnpadded();
+
+ // test mime decoding with ignored character after padding
+ testDecodeIgnoredAfterPadding();
}
private static sun.misc.BASE64Encoder sunmisc = new sun.misc.BASE64Encoder();
@@ -295,6 +304,7 @@
checkNull(new Runnable() { public void run() { enc.encode(bb_null); }});
checkNull(new Runnable() { public void run() { enc.encode(bb_null, ByteBuffer.allocate(10), 0); }});
checkNull(new Runnable() { public void run() { enc.encode(ByteBuffer.allocate(10), bb_null, 0); }});
+ checkNull(new Runnable() { public void run() { enc.wrap(null); }});
}
private static void testNull(final Base64.Decoder dec) {
@@ -305,6 +315,7 @@
checkNull(new Runnable() { public void run() { dec.decode(bb_null); }});
checkNull(new Runnable() { public void run() { dec.decode(bb_null, ByteBuffer.allocate(10)); }});
checkNull(new Runnable() { public void run() { dec.decode(ByteBuffer.allocate(10), bb_null); }});
+ checkNull(new Runnable() { public void run() { dec.wrap(null); }});
}
private static interface Testable {
@@ -354,6 +365,94 @@
} catch (IllegalArgumentException iae) {}
}
+ private static void testDecodeIgnoredAfterPadding() throws Throwable {
+ for (byte nonBase64 : new byte[] {'#', '(', '!', '\\', '-', '_', '\n', '\r'}) {
+ byte[][] src = new byte[][] {
+ "A".getBytes("ascii"),
+ "AB".getBytes("ascii"),
+ "ABC".getBytes("ascii"),
+ "ABCD".getBytes("ascii"),
+ "ABCDE".getBytes("ascii")
+ };
+ Base64.Encoder encM = Base64.getMimeEncoder();
+ Base64.Decoder decM = Base64.getMimeDecoder();
+ Base64.Encoder enc = Base64.getEncoder();
+ Base64.Decoder dec = Base64.getDecoder();
+ for (int i = 0; i < src.length; i++) {
+ // decode(byte[])
+ byte[] encoded = encM.encode(src[i]);
+ encoded = Arrays.copyOf(encoded, encoded.length + 1);
+ encoded[encoded.length - 1] = nonBase64;
+ checkEqual(decM.decode(encoded), src[i], "Non-base64 char is not ignored");
+ try {
+ dec.decode(encoded);
+ throw new RuntimeException("No IAE for non-base64 char");
+ } catch (IllegalArgumentException iae) {}
+
+ // decode(ByteBuffer[], ByteBuffer[])
+ ByteBuffer encodedBB = ByteBuffer.wrap(encoded);
+ ByteBuffer decodedBB = ByteBuffer.allocate(100);
+ int ret = decM.decode(encodedBB, decodedBB);
+ byte[] buf = new byte[ret];
+ decodedBB.flip();
+ decodedBB.get(buf);
+ checkEqual(buf, src[i], "Non-base64 char is not ignored");
+ try {
+ encodedBB.rewind();
+ decodedBB.clear();
+ dec.decode(encodedBB, decodedBB);
+ throw new RuntimeException("No IAE for non-base64 char");
+ } catch (IllegalArgumentException iae) {}
+ // direct
+ encodedBB.rewind();
+ decodedBB = ByteBuffer.allocateDirect(100);
+ ret = decM.decode(encodedBB, decodedBB);
+ buf = new byte[ret];
+ decodedBB.flip();
+ decodedBB.get(buf);
+ checkEqual(buf, src[i], "Non-base64 char is not ignored");
+ try {
+ encodedBB.rewind();
+ decodedBB.clear();
+ dec.decode(encodedBB, decodedBB);
+ throw new RuntimeException("No IAE for non-base64 char");
+ } catch (IllegalArgumentException iae) {}
+ }
+ }
+ }
+
+ private static void testDecodeUnpadded() throws Throwable {
+ byte[] srcA = new byte[] { 'Q', 'Q' };
+ byte[] srcAA = new byte[] { 'Q', 'Q', 'E'};
+ Base64.Decoder dec = Base64.getDecoder();
+ byte[] ret = dec.decode(srcA);
+ if (ret[0] != 'A')
+ throw new RuntimeException("Decoding unpadding input A failed");
+ ret = dec.decode(srcAA);
+ if (ret[0] != 'A' && ret[1] != 'A')
+ throw new RuntimeException("Decoding unpadding input AA failed");
+ ret = new byte[10];
+ if (dec.wrap(new ByteArrayInputStream(srcA)).read(ret) != 1 &&
+ ret[0] != 'A')
+ throw new RuntimeException("Decoding unpadding input A from stream failed");
+ if (dec.wrap(new ByteArrayInputStream(srcA)).read(ret) != 2 &&
+ ret[0] != 'A' && ret[1] != 'A')
+ throw new RuntimeException("Decoding unpadding input AA from stream failed");
+ }
+
+ // single-non-base64-char should be ignored for mime decoding, but
+ // iae for basic decoding
+ private static void testSingleNonBase64MimeDec() throws Throwable {
+ for (String nonBase64 : new String[] {"#", "(", "!", "\\", "-", "_"}) {
+ if (Base64.getMimeDecoder().decode(nonBase64).length != 0) {
+ throw new RuntimeException("non-base64 char is not ignored");
+ }
+ try {
+ Base64.getDecoder().decode(nonBase64);
+ throw new RuntimeException("No IAE for single non-base64 char");
+ } catch (IllegalArgumentException iae) {}
+ }
+ }
private static void testDecBufRet() throws Throwable {
Random rnd = new java.util.Random();
--- a/jdk/test/java/util/Formatter/Basic-X.java.template Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/test/java/util/Formatter/Basic-X.java.template Tue Feb 05 11:11:53 2013 -0800
@@ -1103,6 +1103,15 @@
test("%.5f", "1.99999", val);
test("%.6f", "1.999990", val);
+ val = new BigDecimal(0.9996);
+ test("%.0f", "1", val);
+ test("%.1f", "1.0", val);
+ test("%.2f", "1.00", val);
+ test("%.3f", "1.000", val);
+ test("%.4f", "0.9996", val);
+ test("%.5f", "0.99960", val);
+ test("%.6f", "0.999600", val);
+
#end[BigDecimal]
#if[float]
--- a/jdk/test/java/util/Formatter/BasicBigDecimal.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/test/java/util/Formatter/BasicBigDecimal.java Tue Feb 05 11:11:53 2013 -0800
@@ -1103,6 +1103,15 @@
test("%.5f", "1.99999", val);
test("%.6f", "1.999990", val);
+ val = new BigDecimal(0.9996);
+ test("%.0f", "1", val);
+ test("%.1f", "1.0", val);
+ test("%.2f", "1.00", val);
+ test("%.3f", "1.000", val);
+ test("%.4f", "0.9996", val);
+ test("%.5f", "0.99960", val);
+ test("%.6f", "0.999600", val);
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/HashMap/HashMapCloneLeak.java Tue Feb 05 11:11:53 2013 -0800
@@ -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);
+ }
+ }
+
+}
--- a/jdk/test/javax/management/remote/mandatory/notif/DeadListenerTest.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/test/javax/management/remote/mandatory/notif/DeadListenerTest.java Tue Feb 05 11:11:53 2013 -0800
@@ -31,6 +31,7 @@
import com.sun.jmx.remote.internal.ServerNotifForwarder;
import java.io.IOException;
import java.lang.management.ManagementFactory;
+import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
@@ -86,20 +87,26 @@
Map<ObjectName, Set<?>> listenerMap = (Map<ObjectName, Set<?>>) listenerMapF.get(serverNotifForwarder);
assertTrue("Server listenerMap initially empty", mapWithoutKey(listenerMap, delegateName).isEmpty());
- CountListener count1 = new CountListener();
+ final AtomicInteger count1Val = new AtomicInteger();
+ CountListener count1 = new CountListener(count1Val);
mbsc.addNotificationListener(name, count1, null, null);
+ WeakReference<CountListener> count1Ref = new WeakReference<>(count1);
+ count1 = null;
- CountListener count2 = new CountListener();
+ final AtomicInteger count2Val = new AtomicInteger();
+ CountListener count2 = new CountListener(count2Val);
NotificationFilterSupport dummyFilter = new NotificationFilterSupport();
dummyFilter.enableType("");
mbsc.addNotificationListener(name, count2, dummyFilter, "noddy");
+ WeakReference<CountListener> count2Ref = new WeakReference<>(count2);
+ count2 = null;
assertTrue("One entry in listenerMap for two listeners on same MBean", mapWithoutKey(listenerMap, delegateName).size() == 1);
Set<?> set = listenerMap.get(name);
assertTrue("Set in listenerMap for MBean has two elements", set != null && set.size() == 2);
- assertTrue("Initial value of count1 == 0", count1.count() == 0);
- assertTrue("Initial value of count2 == 0", count2.count() == 0);
+ assertTrue("Initial value of count1 == 0", count1Val.get() == 0);
+ assertTrue("Initial value of count2 == 0", count2Val.get() == 0);
Notification notif = new Notification("type", name, 0);
@@ -107,11 +114,11 @@
// Make sure notifs are working normally.
long deadline = System.currentTimeMillis() + 2000;
- while ((count1.count() != 1 || count2.count() != 1) && System.currentTimeMillis() < deadline) {
+ while ((count1Val.get() != 1 || count2Val.get() != 1) && System.currentTimeMillis() < deadline) {
Thread.sleep(10);
}
- assertTrue("New value of count1 == 1", count1.count() == 1);
- assertTrue("Initial value of count2 == 1", count2.count() == 1);
+ assertTrue("New value of count1 == 1", count1Val.get() == 1);
+ assertTrue("Initial value of count2 == 1", count2Val.get() == 1);
// Make sure that removing a nonexistent listener from an existent MBean produces ListenerNotFoundException
CountListener count3 = new CountListener();
@@ -136,28 +143,29 @@
mbs.unregisterMBean(name);
mbean.sendNotification(notif);
Thread.sleep(200);
- assertTrue("New value of count1 == 1", count1.count() == 1);
- assertTrue("Initial value of count2 == 1", count2.count() == 1);
+
+ assertTrue("New value of count1 == 1", count1Val.get() == 1);
+ assertTrue("Initial value of count2 == 1", count2Val.get() == 1);
+
+ // wait for the listener cleanup to take place upon processing notifications
+ int countdown = 50; // waiting max. 5 secs
+ while (countdown-- > 0 &&
+ (count1Ref.get() != null ||
+ count2Ref.get() != null)) {
+ System.gc();
+ Thread.sleep(100);
+ System.gc();
+ }
+ // listener has been removed or the wait has timed out
+
+ assertTrue("count1 notification listener has not been cleaned up", count1Ref.get() == null);
+ assertTrue("count2 notification listener has not been cleaned up", count2Ref.get() == null);
// Check that there is no trace of the listeners any more in ServerNotifForwarder.listenerMap.
// THIS DEPENDS ON JMX IMPLEMENTATION DETAILS.
// If the JMX implementation changes, the code here may have to change too.
Set<?> setForUnreg = listenerMap.get(name);
assertTrue("No trace of unregistered MBean: " + setForUnreg, setForUnreg == null);
-
- // Remove attempts should fail.
- try {
- mbsc.removeNotificationListener(name, count1);
- assertTrue("Remove of count1 listener should have failed", false);
- } catch (ListenerNotFoundException e) {
- // OK: expected
- }
- try {
- mbsc.removeNotificationListener(name, count2, dummyFilter, "noddy");
- assertTrue("Remove of count2 listener should have failed", false);
- } catch (ListenerNotFoundException e) {
- // OK: expected
- }
}
private static <K, V> Map<K, V> mapWithoutKey(Map<K, V> map, K key) {
@@ -173,6 +181,10 @@
public static class CountListener implements NotificationListener {
final AtomicInteger count;
+ public CountListener(AtomicInteger i) {
+ count = i;
+ }
+
public CountListener() {
this.count = new AtomicInteger();
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/management/jdp/JdpClient.java Tue Feb 05 11:11:53 2013 -0800
@@ -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);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/management/jdp/JdpDoSomething.java Tue Feb 05 11:11:53 2013 -0800
@@ -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");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/management/jdp/JdpTest.sh Tue Feb 05 11:11:53 2013 -0800
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/management/jdp/JdpUnitTest.java Tue Feb 05 11:11:53 2013 -0800
@@ -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);
+ }
+ }
+}
Binary file jdk/test/sun/net/ftp/EncDec.doc has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/net/ftp/MarkResetTest.java Tue Feb 05 11:11:53 2013 -0800
@@ -0,0 +1,455 @@
+/*
+ * Copyright (c) 2002, 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.
+ */
+
+/*
+ *
+ * run from MarkResetTest.sh
+ */
+
+import java.io.*;
+import java.net.*;
+import java.util.regex.*;
+
+public class MarkResetTest {
+
+ /**
+ * A class that simulates, on a separate, an FTP server.
+ */
+ private class FtpServer extends Thread {
+ private ServerSocket server;
+ private int port;
+ private boolean done = false;
+ private boolean pasvEnabled = true;
+ private boolean portEnabled = true;
+ private boolean extendedEnabled = true;
+
+ /**
+ * This Inner class will handle ONE client at a time.
+ * That's where 99% of the protocol handling is done.
+ */
+
+ private class FtpServerHandler extends Thread {
+ BufferedReader in;
+ PrintWriter out;
+ Socket client;
+ private final int ERROR = 0;
+ private final int USER = 1;
+ private final int PASS = 2;
+ private final int CWD = 3;
+ private final int TYPE = 4;
+ private final int RETR = 5;
+ private final int PASV = 6;
+ private final int PORT = 7;
+ private final int QUIT = 8;
+ private final int EPSV = 9;
+ String[] cmds = { "USER", "PASS", "CWD",
+ "TYPE", "RETR", "PASV",
+ "PORT", "QUIT", "EPSV"};
+ private String arg = null;
+ private ServerSocket pasv = null;
+ private int data_port = 0;
+ private InetAddress data_addr = null;
+
+ /**
+ * Parses a line to match it with one of the supported FTP commands.
+ * Returns the command number.
+ */
+
+ private int parseCmd(String cmd) {
+ if (cmd == null || cmd.length() < 3)
+ return ERROR;
+ int blank = cmd.indexOf(' ');
+ if (blank < 0)
+ blank = cmd.length();
+ if (blank < 3)
+ return ERROR;
+ String s = cmd.substring(0, blank);
+ if (cmd.length() > blank+1)
+ arg = cmd.substring(blank+1, cmd.length());
+ else
+ arg = null;
+ for (int i = 0; i < cmds.length; i++) {
+ if (s.equalsIgnoreCase(cmds[i]))
+ return i+1;
+ }
+ return ERROR;
+ }
+
+ public FtpServerHandler(Socket cl) {
+ client = cl;
+ }
+
+ protected boolean isPasvSet() {
+ if (pasv != null && !pasvEnabled) {
+ try {
+ pasv.close();
+ } catch (IOException ex) {
+ }
+ pasv = null;
+ }
+ if (pasvEnabled && pasv != null)
+ return true;
+ return false;
+ }
+
+ /**
+ * Open the data socket with the client. This can be the
+ * result of a "PASV" or "PORT" command.
+ */
+
+ protected OutputStream getOutDataStream() {
+ try {
+ if (isPasvSet()) {
+ Socket s = pasv.accept();
+ return s.getOutputStream();
+ }
+ if (data_addr != null) {
+ Socket s = new Socket(data_addr, data_port);
+ data_addr = null;
+ data_port = 0;
+ return s.getOutputStream();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ protected InputStream getInDataStream() {
+ try {
+ if (isPasvSet()) {
+ Socket s = pasv.accept();
+ return s.getInputStream();
+ }
+ if (data_addr != null) {
+ Socket s = new Socket(data_addr, data_port);
+ data_addr = null;
+ data_port = 0;
+ return s.getInputStream();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * Handles the protocol exchange with the client.
+ */
+
+ public void run() {
+ boolean done = false;
+ String str;
+ int res;
+ boolean logged = false;
+ boolean waitpass = false;
+
+ try {
+ in = new BufferedReader(new InputStreamReader(
+ client.getInputStream()));
+ out = new PrintWriter(client.getOutputStream(), true);
+ out.println("220 tatooine FTP server (SunOS 5.8) ready.");
+ } catch (Exception ex) {
+ return;
+ }
+ while (!done) {
+ try {
+ str = in.readLine();
+ res = parseCmd(str);
+ if ((res > PASS && res != QUIT) && !logged) {
+ out.println("530 Not logged in.");
+ continue;
+ }
+ switch (res) {
+ case ERROR:
+ out.println("500 '" + str +
+ "': command not understood.");
+ break;
+ case USER:
+ if (!logged && !waitpass) {
+ out.println("331 Password required for " + arg);
+ waitpass = true;
+ } else {
+ out.println("503 Bad sequence of commands.");
+ }
+ break;
+ case PASS:
+ if (!logged && waitpass) {
+ out.println("230-Welcome to the FTP server!");
+ out.println("ab");
+ out.println("230 Guest login ok, " +
+ "access restrictions apply.");
+ logged = true;
+ waitpass = false;
+ } else
+ out.println("503 Bad sequence of commands.");
+ break;
+ case QUIT:
+ out.println("221 Goodbye.");
+ out.flush();
+ out.close();
+ if (pasv != null)
+ pasv.close();
+ done = true;
+ break;
+ case TYPE:
+ out.println("200 Type set to " + arg + ".");
+ break;
+ case CWD:
+ out.println("250 CWD command successful.");
+ break;
+ case EPSV:
+ if (!extendedEnabled || !pasvEnabled) {
+ out.println("500 EPSV is disabled, " +
+ "use PORT instead.");
+ continue;
+ }
+ if ("all".equalsIgnoreCase(arg)) {
+ out.println("200 EPSV ALL command successful.");
+ continue;
+ }
+ try {
+ if (pasv == null)
+ pasv = new ServerSocket(0);
+ int port = pasv.getLocalPort();
+ out.println("229 Entering Extended" +
+ " Passive Mode (|||" + port + "|)");
+ } catch (IOException ssex) {
+ out.println("425 Can't build data connection:" +
+ " Connection refused.");
+ }
+ break;
+
+ case PASV:
+ if (!pasvEnabled) {
+ out.println("500 PASV is disabled, " +
+ "use PORT instead.");
+ continue;
+ }
+ try {
+ if (pasv == null)
+ pasv = new ServerSocket(0);
+ int port = pasv.getLocalPort();
+
+ // Parenthesis are optional, so let's be
+ // nasty and don't put them
+ out.println("227 Entering Passive Mode" +
+ " 127,0,0,1," +
+ (port >> 8) + "," + (port & 0xff));
+ } catch (IOException ssex) {
+ out.println("425 Can't build data connection:" +
+ "Connection refused.");
+ }
+ break;
+ case PORT:
+ if (!portEnabled) {
+ out.println("500 PORT is disabled, " +
+ "use PASV instead");
+ continue;
+ }
+ StringBuffer host;
+ int i = 0, j = 4;
+ while (j > 0) {
+ i = arg.indexOf(',', i + 1);
+ if (i < 0)
+ break;
+ j--;
+ }
+ if (j != 0) {
+ out.println("500 '" + arg + "':" +
+ " command not understood.");
+ continue;
+ }
+ try {
+ host = new StringBuffer(arg.substring(0, i));
+ for (j = 0; j < host.length(); j++)
+ if (host.charAt(j) == ',')
+ host.setCharAt(j, '.');
+ String ports = arg.substring(i+1);
+ i = ports.indexOf(',');
+ data_port = Integer.parseInt(
+ ports.substring(0, i)) << 8;
+ data_port += (Integer.parseInt(
+ ports.substring(i+1)));
+ data_addr = InetAddress.getByName(
+ host.toString());
+ out.println("200 Command okay.");
+ } catch (Exception ex3) {
+ data_port = 0;
+ data_addr = null;
+ out.println("500 '" + arg + "':" +
+ " command not understood.");
+ }
+ break;
+ case RETR:
+ {
+ File file = new File(arg);
+ if (!file.exists()) {
+ System.out.println("File not found");
+ out.println("200 Command okay.");
+ out.println("550 '" + arg +
+ "' No such file or directory.");
+ break;
+ }
+ FileInputStream fin = new FileInputStream(file);
+ OutputStream dout = getOutDataStream();
+ if (dout != null) {
+ out.println("150 Binary data connection" +
+ " for " + arg +
+ " (" + client.getInetAddress().
+ getHostAddress() + ") (" +
+ file.length() + " bytes).");
+ int c;
+ int len = 0;
+ while ((c = fin.read()) != -1) {
+ dout.write(c);
+ len++;
+ }
+ dout.flush();
+ dout.close();
+ fin.close();
+ out.println("226 Binary Transfer complete.");
+ } else {
+ out.println("425 Can't build data" +
+ " connection: Connection refused.");
+ }
+ }
+ break;
+ }
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ try {
+ out.close();
+ } catch (Exception ex2) {
+ }
+ done = true;
+ }
+ }
+ }
+ }
+
+ public FtpServer(int port) {
+ this.port = port;
+ }
+
+ public FtpServer() {
+ this(21);
+ }
+
+ public int getPort() {
+ if (server != null)
+ return server.getLocalPort();
+ return 0;
+ }
+
+ /**
+ * A way to tell the server that it can stop.
+ */
+ synchronized public void terminate() {
+ done = true;
+ }
+
+
+ /*
+ * All we got to do here is create a ServerSocket and wait for a
+ * connection. When a connection happens, we just have to create
+ * a thread that will handle it.
+ */
+ public void run() {
+ try {
+ server = new ServerSocket(port);
+ Socket client;
+ client = server.accept();
+ (new FtpServerHandler(client)).start();
+ server.close();
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ MarkResetTest test = new MarkResetTest();
+ }
+
+ public MarkResetTest() {
+ FtpServer server = null;
+ try {
+ server = new FtpServer(0);
+ server.start();
+ int port = 0;
+ while (port == 0) {
+ Thread.sleep(500);
+ port = server.getPort();
+ }
+
+ String filename = "EncDec.doc";
+ URL url = new URL("ftp://localhost:" + port + "/" +
+ filename);
+
+ URLConnection con = url.openConnection();
+ System.out.println("getContent: " + con.getContent());
+ System.out.println("getContent-length: " + con.getContentLength());
+
+ InputStream is = con.getInputStream();
+
+ /**
+ * guessContentTypeFromStream method calls mark and reset methods
+ * on the given stream. Make sure that calling
+ * guessContentTypeFromStream repeatedly does not affect
+ * reading from the stream afterwards
+ */
+ System.out.println("Call GuessContentTypeFromStream()" +
+ " several times..");
+ for (int i = 0; i < 5; i++) {
+ System.out.println((i + 1) + " mime-type: " +
+ con.guessContentTypeFromStream(is));
+ }
+
+ int len = 0;
+ int c;
+ while ((c = is.read()) != -1) {
+ len++;
+ }
+ is.close();
+ System.out.println("read: " + len + " bytes of the file");
+
+ // We're done!
+ server.terminate();
+ server.interrupt();
+
+ // Did we pass ?
+ if (len != (new File(filename)).length()) {
+ throw new Exception("Failed to read the file correctly");
+ }
+ System.out.println("PASSED: File read correctly");
+ } catch (Exception e) {
+ e.printStackTrace();
+ try {
+ server.terminate();
+ server.interrupt();
+ } catch (Exception ex) {
+ }
+ throw new RuntimeException("FTP support error: " + e.getMessage());
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/net/ftp/MarkResetTest.sh Tue Feb 05 11:11:53 2013 -0800
@@ -0,0 +1,55 @@
+#
+# Copyright (c) 2002, 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 4673103
+# @run shell/timeout=140 MarkResetTest.sh
+# @summary URLConnection.getContent() hangs over FTP for DOC, PPT, XLS files
+
+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}MarkResetTest.java
+
+# ftp server used by the test requires the file to be present
+# in this directory
+cp ${TESTSRC}${FS}EncDec.doc .
+
+${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} MarkResetTest
Binary file jdk/test/sun/net/www/EncDec.doc has changed
--- a/jdk/test/sun/net/www/MarkResetTest.java Tue Feb 05 11:10:07 2013 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,455 +0,0 @@
-/*
- * Copyright (c) 2002, 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.
- */
-
-/*
- *
- * run from MarkResetTest.sh
- */
-
-import java.io.*;
-import java.net.*;
-import java.util.regex.*;
-
-public class MarkResetTest {
-
- /**
- * A class that simulates, on a separate, an FTP server.
- */
- private class FtpServer extends Thread {
- private ServerSocket server;
- private int port;
- private boolean done = false;
- private boolean pasvEnabled = true;
- private boolean portEnabled = true;
- private boolean extendedEnabled = true;
-
- /**
- * This Inner class will handle ONE client at a time.
- * That's where 99% of the protocol handling is done.
- */
-
- private class FtpServerHandler extends Thread {
- BufferedReader in;
- PrintWriter out;
- Socket client;
- private final int ERROR = 0;
- private final int USER = 1;
- private final int PASS = 2;
- private final int CWD = 3;
- private final int TYPE = 4;
- private final int RETR = 5;
- private final int PASV = 6;
- private final int PORT = 7;
- private final int QUIT = 8;
- private final int EPSV = 9;
- String[] cmds = { "USER", "PASS", "CWD",
- "TYPE", "RETR", "PASV",
- "PORT", "QUIT", "EPSV"};
- private String arg = null;
- private ServerSocket pasv = null;
- private int data_port = 0;
- private InetAddress data_addr = null;
-
- /**
- * Parses a line to match it with one of the supported FTP commands.
- * Returns the command number.
- */
-
- private int parseCmd(String cmd) {
- if (cmd == null || cmd.length() < 3)
- return ERROR;
- int blank = cmd.indexOf(' ');
- if (blank < 0)
- blank = cmd.length();
- if (blank < 3)
- return ERROR;
- String s = cmd.substring(0, blank);
- if (cmd.length() > blank+1)
- arg = cmd.substring(blank+1, cmd.length());
- else
- arg = null;
- for (int i = 0; i < cmds.length; i++) {
- if (s.equalsIgnoreCase(cmds[i]))
- return i+1;
- }
- return ERROR;
- }
-
- public FtpServerHandler(Socket cl) {
- client = cl;
- }
-
- protected boolean isPasvSet() {
- if (pasv != null && !pasvEnabled) {
- try {
- pasv.close();
- } catch (IOException ex) {
- }
- pasv = null;
- }
- if (pasvEnabled && pasv != null)
- return true;
- return false;
- }
-
- /**
- * Open the data socket with the client. This can be the
- * result of a "PASV" or "PORT" command.
- */
-
- protected OutputStream getOutDataStream() {
- try {
- if (isPasvSet()) {
- Socket s = pasv.accept();
- return s.getOutputStream();
- }
- if (data_addr != null) {
- Socket s = new Socket(data_addr, data_port);
- data_addr = null;
- data_port = 0;
- return s.getOutputStream();
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
-
- protected InputStream getInDataStream() {
- try {
- if (isPasvSet()) {
- Socket s = pasv.accept();
- return s.getInputStream();
- }
- if (data_addr != null) {
- Socket s = new Socket(data_addr, data_port);
- data_addr = null;
- data_port = 0;
- return s.getInputStream();
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
-
- /**
- * Handles the protocol exchange with the client.
- */
-
- public void run() {
- boolean done = false;
- String str;
- int res;
- boolean logged = false;
- boolean waitpass = false;
-
- try {
- in = new BufferedReader(new InputStreamReader(
- client.getInputStream()));
- out = new PrintWriter(client.getOutputStream(), true);
- out.println("220 tatooine FTP server (SunOS 5.8) ready.");
- } catch (Exception ex) {
- return;
- }
- while (!done) {
- try {
- str = in.readLine();
- res = parseCmd(str);
- if ((res > PASS && res != QUIT) && !logged) {
- out.println("530 Not logged in.");
- continue;
- }
- switch (res) {
- case ERROR:
- out.println("500 '" + str +
- "': command not understood.");
- break;
- case USER:
- if (!logged && !waitpass) {
- out.println("331 Password required for " + arg);
- waitpass = true;
- } else {
- out.println("503 Bad sequence of commands.");
- }
- break;
- case PASS:
- if (!logged && waitpass) {
- out.println("230-Welcome to the FTP server!");
- out.println("ab");
- out.println("230 Guest login ok, " +
- "access restrictions apply.");
- logged = true;
- waitpass = false;
- } else
- out.println("503 Bad sequence of commands.");
- break;
- case QUIT:
- out.println("221 Goodbye.");
- out.flush();
- out.close();
- if (pasv != null)
- pasv.close();
- done = true;
- break;
- case TYPE:
- out.println("200 Type set to " + arg + ".");
- break;
- case CWD:
- out.println("250 CWD command successful.");
- break;
- case EPSV:
- if (!extendedEnabled || !pasvEnabled) {
- out.println("500 EPSV is disabled, " +
- "use PORT instead.");
- continue;
- }
- if ("all".equalsIgnoreCase(arg)) {
- out.println("200 EPSV ALL command successful.");
- continue;
- }
- try {
- if (pasv == null)
- pasv = new ServerSocket(0);
- int port = pasv.getLocalPort();
- out.println("229 Entering Extended" +
- " Passive Mode (|||" + port + "|)");
- } catch (IOException ssex) {
- out.println("425 Can't build data connection:" +
- " Connection refused.");
- }
- break;
-
- case PASV:
- if (!pasvEnabled) {
- out.println("500 PASV is disabled, " +
- "use PORT instead.");
- continue;
- }
- try {
- if (pasv == null)
- pasv = new ServerSocket(0);
- int port = pasv.getLocalPort();
-
- // Parenthesis are optional, so let's be
- // nasty and don't put them
- out.println("227 Entering Passive Mode" +
- " 127,0,0,1," +
- (port >> 8) + "," + (port & 0xff));
- } catch (IOException ssex) {
- out.println("425 Can't build data connection:" +
- "Connection refused.");
- }
- break;
- case PORT:
- if (!portEnabled) {
- out.println("500 PORT is disabled, " +
- "use PASV instead");
- continue;
- }
- StringBuffer host;
- int i = 0, j = 4;
- while (j > 0) {
- i = arg.indexOf(',', i + 1);
- if (i < 0)
- break;
- j--;
- }
- if (j != 0) {
- out.println("500 '" + arg + "':" +
- " command not understood.");
- continue;
- }
- try {
- host = new StringBuffer(arg.substring(0, i));
- for (j = 0; j < host.length(); j++)
- if (host.charAt(j) == ',')
- host.setCharAt(j, '.');
- String ports = arg.substring(i+1);
- i = ports.indexOf(',');
- data_port = Integer.parseInt(
- ports.substring(0, i)) << 8;
- data_port += (Integer.parseInt(
- ports.substring(i+1)));
- data_addr = InetAddress.getByName(
- host.toString());
- out.println("200 Command okay.");
- } catch (Exception ex3) {
- data_port = 0;
- data_addr = null;
- out.println("500 '" + arg + "':" +
- " command not understood.");
- }
- break;
- case RETR:
- {
- File file = new File(arg);
- if (!file.exists()) {
- System.out.println("File not found");
- out.println("200 Command okay.");
- out.println("550 '" + arg +
- "' No such file or directory.");
- break;
- }
- FileInputStream fin = new FileInputStream(file);
- OutputStream dout = getOutDataStream();
- if (dout != null) {
- out.println("150 Binary data connection" +
- " for " + arg +
- " (" + client.getInetAddress().
- getHostAddress() + ") (" +
- file.length() + " bytes).");
- int c;
- int len = 0;
- while ((c = fin.read()) != -1) {
- dout.write(c);
- len++;
- }
- dout.flush();
- dout.close();
- fin.close();
- out.println("226 Binary Transfer complete.");
- } else {
- out.println("425 Can't build data" +
- " connection: Connection refused.");
- }
- }
- break;
- }
- } catch (IOException ioe) {
- ioe.printStackTrace();
- try {
- out.close();
- } catch (Exception ex2) {
- }
- done = true;
- }
- }
- }
- }
-
- public FtpServer(int port) {
- this.port = port;
- }
-
- public FtpServer() {
- this(21);
- }
-
- public int getPort() {
- if (server != null)
- return server.getLocalPort();
- return 0;
- }
-
- /**
- * A way to tell the server that it can stop.
- */
- synchronized public void terminate() {
- done = true;
- }
-
-
- /*
- * All we got to do here is create a ServerSocket and wait for a
- * connection. When a connection happens, we just have to create
- * a thread that will handle it.
- */
- public void run() {
- try {
- server = new ServerSocket(port);
- Socket client;
- client = server.accept();
- (new FtpServerHandler(client)).start();
- server.close();
- } catch (Exception e) {
- }
- }
- }
-
- public static void main(String[] args) throws Exception {
- MarkResetTest test = new MarkResetTest();
- }
-
- public MarkResetTest() {
- FtpServer server = null;
- try {
- server = new FtpServer(0);
- server.start();
- int port = 0;
- while (port == 0) {
- Thread.sleep(500);
- port = server.getPort();
- }
-
- String filename = "EncDec.doc";
- URL url = new URL("ftp://localhost:" + port + "/" +
- filename);
-
- URLConnection con = url.openConnection();
- System.out.println("getContent: " + con.getContent());
- System.out.println("getContent-length: " + con.getContentLength());
-
- InputStream is = con.getInputStream();
-
- /**
- * guessContentTypeFromStream method calls mark and reset methods
- * on the given stream. Make sure that calling
- * guessContentTypeFromStream repeatedly does not affect
- * reading from the stream afterwards
- */
- System.out.println("Call GuessContentTypeFromStream()" +
- " several times..");
- for (int i = 0; i < 5; i++) {
- System.out.println((i + 1) + " mime-type: " +
- con.guessContentTypeFromStream(is));
- }
-
- int len = 0;
- int c;
- while ((c = is.read()) != -1) {
- len++;
- }
- is.close();
- System.out.println("read: " + len + " bytes of the file");
-
- // We're done!
- server.terminate();
- server.interrupt();
-
- // Did we pass ?
- if (len != (new File(filename)).length()) {
- throw new Exception("Failed to read the file correctly");
- }
- System.out.println("PASSED: File read correctly");
- } catch (Exception e) {
- e.printStackTrace();
- try {
- server.terminate();
- server.interrupt();
- } catch (Exception ex) {
- }
- throw new RuntimeException("FTP support error: " + e.getMessage());
- }
- }
-}
--- a/jdk/test/sun/net/www/MarkResetTest.sh Tue Feb 05 11:10:07 2013 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-#
-# Copyright (c) 2002, 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 4673103
-# @run shell/timeout=140 MarkResetTest.sh
-# @summary URLConnection.getContent() hangs over FTP for DOC, PPT, XLS files
-
-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}MarkResetTest.java
-
-# ftp server used by the test requires the file to be present
-# in this directory
-cp ${TESTSRC}${FS}EncDec.doc .
-
-${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} MarkResetTest
--- a/jdk/test/sun/net/www/http/HttpClient/ProxyTest.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/test/sun/net/www/http/HttpClient/ProxyTest.java Tue Feb 05 11:11:53 2013 -0800
@@ -161,8 +161,18 @@
}
}
+ private static boolean hasFtp() {
+ try {
+ return new java.net.URL("ftp://") != null;
+ } catch (java.net.MalformedURLException x) {
+ System.out.println("FTP not supported by this runtime.");
+ return false;
+ }
+ }
+
public static void main(String[] args) throws Exception {
- ProxyTest test = new ProxyTest();
+ if (hasFtp())
+ new ProxyTest();
}
public ProxyTest() throws Exception {
--- a/jdk/test/sun/security/pkcs12/StorePasswordTest.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/test/sun/security/pkcs12/StorePasswordTest.java Tue Feb 05 11:11:53 2013 -0800
@@ -47,40 +47,49 @@
new File(KEYSTORE).delete();
- try {
-
- KeyStore keystore = KeyStore.getInstance("PKCS12");
- keystore.load(null, null);
+ KeyStore keystore = KeyStore.getInstance("PKCS12");
+ keystore.load(null, null);
- // Set entry
- keystore.setEntry(ALIAS,
- new KeyStore.SecretKeyEntry(convertPassword(USER_PASSWORD)),
- new KeyStore.PasswordProtection(PASSWORD));
+ // Set entry
+ Set<KeyStore.Entry.Attribute> attrs = new HashSet<>();
+ attrs.add(new PKCS12Attribute("1.3.5.7.9", "printable1"));
+ attrs.add(new PKCS12Attribute("2.4.6.8.10", "1F:2F:3F:4F:5F"));
+ int originalAttrCount = attrs.size() + 2;
+ keystore.setEntry(ALIAS,
+ new KeyStore.SecretKeyEntry(convertPassword(USER_PASSWORD), attrs),
+ new KeyStore.PasswordProtection(PASSWORD));
+ try (FileOutputStream outStream = new FileOutputStream(KEYSTORE)) {
System.out.println("Storing keystore to: " + KEYSTORE);
- keystore.store(new FileOutputStream(KEYSTORE), PASSWORD);
+ keystore.store(outStream, PASSWORD);
+ }
+ try (FileInputStream inStream = new FileInputStream(KEYSTORE)) {
System.out.println("Loading keystore from: " + KEYSTORE);
- keystore.load(new FileInputStream(KEYSTORE), PASSWORD);
+ keystore.load(inStream, PASSWORD);
System.out.println("Loaded keystore with " + keystore.size() +
" entries");
- KeyStore.Entry entry = keystore.getEntry(ALIAS,
- new KeyStore.PasswordProtection(PASSWORD));
- System.out.println("Retrieved entry: " + entry);
+ }
+
+ KeyStore.Entry entry = keystore.getEntry(ALIAS,
+ new KeyStore.PasswordProtection(PASSWORD));
+ int attrCount = entry.getAttributes().size();
+ System.out.println("Retrieved entry with " + attrCount + " attrs: " +
+ entry);
+ if (attrCount != originalAttrCount) {
+ throw new Exception("Failed to recover all the entry attributes");
+ }
- SecretKey key = (SecretKey) keystore.getKey(ALIAS, PASSWORD);
- SecretKeyFactory factory =
- SecretKeyFactory.getInstance(key.getAlgorithm());
- PBEKeySpec keySpec =
- (PBEKeySpec) factory.getKeySpec(key, PBEKeySpec.class);
- char[] pwd = keySpec.getPassword();
- System.out.println("Recovered credential: " + new String(pwd));
+ SecretKey key = (SecretKey) keystore.getKey(ALIAS, PASSWORD);
+ SecretKeyFactory factory =
+ SecretKeyFactory.getInstance(key.getAlgorithm());
+ PBEKeySpec keySpec =
+ (PBEKeySpec) factory.getKeySpec(key, PBEKeySpec.class);
+ char[] pwd = keySpec.getPassword();
+ System.out.println("Recovered credential: " + new String(pwd));
- if (!Arrays.equals(USER_PASSWORD.toCharArray(), pwd)) {
- throw new Exception("Failed to recover the stored password");
- }
- } finally {
- new File(KEYSTORE).delete();
+ if (!Arrays.equals(USER_PASSWORD.toCharArray(), pwd)) {
+ throw new Exception("Failed to recover the stored password");
}
}
--- a/jdk/test/sun/security/pkcs12/StoreSecretKeyTest.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/test/sun/security/pkcs12/StoreSecretKeyTest.java Tue Feb 05 11:11:53 2013 -0800
@@ -53,35 +53,34 @@
new File(KEYSTORE).delete();
- try {
+ KeyStore keystore = KeyStore.getInstance("PKCS12");
+ keystore.load(null, null);
- KeyStore keystore = KeyStore.getInstance("PKCS12");
- keystore.load(null, null);
+ // Set entry
+ keystore.setEntry(ALIAS,
+ new KeyStore.SecretKeyEntry(generateSecretKey("AES", 128)),
+ new KeyStore.PasswordProtection(PASSWORD));
- // Set entry
- keystore.setEntry(ALIAS,
- new KeyStore.SecretKeyEntry(generateSecretKey("AES", 128)),
- new KeyStore.PasswordProtection(PASSWORD));
+ try (FileOutputStream outStream = new FileOutputStream(KEYSTORE)) {
+ System.out.println("Storing keystore to: " + KEYSTORE);
+ keystore.store(outStream, PASSWORD);
+ }
- System.out.println("Storing keystore to: " + KEYSTORE);
- keystore.store(new FileOutputStream(KEYSTORE), PASSWORD);
-
+ try (FileInputStream inStream = new FileInputStream(KEYSTORE)) {
System.out.println("Loading keystore from: " + KEYSTORE);
- keystore.load(new FileInputStream(KEYSTORE), PASSWORD);
+ keystore.load(inStream, PASSWORD);
System.out.println("Loaded keystore with " + keystore.size() +
" entries");
- KeyStore.Entry entry = keystore.getEntry(ALIAS,
- new KeyStore.PasswordProtection(PASSWORD));
- System.out.println("Retrieved entry: " + entry);
+ }
- if (entry instanceof KeyStore.SecretKeyEntry) {
- System.out.println("Retrieved secret key entry: " +
- entry);
- } else {
- throw new Exception("Not a secret key entry");
- }
- } finally {
- new File(KEYSTORE).delete();
+ KeyStore.Entry entry = keystore.getEntry(ALIAS,
+ new KeyStore.PasswordProtection(PASSWORD));
+ System.out.println("Retrieved entry: " + entry);
+
+ if (entry instanceof KeyStore.SecretKeyEntry) {
+ System.out.println("Retrieved secret key entry: " + entry);
+ } else {
+ throw new Exception("Not a secret key entry");
}
}
--- a/jdk/test/sun/security/pkcs12/StoreTrustedCertTest.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/test/sun/security/pkcs12/StoreTrustedCertTest.java Tue Feb 05 11:11:53 2013 -0800
@@ -49,59 +49,57 @@
new File(KEYSTORE).delete();
- try {
- KeyStore keystore = KeyStore.getInstance("PKCS12");
- keystore.load(null, null);
+ KeyStore keystore = KeyStore.getInstance("PKCS12");
+ keystore.load(null, null);
- Certificate cert = loadCertificate(CERT);
- Set<KeyStore.Entry.Attribute> attributes = new HashSet<>();
- attributes.add(new PKCS12Attribute("1.3.5.7.9", "that's odd"));
- attributes.add(new PKCS12Attribute("2.4.6.8.10", "that's even"));
+ Certificate cert = loadCertificate(CERT);
+ Set<KeyStore.Entry.Attribute> attributes = new HashSet<>();
+ attributes.add(new PKCS12Attribute("1.3.5.7.9", "that's odd"));
+ attributes.add(new PKCS12Attribute("2.4.6.8.10", "that's even"));
+
+ // Set trusted certificate entry
+ keystore.setEntry(ALIAS,
+ new KeyStore.TrustedCertificateEntry(cert), null);
- // Set trusted certificate entry
- keystore.setEntry(ALIAS,
- new KeyStore.TrustedCertificateEntry(cert), null);
+ // Set trusted certificate entry with attributes
+ keystore.setEntry(ALIAS2,
+ new KeyStore.TrustedCertificateEntry(cert, attributes), null);
- // Set trusted certificate entry with attributes
- keystore.setEntry(ALIAS2,
- new KeyStore.TrustedCertificateEntry(cert, attributes), null);
-
+ try (FileOutputStream outStream = new FileOutputStream(KEYSTORE)) {
System.out.println("Storing keystore to: " + KEYSTORE);
- keystore.store(new FileOutputStream(KEYSTORE), PASSWORD);
+ keystore.store(outStream, PASSWORD);
+ }
+ try (FileInputStream inStream = new FileInputStream(KEYSTORE)) {
System.out.println("Loading keystore from: " + KEYSTORE);
- keystore.load(new FileInputStream(KEYSTORE), PASSWORD);
+ keystore.load(inStream, PASSWORD);
System.out.println("Loaded keystore with " + keystore.size() +
" entries");
+ }
- KeyStore.Entry entry = keystore.getEntry(ALIAS, null);
- if (entry instanceof KeyStore.TrustedCertificateEntry) {
- System.out.println("Retrieved trusted certificate entry: " +
- entry);
- } else {
- throw new Exception("Not a trusted certificate entry");
- }
- System.out.println();
+ KeyStore.Entry entry = keystore.getEntry(ALIAS, null);
+ if (entry instanceof KeyStore.TrustedCertificateEntry) {
+ System.out.println("Retrieved trusted certificate entry: " + entry);
+ } else {
+ throw new Exception("Not a trusted certificate entry");
+ }
+ System.out.println();
- entry = keystore.getEntry(ALIAS2, null);
- if (entry instanceof KeyStore.TrustedCertificateEntry) {
- KeyStore.TrustedCertificateEntry trustedEntry =
- (KeyStore.TrustedCertificateEntry) entry;
- Set<KeyStore.Entry.Attribute> entryAttributes =
- trustedEntry.getAttributes();
+ entry = keystore.getEntry(ALIAS2, null);
+ if (entry instanceof KeyStore.TrustedCertificateEntry) {
+ KeyStore.TrustedCertificateEntry trustedEntry =
+ (KeyStore.TrustedCertificateEntry) entry;
+ Set<KeyStore.Entry.Attribute> entryAttributes =
+ trustedEntry.getAttributes();
- if (entryAttributes.containsAll(attributes)) {
- System.out.println("Retrieved trusted certificate entry " +
- "with attributes: " + entry);
- } else {
- throw new Exception("Failed to retrieve entry attributes");
- }
+ if (entryAttributes.containsAll(attributes)) {
+ System.out.println("Retrieved trusted certificate entry " +
+ "with attributes: " + entry);
} else {
- throw new Exception("Not a trusted certificate entry");
+ throw new Exception("Failed to retrieve entry attributes");
}
-
- } finally {
- new File(KEYSTORE).delete();
+ } else {
+ throw new Exception("Not a trusted certificate entry");
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/util/Oid/S11N.java Tue Feb 05 11:11:53 2013 -0800
@@ -0,0 +1,246 @@
+/*
+ * 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 4811968 6908628 8006564
+ * @run main S11N check
+ * @summary Serialization compatibility with old versions (and fixes)
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.HashMap;
+import java.util.Map;
+import sun.misc.BASE64Encoder;
+import sun.security.util.ObjectIdentifier;
+
+public class S11N {
+ static String[] SMALL= {
+ "0.0",
+ "1.1",
+ "2.2",
+ "1.2.3456",
+ "1.2.2147483647.4",
+ "1.2.268435456.4",
+ };
+
+ static String[] HUGE = {
+ "2.16.764.1.3101555394.1.0.100.2.1",
+ "1.2.2147483648.4",
+ "2.3.4444444444444444444444",
+ "1.2.8888888888888888.33333333333333333.44444444444444",
+ };
+
+ // Do not use j.u.Base64, the test needs to run in jdk6
+ static BASE64Encoder encoder = new BASE64Encoder() {
+ @Override
+ protected int bytesPerLine() {
+ return 48;
+ }
+ };
+
+ public static void main(String[] args) throws Exception {
+ if (args[0].equals("check")) {
+ int version = Integer.valueOf(System.getProperty("java.version")
+ .split("\\.")[1]);
+ System.out.println("version is " + version);
+ if (version >= 7) {
+ for (String oid: SMALL) {
+ // 7 -> 7
+ check(out(oid), oid);
+ // 6 -> 7
+ check(out6(oid), oid);
+ }
+ for (String oid: HUGE) {
+ // 7 -> 7
+ check(out(oid), oid);
+ }
+ } else {
+ for (String oid: SMALL) {
+ // 6 -> 6
+ check(out(oid), oid);
+ // 7 -> 6
+ check(out7(oid), oid);
+ }
+ for (String oid: HUGE) {
+ // 7 -> 6 fails for HUGE oids
+ boolean ok = false;
+ try {
+ check(out7(oid), oid);
+ ok = true;
+ } catch (Exception e) {
+ System.out.println(e);
+ }
+ if (ok) {
+ throw new Exception();
+ }
+ }
+ }
+ } else {
+ // Generates the JDK6 serialized string inside this test, call
+ // $JDK7/bin/java S11N dump7
+ // $JDK6/bin/java S11N dump6
+ // and paste the output at the end of this test.
+ dump(args[0], SMALL);
+ // For jdk6, the following line will throw an exception, ignore it
+ dump(args[0], HUGE);
+ }
+ }
+
+ // Gets the serialized form for jdk6
+ private static byte[] out6(String oid) throws Exception {
+ return new sun.misc.BASE64Decoder().decodeBuffer(dump6.get(oid));
+ }
+
+ // Gets the serialized form for jdk7
+ private static byte[] out7(String oid) throws Exception {
+ return new sun.misc.BASE64Decoder().decodeBuffer(dump7.get(oid));
+ }
+
+ // Gets the serialized form for this java
+ private static byte[] out(String oid) throws Exception {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ new ObjectOutputStream(bout).writeObject(new ObjectIdentifier(oid));
+ return bout.toByteArray();
+ }
+
+ // Makes sure serialized form can be deserialized
+ private static void check(byte[] in, String oid) throws Exception {
+ ObjectIdentifier o = (ObjectIdentifier) (
+ new ObjectInputStream(new ByteArrayInputStream(in)).readObject());
+ if (!o.toString().equals(oid)) {
+ throw new Exception("Read Fail " + o + ", not " + oid);
+ }
+ }
+
+ // dump serialized form to java code style text
+ private static void dump(String title, String[] oids) throws Exception {
+ for (String oid: oids) {
+ String[] base64 = encoder.encodeBuffer(out(oid)).split("\n");
+ System.out.println(" " + title + ".put(\"" + oid + "\",");
+ for (int i = 0; i<base64.length; i++) {
+ System.out.print(" \"" + base64[i] + "\"");
+ if (i == base64.length - 1) {
+ System.out.println(");");
+ } else {
+ System.out.println(" +");
+ }
+ }
+ }
+ }
+
+ // Do not use diamond operator, this test is also meant to run in jdk6
+ private static Map<String,String> dump7 = new HashMap<String,String>();
+ private static Map<String,String> dump6 = new HashMap<String,String>();
+
+ static {
+ ////////////// PASTE BEGIN //////////////
+ dump7.put("0.0",
+ "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" +
+ "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" +
+ "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAAAnVyAAJbSU26YCZ26rKlAgAAeHAA" +
+ "AAACAAAAAAAAAAB1cgACW0Ks8xf4BghU4AIAAHhwAAAAAQB4");
+ dump7.put("1.1",
+ "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" +
+ "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" +
+ "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAAAnVyAAJbSU26YCZ26rKlAgAAeHAA" +
+ "AAACAAAAAQAAAAF1cgACW0Ks8xf4BghU4AIAAHhwAAAAASl4");
+ dump7.put("2.2",
+ "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" +
+ "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" +
+ "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAAAnVyAAJbSU26YCZ26rKlAgAAeHAA" +
+ "AAACAAAAAgAAAAJ1cgACW0Ks8xf4BghU4AIAAHhwAAAAAVJ4");
+ dump7.put("1.2.3456",
+ "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" +
+ "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" +
+ "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAAA3VyAAJbSU26YCZ26rKlAgAAeHAA" +
+ "AAADAAAAAQAAAAIAAA2AdXIAAltCrPMX+AYIVOACAAB4cAAAAAMqmwB4");
+ dump7.put("1.2.2147483647.4",
+ "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" +
+ "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" +
+ "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAABHVyAAJbSU26YCZ26rKlAgAAeHAA" +
+ "AAAEAAAAAQAAAAJ/////AAAABHVyAAJbQqzzF/gGCFTgAgAAeHAAAAAHKof///9/" +
+ "BHg=");
+ dump7.put("1.2.268435456.4",
+ "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" +
+ "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" +
+ "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAABHVyAAJbSU26YCZ26rKlAgAAeHAA" +
+ "AAAEAAAAAQAAAAIQAAAAAAAABHVyAAJbQqzzF/gGCFTgAgAAeHAAAAAHKoGAgIAA" +
+ "BHg=");
+ dump7.put("2.16.764.1.3101555394.1.0.100.2.1",
+ "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" +
+ "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" +
+ "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhw/////3NyAD5zdW4uc2VjdXJpdHkudXRp" +
+ "bC5PYmplY3RJZGVudGlmaWVyJEh1Z2VPaWROb3RTdXBwb3J0ZWRCeU9sZEpESwAA" +
+ "AAAAAAABAgAAeHB1cgACW0Ks8xf4BghU4AIAAHhwAAAADmCFfAGLxvf1QgEAZAIB" +
+ "eA==");
+ dump7.put("1.2.2147483648.4",
+ "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" +
+ "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" +
+ "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhw/////3NyAD5zdW4uc2VjdXJpdHkudXRp" +
+ "bC5PYmplY3RJZGVudGlmaWVyJEh1Z2VPaWROb3RTdXBwb3J0ZWRCeU9sZEpESwAA" +
+ "AAAAAAABAgAAeHB1cgACW0Ks8xf4BghU4AIAAHhwAAAAByqIgICAAAR4");
+ dump7.put("2.3.4444444444444444444444",
+ "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" +
+ "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" +
+ "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhw/////3NyAD5zdW4uc2VjdXJpdHkudXRp" +
+ "bC5PYmplY3RJZGVudGlmaWVyJEh1Z2VPaWROb3RTdXBwb3J0ZWRCeU9sZEpESwAA" +
+ "AAAAAAABAgAAeHB1cgACW0Ks8xf4BghU4AIAAHhwAAAADFOD4e+HpNG968eOHHg=");
+ dump7.put("1.2.8888888888888888.33333333333333333.44444444444444",
+ "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" +
+ "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" +
+ "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhw/////3NyAD5zdW4uc2VjdXJpdHkudXRp" +
+ "bC5PYmplY3RJZGVudGlmaWVyJEh1Z2VPaWROb3RTdXBwb3J0ZWRCeU9sZEpESwAA" +
+ "AAAAAAABAgAAeHB1cgACW0Ks8xf4BghU4AIAAHhwAAAAGCqP5Yzbxa6cOLubj9ek" +
+ "japVio3AusuOHHg=");
+
+ dump6.put("0.0",
+ "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" +
+ "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAJ1cgAC" +
+ "W0lNumAmduqypQIAAHhwAAAAAgAAAAAAAAAA");
+ dump6.put("1.1",
+ "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" +
+ "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAJ1cgAC" +
+ "W0lNumAmduqypQIAAHhwAAAAAgAAAAEAAAAB");
+ dump6.put("2.2",
+ "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" +
+ "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAJ1cgAC" +
+ "W0lNumAmduqypQIAAHhwAAAAAgAAAAIAAAAC");
+ dump6.put("1.2.3456",
+ "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" +
+ "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAN1cgAC" +
+ "W0lNumAmduqypQIAAHhwAAAAAwAAAAEAAAACAAANgA==");
+ dump6.put("1.2.2147483647.4",
+ "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" +
+ "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAR1cgAC" +
+ "W0lNumAmduqypQIAAHhwAAAABAAAAAEAAAACf////wAAAAQ=");
+ dump6.put("1.2.268435456.4",
+ "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" +
+ "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAR1cgAC" +
+ "W0lNumAmduqypQIAAHhwAAAABAAAAAEAAAACEAAAAAAAAAQ=");
+ ////////////// PASTE END //////////////
+ }
+}
--- a/jdk/test/sun/security/util/Oid/S11N.sh Tue Feb 05 11:10:07 2013 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,188 +0,0 @@
-#
-# Copyright (c) 2004, 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 4811968 6908628
-# @summary Serialization compatibility with old versions (and fix)
-# @author Weijun Wang
-#
-# set a few environment variables so that the shell-script can run stand-alone
-# in the source directory
-
-if [ "${TESTSRC}" = "" ] ; then
- TESTSRC="."
-fi
-if [ "${TESTCLASSES}" = "" ] ; then
- TESTCLASSES="."
-fi
-if [ "${TESTJAVA}" = "" ] ; then
- echo "TESTJAVA not set. Test cannot execute."
- echo "FAILED!!!"
- exit 1
-fi
-if [ "${COMPILEJAVA}" = "" ]; then
- COMPILEJAVA="${TESTJAVA}"
-fi
-
-# set platform-dependent variables
-PF=""
-
-OS=`uname -s`
-case "$OS" in
- SunOS )
- FS="/"
- ARCH=`isainfo`
- case "$ARCH" in
- sparc* )
- PF="solaris-sparc"
- ;;
- i[3-6]86 )
- PF="solaris-i586"
- ;;
- amd64* )
- PF="solaris-amd64"
- ;;
- * )
- echo "Unsupported System: Solaris ${ARCH}"
- exit 0;
- ;;
- esac
- ;;
- Linux )
- ARCH=`uname -m`
- FS="/"
- case "$ARCH" in
- i[3-6]86 )
- PF="linux-i586"
- ;;
- amd64* | x86_64 )
- PF="linux-amd64"
- ;;
- * )
- echo "Unsupported System: Linux ${ARCH}"
- exit 0;
- ;;
- esac
- ;;
- Windows* )
- FS="\\"
- PF="windows-i586"
-
- # 'uname -m' does not give us enough information -
- # should rely on $PROCESSOR_IDENTIFIER (as is done in Defs-windows.gmk),
- # but JTREG does not pass this env variable when executing a shell script.
- #
- # execute test program - rely on it to exit if platform unsupported
-
- ;;
- * )
- echo "Unsupported System: ${OS}"
- exit 0;
- ;;
-esac
-
-echo "==================================================="
-echo "Try to set ALT_JAVA_RE_JDK if you see timeout error"
-echo "==================================================="
-
-# the test code
-
-${COMPILEJAVA}${FS}bin${FS}javac -target 1.4 -source 1.4 \
- -d . ${TESTSRC}${FS}SerialTest.java || exit 10
-
-# You can set ALT_JAVA_RE_JDK to another location that contains the
-# binaries for older JDK releases. You can set it to a non-existent
-# directory to skip the interop tests between different versions.
-
-if [ "$ALT_JAVA_RE_JDK" = "" ]; then
- JAVA_RE_JDK=/java/re/j2se
-else
- JAVA_RE_JDK=$ALT_JAVA_RE_JDK
-fi
-
-OLDJAVA="
- $JAVA_RE_JDK/1.6.0/latest/binaries/${PF}
- $JAVA_RE_JDK/1.5.0/latest/binaries/${PF}
- $JAVA_RE_JDK/1.4.2/latest/binaries/${PF}
-"
-
-SMALL="
- 0.0
- 1.1
- 2.2
- 1.2.3456
- 1.2.2147483647.4
- 1.2.268435456.4
-"
-
-HUGE="
- 2.16.764.1.3101555394.1.0.100.2.1
- 1.2.2147483648.4
- 2.3.4444444444444444444444
- 1.2.888888888888888888.111111111111111.2222222222222.33333333333333333.44444444444444
-"
-
-for oid in ${SMALL}; do
- echo ${oid}
- # new ->
- ${TESTJAVA}${FS}bin${FS}java SerialTest out ${oid} > tmp.oid.serial || exit 1
- # -> new
- ${TESTJAVA}${FS}bin${FS}java SerialTest in ${oid} < tmp.oid.serial || exit 2
- for oldj in ${OLDJAVA}; do
- if [ -d ${oldj} ]; then
- echo ${oldj}
- # -> old
- ${oldj}${FS}bin${FS}java SerialTest in ${oid} < tmp.oid.serial || exit 3
- # old ->
- ${oldj}${FS}bin${FS}java SerialTest out ${oid} > tmp.oid.serial.old || exit 4
- # -> new
- ${TESTJAVA}${FS}bin${FS}java SerialTest in ${oid} < tmp.oid.serial.old || exit 5
- fi
- done
-done
-
-for oid in ${HUGE}; do
- echo ${oid}
- # new ->
- ${TESTJAVA}${FS}bin${FS}java SerialTest out ${oid} > tmp.oid.serial || exit 1
- # -> new
- ${TESTJAVA}${FS}bin${FS}java SerialTest in ${oid} < tmp.oid.serial || exit 2
- for oldj in ${OLDJAVA}; do
- if [ -d ${oldj} ]; then
- echo ${oldj}
- # -> old
- ${oldj}${FS}bin${FS}java SerialTest badin < tmp.oid.serial || exit 3
- fi
- done
-done
-
-rm -f tmp.oid.serial
-rm -f tmp.oid.serial.old
-rm -f SerialTest.class
-
-for oldj in ${OLDJAVA}; do
- if [ ! -d ${oldj} ]; then
- echo WARNING: ${oldj} is missing. Test incomplete! > /dev/stderr
- fi
-done
-
-exit 0
--- a/jdk/test/sun/security/util/Oid/SerialTest.java Tue Feb 05 11:10:07 2013 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2004, 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.
- */
-
-/*
- * read S11.sh
- */
-import java.io.*;
-import sun.security.util.*;
-
-/**
- * Test OID serialization between versions
- *
- * java SerialTest out oid // write a OID into System.out
- * java SerialTest in oid // read from System.in and compare it with oid
- * java SerialTest badin // make sure *cannot* read from System.in
- */
-class SerialTest {
- public static void main(String[] args) throws Exception {
- if (args[0].equals("out"))
- out(args[1]);
- else if (args[0].equals("in"))
- in(args[1]);
- else
- badin();
- }
-
- static void in(String oid) throws Exception {
- ObjectIdentifier o = (ObjectIdentifier) (new ObjectInputStream(System.in).readObject());
- if (!o.toString().equals(oid))
- throw new Exception("Read Fail " + o + ", not " + oid);
- }
-
- static void badin() throws Exception {
- boolean pass = true;
- try {
- new ObjectInputStream(System.in).readObject();
- } catch (Exception e) {
- pass = false;
- }
- if (pass) throw new Exception("Should fail but not");
- }
-
- static void out(String oid) throws Exception {
- new ObjectOutputStream(System.out).writeObject(new ObjectIdentifier(oid));
- }
-}
--- a/jdk/test/tools/launcher/Arrrghs.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/test/tools/launcher/Arrrghs.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -309,6 +309,7 @@
checkArgumentParsing("../../*", "../../*");
checkArgumentParsing("..\\..\\", "..\\..\\");
checkArgumentParsing("../../", "../../");
+ checkArgumentParsing("a b\\ c", "a", "b\\", "c");
}
private void initEmptyDir(File emptyDir) throws IOException {
--- a/jdk/test/tools/launcher/VersionCheck.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/test/tools/launcher/VersionCheck.java Tue Feb 05 11:11:53 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -42,6 +42,7 @@
// tools that do not accept -J-option
static final String[] BLACKLIST_JOPTION = {
"controlpanel",
+ "jabswitch",
"java-rmi",
"java-rmi.cgi",
"java",
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/pack200/InstructionTests.java Tue Feb 05 11:11:53 2013 -0800
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+import java.io.File;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.List;
+import static java.nio.file.StandardOpenOption.*;
+import java.util.regex.Pattern;
+
+/*
+ * @test
+ * @bug 8003549
+ * @summary tests class files instruction formats introduced in JSR-335
+ * @compile -XDignore.symbol.file Utils.java InstructionTests.java
+ * @run main InstructionTests
+ * @author ksrini
+ */
+public class InstructionTests {
+ public static void main(String... args) throws Exception {
+ testInvokeOpCodes();
+ }
+ /*
+ * the following should produce invokestatic and invokespecial
+ * on InterfaceMethodRefs vs. MethodRefs, packer/unpacker should work
+ */
+ static void testInvokeOpCodes() throws Exception {
+ List<String> scratch = new ArrayList<>();
+ final String fname = "A";
+ String javaFileName = fname + Utils.JAVA_FILE_EXT;
+ scratch.add("interface IntIterator {");
+ scratch.add(" default void forEach(){}");
+ scratch.add(" static void next() {}");
+ scratch.add("}");
+ scratch.add("class A implements IntIterator {");
+ scratch.add("public void forEach(Object o){");
+ scratch.add("IntIterator.super.forEach();");
+ scratch.add("IntIterator.next();");
+ scratch.add("}");
+ scratch.add("}");
+ File cwd = new File(".");
+ File javaFile = new File(cwd, javaFileName);
+ Files.write(javaFile.toPath(), scratch, Charset.defaultCharset(),
+ CREATE, TRUNCATE_EXISTING);
+
+ // make sure we have -g so that we compare LVT and LNT entries
+ Utils.compiler("-g", javaFile.getName());
+
+ // jar the file up
+ File testjarFile = new File(cwd, "test" + Utils.JAR_FILE_EXT);
+ Utils.jar("cvf", testjarFile.getName(), ".");
+
+ // pack using --repack
+ File outjarFile = new File(cwd, "out" + Utils.JAR_FILE_EXT);
+ scratch.clear();
+ scratch.add(Utils.getPack200Cmd());
+ scratch.add("-J-ea");
+ scratch.add("-J-esa");
+ scratch.add("--repack");
+ scratch.add(outjarFile.getName());
+ scratch.add(testjarFile.getName());
+ List<String> output = Utils.runExec(scratch);
+ // TODO remove this when we get bc escapes working correctly
+ // this test anyhow would fail at that time
+ findString("WARNING: Passing.*" + fname + Utils.CLASS_FILE_EXT,
+ output);
+
+ Utils.doCompareVerify(testjarFile, outjarFile);
+ }
+
+ static boolean findString(String str, List<String> list) {
+ Pattern p = Pattern.compile(str);
+ for (String x : list) {
+ if (p.matcher(x).matches())
+ return true;
+ }
+ throw new RuntimeException("Error: " + str + " not found in output");
+ }
+}
--- a/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java Tue Feb 05 11:10:07 2013 -0800
+++ b/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java Tue Feb 05 11:11:53 2013 -0800
@@ -57,8 +57,10 @@
import com.sun.tools.classfile.Opcode;
import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute;
import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute;
+import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute;
import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute;
import com.sun.tools.classfile.RuntimeVisibleParameterAnnotations_attribute;
+import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute;
import com.sun.tools.classfile.Signature_attribute;
import com.sun.tools.classfile.SourceDebugExtension_attribute;
import com.sun.tools.classfile.SourceFile_attribute;
@@ -1214,6 +1216,21 @@
p.add(e);
return null;
}
+
+ /*
+ * TODO
+ * add these two for now to keep the compiler happy, we will implement
+ * these along with the JSR-308 changes.
+ */
+ @Override
+ public Element visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute rvta, Element p) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Element visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute rita, Element p) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
}
class StackMapVisitor implements StackMapTable_attribute.stack_map_frame.Visitor<Element, Void> {