001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.tools.ant.taskdefs.compilers;
020:
021: import org.apache.tools.ant.BuildException;
022: import org.apache.tools.ant.Project;
023: import org.apache.tools.ant.taskdefs.Apt;
024: import org.apache.tools.ant.types.Commandline;
025: import org.apache.tools.ant.types.Path;
026:
027: import java.io.File;
028: import java.lang.reflect.Method;
029: import java.util.Enumeration;
030: import java.util.Vector;
031:
032: /**
033: * The implementation of the apt compiler for JDK 1.5
034: * <p/>
035: * As usual, the low level entry points for Java tools are neither documented or
036: * stable; this entry point may change from that of 1.5.0_01-b08 without any
037: * warning at all. The IDE decompile of the tool entry points is as follows:
038: * <pre>
039: * public class Main {
040: * public Main() ;
041: * <p/>
042: * public static transient void main(String... strings) ;
043: * <p/>
044: * public static transient int process(String... strings);
045: * <p/>
046: * public static transient int process(PrintWriter printWriter,
047: * String... strings) ;
048: * public static transient int process(
049: * AnnotationProcessorFactory annotationProcessorFactory,
050: * String... strings) ;
051: * <p/>
052: * public static transient int process(
053: * AnnotationProcessorFactory annotationProcessorFactory,
054: * PrintWriter printWriter,
055: * String... strings);
056: * private static transient int processing(
057: * AnnotationProcessorFactory annotationProcessorFactory,
058: * PrintWriter printWriter,
059: * String... strings) ;
060: * }
061: * </pre>
062: *
063: * This Adapter is designed to run Apt in-JVM, an option that is not actually
064: * exposed to end-users, because it was too brittle during beta testing; classpath
065: * problems being the core issue.
066: *
067: *
068: *
069: * @since Ant 1.7
070: */
071: public class AptCompilerAdapter extends DefaultCompilerAdapter {
072:
073: /**
074: * Integer returned by the Apt compiler to indicate success.
075: */
076: private static final int APT_COMPILER_SUCCESS = 0;
077: /**
078: * class in tools.jar that implements APT
079: */
080: public static final String APT_ENTRY_POINT = "com.sun.tools.apt.Main";
081:
082: /**
083: * method used to compile.
084: */
085: public static final String APT_METHOD_NAME = "process";
086:
087: /**
088: * Get the facade task that fronts this adapter
089: *
090: * @return task instance
091: * @see DefaultCompilerAdapter#getJavac()
092: */
093: protected Apt getApt() {
094: return (Apt) getJavac();
095: }
096:
097: /**
098: * Using the front end arguments, set up the command line to run Apt
099: *
100: * @param apt task
101: * @param cmd command that is set up with the various switches from the task
102: * options
103: */
104: static void setAptCommandlineSwitches(Apt apt, Commandline cmd) {
105:
106: if (!apt.isCompile()) {
107: cmd.createArgument().setValue("-nocompile");
108: }
109:
110: // Process the factory class
111: String factory = apt.getFactory();
112: if (factory != null) {
113: cmd.createArgument().setValue("-factory");
114: cmd.createArgument().setValue(factory);
115: }
116:
117: // Process the factory path
118: Path factoryPath = apt.getFactoryPath();
119: if (factoryPath != null) {
120: cmd.createArgument().setValue("-factorypath");
121: cmd.createArgument().setPath(factoryPath);
122: }
123:
124: File preprocessDir = apt.getPreprocessDir();
125: if (preprocessDir != null) {
126: cmd.createArgument().setValue("-s");
127: cmd.createArgument().setFile(preprocessDir);
128: }
129:
130: // Process the processor options
131: Vector options = apt.getOptions();
132: Enumeration elements = options.elements();
133: Apt.Option opt;
134: StringBuffer arg = null;
135: while (elements.hasMoreElements()) {
136: opt = (Apt.Option) elements.nextElement();
137: arg = new StringBuffer();
138: arg.append("-A").append(opt.getName());
139: if (opt.getValue() != null) {
140: arg.append("=").append(opt.getValue());
141: }
142: cmd.createArgument().setValue(arg.toString());
143: }
144: }
145:
146: /**
147: * using our front end task, set up the command line switches
148: *
149: * @param cmd command line to set up
150: */
151: protected void setAptCommandlineSwitches(Commandline cmd) {
152: Apt apt = getApt();
153: setAptCommandlineSwitches(apt, cmd);
154: }
155:
156: /**
157: * Run the compilation.
158: * @return true on success.
159: * @throws BuildException if the compilation has problems.
160: */
161: public boolean execute() throws BuildException {
162: attributes.log("Using apt compiler", Project.MSG_VERBOSE);
163: //set up the javac options
164: Commandline cmd = setupModernJavacCommand();
165: //then add the Apt options
166: setAptCommandlineSwitches(cmd);
167:
168: //finally invoke APT
169: // Use reflection to be able to build on all JDKs:
170: try {
171: Class c = Class.forName(APT_ENTRY_POINT);
172: Object compiler = c.newInstance();
173: Method compile = c.getMethod(APT_METHOD_NAME,
174: new Class[] { (new String[] {}).getClass() });
175: int result = ((Integer) compile.invoke(compiler,
176: new Object[] { cmd.getArguments() })).intValue();
177: return (result == APT_COMPILER_SUCCESS);
178: } catch (BuildException be) {
179: //rethrow build exceptions
180: throw be;
181: } catch (Exception ex) {
182: //cast everything else to a build exception
183: throw new BuildException("Error starting apt compiler", ex,
184: location);
185: }
186: }
187: }
|