KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > apt > dispatch > BatchAnnotationProcessorManager


1 /*******************************************************************************
2  * Copyright (c) 2005, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.compiler.apt.dispatch;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Iterator JavaDoc;
15 import java.util.List JavaDoc;
16 import java.util.ServiceConfigurationError JavaDoc;
17 import java.util.ServiceLoader JavaDoc;
18
19 import javax.annotation.processing.Processor;
20 import javax.tools.StandardLocation;
21
22 import org.eclipse.jdt.internal.compiler.batch.Main;
23 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
24
25 /**
26  * Java 6 annotation processor manager used when compiling from the command line
27  * or via the javax.tools.JavaCompiler interface.
28  * @see org.eclipse.jdt.internal.compiler.apt.ide.dispatch.IdeAnnotationProcessorManager
29  */

30 public class BatchAnnotationProcessorManager extends BaseAnnotationProcessorManager
31 {
32     
33     /**
34      * Processors that have been set by calling CompilationTask.setProcessors().
35      */

36     private List JavaDoc<Processor> _setProcessors = null;
37     private Iterator JavaDoc<Processor> _setProcessorIter = null;
38     
39     /**
40      * Processors named with the -processor option on the command line.
41      */

42     private List JavaDoc<String JavaDoc> _commandLineProcessors;
43     private Iterator JavaDoc<String JavaDoc> _commandLineProcessorIter = null;
44     
45     private ServiceLoader JavaDoc<Processor> _serviceLoader = null;
46     private Iterator JavaDoc<Processor> _serviceLoaderIter;
47     
48     private ClassLoader JavaDoc _procLoader;
49     
50     // Set this to true in order to trace processor discovery when -XprintProcessorInfo is specified
51
private final static boolean VERBOSE_PROCESSOR_DISCOVERY = true;
52     private boolean _printProcessorDiscovery = false;
53     
54     /**
55      * Zero-arg constructor so this object can be easily created via reflection.
56      * A BatchAnnotationProcessorManager cannot be used until its
57      * {@link #configure(Main, String[])} method has been called.
58      */

59     public BatchAnnotationProcessorManager()
60     {
61     }
62
63     @Override JavaDoc
64     public void configure(Object JavaDoc batchCompiler, String JavaDoc[] commandLineArguments) {
65         if (null != _processingEnv) {
66             throw new IllegalStateException JavaDoc(
67                     "Calling configure() more than once on an AnnotationProcessorManager is not supported"); //$NON-NLS-1$
68
}
69         BatchProcessingEnvImpl processingEnv = new BatchProcessingEnvImpl(this, (Main) batchCompiler, commandLineArguments);
70         _processingEnv = processingEnv;
71         _procLoader = processingEnv.getFileManager().getClassLoader(StandardLocation.ANNOTATION_PROCESSOR_PATH);
72         parseCommandLine(commandLineArguments);
73         _round = 0;
74     }
75     
76     /**
77      * If a -processor option was specified in command line arguments,
78      * parse it into a list of qualified classnames.
79      * @param commandLineArguments contains one string for every space-delimited token on the command line
80      * @return a list of qualified classnames, or null if there was no -processor option.
81      */

82     private void parseCommandLine(String JavaDoc[] commandLineArguments) {
83         List JavaDoc<String JavaDoc> commandLineProcessors = null;
84         for (int i = 0; i < commandLineArguments.length; ++i) {
85             String JavaDoc option = commandLineArguments[i];
86             if ("-XprintProcessorInfo".equals(option)) { //$NON-NLS-1$
87
_printProcessorInfo = true;
88                 _printProcessorDiscovery = VERBOSE_PROCESSOR_DISCOVERY;
89             }
90             else if ("-XprintRounds".equals(option)) { //$NON-NLS-1$
91
_printRounds = true;
92             }
93             else if ("-processor".equals(option)) { //$NON-NLS-1$
94
commandLineProcessors = new ArrayList JavaDoc<String JavaDoc>();
95                 String JavaDoc procs = commandLineArguments[++i];
96                 for (String JavaDoc proc : procs.split(",")) { //$NON-NLS-1$
97
commandLineProcessors.add(proc);
98                 }
99                 break;
100             }
101         }
102         _commandLineProcessors = commandLineProcessors;
103         if (null != _commandLineProcessors) {
104             _commandLineProcessorIter = _commandLineProcessors.iterator();
105         }
106     }
107
108     @Override JavaDoc
109     public ProcessorInfo discoverNextProcessor() {
110         if (null != _setProcessors) {
111             // If setProcessors() was called, use that list until it's empty and then stop.
112
if (_setProcessorIter.hasNext()) {
113                 Processor p = _setProcessorIter.next();
114                 p.init(_processingEnv);
115                 ProcessorInfo pi = new ProcessorInfo(p);
116                 _processors.add(pi);
117                 if (_printProcessorDiscovery && null != _out) {
118                     _out.println("API specified processor: " + pi); //$NON-NLS-1$
119
}
120                 return pi;
121             }
122             return null;
123         }
124         
125         if (null != _commandLineProcessors) {
126             // If there was a -processor option, iterate over processor names,
127
// creating and initializing processors, until no more names are found, then stop.
128
if (_commandLineProcessorIter.hasNext()) {
129                 String JavaDoc proc = _commandLineProcessorIter.next();
130                 try {
131                     Class JavaDoc<?> clazz = _procLoader.loadClass(proc);
132                     Object JavaDoc o = clazz.newInstance();
133                     Processor p = (Processor) o;
134                     p.init(_processingEnv);
135                     ProcessorInfo pi = new ProcessorInfo(p);
136                     _processors.add(pi);
137                     if (_printProcessorDiscovery && null != _out) {
138                         _out.println("Command line specified processor: " + pi); //$NON-NLS-1$
139
}
140                     return pi;
141                 } catch (Exception JavaDoc e) {
142                     // TODO: better error handling
143
throw new AbortCompilation(null, e);
144                 }
145             }
146             return null;
147         }
148         
149         // if no processors were explicitly specified with setProcessors()
150
// or the command line, search the processor path with ServiceLoader.
151
if (null == _serviceLoader ) {
152             _serviceLoader = ServiceLoader.load(Processor.class, _procLoader);
153             _serviceLoaderIter = _serviceLoader.iterator();
154         }
155         try {
156             if (_serviceLoaderIter.hasNext()) {
157                 Processor p = _serviceLoaderIter.next();
158                 p.init(_processingEnv);
159                 ProcessorInfo pi = new ProcessorInfo(p);
160                 _processors.add(pi);
161                 if (_printProcessorDiscovery && null != _out) {
162                     StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
163                     sb.append("Discovered processor service "); //$NON-NLS-1$
164
sb.append(pi);
165                     sb.append("\n supporting "); //$NON-NLS-1$
166
sb.append(pi.getSupportedAnnotationTypesAsString());
167                     sb.append("\n in "); //$NON-NLS-1$
168
sb.append(getProcessorLocation(p));
169                     _out.println(sb.toString());
170                 }
171                 return pi;
172             }
173         } catch (ServiceConfigurationError JavaDoc e) {
174             // TODO: better error handling
175
throw new AbortCompilation(null, e);
176         }
177         return null;
178     }
179     
180     /**
181      * Used only for debugging purposes. Generates output like "file:jar:D:/temp/jarfiles/myJar.jar!/".
182      * Surely this code already exists in several hundred other places?
183      * @return the location whence a processor class was loaded.
184      */

185     private String JavaDoc getProcessorLocation(Processor p) {
186         // Get the classname in a form that can be passed to ClassLoader.getResource(),
187
// e.g., "pa/pb/pc/Outer$Inner.class"
188
boolean isMember = false;
189         Class JavaDoc<?> outerClass = p.getClass();
190         StringBuilder JavaDoc innerName = new StringBuilder JavaDoc();
191         while (outerClass.isMemberClass()) {
192             innerName.insert(0, outerClass.getSimpleName());
193             innerName.insert(0, '$');
194             isMember = true;
195             outerClass = outerClass.getEnclosingClass();
196         }
197         String JavaDoc path = outerClass.getName();
198         path = path.replace('.', '/');
199         if (isMember) {
200             path = path + innerName;
201         }
202         path = path + ".class"; //$NON-NLS-1$
203

204         // Find the URL for the class resource and strip off the resource name itself
205
String JavaDoc location = _procLoader.getResource(path).toString();
206         if (location.endsWith(path)) {
207             location = location.substring(0, location.length() - path.length());
208         }
209         return location;
210     }
211
212     @Override JavaDoc
213     public void reportProcessorException(Processor p, Exception JavaDoc e) {
214         // TODO: if (verbose) report the processor
215
throw new AbortCompilation(null, e);
216     }
217     
218     @Override JavaDoc
219     public void setProcessors(Object JavaDoc[] processors) {
220         if (!_isFirstRound) {
221             throw new IllegalStateException JavaDoc("setProcessors() cannot be called after processing has begun"); //$NON-NLS-1$
222
}
223         // Cast all the processors here, rather than failing later.
224
// But don't call init() until the processor is actually needed.
225
_setProcessors = new ArrayList JavaDoc<Processor>(processors.length);
226         for (Object JavaDoc o : processors) {
227             Processor p = (Processor)o;
228             _setProcessors.add(p);
229         }
230         _setProcessorIter = _setProcessors.iterator();
231
232         // processors set this way take precedence over anything on the command line
233
_commandLineProcessors = null;
234         _commandLineProcessorIter = null;
235     }
236
237 }
238
Popular Tags