1 /*
2  * Copyright (C) 2009 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 
17 package signature.compare;
18 
19 import signature.UsageException;
20 import signature.compare.model.IApiDelta;
21 import signature.compare.model.IPackageDelta;
22 import signature.compare.model.impl.SigDelta;
23 import signature.converter.Visibility;
24 import signature.converter.dex.DexFactory;
25 import signature.converter.doclet.DocletFactory;
26 import signature.io.IApiDeltaExternalizer;
27 import signature.io.IApiLoader;
28 import signature.io.html.HtmlDeltaExternalizer;
29 import signature.io.impl.BinaryApi;
30 import signature.model.IApi;
31 
32 import java.io.IOException;
33 import java.util.Collections;
34 import java.util.HashSet;
35 import java.util.Set;
36 
37 /**
38  * Driver class for the --compare option.
39  */
40 public class Main {
41 
42     /**
43      * <pre>
44      * --from=(doclet | dex | sig) <sourcefiles>
45      * --name <name>
46      * --to=(doclet | dex | sig) <sourcefiles>
47      * --name <name>
48      * --out directory
49      * --packages packageName{ packageName}
50      * </pre>
51      */
main(String[] args)52     public static void main(String[] args) throws IOException {
53         int at = 0;
54 
55         if (!"--from".equals(args[at])) {
56             throw new UsageException();
57         }
58         String fromType = args[++at];
59 
60         boolean hasName = false;
61         Set<String> fromFiles = new HashSet<String>();
62         ++at;
63         for (/* at */; at < args.length; at++) {
64             if ("--name".equals(args[at])) {
65                 hasName = true;
66                 break;
67             }
68             if ("--to".equals(args[at])) {
69                 break;
70             }
71             fromFiles.add(args[at]);
72         }
73 
74         String nameFrom = null;
75         if (hasName) {
76             nameFrom = "";
77             if (!"--name".equals(args[at])) {
78                 throw new UsageException();
79             }
80             ++at;
81             for (/* at */; at < args.length; at++) {
82                 if ("--to".equals(args[at])) {
83                     break;
84                 }
85                 nameFrom += args[at];
86                 nameFrom += " ";
87             }
88             nameFrom = nameFrom.trim();
89         }
90 
91         if (!"--to".equals(args[at])) {
92             throw new UsageException();
93         }
94         String toType = args[++at];
95 
96         hasName = false;
97         Set<String> toFiles = new HashSet<String>();
98         ++at;
99         for (/* at */; at < args.length; at++) {
100             if ("--name".equals(args[at])) {
101                 hasName = true;
102                 break;
103             }
104             if ("--out".equals(args[at])) {
105                 break;
106             }
107             toFiles.add(args[at]);
108         }
109 
110         String nameTo = null;
111         if (hasName) {
112             nameTo = "";
113             if (!"--name".equals(args[at])) {
114                 throw new UsageException();
115             }
116             ++at;
117             for (/* at */; at < args.length; at++) {
118                 if ("--out".equals(args[at])) {
119                     break;
120                 }
121                 nameTo += args[at];
122                 nameTo += " ";
123             }
124             nameTo = nameTo.trim();
125         }
126 
127         if (!"--out".equals(args[at])) {
128             throw new UsageException();
129         }
130         String output = args[++at];
131 
132         if (!"--packages".equals(args[++at])) {
133             throw new UsageException();
134         }
135         Set<String> packages = new HashSet<String>();
136         ++at;
137         for (/* at */; at < args.length; at++) {
138             packages.add(args[at]);
139         }
140 
141         IApiComparator comparator = new ApiComparator();
142         IApi fromApi = getApi(fromType, nameFrom, fromFiles, packages);
143         IApi toApi = getApi(toType, nameTo, toFiles, packages);
144 
145         IApiDeltaExternalizer externalizer = new HtmlDeltaExternalizer();
146         System.out.println("Writing delta report to " + output);
147         IApiDelta delta = comparator.compare(fromApi, toApi);
148         if (delta == null) {
149             delta = new EmptyDelta(fromApi, toApi);
150         }
151 
152         externalizer.externalize(output, delta);
153     }
154 
155     private static class EmptyDelta extends SigDelta<IApi> implements
156             IApiDelta {
EmptyDelta(IApi from, IApi to)157         public EmptyDelta(IApi from, IApi to) {
158             super(from, to);
159         }
160 
getPackageDeltas()161         public Set<IPackageDelta> getPackageDeltas() {
162             return Collections.emptySet();
163         }
164     }
165 
getApi(String specType, String name, Set<String> fileNames, Set<String> packageNames)166     private static IApi getApi(String specType, String name,
167             Set<String> fileNames, Set<String> packageNames) throws
168             IOException {
169         System.out.println("Loading " + name + " of type " + specType
170                 + " from " + fileNames);
171         IApiLoader factory = null;
172         if ("doclet".equals(specType)) {
173             checkName(name);
174             factory = new DocletFactory();
175         } else if ("dex".equals(specType)) {
176             checkName(name);
177             factory = new DexFactory();
178         } else if ("sig".equals(specType)) {
179             factory = new BinaryApi();
180         } else {
181             throw new UsageException();
182         }
183         return factory.loadApi(name, Visibility.PROTECTED, fileNames,
184                 packageNames);
185     }
186 
checkName(String name)187     private static void checkName(String name) {
188         if (name == null) {
189             throw new UsageException();
190         }
191     }
192 }
193