• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 package ohos;
17 
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.util.List;
21 
22 import static ohos.Uncompress.getResourceFromHap;
23 
24 
25 /**
26  * bundle uncompress.
27  * step1: parse arguments
28  * step2: verity arguments
29  * step3: uncompress arguments
30  *
31  */
32 public class UncompressEntrance {
33     /**
34      * Parses and returns the hap list that supports the device type.
35      */
36     public static final String PARSE_MODE_HAPLIST = "hap-list";
37 
38     /**
39      * Parses and returns the information about the hap.
40      */
41     public static final String PARSE_MODE_HAPINFO = "hap-info";
42 
43     /**
44      * Parses and returns the informations about the hap list that supports the device type and the haps in the app.
45      */
46     public static final String PARSE_MODE_ALL = "all";
47 
48     /**
49      * Device type of default.
50      */
51     public static final String DEVICE_TYPE_DEFAULT = "default";
52 
53     /**
54      * Device type of phone.
55      */
56     public static final String DEVICE_TYPE_PHONE = "phone";
57 
58     /**
59      * Device type of tablet.
60      */
61     public static final String DEVICE_TYPE_TABLET = "tablet";
62 
63     /**
64      * Device type of tv.
65      */
66     public static final String DEVICE_TYPE_TV = "tv";
67 
68     /**
69      * Device type of car.
70      */
71     public static final String DEVICE_TYPE_CAR = "car";
72 
73     /**
74      * Device type of smartWatch.
75      */
76     public static final String DEVICE_TYPE_SMARTWATCH = "smartWatch";
77 
78     /**
79      * Device type of fitnessWatch.
80      */
81     public static final String DEVICE_TYPE_FITNESSWATCH = "fitnessWatch";
82 
83     /**
84      * Device type of fitnessBand.
85      */
86     public static final String DEVICE_TYPE_FITNESSBAND = "fitnessBand";
87 
88     private static final String APPQF_SUFFIX = ".appqf";
89     private static final String APP_SUFFIX = ".app";
90     private static final String HAP_SUFFIX = ".hap";
91     private static final String HSP_SUFFIX = ".hsp";
92 
93     private static final int EXIT_STATUS_NORMAL = 0;
94     private static final int EXIT_STATUS_EXCEPTION = 1;
95     private static final Log LOG = new Log(UncompressEntrance.class.toString());
96 
97     /**
98      * Indicates the parseMode for parseApp interface.
99      */
100     public enum ParseAppMode {
101         ALL(0, "all"),
102         HAP_LIST(1, "hap-list"),
103         HAP_INFO(2, "hap-info");
104 
ParseAppMode(int index, String type)105         ParseAppMode(int index, String type) {
106             this.index = index;
107             this.type = type;
108         }
109 
getType(int index)110         public static String getType(int index) {
111             for (UncompressEntrance.ParseAppMode resType : UncompressEntrance.ParseAppMode.values()) {
112                 if (resType.getIndex() == index) {
113                     return resType.type;
114                 }
115             }
116             return "";
117         }
118 
getIndex()119         public int getIndex() {
120             return index;
121         }
getType()122         public String getType() {
123             return type;
124         }
125         private final int index;
126         private final String type;
127     }
128 
129     /**
130      * Unpack the app.
131      *
132      * @param appPath Indicates the app path.
133      * @param outPath Indicates the out path.
134      * @param deviceType Indicates the device type supported by the haps.If this parameter is null, all the haps will
135      *                   be unpacked.
136      * @param unpackApk Indicates whether to decompress the apk file in the hap.The default value is {@code false},
137      *                  not unpack the apk file.
138      * @return Return the unpack result.
139      */
unpack(String appPath, String outPath, String deviceType, boolean unpackApk)140     public static boolean unpack(String appPath, String outPath, String deviceType, boolean unpackApk) {
141         if (appPath == null || appPath.isEmpty()) {
142             LOG.error("UncompressEntrance::unpack appPath is invalid!");
143             return false;
144         }
145 
146         if (outPath == null || outPath.isEmpty()) {
147             LOG.error("UncompressEntrance::unpack outPath is invalid!");
148             return false;
149         }
150 
151         Utility utility = new Utility();
152         utility.setMode(Utility.MODE_APP);
153         utility.setAppPath(appPath);
154         utility.setDeviceType(deviceType == null ? "" : deviceType);
155         utility.setOutPath(outPath);
156         utility.setUnpackApk(String.valueOf(unpackApk));
157         utility.setForceRewrite("true");
158 
159         if (!UncompressVerify.commandVerify(utility)) {
160             LOG.error("CompressEntrance::unpack verity failed");
161             return false;
162         }
163 
164         if (!Uncompress.unpackageProcess(utility)) {
165             LOG.error("UncompressEntrance::unpackageProcess failed");
166             return false;
167         }
168 
169         return true;
170     }
171 
172     /**
173      * Unpack the hap.
174      *
175      * @param hapPath Indicates the hap path.
176      * @param outPath Indicates the out path.
177      * @param unpackApk Indicates whether to decompress the apk file in the hap.The default value is {@code false},
178      *                  not unpack the apk file.
179      * @return Return the unpack result.
180      */
unpackHap(String hapPath, String outPath, boolean unpackApk)181     public static boolean unpackHap(String hapPath, String outPath, boolean unpackApk) {
182         if (hapPath == null || hapPath.isEmpty()) {
183             LOG.error("UncompressEntrance::unpackHap hapPath is invalid!");
184             return false;
185         }
186 
187         if (outPath == null || outPath.isEmpty()) {
188             LOG.error("UncompressEntrance::unpackHap outPath is invalid!");
189             return false;
190         }
191 
192         Utility utility = new Utility();
193         utility.setMode(Utility.MODE_HAP);
194         utility.setHapPath(hapPath);
195         utility.setDeviceType("");
196         utility.setOutPath(outPath);
197         utility.setUnpackApk(String.valueOf(unpackApk));
198         utility.setForceRewrite("true");
199 
200         if (!UncompressVerify.commandVerify(utility)) {
201             LOG.error("CompressEntrance::unpackHap verity failed");
202             return false;
203         }
204 
205         if (!Uncompress.unpackageProcess(utility)) {
206             LOG.error("UncompressEntrance::unpackageProcess failed");
207             return false;
208         }
209 
210         return true;
211     }
212 
213 
214     /**
215      * Parse the app.
216      *
217      * @param appPath Indicates the app path.
218      * @param parseMode Indicates the parse mode, which can be {@link #PARSE_MODE_HAPLIST}, {@link #PARSE_MODE_HAPINFO},
219      *                  {@link #PARSE_MODE_ALL}.
220      * @param deviceType Indicates the device type supported by the haps, This parameter is required
221      *                   when {@code #parseMode} is {@link #PARSE_MODE_HAPLIST}.
222      * @param hapName Indicates the hap name, This parameter is required when {@code #parseMode}
223      *                is {@link #PARSE_MODE_HAPINFO}.
224      * @param outPath Indicates the out path to unpack the files.
225      * @return Return the uncomperss result of parseApp
226      * @deprecated
227      */
parseApp(String appPath, String parseMode, String deviceType, String hapName, String outPath)228     public static UncompressResult parseApp(String appPath, String parseMode, String deviceType, String hapName,
229                                             String outPath) {
230         UncompressResult compressResult = new UncompressResult();
231 
232         Utility utility = new Utility();
233         utility.setAppPath(appPath);
234         utility.setParseMode(parseMode);
235         utility.setDeviceType(deviceType == null ? "" : deviceType);
236         utility.setHapName(hapName == null ? "" : hapName);
237 
238         if (!UncompressVerify.isPathValid(utility.getAppPath(), true, APP_SUFFIX)) {
239             LOG.error("UncompressEntrance::parseApp must input a app file!");
240             compressResult.setResult(false);
241             compressResult.setMessage("ParseApp verify failed");
242             return compressResult;
243         }
244         if (!UncompressVerify.isParseAppModeValid(utility.getParseMode(), utility.getHapName())) {
245             compressResult.setResult(false);
246             compressResult.setMessage("ParseApp verify failed");
247             return compressResult;
248         }
249 
250         compressResult = Uncompress.uncompressAppByPath(utility);
251 
252         return compressResult;
253     }
254 
255     /**
256      * Parse the app.
257      *
258      * @param input Indicates the InputStream about the app package.
259      * @param parseMode Indicates the parse mode, which can be {@link #PARSE_MODE_HAPLIST}, {@link #PARSE_MODE_HAPINFO},
260      *                  {@link #PARSE_MODE_ALL}.
261      * @param deviceType Indicates the device type supported by the haps, This parameter is required
262      *                   when {@code #parseMode} is {@link #PARSE_MODE_HAPLIST}.
263      * @param hapName Indicates the hap name, This parameter is required when {@code #parseMode}
264      *                is {@link #PARSE_MODE_HAPINFO}.
265      * @param outPath Indicates the out path to unzip temp files.
266      * @return Return the uncomperss result of parseApp
267      * @deprecated
268      */
parseApp(InputStream input, String parseMode, String deviceType, String hapName, String outPath)269     public static UncompressResult parseApp(InputStream input, String parseMode, String deviceType, String hapName,
270                                             String outPath) {
271         UncompressResult compressResult = new UncompressResult();
272 
273         if (input == null) {
274             LOG.error("UncompressEntrance::parseApp input is null!");
275             compressResult.setResult(false);
276             compressResult.setMessage("ParseApp input is null");
277             return compressResult;
278         }
279 
280         Utility utility = new Utility();
281         utility.setMode(Utility.MODE_APP);
282         utility.setParseMode(parseMode);
283         utility.setDeviceType(deviceType == null ? "" : deviceType);
284         utility.setHapName(hapName == null ? "" : hapName);
285 
286         if (!UncompressVerify.isParseAppModeValid(utility.getParseMode(), utility.getHapName())) {
287             compressResult.setResult(false);
288             compressResult.setMessage("ParseApp verify failed");
289             return compressResult;
290         }
291 
292         compressResult = Uncompress.uncompressAppByInput(utility, input);
293 
294         return compressResult;
295     }
296 
297     /**
298      * Parse the app.
299      *
300      * @param appPath Indicates the path about the app package.
301      * @param parseAppMode Indicates the parse mode.
302      * @param hapName Indicates the hap name, This parameter is required when {@code #parseMode}
303      *                is {@link #PARSE_MODE_HAPINFO}.
304      * @return Return the uncomperss result of parseApp
305      */
parseApp(String appPath, ParseAppMode parseAppMode, String hapName)306     public static UncompressResult parseApp(String appPath, ParseAppMode parseAppMode, String hapName) {
307         UncompressResult compressResult = new UncompressResult();
308         Utility utility = new Utility();
309         utility.setAppPath(appPath);
310         utility.setParseMode(parseAppMode.getType());
311         utility.setDeviceType("");
312         utility.setHapName(hapName);
313         if (!UncompressVerify.isPathValid(utility.getAppPath(), true, APP_SUFFIX)) {
314             LOG.error("UncompressEntrance::parseApp must input a app file!");
315             compressResult.setResult(false);
316             compressResult.setMessage("ParseApp verify failed");
317             return compressResult;
318         }
319         if (!UncompressVerify.isParseAppModeValid(utility.getParseMode(), utility.getHapName())) {
320             compressResult.setResult(false);
321             compressResult.setMessage("ParseApp verify failed");
322             return compressResult;
323         }
324         compressResult = Uncompress.uncompressAppByPath(utility);
325 
326         return compressResult;
327     }
328 
329     /**
330      * Parse the app.
331      *
332      * @param input Indicates the input stream about the app package.
333      * @param parseAppMode Indicates the parse mode.
334      * @param hapName Indicates the hap name, This parameter is required when {@code #parseMode}
335      *                is {@link #PARSE_MODE_HAPINFO}.
336      * @return Return the uncomperss result of parseApp
337      */
parseApp(InputStream input, ParseAppMode parseAppMode, String hapName)338     public static UncompressResult parseApp(InputStream input, ParseAppMode parseAppMode, String hapName) {
339         UncompressResult compressResult = new UncompressResult();
340         if (input == null) {
341             LOG.error("UncompressEntrance::parseApp input is null!");
342             compressResult.setResult(false);
343             compressResult.setMessage("ParseApp input is null");
344             return compressResult;
345         }
346         Utility utility = new Utility();
347         utility.setParseMode(parseAppMode.getType());
348         utility.setDeviceType("");
349         utility.setHapName(hapName);
350         if (!UncompressVerify.isParseAppModeValid(utility.getParseMode(), utility.getHapName())) {
351             compressResult.setResult(false);
352             compressResult.setMessage("ParseApp verify failed");
353             return compressResult;
354         }
355         compressResult = Uncompress.uncompressAppByInput(utility, input);
356         return compressResult;
357     }
358 
359     /**
360      * Parse the hap.
361      *
362      * @param hapPath Indicates the hap path.
363      * @return Return the uncomperss result of parseHap
364      */
parseHap(String hapPath)365     public static UncompressResult parseHap(String hapPath) {
366         UncompressResult compressResult = new UncompressResult();
367 
368         Utility utility = new Utility();
369         utility.setHapPath(hapPath);
370         if (!UncompressVerify.isPathValid(utility.getHapPath(), true, HAP_SUFFIX) &&
371                 !UncompressVerify.isPathValid(utility.getHapPath(), true, HSP_SUFFIX)) {
372             LOG.error("UncompressEntrance::parseHap must input a hap file!");
373             compressResult.setResult(false);
374             compressResult.setMessage("ParseHap hapPath is invalid");
375         }
376 
377         compressResult = Uncompress.uncompressHap(utility);
378 
379         return compressResult;
380     }
381 
382     /**
383      * Parse the hap.
384      *
385      * @param input Indicates the InputStream about the app package.
386      * @return Return the uncomperss result of parseHap
387      */
parseHap(InputStream input)388     public static UncompressResult parseHap(InputStream input) {
389         UncompressResult compressResult = new UncompressResult();
390 
391         if (input == null) {
392             LOG.error("UncompressEntrance::parseHap input is null!");
393             compressResult.setResult(false);
394             compressResult.setMessage("ParseHap input is null");
395             return compressResult;
396         }
397 
398         Utility utility = new Utility();
399         compressResult = Uncompress.uncompressHapByInput(utility, input);
400         return compressResult;
401     }
402 
403     /**
404      * Parse the hap resource.
405      *
406      * @param hapPath Indicates the hap path.
407      * @return Return the List<ResourceIndexResult> result of parseHap
408      */
parseResource(String hapPath)409     public static List<ResourceIndexResult> parseResource(String hapPath) throws BundleException, IOException {
410         return getResourceFromHap(hapPath);
411     }
412 
413     /**
414      * Parse the appqf file.
415      *
416      * @param appqfPath Indicates the hap path.
417      * @return Return the List<ResourceIndexResult> result of parseHap
418      */
parseAPPQF(String appqfPath)419     public static APPQFResult parseAPPQF(String appqfPath) {
420         APPQFResult result = new APPQFResult();
421         if (!appqfPath.endsWith(APPQF_SUFFIX)) {
422             LOG.error("UncompressEntrance::parseAPPQF Error, input wrong type APPQF file!");
423             result.setSuccess(false);
424         }
425         try {
426             result.setHqfInfoList(Uncompress.parseAPPQFFile(appqfPath));
427             result.setSuccess(true);
428         } catch (BundleException e) {
429             LOG.error("UncompressEntrance::parseAPPQF failed, read patch.json in APPQF file failed!");
430             result.setSuccess(false);
431         }
432         return result;
433     }
434 
435     /**
436      * uncompress tool main function.
437      *
438      * @param args command line
439      */
main(String[] args)440     public static void main(String[] args) {
441         Utility utility = new Utility();
442 
443         if (!CommandParser.commandParser(utility, args)) {
444             LOG.error("UncompressEntrance::main exit, parser failed");
445             ShowHelp.uncompressHelp();
446             System.exit(EXIT_STATUS_EXCEPTION);
447         }
448 
449         if (!UncompressVerify.commandVerify(utility)) {
450             LOG.error("UncompressEntrance::main exit, verify failed");
451             ShowHelp.uncompressHelp();
452             System.exit(EXIT_STATUS_EXCEPTION);
453         }
454 
455         if (!Uncompress.unpackageProcess(utility)) {
456             LOG.error("UncompressEntrance::main exit, uncompress failed");
457             ShowHelp.uncompressHelp();
458             System.exit(EXIT_STATUS_EXCEPTION);
459         }
460 
461         System.exit(EXIT_STATUS_NORMAL);
462     }
463 }