Main.java revision 2473ef5654b2a4b65132a35677c6ddfd481aab2c
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.tools.layoutlib.create;
18
19import java.io.IOException;
20import java.util.ArrayList;
21import java.util.Set;
22
23
24
25public class Main {
26
27    public static void main(String[] args) {
28
29        Log log = new Log();
30
31        ArrayList<String> osJarPath = new ArrayList<String>();
32        String[] osDestJar = { null };
33
34        if (!processArgs(log, args, osJarPath, osDestJar)) {
35            log.error("Usage: layoutlib_create [-v] output.jar input.jar ...");
36            System.exit(1);
37        }
38
39        log.info("Output: %1$s", osDestJar[0]);
40        for (String path : osJarPath) {
41            log.info("Input :      %1$s", path);
42        }
43
44        try {
45            AsmGenerator agen = new AsmGenerator(log, osDestJar[0],
46                    new Class<?>[] {  // classes to inject in the final JAR
47                        OverrideMethod.class,
48                        MethodListener.class,
49                        MethodAdapter.class
50                    },
51                    new String[] {  // methods to force override
52                        "android.view.View#isInEditMode",
53                        "android.content.res.Resources$Theme#obtainStyledAttributes",
54                    },
55                    new String[] {  // classes to rename (so that we can replace them in layoutlib)
56                        // original-platform-class-name ======> renamed-class-name
57                        "android.graphics.Bitmap",              "android.graphics._Original_Bitmap",
58                        "android.graphics.BitmapShader",        "android.graphics._Original_BitmapShader",
59                        "android.graphics.Canvas",              "android.graphics._Original_Canvas",
60                        "android.graphics.ComposeShader",       "android.graphics._Original_ComposeShader",
61                        "android.graphics.LinearGradient",      "android.graphics._Original_LinearGradient",
62                        "android.graphics.Matrix",              "android.graphics._Original_Matrix",
63                        "android.graphics.Paint",               "android.graphics._Original_Paint",
64                        "android.graphics.Path",                "android.graphics._Original_Path",
65                        "android.graphics.PorterDuffXfermode",  "android.graphics._Original_PorterDuffXfermode",
66                        "android.graphics.RadialGradient",      "android.graphics._Original_RadialGradient",
67                        "android.graphics.Shader",              "android.graphics._Original_Shader",
68                        "android.graphics.SweepGradient",       "android.graphics._Original_SweepGradient",
69                        "android.graphics.Typeface",            "android.graphics._Original_Typeface",
70                        "android.os.ServiceManager",            "android.os._Original_ServiceManager",
71                        "android.util.FloatMath",               "android.util._Original_FloatMath",
72                        "android.view.SurfaceView",             "android.view._Original_SurfaceView",
73                        "android.view.accessibility.AccessibilityManager", "android.view.accessibility._Original_AccessibilityManager",
74                    },
75                    new String[] { // methods deleted from their return type.
76                        "android.graphics.Paint", // class to delete method from
77                        "android.graphics.Paint$Align", // list of type identifying methods to delete
78                        "android.graphics.Paint$Style",
79                        "android.graphics.Paint$Join",
80                        "android.graphics.Paint$Cap",
81                        "android.graphics.Paint$FontMetrics",
82                        "android.graphics.Paint$FontMetricsInt",
83                        null }
84            );
85
86            AsmAnalyzer aa = new AsmAnalyzer(log, osJarPath, agen,
87                    new String[] { "android.view.View" },   // derived from
88                    new String[] {                          // include classes
89                        "android.*", // for android.R
90                        "android.util.*",
91                        "com.android.internal.util.*",
92                        "android.view.*",
93                        "android.widget.*",
94                        "com.android.internal.widget.*",
95                        "android.text.**",
96                        "android.graphics.*",
97                        "android.graphics.drawable.*",
98                        "android.content.*",
99                        "android.content.res.*",
100                        "org.apache.harmony.xml.*",
101                        "com.android.internal.R**",
102                        "android.pim.*", // for datepicker
103                        "android.os.*",  // for android.os.Handler
104                        });
105            aa.analyze();
106            agen.generate();
107
108            // Throw an error if any class failed to get renamed by the generator
109            //
110            // IMPORTANT: if you're building the platform and you get this error message,
111            // it means the renameClasses[] array in AsmGenerator needs to be updated: some
112            // class should have been renamed but it was not found in the input JAR files.
113            Set<String> notRenamed = agen.getClassesNotRenamed();
114            if (notRenamed.size() > 0) {
115                // (80-column guide below for error formatting)
116                // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
117                log.error(
118                  "ERROR when running layoutlib_create: the following classes are referenced\n" +
119                  "by tools/layoutlib/create but were not actually found in the input JAR files.\n" +
120                  "This may be due to some platform classes having been renamed.");
121                for (String fqcn : notRenamed) {
122                    log.error("- Class not found: %s", fqcn.replace('/', '.'));
123                }
124                for (String path : osJarPath) {
125                    log.info("- Input JAR : %1$s", path);
126                }
127                System.exit(1);
128            }
129
130            System.exit(0);
131        } catch (IOException e) {
132            log.exception(e, "Failed to load jar");
133        } catch (LogAbortException e) {
134            e.error(log);
135        }
136
137        System.exit(1);
138    }
139
140    /**
141     * Returns true if args where properly parsed.
142     * Returns false if program should exit with command-line usage.
143     * <p/>
144     * Note: the String[0] is an output parameter wrapped in an array, since there is no
145     * "out" parameter support.
146     */
147    private static boolean processArgs(Log log, String[] args,
148            ArrayList<String> osJarPath, String[] osDestJar) {
149        for (int i = 0; i < args.length; i++) {
150            String s = args[i];
151            if (s.equals("-v")) {
152                log.setVerbose(true);
153            } else if (!s.startsWith("-")) {
154                if (osDestJar[0] == null) {
155                    osDestJar[0] = s;
156                } else {
157                    osJarPath.add(s);
158                }
159            } else {
160                log.error("Unknow argument: %s", s);
161                return false;
162            }
163        }
164
165        if (osJarPath.isEmpty()) {
166            log.error("Missing parameter: path to input jar");
167            return false;
168        }
169        if (osDestJar[0] == null) {
170            log.error("Missing parameter: path to output jar");
171            return false;
172        }
173
174        return true;
175    }
176
177}
178