PrecompiledTemplateLoader.java revision 56ed4167b942ec265f9cee70ac4d71d10b3835ce
1/* 2 * Copyright (C) 2010 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.google.clearsilver.jsilver.precompiler; 18 19import com.google.clearsilver.jsilver.autoescape.AutoEscapeOptions; 20import com.google.clearsilver.jsilver.autoescape.EscapeMode; 21import com.google.clearsilver.jsilver.compiler.BaseCompiledTemplate; 22import com.google.clearsilver.jsilver.functions.FunctionExecutor; 23import com.google.clearsilver.jsilver.resourceloader.ResourceLoader; 24import com.google.clearsilver.jsilver.template.DelegatingTemplateLoader; 25import com.google.clearsilver.jsilver.template.Template; 26import com.google.clearsilver.jsilver.template.TemplateLoader; 27import com.google.common.annotations.VisibleForTesting; 28import com.google.common.collect.ImmutableMap; 29import java.util.HashMap; 30import java.util.Map; 31 32/** 33 * TemplateLoader that stores objects from precompiled Template classes and serves them when asked 34 * for them. If not found, it passes the request on to the delegate TemplateLoader. 35 */ 36public class PrecompiledTemplateLoader implements DelegatingTemplateLoader { 37 38 /** 39 * This is the next TemplateLoader to ask if we don't find the template. 40 */ 41 private final TemplateLoader nextLoader; 42 43 private final Map<Object, BaseCompiledTemplate> templateMap; 44 private final AutoEscapeOptions autoEscapeOptions; 45 46 public PrecompiledTemplateLoader(TemplateLoader nextLoader, 47 Map<Object, String> templateToClassNameMap, FunctionExecutor globalFunctionExecutor, 48 AutoEscapeOptions autoEscapeOptions) { 49 this.nextLoader = nextLoader; 50 this.autoEscapeOptions = autoEscapeOptions; 51 this.templateMap = makeTemplateMap(templateToClassNameMap, globalFunctionExecutor); 52 } 53 54 private Map<Object, BaseCompiledTemplate> makeTemplateMap( 55 Map<Object, String> templateToClassNameMap, FunctionExecutor globalFunctionExecutor) { 56 Map<Object, BaseCompiledTemplate> templateMap = new HashMap<Object, BaseCompiledTemplate>(); 57 ClassLoader classLoader = getClass().getClassLoader(); 58 for (Map.Entry<Object, String> entry : templateToClassNameMap.entrySet()) { 59 String className = entry.getValue(); 60 BaseCompiledTemplate compiledTemplate = loadTemplateObject(className, classLoader); 61 // Fill in the necessary 62 compiledTemplate.setFunctionExecutor(globalFunctionExecutor); 63 compiledTemplate.setTemplateName(entry.getKey().toString()); 64 compiledTemplate.setTemplateLoader(this); 65 if (entry.getKey() instanceof PrecompiledTemplateMapKey) { 66 PrecompiledTemplateMapKey mapKey = (PrecompiledTemplateMapKey) entry.getKey(); 67 // The template's escapeMode is not currently used as the autoescaping is all 68 // handled at compile time. Still set it in case it is needed later on. 69 compiledTemplate.setEscapeMode(mapKey.getEscapeMode()); 70 } else { 71 compiledTemplate.setEscapeMode(EscapeMode.ESCAPE_NONE); 72 } 73 compiledTemplate.setAutoEscapeOptions(autoEscapeOptions); 74 templateMap.put(entry.getKey(), compiledTemplate); 75 } 76 return ImmutableMap.copyOf(templateMap); 77 } 78 79 @VisibleForTesting 80 protected BaseCompiledTemplate loadTemplateObject(String className, ClassLoader classLoader) { 81 try { 82 Class<?> templateClass = classLoader.loadClass(className); 83 // TODO: Not safe to use in untrusted environments 84 // Does not handle ClassCastException or 85 // verify class type before calling newInstance. 86 return (BaseCompiledTemplate) templateClass.newInstance(); 87 } catch (ClassNotFoundException e) { 88 throw new IllegalArgumentException("Class not found: " + className, e); 89 } catch (IllegalAccessException e) { 90 throw new Error(e); 91 } catch (InstantiationException e) { 92 throw new Error(e); 93 } 94 } 95 96 @Override 97 public void setTemplateLoaderDelegate(TemplateLoader templateLoaderDelegate) { 98 for (BaseCompiledTemplate template : templateMap.values()) { 99 template.setTemplateLoader(templateLoaderDelegate); 100 } 101 } 102 103 @Override 104 public Template load(String templateName, ResourceLoader resourceLoader, EscapeMode escapeMode) { 105 Object key = resourceLoader.getKey(templateName); 106 PrecompiledTemplateMapKey mapKey = new PrecompiledTemplateMapKey(key, escapeMode); 107 Template template = templateMap.get(mapKey); 108 if (template != null) { 109 return template; 110 } else { 111 return nextLoader.load(templateName, resourceLoader, escapeMode); 112 } 113 } 114 115 /** 116 * We don't cache temporary templates here so we just call delegate TemplateLoader. 117 */ 118 @Override 119 public Template createTemp(String name, String content, EscapeMode escapeMode) { 120 return nextLoader.createTemp(name, content, escapeMode); 121 } 122} 123