001/* 002 * Copyright 2002-2019 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 * https://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.test.context.util; 018 019import java.util.Arrays; 020import java.util.List; 021import java.util.regex.Pattern; 022import java.util.stream.Collectors; 023import java.util.stream.Stream; 024 025import org.springframework.core.io.Resource; 026import org.springframework.core.io.ResourceLoader; 027import org.springframework.core.io.support.ResourcePatternUtils; 028import org.springframework.util.ClassUtils; 029import org.springframework.util.ResourceUtils; 030import org.springframework.util.StringUtils; 031 032/** 033 * Utility methods for working with resources within the <em>Spring TestContext 034 * Framework</em>. Mainly for internal use within the framework. 035 * 036 * @author Sam Brannen 037 * @author Tadaya Tsuyukubo 038 * @since 4.1 039 * @see org.springframework.util.ResourceUtils 040 * @see org.springframework.core.io.Resource 041 * @see org.springframework.core.io.ClassPathResource 042 * @see org.springframework.core.io.FileSystemResource 043 * @see org.springframework.core.io.UrlResource 044 * @see org.springframework.core.io.ResourceLoader 045 */ 046public abstract class TestContextResourceUtils { 047 048 private static final String SLASH = "/"; 049 050 private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile(".*\\$\\{[^}]+}.*"); 051 052 053 /** 054 * Convert the supplied paths to classpath resource paths. 055 * 056 * <p>Delegates to {@link #convertToClasspathResourcePaths(Class, boolean, String...)} 057 * with {@code false} supplied for the {@code preservePlaceholders} flag. 058 * @param clazz the class with which the paths are associated 059 * @param paths the paths to be converted 060 * @return a new array of converted resource paths 061 * @see #convertToResources 062 */ 063 public static String[] convertToClasspathResourcePaths(Class<?> clazz, String... paths) { 064 return convertToClasspathResourcePaths(clazz, false, paths); 065 } 066 067 /** 068 * Convert the supplied paths to classpath resource paths. 069 * 070 * <p>For each of the supplied paths: 071 * <ul> 072 * <li>A plain path — for example, {@code "context.xml"} — will 073 * be treated as a classpath resource that is relative to the package in 074 * which the specified class is defined. Such a path will be prepended with 075 * the {@code classpath:} prefix and the path to the package for the class. 076 * <li>A path starting with a slash will be treated as an absolute path 077 * within the classpath, for example: {@code "/org/example/schema.sql"}. 078 * Such a path will be prepended with the {@code classpath:} prefix. 079 * <li>A path which is already prefixed with a URL protocol (e.g., 080 * {@code classpath:}, {@code file:}, {@code http:}, etc.) will not have its 081 * protocol modified. 082 * </ul> 083 * <p>Each path will then be {@linkplain StringUtils#cleanPath cleaned}, 084 * unless the {@code preservePlaceholders} flag is {@code true} and the path 085 * contains one or more placeholders in the form <code>${placeholder.name}</code>. 086 * @param clazz the class with which the paths are associated 087 * @param preservePlaceholders {@code true} if placeholders should be preserved 088 * @param paths the paths to be converted 089 * @return a new array of converted resource paths 090 * @since 5.2 091 * @see #convertToResources 092 * @see ResourceUtils#CLASSPATH_URL_PREFIX 093 * @see ResourceUtils#FILE_URL_PREFIX 094 */ 095 public static String[] convertToClasspathResourcePaths(Class<?> clazz, boolean preservePlaceholders, String... paths) { 096 String[] convertedPaths = new String[paths.length]; 097 for (int i = 0; i < paths.length; i++) { 098 String path = paths[i]; 099 100 // Absolute path 101 if (path.startsWith(SLASH)) { 102 convertedPaths[i] = ResourceUtils.CLASSPATH_URL_PREFIX + path; 103 } 104 // Relative path 105 else if (!ResourcePatternUtils.isUrl(path)) { 106 convertedPaths[i] = ResourceUtils.CLASSPATH_URL_PREFIX + SLASH + 107 ClassUtils.classPackageAsResourcePath(clazz) + SLASH + path; 108 } 109 // URL 110 else { 111 convertedPaths[i] = path; 112 } 113 114 if (!(preservePlaceholders && PLACEHOLDER_PATTERN.matcher(convertedPaths[i]).matches())) { 115 convertedPaths[i] = StringUtils.cleanPath(convertedPaths[i]); 116 } 117 } 118 return convertedPaths; 119 } 120 121 /** 122 * Convert the supplied paths to an array of {@link Resource} handles using 123 * the given {@link ResourceLoader}. 124 * @param resourceLoader the {@code ResourceLoader} to use to convert the paths 125 * @param paths the paths to be converted 126 * @return a new array of resources 127 * @see #convertToResourceList(ResourceLoader, String...) 128 * @see #convertToClasspathResourcePaths 129 */ 130 public static Resource[] convertToResources(ResourceLoader resourceLoader, String... paths) { 131 return stream(resourceLoader, paths).toArray(Resource[]::new); 132 } 133 134 /** 135 * Convert the supplied paths to a list of {@link Resource} handles using 136 * the given {@link ResourceLoader}. 137 * @param resourceLoader the {@code ResourceLoader} to use to convert the paths 138 * @param paths the paths to be converted 139 * @return a new list of resources 140 * @since 4.2 141 * @see #convertToResources(ResourceLoader, String...) 142 * @see #convertToClasspathResourcePaths 143 */ 144 public static List<Resource> convertToResourceList(ResourceLoader resourceLoader, String... paths) { 145 return stream(resourceLoader, paths).collect(Collectors.toList()); 146 } 147 148 private static Stream<Resource> stream(ResourceLoader resourceLoader, String... paths) { 149 return Arrays.stream(paths).map(resourceLoader::getResource); 150 } 151 152}