All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.velocity.runtime.resource.loader.StringResourceLoader Maven / Gradle / Ivy

The newest version!
package org.apache.velocity.runtime.resource.loader;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

import org.apache.commons.lang3.StringUtils;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.exception.VelocityException;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.Resource;
import org.apache.velocity.runtime.resource.util.StringResource;
import org.apache.velocity.runtime.resource.util.StringResourceRepository;
import org.apache.velocity.runtime.resource.util.StringResourceRepositoryImpl;
import org.apache.velocity.util.ClassUtils;
import org.apache.velocity.util.ExtProperties;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * Resource loader that works with Strings. Users should manually add
 * resources to the repository that is used by the resource loader instance.
 *
 * Below is an example configuration for this loader.
 * Note that 'repository.class' is not necessary;
 * if not provided, the factory will fall back on using
 * {@link StringResourceRepositoryImpl} as the default.
 * 
 * resource.loaders = string
 * resource.loader.string.description = Velocity StringResource loader
 * resource.loader.string.class = org.apache.velocity.runtime.resource.loader.StringResourceLoader
 * resource.loader.string.repository.name = MyRepositoryName (optional, to avoid using the default repository)
 * resource.loader.string.repository.class = org.apache.velocity.runtime.resource.loader.StringResourceRepositoryImpl
 * 
* Resources can be added to the repository like this: *

 *   StringResourceRepository repo = StringResourceLoader.getRepository();
 *
 *   String myTemplateName = "/some/imaginary/path/hello.vm";
 *   String myTemplate = "Hi, ${username}... this is some template!";
 *   repo.putStringResource(myTemplateName, myTemplate);
 * 
* * After this, the templates can be retrieved as usual. *
*

If there will be multiple StringResourceLoaders used in an application, * you should consider specifying a 'resource.loader.string.repository.name = foo' * property in order to keep you string resources in a non-default repository. * This can help to avoid conflicts between different frameworks or components * that are using StringResourceLoader. * You can then retrieve your named repository like this: *


 *   StringResourceRepository repo = StringResourceLoader.getRepository("foo");
 * 
*

and add string resources to the repo just as in the previous example. *

*

If you have concerns about memory leaks or for whatever reason do not wish * to have your string repository stored statically as a class member, then you * should set 'resource.loader.string.repository.static = false' in your properties. * This will tell the resource loader that the string repository should be stored * in the Velocity application attributes. To retrieve the repository, do:

*

 *   StringResourceRepository repo = velocityEngine.getApplicationAttribute("foo");
 * 
*

If you did not specify a name for the repository, then it will be stored under the * class name of the repository implementation class (for which the default is * 'org.apache.velocity.runtime.resource.util.StringResourceRepositoryImpl'). * Incidentally, this is also true for the default statically stored repository. *

*

Whether your repository is stored statically or in Velocity's application * attributes, you can also manually create and set it prior to Velocity * initialization. For a static repository, you can do something like this: *


 *   StringResourceRepository repo = new MyStringResourceRepository();
 *   repo.magicallyAddSomeStringResources();
 *   StringResourceLoader.setRepository("foo", repo);
 * 
*

Or for a non-static repository:

*

 *   StringResourceRepository repo = new MyStringResourceRepository();
 *   repo.magicallyAddSomeStringResources();
 *   velocityEngine.setApplicationAttribute("foo", repo);
 * 
*

Then, assuming the 'resource.loader.string.repository.name' property is * set to 'some.name', the StringResourceLoader will use that already created * repository, rather than creating a new one. *

