1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.doxia.macro.snippet;
20
21 import java.io.BufferedReader;
22 import java.io.IOException;
23 import java.io.InputStreamReader;
24 import java.net.URL;
25 import java.util.ArrayList;
26 import java.util.List;
27 import java.util.regex.Pattern;
28
29
30
31
32 public class SnippetReader {
33
34 private static final String EOL = System.getProperty("line.separator");
35
36
37 private URL source;
38
39
40 private String encoding;
41
42
43
44
45
46
47
48 public SnippetReader(URL src, String encoding) {
49 this.source = src;
50 this.encoding = encoding;
51 }
52
53
54
55
56
57
58 public SnippetReader(URL src) {
59 this(src, null);
60 }
61
62
63
64
65
66
67
68
69 public StringBuffer readSnippet(String snippetId) throws IOException {
70 List<String> lines = readLines(snippetId);
71 int minIndent = minIndent(lines);
72 StringBuffer result = new StringBuffer();
73 for (String line : lines) {
74 result.append(line.substring(minIndent));
75 result.append(EOL);
76 }
77 return result;
78 }
79
80
81
82
83
84
85
86 int minIndent(List<String> lines) {
87 int minIndent = Integer.MAX_VALUE;
88 for (String line : lines) {
89 minIndent = Math.min(minIndent, indent(line));
90 }
91 return minIndent;
92 }
93
94
95
96
97
98
99
100 int indent(String line) {
101 char[] chars = line.toCharArray();
102 int indent = 0;
103 for (; indent < chars.length; indent++) {
104 if (chars[indent] != ' ') {
105 break;
106 }
107 }
108 return indent;
109 }
110
111
112
113
114
115
116
117
118 private List<String> readLines(String snippetId) throws IOException {
119 BufferedReader reader;
120 if (encoding == null || "".equals(encoding)) {
121 reader = new BufferedReader(new InputStreamReader(source.openStream()));
122 } else {
123 reader = new BufferedReader(new InputStreamReader(source.openStream(), encoding));
124 }
125
126 List<String> lines = new ArrayList<>();
127 try (BufferedReader withReader = reader) {
128 boolean capture = false;
129 String line;
130 boolean foundStart = false;
131 boolean foundEnd = false;
132 boolean hasSnippetId = snippetId != null && !snippetId.isEmpty();
133 while ((line = withReader.readLine()) != null) {
134 if (!hasSnippetId) {
135 lines.add(line);
136 } else {
137 if (isStart(snippetId, line)) {
138 capture = true;
139 foundStart = true;
140 } else if (isEnd(snippetId, line)) {
141 foundEnd = true;
142 break;
143 } else if (capture) {
144 lines.add(line);
145 }
146 }
147 }
148
149 if (hasSnippetId && !foundStart) {
150 throw new IOException("Failed to find START of snippet " + snippetId + " in file at URL: " + source);
151 }
152 if (hasSnippetId && !foundEnd) {
153 throw new IOException("Failed to find END of snippet " + snippetId + " in file at URL: " + source);
154 }
155 }
156 return lines;
157 }
158
159
160
161
162
163
164
165
166 protected boolean isStart(String snippetId, String line) {
167 return isDemarcator(snippetId, "START", line);
168 }
169
170
171
172
173
174
175
176
177
178 protected static boolean isDemarcator(String snippetId, String what, String line) {
179
180
181 String snippetRegExp = "(^|\\W)(?i:SNIPPET)($|\\W)";
182 String snippetIdRegExp = "(^|\\W)" + snippetId + "($|\\W)";
183 String whatRegExp = "(^|\\W)(?i:" + what + ")($|\\W)";
184
185 return Pattern.compile(snippetRegExp).matcher(line).find()
186 && Pattern.compile(whatRegExp).matcher(line).find()
187 && Pattern.compile(snippetIdRegExp).matcher(line).find();
188 }
189
190
191
192
193
194
195
196
197 protected boolean isEnd(String snippetId, String line) {
198 return isDemarcator(snippetId, "END", line);
199 }
200 }