1 package com.github.mikkoi.maven.plugins.enforcer.rule.propertyusage;
2
3 import org.apache.maven.plugin.logging.Log;
4
5 import javax.annotation.Nonnull;
6 import java.io.File;
7 import java.io.FileInputStream;
8 import java.io.IOException;
9 import java.io.InputStream;
10 import java.nio.charset.Charset;
11 import java.nio.file.Files;
12 import java.nio.file.Paths;
13 import java.util.Collection;
14 import java.util.HashMap;
15 import java.util.HashSet;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Properties;
19 import java.util.Set;
20 import java.util.regex.Matcher;
21 import java.util.regex.Pattern;
22
23
24
25
26 class PropertyFiles {
27
28 private final Log log;
29
30 private final Charset charset;
31
32 private final Pattern commentLineP = Pattern.compile("^[\\s]{0,}[\\#\\!]{1}.{0,}$");
33 private final Pattern simplePropertyLineP = Pattern.compile("^[\\s]{0,}([^=:]{1,})[=:]{1}(.{0,})$", Pattern.COMMENTS | Pattern.UNICODE_CHARACTER_CLASS);
34 private final Pattern notSimplePropertyLineP = Pattern.compile("^[\\s]{0,}([\\S]{1,})[\\s]{0,}(.{0,})$", Pattern.COMMENTS | Pattern.UNICODE_CHARACTER_CLASS);
35 private final Pattern multiLineP = Pattern.compile("\\\\{1}[\\s]{0,}$");
36
37 PropertyFiles(@Nonnull final Log logger, @Nonnull final Charset cset) {
38 log = logger;
39 charset = cset;
40 }
41
42
43
44
45
46 @Nonnull
47 Map<String, Integer> readPropertiesFromFilesWithoutCount(@Nonnull final Collection<String> filenames)
48 throws IOException {
49 Map<String, Integer> results = new HashMap<>();
50 for (String filename : filenames) {
51 File file = new File(filename);
52 Properties properties = new Properties();
53 log.debug("PropertyFiles:readPropertiesFromFilesWithoutCount() Reading file " + filename + ".");
54 try (InputStream inputStream = new FileInputStream(file)) {
55 properties.load(inputStream);
56 for (String name : properties.stringPropertyNames()) {
57 log.debug(" Reading property " + name + ".");
58 results.put(name, 1);
59 }
60 }
61 }
62 return results;
63 }
64
65
66
67
68
69
70
71
72 @Nonnull
73 Map<String, Integer> readPropertiesFromFilesWithCount(@Nonnull final Collection<String> filenames)
74 throws IOException {
75 final Map<String, Integer> results = new HashMap<>();
76 log.debug("commentLineP:" + commentLineP.pattern());
77 log.debug("simplePropertyLineP:" + simplePropertyLineP.pattern());
78 log.debug("simplePropertyLineP:" + simplePropertyLineP.pattern());
79 log.debug("multiLineP:" + multiLineP);
80 for (final String filename : filenames) {
81 log.debug("Reading property file '" + filename + "'.");
82 readPropertiesFromFileWithCount(filename).forEach((key, value) -> results.put(key, value));
83 }
84 return results;
85 }
86
87
88
89
90
91
92
93
94 @Nonnull
95 Map<String, Set<PropertyDefinition>> readPropertiesFromFilesGetDefinitions(@Nonnull final Collection<String> filenames)
96 throws IOException {
97 final Map<String, Set<PropertyDefinition>> results = new HashMap<>();
98 log.debug("commentLineP:" + commentLineP.pattern());
99 log.debug("simplePropertyLineP:" + simplePropertyLineP.pattern());
100 log.debug("simplePropertyLineP:" + simplePropertyLineP.pattern());
101 log.debug("multiLineP:" + multiLineP);
102 for (final String filename : filenames) {
103 log.debug("Reading property file '" + filename + "'.");
104 readPropertiesFromFileGetDefinitions(filename).forEach((key, value) -> {
105 log.debug("key:" + key);
106 log.debug("value:" + value);
107 if(results.containsKey(key)) {
108 results.get(key).addAll(value);
109 } else {
110 results.put(key, value);
111 }
112 });
113 }
114 return results;
115 }
116
117
118
119
120
121
122
123
124 @SuppressWarnings({
125 "squid:S3776",
126 "squid:S134",
127 "squid:S135"
128 })
129 @Nonnull
130 Map<String, Integer> readPropertiesFromFileWithCount(@Nonnull final String filename)
131 throws IOException {
132 final Map<String, Integer> results = new HashMap<>();
133 List<String> rows = Files.readAllLines(Paths.get(filename), charset);
134 boolean readingMultiLineDefinition = false;
135 int linenumber = 0;
136 for (String row : rows) {
137 linenumber++;
138 log.debug(" Reading property row '" + row + "' (" + linenumber + ").");
139 Matcher commentLineM = commentLineP.matcher(row);
140 if (commentLineM.find()) {
141 log.debug(" This is comment line.");
142 continue;
143 }
144 Matcher multiLineM = multiLineP.matcher(row);
145 if (multiLineM.find()) {
146 if (readingMultiLineDefinition) {
147 log.debug(" This is multirow (not first row)");
148 continue;
149 } else {
150 log.debug(" This is multirow (first row).");
151 readingMultiLineDefinition = true;
152 }
153 } else {
154 if (readingMultiLineDefinition) {
155 log.debug(" This is multirow (last row).");
156 readingMultiLineDefinition = false;
157 continue;
158 }
159 }
160 Matcher simplePropertyLineM = simplePropertyLineP.matcher(row);
161 if (simplePropertyLineM.find()) {
162 log.debug(" This is simple property line.");
163 final String key = simplePropertyLineM.group(1).trim();
164 storePropertyName(key, results);
165 continue;
166 }
167 Matcher notSimplePropertyLineM = notSimplePropertyLineP.matcher(row);
168 if (notSimplePropertyLineM.find()) {
169 log.debug(" This is not simple property line.");
170 final String key = notSimplePropertyLineM.group(1).trim();
171 storePropertyName(key, results);
172 continue;
173 }
174 log.debug(" This row matched nothing, propably empty or multiline continuation.");
175 }
176 return results;
177 }
178
179
180
181
182
183
184
185 @SuppressWarnings({
186 "squid:S3776",
187 "squid:S134",
188 "squid:S135"
189 })
190 @Nonnull
191 Map<String, Set<PropertyDefinition>> readPropertiesFromFileGetDefinitions(@Nonnull final String filename)
192 throws IOException {
193 final Map<String, Set<PropertyDefinition>> propertyDefinitions = new HashMap<>();
194 List<String> rows = Files.readAllLines(Paths.get(filename), charset);
195 boolean readingMultiLineDefinition = false;
196 int linenumber = 0;
197 for (String row : rows) {
198 linenumber++;
199 log.debug(" Reading property row '" + row + "' (" + linenumber + ").");
200 Matcher commentLineM = commentLineP.matcher(row);
201 if (commentLineM.find()) {
202 log.debug(" This is comment line.");
203 continue;
204 }
205 Matcher multiLineM = multiLineP.matcher(row);
206 if (multiLineM.find()) {
207 if (readingMultiLineDefinition) {
208 log.debug(" This is multirow (not first row)");
209 continue;
210 } else {
211 log.debug(" This is multirow (first row).");
212 readingMultiLineDefinition = true;
213 }
214 } else {
215 if (readingMultiLineDefinition) {
216 log.debug(" This is multirow (last row).");
217 readingMultiLineDefinition = false;
218 continue;
219 }
220 }
221 Matcher simplePropertyLineM = simplePropertyLineP.matcher(row);
222 if (simplePropertyLineM.find()) {
223 log.debug(" This is simple property line.");
224 final String key = simplePropertyLineM.group(1).trim();
225 final String value = simplePropertyLineM.group(2).trim();
226 storePropertyDefinition(key, value, filename, linenumber, propertyDefinitions);
227 continue;
228 }
229 Matcher notSimplePropertyLineM = notSimplePropertyLineP.matcher(row);
230 if (notSimplePropertyLineM.find()) {
231 log.debug(" This is not simple property line.");
232 final String key = notSimplePropertyLineM.group(1).trim();
233 final String value = notSimplePropertyLineM.group(2).trim();
234 storePropertyDefinition(key, value, filename, linenumber, propertyDefinitions);
235 continue;
236 }
237 log.debug(" This row matched nothing, propably empty or multiline continuation.");
238 }
239 return propertyDefinitions;
240 }
241
242 private void storePropertyName(@Nonnull final String key, @Nonnull final Map<String, Integer> properties) {
243 log.debug(" Reading property " + key + ".");
244 if (!properties.containsKey(key)) {
245 log.debug(" Not defined before.");
246 properties.put(key, 1);
247 } else {
248 log.debug(" Defined before. Update counter.");
249 properties.replace(key, properties.get(key) + 1);
250 }
251 }
252
253 private void storePropertyDefinition(@Nonnull final String key, @Nonnull final String value, @Nonnull final String filename, final int linenumber, @Nonnull final Map<String, Set<PropertyDefinition>> propertyDefinitions) {
254 log.debug(" Reading property " + key + ".");
255 if (propertyDefinitions.containsKey(key)) {
256 log.debug(" Defined before.");
257 propertyDefinitions.get(key).add(new PropertyDefinition(key, value, filename, linenumber));
258 } else {
259 log.debug(" Not defined before.");
260 final Set<PropertyDefinition> defs = new HashSet<>();
261 defs.add(new PropertyDefinition(key, value, filename, linenumber));
262 propertyDefinitions.put(key, defs);
263 }
264 }
265 }