Remove web concerns from template package and move out of -all
Co-authored-by: Phillip Webb <phil.webb@broadcom.com>
This commit is contained in:
committed by
Phillip Webb
parent
4cdfa2eecc
commit
57006ee82e
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.template;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Abstract base class for {@link TemplateAvailabilityProvider} implementations that find
|
||||
* templates from paths.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
* @author Madhura Bhave
|
||||
* @since 1.4.6
|
||||
*/
|
||||
public abstract class PathBasedTemplateAvailabilityProvider implements TemplateAvailabilityProvider {
|
||||
|
||||
private final String className;
|
||||
|
||||
private final Class<TemplateAvailabilityProperties> propertiesClass;
|
||||
|
||||
private final String propertyPrefix;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public PathBasedTemplateAvailabilityProvider(String className,
|
||||
Class<? extends TemplateAvailabilityProperties> propertiesClass, String propertyPrefix) {
|
||||
this.className = className;
|
||||
this.propertiesClass = (Class<TemplateAvailabilityProperties>) propertiesClass;
|
||||
this.propertyPrefix = propertyPrefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTemplateAvailable(String view, Environment environment, ClassLoader classLoader,
|
||||
ResourceLoader resourceLoader) {
|
||||
if (ClassUtils.isPresent(this.className, classLoader)) {
|
||||
Binder binder = Binder.get(environment);
|
||||
TemplateAvailabilityProperties properties = binder.bindOrCreate(this.propertyPrefix, this.propertiesClass);
|
||||
return isTemplateAvailable(view, resourceLoader, properties);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isTemplateAvailable(String view, ResourceLoader resourceLoader,
|
||||
TemplateAvailabilityProperties properties) {
|
||||
String location = properties.getPrefix() + view + properties.getSuffix();
|
||||
for (String path : properties.getLoaderPath()) {
|
||||
if (resourceLoader.getResource(path + location).exists()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected abstract static class TemplateAvailabilityProperties {
|
||||
|
||||
private String prefix;
|
||||
|
||||
private String suffix;
|
||||
|
||||
protected TemplateAvailabilityProperties(String prefix, String suffix) {
|
||||
this.prefix = prefix;
|
||||
this.suffix = suffix;
|
||||
}
|
||||
|
||||
protected abstract List<String> getLoaderPath();
|
||||
|
||||
public String getPrefix() {
|
||||
return this.prefix;
|
||||
}
|
||||
|
||||
public void setPrefix(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
public String getSuffix() {
|
||||
return this.suffix;
|
||||
}
|
||||
|
||||
public void setSuffix(String suffix) {
|
||||
this.suffix = suffix;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.template;
|
||||
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
|
||||
/**
|
||||
* Indicates the availability of view templates for a particular templating engine such as
|
||||
* FreeMarker or Thymeleaf.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface TemplateAvailabilityProvider {
|
||||
|
||||
/**
|
||||
* Returns {@code true} if a template is available for the given {@code view}.
|
||||
* @param view the view name
|
||||
* @param environment the environment
|
||||
* @param classLoader the class loader
|
||||
* @param resourceLoader the resource loader
|
||||
* @return if the template is available
|
||||
*/
|
||||
boolean isTemplateAvailable(String view, Environment environment, ClassLoader classLoader,
|
||||
ResourceLoader resourceLoader);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.template;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Collection of {@link TemplateAvailabilityProvider} beans that can be used to check
|
||||
* which (if any) templating engine supports a given view. Caches responses unless the
|
||||
* {@code spring.template.provider.cache} property is set to {@code false}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Madhura Bhave
|
||||
* @since 1.4.0
|
||||
*/
|
||||
public class TemplateAvailabilityProviders {
|
||||
|
||||
private final List<TemplateAvailabilityProvider> providers;
|
||||
|
||||
private static final int CACHE_LIMIT = 1024;
|
||||
|
||||
private static final TemplateAvailabilityProvider NONE = new NoTemplateAvailabilityProvider();
|
||||
|
||||
/**
|
||||
* Resolved template views, returning already cached instances without a global lock.
|
||||
*/
|
||||
private final Map<String, TemplateAvailabilityProvider> resolved = new ConcurrentHashMap<>(CACHE_LIMIT);
|
||||
|
||||
/**
|
||||
* Map from view name resolve template view, synchronized when accessed.
|
||||
*/
|
||||
private final Map<String, TemplateAvailabilityProvider> cache = new LinkedHashMap<>(CACHE_LIMIT, 0.75f, true) {
|
||||
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<String, TemplateAvailabilityProvider> eldest) {
|
||||
if (size() > CACHE_LIMIT) {
|
||||
TemplateAvailabilityProviders.this.resolved.remove(eldest.getKey());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new {@link TemplateAvailabilityProviders} instance.
|
||||
* @param applicationContext the source application context
|
||||
*/
|
||||
public TemplateAvailabilityProviders(ApplicationContext applicationContext) {
|
||||
this((applicationContext != null) ? applicationContext.getClassLoader() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link TemplateAvailabilityProviders} instance.
|
||||
* @param classLoader the source class loader
|
||||
*/
|
||||
public TemplateAvailabilityProviders(ClassLoader classLoader) {
|
||||
Assert.notNull(classLoader, "'classLoader' must not be null");
|
||||
this.providers = SpringFactoriesLoader.loadFactories(TemplateAvailabilityProvider.class, classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link TemplateAvailabilityProviders} instance.
|
||||
* @param providers the underlying providers
|
||||
*/
|
||||
protected TemplateAvailabilityProviders(Collection<? extends TemplateAvailabilityProvider> providers) {
|
||||
Assert.notNull(providers, "'providers' must not be null");
|
||||
this.providers = new ArrayList<>(providers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the underlying providers being used.
|
||||
* @return the providers being used
|
||||
*/
|
||||
public List<TemplateAvailabilityProvider> getProviders() {
|
||||
return this.providers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the provider that can be used to render the given view.
|
||||
* @param view the view to render
|
||||
* @param applicationContext the application context
|
||||
* @return a {@link TemplateAvailabilityProvider} or null
|
||||
*/
|
||||
public TemplateAvailabilityProvider getProvider(String view, ApplicationContext applicationContext) {
|
||||
Assert.notNull(applicationContext, "'applicationContext' must not be null");
|
||||
return getProvider(view, applicationContext.getEnvironment(), applicationContext.getClassLoader(),
|
||||
applicationContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the provider that can be used to render the given view.
|
||||
* @param view the view to render
|
||||
* @param environment the environment
|
||||
* @param classLoader the class loader
|
||||
* @param resourceLoader the resource loader
|
||||
* @return a {@link TemplateAvailabilityProvider} or null
|
||||
*/
|
||||
public TemplateAvailabilityProvider getProvider(String view, Environment environment, ClassLoader classLoader,
|
||||
ResourceLoader resourceLoader) {
|
||||
Assert.notNull(view, "'view' must not be null");
|
||||
Assert.notNull(environment, "'environment' must not be null");
|
||||
Assert.notNull(classLoader, "'classLoader' must not be null");
|
||||
Assert.notNull(resourceLoader, "'resourceLoader' must not be null");
|
||||
Boolean useCache = environment.getProperty("spring.template.provider.cache", Boolean.class, true);
|
||||
if (!useCache) {
|
||||
return findProvider(view, environment, classLoader, resourceLoader);
|
||||
}
|
||||
TemplateAvailabilityProvider provider = this.resolved.get(view);
|
||||
if (provider == null) {
|
||||
synchronized (this.cache) {
|
||||
provider = findProvider(view, environment, classLoader, resourceLoader);
|
||||
provider = (provider != null) ? provider : NONE;
|
||||
this.resolved.put(view, provider);
|
||||
this.cache.put(view, provider);
|
||||
}
|
||||
}
|
||||
return (provider != NONE) ? provider : null;
|
||||
}
|
||||
|
||||
private TemplateAvailabilityProvider findProvider(String view, Environment environment, ClassLoader classLoader,
|
||||
ResourceLoader resourceLoader) {
|
||||
for (TemplateAvailabilityProvider candidate : this.providers) {
|
||||
if (candidate.isTemplateAvailable(view, environment, classLoader, resourceLoader)) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final class NoTemplateAvailabilityProvider implements TemplateAvailabilityProvider {
|
||||
|
||||
@Override
|
||||
public boolean isTemplateAvailable(String view, Environment environment, ClassLoader classLoader,
|
||||
ResourceLoader resourceLoader) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.template;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Contains a location that templates can be loaded from.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 1.2.1
|
||||
*/
|
||||
public class TemplateLocation {
|
||||
|
||||
private final String path;
|
||||
|
||||
public TemplateLocation(String path) {
|
||||
Assert.notNull(path, "'path' must not be null");
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this template location exists using the specified
|
||||
* {@link ResourcePatternResolver}.
|
||||
* @param resolver the resolver used to test if the location exists
|
||||
* @return {@code true} if the location exists.
|
||||
*/
|
||||
public boolean exists(ResourcePatternResolver resolver) {
|
||||
Assert.notNull(resolver, "'resolver' must not be null");
|
||||
if (resolver.getResource(this.path).exists()) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
return anyExists(resolver);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean anyExists(ResourcePatternResolver resolver) throws IOException {
|
||||
String searchPath = this.path;
|
||||
if (searchPath.startsWith(ResourceLoader.CLASSPATH_URL_PREFIX)) {
|
||||
searchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
|
||||
+ searchPath.substring(ResourceLoader.CLASSPATH_URL_PREFIX.length());
|
||||
}
|
||||
if (searchPath.startsWith(ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX)) {
|
||||
Resource[] resources = resolver.getResources(searchPath);
|
||||
for (Resource resource : resources) {
|
||||
if (resource.exists()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.template;
|
||||
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
||||
|
||||
/**
|
||||
* {@link RuntimeHintsRegistrar} for default template location.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class TemplateRuntimeHints implements RuntimeHintsRegistrar {
|
||||
|
||||
@Override
|
||||
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
|
||||
hints.resources().registerPatternIfPresent(classLoader, "templates", (hint) -> hint.includes("templates/**"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Base classes for template Auto-configuration.
|
||||
*/
|
||||
package org.springframework.boot.autoconfigure.template;
|
||||
@@ -3,3 +3,6 @@ org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingP
|
||||
|
||||
org.springframework.beans.factory.aot.BeanRegistrationExcludeFilter=\
|
||||
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer
|
||||
|
||||
org.springframework.aot.hint.RuntimeHintsRegistrar=\
|
||||
org.springframework.boot.autoconfigure.template.TemplateRuntimeHints
|
||||
|
||||
Reference in New Issue
Block a user