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 "<outpath_jar_path>_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