aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/compilers/AptCompilerAdapter.java
blob: 9503ac0257e5f84e9caae018d63a9f76a78f7f1c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

package org.apache.tools.ant.taskdefs.compilers;

import java.io.File;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.Vector;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Apt;
import org.apache.tools.ant.types.Commandline;
import org.apache.tools.ant.types.Path;


/**
 * <p>The implementation of the apt compiler for JDK 1.5.</p>
 *
 * <p>As usual, the low level entry points for Java tools are neither documented or
 * stable; this entry point may change from that of 1.5.0_01-b08 without any
 * warning at all. The IDE decompile of the tool entry points is as follows:</p>
 * <pre>
 * public class Main {
 * public Main() ;
 *
 * public static transient void main(String... strings);
 *
 * public static transient int process(String... strings);
 *
 * public static transient int process(PrintWriter printWriter,
 *      String... strings);
 * public static transient int process(
 *      AnnotationProcessorFactory annotationProcessorFactory,
 *      String... strings);
 *
 * public static transient int process(
 *      AnnotationProcessorFactory annotationProcessorFactory,
 *      PrintWriter printWriter,
 *      String... strings);
 * private static transient int processing(
 *      AnnotationProcessorFactory annotationProcessorFactory,
 *      PrintWriter printWriter,
 *      String... strings) ;
 * }
 * </pre>
 *
 * This Adapter is designed to run Apt in-JVM, an option that is not actually
 * exposed to end-users, because it was too brittle during beta testing; classpath
 * problems being the core issue.
 *
 * @since Ant 1.7
 */
public class AptCompilerAdapter extends DefaultCompilerAdapter {

    /**
     * Integer returned by the Apt compiler to indicate success.
     */
    private static final int APT_COMPILER_SUCCESS = 0;
    /**
     * class in tools.jar that implements APT
     */
    public static final String APT_ENTRY_POINT = "com.sun.tools.apt.Main";

    /**
     * method used to compile.
     */
    public static final String APT_METHOD_NAME = "process";

    /**
     * Get the facade task that fronts this adapter
     *
     * @return task instance
     * @see DefaultCompilerAdapter#getJavac()
     */
    protected Apt getApt() {
        return (Apt) getJavac();
    }

    /**
     * Using the front end arguments, set up the command line to run Apt
     *
     * @param apt task
     * @param cmd command that is set up with the various switches from the task
     *            options
     */
    static void setAptCommandlineSwitches(final Apt apt, final Commandline cmd) {

        if (!apt.isCompile()) {
            cmd.createArgument().setValue("-nocompile");
        }

        // Process the factory class
        final String factory = apt.getFactory();
        if (factory != null) {
            cmd.createArgument().setValue("-factory");
            cmd.createArgument().setValue(factory);
        }

        // Process the factory path
        final Path factoryPath = apt.getFactoryPath();
        if (factoryPath != null) {
            cmd.createArgument().setValue("-factorypath");
            cmd.createArgument().setPath(factoryPath);
        }

        final File preprocessDir = apt.getPreprocessDir();
        if (preprocessDir != null) {
            cmd.createArgument().setValue("-s");
            cmd.createArgument().setFile(preprocessDir);
        }

        // Process the processor options
        final Vector options = apt.getOptions();
        final Enumeration elements = options.elements();
        Apt.Option opt;
        StringBuffer arg = null;
        while (elements.hasMoreElements()) {
            opt = (Apt.Option) elements.nextElement();
            arg = new StringBuffer();
            arg.append("-A").append(opt.getName());
            if (opt.getValue() != null) {
                arg.append("=").append(opt.getValue());
            }
            cmd.createArgument().setValue(arg.toString());
        }
    }

    /**
     * using our front end task, set up the command line switches
     *
     * @param cmd command line to set up
     */
    protected void setAptCommandlineSwitches(final Commandline cmd) {
        final Apt apt = getApt();
        setAptCommandlineSwitches(apt, cmd);
    }

    /**
     * Run the compilation.
     * @return true on success.
     * @throws BuildException if the compilation has problems.
     */
    public boolean execute() throws BuildException {
        attributes.log("Using apt compiler", Project.MSG_VERBOSE);
        //set up the javac options
        final Commandline cmd = setupModernJavacCommand();
        //then add the Apt options
        setAptCommandlineSwitches(cmd);

        //finally invoke APT
        // Use reflection to be able to build on all JDKs:
        try {
            final Class c = Class.forName(APT_ENTRY_POINT);
            final Object compiler = c.newInstance();
            final Method compile = c.getMethod(APT_METHOD_NAME,
                    new Class[]{(new String[]{}).getClass()});
            final int result = ((Integer) compile.invoke
                    (compiler, new Object[]{cmd.getArguments()}))
                    .intValue();
            return (result == APT_COMPILER_SUCCESS);
        } catch (final BuildException be) {
            //rethrow build exceptions
            throw be;
        } catch (final Exception ex) {
            //cast everything else to a build exception
            throw new BuildException("Error starting apt compiler",
                    ex, location);
        }
    }
}