@SuppressWarnings("unchecked")
    public Template getTemplate(String name, Locale locale, String encoding, Object args) throws IOException, ParseException {
        name = UrlUtils.cleanName(name);
        locale = cleanLocale(locale);
        Map<Object, Object> cache = this.cache; // safe copy reference
        if (cache == null) {
            return parseTemplate(null, name, locale, encoding, args);
        }
        Resource resource = null;
        long lastModified;
        if (reloadable) {
            resource = loadResource(name, locale, encoding);
            lastModified = resource.getLastModified();
        } else {
            lastModified = Long.MIN_VALUE;
        }
        String key = name;
        if (locale != null || encoding != null) {
            StringBuilder buf = new StringBuilder(name.length() + 20);
            buf.append(name);
            if (locale != null) {
                buf.append("_");
                buf.append(locale);
            }
            if (encoding != null) {
                buf.append("_");
                buf.append(encoding);
            }
            key = buf.toString();
        }
        VolatileReference<Template> reference = (VolatileReference<Template>) cache.get(key);
        if (reference == null) {
            if (cache instanceof ConcurrentMap) {
                reference = new VolatileReference<Template>(); // quickly
                VolatileReference<Template> old = (VolatileReference<Template>) ((ConcurrentMap<Object, Object>) cache).putIfAbsent(key, reference);
                if (old != null) { // duplicate
                    reference = old;
                }
            } else {
                synchronized (cache) { // cache lock
                    reference = (VolatileReference<Template>) cache.get(key);
                    if (reference == null) { // double check
                        reference = new VolatileReference<Template>(); // quickly
                        cache.put(key, reference);
                    }
                }
            }
        }
        assert (reference != null);
        Template template = reference.get();
        if (template == null || template.getLastModified() < lastModified) {
            synchronized (reference) { // reference lock
                template = reference.get();
                if (template == null || template.getLastModified() < lastModified) { // double check
                    template = parseTemplate(resource, name, locale, encoding, args); // slowly
                    reference.set(template);
                }
            }
        }
        assert (template != null);
        return template;
    }
@ SuppressWarnings ( "unchecked" ) public Template getTemplate ( String name , Locale locale , String encoding , Object args ) throws IOException , ParseException { name = UrlUtils . cleanName ( name ) ; locale = cleanLocale ( locale ) ; Map < Object , Object > cache = this . cache ; if ( cache == null ) { return parseTemplate ( null , name , locale , encoding , args ) ; } Resource resource = null ; long lastModified ; if ( reloadable ) { resource = loadResource ( name , locale , encoding ) ; lastModified = resource . getLastModified ( ) ; } else { lastModified = Long . MIN_VALUE ; } String key = name ; if ( locale != null || encoding != null ) { StringBuilder buf = new StringBuilder ( name . length ( ) + 20 ) ; buf . append ( name ) ; if ( locale != null ) { buf . append ( "_" ) ; buf . append ( locale ) ; } if ( encoding != null ) { buf . append ( "_" ) ; buf . append ( encoding ) ; } key = buf . toString ( ) ; } VolatileReference < Template > reference = ( VolatileReference < Template > ) cache . get ( key ) ; if ( reference == null ) { if ( cache instanceof ConcurrentMap ) { reference = new VolatileReference < Template > ( ) ; VolatileReference < Template > old = ( VolatileReference < Template > ) ( ( ConcurrentMap < Object , Object > ) cache ) . putIfAbsent ( key , reference ) ; if ( old != null ) { reference = old ; } } else { synchronized ( cache ) { reference = ( VolatileReference < Template > ) cache . get ( key ) ; if ( reference == null ) { reference = new VolatileReference < Template > ( ) ; cache . put ( key , reference ) ; } } } } assert ( reference != null ) ; Template template = reference . get ( ) ; if ( template == null || template . getLastModified ( ) < lastModified ) { synchronized ( reference ) { template = reference . get ( ) ; if ( template == null || template . getLastModified ( ) < lastModified ) { template = parseTemplate ( resource , name , locale , encoding , args ) ; reference . set ( template ) ; } } } assert ( template != null ) ; return template ; }
Get template.

@param name     - template name
@param locale   - template locale
@param encoding - template encoding
@return template instance
@throws IOException    - If an I/O error occurs
@throws ParseException - If the template cannot be parsed
@see #getEngine()