Skip to content

Commit d2c6ea5

Browse files
committed
Polish
1 parent 805b715 commit d2c6ea5

File tree

2 files changed

+64
-78
lines changed

2 files changed

+64
-78
lines changed

spring-webflux/src/main/java/org/springframework/web/reactive/resource/AppCacheManifestTransformer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ public Mono<Resource> transform(ServerWebExchange exchange, Resource inputResour
125125
return Flux.generate(new LineGenerator(content))
126126
.concatMap(info -> processLine(info, exchange, resource, chain))
127127
.collect(() -> new LineAggregator(resource, content), LineAggregator::add)
128-
.flatMap(aggregator -> Mono.just(aggregator.createResource()));
128+
.map(LineAggregator::createResource);
129129
});
130130
}
131131

spring-webflux/src/main/java/org/springframework/web/reactive/resource/CssLinkResourceTransformer.java

Lines changed: 63 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@
2222
import java.nio.charset.StandardCharsets;
2323
import java.util.ArrayList;
2424
import java.util.Collections;
25-
import java.util.HashSet;
2625
import java.util.List;
2726
import java.util.Set;
27+
import java.util.SortedSet;
28+
import java.util.TreeSet;
2829

2930
import org.apache.commons.logging.Log;
3031
import org.apache.commons.logging.LogFactory;
@@ -83,27 +84,27 @@ public Mono<Resource> transform(ServerWebExchange exchange, Resource resource,
8384
logger.trace("Transforming resource: " + newResource);
8485
}
8586

86-
byte[] bytes = new byte[0];
87+
byte[] bytes;
8788
try {
8889
bytes = FileCopyUtils.copyToByteArray(newResource.getInputStream());
8990
}
9091
catch (IOException ex) {
9192
return Mono.error(Exceptions.propagate(ex));
9293
}
93-
String fullContent = new String(bytes, DEFAULT_CHARSET);
94-
List<Segment> segments = parseContent(fullContent);
94+
String cssContent = new String(bytes, DEFAULT_CHARSET);
95+
List<ContentChunkInfo> contentChunkInfos = parseContent(cssContent);
9596

