001: /*******************************************************************************
002: * Copyright (c) 2007 BEA Systems, Inc.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * wharley@bea.com - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.apt.pluggable.tests.processors.genclass6;
011:
012: import java.io.IOException;
013: import java.io.PrintWriter;
014: import java.util.HashMap;
015: import java.util.Map;
016: import java.util.Set;
017:
018: import javax.annotation.processing.AbstractProcessor;
019: import javax.annotation.processing.Filer;
020: import javax.annotation.processing.Messager;
021: import javax.annotation.processing.ProcessingEnvironment;
022: import javax.annotation.processing.RoundEnvironment;
023: import javax.annotation.processing.SupportedAnnotationTypes;
024: import javax.annotation.processing.SupportedOptions;
025: import javax.annotation.processing.SupportedSourceVersion;
026: import javax.lang.model.SourceVersion;
027: import javax.lang.model.element.Element;
028: import javax.lang.model.element.TypeElement;
029: import javax.tools.Diagnostic;
030: import javax.tools.FileObject;
031: import javax.tools.JavaFileObject;
032: import javax.tools.StandardLocation;
033:
034: import org.eclipse.jdt.apt.pluggable.tests.annotations.GenClass6;
035:
036: /**
037: * A processor that reads the GenClass6 annotation and produces the specified Java type
038: */
039: @SupportedAnnotationTypes({"org.eclipse.jdt.apt.pluggable.tests.annotations.GenClass6"})
040: @SupportedSourceVersion(SourceVersion.RELEASE_6)
041: @SupportedOptions({})
042: public class GenClass6Proc extends AbstractProcessor {
043:
044: private ProcessingEnvironment _processingEnv;
045: private Messager _messager;
046: private Filer _filer;
047: private Map<String, Element> _classesToSummarize; // map of generated name to element that produced it
048:
049: /* (non-Javadoc)
050: * @see javax.annotation.processing.AbstractProcessor#init(javax.annotation.processing.ProcessingEnvironment)
051: */
052: @Override
053: public synchronized void init(ProcessingEnvironment processingEnv) {
054: super .init(processingEnv);
055: _processingEnv = processingEnv;
056: _filer = _processingEnv.getFiler();
057: _messager = _processingEnv.getMessager();
058: _classesToSummarize = new HashMap<String, Element>();
059: }
060:
061: /* (non-Javadoc)
062: * @see javax.annotation.processing.AbstractProcessor#process(java.util.Set, javax.annotation.processing.RoundEnvironment)
063: */
064: @Override
065: public boolean process(Set<? extends TypeElement> annotations,
066: RoundEnvironment roundEnv) {
067: if (roundEnv.processingOver() && !_classesToSummarize.isEmpty()) {
068: summarize();
069: } else if (!annotations.isEmpty()) {
070: round(annotations, roundEnv);
071: }
072: return true;
073: }
074:
075: /**
076: * Perform a round of processing
077: */
078: private void round(Set<? extends TypeElement> annotations,
079: RoundEnvironment roundEnv) {
080: TypeElement genClassAnno = annotations.iterator().next();
081: Set<? extends Element> annotatedEls = roundEnv
082: .getElementsAnnotatedWith(genClassAnno);
083: for (Element e : annotatedEls) {
084: GenClass6 genClassMirror = e.getAnnotation(GenClass6.class);
085: generateType(genClassMirror, e);
086: }
087: }
088:
089: /**
090: * @param genClassMirror
091: */
092: private void generateType(GenClass6 genClassMirror,
093: Element annotatedEl) {
094: // Collect and validate the parameters of the annotation
095: String pkg = null;
096: String name = null;
097: String method = null;
098: boolean summary = false;
099: int rounds = 1;
100: try {
101: pkg = genClassMirror.pkg();
102: name = genClassMirror.name();
103: method = genClassMirror.method();
104: summary = genClassMirror.summary();
105: rounds = genClassMirror.rounds();
106: } catch (Exception e) {
107: _messager.printMessage(Diagnostic.Kind.WARNING,
108: "Unable to read @GenClass6 annotation"
109: + e.getLocalizedMessage(), annotatedEl);
110: return;
111: }
112: if (name.length() == 0) {
113: // User hasn't specified name yet
114: _messager.printMessage(Diagnostic.Kind.WARNING,
115: "The name attribute is missing", annotatedEl);
116: return;
117: }
118: if (pkg == null) {
119: pkg = "";
120: }
121: String qname = (pkg.length() > 0) ? pkg + '.' + name : name;
122: if (method == null) {
123: method = "";
124: }
125:
126: // Get a writer
127: JavaFileObject jfo = null;
128: try {
129: jfo = _filer.createSourceFile(qname, annotatedEl);
130: } catch (IOException e) {
131: _messager.printMessage(Diagnostic.Kind.WARNING,
132: "Unable to open file for class " + qname,
133: annotatedEl);
134: return;
135: }
136: PrintWriter pw = null;
137: try {
138: pw = new PrintWriter(jfo.openWriter());
139: } catch (IOException e) {
140: _messager.printMessage(Diagnostic.Kind.WARNING,
141: "Unable to get writer for file " + jfo.getName());
142: return;
143: }
144:
145: // Generate the class
146: if (summary) {
147: _classesToSummarize.put(qname, annotatedEl);
148: }
149: pw.println("// Generated by " + this .getClass().getName());
150: pw.println("package " + pkg + ";");
151: if (rounds > 1) {
152: pw.println("import " + GenClass6.class.getCanonicalName()
153: + ";");
154: StringBuilder sb = new StringBuilder();
155: sb.append("@GenClass6(");
156: if (pkg.length() > 0) {
157: sb.append("pkg = \"");
158: sb.append(pkg);
159: sb.append("\", ");
160: }
161: sb.append("name = \"");
162: sb.append(name);
163: sb.append("Gen\"");
164: if (method.length() > 0) {
165: sb.append(", method = \"");
166: sb.append(method);
167: sb.append("\"");
168: }
169: if (--rounds > 1) {
170: sb.append(", rounds = ");
171: sb.append(rounds);
172: }
173: if (summary) {
174: sb.append(", summary = true");
175: }
176: sb.append(")");
177: pw.println(sb.toString());
178: }
179: pw.println("public class " + name + "{");
180: if (method != null && method.length() > 0) {
181: pw.println("\tpublic String " + method
182: + "() { return null; }");
183: }
184: pw.println("}");
185: pw.close();
186: }
187:
188: /**
189: * Generate the summary.txt file if requested
190: */
191: protected void summarize() {
192: PrintWriter pw = null;
193: try {
194: Element[] parents = new Element[_classesToSummarize.size()];
195: parents = _classesToSummarize.values().toArray(parents);
196: FileObject summaryFile = _filer.createResource(
197: StandardLocation.SOURCE_OUTPUT, "", "summary.txt",
198: parents);
199: pw = new PrintWriter(summaryFile.openWriter());
200: for (String clazz : _classesToSummarize.keySet()) {
201: pw.println(clazz);
202: }
203: pw.flush();
204: } catch (IOException e) {
205: _messager.printMessage(Diagnostic.Kind.ERROR,
206: "Unable to create summary.txt: "
207: + e.getLocalizedMessage());
208: } finally {
209: if (pw != null) {
210: pw.close();
211: }
212: }
213: }
214:
215: }
|