From 34663300a6952e1c708e0ec39296e4fdf3d85feb Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 17 Sep 2018 14:22:19 +0200 Subject: [PATCH] Avoid regex pattern matching for simple String replacement steps Issue: SPR-17279 --- .../standard/DateTimeFormatterFactory.java | 4 ++-- .../classloading/WeavingTransformer.java | 5 +++-- .../expression/spel/ast/StringLiteral.java | 11 ++++++++--- .../expression/spel/standard/SpelCompiler.java | 9 +++++---- .../jdbc/core/BeanPropertyRowMapper.java | 2 +- .../codec/ServerSentEventHttpMessageWriter.java | 5 +++-- .../web/context/request/ServletWebRequest.java | 6 ++++-- .../web/filter/ShallowEtagHeaderFilter.java | 13 +++++++++++-- .../adapter/DefaultServerWebExchange.java | 17 ++++++++++++----- .../web/servlet/tags/UrlTag.java | 7 ++++--- .../view/groovy/GroovyMarkupConfigurer.java | 2 +- .../web/socket/sockjs/client/SockJsUrlInfo.java | 5 +++-- .../web/socket/sockjs/frame/SockJsFrame.java | 5 ++++- 13 files changed, 61 insertions(+), 30 deletions(-) diff --git a/spring-context/src/main/java/org/springframework/format/datetime/standard/DateTimeFormatterFactory.java b/spring-context/src/main/java/org/springframework/format/datetime/standard/DateTimeFormatterFactory.java index d8d85c6ce2a..8488984e437 100644 --- a/spring-context/src/main/java/org/springframework/format/datetime/standard/DateTimeFormatterFactory.java +++ b/spring-context/src/main/java/org/springframework/format/datetime/standard/DateTimeFormatterFactory.java @@ -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"); * 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: // 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'... - String patternToUse = this.pattern.replace("yy", "uu"); + String patternToUse = StringUtils.replace(this.pattern, "yy", "uu"); dateTimeFormatter = DateTimeFormatter.ofPattern(patternToUse).withResolverStyle(ResolverStyle.STRICT); } else if (this.iso != null && this.iso != ISO.NONE) { diff --git a/spring-context/src/main/java/org/springframework/instrument/classloading/WeavingTransformer.java b/spring-context/src/main/java/org/springframework/instrument/classloading/WeavingTransformer.java index 48264329d39..d09d87aaacb 100644 --- a/spring-context/src/main/java/org/springframework/instrument/classloading/WeavingTransformer.java +++ b/spring-context/src/main/java/org/springframework/instrument/classloading/WeavingTransformer.java @@ -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"); * 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.util.Assert; +import org.springframework.util.StringUtils; /** * ClassFileTransformer-based weaver, allowing for a list of transformers to be @@ -73,7 +74,7 @@ public class WeavingTransformer { * @return (possibly transformed) class byte definition */ public byte[] transformIfNecessary(String className, byte[] bytes) { - String internalName = className.replace(".", "/"); + String internalName = StringUtils.replace(className, ".", "/"); return transformIfNecessary(className, internalName, bytes, null); } diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/StringLiteral.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/StringLiteral.java index 01ec13b3b4c..5eb8f4f0f17 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/StringLiteral.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/StringLiteral.java @@ -19,6 +19,7 @@ package org.springframework.expression.spel.ast; import org.springframework.asm.MethodVisitor; import org.springframework.expression.TypedValue; import org.springframework.expression.spel.CodeFlow; +import org.springframework.util.StringUtils; /** * 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) { - super(payload,pos); - value = value.substring(1, value.length() - 1); - this.value = new TypedValue(value.replaceAll("''", "'").replaceAll("\"\"", "\"")); + super(payload, pos); + + 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"; } diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/standard/SpelCompiler.java b/spring-expression/src/main/java/org/springframework/expression/spel/standard/SpelCompiler.java index 30126338e25..b599c17f0a9 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/standard/SpelCompiler.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/standard/SpelCompiler.java @@ -36,6 +36,7 @@ import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; import org.springframework.util.ConcurrentReferenceHashMap; import org.springframework.util.ReflectionUtils; +import org.springframework.util.StringUtils; /** * 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 private Class createExpressionClass(SpelNodeImpl expressionToCompile) { // 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(); - 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 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); @@ -152,7 +153,7 @@ public final class SpelCompiler implements Opcodes { new String[ ]{"org/springframework/expression/EvaluationException"}); 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 try { @@ -181,7 +182,7 @@ public final class SpelCompiler implements Opcodes { byte[] data = cw.toByteArray(); // TODO need to make this conditionally occur based on a debug flag // dump(expressionToCompile.toStringAST(), clazzName, data); - return loadClass(clazzName.replaceAll("/", "."), data); + return loadClass(StringUtils.replace(className, "/", "."), data); } /** diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/BeanPropertyRowMapper.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/BeanPropertyRowMapper.java index b51b2c1951d..764136250f7 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/BeanPropertyRowMapper.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/BeanPropertyRowMapper.java @@ -292,7 +292,7 @@ public class BeanPropertyRowMapper implements RowMapper { for (int index = 1; index <= columnCount; 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); if (pd != null) { try { diff --git a/spring-web/src/main/java/org/springframework/http/codec/ServerSentEventHttpMessageWriter.java b/spring-web/src/main/java/org/springframework/http/codec/ServerSentEventHttpMessageWriter.java index fca24aed742..f10a88c70c8 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/ServerSentEventHttpMessageWriter.java +++ b/spring-web/src/main/java/org/springframework/http/codec/ServerSentEventHttpMessageWriter.java @@ -38,6 +38,7 @@ import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; /** * {@code HttpMessageWriter} for {@code "text/event-stream"} responses. @@ -135,7 +136,7 @@ public class ServerSentEventHttpMessageWriter implements HttpMessageWriter} tag creates URLs. Modeled after the JSTL c:url tag with + * The {@code } tag creates URLs. Modeled after the JSTL {@code c:url} tag with * backwards compatibility in mind. * *

Enhancements to the JSTL functionality include: @@ -361,7 +361,8 @@ public class UrlTag extends HtmlEscapingAwareTag implements ParamAware { usedParams.add(param.getName()); String value = param.getValue(); 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) { throw new JspException(ex); @@ -373,7 +374,7 @@ public class UrlTag extends HtmlEscapingAwareTag implements ParamAware { usedParams.add(param.getName()); String value = param.getValue(); try { - uri = uri.replace(template, + uri = StringUtils.replace(uri, template, (value != null ? UriUtils.encodePathSegment(param.getValue(), encoding) : "")); } catch (UnsupportedCharsetException ex) { diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/groovy/GroovyMarkupConfigurer.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/groovy/GroovyMarkupConfigurer.java index 620e869f356..d5c5acfffe8 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/groovy/GroovyMarkupConfigurer.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/groovy/GroovyMarkupConfigurer.java @@ -194,7 +194,7 @@ public class GroovyMarkupConfigurer extends TemplateConfiguration protected URL resolveTemplate(ClassLoader classLoader, String templatePath) throws IOException { MarkupTemplateEngine.TemplateResource resource = MarkupTemplateEngine.TemplateResource.parse(templatePath); 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) { url = classLoader.getResource(resource.withLocale(locale.getLanguage()).toString()); } diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/client/SockJsUrlInfo.java b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/client/SockJsUrlInfo.java index e01abaabf10..028e4a46497 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/client/SockJsUrlInfo.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/client/SockJsUrlInfo.java @@ -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"); * 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.util.IdGenerator; import org.springframework.util.JdkIdGenerator; +import org.springframework.util.StringUtils; import org.springframework.web.socket.sockjs.transport.TransportType; import org.springframework.web.util.UriComponentsBuilder; @@ -68,7 +69,7 @@ public class SockJsUrlInfo { public String getSessionId() { if (this.sessionId == null) { - this.sessionId = getUuid().toString().replace("-",""); + this.sessionId = StringUtils.delete(getUuid().toString(), "-"); } return this.sessionId; } diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/frame/SockJsFrame.java b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/frame/SockJsFrame.java index 83288c7b6eb..2f985fc24c8 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/frame/SockJsFrame.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/frame/SockJsFrame.java @@ -21,6 +21,7 @@ import java.nio.charset.StandardCharsets; import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; /** * Represents a SockJS frame. Provides factory methods to create SockJS frames. @@ -142,7 +143,9 @@ public class SockJsFrame { if (result.length() > 80) { 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 + "'"; }