Browse Source

Merge branch '6.2.x'

pull/34249/head
Juergen Hoeller 1 year ago
parent
commit
b8c3f03ec0
  1. 49
      spring-core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java
  2. 45
      spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/AbstractJdbcCall.java
  3. 9
      spring-jdbc/src/main/java/org/springframework/jdbc/datasource/JdbcTransactionObjectSupport.java

49
spring-core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2024 the original author or authors. * Copyright 2002-2025 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.
@ -40,6 +40,7 @@ import java.nio.file.Path;
import java.util.Collections; import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Map; import java.util.Map;
import java.util.NavigableSet; import java.util.NavigableSet;
@ -642,13 +643,15 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
} }
} }
if (currentPrefix != null) { if (currentPrefix != null) {
// A prefix match found, potentially to be turned into a common parent cache entry. if (checkPathWithinPackage(path.substring(currentPrefix.length()))) {
if (commonPrefix == null || !commonUnique || currentPrefix.length() > commonPrefix.length()) { // A prefix match found, potentially to be turned into a common parent cache entry.
commonPrefix = currentPrefix; if (commonPrefix == null || !commonUnique || currentPrefix.length() > commonPrefix.length()) {
existingPath = path; commonPrefix = currentPrefix;
} existingPath = path;
else if (currentPrefix.equals(commonPrefix)) { }
commonUnique = false; else if (currentPrefix.equals(commonPrefix)) {
commonUnique = false;
}
} }
} }
else if (actualRootPath == null || path.length() > actualRootPath.length()) { else if (actualRootPath == null || path.length() > actualRootPath.length()) {
@ -801,7 +804,7 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
if (separatorIndex == -1) { if (separatorIndex == -1) {
separatorIndex = urlFile.indexOf(ResourceUtils.JAR_URL_SEPARATOR); separatorIndex = urlFile.indexOf(ResourceUtils.JAR_URL_SEPARATOR);
} }
if (separatorIndex != -1) { if (separatorIndex >= 0) {
jarFileUrl = urlFile.substring(0, separatorIndex); jarFileUrl = urlFile.substring(0, separatorIndex);
rootEntryPath = urlFile.substring(separatorIndex + 2); // both separators are 2 chars rootEntryPath = urlFile.substring(separatorIndex + 2); // both separators are 2 chars
NavigableSet<String> entriesCache = this.jarEntriesCache.get(jarFileUrl); NavigableSet<String> entriesCache = this.jarEntriesCache.get(jarFileUrl);
@ -828,11 +831,17 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
if (con instanceof JarURLConnection jarCon) { if (con instanceof JarURLConnection jarCon) {
// Should usually be the case for traditional JAR files. // Should usually be the case for traditional JAR files.
jarFile = jarCon.getJarFile(); try {
jarFileUrl = jarCon.getJarFileURL().toExternalForm(); jarFile = jarCon.getJarFile();
JarEntry jarEntry = jarCon.getJarEntry(); jarFileUrl = jarCon.getJarFileURL().toExternalForm();
rootEntryPath = (jarEntry != null ? jarEntry.getName() : ""); JarEntry jarEntry = jarCon.getJarEntry();
closeJarFile = !jarCon.getUseCaches(); rootEntryPath = (jarEntry != null ? jarEntry.getName() : "");
closeJarFile = !jarCon.getUseCaches();
}
catch (FileNotFoundException ex) {
// Happens in case of cached root directory without specific subdirectory present.
return Collections.emptySet();
}
} }
else { else {
// No JarURLConnection -> need to resort to URL file parsing. // No JarURLConnection -> need to resort to URL file parsing.
@ -869,7 +878,13 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
} }
Set<Resource> result = new LinkedHashSet<>(64); Set<Resource> result = new LinkedHashSet<>(64);
NavigableSet<String> entriesCache = new TreeSet<>(); NavigableSet<String> entriesCache = new TreeSet<>();
for (String entryPath : jarFile.stream().map(JarEntry::getName).sorted().toList()) { Iterator<String> entryIterator = jarFile.stream().map(JarEntry::getName).sorted().iterator();
while (entryIterator.hasNext()) {
String entryPath = entryIterator.next();
int entrySeparatorIndex = entryPath.indexOf(ResourceUtils.JAR_URL_SEPARATOR);
if (entrySeparatorIndex >= 0) {
entryPath = entryPath.substring(entrySeparatorIndex + ResourceUtils.JAR_URL_SEPARATOR.length());
}
entriesCache.add(entryPath); entriesCache.add(entryPath);
if (entryPath.startsWith(rootEntryPath)) { if (entryPath.startsWith(rootEntryPath)) {
String relativePath = entryPath.substring(rootEntryPath.length()); String relativePath = entryPath.substring(rootEntryPath.length());
@ -1099,6 +1114,10 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
return (path.startsWith("/") ? path.substring(1) : path); return (path.startsWith("/") ? path.substring(1) : path);
} }
private static boolean checkPathWithinPackage(String path) {
return (path.contains("/") && !path.contains(ResourceUtils.JAR_URL_SEPARATOR));
}
/** /**
* Inner delegate class, avoiding a hard JBoss VFS API dependency at runtime. * Inner delegate class, avoiding a hard JBoss VFS API dependency at runtime.

45
spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/AbstractJdbcCall.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2023 the original author or authors. * Copyright 2002-2025 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.
@ -21,6 +21,8 @@ import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.sql.DataSource; import javax.sql.DataSource;
@ -66,6 +68,9 @@ public abstract class AbstractJdbcCall {
/** List of RefCursor/ResultSet RowMapper objects. */ /** List of RefCursor/ResultSet RowMapper objects. */
private final Map<String, RowMapper<?>> declaredRowMappers = new LinkedHashMap<>(); private final Map<String, RowMapper<?>> declaredRowMappers = new LinkedHashMap<>();
/** Lock for the compilation step. */
private final Lock compilationLock = new ReentrantLock();
/** /**
* Has this operation been compiled? Compilation means at least checking * Has this operation been compiled? Compilation means at least checking
* that a DataSource or JdbcTemplate has been provided. * that a DataSource or JdbcTemplate has been provided.
@ -278,24 +283,30 @@ public abstract class AbstractJdbcCall {
* @throws org.springframework.dao.InvalidDataAccessApiUsageException if the object hasn't * @throws org.springframework.dao.InvalidDataAccessApiUsageException if the object hasn't
* been correctly initialized, for example if no DataSource has been provided * been correctly initialized, for example if no DataSource has been provided
*/ */
public final synchronized void compile() throws InvalidDataAccessApiUsageException { public final void compile() throws InvalidDataAccessApiUsageException {
if (!isCompiled()) { this.compilationLock.lock();
if (getProcedureName() == null) { try {
throw new InvalidDataAccessApiUsageException("Procedure or Function name is required"); if (!isCompiled()) {
} if (getProcedureName() == null) {
try { throw new InvalidDataAccessApiUsageException("Procedure or Function name is required");
this.jdbcTemplate.afterPropertiesSet(); }
} try {
catch (IllegalArgumentException ex) { this.jdbcTemplate.afterPropertiesSet();
throw new InvalidDataAccessApiUsageException(ex.getMessage()); }
} catch (IllegalArgumentException ex) {
compileInternal(); throw new InvalidDataAccessApiUsageException(ex.getMessage());
this.compiled = true; }
if (logger.isDebugEnabled()) { compileInternal();
logger.debug("SqlCall for " + (isFunction() ? "function" : "procedure") + this.compiled = true;
" [" + getProcedureName() + "] compiled"); if (logger.isDebugEnabled()) {
logger.debug("SqlCall for " + (isFunction() ? "function" : "procedure") +
" [" + getProcedureName() + "] compiled");
}
} }
} }
finally {
this.compilationLock.unlock();
}
} }
/** /**

9
spring-jdbc/src/main/java/org/springframework/jdbc/datasource/JdbcTransactionObjectSupport.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2024 the original author or authors. * Copyright 2002-2025 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.
@ -181,6 +181,13 @@ public abstract class JdbcTransactionObjectSupport implements SavepointManager,
catch (SQLFeatureNotSupportedException ex) { catch (SQLFeatureNotSupportedException ex) {
// typically on Oracle - ignore // typically on Oracle - ignore
} }
catch (SQLException ex) {
// ignore Microsoft SQLServerException: This operation is not supported.
String msg = ex.getMessage();
if (msg == null || !msg.contains("not supported")) {
throw new TransactionSystemException("Could not explicitly release JDBC savepoint", ex);
}
}
catch (Throwable ex) { catch (Throwable ex) {
throw new TransactionSystemException("Could not explicitly release JDBC savepoint", ex); throw new TransactionSystemException("Could not explicitly release JDBC savepoint", ex);
} }

Loading…
Cancel
Save