Main.java revision 0cb5e26dab4d6c62f7e1ac5a6ddd509ba3ee8c8c
1/*
2 * Copyright (C) 2009 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.mkstubs;
18
19import org.objectweb.asm.ClassReader;
20
21import java.io.BufferedReader;
22import java.io.File;
23import java.io.FileReader;
24import java.io.IOException;
25import java.util.Map;
26
27
28/**
29 *
30 */
31public class Main {
32
33    static class Params {
34        private String mInputJarPath;
35        private String mOutputJarPath;
36        private Filter mFilter;
37
38        public Params(String inputJarPath, String outputJarPath) {
39            mInputJarPath = inputJarPath;
40            mOutputJarPath = outputJarPath;
41            mFilter = new Filter();
42        }
43
44        public String getInputJarPath() {
45            return mInputJarPath;
46        }
47
48        public String getOutputJarPath() {
49            return mOutputJarPath;
50        }
51
52        public Filter getFilter() {
53            return mFilter;
54        }
55    }
56
57    /**
58     * @param args
59     */
60    public static void main(String[] args) {
61
62        Main m = new Main();
63        try {
64            Params p = m.processArgs(args);
65            m.process(p);
66        } catch (IOException e) {
67            e.printStackTrace();
68        }
69    }
70
71    private Params processArgs(String[] args) throws IOException {
72
73        if (args.length < 2) {
74            usage();
75        }
76
77        Params p = new Params(args[0], args[1]);
78
79        for (int i = 2; i < args.length; i++) {
80            addString(p, args[i]);
81        }
82
83        return p;
84    }
85
86    private void addString(Params p, String s) throws IOException {
87        s = s.trim();
88
89        if (s.length() < 2) {
90            return;
91        }
92
93        char mode = s.charAt(0);
94        s = s.substring(1).trim();
95
96        if (mode == '@') {
97            addStringsFromFile(p, s);
98
99        } else if (mode == '-') {
100            s = s.replace('.', '/');  // transform FQCN into ASM internal name
101            if (s.endsWith("*")) {
102                p.getFilter().getExcludePrefix().add(s.substring(0, s.length() - 1));
103            } else {
104                p.getFilter().getExcludeFull().add(s);
105            }
106
107        } else if (mode == '+') {
108            s = s.replace('.', '/');  // transform FQCN into ASM internal name
109            if (s.endsWith("*")) {
110                p.getFilter().getIncludePrefix().add(s.substring(0, s.length() - 1));
111            } else {
112                p.getFilter().getIncludeFull().add(s);
113            }
114        }
115    }
116
117    private void addStringsFromFile(Params p, String inputFile)
118            throws IOException {
119        BufferedReader br = null;
120        try {
121            br = new BufferedReader(new FileReader(inputFile));
122            String line;
123            while ((line = br.readLine()) != null) {
124                addString(p, line);
125            }
126        } finally {
127            br.close();
128        }
129    }
130
131    private void usage() {
132        System.out.println("Usage: mkstub input.jar output.jar [excluded-class @excluded-classes-file ...]");
133
134        System.out.println("Include syntax:\n" +
135                "+com.package.* : whole package, with glob\n" +
136                "+com.package.Class[$Inner] or ...Class*: whole classes with optional glob\n" +
137                "Inclusion is not supported at method/field level.\n\n");
138
139        System.out.println("Exclude syntax:\n" +
140        		"-com.package.* : whole package, with glob\n" +
141        		"-com.package.Class[$Inner] or ...Class*: whole classes with optional glob\n" +
142        		"-com.package.Class#method: whole method or field\n" +
143                "-com.package.Class#method(IILjava/lang/String;)V: specific method with signature.\n\n");
144        System.exit(1);
145    }
146
147    private void process(Params p) throws IOException {
148        AsmAnalyzer aa = new AsmAnalyzer();
149        Map<String, ClassReader> classes = aa.parseInputJar(p.getInputJarPath());
150
151        System.out.println(String.format("Classes loaded: %d", classes.size()));
152
153        aa.filter(classes, p.getFilter());
154
155        System.out.println(String.format("Classes filtered: %d", classes.size()));
156
157        // dump as Java source files, mostly for debugging
158        SourceGenerator src_gen = new SourceGenerator();
159        File dst_src_dir = new File(p.getOutputJarPath() + "_sources");
160        dst_src_dir.mkdir();
161        src_gen.generateSource(dst_src_dir, classes, p.getFilter());
162
163        // dump the stubbed jar
164        StubGenerator stub_gen = new StubGenerator();
165        File dst_jar = new File(p.getOutputJarPath());
166        stub_gen.generateStubbedJar(dst_jar, classes, p.getFilter());
167    }
168}
169