1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/test/tools/javac/enum/EnumImplicitPrivateConstructor.java Wed Apr 27 01:34:52 2016 +0800 1.3 @@ -0,0 +1,211 @@ 1.4 +/* 1.5 + * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + */ 1.26 + 1.27 +/* 1.28 + * @test 1.29 + * @bug 5009601 5010455 5005748 1.30 + * @summary enum constructors can be declared private 1.31 + * @author Joseph D. Darcy 1.32 + */ 1.33 + 1.34 +import java.util.*; 1.35 +import java.lang.reflect.*; 1.36 +import java.lang.annotation.*; 1.37 + 1.38 +/* 1.39 + * Arguably, only the final and abstract should be held in 1.40 + * ExpectedModifiers; whether or not an enum should be static could be 1.41 + * inferred from getDeclaringClass and working versions of 1.42 + * getEnclosingMethod and getEnclosingConstructor. I.e. if 1.43 + * getDeclaringClass, getEnclosingMethod, and getEnclosingConstructor 1.44 + * were all null, the enum is a top-level class and should not be 1.45 + * static; otherwise, it should be static. 1.46 + */ 1.47 + 1.48 +@ExpectedModifiers(Modifier.FINAL) 1.49 +public enum EnumImplicitPrivateConstructor { 1.50 + RED(255, 0, 0), 1.51 + GREEN(0, 255, 0), 1.52 + BLUE(0, 0, 255); 1.53 + 1.54 + private int r, g, b; 1.55 + EnumImplicitPrivateConstructor(int r, int g, int b) { 1.56 + this.r = r; 1.57 + this.g = g; 1.58 + this.b = b; 1.59 + } 1.60 + 1.61 + /* 1.62 + * Using reflection, Verify that 1.63 + * 1. all non-synthetic constructors of enum classes are marked as private. 1.64 + * 2. top-level enum classes are marked as static 1.65 + * 3. enum's are marked final and abstract as appropriate 1.66 + * 4. enum constructors *cannot* be invoked reflectively 1.67 + */ 1.68 + public static void main(String argv[]) throws Exception { 1.69 + boolean passed = true; 1.70 + 1.71 + Collection<Class> classes = new LinkedHashSet<Class>(); 1.72 + 1.73 + classes.add(Class.forName("EnumImplicitPrivateConstructor")); 1.74 + classes.add(Class.forName("EnumImplicitPrivateConstructor$AnotherEnum")); 1.75 + classes.add(Class.forName("EnumImplicitPrivateConstructor$YetAnotherEnum")); 1.76 + classes.add(Class.forName("EnumImplicitPrivateConstructor$OneMoreEnum")); 1.77 + 1.78 + // Add classes of specialized enum constants 1.79 + for(Enum e: YetAnotherEnum.values()) 1.80 + classes.add(e.getClass()); 1.81 + 1.82 + for(Class clazz: classes) { 1.83 + System.out.println("Testing class " + clazz); 1.84 + 1.85 + int classModifiers = clazz.getModifiers(); 1.86 + 1.87 + // Why is this cast needed? 1.88 + ExpectedModifiers em = (ExpectedModifiers)clazz.getAnnotation(ExpectedModifiers.class); 1.89 + if (em != null) { 1.90 + System.out.println("\tTesting expected modifiers"); 1.91 + int expected = em.value(); 1.92 + 1.93 + if (expected != (classModifiers & (Modifier.ABSTRACT|Modifier.FINAL|Modifier.STATIC))) { 1.94 + passed = false; 1.95 + System.out.println("\tFAILED: Expected 0x" + Integer.toHexString(expected) + 1.96 + " got 0x" +Integer.toHexString(classModifiers)); 1.97 + } 1.98 + } 1.99 + 1.100 + for(Constructor ctor: clazz.getDeclaredConstructors() ) { 1.101 + System.out.println("\tTesting constructor " + ctor); 1.102 + 1.103 + // We don't need no stinkin' access rules 1.104 + try { 1.105 + ctor.setAccessible(true); 1.106 + } catch (java.security.AccessControlException ex) { 1.107 + } 1.108 + 1.109 + int modifiers = ctor.getModifiers(); 1.110 + 1.111 + /* 1.112 + * If clazz is for a specialized enum constant, the 1.113 + * class will have the ENUM bit set but clazz.isEnum() 1.114 + * will be false. A constructor in such a class must 1.115 + * be non-private to allow the parent class to call 1.116 + * the constructor. Therefore, only impose the 1.117 + * private constructor check for genuine isEnum 1.118 + * classes. 1.119 + */ 1.120 + if (clazz.isEnum()) { 1.121 + if ((modifiers & Modifier.PRIVATE) == 0 && 1.122 + ! ctor.isSynthetic() ) { 1.123 + passed = false; 1.124 + System.out.println("\tFAILED: Constructor not marked private: modifiers 0x" + 1.125 + Integer.toHexString(modifiers)); 1.126 + } 1.127 + } 1.128 + 1.129 + try { 1.130 + // Should get exception trying to invoke 1.131 + Object o = null; 1.132 + try { 1.133 + o = ctor.newInstance("abc", 123); 1.134 + } catch (IllegalAccessException ex) { 1.135 + } 1.136 + 1.137 + /* 1.138 + * A better test would query the number (and type) 1.139 + * of parameters and create an appropriate 1.140 + * argument list since IllegalArgumentException can be 1.141 + * thrown for just using the wrong number of arguments. 1.142 + */ 1.143 + 1.144 + if (o != null) { 1.145 + passed = false; 1.146 + System.err.println("Error: Created new enum object!"); 1.147 + System.err.println(o.getClass()); 1.148 + System.err.println(o.toString()); 1.149 + } 1.150 + } catch (IllegalArgumentException iae) {} 1.151 + 1.152 + } 1.153 + } 1.154 + 1.155 + if (!passed) 1.156 + throw new RuntimeException("Error during testing."); 1.157 + } 1.158 + 1.159 + 1.160 + /* 1.161 + * Should be final and not abstract. 1.162 + */ 1.163 + @ExpectedModifiers(Modifier.FINAL|Modifier.STATIC) 1.164 + enum AnotherEnum { 1.165 + YELLOW, 1.166 + CYAN, 1.167 + MAGENTA; 1.168 + } 1.169 + 1.170 + /* 1.171 + * Should be neither final nor abstract. 1.172 + */ 1.173 + @ExpectedModifiers(Modifier.STATIC) 1.174 + enum YetAnotherEnum { 1.175 + GREEN { 1.176 + int value(){ return 1;} 1.177 + }, 1.178 + 1.179 + ORANGE { 1.180 + int value(){ return 2;} 1.181 + }, 1.182 + 1.183 + VIOLET { 1.184 + int value(){ return 3;} 1.185 + }; 1.186 + 1.187 + int value(){ return 0;} 1.188 + } 1.189 + 1.190 + /* 1.191 + * Should be abstract and not final. 1.192 + */ 1.193 + @ExpectedModifiers(Modifier.ABSTRACT|Modifier.STATIC) 1.194 + enum OneMoreEnum { 1.195 + SANGUINE { 1.196 + int value(){ return 1;} 1.197 + }, 1.198 + 1.199 + VERDANT { 1.200 + int value(){ return 2;} 1.201 + }, 1.202 + 1.203 + CERULEAN { 1.204 + int value(){ return 3;} 1.205 + }; 1.206 + 1.207 + abstract int value(); 1.208 + } 1.209 +} 1.210 + 1.211 +@Retention(RetentionPolicy.RUNTIME) 1.212 +@interface ExpectedModifiers { 1.213 + int value(); 1.214 +}