# HG changeset patch # User vinnie # Date 1368735761 25200 # Node ID 50d2fb6f323f0277610652d90f2748e5a7679f03 # Parent 307d170884eab4d60cb301b6604d5ae033142862# Parent 46864558d06823f9f3eddac9bf6b964879e07cf4 Merge diff -r 307d170884ea -r 50d2fb6f323f jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java Thu May 16 02:43:58 2013 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java Thu May 16 13:22:41 2013 -0700 @@ -99,6 +99,7 @@ return this == def.canon; } + @Override public int compareTo(Attribute that) { return this.def.compareTo(that.def); } @@ -212,20 +213,20 @@ // Metadata. // // We define metadata using similar layouts - // for all five kinds of metadata attributes. + // for all five kinds of metadata attributes and 2 type metadata attributes // // Regular annotations are a counted list of [RSHNH[RUH(1)]][...] // pack.method.attribute.RuntimeVisibleAnnotations=[NH[(1)]][RSHNH[RUH(1)]][TB...] // // Parameter annotations are a counted list of regular annotations. - // pack.method.attribute.RuntimeVisibleParameterAnnotations=[NH[(1)]][NH[(1)]][RSHNH[RUH(1)]][TB...] + // pack.method.attribute.RuntimeVisibleParameterAnnotations=[NB[(1)]][NH[(1)]][RSHNH[RUH(1)]][TB...] // // RuntimeInvisible annotations are defined similarly... // Non-method annotations are defined similarly... // // Annotation are a simple tagged value [TB...] // pack.attribute.method.AnnotationDefault=[TB...] - // + static { String mdLayouts[] = { Attribute.normalizeLayoutString @@ -238,6 +239,9 @@ +"\n # annotations :=" +"\n [ NH[(1)] ] # forward call to annotation" +"\n " + ), + Attribute.normalizeLayoutString + ("" +"\n # annotation :=" +"\n [RSH" +"\n NH[RUH (1)] # forward call to value" @@ -259,24 +263,67 @@ +"\n ()[] ]" ) }; + /* + * RuntimeVisibleTypeAnnotation and RuntimeInvisibleTypeAnnotatation are + * similar to RuntimeVisibleAnnotation and RuntimeInvisibleAnnotation, + * a type-annotation union and a type-path structure precedes the + * annotation structure + */ + String typeLayouts[] = { + Attribute.normalizeLayoutString + ("" + +"\n # type-annotations :=" + +"\n [ NH[(1)(2)(3)] ] # forward call to type-annotations" + ), + Attribute.normalizeLayoutString + ( "" + +"\n # type-annotation :=" + +"\n [TB" + +"\n (0-1) [B] # {CLASS, METHOD}_TYPE_PARAMETER" + +"\n (16) [FH] # CLASS_EXTENDS" + +"\n (17-18) [BB] # {CLASS, METHOD}_TYPE_PARAMETER_BOUND" + +"\n (19-21) [] # FIELD, METHOD_RETURN, METHOD_RECEIVER" + +"\n (22) [B] # METHOD_FORMAL_PARAMETER" + +"\n (23) [H] # THROWS" + +"\n (64-65) [NH[PHOHH]] # LOCAL_VARIABLE, RESOURCE_VARIABLE" + +"\n (66) [H] # EXCEPTION_PARAMETER" + +"\n (67-70) [PH] # INSTANCEOF, NEW, {CONSTRUCTOR, METHOD}_REFERENCE_RECEIVER" + +"\n (71-75) [PHB] # CAST, {CONSTRUCTOR,METHOD}_INVOCATION_TYPE_ARGUMENT, {CONSTRUCTOR, METHOD}_REFERENCE_TYPE_ARGUMENT" + +"\n ()[] ]" + ), + Attribute.normalizeLayoutString + ("" + +"\n # type-path" + +"\n [ NB[BB] ]" + ) + }; Map sd = standardDefs; - String defaultLayout = mdLayouts[2]; - String annotationsLayout = mdLayouts[1] + mdLayouts[2]; + String defaultLayout = mdLayouts[3]; + String annotationsLayout = mdLayouts[1] + mdLayouts[2] + mdLayouts[3]; String paramsLayout = mdLayouts[0] + annotationsLayout; + String typesLayout = typeLayouts[0] + typeLayouts[1] + + typeLayouts[2] + mdLayouts[2] + mdLayouts[3]; + for (int ctype = 0; ctype < ATTR_CONTEXT_LIMIT; ctype++) { - if (ctype == ATTR_CONTEXT_CODE) continue; - define(sd, ctype, - "RuntimeVisibleAnnotations", annotationsLayout); + if (ctype != ATTR_CONTEXT_CODE) { + define(sd, ctype, + "RuntimeVisibleAnnotations", annotationsLayout); + define(sd, ctype, + "RuntimeInvisibleAnnotations", annotationsLayout); + + if (ctype == ATTR_CONTEXT_METHOD) { + define(sd, ctype, + "RuntimeVisibleParameterAnnotations", paramsLayout); + define(sd, ctype, + "RuntimeInvisibleParameterAnnotations", paramsLayout); + define(sd, ctype, + "AnnotationDefault", defaultLayout); + } + } define(sd, ctype, - "RuntimeInvisibleAnnotations", annotationsLayout); - if (ctype == ATTR_CONTEXT_METHOD) { - define(sd, ctype, - "RuntimeVisibleParameterAnnotations", paramsLayout); - define(sd, ctype, - "RuntimeInvisibleParameterAnnotations", paramsLayout); - define(sd, ctype, - "AnnotationDefault", defaultLayout); - } + "RuntimeVisibleTypeAnnotations", typesLayout); + define(sd, ctype, + "RuntimeInvisibleTypeAnnotations", typesLayout); } } @@ -529,6 +576,7 @@ return canon.addContent(bytes, null); } + @Override public boolean equals(Object x) { return ( x != null) && ( x.getClass() == Layout.class ) && equals((Layout)x); @@ -538,11 +586,13 @@ && this.layout.equals(that.layout) && this.ctype == that.ctype; } + @Override public int hashCode() { return (((17 + name.hashCode()) * 37 + layout.hashCode()) * 37 + ctype); } + @Override public int compareTo(Layout that) { int r; r = this.name.compareTo(that.name); @@ -551,6 +601,7 @@ if (r != 0) return r; return this.ctype - that.ctype; } + @Override public String toString() { String str = contextName(ctype)+"."+name+"["+layout+"]"; // If -ea, print out more informative strings! @@ -698,11 +749,14 @@ // References (to a local cpMap) are embedded in the bytes. def.parse(holder, bytes, 0, bytes.length, new ValueStream() { + @Override public void putInt(int bandIndex, int value) { } + @Override public void putRef(int bandIndex, Entry ref) { refs.add(ref); } + @Override public int encodeBCI(int bci) { return bci; } @@ -716,6 +770,7 @@ return def.unparse(in, out); } + @Override public String toString() { return def +"{"+(bytes == null ? -1 : size())+"}" @@ -1309,7 +1364,7 @@ } out.putRef(bandIndex, globalRef); break; - default: assert(false); continue; + default: assert(false); } } return pos; @@ -1416,8 +1471,7 @@ int localRef; if (globalRef != null) { // It's a one-element array, really an lvalue. - fixups[0] = Fixups.add(fixups[0], null, out.size(), - Fixups.U2_FORMAT, globalRef); + fixups[0] = Fixups.addRefWithLoc(fixups[0], out.size(), globalRef); localRef = 0; // placeholder for fixups } else { localRef = 0; // fixed null value diff -r 307d170884ea -r 50d2fb6f323f jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java Thu May 16 02:43:58 2013 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java Thu May 16 13:22:41 2013 -0700 @@ -48,6 +48,7 @@ import java.util.Map; import java.util.jar.Pack200; import static com.sun.java.util.jar.pack.Constants.*; +import java.util.LinkedList; /** * Define the structure and ordering of "bands" in a packed file. @@ -495,6 +496,7 @@ } protected int lengthForDebug = -1; // DEBUG ONLY + @Override public String toString() { // DEBUG ONLY int length = (lengthForDebug != -1 ? lengthForDebug : length()); String str = name; @@ -518,20 +520,24 @@ super(name, regularCoding); } + @Override public int capacity() { return values == null ? -1 : values.length; } /** Declare predicted or needed capacity. */ + @Override protected void setCapacity(int cap) { assert(length <= cap); if (cap == -1) { values = null; return; } values = realloc(values, cap); } + @Override public int length() { return length; } + @Override protected int valuesRemainingForDebug() { return length - valuesDisbursed; } @@ -583,6 +589,7 @@ return true; } + @Override protected void chooseBandCodings() throws IOException { boolean canVary = canVaryCoding(); if (!canVary || !shouldVaryCoding()) { @@ -653,6 +660,7 @@ } } + @Override protected long computeOutputSize() { outputSize = getCodingChooser().computeByteSize(bandCoding, values, 0, length); @@ -668,6 +676,7 @@ return regularCoding.setD(0).getLength(X); } + @Override protected void writeDataTo(OutputStream out) throws IOException { if (length == 0) return; // nothing to write long len0 = 0; @@ -691,6 +700,7 @@ if (optDumpBands) dumpBand(); } + @Override protected void readDataFrom(InputStream in) throws IOException { length = valuesExpected(); if (length == 0) return; // nothing to read @@ -707,7 +717,6 @@ if (XB < 0) { // Do not consume this value. No alternate coding. in.reset(); - XB = _meta_default; bandCoding = regularCoding; metaCoding = noMetaCoding; } else if (XB == _meta_default) { @@ -733,6 +742,7 @@ if (optDumpBands) dumpBand(); } + @Override public void doneDisbursing() { super.doneDisbursing(); values = null; // for GC @@ -763,7 +773,10 @@ /** Disburse one value. */ protected int getValue() { assert(phase() == DISBURSE_PHASE); - assert(valuesDisbursed < length); + // when debugging return a zero if lengths are zero + if (optDebugBands && length == 0 && valuesDisbursed == length) + return 0; + assert(valuesDisbursed <= length); return values[valuesDisbursed++]; } @@ -784,9 +797,11 @@ super(name, BYTE1); } + @Override public int capacity() { return bytes == null ? -1 : Integer.MAX_VALUE; } + @Override protected void setCapacity(int cap) { assert(bytes == null); // do this just once bytes = new ByteArrayOutputStream(cap); @@ -796,27 +811,32 @@ bytes = null; } + @Override public int length() { return bytes == null ? -1 : bytes.size(); } public void reset() { bytes.reset(); } + @Override protected int valuesRemainingForDebug() { return (bytes == null) ? -1 : ((ByteArrayInputStream)in).available(); } + @Override protected void chooseBandCodings() throws IOException { // No-op. assert(decodeEscapeValue(regularCoding.min(), regularCoding) < 0); assert(decodeEscapeValue(regularCoding.max(), regularCoding) < 0); } + @Override protected long computeOutputSize() { // do not cache return bytes.size(); } + @Override public void writeDataTo(OutputStream out) throws IOException { if (length() == 0) return; bytes.writeTo(out); @@ -834,6 +854,7 @@ } } + @Override public void readDataFrom(InputStream in) throws IOException { int vex = valuesExpected(); if (vex == 0) return; @@ -852,11 +873,13 @@ if (optDumpBands) dumpBand(); } + @Override public void readyToDisburse() { in = new ByteArrayInputStream(bytes.toByteArray()); super.readyToDisburse(); } + @Override public void doneDisbursing() { super.doneDisbursing(); if (optDumpBands @@ -882,11 +905,13 @@ // Tap the stream. bytesForDump = new ByteArrayOutputStream(); this.in = new FilterInputStream(in) { + @Override public int read() throws IOException { int ch = in.read(); if (ch >= 0) bytesForDump.write(ch); return ch; } + @Override public int read(byte b[], int off, int len) throws IOException { int nr = in.read(b, off, len); if (nr >= 0) bytesForDump.write(b, off, nr); @@ -917,6 +942,7 @@ assert(b == (b & 0xFF)); collectorStream().write(b); } + @Override public String toString() { return "byte "+super.toString(); } @@ -1184,6 +1210,7 @@ super(name, regularCoding); } + @Override public Band init() { super.init(); // This is all just to keep the asserts happy: @@ -1259,12 +1286,17 @@ int bandCount() { return bandCount; } private int cap = -1; + @Override public int capacity() { return cap; } + @Override public void setCapacity(int cap) { this.cap = cap; } + @Override public int length() { return 0; } + @Override public int valuesRemainingForDebug() { return 0; } + @Override protected void chooseBandCodings() throws IOException { // coding decision pass for (int i = 0; i < bandCount; i++) { @@ -1273,6 +1305,7 @@ } } + @Override protected long computeOutputSize() { // coding decision pass long sum = 0; @@ -1286,6 +1319,7 @@ return sum; } + @Override protected void writeDataTo(OutputStream out) throws IOException { long preCount = 0; if (outputCounter != null) preCount = outputCounter.getCount(); @@ -1303,6 +1337,7 @@ } } + @Override protected void readDataFrom(InputStream in) throws IOException { assert(false); // not called? for (int i = 0; i < bandCount; i++) { @@ -1314,6 +1349,7 @@ } } + @Override public String toString() { return "{"+bandCount()+" bands: "+super.toString()+"}"; } @@ -1335,14 +1371,17 @@ public long getCount() { return count; } public void setCount(long c) { count = c; } + @Override public void write(int b) throws IOException { count++; if (out != null) out.write(b); } + @Override public void write(byte b[], int off, int len) throws IOException { count += len; if (out != null) out.write(b, off, len); } + @Override public String toString() { return String.valueOf(getCount()); } @@ -1490,6 +1529,7 @@ CPRefBand field_ConstantValue_KQ = field_attr_bands.newCPRefBand("field_ConstantValue_KQ", CONSTANT_FieldSpecific); CPRefBand field_Signature_RS = field_attr_bands.newCPRefBand("field_Signature_RS", CONSTANT_Signature); MultiBand field_metadata_bands = field_attr_bands.newMultiBand("(field_metadata_bands)", UNSIGNED5); + MultiBand field_type_metadata_bands = field_attr_bands.newMultiBand("(field_type_metadata_bands)", UNSIGNED5); CPRefBand method_descr = class_bands.newCPRefBand("method_descr", MDELTA5, CONSTANT_NameandType); MultiBand method_attr_bands = class_bands.newMultiBand("(method_attr_bands)", UNSIGNED5); @@ -1507,6 +1547,7 @@ IntBand method_MethodParameters_NB = method_attr_bands.newIntBand("method_MethodParameters_NB", BYTE1); CPRefBand method_MethodParameters_name_RUN = method_attr_bands.newCPRefBand("method_MethodParameters_name_RUN", UNSIGNED5, CONSTANT_Utf8, NULL_IS_OK); IntBand method_MethodParameters_flag_FH = method_attr_bands.newIntBand("method_MethodParameters_flag_FH"); + MultiBand method_type_metadata_bands = method_attr_bands.newMultiBand("(method_type_metadata_bands)", UNSIGNED5); MultiBand class_attr_bands = class_bands.newMultiBand("(class_attr_bands)", UNSIGNED5); IntBand class_flags_hi = class_attr_bands.newIntBand("class_flags_hi"); @@ -1527,6 +1568,7 @@ CPRefBand class_InnerClasses_name_RUN = class_attr_bands.newCPRefBand("class_InnerClasses_name_RUN", UNSIGNED5, CONSTANT_Utf8, NULL_IS_OK); IntBand class_ClassFile_version_minor_H = class_attr_bands.newIntBand("class_ClassFile_version_minor_H"); IntBand class_ClassFile_version_major_H = class_attr_bands.newIntBand("class_ClassFile_version_major_H"); + MultiBand class_type_metadata_bands = class_attr_bands.newMultiBand("(class_type_metadata_bands)", UNSIGNED5); MultiBand code_bands = class_bands.newMultiBand("(code_bands)", UNSIGNED5); ByteBand code_headers = code_bands.newByteBand("code_headers"); //BYTE1 @@ -1545,7 +1587,7 @@ IntBand code_attr_indexes = code_attr_bands.newIntBand("code_attr_indexes"); IntBand code_attr_calls = code_attr_bands.newIntBand("code_attr_calls"); - MultiBand stackmap_bands = code_attr_bands.newMultiBand("StackMapTable_bands", UNSIGNED5); + MultiBand stackmap_bands = code_attr_bands.newMultiBand("(StackMapTable_bands)", UNSIGNED5); IntBand code_StackMapTable_N = stackmap_bands.newIntBand("code_StackMapTable_N"); IntBand code_StackMapTable_frame_T = stackmap_bands.newIntBand("code_StackMapTable_frame_T",BYTE1); IntBand code_StackMapTable_local_N = stackmap_bands.newIntBand("code_StackMapTable_local_N"); @@ -1573,6 +1615,7 @@ CPRefBand code_LocalVariableTypeTable_name_RU = code_attr_bands.newCPRefBand("code_LocalVariableTypeTable_name_RU", CONSTANT_Utf8); CPRefBand code_LocalVariableTypeTable_type_RS = code_attr_bands.newCPRefBand("code_LocalVariableTypeTable_type_RS", CONSTANT_Signature); IntBand code_LocalVariableTypeTable_slot = code_attr_bands.newIntBand("code_LocalVariableTypeTable_slot"); + MultiBand code_type_metadata_bands = code_attr_bands.newMultiBand("(code_type_metadata_bands)", UNSIGNED5); // bands for bytecodes MultiBand bc_bands = all_bands.newMultiBand("(byte_codes)", UNSIGNED5); @@ -1678,6 +1721,14 @@ metadataBands[ATTR_CONTEXT_FIELD] = field_metadata_bands; metadataBands[ATTR_CONTEXT_METHOD] = method_metadata_bands; } + // Table of bands which contains type_metadata (TypeAnnotations) + protected MultiBand[] typeMetadataBands = new MultiBand[ATTR_CONTEXT_LIMIT]; + { + typeMetadataBands[ATTR_CONTEXT_CLASS] = class_type_metadata_bands; + typeMetadataBands[ATTR_CONTEXT_FIELD] = field_type_metadata_bands; + typeMetadataBands[ATTR_CONTEXT_METHOD] = method_type_metadata_bands; + typeMetadataBands[ATTR_CONTEXT_CODE] = code_type_metadata_bands; + } // Attribute layouts. public static final int ADH_CONTEXT_MASK = 0x3; // (ad_hdr & ADH_CONTEXT_MASK) @@ -1793,36 +1844,47 @@ for (int ctype = 0; ctype < ATTR_CONTEXT_LIMIT; ctype++) { MultiBand xxx_metadata_bands = metadataBands[ctype]; - if (xxx_metadata_bands == null) - continue; // no code attrs + if (ctype != ATTR_CONTEXT_CODE) { + // These arguments cause the bands to be built + // automatically for this complicated layout: + predefineAttribute(X_ATTR_RuntimeVisibleAnnotations, + ATTR_CONTEXT_NAME[ctype]+"_RVA_", + xxx_metadata_bands, + Attribute.lookup(null, ctype, + "RuntimeVisibleAnnotations")); + predefineAttribute(X_ATTR_RuntimeInvisibleAnnotations, + ATTR_CONTEXT_NAME[ctype]+"_RIA_", + xxx_metadata_bands, + Attribute.lookup(null, ctype, + "RuntimeInvisibleAnnotations")); - // These arguments cause the bands to be built - // automatically for this complicated layout: - predefineAttribute(X_ATTR_RuntimeVisibleAnnotations, - ATTR_CONTEXT_NAME[ctype]+"_RVA_", - xxx_metadata_bands, - Attribute.lookup(null, ctype, - "RuntimeVisibleAnnotations")); - predefineAttribute(X_ATTR_RuntimeInvisibleAnnotations, - ATTR_CONTEXT_NAME[ctype]+"_RIA_", - xxx_metadata_bands, - Attribute.lookup(null, ctype, - "RuntimeInvisibleAnnotations")); - if (ctype != ATTR_CONTEXT_METHOD) - continue; - - predefineAttribute(METHOD_ATTR_RuntimeVisibleParameterAnnotations, - "method_RVPA_", xxx_metadata_bands, - Attribute.lookup(null, ctype, - "RuntimeVisibleParameterAnnotations")); - predefineAttribute(METHOD_ATTR_RuntimeInvisibleParameterAnnotations, - "method_RIPA_", xxx_metadata_bands, - Attribute.lookup(null, ctype, - "RuntimeInvisibleParameterAnnotations")); - predefineAttribute(METHOD_ATTR_AnnotationDefault, - "method_AD_", xxx_metadata_bands, - Attribute.lookup(null, ctype, - "AnnotationDefault")); + if (ctype == ATTR_CONTEXT_METHOD) { + predefineAttribute(METHOD_ATTR_RuntimeVisibleParameterAnnotations, + "method_RVPA_", xxx_metadata_bands, + Attribute.lookup(null, ctype, + "RuntimeVisibleParameterAnnotations")); + predefineAttribute(METHOD_ATTR_RuntimeInvisibleParameterAnnotations, + "method_RIPA_", xxx_metadata_bands, + Attribute.lookup(null, ctype, + "RuntimeInvisibleParameterAnnotations")); + predefineAttribute(METHOD_ATTR_AnnotationDefault, + "method_AD_", xxx_metadata_bands, + Attribute.lookup(null, ctype, + "AnnotationDefault")); + } + } + // All contexts have these + MultiBand xxx_type_metadata_bands = typeMetadataBands[ctype]; + predefineAttribute(X_ATTR_RuntimeVisibleTypeAnnotations, + ATTR_CONTEXT_NAME[ctype] + "_RVTA_", + xxx_type_metadata_bands, + Attribute.lookup(null, ctype, + "RuntimeVisibleTypeAnnotations")); + predefineAttribute(X_ATTR_RuntimeInvisibleTypeAnnotations, + ATTR_CONTEXT_NAME[ctype] + "_RITA_", + xxx_type_metadata_bands, + Attribute.lookup(null, ctype, + "RuntimeInvisibleTypeAnnotations")); } @@ -2053,8 +2115,7 @@ Attribute.Layout def = attr.layout(); int ctype = def.ctype(); return predefineAttribute(index, ctype, - makeNewAttributeBands(bandPrefix, def, - addHere), + makeNewAttributeBands(bandPrefix, def, addHere), def.name(), def.layout()); } @@ -2539,7 +2600,7 @@ return true; } - // DEBUG ONLY: Validate next input band. + // DEBUG ONLY: Validate next input band, ensure bands are read in sequence private boolean assertReadyToReadFrom(Band b, InputStream in) throws IOException { Band p = prevForAssertMap.get(b); // Any previous band must be done reading before this one starts. @@ -2547,30 +2608,19 @@ Utils.log.warning("Previous band not done reading."); Utils.log.info(" Previous band: "+p); Utils.log.info(" Next band: "+b); - Thread.dumpStack(); assert(verbose > 0); // die unless verbose is true } String name = b.name; if (optDebugBands && !name.startsWith("(")) { + assert(bandSequenceList != null); // Verify synchronization between reader & writer: - StringBuilder buf = new StringBuilder(); - int ch; - while ((ch = in.read()) > 0) - buf.append((char)ch); - String inName = buf.toString(); + String inName = bandSequenceList.removeFirst(); + // System.out.println("Reading: " + name); if (!inName.equals(name)) { - StringBuilder sb = new StringBuilder(); - sb.append("Expected "+name+" but read: "); - inName += (char)ch; - while (inName.length() < 10) { - inName += (char) in.read(); - } - for (int i = 0; i < inName.length(); i++) { - sb.append(inName.charAt(i)); - } - Utils.log.warning(sb.toString()); + Utils.log.warning("Expected " + name + " but read: " + inName); return false; } + Utils.log.info("Read band in sequence: " + name); } return true; } @@ -2590,7 +2640,12 @@ return true; } - // DEBUG ONLY: Maybe write a debugging cookie to next output band. + /* + * DEBUG ONLY: write the bands to a list and read back the list in order, + * this works perfectly if we use the java packer and unpacker, typically + * this will work with --repack or if they are in the same jvm instance. + */ + static LinkedList bandSequenceList = null; private boolean assertReadyToWriteTo(Band b, OutputStream out) throws IOException { Band p = prevForAssertMap.get(b); // Any previous band must be done writing before this one starts. @@ -2598,16 +2653,15 @@ Utils.log.warning("Previous band not done writing."); Utils.log.info(" Previous band: "+p); Utils.log.info(" Next band: "+b); - Thread.dumpStack(); assert(verbose > 0); // die unless verbose is true } String name = b.name; if (optDebugBands && !name.startsWith("(")) { + if (bandSequenceList == null) + bandSequenceList = new LinkedList<>(); // Verify synchronization between reader & writer: - for (int j = 0; j < name.length(); j++) { - out.write((byte)name.charAt(j)); - } - out.write((byte)0); + bandSequenceList.add(name); + // System.out.println("Writing: " + b); } return true; } @@ -2664,7 +2718,7 @@ buf.append("\\r"); } else { String str = "000"+Integer.toHexString(ch); - buf.append("\\u"+str.substring(str.length()-4)); + buf.append("\\u").append(str.substring(str.length()-4)); } } ps.println(buf); diff -r 307d170884ea -r 50d2fb6f323f jdk/src/share/classes/com/sun/java/util/jar/pack/Constants.java --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Constants.java Thu May 16 02:43:58 2013 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Constants.java Thu May 16 13:22:41 2013 -0700 @@ -45,6 +45,7 @@ 1.5 to 1.5.X 49,0 1.6 to 1.5.x 50,0 1.7 to 1.6.x 51,0 + 1.8 to 1.7.x 52,0 */ public final static Package.Version JAVA_MIN_CLASS_VERSION = @@ -161,7 +162,9 @@ METHOD_ATTR_RuntimeInvisibleParameterAnnotations = 24, CLASS_ATTR_ClassFile_version = 24, METHOD_ATTR_AnnotationDefault = 25, - METHOD_ATTR_MethodParameters = 26, + METHOD_ATTR_MethodParameters = 26, // JDK8 + X_ATTR_RuntimeVisibleTypeAnnotations = 27, // JDK8 + X_ATTR_RuntimeInvisibleTypeAnnotations = 28, // JDK8 CODE_ATTR_StackMapTable = 0, // new in Java 6 CODE_ATTR_LineNumberTable = 1, CODE_ATTR_LocalVariableTable = 2, diff -r 307d170884ea -r 50d2fb6f323f jdk/src/share/classes/com/sun/java/util/jar/pack/Fixups.java --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Fixups.java Thu May 16 02:43:58 2013 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Fixups.java Thu May 16 13:22:41 2013 -0700 @@ -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 @@ -30,6 +30,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; +import java.util.Objects; /** * Collection of relocatable constant pool references. @@ -77,8 +78,9 @@ private static final int MINBIGSIZE = 1; // cleverly share empty bigDescs: - private static int[] noBigDescs = {MINBIGSIZE}; + private static final int[] noBigDescs = {MINBIGSIZE}; + @Override public int size() { return size; } @@ -105,6 +107,7 @@ } } + @Override public void clear() { if (bytes != null) { // Clean the bytes: @@ -141,16 +144,16 @@ assert(old.equals(new ArrayList<>(this))); } - static final int LOC_SHIFT = 1; - static final int FMT_MASK = 0x1; - static final byte UNUSED_BYTE = 0; - static final byte OVERFLOW_BYTE = -1; + private static final int LOC_SHIFT = 1; + private static final int FMT_MASK = 0x1; + private static final byte UNUSED_BYTE = 0; + private static final byte OVERFLOW_BYTE = -1; // fill pointer of bigDescs array is in element [0] - static final int BIGSIZE = 0; + private static final int BIGSIZE = 0; // Format values: - public static final int U2_FORMAT = 0; - public static final int U1_FORMAT = 1; + private static final int U2_FORMAT = 0; + private static final int U1_FORMAT = 1; // Special values for the static methods. private static final int SPECIAL_LOC = 0; @@ -232,6 +235,14 @@ } } + void addU1(int pc, Entry ref) { + add(pc, U1_FORMAT, ref); + } + + void addU2(int pc, Entry ref) { + add(pc, U2_FORMAT, ref); + } + /** Simple and necessary tuple to present each fixup. */ public static class Fixup implements Comparable { @@ -248,15 +259,25 @@ public int location() { return descLoc(desc); } public int format() { return descFmt(desc); } public Entry entry() { return entry; } + @Override public int compareTo(Fixup that) { // Ordering depends only on location. return this.location() - that.location(); } + @Override public boolean equals(Object x) { if (!(x instanceof Fixup)) return false; Fixup that = (Fixup) x; return this.desc == that.desc && this.entry == that.entry; } + @Override + public int hashCode() { + int hash = 7; + hash = 59 * hash + this.desc; + hash = 59 * hash + Objects.hashCode(this.entry); + return hash; + } + @Override public String toString() { return "@"+location()+(format()==U1_FORMAT?".1":"")+"="+entry; } @@ -267,8 +288,11 @@ int index = 0; // index into entries int bigIndex = BIGSIZE+1; // index into bigDescs int next = head; // desc pointing to next fixup + @Override public boolean hasNext() { return index < size; } + @Override public void remove() { throw new UnsupportedOperationException(); } + @Override public Fixup next() { int thisIndex = index; return new Fixup(nextDesc(), entries[thisIndex]); @@ -293,17 +317,20 @@ } } + @Override public Iterator iterator() { return new Itr(); } public void add(int location, int format, Entry entry) { addDesc(makeDesc(location, format), entry); } + @Override public boolean add(Fixup f) { addDesc(f.desc, f.entry); return true; } + @Override public boolean addAll(Collection c) { if (c instanceof Fixups) { // Use knowledge of Itr structure to avoid building little structs. @@ -367,7 +394,13 @@ } /// Static methods that optimize the use of this class. - public static + static Object addRefWithBytes(Object f, byte[] bytes, Entry e) { + return add(f, bytes, 0, U2_FORMAT, e); + } + static Object addRefWithLoc(Object f, int loc, Entry entry) { + return add(f, null, loc, U2_FORMAT, entry); + } + private static Object add(Object prevFixups, byte[] bytes, int loc, int fmt, Entry e) { diff -r 307d170884ea -r 50d2fb6f323f jdk/src/share/classes/com/sun/java/util/jar/pack/Package.java --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Package.java Thu May 16 02:43:58 2013 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Package.java Thu May 16 13:22:41 2013 -0700 @@ -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 @@ -259,7 +259,7 @@ byte[] bytes = new byte[2]; sfName = getRefString(obvious); Object f = null; - f = Fixups.add(f, bytes, 0, Fixups.U2_FORMAT, sfName); + f = Fixups.addRefWithBytes(f, bytes, sfName); a = attrSourceFileSpecial.addContent(bytes, f); } } else if (obvious.equals(sfName.stringValue())) { diff -r 307d170884ea -r 50d2fb6f323f jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java Thu May 16 02:43:58 2013 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java Thu May 16 13:22:41 2013 -0700 @@ -116,7 +116,7 @@ int nr = super.read(b, off, len); servedPos = pos; if (nr >= 0) served += nr; - assert(served <= limit || limit == -1); + //assert(served <= limit || limit == -1); return nr; } public long skip(long n) throws IOException { @@ -1500,6 +1500,7 @@ // ic_local_bands // *class_ClassFile_version_minor_H :UNSIGNED5 // *class_ClassFile_version_major_H :UNSIGNED5 + // class_type_metadata_bands // // field_attr_bands: // *field_flags :UNSIGNED5 @@ -1509,6 +1510,7 @@ // *field_Signature_RS :UNSIGNED5 (cp_Signature) // field_metadata_bands // *field_ConstantValue_KQ :UNSIGNED5 (cp_Int, etc.; see note) + // field_type_metadata_bands // // method_attr_bands: // *method_flags :UNSIGNED5 @@ -1522,6 +1524,7 @@ // *method_MethodParameters_NB: BYTE1 // *method_MethodParameters_RUN: UNSIGNED5 (cp_Utf8) // *method_MethodParameters_FH: UNSIGNED5 (flag) + // method_type_metadata_bands // // code_attr_bands: // *code_flags :UNSIGNED5 @@ -1537,6 +1540,7 @@ // *code_LocalVariableTable_name_RU :UNSIGNED5 (cp_Utf8) // *code_LocalVariableTable_type_RS :UNSIGNED5 (cp_Signature) // *code_LocalVariableTable_slot :UNSIGNED5 + // code_type_metadata_bands countAttrs(ctype, holders); readAttrs(ctype, holders); @@ -1703,8 +1707,9 @@ class_InnerClasses_outer_RCN.readFrom(in); class_InnerClasses_name_RUN.expectLength(tupleCount); class_InnerClasses_name_RUN.readFrom(in); - } else if (totalCount == 0) { - // Expect no elements at all. Skip quickly. + } else if (!optDebugBands && totalCount == 0) { + // Expect no elements at all. Skip quickly. however if we + // are debugging bands, read all bands regardless for (int j = 0; j < ab.length; j++) { ab[j].doneWithUnusedBand(); } @@ -1723,11 +1728,17 @@ assert(cbles[j].kind == Attribute.EK_CBLE); int entryCount = forwardCounts[j]; forwardCounts[j] = -1; // No more, please! - if (cbles[j].flagTest(Attribute.EF_BACK)) + if (totalCount > 0 && cbles[j].flagTest(Attribute.EF_BACK)) entryCount += xxx_attr_calls.getInt(); readAttrBands(cbles[j].body, entryCount, forwardCounts, ab); } } + // mark them read, to satisfy asserts + if (optDebugBands && totalCount == 0) { + for (int j = 0; j < ab.length; j++) { + ab[j].doneDisbursing(); + } + } } } if (!predef) break; @@ -2154,11 +2165,10 @@ if (size == 1) ldcRefSet.add(ref); int fmt; switch (size) { - case 1: fmt = Fixups.U1_FORMAT; break; - case 2: fmt = Fixups.U2_FORMAT; break; + case 1: fixupBuf.addU1(pc, ref); break; + case 2: fixupBuf.addU2(pc, ref); break; default: assert(false); fmt = 0; } - fixupBuf.add(pc, fmt, ref); buf[pc+0] = buf[pc+1] = 0; pc += size; } @@ -2193,7 +2203,7 @@ int coding = bc_initref.getInt(); // Find the nth overloading of in classRef. MemberEntry ref = pkg.cp.getOverloadingForIndex(CONSTANT_Methodref, classRef, "", coding); - fixupBuf.add(pc, Fixups.U2_FORMAT, ref); + fixupBuf.addU2(pc, ref); buf[pc+0] = buf[pc+1] = 0; pc += 2; assert(Instruction.opLength(origBC) == (pc - curPC)); @@ -2226,7 +2236,7 @@ insnMap[numInsns++] = curPC; } buf[pc++] = (byte) origBC; - fixupBuf.add(pc, Fixups.U2_FORMAT, ref); + fixupBuf.addU2(pc, ref); buf[pc+0] = buf[pc+1] = 0; pc += 2; assert(Instruction.opLength(origBC) == (pc - curPC)); @@ -2289,11 +2299,10 @@ buf[pc++] = (byte) origBC; int fmt; switch (size) { - case 1: fmt = Fixups.U1_FORMAT; break; - case 2: fmt = Fixups.U2_FORMAT; break; + case 1: fixupBuf.addU1(pc, ref); break; + case 2: fixupBuf.addU2(pc, ref); break; default: assert(false); fmt = 0; } - fixupBuf.add(pc, fmt, ref); buf[pc+0] = buf[pc+1] = 0; pc += size; if (origBC == _multianewarray) { diff -r 307d170884ea -r 50d2fb6f323f jdk/src/share/classes/com/sun/jndi/ldap/BerDecoder.java --- a/jdk/src/share/classes/com/sun/jndi/ldap/BerDecoder.java Thu May 16 02:43:58 2013 -0700 +++ b/jdk/src/share/classes/com/sun/jndi/ldap/BerDecoder.java Thu May 16 13:22:41 2013 -0700 @@ -42,7 +42,7 @@ */ public BerDecoder(byte buf[], int offset, int bufsize) { - this.buf = buf; + this.buf = buf; // shared buffer, be careful to use this class this.bufsize = bufsize; this.origOffset = offset; diff -r 307d170884ea -r 50d2fb6f323f jdk/src/share/classes/com/sun/jndi/ldap/BerEncoder.java --- a/jdk/src/share/classes/com/sun/jndi/ldap/BerEncoder.java Thu May 16 02:43:58 2013 -0700 +++ b/jdk/src/share/classes/com/sun/jndi/ldap/BerEncoder.java Thu May 16 13:22:41 2013 -0700 @@ -99,7 +99,7 @@ if (curSeqIndex != 0) { throw new IllegalStateException("BER encode error: Unbalanced SEQUENCEs."); } - return buf; + return buf; // shared buffer, be careful to use this method. } /** diff -r 307d170884ea -r 50d2fb6f323f jdk/src/share/classes/com/sun/jndi/ldap/ext/StartTlsResponseImpl.java --- a/jdk/src/share/classes/com/sun/jndi/ldap/ext/StartTlsResponseImpl.java Thu May 16 02:43:58 2013 -0700 +++ b/jdk/src/share/classes/com/sun/jndi/ldap/ext/StartTlsResponseImpl.java Thu May 16 13:22:41 2013 -0700 @@ -134,7 +134,9 @@ * @see #negotiate */ public void setEnabledCipherSuites(String[] suites) { - this.suites = suites; + // The impl does accept null suites, although the spec requires + // a non-null list. + this.suites = suites == null ? null : suites.clone(); } /** diff -r 307d170884ea -r 50d2fb6f323f jdk/src/share/classes/com/sun/tools/jdi/AbstractLauncher.java --- a/jdk/src/share/classes/com/sun/tools/jdi/AbstractLauncher.java Thu May 16 02:43:58 2013 -0700 +++ b/jdk/src/share/classes/com/sun/tools/jdi/AbstractLauncher.java Thu May 16 13:22:41 2013 -0700 @@ -142,7 +142,7 @@ * This class simply provides a context for a single launch and * accept. It provides instance fields that can be used by * all threads involved. This stuff can't be in the Connector proper - * because the connector is is a singleton and not specific to any + * because the connector is a singleton and is not specific to any * one launch. */ private class Helper { diff -r 307d170884ea -r 50d2fb6f323f jdk/src/share/classes/com/sun/tools/jdi/SunCommandLineLauncher.java --- a/jdk/src/share/classes/com/sun/tools/jdi/SunCommandLineLauncher.java Thu May 16 02:43:58 2013 -0700 +++ b/jdk/src/share/classes/com/sun/tools/jdi/SunCommandLineLauncher.java Thu May 16 13:22:41 2013 -0700 @@ -213,7 +213,7 @@ exePath = exe; } // Quote only if necessary in case the quote arg value is bogus - if (hasWhitespace(exe)) { + if (hasWhitespace(exePath)) { exePath = quote + exePath + quote; } diff -r 307d170884ea -r 50d2fb6f323f jdk/src/share/classes/java/util/logging/LogManager.java --- a/jdk/src/share/classes/java/util/logging/LogManager.java Thu May 16 02:43:58 2013 -0700 +++ b/jdk/src/share/classes/java/util/logging/LogManager.java Thu May 16 13:22:41 2013 -0700 @@ -433,11 +433,11 @@ // add a new Logger or return the one that has been added previously // as a LogManager subclass may override the addLogger, getLogger, // readConfiguration, and other methods. - Logger demandLogger(String name, String resourceBundleName) { + Logger demandLogger(String name, String resourceBundleName, Class caller) { Logger result = getLogger(name); if (result == null) { // only allocate the new logger once - Logger newLogger = new Logger(name, resourceBundleName); + Logger newLogger = new Logger(name, resourceBundleName, caller); do { if (addLogger(newLogger)) { // We successfully added the new Logger that we @@ -519,7 +519,7 @@ Logger demandLogger(String name, String resourceBundleName) { // a LogManager subclass may have its own implementation to add and // get a Logger. So delegate to the LogManager to do the work. - return manager.demandLogger(name, resourceBundleName); + return manager.demandLogger(name, resourceBundleName, null); } synchronized Logger findLogger(String name) { diff -r 307d170884ea -r 50d2fb6f323f jdk/src/share/classes/java/util/logging/Logger.java --- a/jdk/src/share/classes/java/util/logging/Logger.java Thu May 16 02:43:58 2013 -0700 +++ b/jdk/src/share/classes/java/util/logging/Logger.java Thu May 16 13:22:41 2013 -0700 @@ -191,8 +191,6 @@ * * @since 1.4 */ - - public class Logger { private static final Handler emptyHandlers[] = new Handler[0]; private static final int offValue = Level.OFF.intValue(); @@ -218,6 +216,7 @@ private ArrayList kids; // WeakReferences to loggers that have us as parent private volatile Level levelObject; private volatile int levelValue; // current effective level value + private WeakReference callersClassLoaderRef; /** * GLOBAL_LOGGER_NAME is a name for the global logger. @@ -278,18 +277,31 @@ * no corresponding resource can be found. */ protected Logger(String name, String resourceBundleName) { + this(name, resourceBundleName, null); + } + + Logger(String name, String resourceBundleName, Class caller) { this.manager = LogManager.getLogManager(); - if (resourceBundleName != null) { - // MissingResourceException or IllegalArgumentException can - // be thrown by setupResourceInfo(). Since this is the Logger - // constructor, the resourceBundleName field is null so - // IllegalArgumentException cannot happen here. - setupResourceInfo(resourceBundleName); - } + setupResourceInfo(resourceBundleName, caller); this.name = name; levelValue = Level.INFO.intValue(); } + private void setCallersClassLoaderRef(Class caller) { + ClassLoader callersClassLoader = ((caller != null) + ? caller.getClassLoader() + : null); + if (callersClassLoader != null) { + this.callersClassLoaderRef = new WeakReference(callersClassLoader); + } + } + + private ClassLoader getCallersClassLoader() { + return (callersClassLoaderRef != null) + ? callersClassLoaderRef.get() + : null; + } + // This constructor is used only to create the global Logger. // It is needed to break a cyclic dependence between the LogManager // and Logger static initializers causing deadlocks. @@ -343,7 +355,9 @@ return manager.demandSystemLogger(name, resourceBundleName); } } - return manager.demandLogger(name, resourceBundleName); + return manager.demandLogger(name, resourceBundleName, caller); + // ends up calling new Logger(name, resourceBundleName, caller) + // iff the logger doesn't exist already } /** @@ -436,11 +450,19 @@ // adding a new Logger object is handled by LogManager.addLogger(). @CallerSensitive public static Logger getLogger(String name, String resourceBundleName) { - Logger result = demandLogger(name, resourceBundleName, Reflection.getCallerClass()); + Class callerClass = Reflection.getCallerClass(); + Logger result = demandLogger(name, resourceBundleName, callerClass); // MissingResourceException or IllegalArgumentException can be // thrown by setupResourceInfo(). - result.setupResourceInfo(resourceBundleName); + // We have to set the callers ClassLoader here in case demandLogger + // above found a previously created Logger. This can happen, for + // example, if Logger.getLogger(name) is called and subsequently + // Logger.getLogger(name, resourceBundleName) is called. In this case + // we won't necessarily have the correct classloader saved away, so + // we need to set it here, too. + + result.setupResourceInfo(resourceBundleName, callerClass); return result; } @@ -507,11 +529,13 @@ // Synchronization is not required here. All synchronization for // adding a new anonymous Logger object is handled by doSetParent(). + @CallerSensitive public static Logger getAnonymousLogger(String resourceBundleName) { LogManager manager = LogManager.getLogManager(); // cleanup some Loggers that have been GC'ed manager.drainLoggerRefQueueBounded(); - Logger result = new Logger(null, resourceBundleName); + Logger result = new Logger(null, resourceBundleName, + Reflection.getCallerClass()); result.anonymous = true; Logger root = manager.getLogger(""); result.doSetParent(root); @@ -527,7 +551,7 @@ * @return localization bundle (may be null) */ public ResourceBundle getResourceBundle() { - return findResourceBundle(getResourceBundleName()); + return findResourceBundle(getResourceBundleName(), true); } /** @@ -609,7 +633,7 @@ String ebname = getEffectiveResourceBundleName(); if (ebname != null && !ebname.equals(SYSTEM_LOGGER_RB_NAME)) { lr.setResourceBundleName(ebname); - lr.setResourceBundle(findResourceBundle(ebname)); + lr.setResourceBundle(findResourceBundle(ebname, true)); } log(lr); } @@ -936,7 +960,7 @@ lr.setLoggerName(name); if (rbname != null) { lr.setResourceBundleName(rbname); - lr.setResourceBundle(findResourceBundle(rbname)); + lr.setResourceBundle(findResourceBundle(rbname, false)); } log(lr); } @@ -960,7 +984,6 @@ * can be null * @param msg The string message (or a key in the message catalog) */ - public void logrb(Level level, String sourceClass, String sourceMethod, String bundleName, String msg) { if (level.intValue() < levelValue || levelValue == offValue) { @@ -1609,9 +1632,18 @@ * there is no suitable previous cached value. * * @param name the ResourceBundle to locate + * @param userCallersClassLoader if true search using the caller's ClassLoader * @return ResourceBundle specified by name or null if not found */ - private synchronized ResourceBundle findResourceBundle(String name) { + private synchronized ResourceBundle findResourceBundle(String name, + boolean useCallersClassLoader) { + // For all lookups, we first check the thread context class loader + // if it is set. If not, we use the system classloader. If we + // still haven't found it we use the callersClassLoaderRef if it + // is set and useCallersClassLoader is true. We set + // callersClassLoaderRef initially upon creating the logger with a + // non-null resource bundle name. + // Return a null bundle for a null name. if (name == null) { return null; @@ -1644,17 +1676,40 @@ catalogLocale = currentLocale; return catalog; } catch (MissingResourceException ex) { + // We can't find the ResourceBundle in the default + // ClassLoader. Drop through. + } + + if (useCallersClassLoader) { + // Try with the caller's ClassLoader + ClassLoader callersClassLoader = getCallersClassLoader(); + + if (callersClassLoader == null || callersClassLoader == cl) { + return null; + } + + try { + catalog = ResourceBundle.getBundle(name, currentLocale, + callersClassLoader); + catalogName = name; + catalogLocale = currentLocale; + return catalog; + } catch (MissingResourceException ex) { + return null; // no luck + } + } else { return null; } } // Private utility method to initialize our one entry - // resource bundle name cache. + // resource bundle name cache and the callers ClassLoader // Note: for consistency reasons, we are careful to check // that a suitable ResourceBundle exists before setting the // resourceBundleName field. - // Synchronized to prevent races in setting the field. - private synchronized void setupResourceInfo(String name) { + // Synchronized to prevent races in setting the fields. + private synchronized void setupResourceInfo(String name, + Class callersClass) { if (name == null) { return; } @@ -1672,9 +1727,14 @@ resourceBundleName + " != " + name); } - if (findResourceBundle(name) == null) { + setCallersClassLoaderRef(callersClass); + if (findResourceBundle(name, true) == null) { // We've failed to find an expected ResourceBundle. - throw new MissingResourceException("Can't find " + name + " bundle", name, ""); + // unset the caller's ClassLoader since we were unable to find the + // the bundle using it + this.callersClassLoaderRef = null; + throw new MissingResourceException("Can't find " + name + " bundle", + name, ""); } resourceBundleName = name; } diff -r 307d170884ea -r 50d2fb6f323f jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java --- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Thu May 16 02:43:58 2013 -0700 +++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Thu May 16 13:22:41 2013 -0700 @@ -1225,7 +1225,7 @@ boolean expectContinue = false; String expects = requests.findValue("Expect"); - if ("100-Continue".equalsIgnoreCase(expects)) { + if ("100-Continue".equalsIgnoreCase(expects) && streaming()) { http.setIgnoreContinue(false); expectContinue = true; } diff -r 307d170884ea -r 50d2fb6f323f jdk/src/share/native/com/sun/java/util/jar/pack/constants.h --- a/jdk/src/share/native/com/sun/java/util/jar/pack/constants.h Thu May 16 02:43:58 2013 -0700 +++ b/jdk/src/share/native/com/sun/java/util/jar/pack/constants.h Thu May 16 13:22:41 2013 -0700 @@ -133,6 +133,8 @@ X_ATTR_Deprecated = 20, X_ATTR_RuntimeVisibleAnnotations = 21, X_ATTR_RuntimeInvisibleAnnotations = 22, + X_ATTR_RuntimeVisibleTypeAnnotations = 27, + X_ATTR_RuntimeInvisibleTypeAnnotations = 28, X_ATTR_OVERFLOW = 16, X_ATTR_LIMIT_NO_FLAGS_HI = 32, X_ATTR_LIMIT_FLAGS_HI = 63, @@ -146,6 +148,8 @@ F(X_ATTR_Deprecated,Deprecated) \ F(X_ATTR_RuntimeVisibleAnnotations,RuntimeVisibleAnnotations) \ F(X_ATTR_RuntimeInvisibleAnnotations,RuntimeInvisibleAnnotations) \ + F(X_ATTR_RuntimeVisibleTypeAnnotations,RuntimeVisibleTypeAnnotations) \ + F(X_ATTR_RuntimeInvisibleTypeAnnotations,RuntimeInvisibleTypeAnnotations) \ /*F(X_ATTR_Synthetic,Synthetic)*/ \ /*(end)*/ #define CLASS_ATTR_DO(F) \ diff -r 307d170884ea -r 50d2fb6f323f jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp --- a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp Thu May 16 02:43:58 2013 -0700 +++ b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp Thu May 16 13:22:41 2013 -0700 @@ -1791,7 +1791,7 @@ switch (*lp++) { case 'B': case 'H': case 'I': case 'V': // unsigned_int case 'S': // signed_int - --lp; // reparse + --lp; // reparse case 'F': lp = parseIntLayout(lp, b, EK_INT); break; @@ -2037,47 +2037,80 @@ MDL0 // annotations: #define MDL1 \ - "[NH[(1)]]" \ - "[RSHNH[RUH(1)]]" + "[NH[(1)]]" MDL1 - // member_value: - "[TB" - "(66,67,73,83,90)[KIH]" - "(68)[KDH]" - "(70)[KFH]" - "(74)[KJH]" - "(99)[RSH]" - "(101)[RSHRUH]" - "(115)[RUH]" - "(91)[NH[(0)]]" - "(64)[" - // nested annotation: - "RSH" - "NH[RUH(0)]" - "]" - "()[]" +#define MDL2 \ + "[RSHNH[RUH(1)]]" + MDL2 + // element_value: +#define MDL3 \ + "[TB" \ + "(66,67,73,83,90)[KIH]" \ + "(68)[KDH]" \ + "(70)[KFH]" \ + "(74)[KJH]" \ + "(99)[RSH]" \ + "(101)[RSHRUH]" \ + "(115)[RUH]" \ + "(91)[NH[(0)]]" \ + "(64)[" \ + /* nested annotation: */ \ + "RSH" \ + "NH[RUH(0)]" \ + "]" \ + "()[]" \ "]" + MDL3 ); const char* md_layout_P = md_layout; const char* md_layout_A = md_layout+strlen(MDL0); - const char* md_layout_V = md_layout+strlen(MDL0 MDL1); + const char* md_layout_V = md_layout+strlen(MDL0 MDL1 MDL2); assert(0 == strncmp(&md_layout_A[-3], ")]][", 4)); assert(0 == strncmp(&md_layout_V[-3], ")]][", 4)); +const char* type_md_layout( + "[NH[(1)(2)(3)]]" + // target-type + target_info + "[TB" + "(0,1)[B]" + "(16)[FH]" + "(17,18)[BB]" + "(19,20,21)[]" + "(22)[B]" + "(23)[H]" + "(64,65)[NH[PHOHH]]" + "(66)[H]" + "(67,68,69,70)[PH]" + "(71,72,73,74,75)[PHB]" + "()[]]" + // target-path + "[NB[BB]]" + // annotation + element_value + MDL2 + MDL3 +); + for (i = 0; i < ATTR_CONTEXT_LIMIT; i++) { attr_definitions& ad = attr_defs[i]; - ad.defineLayout(X_ATTR_RuntimeVisibleAnnotations, - "RuntimeVisibleAnnotations", md_layout_A); - ad.defineLayout(X_ATTR_RuntimeInvisibleAnnotations, - "RuntimeInvisibleAnnotations", md_layout_A); - if (i != ATTR_CONTEXT_METHOD) continue; - ad.defineLayout(METHOD_ATTR_RuntimeVisibleParameterAnnotations, - "RuntimeVisibleParameterAnnotations", md_layout_P); - ad.defineLayout(METHOD_ATTR_RuntimeInvisibleParameterAnnotations, - "RuntimeInvisibleParameterAnnotations", md_layout_P); - ad.defineLayout(METHOD_ATTR_AnnotationDefault, - "AnnotationDefault", md_layout_V); + if (i != ATTR_CONTEXT_CODE) { + ad.defineLayout(X_ATTR_RuntimeVisibleAnnotations, + "RuntimeVisibleAnnotations", md_layout_A); + ad.defineLayout(X_ATTR_RuntimeInvisibleAnnotations, + "RuntimeInvisibleAnnotations", md_layout_A); + if (i == ATTR_CONTEXT_METHOD) { + ad.defineLayout(METHOD_ATTR_RuntimeVisibleParameterAnnotations, + "RuntimeVisibleParameterAnnotations", md_layout_P); + ad.defineLayout(METHOD_ATTR_RuntimeInvisibleParameterAnnotations, + "RuntimeInvisibleParameterAnnotations", md_layout_P); + ad.defineLayout(METHOD_ATTR_AnnotationDefault, + "AnnotationDefault", md_layout_V); + } + } + ad.defineLayout(X_ATTR_RuntimeVisibleTypeAnnotations, + "RuntimeVisibleTypeAnnotations", type_md_layout); + ad.defineLayout(X_ATTR_RuntimeInvisibleTypeAnnotations, + "RuntimeInvisibleTypeAnnotations", type_md_layout); } attr_definition_headers.readData(attr_definition_count); @@ -2433,6 +2466,7 @@ ad.readBandData(X_ATTR_RuntimeVisibleAnnotations); ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations); + CHECK; count = ad.predefCount(CLASS_ATTR_InnerClasses); class_InnerClasses_N.readData(count); @@ -2452,6 +2486,10 @@ class_ClassFile_version_minor_H.readData(count); class_ClassFile_version_major_H.readData(count); CHECK; + + ad.readBandData(X_ATTR_RuntimeVisibleTypeAnnotations); + ad.readBandData(X_ATTR_RuntimeInvisibleTypeAnnotations); + CHECK; break; case ATTR_CONTEXT_FIELD: @@ -2467,6 +2505,10 @@ ad.readBandData(X_ATTR_RuntimeVisibleAnnotations); ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations); CHECK; + + ad.readBandData(X_ATTR_RuntimeVisibleTypeAnnotations); + ad.readBandData(X_ATTR_RuntimeInvisibleTypeAnnotations); + CHECK; break; case ATTR_CONTEXT_METHOD: @@ -2497,6 +2539,11 @@ method_MethodParameters_name_RUN.readData(count); method_MethodParameters_flag_FH.readData(count); CHECK; + + ad.readBandData(X_ATTR_RuntimeVisibleTypeAnnotations); + ad.readBandData(X_ATTR_RuntimeInvisibleTypeAnnotations); + CHECK; + break; case ATTR_CONTEXT_CODE: @@ -2566,18 +2613,22 @@ count = ad.predefCount(CODE_ATTR_LineNumberTable); code_LineNumberTable_N.readData(count); + CHECK; count = code_LineNumberTable_N.getIntTotal(); code_LineNumberTable_bci_P.readData(count); code_LineNumberTable_line.readData(count); + CHECK; count = ad.predefCount(CODE_ATTR_LocalVariableTable); code_LocalVariableTable_N.readData(count); + CHECK; count = code_LocalVariableTable_N.getIntTotal(); code_LocalVariableTable_bci_P.readData(count); code_LocalVariableTable_span_O.readData(count); code_LocalVariableTable_name_RU.readData(count); code_LocalVariableTable_type_RS.readData(count); code_LocalVariableTable_slot.readData(count); + CHECK; count = ad.predefCount(CODE_ATTR_LocalVariableTypeTable); code_LocalVariableTypeTable_N.readData(count); @@ -2587,6 +2638,12 @@ code_LocalVariableTypeTable_name_RU.readData(count); code_LocalVariableTypeTable_type_RS.readData(count); code_LocalVariableTypeTable_slot.readData(count); + CHECK; + + ad.readBandData(X_ATTR_RuntimeVisibleTypeAnnotations); + ad.readBandData(X_ATTR_RuntimeInvisibleTypeAnnotations); + CHECK; + break; } @@ -5151,7 +5208,7 @@ #ifndef PRODUCT int unpacker::printcr_if_verbose(int level, const char* fmt ...) { - if (verbose < level+10) return 0; + if (verbose < level) return 0; va_list vl; va_start(vl, fmt); char fmtbuf[300]; diff -r 307d170884ea -r 50d2fb6f323f jdk/test/ProblemList.txt --- a/jdk/test/ProblemList.txt Thu May 16 02:43:58 2013 -0700 +++ b/jdk/test/ProblemList.txt Thu May 16 13:22:41 2013 -0700 @@ -205,10 +205,6 @@ #7143960 java/net/DatagramSocket/SendDatagramToBadAddress.java macosx-all -# 7150552 -sun/net/www/protocol/http/B6299712.java macosx-all -java/net/CookieHandler/CookieManagerTest.java macosx-all - ############################################################################ # jdk_io diff -r 307d170884ea -r 50d2fb6f323f jdk/test/java/lang/Thread/GenerifyStackTraces.java --- a/jdk/test/java/lang/Thread/GenerifyStackTraces.java Thu May 16 02:43:58 2013 -0700 +++ b/jdk/test/java/lang/Thread/GenerifyStackTraces.java Thu May 16 13:22:41 2013 -0700 @@ -23,7 +23,7 @@ /* * @test - * @bug 4919105 + * @bug 4919105 8004177 * @summary Generified basic unit test of Thread.getAllStackTraces() * @author Mandy Chung */ @@ -33,7 +33,6 @@ public class GenerifyStackTraces { private static Object go = new Object(); - private static Object dumpObj = new Object(); private static String[] methodNames = {"run", "A", "B", "C", "Done"}; private static int DONE_DEPTH = 5; private static boolean testFailed = false; @@ -48,19 +47,26 @@ one = new ThreadOne(); one.start(); - Thread dt = new DumpThread(); - dt.setDaemon(true); + DumpThread dt = new DumpThread(); dt.start(); + try { + one.join(); + } finally { + dt.shutdown(); + } + if (testFailed) { throw new RuntimeException("Test Failed."); } } static class DumpThread extends Thread { + private volatile boolean finished = false; + public void run() { int depth = 2; - while (true) { + while (!finished) { // At each iterator, wait until ThreadOne blocks // to wait for thread dump. // Then dump stack trace and notify ThreadOne to continue. @@ -75,6 +81,11 @@ } } } + + public void shutdown() throws InterruptedException { + finished = true; + this.join(); + } } static class ThreadOne extends Thread { diff -r 307d170884ea -r 50d2fb6f323f jdk/test/java/lang/Thread/StackTraces.java --- a/jdk/test/java/lang/Thread/StackTraces.java Thu May 16 02:43:58 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,182 +0,0 @@ -/* - * Copyright (c) 2003, 2010, 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 4593133 - * @summary Basic unit test of Thread.getStackTraces() - * @author Mandy Chung - */ - -import java.util.*; - -public class StackTraces { - - private static Object go = new Object(); - private static Object dumpObj = new Object(); - private static String[] methodNames = {"run", "A", "B", "C", "Done"}; - private static int DONE_DEPTH = 5; - private static boolean testFailed = false; - - private static Thread one; - private static boolean trace = false; - public static void main(String[] args) throws Exception { - if (args.length > 0 && args[0].equals("trace")) { - trace = true; - } - - one = new ThreadOne(); - one.start(); - - Thread dt = new DumpThread(); - dt.setDaemon(true); - dt.start(); - - if (testFailed) { - throw new RuntimeException("Test Failed."); - } - } - - static class DumpThread extends Thread { - public void run() { - int depth = 2; - while (true) { - // At each iterator, wait until ThreadOne blocks - // to wait for thread dump. - // Then dump stack trace and notify ThreadOne to continue. - try { - sleep(2000); - dumpStacks(depth); - depth++; - finishDump(); - } catch (Exception e) { - e.printStackTrace(); - testFailed = true; - } - } - } - } - - static class ThreadOne extends Thread { - public void run() { - A(); - } - private void A() { - waitForDump(); - B(); - } - private void B() { - waitForDump(); - C(); - } - private void C() { - waitForDump(); - Done(); - } - private void Done() { - waitForDump(); - - // Get stack trace of current thread - StackTraceElement[] stack = getStackTrace(); - try { - checkStack(this, stack, DONE_DEPTH); - } catch (Exception e) { - e.printStackTrace(); - testFailed = true; - } - } - - } - - - static private void waitForDump() { - synchronized(go) { - try { - go.wait(); - } catch (Exception e) { - throw new RuntimeException("Unexpected exception" + e); - } - } - } - - static private void finishDump() { - synchronized(go) { - try { - go.notifyAll(); - } catch (Exception e) { - throw new RuntimeException("Unexpected exception" + e); - } - } - } - - public static void dumpStacks(int depth) throws Exception { - // Get stack trace of another thread - StackTraceElement[] stack = one.getStackTrace(); - checkStack(one, stack, depth); - - // Get stack traces of all Threads - Map m = Thread.getAllStackTraces(); - Set s = m.entrySet(); - Iterator iter = s.iterator(); - - Map.Entry entry; - while (iter.hasNext()) { - entry = (Map.Entry) iter.next(); - Thread t = (Thread) entry.getKey(); - stack = (StackTraceElement[]) entry.getValue(); - if (t == null || stack == null) { - throw new RuntimeException("Null thread or stacktrace returned"); - } - if (t == one) { - checkStack(t, stack, depth); - } - } - } - - private static void checkStack(Thread t, StackTraceElement[] stack, - int depth) throws Exception { - if (trace) { - printStack(t, stack); - } - int frame = stack.length - 1; - for (int i = 0; i < depth && frame >= 0; i++) { - if (! stack[frame].getMethodName().equals(methodNames[i])) { - throw new RuntimeException("Expected " + methodNames[i] + - " in frame " + frame + " but got " + - stack[frame].getMethodName()); - } - frame--; - } - } - - private static void printStack(Thread t, StackTraceElement[] stack) { - System.out.println(t + - " stack: (length = " + stack.length + ")"); - if (t != null) { - for (int j = 0; j < stack.length; j++) { - System.out.println(stack[j]); - } - System.out.println(); - } - } -} diff -r 307d170884ea -r 50d2fb6f323f jdk/test/java/net/CookieHandler/CookieManagerTest.java --- a/jdk/test/java/net/CookieHandler/CookieManagerTest.java Thu May 16 02:43:58 2013 -0700 +++ b/jdk/test/java/net/CookieHandler/CookieManagerTest.java Thu May 16 13:22:41 2013 -0700 @@ -24,21 +24,25 @@ /* * @test * @summary Unit test for java.net.CookieManager - * @bug 6244040 - * @library ../../../sun/net/www/httptest/ - * @build HttpCallback TestHttpServer ClosedChannelList HttpTransaction + * @bug 6244040 7150552 * @run main/othervm -ea CookieManagerTest * @author Edward Wang */ -import java.net.*; -import java.util.*; -import java.io.*; -import sun.net.www.MessageHeader; +import com.sun.net.httpserver.*; +import java.io.IOException; +import java.net.CookieHandler; +import java.net.CookieManager; +import java.net.CookiePolicy; +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.URL; public class CookieManagerTest { - static CookieHttpTransaction httpTrans; - static TestHttpServer server; + + static CookieTransactionHandler httpTrans; + static HttpServer server; public static void main(String[] args) throws Exception { startHttpServer(); @@ -49,41 +53,48 @@ } } - public static void startHttpServer() { - try { - httpTrans = new CookieHttpTransaction(); - server = new TestHttpServer(httpTrans, 1, 1, 0); - } catch (IOException e) { - e.printStackTrace(); - } + public static void startHttpServer() throws IOException { + httpTrans = new CookieTransactionHandler(); + server = HttpServer.create(new InetSocketAddress(0), 0); + server.createContext("/", httpTrans); + server.start(); } - public static void makeHttpCall() { + public static void makeHttpCall() throws IOException { try { - System.out.println("http server listen on: " + server.getLocalPort()); + System.out.println("http server listenining on: " + + server.getAddress().getPort()); // install CookieManager to use CookieHandler.setDefault(new CookieManager()); - for (int i = 0; i < CookieHttpTransaction.testCount; i++) { - System.out.println("====== CookieManager test " + (i+1) + " ======"); - ((CookieManager)CookieHandler.getDefault()).setCookiePolicy(CookieHttpTransaction.testPolicies[i]); - ((CookieManager)CookieHandler.getDefault()).getCookieStore().removeAll(); - URL url = new URL("http" , InetAddress.getLocalHost().getHostAddress(), - server.getLocalPort(), CookieHttpTransaction.testCases[i][0].serverPath); + for (int i = 0; i < CookieTransactionHandler.testCount; i++) { + System.out.println("====== CookieManager test " + (i+1) + + " ======"); + ((CookieManager)CookieHandler.getDefault()) + .setCookiePolicy(CookieTransactionHandler.testPolicies[i]); + ((CookieManager)CookieHandler.getDefault()) + .getCookieStore().removeAll(); + URL url = new URL("http" , + InetAddress.getLocalHost().getHostAddress(), + server.getAddress().getPort(), + CookieTransactionHandler.testCases[i][0] + .serverPath); HttpURLConnection uc = (HttpURLConnection)url.openConnection(); uc.getResponseCode(); uc.disconnect(); } - } catch (IOException e) { - e.printStackTrace(); } finally { - server.terminate(); + server.stop(0); } } } -class CookieHttpTransaction implements HttpCallback { +class CookieTransactionHandler implements HttpHandler { + + private int testcaseDone = 0; + private int testDone = 0; + public static boolean badRequest = false; // the main test control logic will also loop exactly this number // to send http request @@ -91,6 +102,47 @@ private String localHostAddr = "127.0.0.1"; + @Override + public void handle(HttpExchange exchange) throws IOException { + if (testDone < testCases[testcaseDone].length) { + // still have other tests to run, + // check the Cookie header and then redirect it + if (testDone > 0) checkRequest(exchange.getRequestHeaders()); + exchange.getResponseHeaders().add("Location", + testCases[testcaseDone][testDone].serverPath); + exchange.getResponseHeaders() + .add(testCases[testcaseDone][testDone].headerToken, + testCases[testcaseDone][testDone].cookieToSend); + exchange.sendResponseHeaders(302, -1); + testDone++; + } else { + // the last test of this test case + if (testDone > 0) checkRequest(exchange.getRequestHeaders()); + testcaseDone++; + testDone = 0; + exchange.sendResponseHeaders(200, -1); + } + exchange.close(); + } + + private void checkRequest(Headers hdrs) { + + assert testDone > 0; + String cookieHeader = hdrs.getFirst("Cookie"); + if (cookieHeader != null && + cookieHeader + .equalsIgnoreCase(testCases[testcaseDone][testDone-1] + .cookieToRecv)) + { + System.out.printf("%15s %s\n", "PASSED:", cookieHeader); + } else { + System.out.printf("%15s %s\n", "FAILED:", cookieHeader); + System.out.printf("%15s %s\n\n", "should be:", + testCases[testcaseDone][testDone-1].cookieToRecv); + badRequest = true; + } + } + // test cases public static class CookieTestCase { public String headerToken; @@ -106,13 +158,17 @@ } }; - // - // these two must match each other, i.e. testCases.length == testPolicies.length - // - public static CookieTestCase[][] testCases = null; // the test cases to run; each test case may contain multiple roundtrips - public static CookiePolicy[] testPolicies = null; // indicates what CookiePolicy to use with each test cases + /* + * these two must match each other, + * i.e. testCases.length == testPolicies.length + */ - CookieHttpTransaction() { + // the test cases to run; each test case may contain multiple roundtrips + public static CookieTestCase[][] testCases = null; + // indicates what CookiePolicy to use with each test cases + public static CookiePolicy[] testPolicies = null; + + CookieTransactionHandler() { testCases = new CookieTestCase[testCount][]; testPolicies = new CookiePolicy[testCount]; @@ -126,7 +182,9 @@ testPolicies[count] = CookiePolicy.ACCEPT_ORIGINAL_SERVER; testCases[count++] = new CookieTestCase[]{ new CookieTestCase("Set-Cookie", - "CUSTOMER=WILE:BOB; path=/; expires=Sat, 09-Nov-2030 23:12:40 GMT;" + "domain=." + localHostAddr, + "CUSTOMER=WILE:BOB; " + + "path=/; expires=Sat, 09-Nov-2030 23:12:40 GMT;" + "domain=." + + localHostAddr, "CUSTOMER=WILE:BOB", "/" ), @@ -172,12 +230,17 @@ ), new CookieTestCase("Set-Cookie2", "Part_Number=\"Rocket_Launcher_0001\"; Version=\"1\";Path=\"/acme\";" + "domain=." + localHostAddr, - "$Version=\"1\"; Customer=\"WILE_E_COYOTE\";$Path=\"/acme\";" + "$Domain=\"." + localHostAddr + "\"" + "; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";" + "$Domain=\"." + localHostAddr + "\"", + "$Version=\"1\"; Customer=\"WILE_E_COYOTE\";$Path=\"/acme\";" + "$Domain=\"." + + localHostAddr + "\"" + "; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";" + + "$Domain=\"." + localHostAddr + "\"", "/acme/pickitem" ), new CookieTestCase("Set-Cookie2", "Shipping=\"FedEx\"; Version=\"1\"; Path=\"/acme\";" + "domain=." + localHostAddr, - "$Version=\"1\"; Customer=\"WILE_E_COYOTE\";$Path=\"/acme\";" + "$Domain=\"." + localHostAddr + "\"" + "; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";" + "$Domain=\"." + localHostAddr + "\"" + "; Shipping=\"FedEx\";$Path=\"/acme\";" + "$Domain=\"." + localHostAddr + "\"", + "$Version=\"1\"; Customer=\"WILE_E_COYOTE\";$Path=\"/acme\";" + "$Domain=\"." + localHostAddr + + "\"" + "; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";" + "$Domain=\"." + + localHostAddr + "\"" + "; Shipping=\"FedEx\";$Path=\"/acme\";" + + "$Domain=\"." + localHostAddr + "\"", "/acme/shipping" ) }; @@ -191,8 +254,11 @@ "/acme/ammo" ), new CookieTestCase("Set-Cookie2", - "Part_Number=\"Riding_Rocket_0023\"; Version=\"1\"; Path=\"/acme/ammo\";" + "domain=." + localHostAddr, - "$Version=\"1\"; Part_Number=\"Riding_Rocket_0023\";$Path=\"/acme/ammo\";$Domain=\"." + localHostAddr + "\"" + "; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";" + "$Domain=\"." + localHostAddr + "\"", + "Part_Number=\"Riding_Rocket_0023\"; Version=\"1\"; Path=\"/acme/ammo\";" + "domain=." + + localHostAddr, + "$Version=\"1\"; Part_Number=\"Riding_Rocket_0023\";$Path=\"/acme/ammo\";$Domain=\"." + + localHostAddr + "\"" + "; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";" + + "$Domain=\"." + localHostAddr + "\"", "/acme/ammo" ), new CookieTestCase("", @@ -228,60 +294,19 @@ ), new CookieTestCase("Set-Cookie2", "Part_Number=\"Rocket_Launcher_0001\"; Version=\"1\";Path=\"/acme\"", - "$Version=\"1\"; Customer=\"WILE_E_COYOTE\";$Path=\"/acme\";$Domain=\""+localHostAddr+"\"" + "; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";$Domain=\""+localHostAddr+"\"", + "$Version=\"1\"; Customer=\"WILE_E_COYOTE\";$Path=\"/acme\";$Domain=\""+localHostAddr+"\"" + + "; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";$Domain=\""+localHostAddr+"\"", "/acme/pickitem" ), new CookieTestCase("Set-Cookie2", "Shipping=\"FedEx\"; Version=\"1\"; Path=\"/acme\"", - "$Version=\"1\"; Customer=\"WILE_E_COYOTE\";$Path=\"/acme\";$Domain=\""+localHostAddr+"\"" + "; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";$Domain=\""+localHostAddr+"\"" + "; Shipping=\"FedEx\";$Path=\"/acme\";$Domain=\""+localHostAddr+"\"", + "$Version=\"1\"; Customer=\"WILE_E_COYOTE\";$Path=\"/acme\";$Domain=\""+localHostAddr+"\"" + + "; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";$Domain=\""+localHostAddr+"\"" + + "; Shipping=\"FedEx\";$Path=\"/acme\";$Domain=\""+localHostAddr+"\"", "/acme/shipping" ) }; assert count == testCount; } - - private int testcaseDone = 0; - private int testDone = 0; - /* - * Our http server which is conducted by testCases array - */ - public void request(HttpTransaction trans) { - try { - if (testDone < testCases[testcaseDone].length) { - // still have other tests to run, - // check the Cookie header and then redirect it - if (testDone > 0) checkResquest(trans); - trans.addResponseHeader("Location", testCases[testcaseDone][testDone].serverPath); - trans.addResponseHeader(testCases[testcaseDone][testDone].headerToken, - testCases[testcaseDone][testDone].cookieToSend); - testDone++; - trans.sendResponse(302, "Moved Temporarily"); - } else { - // the last test of this test case - if (testDone > 0) checkResquest(trans); - testcaseDone++; - testDone = 0; - trans.sendResponse(200, "OK"); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - private void checkResquest(HttpTransaction trans) { - String cookieHeader = null; - - assert testDone > 0; - cookieHeader = trans.getRequestHeader("Cookie"); - if (cookieHeader != null && - cookieHeader.equalsIgnoreCase(testCases[testcaseDone][testDone-1].cookieToRecv)) - { - System.out.printf("%15s %s\n", "PASSED:", cookieHeader); - } else { - System.out.printf("%15s %s\n", "FAILED:", cookieHeader); - System.out.printf("%15s %s\n\n", "should be:", testCases[testcaseDone][testDone-1].cookieToRecv); - badRequest = true; - } - } } diff -r 307d170884ea -r 50d2fb6f323f jdk/test/java/util/logging/bundlesearch/IndirectlyLoadABundle.java --- a/jdk/test/java/util/logging/bundlesearch/IndirectlyLoadABundle.java Thu May 16 02:43:58 2013 -0700 +++ b/jdk/test/java/util/logging/bundlesearch/IndirectlyLoadABundle.java Thu May 16 13:22:41 2013 -0700 @@ -23,41 +23,26 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.nio.file.Paths; +import java.util.logging.Logger; /** * This class is used to ensure that a resource bundle loadable by a classloader - * is on the caller's stack, but not on the classpath or TCCL to ensure that - * Logger.getLogger() can't load the bundle via a stack search + * is on the caller's stack, but not on the classpath or TCCL. It tests that + * Logger.getLogger() can load the bundle via the immediate caller's classloader * * @author Jim Gish */ public class IndirectlyLoadABundle { - private final static String rbName = "StackSearchableResource"; + private final static String rbName = "CallerSearchableResource"; public boolean loadAndTest() throws Throwable { - // Find out where we are running from so we can setup the URLClassLoader URLs - // test.src and test.classes will be set if running in jtreg, but probably - // not otherwise - String testDir = System.getProperty("test.src", System.getProperty("user.dir")); - String testClassesDir = System.getProperty("test.classes", - System.getProperty("user.dir")); - String sep = System.getProperty("file.separator"); - - URL[] urls = new URL[2]; - - // Allow for both jtreg and standalone cases here - urls[0] = Paths.get(testDir, "resources").toUri().toURL(); - urls[1] = Paths.get(testClassesDir).toUri().toURL(); - - System.out.println("INFO: urls[0] = " + urls[0]); - System.out.println("INFO: urls[1] = " + urls[1]); - // Make sure we can find it via the URLClassLoader - URLClassLoader yetAnotherResourceCL = new URLClassLoader(urls, null); + URLClassLoader yetAnotherResourceCL = new URLClassLoader(getURLs(), null); if (!testForValidResourceSetup(yetAnotherResourceCL)) { throw new Exception("Couldn't directly load bundle " + rbName + " as expected. Test config problem"); @@ -70,23 +55,109 @@ + " able to. Test config problem"); } - Class loadItUpClazz = Class.forName("LoadItUp", true, yetAnotherResourceCL); + Class loadItUpClazz = Class.forName("LoadItUp1", true, + yetAnotherResourceCL); ClassLoader actual = loadItUpClazz.getClassLoader(); if (actual != yetAnotherResourceCL) { - throw new Exception("LoadItUp was loaded by an unexpected CL: " + actual); + throw new Exception("LoadItUp1 was loaded by an unexpected CL: " + actual); } Object loadItUp = loadItUpClazz.newInstance(); - Method testMethod = loadItUpClazz.getMethod("test", String.class); + Method testMethod = loadItUpClazz.getMethod("getLogger", String.class, String.class); try { - return (Boolean) testMethod.invoke(loadItUp, rbName); + return (Logger)testMethod.invoke(loadItUp, "NestedLogger1", rbName) != null; + } catch (InvocationTargetException ex) { + throw ex.getTargetException(); + } + } + + public boolean testGetAnonymousLogger() throws Throwable { + // Test getAnonymousLogger() + URLClassLoader loadItUpCL = new URLClassLoader(getURLs(), null); + Class loadItUpClazz = Class.forName("LoadItUp1", true, loadItUpCL); + ClassLoader actual = loadItUpClazz.getClassLoader(); + if (actual != loadItUpCL) { + throw new Exception("LoadItUp1 was loaded by an unexpected CL: " + + actual); + } + Object loadItUpAnon = loadItUpClazz.newInstance(); + Method testAnonMethod = loadItUpClazz.getMethod("getAnonymousLogger", + String.class); + try { + return (Logger)testAnonMethod.invoke(loadItUpAnon, rbName) != null; } catch (InvocationTargetException ex) { throw ex.getTargetException(); } } + + public boolean testGetLoggerGetLoggerWithBundle() throws Throwable { + // test getLogger("NestedLogger2"); followed by + // getLogger("NestedLogger2", rbName) to see if the bundle is found + // + URL[] urls = getURLs(); + if (getLoggerWithNewCL(urls, "NestedLogger2", null)) { + return getLoggerWithNewCL(urls, "NestedLogger2", rbName); + + } else { + throw new Exception("TEST FAILED: first call to getLogger() failed " + + " in IndirectlyLoadABundle." + + "testGetLoggerGetLoggerWithBundle"); + } + } + + private URL[] getURLs() throws MalformedURLException { + // Find out where we are running from so we can setup the URLClassLoader URLs + // test.src and test.classes will be set if running in jtreg, but probably + // not otherwise + String testDir = System.getProperty("test.src", System.getProperty("user.dir")); + String testClassesDir = System.getProperty("test.classes", + System.getProperty("user.dir")); + URL[] urls = new URL[2]; + // Allow for both jtreg and standalone cases here + urls[0] = Paths.get(testDir, "resources").toUri().toURL(); + urls[1] = Paths.get(testClassesDir).toUri().toURL(); + + return urls; + } + + private boolean getLoggerWithNewCL(URL[] urls, String loggerName, + String bundleName) throws Throwable { + Logger result = null;; + // Test getLogger("foo"); getLogger("foo", "rbName"); + // First do the getLogger() call with no bundle name + URLClassLoader getLoggerCL = new URLClassLoader(urls, null); + Class loadItUpClazz1 = Class.forName("LoadItUp1", true, getLoggerCL); + ClassLoader actual = loadItUpClazz1.getClassLoader(); + if (actual != getLoggerCL) { + throw new Exception("LoadItUp1 was loaded by an unexpected CL: " + + actual); + } + Object loadItUp1 = loadItUpClazz1.newInstance(); + if (bundleName != null) { + Method getLoggerMethod = loadItUpClazz1.getMethod("getLogger", + String.class, + String.class); + try { + result = (Logger) getLoggerMethod.invoke(loadItUp1, loggerName, + bundleName); + } catch (InvocationTargetException ex) { + throw ex.getTargetException(); + } + } else { + Method getLoggerMethod = loadItUpClazz1.getMethod("getLogger", + String.class); + try { + result = (Logger) getLoggerMethod.invoke(loadItUp1, loggerName); + } catch (InvocationTargetException ex) { + throw ex.getTargetException(); + } + } + return result != null; + } + private boolean testForValidResourceSetup(ClassLoader cl) { - // First make sure the test environment is setup properly and the bundle actually - // exists + // First make sure the test environment is setup properly and the bundle + // actually exists return ResourceBundleSearchTest.isOnClassPath(rbName, cl); } } diff -r 307d170884ea -r 50d2fb6f323f jdk/test/java/util/logging/bundlesearch/LoadItUp.java --- a/jdk/test/java/util/logging/bundlesearch/LoadItUp.java Thu May 16 02:43:58 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/* - * 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.util.MissingResourceException; -import java.util.logging.Logger; - -/* - * This class is loaded onto the call stack when the test method is called - * and then its classloader can be used to find a property bundle in the same - * directory as the class. However, Logger is not allowed - * to find the bundle by looking up the stack for this classloader. - * We verify that this cannot happen. - * - * @author Jim Gish - */ -public class LoadItUp { - - private final static boolean DEBUG = false; - - public Boolean test(String rbName) throws Exception { - // we should not be able to find the resource in this directory via - // getLogger calls. The only way that would be possible given this setup - // is that if Logger.getLogger searched up the call stack - return lookupBundle(rbName); - } - - private boolean lookupBundle(String rbName) { - // See if Logger.getLogger can find the resource in this directory - try { - Logger aLogger = Logger.getLogger("NestedLogger", rbName); - } catch (MissingResourceException re) { - if (DEBUG) { - System.out.println( - "As expected, LoadItUp.lookupBundle() did not find the bundle " - + rbName); - } - return false; - } - System.out.println("FAILED: LoadItUp.lookupBundle() found the bundle " - + rbName + " using a stack search."); - return true; - } -} diff -r 307d170884ea -r 50d2fb6f323f jdk/test/java/util/logging/bundlesearch/LoadItUp1.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/util/logging/bundlesearch/LoadItUp1.java Thu May 16 13:22:41 2013 -0700 @@ -0,0 +1,49 @@ +/* + * 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.util.logging.Logger; + +/* + * This class is loaded onto the call stack when the getLogger methods are + * called and then the classes classloader can be used to find a bundle in + * the same directory as the class. However, Logger is not allowed + * to find the bundle by looking up the stack for this classloader. + * We verify that this cannot happen. + * + * @author Jim Gish + */ +public class LoadItUp1 { + public Logger getAnonymousLogger(String rbName) throws Exception { + // we should not be able to find the resource in this directory via + // getLogger calls. The only way that would be possible given this setup + // is that if Logger.getLogger searched up the call stack + return Logger.getAnonymousLogger(rbName); + } + + public Logger getLogger(String loggerName) { + return Logger.getLogger(loggerName); + } + + public Logger getLogger(String loggerName,String bundleName) { + return Logger.getLogger(loggerName, bundleName); + } +} diff -r 307d170884ea -r 50d2fb6f323f jdk/test/java/util/logging/bundlesearch/LoadItUp2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/util/logging/bundlesearch/LoadItUp2.java Thu May 16 13:22:41 2013 -0700 @@ -0,0 +1,62 @@ +/* + * 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.util.MissingResourceException; +import java.util.logging.Logger; + +/* + * This class is loaded onto the call stack by LoadItUp2Invoker from a separate + * classloader. LoadItUp2Invoker was loaded by a class loader that does have + * access to the bundle, but the class loader used to load this class does not. + * Thus the logging code should not be able to see the resource bundle unless + * it has more than a single level stack crawl, which is not allowed. + * + * @author Jim Gish + */ +public class LoadItUp2 { + + private final static boolean DEBUG = false; + + public Boolean test(String rbName) throws Exception { + // we should not be able to find the resource in this directory via + // getLogger calls. The only way that would be possible given this setup + // is that if Logger.getLogger searched up the call stack + return lookupBundle(rbName); + } + + private boolean lookupBundle(String rbName) { + // See if Logger.getLogger can find the resource in this directory + try { + Logger aLogger = Logger.getLogger("NestedLogger2", rbName); + } catch (MissingResourceException re) { + if (DEBUG) { + System.out.println( + "As expected, LoadItUp2.lookupBundle() did not find the bundle " + + rbName); + } + return false; + } + System.out.println("FAILED: LoadItUp2.lookupBundle() found the bundle " + + rbName + " using a stack search."); + return true; + } +} diff -r 307d170884ea -r 50d2fb6f323f jdk/test/java/util/logging/bundlesearch/LoadItUp2Invoker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/util/logging/bundlesearch/LoadItUp2Invoker.java Thu May 16 13:22:41 2013 -0700 @@ -0,0 +1,60 @@ +/* + * 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.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +/** + * This class is loaded by a class loader that can see the resource. It creates + * a new classloader for LoadItUp2 which cannot see the resource. So, 2 levels + * up the call chain we have a class/classloader that can see the resource, but + * 1 level up the class/classloader cannot. + * + * @author Jim Gish + */ +public class LoadItUp2Invoker { + private URLClassLoader cl; + private String rbName; + private Object loadItUp2; + private Method testMethod; + + public void setup(URL[] urls, String rbName) throws + ReflectiveOperationException { + this.cl = new URLClassLoader(urls, null); + this.rbName = rbName; + // Using this new classloader, load the actual test class + // which is now two levels removed from the original caller + Class loadItUp2Clazz = Class.forName("LoadItUp2", true , cl); + this.loadItUp2 = loadItUp2Clazz.newInstance(); + this.testMethod = loadItUp2Clazz.getMethod("test", String.class); + } + + public Boolean test() throws Throwable { + try { + return (Boolean) testMethod.invoke(loadItUp2, rbName); + } catch (InvocationTargetException ex) { + throw ex.getTargetException(); + } + } +} diff -r 307d170884ea -r 50d2fb6f323f jdk/test/java/util/logging/bundlesearch/ResourceBundleSearchTest.java --- a/jdk/test/java/util/logging/bundlesearch/ResourceBundleSearchTest.java Thu May 16 02:43:58 2013 -0700 +++ b/jdk/test/java/util/logging/bundlesearch/ResourceBundleSearchTest.java Thu May 16 13:22:41 2013 -0700 @@ -23,11 +23,11 @@ /* * @test - * @bug 8002070 + * @bug 8002070 8013382 * @summary Remove the stack search for a resource bundle Logger to use * @author Jim Gish - * @build ResourceBundleSearchTest IndirectlyLoadABundle LoadItUp - * @run main ResourceBundleSearchTest + * @build ResourceBundleSearchTest IndirectlyLoadABundle LoadItUp1 LoadItUp2 TwiceIndirectlyLoadABundle LoadItUp2Invoker + * @run main/othervm ResourceBundleSearchTest */ import java.net.URL; import java.net.URLClassLoader; @@ -39,6 +39,12 @@ import java.util.ResourceBundle; import java.util.logging.Logger; +/** + * This class tests various scenarios of loading resource bundles from + * java.util.logging. Since jtreg uses the logging system, it is necessary to + * run these tests using othervm mode to ensure no interference from logging + * initialization by jtreg + */ public class ResourceBundleSearchTest { private final static boolean DEBUG = false; @@ -60,15 +66,11 @@ // ensure we are using en as the default Locale so we can find the resource Locale.setDefault(Locale.ENGLISH); - String testClasses = System.getProperty("test.classes"); - System.out.println( "test.classes = " + testClasses ); - ClassLoader myClassLoader = ClassLoader.getSystemClassLoader(); // Find out where we are running from so we can setup the URLClassLoader URL String userDir = System.getProperty("user.dir"); String testDir = System.getProperty("test.src", userDir); - String sep = System.getProperty("file.separator"); URL[] urls = new URL[1]; @@ -77,30 +79,41 @@ // Test 1 - can we find a Logger bundle from doing a stack search? // We shouldn't be able to - assertFalse(testGetBundleFromStackSearch(), "testGetBundleFromStackSearch"); + assertFalse(testGetBundleFromStackSearch(), "1-testGetBundleFromStackSearch"); // Test 2 - can we find a Logger bundle off of the Thread context class // loader? We should be able to. - assertTrue( - testGetBundleFromTCCL(TCCL_TEST_BUNDLE, rbClassLoader), - "testGetBundleFromTCCL"); + assertTrue(testGetBundleFromTCCL(TCCL_TEST_BUNDLE, rbClassLoader), + "2-testGetBundleFromTCCL"); // Test 3 - Can we find a Logger bundle from the classpath? We should be - // able to, but .... - // We check to see if the bundle is on the classpath or not so that this - // will work standalone. In the case of jtreg/samevm, - // the resource bundles are not on the classpath. Running standalone - // (or othervm), they are + // able to. We'll first check to make sure the setup is correct and + // it actually is on the classpath before checking whether logging + // can see it there. if (isOnClassPath(PROP_RB_NAME, myClassLoader)) { debug("We should be able to see " + PROP_RB_NAME + " on the classpath"); assertTrue(testGetBundleFromSystemClassLoader(PROP_RB_NAME), - "testGetBundleFromSystemClassLoader"); + "3-testGetBundleFromSystemClassLoader"); } else { - debug("We should not be able to see " + PROP_RB_NAME + " on the classpath"); - assertFalse(testGetBundleFromSystemClassLoader(PROP_RB_NAME), - "testGetBundleFromSystemClassLoader"); + throw new Exception("TEST SETUP FAILURE: Cannot see " + PROP_RB_NAME + + " on the classpath"); } + // Test 4 - we should be able to find a bundle from the caller's + // classloader, but only one level up. + assertTrue(testGetBundleFromCallersClassLoader(), + "4-testGetBundleFromCallersClassLoader"); + + // Test 5 - this ensures that getAnonymousLogger(String rbName) + // can find the bundle from the caller's classloader + assertTrue(testGetAnonymousLogger(), "5-testGetAnonymousLogger"); + + // Test 6 - first call getLogger("myLogger"). + // Then call getLogger("myLogger","bundleName") from a different ClassLoader + // Make sure we find the bundle + assertTrue(testGetBundleFromSecondCallersClassLoader(), + "6-testGetBundleFromSecondCallersClassLoader"); + report(); } @@ -112,7 +125,7 @@ System.out.println(msg); } throw new Exception(numFail + " out of " + (numPass + numFail) - + " tests failed."); + + " tests failed."); } } @@ -122,7 +135,7 @@ } else { numFail++; System.out.println("FAILED: " + testName - + " was supposed to return true but did NOT!"); + + " was supposed to return true but did NOT!"); } } @@ -132,13 +145,20 @@ } else { numFail++; System.out.println("FAILED: " + testName - + " was supposed to return false but did NOT!"); + + " was supposed to return false but did NOT!"); } } public boolean testGetBundleFromStackSearch() throws Throwable { // This should fail. This was the old functionality to search up the // caller's call stack + TwiceIndirectlyLoadABundle indirectLoader = new TwiceIndirectlyLoadABundle(); + return indirectLoader.loadAndTest(); + } + + public boolean testGetBundleFromCallersClassLoader() throws Throwable { + // This should pass. This exercises getting the bundle using the + // class loader of the caller (one level up) IndirectlyLoadABundle indirectLoader = new IndirectlyLoadABundle(); return indirectLoader.loadAndTest(); } @@ -193,14 +213,29 @@ bundleName); } catch (MissingResourceException re) { msgs.add("INFO: testGetBundleFromSystemClassLoader() did not find bundle " - + bundleName); + + bundleName); return false; } msgs.add("INFO: testGetBundleFromSystemClassLoader() found the bundle " - + bundleName); + + bundleName); return true; } + private boolean testGetAnonymousLogger() throws Throwable { + // This should pass. This exercises getting the bundle using the + // class loader of the caller (one level up) when calling + // Logger.getAnonymousLogger(String rbName) + IndirectlyLoadABundle indirectLoader = new IndirectlyLoadABundle(); + return indirectLoader.testGetAnonymousLogger(); + } + + private boolean testGetBundleFromSecondCallersClassLoader() throws Throwable { + // This should pass. This exercises getting the bundle using the + // class loader of the caller (one level up) + IndirectlyLoadABundle indirectLoader = new IndirectlyLoadABundle(); + return indirectLoader.testGetLoggerGetLoggerWithBundle(); + } + public static class LoggingThread extends Thread { boolean foundBundle = false; @@ -227,13 +262,13 @@ // this should succeed if the bundle is on the system classpath. try { Logger aLogger = Logger.getLogger(ResourceBundleSearchTest.newLoggerName(), - bundleName); - msg = "INFO: LoggingRunnable() found the bundle " + bundleName - + (setTCCL ? " with " : " without ") + "setting the TCCL"; + bundleName); + msg = "INFO: LoggingThread.run() found the bundle " + bundleName + + (setTCCL ? " with " : " without ") + "setting the TCCL"; foundBundle = true; } catch (MissingResourceException re) { - msg = "INFO: LoggingRunnable() did not find the bundle " + bundleName - + (setTCCL ? " with " : " without ") + "setting the TCCL"; + msg = "INFO: LoggingThread.run() did not find the bundle " + bundleName + + (setTCCL ? " with " : " without ") + "setting the TCCL"; foundBundle = false; } } catch (Throwable e) { diff -r 307d170884ea -r 50d2fb6f323f jdk/test/java/util/logging/bundlesearch/TwiceIndirectlyLoadABundle.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/util/logging/bundlesearch/TwiceIndirectlyLoadABundle.java Thu May 16 13:22:41 2013 -0700 @@ -0,0 +1,91 @@ +/* + * 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.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Paths; + +/** + * This class constructs a scenario where a bundle is accessible on the call + * stack two levels up from the call to getLogger(), but not on the immediate + * caller. This tests that getLogger() isn't doing a stack crawl more than one + * level up to find a bundle. + * + * @author Jim Gish + */ +public class TwiceIndirectlyLoadABundle { + + private final static String rbName = "StackSearchableResource"; + + public boolean loadAndTest() throws Throwable { + // Find out where we are running from so we can setup the URLClassLoader URLs + // test.src and test.classes will be set if running in jtreg, but probably + // not otherwise + String testDir = System.getProperty("test.src", System.getProperty("user.dir")); + String testClassesDir = System.getProperty("test.classes", + System.getProperty("user.dir")); + URL[] urls = new URL[2]; + + // Allow for both jtreg and standalone cases here + // Unlike the 1-level test where we can get the bundle from the caller's + // class loader, for this one we don't want to expose the resource directory + // to the next class. That way we're invoking the LoadItUp2Invoker class + // from this class that does have access to the resources (two levels + // up the call stack), but the Invoker itself won't have access to resource + urls[0] = Paths.get(testDir,"resources").toUri().toURL(); + urls[1] = Paths.get(testClassesDir).toUri().toURL(); + + // Make sure we can find it via the URLClassLoader + URLClassLoader yetAnotherResourceCL = new URLClassLoader(urls, null); + Class loadItUp2InvokerClazz = Class.forName("LoadItUp2Invoker", true, + yetAnotherResourceCL); + ClassLoader actual = loadItUp2InvokerClazz.getClassLoader(); + if (actual != yetAnotherResourceCL) { + throw new Exception("LoadItUp2Invoker was loaded by an unexpected CL: " + + actual); + } + Object loadItUp2Invoker = loadItUp2InvokerClazz.newInstance(); + + Method setupMethod = loadItUp2InvokerClazz.getMethod("setup", + urls.getClass(), String.class); + try { + // For the next class loader we create, we want to leave off + // the resources. That way loadItUp2Invoker will have access to + // them, but the next class won't. + URL[] noResourceUrl = new URL[1]; + noResourceUrl[0] = urls[1]; // from above -- just the test classes + setupMethod.invoke(loadItUp2Invoker, noResourceUrl, rbName); + } catch (InvocationTargetException ex) { + throw ex.getTargetException(); + } + + Method testMethod = loadItUp2InvokerClazz.getMethod("test"); + try { + return (Boolean) testMethod.invoke(loadItUp2Invoker); + } catch (InvocationTargetException ex) { + throw ex.getTargetException(); + } + } +} diff -r 307d170884ea -r 50d2fb6f323f jdk/test/java/util/logging/bundlesearch/resources/CallerSearchableResource_en.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/util/logging/bundlesearch/resources/CallerSearchableResource_en.properties Thu May 16 13:22:41 2013 -0700 @@ -0,0 +1,25 @@ +# +# 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. +# +sample1=translation #4 for sample1 +sample2=translation #4 for sample2 +supports-test=ResourceBundleSearchTest diff -r 307d170884ea -r 50d2fb6f323f jdk/test/sun/net/www/protocol/http/B6299712.java --- a/jdk/test/sun/net/www/protocol/http/B6299712.java Thu May 16 02:43:58 2013 -0700 +++ b/jdk/test/sun/net/www/protocol/http/B6299712.java Thu May 16 13:22:41 2013 -0700 @@ -23,33 +23,33 @@ /* * @test - * @bug 6299712 - * @library ../../httptest/ - * @build HttpCallback TestHttpServer ClosedChannelList HttpTransaction + * @bug 6299712 7150552 * @run main/othervm B6299712 * @summary NullPointerException in sun.net.www.protocol.http.HttpURLConnection.followRedirect */ +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; import java.net.*; import java.io.*; import java.util.*; /* * Test Description: - * - main thread run as a http client - * - another thread runs a http server, which redirect the first call to "/redirect" - * and return '200 OK' for the successive call - * - a global ResponseCache instance is installed, which return DeployCacheResponse - * for url ends with "/redirect", i.e. the url redirected to by our simple http server, - * and null for other url. + * - main thread is run as a http client + * - another thread runs an http server, which redirects calls to "/" to + * "/redirect" and returns '200 OK' for the successive call + * - a global ResponseCache instance is installed, which returns DeployCacheResponse + * for urls that end with "/redirect", i.e. the url redirected to by our simple http server, + * and null for other urls. * - the whole result is that the first call will be served by our simple * http server and is redirected to "/redirect". The successive call will be done * automatically by HttpURLConnection, which will be served by DeployCacheResponse. * The NPE will be thrown on the second round if the bug is there. */ public class B6299712 { - static SimpleHttpTransaction httpTrans; - static TestHttpServer server; + static HttpServer server; public static void main(String[] args) throws Exception { ResponseCache.setDefault(new DeployCacheHandler()); @@ -58,123 +58,119 @@ makeHttpCall(); } - public static void startHttpServer() { + public static void startHttpServer() throws IOException { + server = HttpServer.create(new InetSocketAddress(0), 0); + server.createContext("/", new DefaultHandler()); + server.createContext("/redirect", new RedirectHandler()); + server.start(); + } + + public static void makeHttpCall() throws IOException { try { - httpTrans = new SimpleHttpTransaction(); - server = new TestHttpServer(httpTrans, 1, 10, 0); - } catch (IOException e) { - e.printStackTrace(); + System.out.println("http server listen on: " + + server.getAddress().getPort()); + URL url = new URL("http", + InetAddress.getLocalHost().getHostAddress(), + server.getAddress().getPort(), "/"); + HttpURLConnection uc = (HttpURLConnection)url.openConnection(); + if (uc.getResponseCode() != 200) + throw new RuntimeException("Expected Response Code was 200," + + "received: " + uc.getResponseCode()); + uc.disconnect(); + } finally { + server.stop(0); } } - public static void makeHttpCall() { - try { - System.out.println("http server listen on: " + server.getLocalPort()); - URL url = new URL("http" , InetAddress.getLocalHost().getHostAddress(), - server.getLocalPort(), "/"); - HttpURLConnection uc = (HttpURLConnection)url.openConnection(); - System.out.println(uc.getResponseCode()); - } catch (IOException e) { - e.printStackTrace(); - } finally { - server.terminate(); + static class RedirectHandler implements HttpHandler { + + @Override + public void handle(HttpExchange exchange) throws IOException { + exchange.sendResponseHeaders(200, -1); + exchange.close(); } + } -} + + static class DefaultHandler implements HttpHandler { -class SimpleHttpTransaction implements HttpCallback { - /* - * Our http server which simply redirect first call - */ - public void request(HttpTransaction trans) { - try { - String path = trans.getRequestURI().getPath(); - if (path.equals("/")) { - // the first call, redirect it - String location = "/redirect"; - trans.addResponseHeader("Location", location); - trans.sendResponse(302, "Moved Temporarily"); - } else { - // the second call - trans.sendResponse(200, "OK"); - } - } catch (Exception e) { - e.printStackTrace(); + @Override + public void handle(HttpExchange exchange) throws IOException { + exchange.getResponseHeaders().add("Location", "/redirect"); + exchange.sendResponseHeaders(302, -1); + exchange.close(); } + } -} + + static class DeployCacheHandler extends java.net.ResponseCache { -class DeployCacheHandler extends java.net.ResponseCache { - private boolean inCacheHandler = false; - private boolean _downloading = false; - - public synchronized CacheResponse get(final URI uri, String rqstMethod, - Map requestHeaders) throws IOException { - System.out.println("get!!!: " + uri); - try { + public synchronized CacheResponse get(final URI uri, String rqstMethod, + Map> requestHeaders) throws IOException + { + System.out.println("get!!!: " + uri); if (!uri.toString().endsWith("redirect")) { return null; } - } catch (Exception e) { - e.printStackTrace(); + System.out.println("Serving request from cache"); + return new DeployCacheResponse(new EmptyInputStream(), + new HashMap>()); } - return new DeployCacheResponse(new EmptyInputStream(), new HashMap()); - } - - public synchronized CacheRequest put(URI uri, URLConnection conn) - throws IOException { - URL url = uri.toURL(); - return new DeployCacheRequest(url, conn); - - } -} + public synchronized CacheRequest put(URI uri, URLConnection conn) + throws IOException + { + URL url = uri.toURL(); + return new DeployCacheRequest(url, conn); -class DeployCacheRequest extends java.net.CacheRequest { - - private URL _url; - private URLConnection _conn; - private boolean _downloading = false; - - DeployCacheRequest(URL url, URLConnection conn) { - _url = url; - _conn = conn; - } - - public void abort() { - + } } - public OutputStream getBody() throws IOException { + static class DeployCacheRequest extends java.net.CacheRequest { - return null; - } -} + private URL _url; + private URLConnection _conn; -class DeployCacheResponse extends java.net.CacheResponse { - protected InputStream is; - protected Map headers; + DeployCacheRequest(URL url, URLConnection conn) { + _url = url; + _conn = conn; + } + + public void abort() { - DeployCacheResponse(InputStream is, Map headers) { - this.is = is; - this.headers = headers; + } + + public OutputStream getBody() throws IOException { + + return null; + } } - public InputStream getBody() throws IOException { - return is; + static class DeployCacheResponse extends java.net.CacheResponse { + protected InputStream is; + protected Map> headers; + + DeployCacheResponse(InputStream is, Map> headers) { + this.is = is; + this.headers = headers; + } + + public InputStream getBody() throws IOException { + return is; + } + + public Map> getHeaders() throws IOException { + List val = new ArrayList<>(); + val.add("HTTP/1.1 200 OK"); + headers.put(null, val); + return headers; + } } - public Map getHeaders() throws IOException { - return headers; + static class EmptyInputStream extends InputStream { + + public int read() throws IOException { + return -1; + } } } - -class EmptyInputStream extends InputStream { - public EmptyInputStream() { - } - - public int read() - throws IOException { - return -1; - } -} diff -r 307d170884ea -r 50d2fb6f323f jdk/test/sun/net/www/protocol/http/B8012625.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/net/www/protocol/http/B8012625.java Thu May 16 13:22:41 2013 -0700 @@ -0,0 +1,100 @@ +/* + * 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 8012625 + * @run main B8012625 + */ + +import java.net.*; +import java.io.*; + +import java.net.*; +import java.io.*; +import java.util.concurrent.*; +import com.sun.net.httpserver.*; + +public class B8012625 implements HttpHandler { + + public static void main (String[] args) throws Exception { + B8012625 test = new B8012625(); + test.run(); + } + + public void run() throws Exception { + String u = "http://127.0.0.1:" + port + "/foo"; + URL url = new URL(u); + HttpURLConnection uc = (HttpURLConnection)url.openConnection(); + uc.setDoOutput(true); + uc.setRequestMethod("POST"); + uc.addRequestProperty("Expect", "100-Continue"); + //uc.setFixedLengthStreamingMode(256); + System.out.println ("Client: getting outputstream"); + long before = System.currentTimeMillis(); + OutputStream os = uc.getOutputStream(); + long after = System.currentTimeMillis(); + System.out.println ("Client: writing to outputstream"); + byte[] buf = new byte[256]; + os.write(buf); + System.out.println ("Client: done writing "); + int r = uc.getResponseCode(); + System.out.println ("Client: received response code " + r); + server.stop(1); + ex.shutdownNow(); + if (after - before >= 5000) { + throw new RuntimeException("Error: 5 second delay seen"); + } + } + + int port; + HttpServer server; + ExecutorService ex; + + public B8012625 () throws Exception { + server = HttpServer.create(new InetSocketAddress(0), 10); + HttpContext ctx = server.createContext("/", this); + ex = Executors.newFixedThreadPool(5); + server.setExecutor(ex); + server.start(); + port = server.getAddress().getPort(); + } + + public void handle(HttpExchange ex) throws IOException { + String s = ex.getRequestMethod(); + if (!s.equals("POST")) { + ex.getResponseHeaders().set("Allow", "POST"); + ex.sendResponseHeaders(500, -1); + ex.close(); + return; + } + System.out.println ("Server: reading request body"); + InputStream is = ex.getRequestBody(); + // read request + byte[] buf = new byte [1024]; + while (is.read(buf) != -1) ; + is.close(); + ex.sendResponseHeaders(200, -1); + ex.close(); + } +} diff -r 307d170884ea -r 50d2fb6f323f jdk/test/tools/pack200/AttributeTests.java --- a/jdk/test/tools/pack200/AttributeTests.java Thu May 16 02:43:58 2013 -0700 +++ b/jdk/test/tools/pack200/AttributeTests.java Thu May 16 13:22:41 2013 -0700 @@ -21,12 +21,9 @@ * questions. */ import java.io.File; -import java.nio.charset.Charset; -import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import static java.nio.file.StandardOpenOption.*; /* * @test * @bug 6746111 8005252 8008262 @@ -58,8 +55,7 @@ scratch.add("}"); File cwd = new File("."); File javaFile = new File(cwd, javaFileName); - Files.write(javaFile.toPath(), scratch, Charset.defaultCharset(), - CREATE, TRUNCATE_EXISTING); + Utils.createFile(javaFile, scratch); Utils.compiler(javaFile.getName(), "-parameters"); diff -r 307d170884ea -r 50d2fb6f323f jdk/test/tools/pack200/BandIntegrity.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/tools/pack200/BandIntegrity.java Thu May 16 13:22:41 2013 -0700 @@ -0,0 +1,61 @@ +/* + * 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 + * @summary test ensures the proper sequencing of bands, dump bands as well. + * @compile -XDignore.symbol.file Utils.java BandIntegrity.java + * @run main BandIntegrity + * @author ksrini + */ +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/* + * This makes use of the optDebugBands to ensure the bands are read in the + * same sequence as it was written. The caveat is that this works only with + * the java unpacker, therefore it will work only with --repack such that + * the java packer and unpacker must be called in the same java instance. + */ +public class BandIntegrity { + public static void main(String... args) throws IOException { + File testFile = new File("test.jar"); + Utils.jar("cvf", testFile.getName(), + "-C", Utils.TEST_CLS_DIR.getAbsolutePath(), + "."); + List scratch = new ArrayList<>(); + // band debugging works only with java unpacker + scratch.add("com.sun.java.util.jar.pack.disable.native=true"); + scratch.add("com.sun.java.util.jar.pack.debug.bands=true"); + // while at it, might as well exercise this functionality + scratch.add("com.sun.java.util.jar.pack.dump.bands=true"); + scratch.add("pack.unknown.attribute=error"); + File configFile = new File("pack.conf"); + Utils.createFile(configFile, scratch); + File outFile = new File("out.jar"); + Utils.repack(testFile, outFile, true, + "-v", "--config-file=" + configFile.getName()); + } +} diff -r 307d170884ea -r 50d2fb6f323f jdk/test/tools/pack200/InstructionTests.java --- a/jdk/test/tools/pack200/InstructionTests.java Thu May 16 02:43:58 2013 -0700 +++ b/jdk/test/tools/pack200/InstructionTests.java Thu May 16 13:22:41 2013 -0700 @@ -21,11 +21,8 @@ * 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.*; /* * @test @@ -59,8 +56,7 @@ scratch.add("}"); File cwd = new File("."); File javaFile = new File(cwd, javaFileName); - Files.write(javaFile.toPath(), scratch, Charset.defaultCharset(), - CREATE, TRUNCATE_EXISTING); + Utils.createFile(javaFile, scratch); // -g to compare LVT and LNT entries Utils.compiler("-g", javaFile.getName()); @@ -69,8 +65,7 @@ scratch.clear(); scratch.add("com.sun.java.util.jar.pack.class.format.error=error"); scratch.add("pack.unknown.attribute=error"); - Files.write(propsFile.toPath(), scratch, Charset.defaultCharset(), - CREATE, TRUNCATE_EXISTING); + Utils.createFile(propsFile, scratch); // jar the file up File testjarFile = new File(cwd, "test" + Utils.JAR_FILE_EXT); Utils.jar("cvf", testjarFile.getName(), "."); diff -r 307d170884ea -r 50d2fb6f323f jdk/test/tools/pack200/Utils.java --- a/jdk/test/tools/pack200/Utils.java Thu May 16 02:43:58 2013 -0700 +++ b/jdk/test/tools/pack200/Utils.java Thu May 16 13:22:41 2013 -0700 @@ -32,6 +32,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintStream; +import java.nio.charset.Charset; import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; @@ -45,6 +46,7 @@ import java.util.zip.ZipFile; import static java.nio.file.StandardCopyOption.*; +import static java.nio.file.StandardOpenOption.*; /** * @@ -70,6 +72,7 @@ static final String JAR_FILE_EXT = ".jar"; static final File TEST_SRC_DIR = new File(System.getProperty("test.src")); + static final File TEST_CLS_DIR = new File(System.getProperty("test.classes")); static final String VERIFIER_DIR_NAME = "pack200-verifier"; static final File VerifierJar = new File(VERIFIER_DIR_NAME + JAR_FILE_EXT); @@ -86,6 +89,10 @@ return; } File srcDir = new File(TEST_SRC_DIR, VERIFIER_DIR_NAME); + if (!srcDir.exists()) { + // if not available try one level above + srcDir = new File(TEST_SRC_DIR.getParentFile(), VERIFIER_DIR_NAME); + } List javaFileList = findFiles(srcDir, createFilter(JAVA_FILE_EXT)); File tmpFile = File.createTempFile("javac", ".tmp"); File classesDir = new File("xclasses"); @@ -205,6 +212,10 @@ : name; } + static void createFile(File outFile, List content) throws IOException { + Files.write(outFile.getAbsoluteFile().toPath(), content, + Charset.defaultCharset(), CREATE_NEW, TRUNCATE_EXISTING); + } /* * Suppose a path is provided which consists of a full path diff -r 307d170884ea -r 50d2fb6f323f jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java --- a/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java Thu May 16 02:43:58 2013 -0700 +++ b/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java Thu May 16 13:22:41 2013 -0700 @@ -69,6 +69,9 @@ import com.sun.tools.classfile.StackMapTable_attribute.*; import com.sun.tools.classfile.StackMap_attribute; import com.sun.tools.classfile.Synthetic_attribute; +import com.sun.tools.classfile.TypeAnnotation; +import com.sun.tools.classfile.TypeAnnotation.Position; +import static com.sun.tools.classfile.TypeAnnotation.TargetType.THROWS; import java.util.*; import java.io.*; import java.util.jar.JarEntry; @@ -851,6 +854,7 @@ } } + class AttributeVisitor implements Attribute.Visitor { final ClassFile cf; final ClassReader x; @@ -1088,23 +1092,26 @@ } return null; // already added to parent } + private void parseAnnotation(Annotation anno, Element p) { + Element ea = new Element("Annotation"); + ea.setAttr("name", "" + x.getCpString(anno.type_index)); + for (Annotation.element_value_pair evp : anno.element_value_pairs) { + Element evpe = new Element("Element"); + evpe.setAttr("tag", "" + evp.value.tag); + evpe.setAttr("value", x.getCpString(evp.element_name_index)); + Element child = aev.visit(evp.value, evpe); + if (child != null) { + evpe.add(child); + } + ea.add(evpe); + } + ea.trimToSize(); + p.add(ea); + } private void parseAnnotations(Annotation[] ra, Element p) { - for (Annotation anno : ra) { - Element ea = new Element("Member"); - ea.setAttr("name", "" + x.getCpString(anno.type_index)); - for (Annotation.element_value_pair evp : anno.element_value_pairs) { - Element evpe = new Element("Element"); - evpe.setAttr("tag", "" + evp.value.tag); - evpe.setAttr("value", x.getCpString(evp.element_name_index)); - Element child = aev.visit(evp.value, evpe); - if (child != null) { - evpe.add(child); - } - ea.add(evpe); - } - ea.trimToSize(); - p.add(ea); + for (Annotation anno : ra) { + parseAnnotation(anno, p); } } @@ -1150,6 +1157,145 @@ return null; } + private void parsePosition(Position ap, Element p) { + Element te = new Element(); + switch (ap.type) { + case CLASS_TYPE_PARAMETER: // 0x00 + te.setName("CLASS_TYPE_PARAMETER"); + te.setAttr("idx", "" + ap.parameter_index); + break; + case METHOD_TYPE_PARAMETER: // 0x01 + te.setName("METHOD_TYPE_PARAMETER"); + te.setAttr("idx", "" + ap.parameter_index); + break; + case CLASS_EXTENDS: // 0x10 + te.setName("CLASS_EXTENDS"); + te.setAttr("idx", "" + ap.type_index); + break; + case CLASS_TYPE_PARAMETER_BOUND: // 0x11 + te.setName("CLASS_TYPE_PARAMETER_BOUND"); + te.setAttr("idx1", "" + ap.parameter_index); + te.setAttr("idx2", "" + ap.bound_index); + break; + case METHOD_TYPE_PARAMETER_BOUND: // 0x12 + te.setName("METHOD_TYPE_PARAMETER_BOUND"); + te.setAttr("idx1", "" + ap.parameter_index); + te.setAttr("idx2", "" + ap.bound_index); + break; + case FIELD: // 0x13 + te.setName("FIELD"); + break; + case METHOD_RETURN: // 0x14 + te.setName("METHOD_RETURN"); + break; + case METHOD_RECEIVER: // 0x15 + te.setName("METHOD_RECEIVER"); + break; + case METHOD_FORMAL_PARAMETER: // 0x16 + te.setName("METHOD_FORMAL_PARAMETER"); + te.setAttr("idx", "" + ap.parameter_index); + break; + case THROWS: // 0x17 + te.setName("THROWS"); + te.setAttr("idx", "" + ap.type_index); + break; + case LOCAL_VARIABLE: // 0x40 + te.setName("LOCAL_VARIABLE"); + for (int i = 0; i < ap.lvarIndex.length; i++) { + te.setAttr("lvar_idx_" + i, "" + ap.lvarIndex[i]); + te.setAttr("lvar_len_" + i, "" + ap.lvarLength[i]); + te.setAttr("lvar_off_" + i, "" + ap.lvarOffset[i]); + } + break; + case RESOURCE_VARIABLE: // 0x41 + te.setName("RESOURCE_VARIABLE"); + for (int i = 0; i < ap.lvarIndex.length ; i++) { + te.setAttr("lvar_idx_" + i, "" + ap.lvarIndex[i]); + te.setAttr("lvar_len_" + i, "" + ap.lvarLength[i]); + te.setAttr("lvar_off_" + i, "" + ap.lvarOffset[i]); + } + break; + case EXCEPTION_PARAMETER: // 0x42 + te.setName("EXCEPTION_PARAMETER"); + te.setAttr("idx", "" + ap.exception_index); + break; + case INSTANCEOF: // 0x43 + te.setName("INSTANCE_OF"); + te.setAttr("off", "" + ap.offset); + break; + case NEW: // 0x44 + te.setName("NEW"); + te.setAttr("off", "" + ap.offset); + break; + case CONSTRUCTOR_REFERENCE: // 0x45 + te.setName("CONSTRUCTOR_REFERENCE_RECEIVER"); + te.setAttr("off", "" + ap.offset); + break; + case METHOD_REFERENCE: // 0x46 + te.setName("METHOD_REFERENCE_RECEIVER"); + te.setAttr("off", "" + ap.offset); + break; + case CAST: // 0x47 + te.setName("CAST"); + te.setAttr("off", "" + ap.offset); + te.setAttr("idx", "" + ap.type_index); + break; + case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: // 0x48 + te.setName("CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT"); + te.setAttr("off", "" + ap.offset); + te.setAttr("idx", "" + ap.type_index); + break; + case METHOD_INVOCATION_TYPE_ARGUMENT: // 0x49 + te.setName("METHOD_INVOCATION_TYPE_ARGUMENT"); + te.setAttr("off", "" + ap.offset); + te.setAttr("idx", "" + ap.type_index); + break; + case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: // 0x4A + te.setName("CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT"); + te.setAttr("off", "" + ap.offset); + te.setAttr("idx", "" + ap.type_index); + break; + case METHOD_REFERENCE_TYPE_ARGUMENT: // 0x4B + te.setName("METHOD_REFERENCE_TYPE_ARGUMENT"); + te.setAttr("off", "" + ap.offset); + te.setAttr("idx", "" + ap.type_index); + break; + default: + throw new RuntimeException("not implemented"); + } + te.trimToSize(); + p.add(te); + } + private void parseTypeAnnotations(TypeAnnotation pa, Element p) { + Element pta = new Element("RuntimeVisibleTypeAnnotation"); + p.add(pta); + Position pos = pa.position; + parsePosition(pos, pta); + parseAnnotation(pa.annotation, pta); + } + + @Override + public Element visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute rvta, Element p) { + Element e = new Element(x.getCpString(rvta.attribute_name_index)); + for (TypeAnnotation pa : rvta.annotations) { + parseTypeAnnotations(pa, e); + } + e.sort(); + p.add(e); + return null; + } + + @Override + public Element visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute rita, Element p) { + Element e = new Element(x.getCpString(rita.attribute_name_index)); + for (TypeAnnotation pa : rita.annotations) { + parseTypeAnnotations(pa, e); + } + e.sort(); + p.add(e); + return null; + } + @Override public Element visitSignature(Signature_attribute s, Element p) { String aname = x.getCpString(s.attribute_name_index); @@ -1216,21 +1362,6 @@ 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 { diff -r 307d170884ea -r 50d2fb6f323f jdk/test/tools/pack200/typeannos/Lambda.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/tools/pack200/typeannos/Lambda.java Thu May 16 13:22:41 2013 -0700 @@ -0,0 +1,59 @@ +/* + * 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. + */ + +/* + * @Xtest + * @bug 8008077 + * @summary new type annotation location: lambda expressions + * @compile Lambda.java + * @author Werner Dietl + */ + +import java.lang.annotation.*; + +public class Lambda { + + interface LambdaInt { + void generic(S p1, T p2); + } + + static class LambdaImpl implements LambdaInt { + LambdaImpl(S p1, T p2) {} + public void generic(S p1, T p2) {} + } + + LambdaInt getMethodRefTA(LambdaImpl r) { + return r::<@TA Object, @TB Object>generic; + } + + LambdaInt getConstructorRefTA() { + return LambdaImpl::<@TA Object, @TB Object>new; + } + +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface TA { } + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface TB { } diff -r 307d170884ea -r 50d2fb6f323f jdk/test/tools/pack200/typeannos/Readme.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/tools/pack200/typeannos/Readme.txt Thu May 16 13:22:41 2013 -0700 @@ -0,0 +1,11 @@ +This directory contains tests which exercises all possible TypeAnnotations +structure. These tests are borrowed from +langtools/test/tools.javac/annotations/typeAnnotations. + +The reason it is copied over is that we need to test pack200 and these +annotation may not be present in any of the JDK/JRE jars, yet we need to test +all these cases. + + +Therefore it would be a good practice to sync these tests with the original +if there are any changes. diff -r 307d170884ea -r 50d2fb6f323f jdk/test/tools/pack200/typeannos/TargetTypes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/tools/pack200/typeannos/TargetTypes.java Thu May 16 13:22:41 2013 -0700 @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2009, 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.lang.annotation.*; +import static java.lang.annotation.ElementType.*; + +import java.util.*; +import java.io.*; + +/* + * @Xtest + * @summary compiler accepts all values + * @author Mahmood Ali + * @author Yuri Gaevsky + * @compile TargetTypes.java + */ + +@Target({TYPE_USE, TYPE_PARAMETER, TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@interface A {} + +/** wildcard bound */ +class T0x1C { + void m0x1C(List lst) {} +} + +/** wildcard bound generic/array */ +class T0x1D { + void m0x1D(List> lst) {} +} + +/** typecast */ +class T0x00 { + void m0x00(Long l1) { + Object l2 = (@A Long) l1; + } +} + +/** typecast generic/array */ +class T0x01 { + void m0x01(List list) { + List l = (List<@A T>) list; + } +} + +/** instanceof */ +class T0x02 { + boolean m0x02(String s) { + return (s instanceof @A String); + } +} + +/** object creation (new) */ +class T0x04 { + void m0x04() { + new @A ArrayList(); + } +} + +/** local variable */ +class T0x08 { + void m0x08() { + @A String s = null; + } +} + +/** method parameter generic/array */ +class T0x0D { + void m0x0D(HashMap<@A Object, List<@A List<@A Class>>> s1) {} +} + +/** method receiver */ +class T0x06 { + void m0x06(@A T0x06 this) {} +} + +/** method return type generic/array */ +class T0x0B { + Class<@A Object> m0x0B() { return null; } +} + +/** field generic/array */ +class T0x0F { + HashMap<@A Object, @A Object> c1; +} + +/** method type parameter */ +class T0x20 { + <@A T, @A U> void m0x20() {} +} + +/** class type parameter */ +class T0x22<@A T, @A U> { +} + +/** class type parameter bound */ +class T0x10 { +} + +/** method type parameter bound */ +class T0x12 { + void m0x12() {} +} + +/** class type parameter bound generic/array */ +class T0x11> { +} + + +/** method type parameter bound generic/array */ +class T0x13 { + static > T m0x13() { + return null; + } +} + +/** class extends/implements generic/array */ +class T0x15 extends ArrayList<@A T> { +} + +/** type test (instanceof) generic/array */ +class T0x03 { + void m0x03(T typeObj, Object obj) { + boolean ok = obj instanceof String @A []; + } +} + +/** object creation (new) generic/array */ +class T0x05 { + void m0x05() { + new ArrayList<@A T>(); + } +} + +/** local variable generic/array */ +class T0x09 { + void g() { + List<@A String> l = null; + } + + void a() { + String @A [] as = null; + } +} + +/** type argument in constructor call generic/array */ +class T0x19 { + T0x19() {} + + void g() { + new > T0x19(); + } +} + +/** type argument in method call generic/array */ +class T0x1B { + void m0x1B() { + Collections.emptyList(); + } +} + +/** type argument in constructor call */ +class T0x18 { + T0x18() {} + + void m() { + new <@A Integer> T0x18(); + } +} + +/** type argument in method call */ +class T0x1A { + public static T m() { return null; } + static void m0x1A() { + T0x1A.<@A Integer, @A Short>m(); + } +} + +/** class extends/implements */ +class T0x14 extends @A Object implements @A Serializable, @A Cloneable { +} + +/** exception type in throws */ +class T0x16 { + void m0x16() throws @A Exception {} +} + +/** resource variables **/ +class ResourceVariables { + void m() throws Exception { + try (@A InputStream is = new @A FileInputStream("x")){} + } +} + +/** exception parameters **/ +class ExceptionParameters { + void multipleExceptions() { + try { + new Object(); + } catch (@A Exception e) {} + try { + new Object(); + } catch (@A Exception e) {} + try { + new Object(); + } catch (@A Exception e) {} + } +} diff -r 307d170884ea -r 50d2fb6f323f jdk/test/tools/pack200/typeannos/TestTypeAnnotations.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/tools/pack200/typeannos/TestTypeAnnotations.java Thu May 16 13:22:41 2013 -0700 @@ -0,0 +1,45 @@ +/* + * 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 8001163 + * @summary tests simple TypeAnnotations in classfiles + * @compile -XDignore.symbol.file ../Utils.java + * TestTypeAnnotations.java TargetTypes.java + * TypeUseTarget.java Lambda.java + * @run main TestTypeAnnotations + * @author ksrini + */ +import java.io.File; +import java.io.IOException; + +public class TestTypeAnnotations { + public static void main(String... args) throws IOException { + File testFile = new File("ta.jar"); + Utils.jar("cvf", testFile.getName(), + "-C", Utils.TEST_CLS_DIR.getAbsolutePath(), + "."); + Utils.testWithRepack(testFile, "--unknown-attribute=error"); + } +} diff -r 307d170884ea -r 50d2fb6f323f jdk/test/tools/pack200/typeannos/TypeUseTarget.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/tools/pack200/typeannos/TypeUseTarget.java Thu May 16 13:22:41 2013 -0700 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2008, 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. + */ + +/* + * @Xtest + * @bug 6843077 8006775 + * @summary check that type annotations may appear on all type declarations + * @author Mahmood Ali + * @compile TypeUseTarget.java + */ + +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +@B +class TypeUseTarget { + @B String @B [] field; + + @B String test(@B TypeUseTarget this, @B String param, @B String @B ... vararg) { + @B Object o = new @B String @B [3]; + TypeUseTarget<@B String> target; + return (@B String) null; + } + + @B String genericMethod(K k) { return null; } + @Decl @B String genericMethod1(K k) { return null; } + @B @Decl String genericMethod2(K k) { return null; } + @Decl @B String genericMethod3(K k) { return null; } + @Decl String genericMethod4(K k) { return null; } + @B @Decl String genericMethod5(K k) { return null; } +} + +@B +interface MyInterface { } + +@B +@interface MyAnnotation { } + +@Target(ElementType.TYPE_USE) +@interface B { } + +@interface Decl { }