1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/test/tools/javac/tree/NoPrivateTypesExported.java Wed Apr 27 01:34:52 2016 +0800 1.3 @@ -0,0 +1,291 @@ 1.4 +/* 1.5 + * Copyright (c) 2013, 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 8026180 1.30 + * @summary Ensuring javax.lang.model.**, javax.tools.**, javax.annotation.processing.** 1.31 + * and com.sun.source.** don't export inappropriate types. 1.32 + * @library /tools/javac/lib 1.33 + * @build JavacTestingAbstractProcessor NoPrivateTypesExported 1.34 + * @compile -processor NoPrivateTypesExported NoPrivateTypesExported.java 1.35 + */ 1.36 +import java.lang.annotation.Documented; 1.37 +import java.util.Arrays; 1.38 +import java.util.HashSet; 1.39 +import java.util.List; 1.40 +import java.util.Set; 1.41 +import javax.annotation.processing.RoundEnvironment; 1.42 +import javax.lang.model.element.AnnotationMirror; 1.43 +import javax.lang.model.element.AnnotationValue; 1.44 +import javax.lang.model.element.Element; 1.45 +import javax.lang.model.element.ElementKind; 1.46 +import javax.lang.model.element.ExecutableElement; 1.47 +import javax.lang.model.element.PackageElement; 1.48 +import javax.lang.model.element.TypeElement; 1.49 +import javax.lang.model.element.TypeParameterElement; 1.50 +import javax.lang.model.element.VariableElement; 1.51 +import javax.lang.model.type.ArrayType; 1.52 +import javax.lang.model.type.DeclaredType; 1.53 +import javax.lang.model.type.IntersectionType; 1.54 +import javax.lang.model.type.TypeMirror; 1.55 +import javax.lang.model.type.TypeVariable; 1.56 +import javax.lang.model.type.WildcardType; 1.57 +import javax.lang.model.util.ElementScanner8; 1.58 +import javax.lang.model.util.SimpleAnnotationValueVisitor8; 1.59 +import javax.tools.Diagnostic.Kind; 1.60 + 1.61 +public class NoPrivateTypesExported extends JavacTestingAbstractProcessor { 1.62 + 1.63 + private static final String[] javaxLangModelPackages = new String[] { 1.64 + "javax.lang.model", 1.65 + "javax.lang.model.element", 1.66 + "javax.lang.model.type", 1.67 + "javax.lang.model.util", 1.68 + }; 1.69 + 1.70 + private static final Set<String> javaxLangModelAcceptable; 1.71 + 1.72 + private static final String[] javaxToolsProcessingPackages = new String[] { 1.73 + "javax.annotation.processing", 1.74 + "javax.tools", 1.75 + }; 1.76 + 1.77 + private static final Set<String> javaxToolsProcessingAcceptable; 1.78 + 1.79 + private static final String[] comSunSourcePackages = new String[] { 1.80 + "com.sun.source.doctree", 1.81 + "com.sun.source.tree", 1.82 + "com.sun.source.util" 1.83 + }; 1.84 + 1.85 + private static final Set<String> comSunSourceAcceptable; 1.86 + 1.87 + static { 1.88 + javaxLangModelAcceptable = new HashSet<>(Arrays.asList( 1.89 + "java.io.", 1.90 + "java.lang.", 1.91 + "java.net.", 1.92 + "java.nio.", 1.93 + "java.util.", 1.94 + "javax.lang.model.", 1.95 + "javax.annotation.processing.SupportedSourceVersion", 1.96 + "jdk.Exported" 1.97 + )); 1.98 + Set<String> javaxToolsProcessingAcceptableTemp = new HashSet<>(); 1.99 + javaxToolsProcessingAcceptableTemp.addAll(javaxLangModelAcceptable); 1.100 + javaxToolsProcessingAcceptableTemp.addAll(Arrays.asList( 1.101 + "javax.annotation.processing.", 1.102 + "javax.tools." 1.103 + )); 1.104 + javaxToolsProcessingAcceptable = javaxToolsProcessingAcceptableTemp; 1.105 + Set<String> comSunSourceAcceptableTemp = new HashSet<>(); 1.106 + comSunSourceAcceptableTemp.addAll(javaxToolsProcessingAcceptable); 1.107 + comSunSourceAcceptableTemp.addAll(Arrays.asList( 1.108 + "com.sun.source.doctree.", 1.109 + "com.sun.source.tree.", 1.110 + "com.sun.source.util." 1.111 + )); 1.112 + comSunSourceAcceptable = comSunSourceAcceptableTemp; 1.113 + } 1.114 + 1.115 + @Override 1.116 + public boolean process(Set<? extends TypeElement> annotations, 1.117 + RoundEnvironment roundEnv) { 1.118 + if (roundEnv.processingOver()) { 1.119 + verifyPackage(javaxLangModelPackages, javaxLangModelAcceptable); 1.120 + verifyPackage(javaxToolsProcessingPackages, javaxToolsProcessingAcceptable); 1.121 + verifyPackage(comSunSourcePackages, comSunSourceAcceptable); 1.122 + } 1.123 + return true; 1.124 + } 1.125 + 1.126 + private void verifyPackage(String[] packagesToTest, Set<String> acceptable) { 1.127 + for (String packageToTest : packagesToTest) { 1.128 + PackageElement packageElement = processingEnv.getElementUtils() 1.129 + .getPackageElement(packageToTest); 1.130 + 1.131 + verifyReferredTypesAcceptable(packageElement, acceptable); 1.132 + } 1.133 + } 1.134 + 1.135 + private void verifyReferredTypesAcceptable(Element rootElement, 1.136 + final Set<String> acceptable) { 1.137 + new ElementScanner8<Void, Void>() { 1.138 + @Override public Void visitType(TypeElement e, Void p) { 1.139 + verifyTypeAcceptable(e.getSuperclass(), acceptable); 1.140 + verifyTypesAcceptable(e.getInterfaces(), acceptable); 1.141 + scan(e.getTypeParameters(), p); 1.142 + scan(e.getEnclosedElements(), p); 1.143 + verifyAnnotations(e.getAnnotationMirrors(), acceptable); 1.144 + return null; 1.145 + } 1.146 + @Override public Void visitTypeParameter(TypeParameterElement e, Void p) { 1.147 + verifyTypesAcceptable(e.getBounds(), acceptable); 1.148 + scan(e.getEnclosedElements(), p); 1.149 + verifyAnnotations(e.getAnnotationMirrors(), acceptable); 1.150 + return null; 1.151 + } 1.152 + @Override public Void visitPackage(PackageElement e, Void p) { 1.153 + scan(e.getEnclosedElements(), p); 1.154 + verifyAnnotations(e.getAnnotationMirrors(), acceptable); 1.155 + return null; 1.156 + } 1.157 + @Override public Void visitVariable(VariableElement e, Void p) { 1.158 + verifyTypeAcceptable(e.asType(), acceptable); 1.159 + scan(e.getEnclosedElements(), p); 1.160 + verifyAnnotations(e.getAnnotationMirrors(), acceptable); 1.161 + return null; 1.162 + } 1.163 + @Override 1.164 + public Void visitExecutable(ExecutableElement e, Void p) { 1.165 + scan(e.getTypeParameters(), p); 1.166 + verifyTypeAcceptable(e.getReturnType(), acceptable); 1.167 + scan(e.getParameters(), p); 1.168 + verifyTypesAcceptable(e.getThrownTypes(), acceptable); 1.169 + scan(e.getEnclosedElements(), p); 1.170 + verifyAnnotations(e.getAnnotationMirrors(), acceptable); 1.171 + return null; 1.172 + } 1.173 + }.scan(rootElement, null); 1.174 + } 1.175 + 1.176 + private void verifyAnnotations(Iterable<? extends AnnotationMirror> annotations, 1.177 + Set<String> acceptable) { 1.178 + for (AnnotationMirror mirror : annotations) { 1.179 + Element annotationElement = mirror.getAnnotationType().asElement(); 1.180 + 1.181 + if (annotationElement.getAnnotation(Documented.class) == null) { 1.182 + note("Ignoring undocumented annotation: " + mirror.getAnnotationType()); 1.183 + } 1.184 + 1.185 + verifyTypeAcceptable(mirror.getAnnotationType(), acceptable); 1.186 + 1.187 + for (AnnotationValue value : mirror.getElementValues().values()) { 1.188 + verifyAnnotationValue(value, acceptable); 1.189 + } 1.190 + } 1.191 + } 1.192 + 1.193 + private void verifyAnnotationValue(AnnotationValue value, 1.194 + final Set<String> acceptable) { 1.195 + value.accept(new SimpleAnnotationValueVisitor8<Void, Void>() { 1.196 + @Override public Void visitType(TypeMirror t, Void p) { 1.197 + verifyTypeAcceptable(t, acceptable); 1.198 + return null; 1.199 + } 1.200 + @Override 1.201 + public Void visitEnumConstant(VariableElement c, Void p) { 1.202 + verifyReferredTypesAcceptable(c, acceptable); 1.203 + return null; 1.204 + } 1.205 + @Override public Void visitArray(List<? extends AnnotationValue> vals, 1.206 + Void p) { 1.207 + for (AnnotationValue val : vals) { 1.208 + val.accept(this, p); 1.209 + } 1.210 + return null; 1.211 + } 1.212 + @Override protected Void defaultAction(Object o, Void p) { 1.213 + error("Unexpected AnnotationValue: " + o.toString()); 1.214 + return super.defaultAction(o, p); 1.215 + } 1.216 + }, null); 1.217 + } 1.218 + 1.219 + private void verifyTypesAcceptable(Iterable<? extends TypeMirror> types, 1.220 + Set<String> acceptable) { 1.221 + if (types == null) return ; 1.222 + 1.223 + for (TypeMirror type : types) { 1.224 + verifyTypeAcceptable(type, acceptable); 1.225 + } 1.226 + } 1.227 + 1.228 + private void verifyTypeAcceptable(TypeMirror type, Set<String> acceptable) { 1.229 + if (type == null) return ; 1.230 + 1.231 + verifyAnnotations(type.getAnnotationMirrors(), acceptable); 1.232 + 1.233 + switch (type.getKind()) { 1.234 + case BOOLEAN: case BYTE: case CHAR: case DOUBLE: case FLOAT: 1.235 + case INT: case LONG: case SHORT: case VOID: case NONE: case NULL: 1.236 + return ; 1.237 + case DECLARED: 1.238 + DeclaredType dt = (DeclaredType) type; 1.239 + TypeElement outermostTypeElement = outermostTypeElement(dt.asElement()); 1.240 + String outermostType = outermostTypeElement.getQualifiedName().toString(); 1.241 + boolean isAcceptable = false; 1.242 + for (String acceptablePackage : acceptable) { 1.243 + if (outermostType.startsWith(acceptablePackage)) { 1.244 + isAcceptable = true; 1.245 + break; 1.246 + } 1.247 + } 1.248 + if (!isAcceptable) { 1.249 + error("Type not acceptable for this API: " + dt.toString()); 1.250 + } 1.251 + 1.252 + for (TypeMirror bound : dt.getTypeArguments()) { 1.253 + verifyTypeAcceptable(bound, acceptable); 1.254 + } 1.255 + break; 1.256 + case ARRAY: 1.257 + verifyTypeAcceptable(((ArrayType) type).getComponentType(), acceptable); 1.258 + break; 1.259 + case INTERSECTION: 1.260 + for (TypeMirror element : ((IntersectionType) type).getBounds()) { 1.261 + verifyTypeAcceptable(element, acceptable); 1.262 + } 1.263 + break; 1.264 + case TYPEVAR: 1.265 + verifyTypeAcceptable(((TypeVariable) type).getLowerBound(), acceptable); 1.266 + verifyTypeAcceptable(((TypeVariable) type).getUpperBound(), acceptable); 1.267 + break; 1.268 + case WILDCARD: 1.269 + verifyTypeAcceptable(((WildcardType) type).getExtendsBound(), acceptable); 1.270 + verifyTypeAcceptable(((WildcardType) type).getSuperBound(), acceptable); 1.271 + break; 1.272 + default: 1.273 + error("Type not acceptable for this API: " + type.toString()); 1.274 + break; 1.275 + 1.276 + } 1.277 + } 1.278 + 1.279 + private TypeElement outermostTypeElement(Element el) { 1.280 + while (el.getEnclosingElement().getKind() != ElementKind.PACKAGE) { 1.281 + el = el.getEnclosingElement(); 1.282 + } 1.283 + 1.284 + return (TypeElement) el; 1.285 + } 1.286 + 1.287 + private void error(String text) { 1.288 + processingEnv.getMessager().printMessage(Kind.ERROR, text); 1.289 + } 1.290 + 1.291 + private void note(String text) { 1.292 + processingEnv.getMessager().printMessage(Kind.NOTE, text); 1.293 + } 1.294 +}