Thu, 10 Oct 2013 14:58:04 +0200
8001931: The new build system whitespace cleanup
Reviewed-by: tbell, simonis, erikj
1 /*
2 * Copyright (c) 2004, 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 */
24 /*
25 * @test
26 * @bug 5009601 5010455 5005748
27 * @summary enum constructors can be declared private
28 * @author Joseph D. Darcy
29 */
31 import java.util.*;
32 import java.lang.reflect.*;
33 import java.lang.annotation.*;
35 /*
36 * Arguably, only the final and abstract should be held in
37 * ExpectedModifiers; whether or not an enum should be static could be
38 * inferred from getDeclaringClass and working versions of
39 * getEnclosingMethod and getEnclosingConstructor. I.e. if
40 * getDeclaringClass, getEnclosingMethod, and getEnclosingConstructor
41 * were all null, the enum is a top-level class and should not be
42 * static; otherwise, it should be static.
43 */
45 @ExpectedModifiers(Modifier.FINAL)
46 public enum EnumImplicitPrivateConstructor {
47 RED(255, 0, 0),
48 GREEN(0, 255, 0),
49 BLUE(0, 0, 255);
51 private int r, g, b;
52 EnumImplicitPrivateConstructor(int r, int g, int b) {
53 this.r = r;
54 this.g = g;
55 this.b = b;
56 }
58 /*
59 * Using reflection, Verify that
60 * 1. all non-synthetic constructors of enum classes are marked as private.
61 * 2. top-level enum classes are marked as static
62 * 3. enum's are marked final and abstract as appropriate
63 * 4. enum constructors *cannot* be invoked reflectively
64 */
65 public static void main(String argv[]) throws Exception {
66 boolean passed = true;
68 Collection<Class> classes = new LinkedHashSet<Class>();
70 classes.add(Class.forName("EnumImplicitPrivateConstructor"));
71 classes.add(Class.forName("EnumImplicitPrivateConstructor$AnotherEnum"));
72 classes.add(Class.forName("EnumImplicitPrivateConstructor$YetAnotherEnum"));
73 classes.add(Class.forName("EnumImplicitPrivateConstructor$OneMoreEnum"));
75 // Add classes of specialized enum constants
76 for(Enum e: YetAnotherEnum.values())
77 classes.add(e.getClass());
79 for(Class clazz: classes) {
80 System.out.println("Testing class " + clazz);
82 int classModifiers = clazz.getModifiers();
84 // Why is this cast needed?
85 ExpectedModifiers em = (ExpectedModifiers)clazz.getAnnotation(ExpectedModifiers.class);
86 if (em != null) {
87 System.out.println("\tTesting expected modifiers");
88 int expected = em.value();
90 if (expected != (classModifiers & (Modifier.ABSTRACT|Modifier.FINAL|Modifier.STATIC))) {
91 passed = false;
92 System.out.println("\tFAILED: Expected 0x" + Integer.toHexString(expected) +
93 " got 0x" +Integer.toHexString(classModifiers));
94 }
95 }
97 for(Constructor ctor: clazz.getDeclaredConstructors() ) {
98 System.out.println("\tTesting constructor " + ctor);
100 // We don't need no stinkin' access rules
101 try {
102 ctor.setAccessible(true);
103 } catch (java.security.AccessControlException ex) {
104 }
106 int modifiers = ctor.getModifiers();
108 /*
109 * If clazz is for a specialized enum constant, the
110 * class will have the ENUM bit set but clazz.isEnum()
111 * will be false. A constructor in such a class must
112 * be non-private to allow the parent class to call
113 * the constructor. Therefore, only impose the
114 * private constructor check for genuine isEnum
115 * classes.
116 */
117 if (clazz.isEnum()) {
118 if ((modifiers & Modifier.PRIVATE) == 0 &&
119 ! ctor.isSynthetic() ) {
120 passed = false;
121 System.out.println("\tFAILED: Constructor not marked private: modifiers 0x" +
122 Integer.toHexString(modifiers));
123 }
124 }
126 try {
127 // Should get exception trying to invoke
128 Object o = null;
129 try {
130 o = ctor.newInstance("abc", 123);
131 } catch (IllegalAccessException ex) {
132 }
134 /*
135 * A better test would query the number (and type)
136 * of parameters and create an appropriate
137 * argument list since IllegalArgumentException can be
138 * thrown for just using the wrong number of arguments.
139 */
141 if (o != null) {
142 passed = false;
143 System.err.println("Error: Created new enum object!");
144 System.err.println(o.getClass());
145 System.err.println(o.toString());
146 }
147 } catch (IllegalArgumentException iae) {}
149 }
150 }
152 if (!passed)
153 throw new RuntimeException("Error during testing.");
154 }
157 /*
158 * Should be final and not abstract.
159 */
160 @ExpectedModifiers(Modifier.FINAL|Modifier.STATIC)
161 enum AnotherEnum {
162 YELLOW,
163 CYAN,
164 MAGENTA;
165 }
167 /*
168 * Should be neither final nor abstract.
169 */
170 @ExpectedModifiers(Modifier.STATIC)
171 enum YetAnotherEnum {
172 GREEN {
173 int value(){ return 1;}
174 },
176 ORANGE {
177 int value(){ return 2;}
178 },
180 VIOLET {
181 int value(){ return 3;}
182 };
184 int value(){ return 0;}
185 }
187 /*
188 * Should be abstract and not final.
189 */
190 @ExpectedModifiers(Modifier.ABSTRACT|Modifier.STATIC)
191 enum OneMoreEnum {
192 SANGUINE {
193 int value(){ return 1;}
194 },
196 VERDANT {
197 int value(){ return 2;}
198 },
200 CERULEAN {
201 int value(){ return 3;}
202 };
204 abstract int value();
205 }
206 }
208 @Retention(RetentionPolicy.RUNTIME)
209 @interface ExpectedModifiers {
210 int value();
211 }