blob: 202f4121fc6037c2ac264452afcb93d6743c5673 [file] [log] [blame]
Mathew Inwood63956902018-07-09 15:07:56 +01001/*
2 * Copyright (C) 2018 The Android Open Source Project
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
17package com.android.javac;
18
19import com.google.common.io.Files;
20
21import org.apache.bcel.classfile.ClassParser;
22import org.apache.bcel.classfile.JavaClass;
23
24import java.io.File;
25import java.io.IOException;
26import java.io.InputStream;
27import java.net.URI;
28import java.util.ArrayList;
29import java.util.Arrays;
30import java.util.List;
31import java.util.Locale;
32
33import javax.tools.DiagnosticCollector;
34import javax.tools.JavaCompiler;
35import javax.tools.JavaFileObject;
36import javax.tools.SimpleJavaFileObject;
37import javax.tools.StandardJavaFileManager;
38import javax.tools.StandardLocation;
39import javax.tools.ToolProvider;
40
41/**
42 * Helper class for compiling snippets of Java source and providing access to the resulting class
43 * files.
44 */
45public class Javac {
46
47 private final JavaCompiler mJavac;
48 private final StandardJavaFileManager mFileMan;
49 private final List<JavaFileObject> mCompilationUnits;
50 private final File mClassOutDir;
51
52 public Javac() throws IOException {
53 mJavac = ToolProvider.getSystemJavaCompiler();
54 mFileMan = mJavac.getStandardFileManager(null, Locale.US, null);
55 mClassOutDir = Files.createTempDir();
56 mFileMan.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(mClassOutDir));
57 mFileMan.setLocation(StandardLocation.CLASS_PATH, Arrays.asList(mClassOutDir));
58 mCompilationUnits = new ArrayList<>();
59 }
60
61 private String classToFileName(String classname) {
62 return classname.replace('.', '/');
63 }
64
65 public Javac addSource(String classname, String contents) {
66 JavaFileObject java = new SimpleJavaFileObject(URI.create(
67 String.format("string:///%s.java", classToFileName(classname))),
68 JavaFileObject.Kind.SOURCE
69 ){
70 @Override
71 public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
72 return contents;
73 }
74 };
75 mCompilationUnits.add(java);
76 return this;
77 }
78
79 public boolean compile() {
80 JavaCompiler.CompilationTask task = mJavac.getTask(
81 null,
82 mFileMan,
83 null,
84 null,
85 null,
86 mCompilationUnits);
87 return task.call();
88 }
89
90 public InputStream getClassFile(String classname) throws IOException {
91 Iterable<? extends JavaFileObject> objs = mFileMan.getJavaFileObjects(
92 new File(mClassOutDir, String.format("%s.class", classToFileName(classname))));
93 if (!objs.iterator().hasNext()) {
94 return null;
95 }
96 return objs.iterator().next().openInputStream();
97 }
98
99 public JavaClass getCompiledClass(String classname) throws IOException {
100 return new ClassParser(getClassFile(classname),
101 String.format("%s.class", classToFileName(classname))).parse();
102 }
103}