Using Regular expression objects for splitting and replacing in strings. (#1059)

* Where possible, replace .split() and .replace() methods with compiled Regex patterns.
This prevents a regular expression from being compiled multiple times during runtime.

* Forgot making one instance `private static final`.
This commit is contained in:
Koen De Groote
2017-07-06 20:14:51 +12:00
committed by Rob Bygrave
parent 08263c4588
commit 36a5610e25
12 changed files with 68 additions and 24 deletions
@@ -2,6 +2,7 @@ package io.ebean;
import io.ebean.RawSql.ColumnMapping;
import java.util.regex.Pattern;
import javax.persistence.PersistenceException;
import java.util.ArrayList;
@@ -10,6 +11,8 @@ import java.util.ArrayList;
*/
final class DRawSqlColumnsParser {
private static final Pattern COLINFO_SPLIT = Pattern.compile("\\s(?=[^\\)]*(?:\\(|$))");
private final int end;
private final String sqlSelect;
@@ -44,7 +47,7 @@ final class DRawSqlColumnsParser {
String colInfo = sqlSelect.substring(start, pos++);
colInfo = colInfo.trim();
String[] split = colInfo.split("\\s(?=[^\\)]*(?:\\(|$))");
String[] split = COLINFO_SPLIT.split(colInfo);
if (split.length > 1) {
ArrayList<String> tmp = new ArrayList<>(split.length);
for (String aSplit : split) {
@@ -2,6 +2,8 @@ package io.ebean.config;
import io.ebean.config.dbplatform.DatabasePlatform;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Inheritance;
import javax.persistence.Table;
@@ -14,16 +16,15 @@ import java.lang.annotation.Annotation;
*/
public abstract class AbstractNamingConvention implements NamingConvention {
private static final Pattern TABLE_REPLACE = Pattern.compile("{table}", Pattern.LITERAL);
private static final Pattern COLUMN_REPLACE = Pattern.compile("{column}", Pattern.LITERAL);
/**
* The Constant DEFAULT_SEQ_FORMAT.
*/
public static final String DEFAULT_SEQ_FORMAT = "{table}_seq";
/**
* Sequence Format that includes the Primary Key column
*/
public static final String TABLE_PKCOLUMN_SEQ_FORMAT = "{table}_{column}_seq";
/**
* The catalog.
*/
@@ -83,11 +84,11 @@ public abstract class AbstractNamingConvention implements NamingConvention {
@Override
public String getSequenceName(String tableName, String pkColumn) {
String s = sequenceFormat.replace("{table}", tableName);
String s = TABLE_REPLACE.matcher(sequenceFormat).replaceAll(Matcher.quoteReplacement(tableName));
if (pkColumn == null) {
pkColumn = "";
}
return s.replace("{column}", pkColumn);
return COLUMN_REPLACE.matcher(s).replaceAll(Matcher.quoteReplacement(pkColumn));
}
/**
@@ -1,5 +1,7 @@
package io.ebean.config;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -18,6 +20,8 @@ final class PropertyMapLoader {
private static final Logger logger = LoggerFactory.getLogger(PropertyMapLoader.class);
private static final Pattern OTHER_PROPS_REPLACE = Pattern.compile("\\", Pattern.LITERAL);
/**
* Load the <code>test-ebean.properties</code>.
*/
@@ -109,7 +113,7 @@ final class PropertyMapLoader {
otherProps = p.remove("load.properties.override");
}
if (otherProps != null) {
otherProps = otherProps.replace("\\", "/");
otherProps = OTHER_PROPS_REPLACE.matcher(otherProps).replaceAll(Matcher.quoteReplacement("/"));
InputStream is = findInputStream(otherProps);
if (is != null) {
logger.debug("loading properties from {}", otherProps);
@@ -27,6 +27,7 @@ import io.ebean.event.changelog.ChangeLogRegister;
import io.ebean.event.readaudit.ReadAuditLogger;
import io.ebean.event.readaudit.ReadAuditPrepare;
import io.ebean.meta.MetaInfoManager;
import java.util.regex.Pattern;
import org.avaje.datasource.DataSourceConfig;
import javax.sql.DataSource;
@@ -75,6 +76,8 @@ import java.util.ServiceLoader;
*/
public class ServerConfig {
private static final Pattern NAMES_SPLIT = Pattern.compile("[ ,;]");
/**
* The EbeanServer name.
*/
@@ -2633,7 +2636,7 @@ public class ServerConfig {
List<Class<?>> classes = new ArrayList<>();
String[] split = classNames.split("[ ,;]");
String[] split = NAMES_SPLIT.split(classNames);
for (String aSplit : split) {
String cn = aSplit.trim();
if (!cn.isEmpty() && !"class".equalsIgnoreCase(cn)) {
@@ -2654,7 +2657,7 @@ public class ServerConfig {
if (searchPackages != null) {
String[] entries = searchPackages.split("[ ,;]");
String[] entries = NAMES_SPLIT.split(searchPackages);
for (String entry : entries) {
hitList.add(entry.trim());
}
@@ -1,12 +1,16 @@
package io.ebean.config.dbplatform;
import io.ebean.dbmigration.migration.IdentityType;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Defines the identity/sequence behaviour for the database.
*/
public class DbIdentity {
private static final Pattern TABLE_REPLACE = Pattern.compile("{table}", Pattern.LITERAL);
/**
* Set if this DB supports sequences. Note some DB's support both Sequences
* and Identity.
@@ -50,7 +54,8 @@ public class DbIdentity {
if (selectLastInsertedIdTemplate == null) {
return null;
}
return selectLastInsertedIdTemplate.replace("{table}", table);
return TABLE_REPLACE.matcher(selectLastInsertedIdTemplate).replaceAll(Matcher.quoteReplacement(table));
}
/**
@@ -2,9 +2,12 @@ package io.ebean.config.dbplatform.sqlserver;
import io.ebean.PersistBatch;
import io.ebean.Platform;
import io.ebean.config.dbplatform.*;
import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebean.config.dbplatform.DbPlatformType;
import io.ebean.config.dbplatform.DbType;
import io.ebean.config.dbplatform.IdType;
import io.ebean.config.dbplatform.SqlErrorCodes;
import io.ebean.dbmigration.ddlgeneration.platform.SqlServerDdl;
import java.sql.Types;
/**
@@ -1,12 +1,15 @@
package io.ebean.dbmigration.model;
import java.util.Arrays;
import java.util.regex.Pattern;
/**
* The version of a migration used so that migrations are processed in order.
*/
public class MigrationVersion implements Comparable<MigrationVersion> {
private static final Pattern SECTION_SPLITTER = Pattern.compile("[\\.-]");
private static final int[] REPEAT_ORDERING = {Integer.MAX_VALUE};
private static final boolean[] REPEAT_UNDERSCORES = {false};
@@ -169,7 +172,7 @@ public class MigrationVersion implements Comparable<MigrationVersion> {
value = value.replace('_', '.');
String[] sections = value.split("[\\.-]");
String[] sections = SECTION_SPLITTER.split(value);
if ("r".equalsIgnoreCase(sections[0])) {
// a "repeatable" version (does not have a version number)
@@ -1,5 +1,6 @@
package io.ebeaninternal.extraddl.model;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -15,6 +16,8 @@ public class ExtraDdlXmlReader {
private static final Logger logger = LoggerFactory.getLogger(ExtraDdlXmlReader.class);
private static final Pattern PLATFORM_REGEX_SPLIT = Pattern.compile("[,;]");
/**
* Return the combined extra DDL that should be run given the platform name.
*/
@@ -44,7 +47,8 @@ public class ExtraDdlXmlReader {
if (platforms == null || platforms.trim().isEmpty()) {
return true;
}
String[] names = platforms.split("[,;]");
String[] names = PLATFORM_REGEX_SPLIT.split(platforms);
for (String name : names) {
if (name.trim().toLowerCase().contains(platformName)) {
return true;
@@ -1,5 +1,6 @@
package io.ebeaninternal.server.core.bootup;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -21,6 +22,8 @@ class ManifestReader {
private final Set<String> packageSet = new HashSet<>();
private static final Pattern PACKAGE_DELIMITER = Pattern.compile("[,; ]");
/**
* Read the packages from ebean.mf manifest files found as resources.
*/
@@ -73,7 +76,7 @@ class ManifestReader {
* Collect each individual package splitting by delimiters.
*/
private void add(String packages) {
String[] split = packages.split("[,; ]");
String[] split = PACKAGE_DELIMITER.split(packages);
for (String aSplit : split) {
String pkg = aSplit.trim();
if (!pkg.isEmpty()) {
@@ -3,6 +3,8 @@ package io.ebeaninternal.server.query;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.el.ElPropertyDeploy;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.persistence.PersistenceException;
import java.util.HashMap;
import java.util.HashSet;
@@ -15,6 +17,8 @@ import java.util.TreeSet;
*/
class SqlTreeAlias {
private static final Pattern TABLE_ALIAS_REPLACE = Pattern.compile("${}", Pattern.LITERAL);
private int counter;
private int manyWhereCounter;
@@ -178,9 +182,9 @@ class SqlTreeAlias {
private String parseRootAlias(String clause) {
if (rootTableAlias == null) {
return clause.replace("${}", "");
return TABLE_ALIAS_REPLACE.matcher(clause).replaceAll("");
} else {
return clause.replace("${}", rootTableAlias + ".");
return TABLE_ALIAS_REPLACE.matcher(clause).replaceAll(Matcher.quoteReplacement(rootTableAlias + "."));
}
}
@@ -9,6 +9,7 @@ import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
/**
* Set properties for a UpdateQuery.
@@ -19,6 +20,8 @@ public class OrmUpdateProperties {
private static final NoneValue NONE_VALUE = new NoneValue();
private static final Pattern TABLE_ALIAS_REPLACE = Pattern.compile("${}", Pattern.LITERAL);
/**
* Bind value used in the set clause for update query.
* It may/may not have bind values etc.
@@ -188,8 +191,9 @@ public class OrmUpdateProperties {
if (setCount++ > 0) {
sb.append(", ");
}
// translate to db columns and remove table alias placeholders
sb.append(deployParser.parse(property).replace("${}", ""));
sb.append(TABLE_ALIAS_REPLACE.matcher(deployParser.parse(property)).replaceAll(""));
sb.append(entry.getValue().bindClause());
}
return sb.toString();
@@ -21,6 +21,8 @@ import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Rob Bygrave: This is a copy of the google guava InetAddresses class
@@ -115,6 +117,10 @@ public final class ConvertInetAddresses {
private static final int IPV4_PART_COUNT = 4;
private static final int IPV6_PART_COUNT = 8;
public static final String DOUBLE_COLON = "::";
private static final Pattern IPSTRING_REPLACE = Pattern.compile(DOUBLE_COLON, Pattern.LITERAL);
private ConvertInetAddresses() {
}
@@ -186,7 +192,7 @@ public final class ConvertInetAddresses {
// handle IPv6 forms of IPv4 addresses
if (ipString.toUpperCase(Locale.US).startsWith("::FFFF:")) {
ipString = ipString.substring(7);
} else if (ipString.startsWith("::")) {
} else if (ipString.startsWith(DOUBLE_COLON)) {
ipString = ipString.substring(2);
isIpv6 = true;
}
@@ -260,13 +266,14 @@ public final class ConvertInetAddresses {
// Fill in any omitted colons
private static String padIpString(String ipString) {
if (ipString.contains("::")) {
if (ipString.contains(DOUBLE_COLON)) {
int count = numberOfColons(ipString);
StringBuilder buffer = new StringBuilder("::");
StringBuilder buffer = new StringBuilder(DOUBLE_COLON);
for (int i = 0; i + count < 7; i++) {
buffer.append(":");
}
ipString = ipString.replace("::", buffer);
ipString = IPSTRING_REPLACE.matcher(ipString).replaceAll(Matcher.quoteReplacement(buffer.toString()));
}
return ipString;
}