Fri, 25 Feb 2011 12:09:33 -0800
7021650: fix Context issues
Reviewed-by: mcimadamore
1.1 --- a/src/share/classes/com/sun/tools/apt/util/Bark.java Thu Feb 24 08:40:49 2011 -0800 1.2 +++ b/src/share/classes/com/sun/tools/apt/util/Bark.java Fri Feb 25 12:09:33 2011 -0800 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 2004, 2008, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -48,15 +48,15 @@ 1.11 * Preregisters factories to create and use a Bark object for use as 1.12 * both a Log and a Bark. 1.13 */ 1.14 - public static void preRegister(final Context context) { 1.15 + public static void preRegister(Context context) { 1.16 context.put(barkKey, new Context.Factory<Bark>() { 1.17 - public Bark make() { 1.18 - return new Bark(context); 1.19 + public Bark make(Context c) { 1.20 + return new Bark(c); 1.21 } 1.22 }); 1.23 context.put(Log.logKey, new Context.Factory<Log>() { 1.24 - public Log make() { 1.25 - return Bark.instance(context); 1.26 + public Log make(Context c) { 1.27 + return Bark.instance(c); 1.28 } 1.29 }); 1.30 }
2.1 --- a/src/share/classes/com/sun/tools/javac/api/JavacTool.java Thu Feb 24 08:40:49 2011 -0800 2.2 +++ b/src/share/classes/com/sun/tools/javac/api/JavacTool.java Fri Feb 25 12:09:33 2011 -0800 2.3 @@ -1,5 +1,5 @@ 2.4 /* 2.5 - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 2.6 + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. 2.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.8 * 2.9 * This code is free software; you can redistribute it and/or modify it 2.10 @@ -157,19 +157,19 @@ 2.11 /** 2.12 * Register that a compilation is about to start. 2.13 */ 2.14 - void beginContext(final Context context) { 2.15 + void beginContext(Context context) { 2.16 if (compilationInProgress) 2.17 throw new IllegalStateException("Compilation in progress"); 2.18 compilationInProgress = true; 2.19 final JavaFileManager givenFileManager = context.get(JavaFileManager.class); 2.20 context.put(JavaFileManager.class, (JavaFileManager)null); 2.21 context.put(JavaFileManager.class, new Context.Factory<JavaFileManager>() { 2.22 - public JavaFileManager make() { 2.23 + public JavaFileManager make(Context c) { 2.24 if (givenFileManager != null) { 2.25 - context.put(JavaFileManager.class, givenFileManager); 2.26 + c.put(JavaFileManager.class, givenFileManager); 2.27 return givenFileManager; 2.28 } else { 2.29 - return new JavacFileManager(context, true, null); 2.30 + return new JavacFileManager(c, true, null); 2.31 } 2.32 } 2.33 });
3.1 --- a/src/share/classes/com/sun/tools/javac/file/CacheFSInfo.java Thu Feb 24 08:40:49 2011 -0800 3.2 +++ b/src/share/classes/com/sun/tools/javac/file/CacheFSInfo.java Fri Feb 25 12:09:33 2011 -0800 3.3 @@ -44,13 +44,13 @@ 3.4 public class CacheFSInfo extends FSInfo { 3.5 3.6 /** 3.7 - * Register a Context.Factory to create a singleton CacheFSInfo. 3.8 + * Register a Context.Factory to create a CacheFSInfo. 3.9 */ 3.10 - public static void preRegister(final Context context) { 3.11 + public static void preRegister(Context context) { 3.12 context.put(FSInfo.class, new Context.Factory<FSInfo>() { 3.13 - public FSInfo make() { 3.14 + public FSInfo make(Context c) { 3.15 FSInfo instance = new CacheFSInfo(); 3.16 - context.put(FSInfo.class, instance); 3.17 + c.put(FSInfo.class, instance); 3.18 return instance; 3.19 } 3.20 });
4.1 --- a/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java Thu Feb 24 08:40:49 2011 -0800 4.2 +++ b/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java Fri Feb 25 12:09:33 2011 -0800 4.3 @@ -129,10 +129,10 @@ 4.4 /** 4.5 * Register a Context.Factory to create a JavacFileManager. 4.6 */ 4.7 - public static void preRegister(final Context context) { 4.8 + public static void preRegister(Context context) { 4.9 context.put(JavaFileManager.class, new Context.Factory<JavaFileManager>() { 4.10 - public JavaFileManager make() { 4.11 - return new JavacFileManager(context, true, null); 4.12 + public JavaFileManager make(Context c) { 4.13 + return new JavacFileManager(c, true, null); 4.14 } 4.15 }); 4.16 }
5.1 --- a/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Thu Feb 24 08:40:49 2011 -0800 5.2 +++ b/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Fri Feb 25 12:09:33 2011 -0800 5.3 @@ -312,7 +312,7 @@ 5.4 5.5 /** Construct a new compiler using a shared context. 5.6 */ 5.7 - public JavaCompiler(final Context context) { 5.8 + public JavaCompiler(Context context) { 5.9 this.context = context; 5.10 context.put(compilerKey, this); 5.11
6.1 --- a/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Thu Feb 24 08:40:49 2011 -0800 6.2 +++ b/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Fri Feb 25 12:09:33 2011 -0800 6.3 @@ -1045,7 +1045,7 @@ 6.4 * other values are implicitly reset. 6.5 */ 6.6 private Context nextContext() { 6.7 - Context next = new Context(); 6.8 + Context next = new Context(context); 6.9 6.10 Options options = Options.instance(context); 6.11 Assert.checkNonNull(options);
7.1 --- a/src/share/classes/com/sun/tools/javac/util/Context.java Thu Feb 24 08:40:49 2011 -0800 7.2 +++ b/src/share/classes/com/sun/tools/javac/util/Context.java Fri Feb 25 12:09:33 2011 -0800 7.3 @@ -108,7 +108,7 @@ 7.4 * instance. 7.5 */ 7.6 public static interface Factory<T> { 7.7 - T make(); 7.8 + T make(Context c); 7.9 }; 7.10 7.11 /** 7.12 @@ -124,6 +124,8 @@ 7.13 Object old = ht.put(key, fac); 7.14 if (old != null) 7.15 throw new AssertionError("duplicate context value"); 7.16 + checkState(ft); 7.17 + ft.put(key, fac); // cannot be duplicate if unique in ht 7.18 } 7.19 7.20 /** Set the value for the key in this context. */ 7.21 @@ -142,7 +144,7 @@ 7.22 Object o = ht.get(key); 7.23 if (o instanceof Factory<?>) { 7.24 Factory<?> fac = (Factory<?>)o; 7.25 - o = fac.make(); 7.26 + o = fac.make(this); 7.27 if (o instanceof Factory<?>) 7.28 throw new AssertionError("T extends Context.Factory"); 7.29 Assert.check(ht.get(key) == o); 7.30 @@ -158,6 +160,20 @@ 7.31 7.32 public Context() {} 7.33 7.34 + /** 7.35 + * The table of preregistered factories. 7.36 + */ 7.37 + private Map<Key<?>,Factory<?>> ft = new HashMap<Key<?>,Factory<?>>(); 7.38 + 7.39 + public Context(Context prev) { 7.40 + kt.putAll(prev.kt); // retain all implicit keys 7.41 + ft.putAll(prev.ft); // retain all factory objects 7.42 + ht.putAll(prev.ft); // init main table with factories 7.43 + } 7.44 + 7.45 + /* 7.46 + * The key table, providing a unique Key<T> for each Class<T>. 7.47 + */ 7.48 private Map<Class<?>, Key<?>> kt = new HashMap<Class<?>, Key<?>>(); 7.49 7.50 private <T> Key<T> key(Class<T> clss) { 7.51 @@ -198,6 +214,7 @@ 7.52 public void clear() { 7.53 ht = null; 7.54 kt = null; 7.55 + ft = null; 7.56 } 7.57 7.58 private static void checkState(Map<?,?> t) {
8.1 --- a/src/share/classes/com/sun/tools/javadoc/JavadocClassReader.java Thu Feb 24 08:40:49 2011 -0800 8.2 +++ b/src/share/classes/com/sun/tools/javadoc/JavadocClassReader.java Fri Feb 25 12:09:33 2011 -0800 8.3 @@ -1,5 +1,5 @@ 8.4 /* 8.5 - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. 8.6 + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. 8.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 8.8 * 8.9 * This code is free software; you can redistribute it and/or modify it 8.10 @@ -44,10 +44,10 @@ 8.11 return (JavadocClassReader)instance; 8.12 } 8.13 8.14 - public static void preRegister(final Context context) { 8.15 + public static void preRegister(Context context) { 8.16 context.put(classReaderKey, new Context.Factory<ClassReader>() { 8.17 - public ClassReader make() { 8.18 - return new JavadocClassReader(context); 8.19 + public ClassReader make(Context c) { 8.20 + return new JavadocClassReader(c); 8.21 } 8.22 }); 8.23 }
9.1 --- a/src/share/classes/com/sun/tools/javadoc/JavadocEnter.java Thu Feb 24 08:40:49 2011 -0800 9.2 +++ b/src/share/classes/com/sun/tools/javadoc/JavadocEnter.java Fri Feb 25 12:09:33 2011 -0800 9.3 @@ -1,5 +1,5 @@ 9.4 /* 9.5 - * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved. 9.6 + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. 9.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 9.8 * 9.9 * This code is free software; you can redistribute it and/or modify it 9.10 @@ -48,10 +48,10 @@ 9.11 return (JavadocEnter)instance; 9.12 } 9.13 9.14 - public static void preRegister(final Context context) { 9.15 + public static void preRegister(Context context) { 9.16 context.put(enterKey, new Context.Factory<Enter>() { 9.17 - public Enter make() { 9.18 - return new JavadocEnter(context); 9.19 + public Enter make(Context c) { 9.20 + return new JavadocEnter(c); 9.21 } 9.22 }); 9.23 }
10.1 --- a/src/share/classes/com/sun/tools/javadoc/JavadocMemberEnter.java Thu Feb 24 08:40:49 2011 -0800 10.2 +++ b/src/share/classes/com/sun/tools/javadoc/JavadocMemberEnter.java Fri Feb 25 12:09:33 2011 -0800 10.3 @@ -1,5 +1,5 @@ 10.4 /* 10.5 - * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. 10.6 + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. 10.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 10.8 * 10.9 * This code is free software; you can redistribute it and/or modify it 10.10 @@ -46,10 +46,10 @@ 10.11 return (JavadocMemberEnter)instance; 10.12 } 10.13 10.14 - public static void preRegister(final Context context) { 10.15 + public static void preRegister(Context context) { 10.16 context.put(memberEnterKey, new Context.Factory<MemberEnter>() { 10.17 - public MemberEnter make() { 10.18 - return new JavadocMemberEnter(context); 10.19 + public MemberEnter make(Context c) { 10.20 + return new JavadocMemberEnter(c); 10.21 } 10.22 }); 10.23 }
11.1 --- a/src/share/classes/com/sun/tools/javadoc/JavadocTodo.java Thu Feb 24 08:40:49 2011 -0800 11.2 +++ b/src/share/classes/com/sun/tools/javadoc/JavadocTodo.java Fri Feb 25 12:09:33 2011 -0800 11.3 @@ -1,5 +1,5 @@ 11.4 /* 11.5 - * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. 11.6 + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. 11.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 11.8 * 11.9 * This code is free software; you can redistribute it and/or modify it 11.10 @@ -34,10 +34,10 @@ 11.11 * @author Neal Gafter 11.12 */ 11.13 public class JavadocTodo extends Todo { 11.14 - public static void preRegister(final Context context) { 11.15 + public static void preRegister(Context context) { 11.16 context.put(todoKey, new Context.Factory<Todo>() { 11.17 - public Todo make() { 11.18 - return new JavadocTodo(context); 11.19 + public Todo make(Context c) { 11.20 + return new JavadocTodo(c); 11.21 } 11.22 }); 11.23 }
12.1 --- a/src/share/classes/com/sun/tools/javadoc/Messager.java Thu Feb 24 08:40:49 2011 -0800 12.2 +++ b/src/share/classes/com/sun/tools/javadoc/Messager.java Fri Feb 25 12:09:33 2011 -0800 12.3 @@ -1,5 +1,5 @@ 12.4 /* 12.5 - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. 12.6 + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. 12.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 12.8 * 12.9 * This code is free software; you can redistribute it and/or modify it 12.10 @@ -57,23 +57,23 @@ 12.11 return (Messager)instance; 12.12 } 12.13 12.14 - public static void preRegister(final Context context, 12.15 + public static void preRegister(Context context, 12.16 final String programName) { 12.17 context.put(logKey, new Context.Factory<Log>() { 12.18 - public Log make() { 12.19 - return new Messager(context, 12.20 + public Log make(Context c) { 12.21 + return new Messager(c, 12.22 programName); 12.23 } 12.24 }); 12.25 } 12.26 - public static void preRegister(final Context context, 12.27 + public static void preRegister(Context context, 12.28 final String programName, 12.29 final PrintWriter errWriter, 12.30 final PrintWriter warnWriter, 12.31 final PrintWriter noticeWriter) { 12.32 context.put(logKey, new Context.Factory<Log>() { 12.33 - public Log make() { 12.34 - return new Messager(context, 12.35 + public Log make(Context c) { 12.36 + return new Messager(c, 12.37 programName, 12.38 errWriter, 12.39 warnWriter,
13.1 --- a/test/tools/javac/diags/ArgTypeCompilerFactory.java Thu Feb 24 08:40:49 2011 -0800 13.2 +++ b/test/tools/javac/diags/ArgTypeCompilerFactory.java Fri Feb 25 12:09:33 2011 -0800 13.3 @@ -34,6 +34,7 @@ 13.4 import com.sun.tools.javac.code.*; 13.5 import com.sun.tools.javac.file.*; 13.6 import com.sun.tools.javac.main.Main; 13.7 +import com.sun.tools.javac.main.JavaCompiler; 13.8 import com.sun.tools.javac.parser.Token; 13.9 import com.sun.tools.javac.util.*; 13.10 import com.sun.tools.javac.util.AbstractDiagnosticFormatter.SimpleConfiguration; 13.11 @@ -107,8 +108,7 @@ 13.12 JavacTaskImpl t = (JavacTaskImpl) tool.getTask(out, fm, null, opts, null, fos); 13.13 Context c = t.getContext(); 13.14 ArgTypeMessages.preRegister(c); 13.15 - Options options = Options.instance(c); 13.16 - Log.instance(c).setDiagnosticFormatter(new ArgTypeDiagnosticFormatter(options)); 13.17 + ArgTypeJavaCompiler.preRegister(c); 13.18 Boolean ok = t.call(); 13.19 13.20 return ok; 13.21 @@ -144,7 +144,7 @@ 13.22 } 13.23 }; 13.24 JavacFileManager.preRegister(c); // can't create it until Log has been set up 13.25 - ArgTypeDiagnosticFormatter.preRegister(c); 13.26 + ArgTypeJavaCompiler.preRegister(c); 13.27 ArgTypeMessages.preRegister(c); 13.28 int result = main.compile(args.toArray(new String[args.size()]), c); 13.29 13.30 @@ -170,7 +170,7 @@ 13.31 13.32 Context c = new Context(); 13.33 JavacFileManager.preRegister(c); // can't create it until Log has been set up 13.34 - ArgTypeDiagnosticFormatter.preRegister(c); 13.35 + ArgTypeJavaCompiler.preRegister(c); 13.36 ArgTypeMessages.preRegister(c); 13.37 com.sun.tools.javac.main.Main m = new com.sun.tools.javac.main.Main("javac", out); 13.38 int rc = m.compile(args.toArray(new String[args.size()]), c); 13.39 @@ -189,17 +189,6 @@ 13.40 * arg types. 13.41 */ 13.42 static class ArgTypeDiagnosticFormatter extends AbstractDiagnosticFormatter { 13.43 - static void preRegister(final Context context) { 13.44 - context.put(Log.logKey, new Context.Factory<Log>() { 13.45 - public Log make() { 13.46 - Log log = new Log(context) { }; 13.47 - Options options = Options.instance(context); 13.48 - log.setDiagnosticFormatter(new ArgTypeDiagnosticFormatter(options)); 13.49 - return log; 13.50 - } 13.51 - }); 13.52 - 13.53 - } 13.54 13.55 ArgTypeDiagnosticFormatter(Options options) { 13.56 super(null, new SimpleConfiguration(options, 13.57 @@ -246,14 +235,37 @@ 13.58 } 13.59 13.60 /** 13.61 + * Trivial subtype of JavaCompiler to get access to the protected compilerKey field. 13.62 + * The factory is used to ensure that the log is initialized with an instance of 13.63 + * ArgTypeDiagnosticFormatter before we create the required JavaCompiler. 13.64 + */ 13.65 + static class ArgTypeJavaCompiler extends JavaCompiler { 13.66 + static void preRegister(Context context) { 13.67 + context.put(compilerKey, new Context.Factory<JavaCompiler>() { 13.68 + public JavaCompiler make(Context c) { 13.69 + Log log = Log.instance(c); 13.70 + Options options = Options.instance(c); 13.71 + log.setDiagnosticFormatter(new ArgTypeDiagnosticFormatter(options)); 13.72 + return new JavaCompiler(c); 13.73 + } 13.74 + }); 13.75 + } 13.76 + 13.77 + // not used 13.78 + private ArgTypeJavaCompiler() { 13.79 + super(null); 13.80 + } 13.81 + } 13.82 + 13.83 + /** 13.84 * Diagnostic formatter which "localizes" a message as a line 13.85 * containing a key, and a possibly empty set of descriptive strings for the 13.86 * arg types. 13.87 */ 13.88 static class ArgTypeMessages extends JavacMessages { 13.89 - static void preRegister(final Context c) { 13.90 - c.put(JavacMessages.messagesKey, new Context.Factory<JavacMessages>() { 13.91 - public JavacMessages make() { 13.92 + static void preRegister(Context context) { 13.93 + context.put(JavacMessages.messagesKey, new Context.Factory<JavacMessages>() { 13.94 + public JavacMessages make(Context c) { 13.95 return new ArgTypeMessages(c) { 13.96 @Override 13.97 public String getLocalizedString(Locale l, String key, Object... args) {
14.1 --- a/test/tools/javac/diags/Example.java Thu Feb 24 08:40:49 2011 -0800 14.2 +++ b/test/tools/javac/diags/Example.java Fri Feb 25 12:09:33 2011 -0800 14.3 @@ -522,10 +522,10 @@ 14.4 super(context); 14.5 } 14.6 14.7 - static void preRegister(final Context c, final Set<String> keys) { 14.8 + static void preRegister(Context c, final Set<String> keys) { 14.9 if (keys != null) { 14.10 c.put(JavacMessages.messagesKey, new Context.Factory<JavacMessages>() { 14.11 - public JavacMessages make() { 14.12 + public JavacMessages make(Context c) { 14.13 return new MessageTracker(c) { 14.14 @Override 14.15 public String getLocalizedString(Locale l, String key, Object... args) {
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/test/tools/javac/util/context/T7021650.java Fri Feb 25 12:09:33 2011 -0800 15.3 @@ -0,0 +1,216 @@ 15.4 +/* 15.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 15.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 15.7 + * 15.8 + * This code is free software; you can redistribute it and/or modify it 15.9 + * under the terms of the GNU General Public License version 2 only, as 15.10 + * published by the Free Software Foundation. 15.11 + * 15.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 15.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15.15 + * version 2 for more details (a copy is included in the LICENSE file that 15.16 + * accompanied this code). 15.17 + * 15.18 + * You should have received a copy of the GNU General Public License version 15.19 + * 2 along with this work; if not, write to the Free Software Foundation, 15.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 15.21 + * 15.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 15.23 + * or visit www.oracle.com if you need additional information or have any 15.24 + * questions. 15.25 + */ 15.26 + 15.27 +/** 15.28 + * @test 15.29 + * @bug 7021650 15.30 + * @summary Fix Context issues 15.31 + * @library ../../lib 15.32 + * @build JavacTestingAbstractProcessor T7021650 15.33 + * @run main T7021650 15.34 + */ 15.35 + 15.36 +import java.io.*; 15.37 +import java.net.*; 15.38 +import java.util.*; 15.39 +import javax.annotation.processing.*; 15.40 +import javax.lang.model.element.*; 15.41 +import javax.tools.*; 15.42 + 15.43 +import com.sun.tools.javac.comp.Attr; 15.44 +import com.sun.tools.javac.file.JavacFileManager; 15.45 +import com.sun.tools.javac.main.Main; 15.46 +import com.sun.tools.javac.processing.JavacProcessingEnvironment; 15.47 +import com.sun.tools.javac.util.Context; 15.48 + 15.49 +public class T7021650 extends JavacTestingAbstractProcessor { 15.50 + public static void main(String... args) throws Exception { 15.51 + new T7021650().run(); 15.52 + } 15.53 + 15.54 + static File testSrc = new File(System.getProperty("test.src")); 15.55 + static final int MAX_ROUNDS = 3; 15.56 + 15.57 + /** 15.58 + * Perform a compilation with custom factories registered in the context, 15.59 + * and verify that corresponding objects are created in each round. 15.60 + */ 15.61 + void run() throws Exception { 15.62 + Counter demoCounter = new Counter(); 15.63 + Counter myAttrCounter = new Counter(); 15.64 + 15.65 + Context context = new Context(); 15.66 + // Use a custom file manager which creates classloaders for annotation 15.67 + // processors with a sensible delegation parent, so that all instances 15.68 + // of test classes come from the same class loader. This is important 15.69 + // because the test performs class checks on the instances of classes 15.70 + // found in the context for each round or processing. 15.71 + context.put(JavaFileManager.class, new Context.Factory<JavaFileManager>() { 15.72 + public JavaFileManager make(Context c) { 15.73 + return new JavacFileManager(c, true, null) { 15.74 + @Override 15.75 + protected ClassLoader getClassLoader(URL[] urls) { 15.76 + return new URLClassLoader(urls, T7021650.class.getClassLoader()); 15.77 + } 15.78 + }; 15.79 + } 15.80 + }); 15.81 + 15.82 + Demo.preRegister(context, demoCounter); 15.83 + MyAttr.preRegister(context, myAttrCounter); 15.84 + 15.85 + String[] args = { 15.86 + "-d", ".", 15.87 + "-processor", T7021650.class.getName(), 15.88 + "-XprintRounds", 15.89 + new File(testSrc, T7021650.class.getName() + ".java").getPath() 15.90 + }; 15.91 + 15.92 + compile(context, args); 15.93 + 15.94 + // Expect to create Demo for initial round, then MAX_ROUNDS in which 15.95 + // GenX files are generated, then standard final round of processing. 15.96 + checkEqual("demoCounter", demoCounter.count, MAX_ROUNDS + 2); 15.97 + 15.98 + // Expect to create MyAttr for same processing rounds as for Demo, 15.99 + // plus additional context for final compilation. 15.100 + checkEqual("myAttrCounter", myAttrCounter.count, MAX_ROUNDS + 3); 15.101 + } 15.102 + 15.103 + void compile(Context context, String... args) throws Exception { 15.104 + StringWriter sw = new StringWriter(); 15.105 + PrintWriter pw = new PrintWriter(sw); 15.106 + Main m = new Main("javac", pw); 15.107 + int rc = m.compile(args, context); 15.108 + pw.close(); 15.109 + String out = sw.toString(); 15.110 + if (!out.isEmpty()) 15.111 + System.err.println(out); 15.112 + if (rc != 0) 15.113 + throw new Exception("compilation failed unexpectedly: rc=" + rc); 15.114 + } 15.115 + 15.116 + void checkEqual(String label, int found, int expect) throws Exception { 15.117 + if (found != expect) 15.118 + throw new Exception("unexpected value for " + label 15.119 + + ": expected " + expect 15.120 + + ": found " + found); 15.121 + } 15.122 + 15.123 + //--------------- 15.124 + 15.125 + /* 15.126 + * A custom class unknown to javac but nonetheless registered in the context. 15.127 + */ 15.128 + static class Demo { 15.129 + static void preRegister(Context context, final Counter counter) { 15.130 + context.put(Demo.class, new Context.Factory<Demo>() { 15.131 + public Demo make(Context c) { 15.132 + counter.count++; 15.133 + return new Demo(c); 15.134 + } 15.135 + }); 15.136 + } 15.137 + 15.138 + Demo(Context c) { 15.139 + c.put(Demo.class, this); 15.140 + } 15.141 + 15.142 + static Demo instance(Context context) { 15.143 + return context.get(Demo.class); 15.144 + } 15.145 + } 15.146 + 15.147 + /** 15.148 + * A custom version of a standard javac component. 15.149 + */ 15.150 + static class MyAttr extends Attr { 15.151 + static void preRegister(Context context, final Counter counter) { 15.152 + context.put(attrKey, new Context.Factory<Attr>() { 15.153 + public Attr make(Context c) { 15.154 + counter.count++; 15.155 + return new MyAttr(c); 15.156 + } 15.157 + }); 15.158 + } 15.159 + 15.160 + MyAttr(Context c) { 15.161 + super(c); 15.162 + } 15.163 + } 15.164 + 15.165 + static class Counter { 15.166 + int count; 15.167 + } 15.168 + 15.169 + //--------------- 15.170 + 15.171 + int round = 0; 15.172 + 15.173 + @Override 15.174 + public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 15.175 + round++; 15.176 + 15.177 + Context context = ((JavacProcessingEnvironment) processingEnv).getContext(); 15.178 + 15.179 + // verify items in context as expected 15.180 + check("Demo", Demo.instance(context), Demo.class); 15.181 + check("Attr", Attr.instance(context), MyAttr.class); 15.182 + 15.183 + // For a few rounds, generate new source files, so that we can check whether 15.184 + // values in the context are correctly handled in subsequent processing rounds 15.185 + if (round <= MAX_ROUNDS) { 15.186 + String pkg = "p"; 15.187 + String currClass = "Gen" + round; 15.188 + String curr = pkg + "." + currClass; 15.189 + String next = (pkg + ".Gen" + (round + 1)); 15.190 + StringBuilder text = new StringBuilder(); 15.191 + text.append("package ").append(pkg).append(";\n"); 15.192 + text.append("public class ").append(currClass).append(" {\n"); 15.193 + if (round < MAX_ROUNDS) 15.194 + text.append(" ").append(next).append(" x;\n"); 15.195 + text.append("}\n"); 15.196 + 15.197 + try { 15.198 + JavaFileObject fo = filer.createSourceFile(curr); 15.199 + Writer out = fo.openWriter(); 15.200 + try { 15.201 + out.write(text.toString()); 15.202 + } finally { 15.203 + out.close(); 15.204 + } 15.205 + } catch (IOException e) { 15.206 + throw new Error(e); 15.207 + } 15.208 + } 15.209 + 15.210 + return true; 15.211 + } 15.212 + 15.213 + void check(String label, Object o, Class<?> clazz) { 15.214 + if (o == null) 15.215 + throw new IllegalStateException(label + ": no item found"); 15.216 + if (!clazz.isAssignableFrom(o.getClass())) 15.217 + throw new IllegalStateException(label + ": unexpected class: " + o.getClass()); 15.218 + } 15.219 +}