* * @author Eelco Hillenius * @author Henning P. Schmiedehausen * @author Nathan Bubna * @version $Id$ * @since 1.5 */ public class StringResourceLoader extends ResourceLoader { /** * Key to determine whether the repository should be set as the static one or not. * @since 1.6 */ public static final String REPOSITORY_STATIC = "repository.static"; /** * By default, repositories are stored statically (shared across the VM). * @since 1.6 */ public static final boolean REPOSITORY_STATIC_DEFAULT = true; /** Key to look up the repository implementation class. */ public static final String REPOSITORY_CLASS = "repository.class"; /** The default implementation class. */ public static final String REPOSITORY_CLASS_DEFAULT = StringResourceRepositoryImpl.class.getName(); /** * Key to look up the name for the repository to be used. * @since 1.6 */ public static final String REPOSITORY_NAME = "repository.name"; /** The default name for string resource repositories * ('org.apache.velocity.runtime.resource.util.StringResourceRepository'). * @since 1.6 */ public static final String REPOSITORY_NAME_DEFAULT = StringResourceRepository.class.getName(); /** Key to look up the repository char encoding. */ public static final String REPOSITORY_ENCODING = "repository.encoding"; protected static final Map STATIC_REPOSITORIES = Collections.synchronizedMap(new HashMap<>()); /** * Returns a reference to the default static repository. * @return default static repository */ public static StringResourceRepository getRepository() { return getRepository(REPOSITORY_NAME_DEFAULT); } /** * Returns a reference to the repository stored statically under the * specified name. * @param name * @return named repository * @since 1.6 */ public static StringResourceRepository getRepository(String name) { return (StringResourceRepository)STATIC_REPOSITORIES.get(name); } /** * Sets the specified {@link StringResourceRepository} in static storage * under the specified name. * @param name * @param repo * @since 1.6 */ public static void setRepository(String name, StringResourceRepository repo) { STATIC_REPOSITORIES.put(name, repo); } /** * Removes the {@link StringResourceRepository} stored under the specified * name. * @param name * @return removed repository * @since 1.6 */ public static StringResourceRepository removeRepository(String name) { return (StringResourceRepository)STATIC_REPOSITORIES.remove(name); } /** * Removes all statically stored {@link StringResourceRepository}s. * @since 1.6 */ public static void clearRepositories() { STATIC_REPOSITORIES.clear(); } /** * the repository used internally by this resource loader */ protected StringResourceRepository repository; /** * @param configuration * @see ResourceLoader#init(org.apache.velocity.util.ExtProperties) */ @Override public void init(final ExtProperties configuration) { log.trace("StringResourceLoader: initialization starting."); // get the repository configuration info String repoClass = configuration.getString(REPOSITORY_CLASS, REPOSITORY_CLASS_DEFAULT); String repoName = configuration.getString(REPOSITORY_NAME, REPOSITORY_NAME_DEFAULT); boolean isStatic = configuration.getBoolean(REPOSITORY_STATIC, REPOSITORY_STATIC_DEFAULT); String encoding = configuration.getString(REPOSITORY_ENCODING); // look for an existing repository of that name and isStatic setting if (isStatic) { this.repository = getRepository(repoName); if (repository != null) { log.debug("Loaded repository '{}' from static repo store", repoName); } } else { this.repository = (StringResourceRepository)rsvc.getApplicationAttribute(repoName); if (repository != null) { log.debug("Loaded repository '{}' from application attributes", repoName); } } if (this.repository == null) { // since there's no repository under the repo name, create a new one this.repository = createRepository(repoClass, encoding); // and store it according to the isStatic setting if (isStatic) { setRepository(repoName, this.repository); } else { rsvc.setApplicationAttribute(repoName, this.repository); } } else { // ok, we already have a repo // warn them if they are trying to change the class of the repository if (!this.repository.getClass().getName().equals(repoClass)) { log.debug("Cannot change class of string repository '{}' from {} to {}." + " The change will be ignored.", repoName, this.repository.getClass().getName(), repoClass); } // allow them to change the default encoding of the repo if (encoding != null && !this.repository.getEncoding().equals(encoding)) { log.debug("Changing the default encoding of string repository '{}' from {} to {}", repoName, this.repository.getEncoding(), encoding); this.repository.setEncoding(encoding); } } log.trace("StringResourceLoader: initialization complete."); } /** * @param className * @param encoding * @return created repository * @since 1.6 */ public StringResourceRepository createRepository(final String className, final String encoding) { log.debug("Creating string repository using class {}...", className); StringResourceRepository repo; try { repo = (StringResourceRepository) ClassUtils.getNewInstance(className); } catch (ClassNotFoundException cnfe) { throw new VelocityException("Could not find '" + className + "'", cnfe); } catch (IllegalAccessException iae) { throw new VelocityException("Could not access '" + className + "'", iae); } catch (InstantiationException ie) { throw new VelocityException("Could not instantiate '" + className + "'", ie); } if (encoding != null) { repo.setEncoding(encoding); } else { repo.setEncoding(RuntimeConstants.ENCODING_DEFAULT); } log.debug("Default repository encoding is {}", repo.getEncoding()); return repo; } /** * Overrides superclass for better performance. * @param name resource name * @return whether resource exists * @since 1.6 */ @Override public boolean resourceExists(final String name) { if (name == null) { return false; } return (this.repository.getStringResource(name) != null); } /** * Get a reader so that the Runtime can build a * template with it. * * @param name name of template to get. * @param encoding asked encoding * @return Reader containing the template. * @throws ResourceNotFoundException Ff template not found * in the RepositoryFactory. * @since 2.0 */ @Override public Reader getResourceReader(String name, String encoding) throws ResourceNotFoundException { if (StringUtils.isEmpty(name)) { throw new ResourceNotFoundException("No template name provided"); } StringResource resource = this.repository.getStringResource(name); if(resource == null) { throw new ResourceNotFoundException("Could not locate resource '" + name + "'"); } byte [] byteArray = null; InputStream rawStream = null; try { byteArray = resource.getBody().getBytes(resource.getEncoding()); rawStream = new ByteArrayInputStream(byteArray); return new InputStreamReader(rawStream, resource.getEncoding()); } catch(UnsupportedEncodingException ue) { if (rawStream != null) { try { rawStream.close(); } catch (IOException ioe) {} } throw new VelocityException("Could not convert String using encoding " + resource.getEncoding(), ue, rsvc.getLogContext().getStackTrace()); } } /** * @param resource * @return whether resource was modified * @see ResourceLoader#isSourceModified(org.apache.velocity.runtime.resource.Resource) */ @Override public boolean isSourceModified(final Resource resource) { StringResource original = null; boolean result = true; original = this.repository.getStringResource(resource.getName()); if (original != null) { result = original.getLastModified() != resource.getLastModified(); } return result; } /** * @param resource * @return last modified timestamp * @see ResourceLoader#getLastModified(org.apache.velocity.runtime.resource.Resource) */ @Override public long getLastModified(final Resource resource) { StringResource original = null; original = this.repository.getStringResource(resource.getName()); return (original != null) ? original.getLastModified() : 0; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy