test/tools/javac/tree/NoPrivateTypesExported.java

Wed, 14 Nov 2018 10:18:25 -0800

author
diazhou
date
Wed, 14 Nov 2018 10:18:25 -0800
changeset 3762
7909abb85562
parent 0
959103a6100f
permissions
-rw-r--r--

Added tag jdk8u201-b04 for changeset a7f48b9dfb82

     1 /*
     2  * Copyright (c) 2013, 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 8026180
    27  * @summary Ensuring javax.lang.model.**, javax.tools.**, javax.annotation.processing.**
    28  *          and com.sun.source.** don't export inappropriate types.
    29  * @library /tools/javac/lib
    30  * @build JavacTestingAbstractProcessor NoPrivateTypesExported
    31  * @compile -processor NoPrivateTypesExported NoPrivateTypesExported.java
    32  */
    33 import java.lang.annotation.Documented;
    34 import java.util.Arrays;
    35 import java.util.HashSet;
    36 import java.util.List;
    37 import java.util.Set;
    38 import javax.annotation.processing.RoundEnvironment;
    39 import javax.lang.model.element.AnnotationMirror;
    40 import javax.lang.model.element.AnnotationValue;
    41 import javax.lang.model.element.Element;
    42 import javax.lang.model.element.ElementKind;
    43 import javax.lang.model.element.ExecutableElement;
    44 import javax.lang.model.element.PackageElement;
    45 import javax.lang.model.element.TypeElement;
    46 import javax.lang.model.element.TypeParameterElement;
    47 import javax.lang.model.element.VariableElement;
    48 import javax.lang.model.type.ArrayType;
    49 import javax.lang.model.type.DeclaredType;
    50 import javax.lang.model.type.IntersectionType;
    51 import javax.lang.model.type.TypeMirror;
    52 import javax.lang.model.type.TypeVariable;
    53 import javax.lang.model.type.WildcardType;
    54 import javax.lang.model.util.ElementScanner8;
    55 import javax.lang.model.util.SimpleAnnotationValueVisitor8;
    56 import javax.tools.Diagnostic.Kind;
    58 public class NoPrivateTypesExported extends JavacTestingAbstractProcessor {
    60     private static final String[] javaxLangModelPackages = new String[] {
    61         "javax.lang.model",
    62         "javax.lang.model.element",
    63         "javax.lang.model.type",
    64         "javax.lang.model.util",
    65     };
    67     private static final Set<String> javaxLangModelAcceptable;
    69     private static final String[] javaxToolsProcessingPackages = new String[] {
    70         "javax.annotation.processing",
    71         "javax.tools",
    72     };
    74     private static final Set<String> javaxToolsProcessingAcceptable;
    76     private static final String[] comSunSourcePackages = new String[] {
    77         "com.sun.source.doctree",
    78         "com.sun.source.tree",
    79         "com.sun.source.util"
    80     };
    82     private static final Set<String> comSunSourceAcceptable;
    84     static {
    85         javaxLangModelAcceptable = new HashSet<>(Arrays.asList(
    86             "java.io.",
    87             "java.lang.",
    88             "java.net.",
    89             "java.nio.",
    90             "java.util.",
    91             "javax.lang.model.",
    92             "javax.annotation.processing.SupportedSourceVersion",
    93             "jdk.Exported"
    94         ));
    95         Set<String> javaxToolsProcessingAcceptableTemp = new HashSet<>();
    96         javaxToolsProcessingAcceptableTemp.addAll(javaxLangModelAcceptable);
    97         javaxToolsProcessingAcceptableTemp.addAll(Arrays.asList(
    98                 "javax.annotation.processing.",
    99                 "javax.tools."
   100         ));
   101         javaxToolsProcessingAcceptable = javaxToolsProcessingAcceptableTemp;
   102         Set<String> comSunSourceAcceptableTemp = new HashSet<>();
   103         comSunSourceAcceptableTemp.addAll(javaxToolsProcessingAcceptable);
   104         comSunSourceAcceptableTemp.addAll(Arrays.asList(
   105                 "com.sun.source.doctree.",
   106                 "com.sun.source.tree.",
   107                 "com.sun.source.util."
   108         ));
   109         comSunSourceAcceptable = comSunSourceAcceptableTemp;
   110     }
   112     @Override
   113     public boolean process(Set<? extends TypeElement> annotations,
   114                            RoundEnvironment roundEnv) {
   115         if (roundEnv.processingOver()) {
   116             verifyPackage(javaxLangModelPackages, javaxLangModelAcceptable);
   117             verifyPackage(javaxToolsProcessingPackages, javaxToolsProcessingAcceptable);
   118             verifyPackage(comSunSourcePackages, comSunSourceAcceptable);
   119         }
   120         return true;
   121     }
   123     private void verifyPackage(String[] packagesToTest, Set<String> acceptable) {
   124         for (String packageToTest : packagesToTest) {
   125             PackageElement packageElement = processingEnv.getElementUtils()
   126                     .getPackageElement(packageToTest);
   128             verifyReferredTypesAcceptable(packageElement, acceptable);
   129         }
   130     }
   132     private void verifyReferredTypesAcceptable(Element rootElement,
   133                                                final Set<String> acceptable) {
   134         new ElementScanner8<Void, Void>() {
   135             @Override public Void visitType(TypeElement e, Void p) {
   136                 verifyTypeAcceptable(e.getSuperclass(), acceptable);
   137                 verifyTypesAcceptable(e.getInterfaces(), acceptable);
   138                 scan(e.getTypeParameters(), p);
   139                 scan(e.getEnclosedElements(), p);
   140                 verifyAnnotations(e.getAnnotationMirrors(), acceptable);
   141                 return null;
   142             }
   143             @Override public Void visitTypeParameter(TypeParameterElement e, Void p) {
   144                 verifyTypesAcceptable(e.getBounds(), acceptable);
   145                 scan(e.getEnclosedElements(), p);
   146                 verifyAnnotations(e.getAnnotationMirrors(), acceptable);
   147                 return null;
   148             }
   149             @Override public Void visitPackage(PackageElement e, Void p) {
   150                 scan(e.getEnclosedElements(), p);
   151                 verifyAnnotations(e.getAnnotationMirrors(), acceptable);
   152                 return null;
   153             }
   154             @Override public Void visitVariable(VariableElement e, Void p) {
   155                 verifyTypeAcceptable(e.asType(), acceptable);
   156                 scan(e.getEnclosedElements(), p);
   157                 verifyAnnotations(e.getAnnotationMirrors(), acceptable);
   158                 return null;
   159             }
   160             @Override
   161             public Void visitExecutable(ExecutableElement e, Void p) {
   162                 scan(e.getTypeParameters(), p);
   163                 verifyTypeAcceptable(e.getReturnType(), acceptable);
   164                 scan(e.getParameters(), p);
   165                 verifyTypesAcceptable(e.getThrownTypes(), acceptable);
   166                 scan(e.getEnclosedElements(), p);
   167                 verifyAnnotations(e.getAnnotationMirrors(), acceptable);
   168                 return null;
   169             }
   170         }.scan(rootElement, null);
   171     }
   173     private void verifyAnnotations(Iterable<? extends AnnotationMirror> annotations,
   174                                    Set<String> acceptable) {
   175         for (AnnotationMirror mirror : annotations) {
   176             Element annotationElement = mirror.getAnnotationType().asElement();
   178             if (annotationElement.getAnnotation(Documented.class) == null) {
   179                 note("Ignoring undocumented annotation: " + mirror.getAnnotationType());
   180             }
   182             verifyTypeAcceptable(mirror.getAnnotationType(), acceptable);
   184             for (AnnotationValue value : mirror.getElementValues().values()) {
   185                 verifyAnnotationValue(value, acceptable);
   186             }
   187         }
   188     }
   190     private void verifyAnnotationValue(AnnotationValue value,
   191                                        final Set<String> acceptable) {
   192         value.accept(new SimpleAnnotationValueVisitor8<Void, Void>() {
   193             @Override public Void visitType(TypeMirror t, Void p) {
   194                 verifyTypeAcceptable(t, acceptable);
   195                 return null;
   196             }
   197             @Override
   198             public Void visitEnumConstant(VariableElement c, Void p) {
   199                 verifyReferredTypesAcceptable(c, acceptable);
   200                 return null;
   201             }
   202             @Override public Void visitArray(List<? extends AnnotationValue> vals,
   203                                              Void p) {
   204                 for (AnnotationValue val : vals) {
   205                     val.accept(this, p);
   206                 }
   207                 return null;
   208             }
   209             @Override protected Void defaultAction(Object o, Void p) {
   210                 error("Unexpected AnnotationValue: " + o.toString());
   211                 return super.defaultAction(o, p);
   212             }
   213         }, null);
   214     }
   216     private void verifyTypesAcceptable(Iterable<? extends TypeMirror> types,
   217                                        Set<String> acceptable) {
   218         if (types == null) return ;
   220         for (TypeMirror type : types) {
   221             verifyTypeAcceptable(type, acceptable);
   222         }
   223     }
   225     private void verifyTypeAcceptable(TypeMirror type, Set<String> acceptable) {
   226         if (type == null) return ;
   228         verifyAnnotations(type.getAnnotationMirrors(), acceptable);
   230         switch (type.getKind()) {
   231             case BOOLEAN: case BYTE: case CHAR: case DOUBLE: case FLOAT:
   232             case INT: case LONG: case SHORT: case VOID: case NONE: case NULL:
   233                 return ;
   234             case DECLARED:
   235                 DeclaredType dt = (DeclaredType) type;
   236                 TypeElement outermostTypeElement = outermostTypeElement(dt.asElement());
   237                 String outermostType = outermostTypeElement.getQualifiedName().toString();
   238                 boolean isAcceptable = false;
   239                 for (String acceptablePackage : acceptable) {
   240                     if (outermostType.startsWith(acceptablePackage)) {
   241                         isAcceptable = true;
   242                         break;
   243                     }
   244                 }
   245                 if (!isAcceptable) {
   246                     error("Type not acceptable for this API: " + dt.toString());
   247                 }
   249                 for (TypeMirror bound : dt.getTypeArguments()) {
   250                     verifyTypeAcceptable(bound, acceptable);
   251                 }
   252                 break;
   253             case ARRAY:
   254                 verifyTypeAcceptable(((ArrayType) type).getComponentType(), acceptable);
   255                 break;
   256             case INTERSECTION:
   257                 for (TypeMirror element : ((IntersectionType) type).getBounds()) {
   258                     verifyTypeAcceptable(element, acceptable);
   259                 }
   260                 break;
   261             case TYPEVAR:
   262                 verifyTypeAcceptable(((TypeVariable) type).getLowerBound(), acceptable);
   263                 verifyTypeAcceptable(((TypeVariable) type).getUpperBound(), acceptable);
   264                 break;
   265             case WILDCARD:
   266                 verifyTypeAcceptable(((WildcardType) type).getExtendsBound(), acceptable);
   267                 verifyTypeAcceptable(((WildcardType) type).getSuperBound(), acceptable);
   268                 break;
   269             default:
   270                 error("Type not acceptable for this API: " + type.toString());
   271                 break;
   273         }
   274     }
   276     private TypeElement outermostTypeElement(Element el) {
   277         while (el.getEnclosingElement().getKind() != ElementKind.PACKAGE) {
   278             el = el.getEnclosingElement();
   279         }
   281         return (TypeElement) el;
   282     }
   284     private void error(String text) {
   285         processingEnv.getMessager().printMessage(Kind.ERROR, text);
   286     }
   288     private void note(String text) {
   289         processingEnv.getMessager().printMessage(Kind.NOTE, text);
   290     }
   291 }

mercurial