1 | /*
|
---|
2 | * Copyright 2001-2004 The Apache Software Foundation
|
---|
3 | *
|
---|
4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
---|
5 | * you may not use this file except in compliance with the License.
|
---|
6 | * You may obtain a copy of the License at
|
---|
7 | *
|
---|
8 | * http://www.apache.org/licenses/LICENSE-2.0
|
---|
9 | *
|
---|
10 | * Unless required by applicable law or agreed to in writing, software
|
---|
11 | * distributed under the License is distributed on an "AS IS" BASIS,
|
---|
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
---|
13 | * See the License for the specific language governing permissions and
|
---|
14 | * limitations under the License.
|
---|
15 | *
|
---|
16 | */
|
---|
17 |
|
---|
18 | package org.apache.tools.ant.taskdefs.compilers;
|
---|
19 |
|
---|
20 | import org.apache.tools.ant.BuildException;
|
---|
21 | import org.apache.tools.ant.Project;
|
---|
22 | import org.apache.tools.ant.Task;
|
---|
23 | import org.apache.tools.ant.util.JavaEnvUtils;
|
---|
24 |
|
---|
25 | /**
|
---|
26 | * Creates the necessary compiler adapter, given basic criteria.
|
---|
27 | *
|
---|
28 | * @since Ant 1.3
|
---|
29 | */
|
---|
30 | public class CompilerAdapterFactory {
|
---|
31 | private static final String MODERN_COMPILER = "com.sun.tools.javac.Main";
|
---|
32 |
|
---|
33 | /** This is a singleton -- can't create instances!! */
|
---|
34 | private CompilerAdapterFactory() {
|
---|
35 | }
|
---|
36 |
|
---|
37 | /**
|
---|
38 | * Based on the parameter passed in, this method creates the necessary
|
---|
39 | * factory desired.
|
---|
40 | *
|
---|
41 | * The current mapping for compiler names are as follows:
|
---|
42 | * <ul><li>jikes = jikes compiler
|
---|
43 | * <li>classic, javac1.1, javac1.2 = the standard compiler from JDK
|
---|
44 | * 1.1/1.2
|
---|
45 | * <li>modern, javac1.3, javac1.4, javac1.5 = the compiler of JDK 1.3+
|
---|
46 | * <li>jvc, microsoft = the command line compiler from Microsoft's SDK
|
---|
47 | * for Java / Visual J++
|
---|
48 | * <li>kjc = the kopi compiler</li>
|
---|
49 | * <li>gcj = the gcj compiler from gcc</li>
|
---|
50 | * <li>sj, symantec = the Symantec Java compiler</li>
|
---|
51 | * <li><i>a fully qualified classname</i> = the name of a compiler
|
---|
52 | * adapter
|
---|
53 | * </ul>
|
---|
54 | *
|
---|
55 | * @param compilerType either the name of the desired compiler, or the
|
---|
56 | * full classname of the compiler's adapter.
|
---|
57 | * @param task a task to log through.
|
---|
58 | * @throws BuildException if the compiler type could not be resolved into
|
---|
59 | * a compiler adapter.
|
---|
60 | */
|
---|
61 | public static CompilerAdapter getCompiler(String compilerType, Task task)
|
---|
62 | throws BuildException {
|
---|
63 | boolean isClassicCompilerSupported = true;
|
---|
64 | //as new versions of java come out, add them to this test
|
---|
65 | if (!JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_1)
|
---|
66 | && !JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_2)
|
---|
67 | && !JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_3)) {
|
---|
68 | isClassicCompilerSupported = false;
|
---|
69 | }
|
---|
70 |
|
---|
71 | if (compilerType.equalsIgnoreCase("jikes")) {
|
---|
72 | return new Jikes();
|
---|
73 | }
|
---|
74 | if (compilerType.equalsIgnoreCase("extJavac")) {
|
---|
75 | return new JavacExternal();
|
---|
76 | }
|
---|
77 | if (compilerType.equalsIgnoreCase("classic")
|
---|
78 | || compilerType.equalsIgnoreCase("javac1.1")
|
---|
79 | || compilerType.equalsIgnoreCase("javac1.2")) {
|
---|
80 | if (isClassicCompilerSupported) {
|
---|
81 | return new Javac12();
|
---|
82 | } else {
|
---|
83 | task.log("This version of java does "
|
---|
84 | + "not support the classic "
|
---|
85 | + "compiler; upgrading to modern",
|
---|
86 | Project.MSG_WARN);
|
---|
87 | compilerType = "modern";
|
---|
88 | }
|
---|
89 | }
|
---|
90 | //on java<=1.3 the modern falls back to classic if it is not found
|
---|
91 | //but on java>=1.4 we just bail out early
|
---|
92 | if (compilerType.equalsIgnoreCase("modern")
|
---|
93 | || compilerType.equalsIgnoreCase("javac1.3")
|
---|
94 | || compilerType.equalsIgnoreCase("javac1.4")
|
---|
95 | || compilerType.equalsIgnoreCase("javac1.5")) {
|
---|
96 | // does the modern compiler exist?
|
---|
97 | if (doesModernCompilerExist()) {
|
---|
98 | return new Javac13();
|
---|
99 | } else {
|
---|
100 | if (isClassicCompilerSupported) {
|
---|
101 | task.log("Modern compiler not found - looking for "
|
---|
102 | + "classic compiler", Project.MSG_WARN);
|
---|
103 | return new Javac12();
|
---|
104 | } else {
|
---|
105 | throw new BuildException("Unable to find a javac "
|
---|
106 | + "compiler;\n"
|
---|
107 | + MODERN_COMPILER
|
---|
108 | + " is not on the "
|
---|
109 | + "classpath.\n"
|
---|
110 | + "Perhaps JAVA_HOME does not"
|
---|
111 | + " point to the JDK");
|
---|
112 | }
|
---|
113 | }
|
---|
114 | }
|
---|
115 |
|
---|
116 | if (compilerType.equalsIgnoreCase("jvc")
|
---|
117 | || compilerType.equalsIgnoreCase("microsoft")) {
|
---|
118 | return new Jvc();
|
---|
119 | }
|
---|
120 | if (compilerType.equalsIgnoreCase("kjc")) {
|
---|
121 | return new Kjc();
|
---|
122 | }
|
---|
123 | if (compilerType.equalsIgnoreCase("gcj")) {
|
---|
124 | return new Gcj();
|
---|
125 | }
|
---|
126 | if (compilerType.equalsIgnoreCase("sj")
|
---|
127 | || compilerType.equalsIgnoreCase("symantec")) {
|
---|
128 | return new Sj();
|
---|
129 | }
|
---|
130 | return resolveClassName(compilerType);
|
---|
131 | }
|
---|
132 |
|
---|
133 | /**
|
---|
134 | * query for the Modern compiler existing
|
---|
135 | * @return true if classic os on the classpath
|
---|
136 | */
|
---|
137 | private static boolean doesModernCompilerExist() {
|
---|
138 | try {
|
---|
139 | Class.forName(MODERN_COMPILER);
|
---|
140 | return true;
|
---|
141 | } catch (ClassNotFoundException cnfe) {
|
---|
142 | try {
|
---|
143 | ClassLoader cl = CompilerAdapterFactory.class.getClassLoader();
|
---|
144 | if (cl != null) {
|
---|
145 | cl.loadClass(MODERN_COMPILER);
|
---|
146 | return true;
|
---|
147 | }
|
---|
148 | } catch (ClassNotFoundException cnfe2) {
|
---|
149 | }
|
---|
150 | }
|
---|
151 | return false;
|
---|
152 | }
|
---|
153 |
|
---|
154 | /**
|
---|
155 | * Tries to resolve the given classname into a compiler adapter.
|
---|
156 | * Throws a fit if it can't.
|
---|
157 | *
|
---|
158 | * @param className The fully qualified classname to be created.
|
---|
159 | * @throws BuildException This is the fit that is thrown if className
|
---|
160 | * isn't an instance of CompilerAdapter.
|
---|
161 | */
|
---|
162 | private static CompilerAdapter resolveClassName(String className)
|
---|
163 | throws BuildException {
|
---|
164 | try {
|
---|
165 | Class c = Class.forName(className);
|
---|
166 | Object o = c.newInstance();
|
---|
167 | return (CompilerAdapter) o;
|
---|
168 | } catch (ClassNotFoundException cnfe) {
|
---|
169 | throw new BuildException("Compiler Adapter '" + className
|
---|
170 | + "' can\'t be found.", cnfe);
|
---|
171 | } catch (ClassCastException cce) {
|
---|
172 | throw new BuildException(className + " isn\'t the classname of "
|
---|
173 | + "a compiler adapter.", cce);
|
---|
174 | } catch (Throwable t) {
|
---|
175 | // for all other possibilities
|
---|
176 | throw new BuildException("Compiler Adapter " + className
|
---|
177 | + " caused an interesting exception.", t);
|
---|
178 | }
|
---|
179 | }
|
---|
180 |
|
---|
181 | }
|
---|