Avoid regex pattern matching for simple String replacement steps
Issue: SPR-17279
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -183,7 +183,7 @@ public class DateTimeFormatterFactory {
|
|||||||
// Using strict parsing to align with Joda-Time and standard DateFormat behavior:
|
// Using strict parsing to align with Joda-Time and standard DateFormat behavior:
|
||||||
// otherwise, an overflow like e.g. Feb 29 for a non-leap-year wouldn't get rejected.
|
// otherwise, an overflow like e.g. Feb 29 for a non-leap-year wouldn't get rejected.
|
||||||
// However, with strict parsing, a year digit needs to be specified as 'u'...
|
// However, with strict parsing, a year digit needs to be specified as 'u'...
|
||||||
String patternToUse = this.pattern.replace("yy", "uu");
|
String patternToUse = StringUtils.replace(this.pattern, "yy", "uu");
|
||||||
dateTimeFormatter = DateTimeFormatter.ofPattern(patternToUse).withResolverStyle(ResolverStyle.STRICT);
|
dateTimeFormatter = DateTimeFormatter.ofPattern(patternToUse).withResolverStyle(ResolverStyle.STRICT);
|
||||||
}
|
}
|
||||||
else if (this.iso != null && this.iso != ISO.NONE) {
|
else if (this.iso != null && this.iso != ISO.NONE) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -24,6 +24,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ClassFileTransformer-based weaver, allowing for a list of transformers to be
|
* ClassFileTransformer-based weaver, allowing for a list of transformers to be
|
||||||
@@ -73,7 +74,7 @@ public class WeavingTransformer {
|
|||||||
* @return (possibly transformed) class byte definition
|
* @return (possibly transformed) class byte definition
|
||||||
*/
|
*/
|
||||||
public byte[] transformIfNecessary(String className, byte[] bytes) {
|
public byte[] transformIfNecessary(String className, byte[] bytes) {
|
||||||
String internalName = className.replace(".", "/");
|
String internalName = StringUtils.replace(className, ".", "/");
|
||||||
return transformIfNecessary(className, internalName, bytes, null);
|
return transformIfNecessary(className, internalName, bytes, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package org.springframework.expression.spel.ast;
|
|||||||
import org.springframework.asm.MethodVisitor;
|
import org.springframework.asm.MethodVisitor;
|
||||||
import org.springframework.expression.TypedValue;
|
import org.springframework.expression.TypedValue;
|
||||||
import org.springframework.expression.spel.CodeFlow;
|
import org.springframework.expression.spel.CodeFlow;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expression language AST node that represents a string literal.
|
* Expression language AST node that represents a string literal.
|
||||||
@@ -33,9 +34,13 @@ public class StringLiteral extends Literal {
|
|||||||
|
|
||||||
|
|
||||||
public StringLiteral(String payload, int pos, String value) {
|
public StringLiteral(String payload, int pos, String value) {
|
||||||
super(payload,pos);
|
super(payload, pos);
|
||||||
value = value.substring(1, value.length() - 1);
|
|
||||||
this.value = new TypedValue(value.replaceAll("''", "'").replaceAll("\"\"", "\""));
|
String valueWithinQuotes = value.substring(1, value.length() - 1);
|
||||||
|
valueWithinQuotes = StringUtils.replace(valueWithinQuotes, "''", "'");
|
||||||
|
valueWithinQuotes = StringUtils.replace(valueWithinQuotes, "\"\"", "\"");
|
||||||
|
|
||||||
|
this.value = new TypedValue(valueWithinQuotes);
|
||||||
this.exitTypeDescriptor = "Ljava/lang/String";
|
this.exitTypeDescriptor = "Ljava/lang/String";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import org.springframework.lang.Nullable;
|
|||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
import org.springframework.util.ConcurrentReferenceHashMap;
|
import org.springframework.util.ConcurrentReferenceHashMap;
|
||||||
import org.springframework.util.ReflectionUtils;
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A SpelCompiler will take a regular parsed expression and create (and load) a class
|
* A SpelCompiler will take a regular parsed expression and create (and load) a class
|
||||||
@@ -132,9 +133,9 @@ public final class SpelCompiler implements Opcodes {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private Class<? extends CompiledExpression> createExpressionClass(SpelNodeImpl expressionToCompile) {
|
private Class<? extends CompiledExpression> createExpressionClass(SpelNodeImpl expressionToCompile) {
|
||||||
// Create class outline 'spel/ExNNN extends org.springframework.expression.spel.CompiledExpression'
|
// Create class outline 'spel/ExNNN extends org.springframework.expression.spel.CompiledExpression'
|
||||||
String clazzName = "spel/Ex" + getNextSuffix();
|
String className = "spel/Ex" + getNextSuffix();
|
||||||
ClassWriter cw = new ExpressionClassWriter();
|
ClassWriter cw = new ExpressionClassWriter();
|
||||||
cw.visit(V1_5, ACC_PUBLIC, clazzName, null, "org/springframework/expression/spel/CompiledExpression", null);
|
cw.visit(V1_5, ACC_PUBLIC, className, null, "org/springframework/expression/spel/CompiledExpression", null);
|
||||||
|
|
||||||
// Create default constructor
|
// Create default constructor
|
||||||
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
|
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
|
||||||
@@ -152,7 +153,7 @@ public final class SpelCompiler implements Opcodes {
|
|||||||
new String[ ]{"org/springframework/expression/EvaluationException"});
|
new String[ ]{"org/springframework/expression/EvaluationException"});
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
|
|
||||||
CodeFlow cf = new CodeFlow(clazzName, cw);
|
CodeFlow cf = new CodeFlow(className, cw);
|
||||||
|
|
||||||
// Ask the expression AST to generate the body of the method
|
// Ask the expression AST to generate the body of the method
|
||||||
try {
|
try {
|
||||||
@@ -181,7 +182,7 @@ public final class SpelCompiler implements Opcodes {
|
|||||||
byte[] data = cw.toByteArray();
|
byte[] data = cw.toByteArray();
|
||||||
// TODO need to make this conditionally occur based on a debug flag
|
// TODO need to make this conditionally occur based on a debug flag
|
||||||
// dump(expressionToCompile.toStringAST(), clazzName, data);
|
// dump(expressionToCompile.toStringAST(), clazzName, data);
|
||||||
return loadClass(clazzName.replaceAll("/", "."), data);
|
return loadClass(StringUtils.replace(className, "/", "."), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -292,7 +292,7 @@ public class BeanPropertyRowMapper<T> implements RowMapper<T> {
|
|||||||
|
|
||||||
for (int index = 1; index <= columnCount; index++) {
|
for (int index = 1; index <= columnCount; index++) {
|
||||||
String column = JdbcUtils.lookupColumnName(rsmd, index);
|
String column = JdbcUtils.lookupColumnName(rsmd, index);
|
||||||
String field = lowerCaseName(column.replaceAll(" ", ""));
|
String field = lowerCaseName(StringUtils.delete(column, " "));
|
||||||
PropertyDescriptor pd = (this.mappedFields != null ? this.mappedFields.get(field) : null);
|
PropertyDescriptor pd = (this.mappedFields != null ? this.mappedFields.get(field) : null);
|
||||||
if (pd != null) {
|
if (pd != null) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import org.springframework.http.server.reactive.ServerHttpRequest;
|
|||||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code HttpMessageWriter} for {@code "text/event-stream"} responses.
|
* {@code HttpMessageWriter} for {@code "text/event-stream"} responses.
|
||||||
@@ -135,7 +136,7 @@ public class ServerSentEventHttpMessageWriter implements HttpMessageWriter<Objec
|
|||||||
writeField("retry", retry.toMillis(), sb);
|
writeField("retry", retry.toMillis(), sb);
|
||||||
}
|
}
|
||||||
if (comment != null) {
|
if (comment != null) {
|
||||||
sb.append(':').append(comment.replaceAll("\\n", "\n:")).append("\n");
|
sb.append(':').append(StringUtils.replace(comment, "\n", "\n:")).append("\n");
|
||||||
}
|
}
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
sb.append("data:");
|
sb.append("data:");
|
||||||
@@ -164,7 +165,7 @@ public class ServerSentEventHttpMessageWriter implements HttpMessageWriter<Objec
|
|||||||
|
|
||||||
if (data instanceof String) {
|
if (data instanceof String) {
|
||||||
String text = (String) data;
|
String text = (String) data;
|
||||||
return Flux.from(encodeText(text.replaceAll("\\n", "\ndata:") + "\n", mediaType, factory));
|
return Flux.from(encodeText(StringUtils.replace(text, "\n", "\ndata:") + "\n", mediaType, factory));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.encoder == null) {
|
if (this.encoder == null) {
|
||||||
|
|||||||
@@ -287,13 +287,15 @@ public class ServletWebRequest extends ServletRequestAttributes implements Nativ
|
|||||||
|
|
||||||
// We will perform this validation...
|
// We will perform this validation...
|
||||||
etag = padEtagIfNecessary(etag);
|
etag = padEtagIfNecessary(etag);
|
||||||
|
if (etag.startsWith("W/")) {
|
||||||
|
etag = etag.substring(2);
|
||||||
|
}
|
||||||
while (ifNoneMatch.hasMoreElements()) {
|
while (ifNoneMatch.hasMoreElements()) {
|
||||||
String clientETags = ifNoneMatch.nextElement();
|
String clientETags = ifNoneMatch.nextElement();
|
||||||
Matcher etagMatcher = ETAG_HEADER_VALUE_PATTERN.matcher(clientETags);
|
Matcher etagMatcher = ETAG_HEADER_VALUE_PATTERN.matcher(clientETags);
|
||||||
// Compare weak/strong ETags as per https://tools.ietf.org/html/rfc7232#section-2.3
|
// Compare weak/strong ETags as per https://tools.ietf.org/html/rfc7232#section-2.3
|
||||||
while (etagMatcher.find()) {
|
while (etagMatcher.find()) {
|
||||||
if (StringUtils.hasLength(etagMatcher.group()) &&
|
if (StringUtils.hasLength(etagMatcher.group()) && etag.equals(etagMatcher.group(3))) {
|
||||||
etag.replaceFirst("^W/", "").equals(etagMatcher.group(3))) {
|
|
||||||
this.notModified = true;
|
this.notModified = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,8 +126,7 @@ public class ShallowEtagHeaderFilter extends OncePerRequestFilter {
|
|||||||
String responseETag = generateETagHeaderValue(responseWrapper.getContentInputStream(), this.writeWeakETag);
|
String responseETag = generateETagHeaderValue(responseWrapper.getContentInputStream(), this.writeWeakETag);
|
||||||
rawResponse.setHeader(HEADER_ETAG, responseETag);
|
rawResponse.setHeader(HEADER_ETAG, responseETag);
|
||||||
String requestETag = request.getHeader(HEADER_IF_NONE_MATCH);
|
String requestETag = request.getHeader(HEADER_IF_NONE_MATCH);
|
||||||
if (requestETag != null && ("*".equals(requestETag) || responseETag.equals(requestETag) ||
|
if (requestETag != null && ("*".equals(requestETag) || compareETagHeaderValue(requestETag, responseETag))) {
|
||||||
responseETag.replaceFirst("^W/", "").equals(requestETag.replaceFirst("^W/", "")))) {
|
|
||||||
rawResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
|
rawResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -184,6 +183,16 @@ public class ShallowEtagHeaderFilter extends OncePerRequestFilter {
|
|||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean compareETagHeaderValue(String requestETag, String responseETag) {
|
||||||
|
if (requestETag.startsWith("W/")) {
|
||||||
|
requestETag = requestETag.substring(2);
|
||||||
|
}
|
||||||
|
if (responseETag.startsWith("W/")) {
|
||||||
|
responseETag = responseETag.substring(2);
|
||||||
|
}
|
||||||
|
return requestETag.equals(responseETag);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method can be used to disable the content caching response wrapper
|
* This method can be used to disable the content caching response wrapper
|
||||||
|
|||||||
@@ -318,12 +318,19 @@ public class DefaultServerWebExchange implements ServerWebExchange {
|
|||||||
}
|
}
|
||||||
// We will perform this validation...
|
// We will perform this validation...
|
||||||
etag = padEtagIfNecessary(etag);
|
etag = padEtagIfNecessary(etag);
|
||||||
for (String clientETag : ifNoneMatch) {
|
if (etag.startsWith("W/")) {
|
||||||
|
etag = etag.substring(2);
|
||||||
|
}
|
||||||
|
for (String clientEtag : ifNoneMatch) {
|
||||||
// Compare weak/strong ETags as per https://tools.ietf.org/html/rfc7232#section-2.3
|
// Compare weak/strong ETags as per https://tools.ietf.org/html/rfc7232#section-2.3
|
||||||
if (StringUtils.hasLength(clientETag) &&
|
if (StringUtils.hasLength(clientEtag)) {
|
||||||
clientETag.replaceFirst("^W/", "").equals(etag.replaceFirst("^W/", ""))) {
|
if (clientEtag.startsWith("W/")) {
|
||||||
this.notModified = true;
|
clientEtag = clientEtag.substring(2);
|
||||||
break;
|
}
|
||||||
|
if (clientEtag.equals(etag)) {
|
||||||
|
this.notModified = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ import org.springframework.web.util.TagUtils;
|
|||||||
import org.springframework.web.util.UriUtils;
|
import org.springframework.web.util.UriUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@code <url>} tag creates URLs. Modeled after the JSTL c:url tag with
|
* The {@code <url>} tag creates URLs. Modeled after the JSTL {@code c:url} tag with
|
||||||
* backwards compatibility in mind.
|
* backwards compatibility in mind.
|
||||||
*
|
*
|
||||||
* <p>Enhancements to the JSTL functionality include:
|
* <p>Enhancements to the JSTL functionality include:
|
||||||
@@ -361,7 +361,8 @@ public class UrlTag extends HtmlEscapingAwareTag implements ParamAware {
|
|||||||
usedParams.add(param.getName());
|
usedParams.add(param.getName());
|
||||||
String value = param.getValue();
|
String value = param.getValue();
|
||||||
try {
|
try {
|
||||||
uri = uri.replace(template, (value != null ? UriUtils.encodePath(value, encoding) : ""));
|
uri = StringUtils.replace(uri, template,
|
||||||
|
(value != null ? UriUtils.encodePath(value, encoding) : ""));
|
||||||
}
|
}
|
||||||
catch (UnsupportedCharsetException ex) {
|
catch (UnsupportedCharsetException ex) {
|
||||||
throw new JspException(ex);
|
throw new JspException(ex);
|
||||||
@@ -373,7 +374,7 @@ public class UrlTag extends HtmlEscapingAwareTag implements ParamAware {
|
|||||||
usedParams.add(param.getName());
|
usedParams.add(param.getName());
|
||||||
String value = param.getValue();
|
String value = param.getValue();
|
||||||
try {
|
try {
|
||||||
uri = uri.replace(template,
|
uri = StringUtils.replace(uri, template,
|
||||||
(value != null ? UriUtils.encodePathSegment(param.getValue(), encoding) : ""));
|
(value != null ? UriUtils.encodePathSegment(param.getValue(), encoding) : ""));
|
||||||
}
|
}
|
||||||
catch (UnsupportedCharsetException ex) {
|
catch (UnsupportedCharsetException ex) {
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ public class GroovyMarkupConfigurer extends TemplateConfiguration
|
|||||||
protected URL resolveTemplate(ClassLoader classLoader, String templatePath) throws IOException {
|
protected URL resolveTemplate(ClassLoader classLoader, String templatePath) throws IOException {
|
||||||
MarkupTemplateEngine.TemplateResource resource = MarkupTemplateEngine.TemplateResource.parse(templatePath);
|
MarkupTemplateEngine.TemplateResource resource = MarkupTemplateEngine.TemplateResource.parse(templatePath);
|
||||||
Locale locale = LocaleContextHolder.getLocale();
|
Locale locale = LocaleContextHolder.getLocale();
|
||||||
URL url = classLoader.getResource(resource.withLocale(locale.toString().replace("-", "_")).toString());
|
URL url = classLoader.getResource(resource.withLocale(StringUtils.replace(locale.toString(), "-", "_")).toString());
|
||||||
if (url == null) {
|
if (url == null) {
|
||||||
url = classLoader.getResource(resource.withLocale(locale.getLanguage()).toString());
|
url = classLoader.getResource(resource.withLocale(locale.getLanguage()).toString());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -22,6 +22,7 @@ import java.util.UUID;
|
|||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.IdGenerator;
|
import org.springframework.util.IdGenerator;
|
||||||
import org.springframework.util.JdkIdGenerator;
|
import org.springframework.util.JdkIdGenerator;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.socket.sockjs.transport.TransportType;
|
import org.springframework.web.socket.sockjs.transport.TransportType;
|
||||||
import org.springframework.web.util.UriComponentsBuilder;
|
import org.springframework.web.util.UriComponentsBuilder;
|
||||||
|
|
||||||
@@ -68,7 +69,7 @@ public class SockJsUrlInfo {
|
|||||||
|
|
||||||
public String getSessionId() {
|
public String getSessionId() {
|
||||||
if (this.sessionId == null) {
|
if (this.sessionId == null) {
|
||||||
this.sessionId = getUuid().toString().replace("-","");
|
this.sessionId = StringUtils.delete(getUuid().toString(), "-");
|
||||||
}
|
}
|
||||||
return this.sessionId;
|
return this.sessionId;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import java.nio.charset.StandardCharsets;
|
|||||||
|
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a SockJS frame. Provides factory methods to create SockJS frames.
|
* Represents a SockJS frame. Provides factory methods to create SockJS frames.
|
||||||
@@ -142,7 +143,9 @@ public class SockJsFrame {
|
|||||||
if (result.length() > 80) {
|
if (result.length() > 80) {
|
||||||
result = result.substring(0, 80) + "...(truncated)";
|
result = result.substring(0, 80) + "...(truncated)";
|
||||||
}
|
}
|
||||||
return "SockJsFrame content='" + result.replace("\n", "\\n").replace("\r", "\\r") + "'";
|
result = StringUtils.replace(result, "\n", "\\n");
|
||||||
|
result = StringUtils.replace(result, "\r", "\\r");
|
||||||
|
return "SockJsFrame content='" + result + "'";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user