Package org.apache.velocity.runtime.resource.loader

Source Code of org.apache.velocity.runtime.resource.loader.StringResourceLoader

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 java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import org.apache.commons.collections.ExtendedProperties;
import org.apache.commons.lang.StringUtils;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.exception.VelocityException;
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;

/**
* 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.
* <pre>
* resource.loader = string
* string.resource.loader.description = Velocity StringResource loader
* string.resource.loader.class = org.apache.velocity.runtime.resource.loader.StringResourceLoader
* string.resource.loader.repository.class = org.apache.velocity.runtime.resource.util.StringResourceRepositoryImpl
* </pre>
* Resources can be added to the repository like this:
* <pre><code>
*   StringResourceRepository repo = StringResourceLoader.getRepository();
*
*   String myTemplateName = "/some/imaginary/path/hello.vm";
*   String myTemplate = "Hi, ${username}... this is some template!";
*   repo.putStringResource(myTemplateName, myTemplate);
* </code></pre>
*
* After this, the templates can be retrieved as usual.
* <br>
* <p>If there will be multiple StringResourceLoaders used in an application,
* you should consider specifying a 'string.resource.loader.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:
* <pre><code>
*   StringResourceRepository repo = StringResourceLoader.getRepository("foo");
* </code></pre>
* and add string resources to the repo just as in the previous example.
* </p>
* <p>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 'string.resource.loader.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:
* <pre><code>
*   StringResourceRepository repo = velocityEngine.getApplicationAttribute("foo");
* </code></pre>
* 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.
* </p>
* <p>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:
* <pre><code>
*   StringResourceRepository repo = new MyStringResourceRepository();
*   repo.magicallyAddSomeStringResources();
*   StringResourceLoader.setRepository("foo", repo);
* </code></pre>
* Or for a non-static repository:
* <pre><code>
*   StringResourceRepository repo = new MyStringResourceRepository();
*   repo.magicallyAddSomeStringResources();
*   velocityEngine.setApplicationAttribute("foo", repo);
* </code></pre>
* Then, assuming the 'string.resource.loader.repository.name' property is
* set to 'some.name', the StringResourceLoader will use that already created
* repository, rather than creating a new one.
* </p>
*
* @author <a href="mailto:eelco.hillenius@openedge.nl">Eelco Hillenius</a>
* @author <a href="mailto:henning@apache.org">Henning P. Schmiedehausen</a>
* @author Nathan Bubna
* @version $Id: StringResourceLoader.java 825302 2009-10-14 21:51:39Z nbubna $
* @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";

    /** The default repository encoding. */
    public static final String REPOSITORY_ENCODING_DEFAULT = "UTF-8";


    protected static final Map STATIC_REPOSITORIES =
        Collections.synchronizedMap(new HashMap());

    /**
     * Returns a reference to the default static repository.
     */
    public static StringResourceRepository getRepository()
    {
        return getRepository(REPOSITORY_NAME_DEFAULT);
    }

    /**
     * Returns a reference to the repository stored statically under the
     * specified name.
     * @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.
     * @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.
     * @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;


    /**
     * @see org.apache.velocity.runtime.resource.loader.ResourceLoader#init(org.apache.commons.collections.ExtendedProperties)
     */
    public void init(final ExtendedProperties 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.isDebugEnabled())
            {
                log.debug("Loaded repository '"+repoName+"' from static repo store");
            }
        }
        else
        {
            this.repository = (StringResourceRepository)rsvc.getApplicationAttribute(repoName);
            if (repository != null && log.isDebugEnabled())
            {
                log.debug("Loaded repository '"+repoName+"' from application attributes");
            }
        }

        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 '"+repoName+
                          "' from "+this.repository.getClass().getName()+" to "+repoClass+
                          ". The change will be ignored.");
            }

            // allow them to change the default encoding of the repo
            if (encoding != null &&
                !this.repository.getEncoding().equals(encoding))
            {
                if (log.isDebugEnabled())
                {
                    log.debug("Changing the default encoding of string repository '"+repoName+
                              "' from "+this.repository.getEncoding()+" to "+encoding);
                }
                this.repository.setEncoding(encoding);
            }
        }

        log.trace("StringResourceLoader : initialization complete.");
    }

    /**
     * @since 1.6
     */
    public StringResourceRepository createRepository(final String className,
                                                     final String encoding)
    {
        if (log.isDebugEnabled())
        {
            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(REPOSITORY_ENCODING_DEFAULT);
        }

        if (log.isDebugEnabled())
        {
            log.debug("Default repository encoding is " + repo.getEncoding());
        }
        return repo;
    }

    /**
     * Overrides superclass for better performance.
     * @since 1.6
     */
    public boolean resourceExists(final String name)
    {
        if (name == null)
        {
            return false;
        }
        return (this.repository.getStringResource(name) != null);
    }

    /**
     * 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 Ff template not found
     *         in the RepositoryFactory.
     */
    public InputStream getResourceStream(final String name)
            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;
     
        try
        {
            byteArray = resource.getBody().getBytes(resource.getEncoding());
            return new ByteArrayInputStream(byteArray);
        }
        catch(UnsupportedEncodingException ue)
        {
            throw new VelocityException("Could not convert String using encoding " + resource.getEncoding(), ue);
        }
    }

    /**
     * @see org.apache.velocity.runtime.resource.loader.ResourceLoader#isSourceModified(org.apache.velocity.runtime.resource.Resource)
     */
    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;
    }

    /**
     * @see org.apache.velocity.runtime.resource.loader.ResourceLoader#getLastModified(org.apache.velocity.runtime.resource.Resource)
     */
    public long getLastModified(final Resource resource)
    {
        StringResource original = null;

        original = this.repository.getStringResource(resource.getName());

        return (original != null)
                ? original.getLastModified()
                : 0;
    }

}
TOP

Related Classes of org.apache.velocity.runtime.resource.loader.StringResourceLoader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.