Main.java revision 1297169e0952bcec5786304b29b45017d7074d52
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.ArrayList;
261297169e0952bcec5786304b29b45017d7074d52Raphael Mollimport java.util.Map;
271297169e0952bcec5786304b29b45017d7074d52Raphael Moll
281297169e0952bcec5786304b29b45017d7074d52Raphael Moll
291297169e0952bcec5786304b29b45017d7074d52Raphael Moll/**
301297169e0952bcec5786304b29b45017d7074d52Raphael Moll *
311297169e0952bcec5786304b29b45017d7074d52Raphael Moll */
321297169e0952bcec5786304b29b45017d7074d52Raphael Mollpublic class Main {
331297169e0952bcec5786304b29b45017d7074d52Raphael Moll
341297169e0952bcec5786304b29b45017d7074d52Raphael Moll    static class Params {
351297169e0952bcec5786304b29b45017d7074d52Raphael Moll        private String mInputJarPath;
361297169e0952bcec5786304b29b45017d7074d52Raphael Moll        private String mOutputJarPath;
371297169e0952bcec5786304b29b45017d7074d52Raphael Moll        private ArrayList<String> mInclusions = new ArrayList<String>();
381297169e0952bcec5786304b29b45017d7074d52Raphael Moll        private ArrayList<String> mExclusions = new ArrayList<String>();
391297169e0952bcec5786304b29b45017d7074d52Raphael Moll
401297169e0952bcec5786304b29b45017d7074d52Raphael Moll        public Params(String inputJarPath, String outputJarPath) {
411297169e0952bcec5786304b29b45017d7074d52Raphael Moll            mInputJarPath = inputJarPath;
421297169e0952bcec5786304b29b45017d7074d52Raphael Moll            mOutputJarPath = outputJarPath;
431297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
441297169e0952bcec5786304b29b45017d7074d52Raphael Moll
451297169e0952bcec5786304b29b45017d7074d52Raphael Moll        public String getInputJarPath() {
461297169e0952bcec5786304b29b45017d7074d52Raphael Moll            return mInputJarPath;
471297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
481297169e0952bcec5786304b29b45017d7074d52Raphael Moll
491297169e0952bcec5786304b29b45017d7074d52Raphael Moll        public String getOutputJarPath() {
501297169e0952bcec5786304b29b45017d7074d52Raphael Moll            return mOutputJarPath;
511297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
521297169e0952bcec5786304b29b45017d7074d52Raphael Moll
531297169e0952bcec5786304b29b45017d7074d52Raphael Moll        public ArrayList<String> getExclusions() {
541297169e0952bcec5786304b29b45017d7074d52Raphael Moll            return mExclusions;
551297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
561297169e0952bcec5786304b29b45017d7074d52Raphael Moll
571297169e0952bcec5786304b29b45017d7074d52Raphael Moll        public ArrayList<String> getInclusions() {
581297169e0952bcec5786304b29b45017d7074d52Raphael Moll            return mInclusions;
591297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
601297169e0952bcec5786304b29b45017d7074d52Raphael Moll    }
611297169e0952bcec5786304b29b45017d7074d52Raphael Moll
621297169e0952bcec5786304b29b45017d7074d52Raphael Moll    /**
631297169e0952bcec5786304b29b45017d7074d52Raphael Moll     * @param args
641297169e0952bcec5786304b29b45017d7074d52Raphael Moll     */
651297169e0952bcec5786304b29b45017d7074d52Raphael Moll    public static void main(String[] args) {
661297169e0952bcec5786304b29b45017d7074d52Raphael Moll
671297169e0952bcec5786304b29b45017d7074d52Raphael Moll        Main m = new Main();
681297169e0952bcec5786304b29b45017d7074d52Raphael Moll        try {
691297169e0952bcec5786304b29b45017d7074d52Raphael Moll            Params p = m.processArgs(args);
701297169e0952bcec5786304b29b45017d7074d52Raphael Moll            m.process(p);
711297169e0952bcec5786304b29b45017d7074d52Raphael Moll        } catch (IOException e) {
721297169e0952bcec5786304b29b45017d7074d52Raphael Moll            e.printStackTrace();
731297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
741297169e0952bcec5786304b29b45017d7074d52Raphael Moll    }
751297169e0952bcec5786304b29b45017d7074d52Raphael Moll
761297169e0952bcec5786304b29b45017d7074d52Raphael Moll    private Params processArgs(String[] args) throws IOException {
771297169e0952bcec5786304b29b45017d7074d52Raphael Moll
781297169e0952bcec5786304b29b45017d7074d52Raphael Moll        if (args.length < 2) {
791297169e0952bcec5786304b29b45017d7074d52Raphael Moll            usage();
801297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
811297169e0952bcec5786304b29b45017d7074d52Raphael Moll
821297169e0952bcec5786304b29b45017d7074d52Raphael Moll        Params p = new Params(args[0], args[1]);
831297169e0952bcec5786304b29b45017d7074d52Raphael Moll
841297169e0952bcec5786304b29b45017d7074d52Raphael Moll        for (int i = 2; i < args.length; i++) {
851297169e0952bcec5786304b29b45017d7074d52Raphael Moll            String s = args[i];
861297169e0952bcec5786304b29b45017d7074d52Raphael Moll            if (s.startsWith("@")) {
871297169e0952bcec5786304b29b45017d7074d52Raphael Moll                addStringsFromFile(p, s.substring(1));
881297169e0952bcec5786304b29b45017d7074d52Raphael Moll            } else if (s.startsWith("-")) {
891297169e0952bcec5786304b29b45017d7074d52Raphael Moll                p.getExclusions().add(s.substring(1));
901297169e0952bcec5786304b29b45017d7074d52Raphael Moll            } else if (s.startsWith("+")) {
911297169e0952bcec5786304b29b45017d7074d52Raphael Moll                p.getInclusions().add(s.substring(1));
921297169e0952bcec5786304b29b45017d7074d52Raphael Moll            }
931297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
941297169e0952bcec5786304b29b45017d7074d52Raphael Moll
951297169e0952bcec5786304b29b45017d7074d52Raphael Moll        return p;
961297169e0952bcec5786304b29b45017d7074d52Raphael Moll    }
971297169e0952bcec5786304b29b45017d7074d52Raphael Moll
981297169e0952bcec5786304b29b45017d7074d52Raphael Moll    private void addStringsFromFile(Params p, String inputFile)
991297169e0952bcec5786304b29b45017d7074d52Raphael Moll            throws IOException {
1001297169e0952bcec5786304b29b45017d7074d52Raphael Moll        BufferedReader br = null;
1011297169e0952bcec5786304b29b45017d7074d52Raphael Moll        try {
1021297169e0952bcec5786304b29b45017d7074d52Raphael Moll            br = new BufferedReader(new FileReader(inputFile));
1031297169e0952bcec5786304b29b45017d7074d52Raphael Moll            String line;
1041297169e0952bcec5786304b29b45017d7074d52Raphael Moll            while ((line = br.readLine()) != null) {
1051297169e0952bcec5786304b29b45017d7074d52Raphael Moll                line = line.trim();
1061297169e0952bcec5786304b29b45017d7074d52Raphael Moll                if (line.length() == 0) {
1071297169e0952bcec5786304b29b45017d7074d52Raphael Moll                    continue;
1081297169e0952bcec5786304b29b45017d7074d52Raphael Moll                }
1091297169e0952bcec5786304b29b45017d7074d52Raphael Moll                char mode = line.charAt(0);
1101297169e0952bcec5786304b29b45017d7074d52Raphael Moll                line = line.substring(1).trim();
1111297169e0952bcec5786304b29b45017d7074d52Raphael Moll
1121297169e0952bcec5786304b29b45017d7074d52Raphael Moll                if (line.length() > 0) {
1131297169e0952bcec5786304b29b45017d7074d52Raphael Moll                    // Keep all class names in ASM path-like format, e.g. android/view/View
1141297169e0952bcec5786304b29b45017d7074d52Raphael Moll                    line = line.replace('.', '/');
1151297169e0952bcec5786304b29b45017d7074d52Raphael Moll                    if (mode == '-') {
1161297169e0952bcec5786304b29b45017d7074d52Raphael Moll                        p.getExclusions().add(line);
1171297169e0952bcec5786304b29b45017d7074d52Raphael Moll                    } else if (mode == '+') {
1181297169e0952bcec5786304b29b45017d7074d52Raphael Moll                        p.getInclusions().add(line);
1191297169e0952bcec5786304b29b45017d7074d52Raphael Moll                    }
1201297169e0952bcec5786304b29b45017d7074d52Raphael Moll                }
1211297169e0952bcec5786304b29b45017d7074d52Raphael Moll            }
1221297169e0952bcec5786304b29b45017d7074d52Raphael Moll        } finally {
1231297169e0952bcec5786304b29b45017d7074d52Raphael Moll            br.close();
1241297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
1251297169e0952bcec5786304b29b45017d7074d52Raphael Moll    }
1261297169e0952bcec5786304b29b45017d7074d52Raphael Moll
1271297169e0952bcec5786304b29b45017d7074d52Raphael Moll    private void usage() {
1281297169e0952bcec5786304b29b45017d7074d52Raphael Moll        System.out.println("Usage: mkstub input.jar output.jar [excluded-class @excluded-classes-file ...]");
1291297169e0952bcec5786304b29b45017d7074d52Raphael Moll
1301297169e0952bcec5786304b29b45017d7074d52Raphael Moll        System.out.println("Include syntax:\n" +
1311297169e0952bcec5786304b29b45017d7074d52Raphael Moll                "+com.package.* : whole package, with glob\n" +
1321297169e0952bcec5786304b29b45017d7074d52Raphael Moll                "+com.package.Class[$Inner] or ...Class*: whole classes with optional glob\n" +
1331297169e0952bcec5786304b29b45017d7074d52Raphael Moll                "Inclusion is not supported at method/field level.\n\n");
1341297169e0952bcec5786304b29b45017d7074d52Raphael Moll
1351297169e0952bcec5786304b29b45017d7074d52Raphael Moll        System.out.println("Exclude syntax:\n" +
1361297169e0952bcec5786304b29b45017d7074d52Raphael Moll        		"-com.package.* : whole package, with glob\n" +
1371297169e0952bcec5786304b29b45017d7074d52Raphael Moll        		"-com.package.Class[$Inner] or ...Class*: whole classes with optional glob\n" +
1381297169e0952bcec5786304b29b45017d7074d52Raphael Moll        		"-com.package.Class#method: whole method or field\n" +
1391297169e0952bcec5786304b29b45017d7074d52Raphael Moll                "-com.package.Class#method(IILjava/lang/String;)V: specific method with signature.\n\n");
1401297169e0952bcec5786304b29b45017d7074d52Raphael Moll        System.exit(1);
1411297169e0952bcec5786304b29b45017d7074d52Raphael Moll    }
1421297169e0952bcec5786304b29b45017d7074d52Raphael Moll
1431297169e0952bcec5786304b29b45017d7074d52Raphael Moll    private void process(Params p) throws IOException {
1441297169e0952bcec5786304b29b45017d7074d52Raphael Moll        AsmAnalyzer aa = new AsmAnalyzer();
1451297169e0952bcec5786304b29b45017d7074d52Raphael Moll        Map<String, ClassReader> classes = aa.parseInputJar(p.getInputJarPath());
1461297169e0952bcec5786304b29b45017d7074d52Raphael Moll
1471297169e0952bcec5786304b29b45017d7074d52Raphael Moll        aa.filter(classes, p.getInclusions(), p.getExclusions());
1481297169e0952bcec5786304b29b45017d7074d52Raphael Moll
1491297169e0952bcec5786304b29b45017d7074d52Raphael Moll        AsmGenerator gen = new AsmGenerator();
1501297169e0952bcec5786304b29b45017d7074d52Raphael Moll
1511297169e0952bcec5786304b29b45017d7074d52Raphael Moll        // dump as Java source files, mostly for debugging
1521297169e0952bcec5786304b29b45017d7074d52Raphael Moll        File dst_src_dir = new File(p.getOutputJarPath() + File.separator + "sources");
1531297169e0952bcec5786304b29b45017d7074d52Raphael Moll        dst_src_dir.mkdir();
1541297169e0952bcec5786304b29b45017d7074d52Raphael Moll        gen.generateSource(dst_src_dir, classes, p.getExclusions());
1551297169e0952bcec5786304b29b45017d7074d52Raphael Moll
1561297169e0952bcec5786304b29b45017d7074d52Raphael Moll    }
1571297169e0952bcec5786304b29b45017d7074d52Raphael Moll
1581297169e0952bcec5786304b29b45017d7074d52Raphael Moll    /** @deprecated debug only */
1591297169e0952bcec5786304b29b45017d7074d52Raphael Moll    private void displayClasses(Map<String, ClassReader> classes) {
1601297169e0952bcec5786304b29b45017d7074d52Raphael Moll        for(String className : classes.keySet()) {
1611297169e0952bcec5786304b29b45017d7074d52Raphael Moll            System.out.println("Found " + className);
1621297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
1631297169e0952bcec5786304b29b45017d7074d52Raphael Moll    }
1641297169e0952bcec5786304b29b45017d7074d52Raphael Moll
1651297169e0952bcec5786304b29b45017d7074d52Raphael Moll}
166