1f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project/*
2f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project * Copyright (C) 2009 The Android Open Source Project
3f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project *
4f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project * you may not use this file except in compliance with the License.
6f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project * You may obtain a copy of the License at
7f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project *
8f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project *
10f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project * See the License for the specific language governing permissions and
14f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project * limitations under the License.
15f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project */
16f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
17f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectpackage dex.reader.util;
18f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
19f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport java.io.IOException;
20f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport java.util.Arrays;
21f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport java.util.Collections;
22f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport java.util.HashSet;
23f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport java.util.Set;
24f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
25f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport javax.tools.Diagnostic;
26f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport javax.tools.DiagnosticCollector;
27f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport javax.tools.JavaCompiler;
28f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport javax.tools.JavaFileObject;
29f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport javax.tools.StandardJavaFileManager;
30f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport javax.tools.ToolProvider;
31f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport javax.tools.JavaCompiler.CompilationTask;
32f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
33f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport com.android.dx.dex.cf.CfOptions;
34f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport com.android.dx.dex.cf.CfTranslator;
35f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport com.android.dx.dex.file.ClassDefItem;
36f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport com.android.dx.dex.file.DexFile;
37f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
38f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport dex.reader.DexBuffer;
39f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectimport dex.reader.DexFileReader;
40f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
41f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Projectpublic class JavaSourceToDexUtil {
42f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
43f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    public dex.structure.DexFile getFrom(JavaSource source) throws IOException{
44f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        return getAllFrom(Collections.singleton(source));
45f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    }
46f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
47f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    public dex.structure.DexFile getFrom(JavaSource... source) throws IOException{
48f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        return getAllFrom(new HashSet<JavaSource>(Arrays.asList(source)));
49f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    }
50f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
51f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    public dex.structure.DexFile getAllFrom(Set<JavaSource> sources) throws IOException{
52f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        return getFrom(sources, null);
53f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    }
54f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
55f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    /**
56f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project     * Converts java source code to a {@link dex.structure.DexFile} loaded by
57f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project     * {@link DexFileReader}. Converts only classes with the specified name in
58f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project     * classesToDex or all classes if classesToDex is null.
59f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project     *
60f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project     * @throws IOException
61f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project     */
62f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    public dex.structure.DexFile getFrom(Set<JavaSource> sources,
63f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project            Set<String> classesToDex) throws IOException {
64f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        Set<MemoryByteCode> byteCodeInMemory = compileToByteCode(sources);
65f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
66f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        byte[] dexCode = convertToDexCode(byteCodeInMemory, classesToDex);
67f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        DexBuffer dexBuffer = new DexBuffer(dexCode);
68f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        DexFileReader reader = new DexFileReader();
69f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        return reader.read(dexBuffer);
70f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    }
71f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
72f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
73f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    private byte[] convertToDexCode(Set<MemoryByteCode> byteCodeInMemory, Set<String> classNamesToDex) throws IOException {
74f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        CfOptions cfOptions = new CfOptions();
75f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        DexFile dexFile = new DexFile();
76f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        for (MemoryByteCode memoryByteCode : byteCodeInMemory) {
77f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project            if(classNamesToDex == null || classNamesToDex.contains(memoryByteCode.getName())) {
78f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project            ClassDefItem classDefItem = CfTranslator.translate(memoryByteCode.getName().replace('.', '/') +".class", memoryByteCode.getBytes(), cfOptions);
79f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project            dexFile.add(classDefItem);
80f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project            }
81f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        }
82f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        return dexFile.toDex(null, false);
83f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    }
84f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
85f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
86f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    public Set<MemoryByteCode> compileToByteCode(Set<JavaSource> source) {
87f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
88f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        DiagnosticCollector<JavaFileObject> diacol = new DiagnosticCollector<JavaFileObject>();
89f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        StandardJavaFileManager sjfm = javac.getStandardFileManager(diacol,
90f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project                null, null);
91f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        SpecialJavaFileManager xfm = new SpecialJavaFileManager(sjfm);
92f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
93f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        CompilationTask compile = javac.getTask(null, xfm, diacol, Arrays
94f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project                .asList(new String[] {"-classpath", "."}), null, source);
95f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        boolean success = compile.call();
96f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        if(!success) {
97f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        StringBuilder errorMessage = new StringBuilder();
98f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project            for (Diagnostic<? extends JavaFileObject> dia : diacol.getDiagnostics()) {
99f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project                errorMessage.append(dia);
100f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project            }
101f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project            throw new IllegalStateException(errorMessage.toString());
102f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        }
103f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project        return xfm.getAllMemoryByteCodes();
104f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project    }
105f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project}
106f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
107f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
108f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
109f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
110f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
111f8057104af9cae031b544e971a52adafa7c0d9eThe Android Open Source Project
112