Main.java revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.tools.layoutlib.create;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Set;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class Main {
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void main(String[] args) {
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Log log = new Log();
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<String> osJarPath = new ArrayList<String>();
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String[] osDestJar = { null };
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!processArgs(log, args, osJarPath, osDestJar)) {
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            log.error("Usage: layoutlib_create [-v] output.jar input.jar ...");
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            System.exit(1);
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        log.info("Output: %1$s", osDestJar[0]);
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (String path : osJarPath) {
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            log.info("Input :      %1$s", path);
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            AsmGenerator agen = new AsmGenerator(log, osDestJar[0],
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    new Class<?>[] {  // classes to inject in the final JAR
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        OverrideMethod.class,
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        MethodListener.class,
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        MethodAdapter.class
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    },
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    new String[] {  // methods to force override
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.view.View#isInEditMode",
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.content.res.Resources$Theme#obtainStyledAttributes",
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    },
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    new String[] {  // classes to rename (so that we can replace them in layoutlib)
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // original-platform-class-name ======> renamed-class-name
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.graphics.Matrix",              "android.graphics._Original_Matrix",
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.graphics.Paint",               "android.graphics._Original_Paint",
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.graphics.Typeface",            "android.graphics._Original_Typeface",
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.graphics.Bitmap",              "android.graphics._Original_Bitmap",
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.graphics.Path",                "android.graphics._Original_Path",
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.graphics.PorterDuffXfermode",  "android.graphics._Original_PorterDuffXfermode",
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.graphics.Shader",              "android.graphics._Original_Shader",
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.graphics.LinearGradient",      "android.graphics._Original_LinearGradient",
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.graphics.BitmapShader",        "android.graphics._Original_BitmapShader",
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.graphics.ComposeShader",       "android.graphics._Original_ComposeShader",
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.graphics.RadialGradient",      "android.graphics._Original_RadialGradient",
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.graphics.SweepGradient",       "android.graphics._Original_SweepGradient",
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.util.FloatMath",               "android.util._Original_FloatMath",
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.view.SurfaceView",             "android.view._Original_SurfaceView",
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    },
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    new String[] { // methods deleted from their return type.
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.graphics.Paint", // class to delete method from
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.graphics.Paint$Align", // list of type identifying methods to delete
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.graphics.Paint$Style",
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.graphics.Paint$Join",
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.graphics.Paint$Cap",
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.graphics.Paint$FontMetrics",
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.graphics.Paint$FontMetricsInt",
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        null }
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            );
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            AsmAnalyzer aa = new AsmAnalyzer(log, osJarPath, agen,
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    new String[] { "android.view.View" },   // derived from
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    new String[] {                          // include classes
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.*", // for android.R
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.util.*",
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "com.android.internal.util.*",
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.view.*",
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.widget.*",
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "com.android.internal.widget.*",
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.text.**",
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.graphics.*",
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.graphics.drawable.*",
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.content.*",
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.content.res.*",
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "org.apache.harmony.xml.*",
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "com.android.internal.R**",
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.pim.*", // for datepicker
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "android.os.*",  // for android.os.Handler
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        });
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            aa.analyze();
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            agen.generate();
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Throw an error if any class failed to get renamed by the generator
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            //
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // IMPORTANT: if you're building the platform and you get this error message,
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // it means the renameClasses[] array in AsmGenerator needs to be updated: some
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // class should have been renamed but it was not found in the input JAR files.
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Set<String> notRenamed = agen.getClassesNotRenamed();
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (notRenamed.size() > 0) {
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // (80-column guide below for error formatting)
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                log.error(
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                  "ERROR when running layoutlib_create: the following classes are referenced\n" +
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                  "by tools/layoutlib/create but were not actually found in the input JAR files.\n" +
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                  "This may be due to some platform classes having been renamed.");
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (String fqcn : notRenamed) {
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    log.error("- Class not found: %s", fqcn.replace('/', '.'));
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (String path : osJarPath) {
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    log.info("- Input JAR : %1$s", path);
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                System.exit(1);
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            System.exit(0);
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (IOException e) {
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            log.exception(e, "Failed to load jar");
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (LogAbortException e) {
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            e.error(log);
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        System.exit(1);
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if args where properly parsed.
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns false if program should exit with command-line usage.
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p/>
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Note: the String[0] is an output parameter wrapped in an array, since there is no
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * "out" parameter support.
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static boolean processArgs(Log log, String[] args,
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<String> osJarPath, String[] osDestJar) {
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < args.length; i++) {
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String s = args[i];
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (s.equals("-v")) {
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                log.setVerbose(true);
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (!s.startsWith("-")) {
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (osDestJar[0] == null) {
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    osDestJar[0] = s;
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    osJarPath.add(s);
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                log.error("Unknow argument: %s", s);
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (osJarPath.isEmpty()) {
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            log.error("Missing parameter: path to input jar");
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (osDestJar[0] == null) {
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            log.error("Missing parameter: path to output jar");
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
175