1 /*
2  * Copyright (C) 2015 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 com.android.compatibility.common.util;
18 
19 import com.android.tradefed.util.FileUtil;
20 
21 import org.json.JSONArray;
22 import org.json.JSONException;
23 import org.json.JSONObject;
24 import org.json.JSONTokener;
25 import org.xmlpull.v1.XmlPullParserException;
26 import org.xmlpull.v1.XmlPullParserFactory;
27 import org.xmlpull.v1.XmlSerializer;
28 
29 import java.io.File;
30 import java.io.FileOutputStream;
31 import java.io.IOException;
32 import java.io.OutputStream;
33 import java.util.ArrayList;
34 import java.util.HashMap;
35 import java.util.List;
36 import java.util.Map;
37 
38 public class DynamicConfigHandler {
39 
40     private final static String MERGED_CONFIG_FILE_FOLDER = "dynamic-config-files-merged";
41     private static final String NS = null; //xml constant representing null namespace
42     private static final String ENCODING = "UTF-8";
43 
getMergedDynamicConfigFile(File localConfigFile, String apbsConfigJson, String moduleName)44     public static File getMergedDynamicConfigFile(File localConfigFile, String apbsConfigJson,
45             String moduleName) throws IOException, XmlPullParserException, JSONException {
46 
47         Map<String, List<String>> localConfig = DynamicConfig.createConfigMap(localConfigFile);
48         Map<String, List<String>> apbsConfig = parseJsonToConfigMap(apbsConfigJson);
49         localConfig.putAll(apbsConfig);
50         return storeMergedConfigFile(localConfig, moduleName);
51     }
52 
parseJsonToConfigMap(String apbsConfigJson)53     private static Map<String, List<String>> parseJsonToConfigMap(String apbsConfigJson)
54             throws JSONException {
55 
56         Map<String, List<String>> configMap = new HashMap<String, List<String>>();
57         if (apbsConfigJson == null) {
58             return configMap;
59         }
60 
61         JSONObject rootObj  = new JSONObject(new JSONTokener(apbsConfigJson));
62         JSONObject configObject = rootObj.getJSONObject("dynamicConfigEntries");
63         JSONArray keys = configObject.names();
64         for (int i = 0; i < keys.length(); i++) {
65             String key = keys.getString(i);
66             JSONArray jsonValues = configObject.getJSONObject(key).getJSONArray("configValues");
67             List<String> values = new ArrayList<>();
68             for (int j = 0; j < jsonValues.length(); j ++) {
69                 values.add(jsonValues.getString(j));
70             }
71             configMap.put(key, values);
72         }
73         return configMap;
74     }
75 
storeMergedConfigFile(Map<String, List<String>> configMap, String moduleName)76     private static File storeMergedConfigFile(Map<String, List<String>> configMap,
77             String moduleName) throws XmlPullParserException, IOException {
78 
79         File folder = FileUtil.createTempDir(MERGED_CONFIG_FILE_FOLDER);
80         File mergedConfigFile = new File(folder, moduleName + ".dynamic");
81         OutputStream stream = new FileOutputStream(mergedConfigFile);
82         XmlSerializer serializer = XmlPullParserFactory.newInstance().newSerializer();
83         serializer.setOutput(stream, ENCODING);
84         serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
85         serializer.startDocument(ENCODING, false);
86 
87         serializer.startTag(NS, DynamicConfig.CONFIG_TAG);
88         for (String key : configMap.keySet()) {
89             serializer.startTag(NS, DynamicConfig.ENTRY_TAG);
90             serializer.attribute(NS, DynamicConfig.KEY_ATTR, key);
91             for (String value : configMap.get(key)) {
92                 serializer.startTag(NS, DynamicConfig.VALUE_TAG);
93                 serializer.text(value);
94                 serializer.endTag(NS, DynamicConfig.VALUE_TAG);
95             }
96             serializer.endTag(NS, DynamicConfig.ENTRY_TAG);
97         }
98         serializer.endTag(NS, DynamicConfig.CONFIG_TAG);
99         serializer.endDocument();
100         return mergedConfigFile;
101     }
102 }
103