96-
if (segments.isEmpty()) {
97+
if (contentChunkInfos.isEmpty()) {
9798
if (logger.isTraceEnabled()) {
9899
logger.trace("No links found.");
99100
}
100101
return Mono.just(newResource);
101102
}
102103

103-
return Flux.fromIterable(segments)
104-
.concatMap(segment -> {
105-
String segmentContent = segment.getContent(fullContent);
106-
if (segment.isLink() && !hasScheme(segmentContent)) {
104+
return Flux.fromIterable(contentChunkInfos)
105+
.concatMap(contentChunkInfo -> {
106+
String segmentContent = contentChunkInfo.getContent(cssContent);
107+
if (contentChunkInfo.isLink() && !hasScheme(segmentContent)) {
107108
String link = toAbsolutePath(segmentContent, exchange);
108109
return resolveUrlPath(link, exchange, newResource, transformerChain)
109110
.defaultIfEmpty(segmentContent);
@@ -116,39 +117,30 @@ public Mono<Resource> transform(ServerWebExchange exchange, Resource resource,
116117
writer.write(chunk);
117118
return writer;
118119
})
119-
.flatMap(writer -> {
120+
.map(writer -> {
120121
byte[] newContent = writer.toString().getBytes(DEFAULT_CHARSET);
121-
return Mono.just(new TransformedResource(resource, newContent));
122+
return new TransformedResource(resource, newContent);
122123
});
123124
});
124125
}
125126

126-
private List<Segment> parseContent(String fullContent) {
127-
128-
List<Segment> links = new ArrayList<>();
129-
for (LinkParser parser : this.linkParsers) {
130-
links.addAll(parser.parseLinks(fullContent));
131-
}
132-
127+
private List<ContentChunkInfo> parseContent(String cssContent) {
128+
SortedSet<ContentChunkInfo> links = new TreeSet<>();
129+
this.linkParsers.forEach(parser -> parser.parse(cssContent, links));
133130
if (links.isEmpty()) {
134131
return Collections.emptyList();
135132
}
136-
137-
Collections.sort(links);
138-
139133
int index = 0;
140-
List<Segment> allSegments = new ArrayList<>(links);
141-
for (Segment link : links) {
142-
allSegments.add(new Segment(index, link.getStart(), false));
134+
List<ContentChunkInfo> result = new ArrayList<>();
135+
for (ContentChunkInfo link : links) {
136+
result.add(new ContentChunkInfo(index, link.getStart(), false));
137+
result.add(link);
143138
index = link.getEnd();
144139
}
145-
if (index < fullContent.length()) {
146-
allSegments.add(new Segment(index, fullContent.length(), false));
140+
if (index < cssContent.length()) {
141+
result.add(new ContentChunkInfo(index, cssContent.length(), false));
147142
}
148-
149-
Collections.sort(allSegments);
150-
151-
return allSegments;
143+
return result;
152144
}
153145

154146
private boolean hasScheme(String link) {
@@ -157,66 +149,60 @@ private boolean hasScheme(String link) {
157149
}
158150

159151

152+
/**
153+
* Extract content chunks that represent links.
154+
*/
160155
@FunctionalInterface
161156
protected interface LinkParser {
162157

163-
Set<Segment> parseLinks(String fullContent);
158+
void parse(String cssContent, SortedSet<ContentChunkInfo> result);
164159

165160
}
166161

167162

168163
protected static abstract class AbstractLinkParser implements LinkParser {
169164

170-
/** Return the keyword to use to search for links. */
165+
/** Return the keyword to use to search for links, e.g. "@import", "url(" */
171166
protected abstract String getKeyword();
172167

173168
@Override
174-
public Set<Segment> parseLinks(String fullContent) {
175-
Set<Segment> linksToAdd = new HashSet<>(8);
176-
int index = 0;
177-
do {
178-
index = fullContent.indexOf(getKeyword(), index);
179-
if (index == -1) {
180-
break;
169+
public void parse(String content, SortedSet<ContentChunkInfo> result) {
170+
int position = 0;
171+
while (true) {
172+
position = content.indexOf(getKeyword(), position);
173+
if (position == -1) {
174+
return;
181175
}
182-
index = skipWhitespace(fullContent, index + getKeyword().length());
183-
if (fullContent.charAt(index) == '\'') {
184-
index = addLink(index, "'", fullContent, linksToAdd);
176+
position += getKeyword().length();
177+
while (Character.isWhitespace(content.charAt(position))) {
178+
position++;
185179
}
186-
else if (fullContent.charAt(index) == '"') {
187-
index = addLink(index, "\"", fullContent, linksToAdd);
180+
if (content.charAt(position) == '\'') {
181+
position = extractLink(position, '\'', content, result);
188182
}
189-
else {
190-
index = extractLink(index, fullContent, linksToAdd);
191-
183+
else if (content.charAt(position) == '"') {
184+
position = extractLink(position, '"', content, result);
192185
}
193-
}
194-
while (true);
195-
return linksToAdd;
196-
}
186+
else {
187+
position = extractUnquotedLink(position, content, result);
197188

198-
private int skipWhitespace(String content, int index) {
199-
while (true) {
200-
if (Character.isWhitespace(content.charAt(index))) {
201-
index++;
202-
continue;
203189
}
204-
return index;
205190
}
206191
}
207192

208-
protected int addLink(int index, String endKey, String content, Set<Segment> linksToAdd) {
193+
protected int extractLink(int index, char endChar, String content, Set<ContentChunkInfo> result) {
209194
int start = index + 1;
210-
int end = content.indexOf(endKey, start);
211-
linksToAdd.add(new Segment(start, end, true));
212-
return end + endKey.length();
195+
int end = content.indexOf(endChar, start);
196+
result.add(new ContentChunkInfo(start, end, true));
197+
return end + 1;
213198
}
214199

215200
/**
216201
* Invoked after a keyword match, after whitespaces removed, and when
217202
* the next char is neither a single nor double quote.
218203
*/
219-
protected abstract int extractLink(int index, String content, Set<Segment> linksToAdd);
204+
protected abstract int extractUnquotedLink(int position, String content,
205+
Set<ContentChunkInfo> linksToAdd);
220206

221207
}
222208

@@ -229,14 +215,14 @@ protected String getKeyword() {
229215
}
230216

231217
@Override
232-
protected int extractLink(int index, String content, Set<Segment> linksToAdd) {
233-
if (content.substring(index, index + 4).equals("url(")) {
234-
// Ignore, UrlLinkParser will take care
218+
protected int extractUnquotedLink(int position, String content, Set<ContentChunkInfo> result) {
219+
if (content.substring(position, position + 4).equals("url(")) {
220+
// Ignore, UrlFunctionContentParser will take care
235221
}
236222
else if (logger.isErrorEnabled()) {
237-
logger.error("Unexpected syntax for @import link at index " + index);
223+
logger.error("Unexpected syntax for @import link at index " + position);
238224
}
239-
return index;
225+
return position;
240226
}
241227
}
242228

@@ -249,26 +235,26 @@ protected String getKeyword() {
249235
}
250236

251237
@Override
252-
protected int extractLink(int index, String content, Set<Segment> linksToAdd) {
238+
protected int extractUnquotedLink(int position, String content, Set<ContentChunkInfo> result) {
253239
// A url() function without unquoted
254-
return addLink(index - 1, ")", content, linksToAdd);
240+
return extractLink(position - 1, ')', content, result);
255241
}
256242
}
257243

258244

259-
private static class Segment implements Comparable<Segment> {
245+
private static class ContentChunkInfo implements Comparable<ContentChunkInfo> {
260246

261247
private final int start;
262248

263249
private final int end;
264250

265-
private final boolean link;
251+
private final boolean isLink;
266252

267253

268-
public Segment(int start, int end, boolean isLink) {
254+
ContentChunkInfo(int start, int end, boolean isLink) {
269255
this.start = start;
270256
this.end = end;
271-
this.link = isLink;
257+
this.isLink = isLink;
272258
}
273259

274260

@@ -281,15 +267,15 @@ public int getEnd() {
281267
}
282268

283269
public boolean isLink() {
284-
return this.link;
270+
return this.isLink;
285271
}
286272

287273
public String getContent(String fullContent) {
288274
return fullContent.substring(this.start, this.end);
289275
}
290276

291277
@Override
292-
public int compareTo(Segment other) {
278+
public int compareTo(ContentChunkInfo other) {
293279
return (this.start < other.start ? -1 : (this.start == other.start ? 0 : 1));
294280
}
295281

@@ -298,8 +284,8 @@ public boolean equals(@Nullable Object obj) {
298284
if (this == obj) {
299285
return true;
300286
}
301-
if (obj != null && obj instanceof Segment) {
302-
Segment other = (Segment) obj;
287+
if (obj != null && obj instanceof ContentChunkInfo) {
288+
ContentChunkInfo other = (ContentChunkInfo) obj;
303289
return (this.start == other.start && this.end == other.end);
304290
}
305291
return false;

0 commit comments

Comments
 (0)