1 /*
2  * Copyright (c) 2006, 2015, 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 /**
25  * @test
26  * @bug 6341866
27  * @summary Source files loaded from source path are not subject to annotation processing
28  * @modules java.compiler
29  *          jdk.compiler
30  * @build Anno T6341866
31  * @run main T6341866
32  */
33 
34 import java.io.*;
35 import java.util.*;
36 import javax.annotation.processing.*;
37 import javax.tools.*;
38 
39 /**
40  * For each of a number of implicit compilation scenarios,
41  * and for each of a set of annotation processing scenarios,
42  * verify that a class file is generated, or not, for an
43  * implicitly compiled source file and that the correct
44  * warning message is given for implicitly compiled files
45  * when annotation processing.
46  */
47 public class T6341866 {
48     static final String testSrc = System.getProperty("test.src", ".");
49     static final String testClasses = System.getProperty("test.classes", ".");
50     static final File a_java = new File(testSrc, "A.java");
51     static final File a_class = new File("A.class");
52     static final File b_java = new File(testSrc, "B.java");
53     static final File b_class = new File("B.class");
54     static final File processorServices = services(Processor.class);
55 
56     enum ImplicitType {
57         NONE(null),                     // don't use implicit compilation
58         OPT_UNSET(null),                // implicit compilation, but no -implicit option
59         OPT_NONE("-implicit:none"),     // implicit compilation wiith -implicit:none
60         OPT_CLASS("-implicit:class");   // implicit compilation wiith -implicit:class
61 
ImplicitType(String opt)62         ImplicitType(String opt) {
63             this.opt = opt;
64         }
65         final String opt;
66     };
67 
68     enum AnnoType {
69         NONE,           // no annotation processing
70         SERVICE,        // implicit annotation processing, via ServiceLoader
71         SPECIFY         // explicit annotation processing
72     };
73 
74 
main(String .... args)75     public static void main(String ... args) throws Exception {
76         boolean ok = true;
77 
78         // iterate over all combinations
79         for (ImplicitType implicitType: EnumSet.allOf(ImplicitType.class)) {
80             for (AnnoType annoType: EnumSet.allOf(AnnoType.class)) {
81                 ok &= test(implicitType, annoType);
82             }
83         }
84 
85         if (!ok)
86             throw new AssertionError("test failed");
87     }
88 
89     /**
90      * Verify that a class file is generated, or not, for an implicitly compiled source file,
91      * and that the correct warning message is given for implicitly compiled files when annotation processing.
92      */
test(ImplicitType implicitType, AnnoType annoType)93     static boolean test(ImplicitType implicitType, AnnoType annoType) throws IOException {
94         System.err.println("test  implicit=" + implicitType + "  anno=" + annoType);
95 
96         // ensure clean start
97         a_class.delete();
98         b_class.delete();
99         processorServices.delete();
100 
101         List<String> opts = new ArrayList<String>();
102         opts.addAll(Arrays.asList("-d", ".", "-sourcepath", testSrc, "-classpath", testClasses, "-Xlint:-options"));
103         if (implicitType.opt != null)
104             opts.add(implicitType.opt);
105 
106         switch (annoType) {
107         case SERVICE:
108             createProcessorServices(Anno.class.getName());
109             break;
110         case SPECIFY:
111             opts.addAll(Arrays.asList("-processor", Anno.class.getName()));
112             break;
113         }
114 
115 
116         JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
117         MyDiagListener dl = new MyDiagListener();
118         try (StandardJavaFileManager fm = javac.getStandardFileManager(dl, null, null)) {
119 
120             // Note: class A references class B, so compile A if we want implicit compilation
121             File file =  (implicitType != ImplicitType.NONE) ? a_java : b_java;
122             Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(file);
123 
124             //System.err.println("compile: " + opts + " " + files);
125 
126             boolean ok = javac.getTask(null, fm, dl, opts, null, files).call();
127             if (!ok) {
128                 error("compilation failed");
129                 return false;
130             }
131 
132             // check implicit compilation results if necessary
133             if (implicitType != ImplicitType.NONE) {
134                 boolean expectClass = (implicitType != ImplicitType.OPT_NONE);
135                 if (b_class.exists() != expectClass) {
136                     if (b_class.exists())
137                         error("B implicitly compiled unexpectedly");
138                     else
139                         error("B not impliictly compiled");
140                     return false;
141                 }
142             }
143 
144             // check message key results
145             String expectKey = null;
146             if (implicitType == ImplicitType.OPT_UNSET) {
147                 switch (annoType) {
148                 case SERVICE:
149                     expectKey = "compiler.warn.proc.use.proc.or.implicit";
150                     break;
151                 case SPECIFY:
152                     expectKey = "compiler.warn.proc.use.implicit";
153                     break;
154                 }
155             }
156 
157             if (expectKey == null) {
158                 if (dl.diagCodes.size() != 0) {
159                     error("no diagnostics expected");
160                     return false;
161                 }
162             } else {
163                 if (!(dl.diagCodes.size() == 1 && dl.diagCodes.get(0).equals(expectKey))) {
164                     error("unexpected diagnostics generated");
165                     return false;
166                 }
167             }
168 
169             return true;
170         }
171     }
172 
createProcessorServices(String name)173     static void createProcessorServices(String name) throws IOException {
174         processorServices.getParentFile().mkdirs();
175 
176         BufferedWriter out = new BufferedWriter(new FileWriter(processorServices));
177         out.write(name);
178         out.newLine();
179         out.close();
180     }
181 
182     static class MyDiagListener implements DiagnosticListener<JavaFileObject> {
report(Diagnostic d)183         public void report(Diagnostic d) {
184             diagCodes.add(d.getCode());
185             System.err.println(d);
186         }
187 
188         List<String> diagCodes = new ArrayList<String>();
189     }
190 
error(String msg)191     static void error(String msg) {
192         System.err.println("ERROR: " + msg);
193     }
194 
services(Class<?> service)195     static File services(Class<?> service) {
196         String[] dirs = { testClasses, "META-INF", "services" };
197         File dir = null;
198         for (String d: dirs)
199             dir = (dir == null ? new File(d) : new File(dir, d));
200 
201         return new File(dir, service.getName());
202     }
203 }
204