1 /* 2 * Copyright (C) 2008 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 17 package util.build; 18 19 import dasm.DAsm; 20 import dasm.DasmError; 21 import dasm.Utils; 22 23 import java.io.BufferedReader; 24 import java.io.Closeable; 25 import java.io.File; 26 import java.io.FileInputStream; 27 import java.io.FileOutputStream; 28 import java.io.FileWriter; 29 import java.io.IOException; 30 import java.io.InputStreamReader; 31 import java.io.Reader; 32 33 class DasmBuildStep extends BuildStep { 34 35 36 boolean generate_linenum = false; 37 38 DasmBuildStep(BuildFile inputFile, BuildFile outputFile) { 39 super(inputFile, outputFile); 40 41 } 42 43 @Override 44 boolean build() { 45 if (super.build()) { 46 return assemble(inputFile.fileName); 47 } 48 return false; 49 } 50 51 private static Reader createReader(String fname) throws IOException { 52 FileInputStream fs = new FileInputStream(fname); 53 InputStreamReader ir; 54 ir = new InputStreamReader(fs); 55 return new BufferedReader(ir); 56 } 57 58 private boolean assemble(File file) { 59 DAsm dAsm = new DAsm(); 60 String fname = file.getAbsolutePath(); 61 62 // read and parse .d file 63 Reader inp = null; 64 try { 65 inp = createReader(fname); 66 dAsm.readD(inp, new File(fname).getName(), generate_linenum); 67 close(inp); 68 } catch(DasmError e) { 69 if(BuildDalvikSuite.DEBUG) 70 e.printStackTrace(); 71 System.err.println("DASM Error: " + e.getMessage()); 72 } catch(Exception e) { 73 if(BuildDalvikSuite.DEBUG) 74 e.printStackTrace(); 75 System.err.println("Exception <" + e.getClass().getName() + ">" + e.getMessage() + 76 " while reading and parsing " + fname); 77 return false; 78 79 } 80 finally { 81 close(inp); 82 } 83 84 if(dAsm.errorCount() > 0) { 85 System.err.println("Found " + dAsm.errorCount() + " errors " + 86 " while reading and parsing " + fname); 87 return false; 88 } 89 90 String class_path[] = Utils.getClassFieldFromString(dAsm.getClassName()); 91 String class_name = class_path[1]; 92 93 // determine where to place .dex file 94 String dest_dir = outputFile.folder.getAbsolutePath(); 95 if (class_path[0] != null) { 96 String class_dir = class_path[0].replaceAll("/|\\.", Character.toString(File.separatorChar)); 97 if (dest_dir != null) { 98 dest_dir = dest_dir + File.separator + class_dir; 99 } else { 100 dest_dir = class_dir; 101 } 102 } 103 104 File out_file = null; 105 106 if (dest_dir == null) { 107 out_file = new File(class_name + ".dex"); 108 } else { 109 out_file = new File(dest_dir, class_name + ".dex"); 110 111 // check that dest_dir exists 112 File dest = new File(dest_dir); 113 if (!dest.exists()) { 114 dest.mkdirs(); 115 } 116 117 if (!dest.isDirectory()) { 118 System.err.println("Cannot create directory " + dest_dir); 119 return false; 120 } 121 } 122 123 // write output 124 FileOutputStream outp = null; 125 126 try { 127 outp = new FileOutputStream(out_file); 128 dAsm.write(outp, null); 129 } catch(Exception e) { 130 if(BuildDalvikSuite.DEBUG) 131 e.printStackTrace(); 132 System.err.println("Exception <" + e.getClass().getName() + ">" + e.getMessage() + 133 " while writing " + out_file.getPath()); 134 135 close(outp); 136 137 out_file.delete(); 138 139 return false; 140 } 141 finally { 142 close(outp); 143 } 144 145 return true; 146 } 147 148 private static void close(Closeable c) { 149 if(c == null) 150 return; 151 try { 152 c.close(); 153 } catch(IOException e) { 154 155 } 156 } 157 158 @Override 159 public boolean equals(Object obj) { 160 if (super.equals(obj)) { 161 DasmBuildStep other = (DasmBuildStep) obj; 162 163 return inputFile.equals(other.inputFile) 164 && generate_linenum == other.generate_linenum 165 && outputFile.equals(other.outputFile); 166 } 167 return false; 168 } 169 170 @Override 171 public int hashCode() { 172 return inputFile.hashCode() ^ outputFile.hashCode() 173 ^ (generate_linenum ? 31 : 37); 174 } 175 } 176