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 
DasmBuildStep(BuildFile inputFile, BuildFile outputFile)38     DasmBuildStep(BuildFile inputFile, BuildFile outputFile) {
39         super(inputFile, outputFile);
40 
41     }
42 
43     @Override
build()44     boolean build() {
45         if (super.build()) {
46             return assemble(inputFile.fileName);
47         }
48         return false;
49     }
50 
createReader(String fname)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 
assemble(File file)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 
close(Closeable c)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
equals(Object obj)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
hashCode()171     public int hashCode() {
172         return inputFile.hashCode() ^ outputFile.hashCode()
173                 ^ (generate_linenum ? 31 : 37);
174     }
175 }
176