Main.java revision 32557b47c5418ec1be949f15be5440701a8c06a6
11297169e0952bcec5786304b29b45017d7074d52Raphael Moll/*
21297169e0952bcec5786304b29b45017d7074d52Raphael Moll * Copyright (C) 2009 The Android Open Source Project
31297169e0952bcec5786304b29b45017d7074d52Raphael Moll *
41297169e0952bcec5786304b29b45017d7074d52Raphael Moll * Licensed under the Apache License, Version 2.0 (the "License");
51297169e0952bcec5786304b29b45017d7074d52Raphael Moll * you may not use this file except in compliance with the License.
61297169e0952bcec5786304b29b45017d7074d52Raphael Moll * You may obtain a copy of the License at
71297169e0952bcec5786304b29b45017d7074d52Raphael Moll *
81297169e0952bcec5786304b29b45017d7074d52Raphael Moll *      http://www.apache.org/licenses/LICENSE-2.0
91297169e0952bcec5786304b29b45017d7074d52Raphael Moll *
101297169e0952bcec5786304b29b45017d7074d52Raphael Moll * Unless required by applicable law or agreed to in writing, software
111297169e0952bcec5786304b29b45017d7074d52Raphael Moll * distributed under the License is distributed on an "AS IS" BASIS,
121297169e0952bcec5786304b29b45017d7074d52Raphael Moll * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131297169e0952bcec5786304b29b45017d7074d52Raphael Moll * See the License for the specific language governing permissions and
141297169e0952bcec5786304b29b45017d7074d52Raphael Moll * limitations under the License.
151297169e0952bcec5786304b29b45017d7074d52Raphael Moll */
161297169e0952bcec5786304b29b45017d7074d52Raphael Moll
171297169e0952bcec5786304b29b45017d7074d52Raphael Mollpackage com.android.mkstubs;
181297169e0952bcec5786304b29b45017d7074d52Raphael Moll
191297169e0952bcec5786304b29b45017d7074d52Raphael Mollimport org.objectweb.asm.ClassReader;
201297169e0952bcec5786304b29b45017d7074d52Raphael Moll
211297169e0952bcec5786304b29b45017d7074d52Raphael Mollimport java.io.BufferedReader;
221297169e0952bcec5786304b29b45017d7074d52Raphael Mollimport java.io.File;
231297169e0952bcec5786304b29b45017d7074d52Raphael Mollimport java.io.FileReader;
241297169e0952bcec5786304b29b45017d7074d52Raphael Mollimport java.io.IOException;
251297169e0952bcec5786304b29b45017d7074d52Raphael Mollimport java.util.Map;
261297169e0952bcec5786304b29b45017d7074d52Raphael Moll
271297169e0952bcec5786304b29b45017d7074d52Raphael Moll
281297169e0952bcec5786304b29b45017d7074d52Raphael Moll/**
291297169e0952bcec5786304b29b45017d7074d52Raphael Moll *
301297169e0952bcec5786304b29b45017d7074d52Raphael Moll */
311297169e0952bcec5786304b29b45017d7074d52Raphael Mollpublic class Main {
321297169e0952bcec5786304b29b45017d7074d52Raphael Moll
331297169e0952bcec5786304b29b45017d7074d52Raphael Moll    static class Params {
341297169e0952bcec5786304b29b45017d7074d52Raphael Moll        private String mInputJarPath;
351297169e0952bcec5786304b29b45017d7074d52Raphael Moll        private String mOutputJarPath;
3632557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        private Filter mFilter;
3732557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll
381297169e0952bcec5786304b29b45017d7074d52Raphael Moll        public Params(String inputJarPath, String outputJarPath) {
391297169e0952bcec5786304b29b45017d7074d52Raphael Moll            mInputJarPath = inputJarPath;
401297169e0952bcec5786304b29b45017d7074d52Raphael Moll            mOutputJarPath = outputJarPath;
4132557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll            mFilter = new Filter();
421297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
431297169e0952bcec5786304b29b45017d7074d52Raphael Moll
441297169e0952bcec5786304b29b45017d7074d52Raphael Moll        public String getInputJarPath() {
451297169e0952bcec5786304b29b45017d7074d52Raphael Moll            return mInputJarPath;
461297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
471297169e0952bcec5786304b29b45017d7074d52Raphael Moll
481297169e0952bcec5786304b29b45017d7074d52Raphael Moll        public String getOutputJarPath() {
491297169e0952bcec5786304b29b45017d7074d52Raphael Moll            return mOutputJarPath;
501297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
511297169e0952bcec5786304b29b45017d7074d52Raphael Moll
5232557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        public Filter getFilter() {
5332557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll            return mFilter;
541297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
551297169e0952bcec5786304b29b45017d7074d52Raphael Moll    }
561297169e0952bcec5786304b29b45017d7074d52Raphael Moll
571297169e0952bcec5786304b29b45017d7074d52Raphael Moll    /**
581297169e0952bcec5786304b29b45017d7074d52Raphael Moll     * @param args
591297169e0952bcec5786304b29b45017d7074d52Raphael Moll     */
601297169e0952bcec5786304b29b45017d7074d52Raphael Moll    public static void main(String[] args) {
611297169e0952bcec5786304b29b45017d7074d52Raphael Moll
621297169e0952bcec5786304b29b45017d7074d52Raphael Moll        Main m = new Main();
631297169e0952bcec5786304b29b45017d7074d52Raphael Moll        try {
641297169e0952bcec5786304b29b45017d7074d52Raphael Moll            Params p = m.processArgs(args);
651297169e0952bcec5786304b29b45017d7074d52Raphael Moll            m.process(p);
661297169e0952bcec5786304b29b45017d7074d52Raphael Moll        } catch (IOException e) {
671297169e0952bcec5786304b29b45017d7074d52Raphael Moll            e.printStackTrace();
681297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
691297169e0952bcec5786304b29b45017d7074d52Raphael Moll    }
701297169e0952bcec5786304b29b45017d7074d52Raphael Moll
711297169e0952bcec5786304b29b45017d7074d52Raphael Moll    private Params processArgs(String[] args) throws IOException {
721297169e0952bcec5786304b29b45017d7074d52Raphael Moll
731297169e0952bcec5786304b29b45017d7074d52Raphael Moll        if (args.length < 2) {
741297169e0952bcec5786304b29b45017d7074d52Raphael Moll            usage();
751297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
761297169e0952bcec5786304b29b45017d7074d52Raphael Moll
771297169e0952bcec5786304b29b45017d7074d52Raphael Moll        Params p = new Params(args[0], args[1]);
781297169e0952bcec5786304b29b45017d7074d52Raphael Moll
791297169e0952bcec5786304b29b45017d7074d52Raphael Moll        for (int i = 2; i < args.length; i++) {
8032557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll            addString(p, args[i]);
811297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
821297169e0952bcec5786304b29b45017d7074d52Raphael Moll
831297169e0952bcec5786304b29b45017d7074d52Raphael Moll        return p;
841297169e0952bcec5786304b29b45017d7074d52Raphael Moll    }
851297169e0952bcec5786304b29b45017d7074d52Raphael Moll
8632557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll    private void addString(Params p, String s) throws IOException {
8732557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        s = s.trim();
8832557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll
8932557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        if (s.length() < 2) {
9032557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll            return;
9132557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        }
9232557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll
9332557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        char mode = s.charAt(0);
9432557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        s = s.substring(1).trim();
9532557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll
9632557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        if (mode == '@') {
9732557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll            addStringsFromFile(p, s);
9832557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll
9932557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        } else if (mode == '-') {
10032557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll            s = s.replace('.', '/');  // transform FQCN into ASM internal name
10132557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll            if (s.endsWith("*")) {
10232557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll                p.getFilter().getExcludePrefix().add(s.substring(0, s.length() - 1));
10332557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll            } else {
10432557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll                p.getFilter().getExcludeFull().add(s);
10532557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll            }
10632557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll
10732557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        } else if (mode == '+') {
10832557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll            s = s.replace('.', '/');  // transform FQCN into ASM internal name
10932557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll            if (s.endsWith("*")) {
11032557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll                p.getFilter().getIncludePrefix().add(s.substring(0, s.length() - 1));
11132557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll            } else {
11232557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll                p.getFilter().getIncludeFull().add(s);
11332557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll            }
11432557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        }
11532557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll    }
11632557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll
1171297169e0952bcec5786304b29b45017d7074d52Raphael Moll    private void addStringsFromFile(Params p, String inputFile)
1181297169e0952bcec5786304b29b45017d7074d52Raphael Moll            throws IOException {
1191297169e0952bcec5786304b29b45017d7074d52Raphael Moll        BufferedReader br = null;
1201297169e0952bcec5786304b29b45017d7074d52Raphael Moll        try {
1211297169e0952bcec5786304b29b45017d7074d52Raphael Moll            br = new BufferedReader(new FileReader(inputFile));
1221297169e0952bcec5786304b29b45017d7074d52Raphael Moll            String line;
1231297169e0952bcec5786304b29b45017d7074d52Raphael Moll            while ((line = br.readLine()) != null) {
12432557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll                addString(p, line);
1251297169e0952bcec5786304b29b45017d7074d52Raphael Moll            }
1261297169e0952bcec5786304b29b45017d7074d52Raphael Moll        } finally {
1271297169e0952bcec5786304b29b45017d7074d52Raphael Moll            br.close();
1281297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
1291297169e0952bcec5786304b29b45017d7074d52Raphael Moll    }
1301297169e0952bcec5786304b29b45017d7074d52Raphael Moll
1311297169e0952bcec5786304b29b45017d7074d52Raphael Moll    private void usage() {
1321297169e0952bcec5786304b29b45017d7074d52Raphael Moll        System.out.println("Usage: mkstub input.jar output.jar [excluded-class @excluded-classes-file ...]");
1331297169e0952bcec5786304b29b45017d7074d52Raphael Moll
1341297169e0952bcec5786304b29b45017d7074d52Raphael Moll        System.out.println("Include syntax:\n" +
1351297169e0952bcec5786304b29b45017d7074d52Raphael Moll                "+com.package.* : whole package, with glob\n" +
1361297169e0952bcec5786304b29b45017d7074d52Raphael Moll                "+com.package.Class[$Inner] or ...Class*: whole classes with optional glob\n" +
1371297169e0952bcec5786304b29b45017d7074d52Raphael Moll                "Inclusion is not supported at method/field level.\n\n");
1381297169e0952bcec5786304b29b45017d7074d52Raphael Moll
1391297169e0952bcec5786304b29b45017d7074d52Raphael Moll        System.out.println("Exclude syntax:\n" +
1401297169e0952bcec5786304b29b45017d7074d52Raphael Moll        		"-com.package.* : whole package, with glob\n" +
1411297169e0952bcec5786304b29b45017d7074d52Raphael Moll        		"-com.package.Class[$Inner] or ...Class*: whole classes with optional glob\n" +
1421297169e0952bcec5786304b29b45017d7074d52Raphael Moll        		"-com.package.Class#method: whole method or field\n" +
1431297169e0952bcec5786304b29b45017d7074d52Raphael Moll                "-com.package.Class#method(IILjava/lang/String;)V: specific method with signature.\n\n");
1441297169e0952bcec5786304b29b45017d7074d52Raphael Moll        System.exit(1);
1451297169e0952bcec5786304b29b45017d7074d52Raphael Moll    }
1461297169e0952bcec5786304b29b45017d7074d52Raphael Moll
1471297169e0952bcec5786304b29b45017d7074d52Raphael Moll    private void process(Params p) throws IOException {
1481297169e0952bcec5786304b29b45017d7074d52Raphael Moll        AsmAnalyzer aa = new AsmAnalyzer();
1491297169e0952bcec5786304b29b45017d7074d52Raphael Moll        Map<String, ClassReader> classes = aa.parseInputJar(p.getInputJarPath());
15032557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll
15132557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        System.out.println(String.format("Classes loaded: %d", classes.size()));
15232557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll
15332557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        aa.filter(classes, p.getFilter());
15432557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll
15532557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        System.out.println(String.format("Classes filtered: %d", classes.size()));
1561297169e0952bcec5786304b29b45017d7074d52Raphael Moll
1571297169e0952bcec5786304b29b45017d7074d52Raphael Moll        // dump as Java source files, mostly for debugging
158323557aaf99f85ec31069e82460b30dfa2abf777Raphael Moll        SourceGenerator src_gen = new SourceGenerator();
159323557aaf99f85ec31069e82460b30dfa2abf777Raphael Moll        File dst_src_dir = new File(p.getOutputJarPath() + "_sources");
1601297169e0952bcec5786304b29b45017d7074d52Raphael Moll        dst_src_dir.mkdir();
16132557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        src_gen.generateSource(dst_src_dir, classes, p.getFilter());
1621297169e0952bcec5786304b29b45017d7074d52Raphael Moll
163323557aaf99f85ec31069e82460b30dfa2abf777Raphael Moll        // dump the stubbed jar
164323557aaf99f85ec31069e82460b30dfa2abf777Raphael Moll        StubGenerator stub_gen = new StubGenerator();
165323557aaf99f85ec31069e82460b30dfa2abf777Raphael Moll        File dst_jar = new File(p.getOutputJarPath());
16632557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        stub_gen.generateStubbedJar(dst_jar, classes, p.getFilter());
1671297169e0952bcec5786304b29b45017d7074d52Raphael Moll    }
1681297169e0952bcec5786304b29b45017d7074d52Raphael Moll}
169