View Javadoc
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.IOException;
7   import java.nio.charset.Charset;
8   import java.nio.file.Files;
9   import java.nio.file.Paths;
10  import java.util.ArrayList;
11  import java.util.Collection;
12  import java.util.HashMap;
13  import java.util.HashSet;
14  import java.util.Map;
15  import java.util.Set;
16  import java.util.regex.Matcher;
17  import java.util.regex.Pattern;
18  
19  /**
20   * Handle issues with .properties files.
21   */
22  class UsageFiles {
23  
24      private final Log log;
25  
26      UsageFiles(final Log log) {
27          this.log = log;
28      }
29  
30      /**
31       * Read usages by matching the property name in template.
32       * this is substituted with the property name.
33       *
34       * @param filenames  Collection of file names to search for property usage.
35       * @param templatesAndProperties  Collection of templates (regexp) to use for matching, and their equivalent property.
36       * @return Map of usages not found and their location (file,row), though location does not matter here.
37       */
38      @Nonnull
39      Set<String> readDefinedUsagesFromFiles(
40              @Nonnull final Collection<String> filenames,
41              @Nonnull final Map<String,String> templatesAndProperties,
42              @Nonnull final Charset charset)
43              throws IOException {
44          final Set<String> results = new HashSet<>();
45          final Map<Pattern,String> tplPatterns = new HashMap<>();
46          templatesAndProperties.forEach((tpl,property) -> tplPatterns.put(Pattern.compile(tpl, Pattern.COMMENTS | Pattern.UNICODE_CHARACTER_CLASS),property));
47          for (final String filename : filenames) {
48              log.debug("Reading file '" + filename + "'.");
49              final String allFile = String.join("", Files.readAllLines(Paths.get(filename), charset));
50              tplPatterns.forEach((tplP, property) -> {
51                  log.debug("    Matching pattern '" + tplP.pattern() + "'.");
52                  log.debug("        Matching with allFile '" + allFile + "'.");
53                  final Matcher matcher = tplP.matcher(allFile);
54                  if (matcher.find()) {
55                      log.debug("        Pattern match found (" + filename + ")" + ", pattern '" + tplP.pattern() + "'.");
56                      results.add(property);
57                  }
58              });
59          }
60          return results;
61      }
62  
63      /**
64       * @param filenames Collection of file names to search for property usage.
65       * @param templates Map of templates (regexp) to use for matching,
66       *                  can be used to separate proper usage patterns for properties.
67       * @return Map of usages not found and their location (file, row).
68       */
69      @Nonnull
70      Set<UsageLocation> readAllUsagesFromFiles(
71              @Nonnull final Collection<String> filenames,
72              @Nonnull final Set<String> templates,
73              @Nonnull final Charset charset)
74              throws IOException {
75          final Set<UsageLocation> foundProperties = new HashSet<>();
76          final ArrayList<Pattern> tplPatterns = new ArrayList<>();
77          templates.forEach(tpl -> tplPatterns.add(Pattern.compile(tpl, Pattern.COMMENTS | Pattern.UNICODE_CHARACTER_CLASS)));
78          for (final String filename : filenames) {
79              log.debug("Reading file '" + filename + "'.");
80              final Collection<String> lines = Files.readAllLines(Paths.get(filename), charset);
81              tplPatterns.forEach(tplP -> {
82                  log.debug("    Matching pattern '" + tplP.pattern() + "'.");
83                  int rowNr = 1;
84                  for (final String row : lines) {
85                      log.debug("        Matching with row '" + row + "'.");
86                      final Matcher matcher = tplP.matcher(row);
87                      if (matcher.find()) {
88                          log.debug("            Pattern match found (" + filename + ":" + rowNr + ")" + ", pattern '" + tplP.pattern() + "'.");
89                          final String propname = matcher.group(1);
90                          log.debug("            Extracted property '" + propname + "'.");
91                          foundProperties.add(new UsageLocation(propname, rowNr, filename));
92                      }
93                      rowNr += 1;
94                  }
95              });
96          }
97          return foundProperties;
98      }
99  
100     static class UsageLocation {
101 
102         @Nonnull
103         private String property;
104 
105         private int row;
106 
107         @Nonnull
108         private String filename;
109 
110         /**
111          * @param propertyVal Property name
112          * @param rowVal      number
113          * @param filenameVal Name of file
114          */
115         UsageLocation(@Nonnull final String propertyVal, final int rowVal, @Nonnull final String filenameVal) {
116             property = propertyVal;
117             row = rowVal;
118             filename = filenameVal;
119         }
120 
121         @Nonnull
122         public String getProperty() {
123             return property;
124         }
125 
126         int getRow() {
127             return row;
128         }
129 
130         @Nonnull
131         String getFilename() {
132             return filename;
133         }
134     }
135 }