001/*
002 * Copyright 2002-2017 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.web.servlet.resource;
018
019import java.util.Collections;
020import javax.servlet.http.HttpServletRequest;
021
022import org.springframework.core.io.Resource;
023
024/**
025 * A base class for a {@code ResourceTransformer} with an optional helper method
026 * for resolving public links within a transformed resource.
027 *
028 * @author Brian Clozel
029 * @author Rossen Stoyanchev
030 * @since 4.1
031 */
032public abstract class ResourceTransformerSupport implements ResourceTransformer {
033
034        private ResourceUrlProvider resourceUrlProvider;
035
036
037        /**
038         * Configure a {@link ResourceUrlProvider} to use when resolving the public
039         * URL of links in a transformed resource (e.g. import links in a CSS file).
040         * This is required only for links expressed as full paths, i.e. including
041         * context and servlet path, and not for relative links.
042         * <p>By default this property is not set. In that case if a
043         * {@code ResourceUrlProvider} is needed an attempt is made to find the
044         * {@code ResourceUrlProvider} exposed through the
045         * {@link org.springframework.web.servlet.resource.ResourceUrlProviderExposingInterceptor
046         * ResourceUrlProviderExposingInterceptor} (configured by default in the MVC
047         * Java config and XML namespace). Therefore explicitly configuring this
048         * property should not be needed in most cases.
049         * @param resourceUrlProvider the URL provider to use
050         */
051        public void setResourceUrlProvider(ResourceUrlProvider resourceUrlProvider) {
052                this.resourceUrlProvider = resourceUrlProvider;
053        }
054
055        /**
056         * Return the configured {@code ResourceUrlProvider}.
057         */
058        public ResourceUrlProvider getResourceUrlProvider() {
059                return this.resourceUrlProvider;
060        }
061
062
063        /**
064         * A transformer can use this method when a resource being transformed
065         * contains links to other resources. Such links need to be replaced with the
066         * public facing link as determined by the resource resolver chain (e.g. the
067         * public URL may have a version inserted).
068         * @param resourcePath the path to a resource that needs to be re-written
069         * @param request the current request
070         * @param resource the resource being transformed
071         * @param transformerChain the transformer chain
072         * @return the resolved URL, or {@code} if not resolvable
073         */
074        protected String resolveUrlPath(String resourcePath, HttpServletRequest request,
075                        Resource resource, ResourceTransformerChain transformerChain) {
076
077                if (resourcePath.startsWith("/")) {
078                        // full resource path
079                        ResourceUrlProvider urlProvider = findResourceUrlProvider(request);
080                        return (urlProvider != null ? urlProvider.getForRequestUrl(request, resourcePath) : null);
081                }
082                else {
083                        // try resolving as relative path
084                        return transformerChain.getResolverChain().resolveUrlPath(
085                                        resourcePath, Collections.singletonList(resource));
086                }
087        }
088
089        private ResourceUrlProvider findResourceUrlProvider(HttpServletRequest request) {
090                if (this.resourceUrlProvider != null) {
091                        return this.resourceUrlProvider;
092                }
093                return (ResourceUrlProvider) request.getAttribute(
094                                ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR);
095        }
096
097}