PrecompiledTemplateMapFileReader.java revision 56ed4167b942ec265f9cee70ac4d71d10b3835ce
1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Copyright (C) 2010 Google Inc. 3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Licensed under the Apache License, Version 2.0 (the "License"); 5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * you may not use this file except in compliance with the License. 6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * You may obtain a copy of the License at 7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * http://www.apache.org/licenses/LICENSE-2.0 9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Unless required by applicable law or agreed to in writing, software 11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * distributed under the License is distributed on an "AS IS" BASIS, 12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * See the License for the specific language governing permissions and 14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * limitations under the License. 15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupackage com.google.clearsilver.jsilver.precompiler; 18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruimport com.google.clearsilver.jsilver.autoescape.EscapeMode; 20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruimport com.google.clearsilver.jsilver.exceptions.JSilverAutoEscapingException; 21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruimport com.google.common.annotations.VisibleForTesting; 22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruimport com.google.common.collect.ImmutableMap; 23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruimport java.io.FileNotFoundException; 25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruimport java.io.IOException; 26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruimport java.io.InputStream; 27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruimport java.io.InputStreamReader; 28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruimport java.io.LineNumberReader; 29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruimport java.io.Reader; 30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruimport java.util.HashMap; 31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruimport java.util.Map; 32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruimport java.util.StringTokenizer; 33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Utility class that reads in the file output by BatchCompiler that is a list of template names and 36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * corresponding class names and returns a Map of template filenames to class names which can be fed 37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * to {@see com.google.clearsilver.jsilver.JSilverOptions#setPrecompiledTemplateMap} 38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic class PrecompiledTemplateMapFileReader { 40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru private final String mapFileName; 42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru private final String dirPattern; 43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru private final String rootDir; 44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru private Map<Object, String> templateMap = null; 46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /** 48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Helper object that reads in the specified resource file and generates a mapping of template 49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * filenames to corresponding BaseCompiledTemplate class names. 50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param filename name of the resource file to read the map from. 52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param dirPattern prefix to remove from read in template names. Used in conjunction with 53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * rootDir to update template file paths. 54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param rootDir optional string to prepend to all non-absolute template filenames. Should be set 55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * to the location of the templates in production via a flag. 56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru public PrecompiledTemplateMapFileReader(String filename, String dirPattern, String rootDir) { 58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru this.mapFileName = filename; 59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru this.dirPattern = dirPattern; 60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru this.rootDir = rootDir; 61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru public Map<Object, String> getTemplateMap() throws IOException { 64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (templateMap == null) { 65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru templateMap = makeTemplateMap(mapFileName, rootDir); 66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return templateMap; 68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru private Map<Object, String> makeTemplateMap(String templateMapFile, String rootDir) 71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru throws IOException { 72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru Map<Object, String> templateMap = new HashMap<Object, String>(); 73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru LineNumberReader reader = null; 74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru try { 75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru reader = new LineNumberReader(getMapFileReader(templateMapFile)); 76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (String line = reader.readLine(); line != null; line = reader.readLine()) { 77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Process single line from the templateMapFile 78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // and put found templates into templateMap. 79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru processTemplateMapFileLine(line, reader.getLineNumber(), templateMap, templateMapFile, 80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru rootDir); 81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } finally { 83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (reader != null) { 84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru reader.close(); 85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return ImmutableMap.copyOf(templateMap); 88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru private void processTemplateMapFileLine(String line, int lineNumber, 91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru Map<Object, String> templateMap, String templateMapFile, String rootDir) { 92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru line = line.trim(); 94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (line.isEmpty() || line.startsWith("#")) { 95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Ignore blank lines and comment lines. 96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru StringTokenizer st = new StringTokenizer(line); 99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (!st.hasMoreTokens()) { 100 throw new IllegalArgumentException("No template file name found in " + templateMapFile 101 + " on line " + lineNumber + ": " + line); 102 } 103 String templateName = st.nextToken(); 104 if (dirPattern != null && templateName.startsWith(dirPattern)) { 105 templateName = templateName.substring(dirPattern.length()); 106 } 107 if (rootDir != null) { 108 // If it is not an absolute path and we were given a root directory, 109 // prepend it. 110 templateName = rootDir + templateName; 111 } 112 if (!st.hasMoreTokens()) { 113 throw new IllegalArgumentException("No class name found in " + templateMapFile + " on line " 114 + lineNumber + ": " + line); 115 } 116 String className = st.nextToken(); 117 EscapeMode escapeMode; 118 if (!st.hasMoreTokens()) { 119 escapeMode = EscapeMode.ESCAPE_NONE; 120 } else { 121 String escapeCmd = st.nextToken(); 122 try { 123 escapeMode = EscapeMode.computeEscapeMode(escapeCmd); 124 } catch (JSilverAutoEscapingException e) { 125 throw new IllegalArgumentException("Invalid escape mode found in " + templateMapFile 126 + " on line " + lineNumber + ": " + escapeCmd); 127 } 128 } 129 PrecompiledTemplateMapKey key = new PrecompiledTemplateMapKey(templateName, escapeMode); 130 templateMap.put(key, className); 131 } 132 133 @VisibleForTesting 134 protected Reader getMapFileReader(String templateMapFile) throws IOException { 135 ClassLoader classLoader = getClass().getClassLoader(); 136 InputStream in = classLoader.getResourceAsStream(templateMapFile); 137 if (in == null) { 138 throw new FileNotFoundException("Unable to locate resource: " + templateMapFile); 139 } 140 return new InputStreamReader(in, "UTF-8"); 141 } 142 143} 144