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
198252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphaelimport com.android.mkstubs.Main.Params;
208252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael
211297169e0952bcec5786304b29b45017d7074d52Raphael Mollimport org.objectweb.asm.ClassReader;
221297169e0952bcec5786304b29b45017d7074d52Raphael Moll
231297169e0952bcec5786304b29b45017d7074d52Raphael Mollimport java.io.BufferedReader;
241297169e0952bcec5786304b29b45017d7074d52Raphael Mollimport java.io.File;
251297169e0952bcec5786304b29b45017d7074d52Raphael Mollimport java.io.FileReader;
261297169e0952bcec5786304b29b45017d7074d52Raphael Mollimport java.io.IOException;
271297169e0952bcec5786304b29b45017d7074d52Raphael Mollimport java.util.Map;
281297169e0952bcec5786304b29b45017d7074d52Raphael Moll
291297169e0952bcec5786304b29b45017d7074d52Raphael Moll
301297169e0952bcec5786304b29b45017d7074d52Raphael Moll/**
31ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll * Main entry point of the MkStubs app.
32ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll * <p/>
33ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll * For workflow details, see {@link #process(Params)}.
341297169e0952bcec5786304b29b45017d7074d52Raphael Moll */
351297169e0952bcec5786304b29b45017d7074d52Raphael Mollpublic class Main {
368252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael
37ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll    /**
38ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * A struct-like class to hold the various input values (e.g. command-line args)
39ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     */
401297169e0952bcec5786304b29b45017d7074d52Raphael Moll    static class Params {
411297169e0952bcec5786304b29b45017d7074d52Raphael Moll        private String mInputJarPath;
421297169e0952bcec5786304b29b45017d7074d52Raphael Moll        private String mOutputJarPath;
4332557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        private Filter mFilter;
448252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        private boolean mVerbose;
458252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        private boolean mDumpSource;
468252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael
478252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        public Params() {
488252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael            mFilter = new Filter();
498252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        }
508252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael
518252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        /** Sets the name of the input jar, where to read classes from. Must not be null. */
528252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        public void setInputJarPath(String inputJarPath) {
531297169e0952bcec5786304b29b45017d7074d52Raphael Moll            mInputJarPath = inputJarPath;
548252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        }
558252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael
568252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        /** Sets the name of the output jar, where to write classes to. Must not be null. */
578252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        public void setOutputJarPath(String outputJarPath) {
581297169e0952bcec5786304b29b45017d7074d52Raphael Moll            mOutputJarPath = outputJarPath;
591297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
60ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll
61ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll        /** Returns the name of the input jar, where to read classes from. */
621297169e0952bcec5786304b29b45017d7074d52Raphael Moll        public String getInputJarPath() {
631297169e0952bcec5786304b29b45017d7074d52Raphael Moll            return mInputJarPath;
641297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
651297169e0952bcec5786304b29b45017d7074d52Raphael Moll
66ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll        /** Returns the name of the output jar, where to write classes to. */
671297169e0952bcec5786304b29b45017d7074d52Raphael Moll        public String getOutputJarPath() {
681297169e0952bcec5786304b29b45017d7074d52Raphael Moll            return mOutputJarPath;
691297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
70ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll
71ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll        /** Returns the current instance of the filter, the include/exclude patterns. */
7232557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        public Filter getFilter() {
7332557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll            return mFilter;
741297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
758252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael
768252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        /** Sets verbose mode on. Default is off. */
778252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        public void setVerbose() {
788252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael            mVerbose = true;
798252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        }
808252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael
818252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        /** Returns true if verbose mode is on. */
828252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        public boolean isVerbose() {
838252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael            return mVerbose;
848252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        }
858252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael
868252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        /** Sets dump source mode on. Default is off. */
878252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        public void setDumpSource() {
888252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael            mDumpSource = true;
898252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        }
908252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael
918252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        /** Returns true if source should be dumped. */
928252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        public boolean isDumpSource() {
938252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael            return mDumpSource;
948252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        }
958252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael    }
968252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael
978252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael    /** Logger that writes on stdout depending a conditional verbose mode. */
988252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael    static class Logger {
998252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        private final boolean mVerbose;
1008252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael
1018252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        public Logger(boolean verbose) {
1028252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael            mVerbose = verbose;
1038252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        }
1048252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael
1058252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        /** Writes to stdout only in verbose mode. */
1068252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        public void debug(String msg, Object...params) {
1078252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael            if (mVerbose) {
1088252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael                System.out.println(String.format(msg, params));
1098252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael            }
1108252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        }
1118252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael
1128252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        /** Writes to stdout all the time. */
1138252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        public void info(String msg, Object...params) {
1148252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael            System.out.println(String.format(msg, params));
1158252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        }
1161297169e0952bcec5786304b29b45017d7074d52Raphael Moll    }
1178252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael
1181297169e0952bcec5786304b29b45017d7074d52Raphael Moll    /**
119ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * Main entry point. Processes arguments then performs the "real" work.
1201297169e0952bcec5786304b29b45017d7074d52Raphael Moll     */
1211297169e0952bcec5786304b29b45017d7074d52Raphael Moll    public static void main(String[] args) {
1221297169e0952bcec5786304b29b45017d7074d52Raphael Moll        Main m = new Main();
1231297169e0952bcec5786304b29b45017d7074d52Raphael Moll        try {
1241297169e0952bcec5786304b29b45017d7074d52Raphael Moll            Params p = m.processArgs(args);
1251297169e0952bcec5786304b29b45017d7074d52Raphael Moll            m.process(p);
1261297169e0952bcec5786304b29b45017d7074d52Raphael Moll        } catch (IOException e) {
1271297169e0952bcec5786304b29b45017d7074d52Raphael Moll            e.printStackTrace();
1281297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
1291297169e0952bcec5786304b29b45017d7074d52Raphael Moll    }
1301297169e0952bcec5786304b29b45017d7074d52Raphael Moll
131ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll    /**
132ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * Grabs command-line arguments.
133ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * The expected arguments are:
134ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * <ul>
135ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * <li> The filename of the input Jar.
136ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * <li> The filename of the output Jar.
137ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * <li> One or more include/exclude patterns or files containing these patterns.
138ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     *      See {@link #addString(Params, String)} for syntax.
139ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * </ul>
140ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * @throws IOException on failure to read a pattern file.
141ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     */
1421297169e0952bcec5786304b29b45017d7074d52Raphael Moll    private Params processArgs(String[] args) throws IOException {
1438252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        Params p = new Params();
1448252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael
1458252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        for (String arg : args) {
1468252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael            if (arg.startsWith("--")) {
1478252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael                if (arg.startsWith("--v")) {
1488252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael                    p.setVerbose();
1498252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael                } else if (arg.startsWith("--s")) {
1508252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael                    p.setDumpSource();
1518252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael                } else if (arg.startsWith("--h")) {
1528252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael                    usage(null);
1538252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael                } else {
1548252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael                    usage("Unknown argument: " + arg);
1558252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael                }
1568252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael            } else if (p.getInputJarPath() == null) {
1578252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael                p.setInputJarPath(arg);
1588252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael            } else if (p.getOutputJarPath() == null) {
1598252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael                p.setOutputJarPath(arg);
1608252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael            } else {
1618252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael                addString(p, arg);
1628252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael            }
1631297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
1641297169e0952bcec5786304b29b45017d7074d52Raphael Moll
1658252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        if (p.getInputJarPath() == null && p.getOutputJarPath() == null) {
1668252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael            usage("Missing input or output JAR.");
1671297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
1688252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael
1691297169e0952bcec5786304b29b45017d7074d52Raphael Moll        return p;
1701297169e0952bcec5786304b29b45017d7074d52Raphael Moll    }
1711297169e0952bcec5786304b29b45017d7074d52Raphael Moll
172ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll    /**
173ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * Adds one pattern string to the current filter.
174ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * The syntax must be:
175ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * <ul>
176ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * <li> +full_include or +prefix_include*
177ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * <li> -full_exclude or -prefix_exclude*
178ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * <li> @filename
179ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * </ul>
180ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * The input string is trimmed so any space around the first letter (-/+/@) or
181ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * at the end is removed. Empty strings are ignored.
1828252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael     *
183ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * @param p The params which filters to edit.
184ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * @param s The string to examine.
185ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * @throws IOException
186ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     */
18732557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll    private void addString(Params p, String s) throws IOException {
188ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll        if (s == null) {
189ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll            return;
190ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll        }
191ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll
19232557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        s = s.trim();
19332557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll
19432557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        if (s.length() < 2) {
19532557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll            return;
19632557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        }
1978252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael
19832557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        char mode = s.charAt(0);
19932557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        s = s.substring(1).trim();
20032557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll
20132557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        if (mode == '@') {
20232557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll            addStringsFromFile(p, s);
2038252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael
20432557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        } else if (mode == '-') {
20532557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll            s = s.replace('.', '/');  // transform FQCN into ASM internal name
20632557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll            if (s.endsWith("*")) {
20732557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll                p.getFilter().getExcludePrefix().add(s.substring(0, s.length() - 1));
20832557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll            } else {
20932557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll                p.getFilter().getExcludeFull().add(s);
21032557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll            }
21132557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll
21232557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        } else if (mode == '+') {
21332557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll            s = s.replace('.', '/');  // transform FQCN into ASM internal name
21432557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll            if (s.endsWith("*")) {
21532557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll                p.getFilter().getIncludePrefix().add(s.substring(0, s.length() - 1));
21632557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll            } else {
21732557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll                p.getFilter().getIncludeFull().add(s);
21832557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll            }
21932557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        }
22032557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll    }
22132557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll
222ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll    /**
223ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * Adds all the filter strings from the given file.
2248252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael     *
225ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * @param p The params which filter to edit.
226ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * @param osFilePath The OS path to the file containing the patterns.
227ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * @throws IOException
2288252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael     *
229ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * @see #addString(Params, String)
230ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     */
231ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll    private void addStringsFromFile(Params p, String osFilePath)
2321297169e0952bcec5786304b29b45017d7074d52Raphael Moll            throws IOException {
2331297169e0952bcec5786304b29b45017d7074d52Raphael Moll        BufferedReader br = null;
2341297169e0952bcec5786304b29b45017d7074d52Raphael Moll        try {
235ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll            br = new BufferedReader(new FileReader(osFilePath));
2361297169e0952bcec5786304b29b45017d7074d52Raphael Moll            String line;
2371297169e0952bcec5786304b29b45017d7074d52Raphael Moll            while ((line = br.readLine()) != null) {
23832557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll                addString(p, line);
2391297169e0952bcec5786304b29b45017d7074d52Raphael Moll            }
2401297169e0952bcec5786304b29b45017d7074d52Raphael Moll        } finally {
241ce6f5c964f56cb9bb670d350da2fa57d3772127bXavier Ducrohet            if (br != null) {
242ce6f5c964f56cb9bb670d350da2fa57d3772127bXavier Ducrohet                br.close();
243ce6f5c964f56cb9bb670d350da2fa57d3772127bXavier Ducrohet            }
2441297169e0952bcec5786304b29b45017d7074d52Raphael Moll        }
2451297169e0952bcec5786304b29b45017d7074d52Raphael Moll    }
2461297169e0952bcec5786304b29b45017d7074d52Raphael Moll
247ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll    /**
248ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * Prints some help to stdout.
2498252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael     * @param error The error that generated the usage, if any. Can be null.
250ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     */
2518252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael    private void usage(String error) {
2528252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        if (error != null) {
2538252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael            System.out.println("ERROR: " + error);
2548252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        }
2558252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael
2568252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        System.out.println("Usage: mkstub [--h|--s|--v] input.jar output.jar [excluded-class @excluded-classes-file ...]");
2578252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael
2588252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        System.out.println("Options:\n" +
2598252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael                " --h | --help    : print this usage.\n" +
2608252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael                " --v | --verbose : verbose mode.\n" +
2618252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael                " --s | --source  : dump source equivalent to modified byte code.\n\n");
2621297169e0952bcec5786304b29b45017d7074d52Raphael Moll
2631297169e0952bcec5786304b29b45017d7074d52Raphael Moll        System.out.println("Include syntax:\n" +
2641297169e0952bcec5786304b29b45017d7074d52Raphael Moll                "+com.package.* : whole package, with glob\n" +
2651297169e0952bcec5786304b29b45017d7074d52Raphael Moll                "+com.package.Class[$Inner] or ...Class*: whole classes with optional glob\n" +
2661297169e0952bcec5786304b29b45017d7074d52Raphael Moll                "Inclusion is not supported at method/field level.\n\n");
2671297169e0952bcec5786304b29b45017d7074d52Raphael Moll
2681297169e0952bcec5786304b29b45017d7074d52Raphael Moll        System.out.println("Exclude syntax:\n" +
2691297169e0952bcec5786304b29b45017d7074d52Raphael Moll        		"-com.package.* : whole package, with glob\n" +
2701297169e0952bcec5786304b29b45017d7074d52Raphael Moll        		"-com.package.Class[$Inner] or ...Class*: whole classes with optional glob\n" +
2711297169e0952bcec5786304b29b45017d7074d52Raphael Moll        		"-com.package.Class#method: whole method or field\n" +
2721297169e0952bcec5786304b29b45017d7074d52Raphael Moll                "-com.package.Class#method(IILjava/lang/String;)V: specific method with signature.\n\n");
2738252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael
2741297169e0952bcec5786304b29b45017d7074d52Raphael Moll        System.exit(1);
2751297169e0952bcec5786304b29b45017d7074d52Raphael Moll    }
2761297169e0952bcec5786304b29b45017d7074d52Raphael Moll
277ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll    /**
278ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * Performs the main workflow of this app:
279ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * <ul>
280ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * <li> Read the input Jar to get all its classes.
281ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * <li> Filter out all classes that should not be included or that should be excluded.
282ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * <li> Goes thru the classes, filters methods/fields and generate their source
283ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     *      in a directory called "&lt;outpath_jar_path&gt;_sources"
284ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * <li> Does the same filtering on the classes but this time generates the real stubbed
285ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     *      output jar.
286ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     * </ul>
287ee8f65c4f76965873842ecc25e40a3ca6774d40cRaphael Moll     */
2881297169e0952bcec5786304b29b45017d7074d52Raphael Moll    private void process(Params p) throws IOException {
2891297169e0952bcec5786304b29b45017d7074d52Raphael Moll        AsmAnalyzer aa = new AsmAnalyzer();
2901297169e0952bcec5786304b29b45017d7074d52Raphael Moll        Map<String, ClassReader> classes = aa.parseInputJar(p.getInputJarPath());
29132557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll
2928252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        Logger log = new Logger(p.isVerbose());
2938252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        log.info("Classes loaded: %d", classes.size());
29432557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll
2958252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        aa.filter(classes, p.getFilter(), log);
2968252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        log.info("Classes filtered: %d", classes.size());
2971297169e0952bcec5786304b29b45017d7074d52Raphael Moll
2981297169e0952bcec5786304b29b45017d7074d52Raphael Moll        // dump as Java source files, mostly for debugging
2998252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        if (p.isDumpSource()) {
3008252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael            SourceGenerator src_gen = new SourceGenerator(log);
3018252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael            File dst_src_dir = new File(p.getOutputJarPath() + "_sources");
3028252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael            dst_src_dir.mkdir();
3038252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael            src_gen.generateSource(dst_src_dir, classes, p.getFilter());
3048252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        }
3058252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael
306323557aaf99f85ec31069e82460b30dfa2abf777Raphael Moll        // dump the stubbed jar
3078252cdea30a5a22ae8b2235d7dee2fdd02ba5ccdRaphael        StubGenerator stub_gen = new StubGenerator(log);
308323557aaf99f85ec31069e82460b30dfa2abf777Raphael Moll        File dst_jar = new File(p.getOutputJarPath());
30932557b47c5418ec1be949f15be5440701a8c06a6Raphael Moll        stub_gen.generateStubbedJar(dst_jar, classes, p.getFilter());
3101297169e0952bcec5786304b29b45017d7074d52Raphael Moll    }
3111297169e0952bcec5786304b29b45017d7074d52Raphael Moll}
312