android: Add simple utility class to generate settings_t compatible config snippets
[strongswan.git] / src / frontends / android / src / org / strongswan / android / utils / SettingsWriter.java
1 /*
2 * Copyright (C) 2015 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 package org.strongswan.android.utils;
17
18 import java.util.Arrays;
19 import java.util.LinkedHashMap;
20 import java.util.Map.Entry;
21 import java.util.regex.Pattern;
22
23
24 /**
25 * Simple generator for data/files that may be parsed by libstrongswan's
26 * settings_t class.
27 */
28 public class SettingsWriter
29 {
30 /**
31 * Top-level section
32 */
33 private final SettingsSection mTop = new SettingsSection();
34
35 /**
36 * Set a string value
37 * @param key
38 * @param value
39 * @return the writer
40 */
41 public SettingsWriter setValue(String key, String value)
42 {
43 Pattern pattern = Pattern.compile("[^#{}=\"\\n\\t ]+");
44 if (key == null || !pattern.matcher(key).matches())
45 {
46 return this;
47 }
48 String[] keys = key.split("\\.");
49 SettingsSection section = mTop;
50 section = findOrCreateSection(Arrays.copyOfRange(keys, 0, keys.length-1));
51 section.Settings.put(keys[keys.length-1], value);
52 return this;
53 }
54
55 /**
56 * Set an integer value
57 * @param key
58 * @param value
59 * @return the writer
60 */
61 public SettingsWriter setValue(String key, Integer value)
62 {
63 return setValue(key, value == null ? null : value.toString());
64 }
65
66 /**
67 * Set a boolean value
68 * @param key
69 * @param value
70 * @return the writer
71 */
72 public SettingsWriter setValue(String key, Boolean value)
73 {
74 return setValue(key, value == null ? null : value ? "1" : "0");
75 }
76
77 /**
78 * Serializes the settings to a string in the format understood by
79 * libstrongswan's settings_t parser.
80 * @return serialized settings
81 */
82 public String serialize()
83 {
84 StringBuilder builder = new StringBuilder();
85 serializeSection(mTop, builder);
86 return builder.toString();
87 }
88
89 /**
90 * Serialize the settings in a section and recursively serialize sub-sections
91 * @param section
92 * @param builder
93 */
94 private void serializeSection(SettingsSection section, StringBuilder builder)
95 {
96 for (Entry<String, String> setting : section.Settings.entrySet())
97 {
98 builder.append(setting.getKey()).append('=');
99 if (setting.getValue() != null)
100 {
101 builder.append("\"").append(escapeValue(setting.getValue())).append("\"");
102 }
103 builder.append('\n');
104 }
105
106 for (Entry<String, SettingsSection> subsection : section.Sections.entrySet())
107 {
108 builder.append(subsection.getKey()).append(" {\n");
109 serializeSection(subsection.getValue(), builder);
110 builder.append("}\n");
111 }
112 }
113
114 /**
115 * Escape value so it may be wrapped in "
116 * @param value
117 * @return
118 */
119 private String escapeValue(String value)
120 {
121 return value.replace("\"", "\\\"");
122 }
123
124 /**
125 * Find or create the nested sections with the given names
126 * @param sections list of section names
127 * @return final section
128 */
129 private SettingsSection findOrCreateSection(String[] sections)
130 {
131 SettingsSection section = mTop;
132 for (String name : sections)
133 {
134 SettingsSection subsection = section.Sections.get(name);
135 if (subsection == null)
136 {
137 subsection = new SettingsSection();
138 section.Sections.put(name, subsection);
139 }
140 section = subsection;
141 }
142 return section;
143 }
144
145 /**
146 * A section containing sub-sections and settings.
147 */
148 private class SettingsSection
149 {
150 /**
151 * Assigned key/value pairs
152 */
153 LinkedHashMap<String,String> Settings = new LinkedHashMap<String, String>();
154
155 /**
156 * Assigned sub-sections
157 */
158 LinkedHashMap<String,SettingsSection> Sections = new LinkedHashMap<String, SettingsWriter.SettingsSection>();
159 }
160 }