Java tutorial
/* * This file is a component of thundr, a software library from 3wks. * Read more: http://3wks.github.io/thundr/ * Copyright (C) 2014 3wks, <thundr@3wks.com.au> * * 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 * * http://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 com.threewks.thundr.view.velocity; import java.io.File; import java.io.InputStream; import javax.servlet.ServletContext; import org.apache.commons.collections.ExtendedProperties; import org.apache.commons.lang3.StringUtils; import org.apache.velocity.exception.ResourceNotFoundException; import org.apache.velocity.runtime.resource.Resource; import org.apache.velocity.runtime.resource.loader.ResourceLoader; import com.atomicleopard.expressive.Cast; import com.threewks.thundr.exception.BaseException; /** * Resource loader that uses the ServletContext of a webapp to * load Velocity templates. * * * This is adapted from the WebappResourceLoader found in velocity tools. */ public class ServletContextResourceLoader extends ResourceLoader { protected ServletContext servletContext = null; /** * This is abstract in the base class, so we need it. <br> * NOTE: this expects that the ServletContext has already * been placed in the runtime's application attributes * under its full class name (i.e. "javax.servlet.ServletContext"). * * @param configuration the {@link ExtendedProperties} associated with * this resource loader. */ @Override public void init(ExtendedProperties configuration) { /* get the ServletContext */ Object obj = rsvc.getApplicationAttribute(ServletContext.class.getName()); servletContext = Cast.as(obj, ServletContext.class); if (servletContext == null) { throw new BaseException( "Unable to use the %s, the %s must be in the velocity extended properties under the key '%s'", this.getClass().getSimpleName(), ServletContext.class.getSimpleName(), ServletContext.class.getName()); } } /** * Get an InputStream so that the Runtime can build a * template with it. * * @param name name of template to get * @return InputStream containing the template * @throws ResourceNotFoundException if template not found * in classpath. */ @Override public synchronized InputStream getResourceStream(String name) throws ResourceNotFoundException { if (StringUtils.isBlank(name)) { throw new ResourceNotFoundException("No template name provided"); } InputStream result = null; try { result = servletContext.getResourceAsStream(name); } catch (Exception e) { throw new ResourceNotFoundException("Resource '" + name + "' not found: " + e.getMessage(), e); } if (result == null) { throw new ResourceNotFoundException("Resource '" + name + "' not found"); } return result; } private File getCachedFile(String rootPath, String fileName) { return new File(rootPath, fileName); } /** * Checks to see if a resource has been deleted, moved or modified. * * @param resource Resource The resource to check for modification * @return boolean True if the resource has been modified */ @Override public boolean isSourceModified(Resource resource) { String rootPath = servletContext.getRealPath("/"); if (rootPath == null) { // rootPath is null if the servlet container cannot translate the // virtual path to a real path for any reason (such as when the // content is being made available from a .war archive) return false; } // first, try getting the previously found file String fileName = resource.getName(); File cachedFile = getCachedFile(rootPath, fileName); if (!cachedFile.exists()) { /* then the source has been moved and/or deleted */ return true; } /* * check to see if the file can now be found elsewhere * before it is found in the previously saved path */ File currentFile = new File(rootPath, fileName); /* if the current is the cached and it is readable */ if (cachedFile.equals(currentFile) && cachedFile.canRead()) { /* then (and only then) do we compare the last modified values */ return (cachedFile.lastModified() != resource.getLastModified()); } else { /* * we found a new file for the resource * or the resource is no longer readable. */ return true; } } /** * Checks to see when a resource was last modified * * @param resource Resource the resource to check * @return long The time when the resource was last modified or 0 if the file can't be read */ @Override public long getLastModified(Resource resource) { String rootPath = servletContext.getRealPath("/"); if (rootPath == null) { // rootPath is null if the servlet container cannot translate the // virtual path to a real path for any reason (such as when the // content is being made available from a .war archive) return 0; } File cachedFile = getCachedFile(rootPath, resource.getName()); if (cachedFile.canRead()) { return cachedFile.lastModified(); } else { return 0; } } }