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.Task;
024: import org.apache.tools.ant.util.ClasspathUtils;
025: import org.apache.tools.ant.util.JavaEnvUtils;
026:
027: /**
028: * Creates the necessary compiler adapter, given basic criteria.
029: *
030: * @since Ant 1.3
031: */
032: public final class CompilerAdapterFactory {
033: private static final String MODERN_COMPILER = "com.sun.tools.javac.Main";
034:
035: /** This is a singleton -- can't create instances!! */
036: private CompilerAdapterFactory() {
037: }
038:
039: /**
040: * Based on the parameter passed in, this method creates the necessary
041: * factory desired.
042: *
043: * The current mapping for compiler names are as follows:
044: * <ul><li>jikes = jikes compiler
045: * <li>classic, javac1.1, javac1.2 = the standard compiler from JDK
046: * 1.1/1.2
047: * <li>modern, javac1.3, javac1.4, javac1.5 = the compiler of JDK 1.3+
048: * <li>jvc, microsoft = the command line compiler from Microsoft's SDK
049: * for Java / Visual J++
050: * <li>kjc = the kopi compiler</li>
051: * <li>gcj = the gcj compiler from gcc</li>
052: * <li>sj, symantec = the Symantec Java compiler</li>
053: * <li><i>a fully qualified classname</i> = the name of a compiler
054: * adapter
055: * </ul>
056: *
057: * @param compilerType either the name of the desired compiler, or the
058: * full classname of the compiler's adapter.
059: * @param task a task to log through.
060: * @return the compiler adapter
061: * @throws BuildException if the compiler type could not be resolved into
062: * a compiler adapter.
063: */
064: public static CompilerAdapter getCompiler(String compilerType,
065: Task task) throws BuildException {
066: boolean isClassicCompilerSupported = true;
067: //as new versions of java come out, add them to this test
068: if (!JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_2)
069: && !JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_3)) {
070: isClassicCompilerSupported = false;
071: }
072:
073: if (compilerType.equalsIgnoreCase("jikes")) {
074: return new Jikes();
075: }
076: if (compilerType.equalsIgnoreCase("extJavac")) {
077: return new JavacExternal();
078: }
079: if (compilerType.equalsIgnoreCase("classic")
080: || compilerType.equalsIgnoreCase("javac1.1")
081: || compilerType.equalsIgnoreCase("javac1.2")) {
082: if (isClassicCompilerSupported) {
083: return new Javac12();
084: } else {
085: task.log("This version of java does "
086: + "not support the classic "
087: + "compiler; upgrading to modern",
088: Project.MSG_WARN);
089: compilerType = "modern";
090: }
091: }
092: //on java<=1.3 the modern falls back to classic if it is not found
093: //but on java>=1.4 we just bail out early
094: if (compilerType.equalsIgnoreCase("modern")
095: || compilerType.equalsIgnoreCase("javac1.3")
096: || compilerType.equalsIgnoreCase("javac1.4")
097: || compilerType.equalsIgnoreCase("javac1.5")
098: || compilerType.equalsIgnoreCase("javac1.6")) {
099: // does the modern compiler exist?
100: if (doesModernCompilerExist()) {
101: return new Javac13();
102: } else {
103: if (isClassicCompilerSupported) {
104: task.log("Modern compiler not found - looking for "
105: + "classic compiler", Project.MSG_WARN);
106: return new Javac12();
107: } else {
108: throw new BuildException("Unable to find a javac "
109: + "compiler;\n" + MODERN_COMPILER
110: + " is not on the " + "classpath.\n"
111: + "Perhaps JAVA_HOME does not"
112: + " point to the JDK.\n"
113: + "It is currently set to \""
114: + JavaEnvUtils.getJavaHome() + "\"");
115: }
116: }
117: }
118:
119: if (compilerType.equalsIgnoreCase("jvc")
120: || compilerType.equalsIgnoreCase("microsoft")) {
121: return new Jvc();
122: }
123: if (compilerType.equalsIgnoreCase("kjc")) {
124: return new Kjc();
125: }
126: if (compilerType.equalsIgnoreCase("gcj")) {
127: return new Gcj();
128: }
129: if (compilerType.equalsIgnoreCase("sj")
130: || compilerType.equalsIgnoreCase("symantec")) {
131: return new Sj();
132: }
133: return resolveClassName(compilerType);
134: }
135:
136: /**
137: * query for the Modern compiler existing
138: * @return true if classic os on the classpath
139: */
140: private static boolean doesModernCompilerExist() {
141: try {
142: Class.forName(MODERN_COMPILER);
143: return true;
144: } catch (ClassNotFoundException cnfe) {
145: try {
146: ClassLoader cl = CompilerAdapterFactory.class
147: .getClassLoader();
148: if (cl != null) {
149: cl.loadClass(MODERN_COMPILER);
150: return true;
151: }
152: } catch (ClassNotFoundException cnfe2) {
153: // Ignore Exception
154: }
155: }
156: return false;
157: }
158:
159: /**
160: * Tries to resolve the given classname into a compiler adapter.
161: * Throws a fit if it can't.
162: *
163: * @param className The fully qualified classname to be created.
164: * @throws BuildException This is the fit that is thrown if className
165: * isn't an instance of CompilerAdapter.
166: */
167: private static CompilerAdapter resolveClassName(String className)
168: throws BuildException {
169: return (CompilerAdapter) ClasspathUtils.newInstance(className,
170: CompilerAdapterFactory.class.getClassLoader(),
171: CompilerAdapter.class);
172: }
173:
174: }
|