1 /* 2 * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import java.io.*; 25 import java.lang.ref.Reference; 26 import java.lang.ref.ReferenceQueue; 27 import java.lang.ref.WeakReference; 28 import java.util.*; 29 import java.util.logging.*; 30 31 /* 32 * @test 33 * @bug 8026027 6543126 34 * @summary Test Level.parse to look up custom levels by name and its 35 * localized name 36 * 37 * @run main/othervm CustomLevel 38 */ 39 40 public class CustomLevel extends Level { 41 public CustomLevel(String name, int value, String resourceBundleName) { 42 super(name, value, resourceBundleName); 43 } 44 45 private static final List<Level> levels = new ArrayList<>(); 46 private static final String RB_NAME = "myresource"; 47 48 private static class CustomLevelReference extends WeakReference<Level> { 49 final String name; 50 final int value; 51 final String resourceBundleName; 52 public CustomLevelReference(Level level, ReferenceQueue<Level> queue) { 53 super(level, queue); 54 name = level.getName(); 55 value = level.intValue(); 56 resourceBundleName = level.getResourceBundleName(); 57 } 58 59 @Override 60 public String toString() { 61 return "CustomLevelReference(\"" + name + "\", " + value + ", \"" 62 + resourceBundleName + "\")"; 63 } 64 } 65 66 public static void main(String[] args) throws Exception { 67 setupCustomLevels(); 68 69 // Level.parse will return the custom Level instance 70 ResourceBundle rb = ResourceBundle.getBundle(RB_NAME); 71 for (Level level : levels) { 72 String name = level.getName(); 73 Level l = Level.parse(name); 74 if (!name.equals("WARNING") && !name.equals("INFO")) { 75 // custom level whose name doesn't conflict with any standard one 76 checkCustomLevel(l, level); 77 } else if (l != Level.WARNING && l != Level.INFO 78 || !name.equals(l.getName())) { 79 throw new RuntimeException("Unexpected level " + formatLevel(l)); 80 } 81 System.out.println("Level.parse found expected level: " 82 + formatLevel(l)); 83 String localizedName = rb.getString(level.getName()); 84 l = Level.parse(localizedName); 85 if (l != level) { 86 throw new RuntimeException("Unexpected level " + l + " " + l.getClass()); 87 } 88 } 89 90 // Now verify that custom level instances are correctly 91 // garbage collected when no longer referenced 92 ReferenceQueue<Level> queue = new ReferenceQueue<>(); 93 while (!levels.isEmpty()) { 94 Level l = levels.stream().findAny().get(); 95 CustomLevelReference ref = new CustomLevelReference(l, queue); 96 97 // remove strong references to l 98 levels.remove(l); 99 l = null; 100 101 // Run gc and wait for garbage collection 102 Reference<? extends Level> ref2; 103 do { 104 System.gc(); 105 Thread.sleep(100); 106 } while ((ref2 = queue.poll()) == null); 107 108 // Check garbage collected reference 109 if (ref2 != ref) { 110 throw new RuntimeException("Unexpected reference: " + ref2); 111 } 112 System.out.println(ref2 + " garbage collected"); 113 final String name = ref.name; 114 try { 115 l = Level.parse(name); 116 if (!name.equals("WARNING") && !name.equals("INFO") 117 || !name.equals(l.getName())) { 118 throw new RuntimeException("Unexpected level " 119 + formatLevel(l)); 120 } else { 121 if (l == Level.WARNING || l == Level.INFO) { 122 System.out.println("Level.parse found expected level: " 123 + formatLevel(l)); 124 } else { 125 throw new RuntimeException("Unexpected level " 126 + formatLevel(l)); 127 } 128 } 129 } catch (IllegalArgumentException iae) { 130 if (!name.equals("WARNING") && !name.equals("INFO")) { 131 System.out.println("Level.parse fired expected exception: " 132 + iae); 133 } else { 134 throw iae; 135 } 136 } 137 } 138 } 139 140 private static void setupCustomLevels() throws IOException { 141 levels.add(new CustomLevel("EMERGENCY", 1090, RB_NAME)); 142 levels.add(new CustomLevel("ALERT", 1060, RB_NAME)); 143 levels.add(new CustomLevel("CRITICAL", 1030, RB_NAME)); 144 levels.add(new CustomLevel("WARNING", 1010, RB_NAME)); 145 levels.add(new CustomLevel("INFO", 1000, RB_NAME)); 146 } 147 static void checkCustomLevel(Level level, Level expected) { 148 // Level value must be the same 149 if (!level.equals(expected)) { 150 throw new RuntimeException(formatLevel(level) + " != " + formatLevel(expected)); 151 } 152 153 if (!level.getName().equals(expected.getName())) { 154 throw new RuntimeException(formatLevel(level) + " != " + formatLevel(expected)); 155 } 156 157 // Level.parse is expected to return the custom Level 158 if (level != expected) { 159 throw new RuntimeException(formatLevel(level) + " != " + formatLevel(expected)); 160 } 161 162 ResourceBundle rb = ResourceBundle.getBundle(RB_NAME); 163 String name = rb.getString(level.getName()); 164 if (!level.getLocalizedName().equals(name)) { 165 // must have the same localized name 166 throw new RuntimeException(level.getLocalizedName() + " != " + name); 167 } 168 } 169 170 static String formatLevel(Level l) { 171 return l + ":" + l.intValue() + ":" + l.getClass().getName(); 172 } 173 }