001/*
002 * Copyright 2002-2012 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.ui.velocity;
018
019import java.io.IOException;
020import java.io.InputStream;
021import java.util.Arrays;
022
023import org.apache.commons.collections.ExtendedProperties;
024import org.apache.commons.logging.Log;
025import org.apache.commons.logging.LogFactory;
026import org.apache.velocity.exception.ResourceNotFoundException;
027import org.apache.velocity.runtime.resource.Resource;
028import org.apache.velocity.runtime.resource.loader.ResourceLoader;
029
030import org.springframework.util.StringUtils;
031
032/**
033 * Velocity ResourceLoader adapter that loads via a Spring ResourceLoader.
034 * Used by VelocityEngineFactory for any resource loader path that cannot
035 * be resolved to a {@code java.io.File}.
036 *
037 * <p>Note that this loader does not allow for modification detection:
038 * Use Velocity's default FileResourceLoader for {@code java.io.File}
039 * resources.
040 *
041 * <p>Expects "spring.resource.loader" and "spring.resource.loader.path"
042 * application attributes in the Velocity runtime: the former of type
043 * {@code org.springframework.core.io.ResourceLoader}, the latter a String.
044 *
045 * @author Juergen Hoeller
046 * @since 14.03.2004
047 * @see VelocityEngineFactory#setResourceLoaderPath
048 * @see org.springframework.core.io.ResourceLoader
049 * @see org.apache.velocity.runtime.resource.loader.FileResourceLoader
050 */
051public class SpringResourceLoader extends ResourceLoader {
052
053        public static final String NAME = "spring";
054
055        public static final String SPRING_RESOURCE_LOADER_CLASS = "spring.resource.loader.class";
056
057        public static final String SPRING_RESOURCE_LOADER_CACHE = "spring.resource.loader.cache";
058
059        public static final String SPRING_RESOURCE_LOADER = "spring.resource.loader";
060
061        public static final String SPRING_RESOURCE_LOADER_PATH = "spring.resource.loader.path";
062
063
064        protected final Log logger = LogFactory.getLog(getClass());
065
066        private org.springframework.core.io.ResourceLoader resourceLoader;
067
068        private String[] resourceLoaderPaths;
069
070
071        @Override
072        public void init(ExtendedProperties configuration) {
073                this.resourceLoader = (org.springframework.core.io.ResourceLoader)
074                                this.rsvc.getApplicationAttribute(SPRING_RESOURCE_LOADER);
075                String resourceLoaderPath = (String) this.rsvc.getApplicationAttribute(SPRING_RESOURCE_LOADER_PATH);
076                if (this.resourceLoader == null) {
077                        throw new IllegalArgumentException(
078                                        "'resourceLoader' application attribute must be present for SpringResourceLoader");
079                }
080                if (resourceLoaderPath == null) {
081                        throw new IllegalArgumentException(
082                                        "'resourceLoaderPath' application attribute must be present for SpringResourceLoader");
083                }
084                this.resourceLoaderPaths = StringUtils.commaDelimitedListToStringArray(resourceLoaderPath);
085                for (int i = 0; i < this.resourceLoaderPaths.length; i++) {
086                        String path = this.resourceLoaderPaths[i];
087                        if (!path.endsWith("/")) {
088                                this.resourceLoaderPaths[i] = path + "/";
089                        }
090                }
091                if (logger.isInfoEnabled()) {
092                        logger.info("SpringResourceLoader for Velocity: using resource loader [" + this.resourceLoader +
093                                        "] and resource loader paths " + Arrays.asList(this.resourceLoaderPaths));
094                }
095        }
096
097        @Override
098        public InputStream getResourceStream(String source) throws ResourceNotFoundException {
099                if (logger.isDebugEnabled()) {
100                        logger.debug("Looking for Velocity resource with name [" + source + "]");
101                }
102                for (String resourceLoaderPath : this.resourceLoaderPaths) {
103                        org.springframework.core.io.Resource resource =
104                                        this.resourceLoader.getResource(resourceLoaderPath + source);
105                        try {
106                                return resource.getInputStream();
107                        }
108                        catch (IOException ex) {
109                                if (logger.isDebugEnabled()) {
110                                        logger.debug("Could not find Velocity resource: " + resource);
111                                }
112                        }
113                }
114                throw new ResourceNotFoundException(
115                                "Could not find resource [" + source + "] in Spring resource loader path");
116        }
117
118        @Override
119        public boolean isSourceModified(Resource resource) {
120                return false;
121        }
122
123        @Override
124        public long getLastModified(Resource resource) {
125                return 0;
126        }
127
128}