001/*
002 * Copyright 2012-2018 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.boot.autoconfigure.template;
018
019import java.util.List;
020
021import org.springframework.boot.context.properties.bind.Binder;
022import org.springframework.core.env.Environment;
023import org.springframework.core.io.ResourceLoader;
024import org.springframework.util.ClassUtils;
025
026/**
027 * Abstract base class for {@link TemplateAvailabilityProvider} implementations that find
028 * templates from paths.
029 *
030 * @author Andy Wilkinson
031 * @author Phillip Webb
032 * @author Madhura Bhave
033 * @since 1.4.6
034 */
035public abstract class PathBasedTemplateAvailabilityProvider
036                implements TemplateAvailabilityProvider {
037
038        private final String className;
039
040        private final Class<TemplateAvailabilityProperties> propertiesClass;
041
042        private final String propertyPrefix;
043
044        @SuppressWarnings("unchecked")
045        public PathBasedTemplateAvailabilityProvider(String className,
046                        Class<? extends TemplateAvailabilityProperties> propertiesClass,
047                        String propertyPrefix) {
048                this.className = className;
049                this.propertiesClass = (Class<TemplateAvailabilityProperties>) propertiesClass;
050                this.propertyPrefix = propertyPrefix;
051        }
052
053        @Override
054        public boolean isTemplateAvailable(String view, Environment environment,
055                        ClassLoader classLoader, ResourceLoader resourceLoader) {
056                if (ClassUtils.isPresent(this.className, classLoader)) {
057                        Binder binder = Binder.get(environment);
058                        TemplateAvailabilityProperties properties = binder
059                                        .bind(this.propertyPrefix, this.propertiesClass)
060                                        .orElseCreate(this.propertiesClass);
061                        return isTemplateAvailable(view, resourceLoader, properties);
062                }
063                return false;
064        }
065
066        private boolean isTemplateAvailable(String view, ResourceLoader resourceLoader,
067                        TemplateAvailabilityProperties properties) {
068                String location = properties.getPrefix() + view + properties.getSuffix();
069                for (String path : properties.getLoaderPath()) {
070                        if (resourceLoader.getResource(path + location).exists()) {
071                                return true;
072                        }
073                }
074                return false;
075        }
076
077        protected abstract static class TemplateAvailabilityProperties {
078
079                private String prefix;
080
081                private String suffix;
082
083                protected TemplateAvailabilityProperties(String prefix, String suffix) {
084                        this.prefix = prefix;
085                        this.suffix = suffix;
086                }
087
088                protected abstract List<String> getLoaderPath();
089
090                public String getPrefix() {
091                        return this.prefix;
092                }
093
094                public void setPrefix(String prefix) {
095                        this.prefix = prefix;
096                }
097
098                public String getSuffix() {
099                        return this.suffix;
100                }
101
102                public void setSuffix(String suffix) {
103                        this.suffix = suffix;
104                }
105
106        }
107
108}