1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.puppycrawl.tools.checkstyle.checks.header;
21
22 import java.io.BufferedInputStream;
23 import java.io.IOException;
24 import java.io.InputStreamReader;
25 import java.io.LineNumberReader;
26 import java.io.Reader;
27 import java.io.StringReader;
28 import java.net.URI;
29 import java.nio.charset.Charset;
30 import java.nio.charset.UnsupportedCharsetException;
31 import java.util.ArrayList;
32 import java.util.List;
33 import java.util.Set;
34 import java.util.regex.Pattern;
35
36 import com.puppycrawl.tools.checkstyle.PropertyType;
37 import com.puppycrawl.tools.checkstyle.XdocsPropertyType;
38 import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck;
39 import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
40 import com.puppycrawl.tools.checkstyle.api.ExternalResourceHolder;
41 import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
42
43
44
45
46
47 public abstract class AbstractHeaderCheck extends AbstractFileSetCheck
48 implements ExternalResourceHolder {
49
50
51 private static final Pattern ESCAPED_LINE_FEED_PATTERN = Pattern.compile("\\\\n");
52
53
54 private final List<String> readerLines = new ArrayList<>();
55
56
57 private URI headerFile;
58
59
60 @XdocsPropertyType(PropertyType.STRING)
61 private Charset charset;
62
63
64
65
66
67 protected abstract void postProcessHeaderLines();
68
69
70
71
72
73
74 protected List<String> getHeaderLines() {
75 return List.copyOf(readerLines);
76 }
77
78
79
80
81
82
83 public void setCharset(String charset) {
84 this.charset = createCharset(charset);
85 }
86
87
88
89
90
91
92
93 public void setHeaderFile(URI uri) throws CheckstyleException {
94 if (uri == null) {
95 throw new CheckstyleException(
96 "property 'headerFile' is missing or invalid in module "
97 + getConfiguration().getName());
98 }
99
100 headerFile = uri;
101 }
102
103
104
105
106
107
108 private void loadHeaderFile() throws CheckstyleException {
109 checkHeaderNotInitialized();
110 try (Reader headerReader = new InputStreamReader(new BufferedInputStream(
111 headerFile.toURL().openStream()), charset)) {
112 loadHeader(headerReader);
113 }
114 catch (final IOException ex) {
115 throw new CheckstyleException(
116 "unable to load header file " + headerFile, ex);
117 }
118 }
119
120
121
122
123
124
125 private void checkHeaderNotInitialized() {
126 if (!readerLines.isEmpty()) {
127 throw new IllegalArgumentException(
128 "header has already been set - "
129 + "set either header or headerFile, not both");
130 }
131 }
132
133
134
135
136
137
138
139
140 private static Charset createCharset(String name) {
141 if (!Charset.isSupported(name)) {
142 final String message = "unsupported charset: '" + name + "'";
143 throw new UnsupportedCharsetException(message);
144 }
145 return Charset.forName(name);
146 }
147
148
149
150
151
152
153
154
155
156 public void setHeader(String header) {
157 if (!CommonUtil.isBlank(header)) {
158 checkHeaderNotInitialized();
159
160 final String headerExpandedNewLines = ESCAPED_LINE_FEED_PATTERN
161 .matcher(header).replaceAll("\n");
162
163 try (Reader headerReader = new StringReader(headerExpandedNewLines)) {
164 loadHeader(headerReader);
165 }
166 catch (final IOException ex) {
167 throw new IllegalArgumentException("unable to load header", ex);
168 }
169 }
170 }
171
172
173
174
175
176
177
178 private void loadHeader(final Reader headerReader) throws IOException {
179 try (LineNumberReader lnr = new LineNumberReader(headerReader)) {
180 String line;
181 do {
182 line = lnr.readLine();
183 if (line != null) {
184 readerLines.add(line);
185 }
186 } while (line != null);
187 postProcessHeaderLines();
188 }
189 }
190
191 @Override
192 protected final void finishLocalSetup() throws CheckstyleException {
193 if (headerFile != null) {
194 loadHeaderFile();
195 }
196 }
197
198 @Override
199 public Set<String> getExternalResourceLocations() {
200 final Set<String> result;
201
202 if (headerFile == null) {
203 result = Set.of();
204 }
205 else {
206 result = Set.of(headerFile.toASCIIString());
207 }
208
209 return result;
210 }
211
212 }