001    /**
002     * Copyright 2005-2013 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package edu.samplu.common;
017    
018    import freemarker.template.Configuration;
019    import freemarker.template.Template;
020    import freemarker.template.TemplateException;
021    import org.apache.commons.io.FileUtils;
022    import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
023    
024    import java.io.File;
025    import java.io.IOException;
026    import java.io.InputStream;
027    import java.util.Enumeration;
028    import java.util.HashMap;
029    import java.util.Iterator;
030    import java.util.Map;
031    import java.util.Properties;
032    
033    /**
034     * FreemarkerUtil loads properties from user defined InputStream.  systemPropertiesOverride should be used to override properties
035     * using a given key to identify them from JVM args. (i.e. -Dkey.name to override the name property in the key file.)
036     * TODO setup so the loading and overriding of properties is done for the user rather then them having to call it.
037     * @author Kuali Rice Team (rice.collab@kuali.org)
038     */
039    public class FreemarkerUtil {
040    
041        protected Configuration cfg;
042    
043        /**
044         * Calls ftlWrite that also accepts a key, using the output getName as the key.
045         * @param output
046         * @param template
047         * @return
048         * @throws java.io.IOException
049         * @throws freemarker.template.TemplateException
050         */
051        public static File ftlWrite(File output, Template template, InputStream inputStream) throws IOException, TemplateException {
052    
053            return ftlWrite(output.getName(), output, template, inputStream);
054        }
055    
056        /**
057         * Loads properties from user defined properties file, if not available uses resource file
058         *
059         * writes processed template  to file
060         * @param key
061         * @param output
062         * @param template
063         * @throws IOException
064         * @throws TemplateException
065         */
066        public static File ftlWrite(String key, File output, Template template, InputStream inputStream) throws IOException, TemplateException {
067            Properties props = loadProperties(inputStream);
068            props.put("baseName", output.getName().substring(0, output.getName().indexOf("ST")));
069            props.put("className", output.getName().substring(0, output.getName().indexOf("ST"))); // backwards compatibility
070            if (output.getName().contains("TmplMthd")) { // Template method pattern
071                props.put("className", output.getName().substring(0, output.getName().indexOf("TmplMthd")));
072            }
073    
074            systemPropertiesOverride(props, key);
075            transformNumberedTestPropertiesToList(props);
076            File outputFile = writeTemplateToFile(output, template, props);
077    
078            return outputFile;
079        }
080    
081        protected static Properties loadProperties(InputStream inputStream) throws IOException {
082            Properties props = new Properties();
083    
084            if(inputStream != null) {
085                props.load(inputStream);
086            }
087    
088            return props;
089        }
090    
091        protected static void transformNumberedTestPropertiesToList(Properties props) {
092            Iterator keys = props.keySet().iterator();
093            Map<String, String> keyLists = new HashMap<String, String>();
094            while (keys.hasNext()) {
095                String key = (String)keys.next();
096                if (Character.isDigit(key.charAt(key.length()-1))) {
097                    keyLists.put(key, props.getProperty(key));
098                }
099            }
100    
101            Iterator listKeys = keyLists.keySet().iterator();
102            while (listKeys.hasNext()) {
103                String key = (String)listKeys.next();
104                props.remove(key);
105            }
106    
107            if (keyLists.values().size() == 0) { // backwards compatibility
108                keyLists.put("test1", (String)props.get("className"));
109            }
110    
111            props.put("tests", keyLists.values());
112        }
113    
114        /**
115         *
116         * @param file
117         * @param template
118         * @param props
119         * @return
120         * @throws IOException
121         * @throws freemarker.template.TemplateException
122         */
123        protected static File writeTemplateToFile(File file, Template template, Properties props) throws IOException, TemplateException {
124            String output = FreeMarkerTemplateUtils.processTemplateIntoString(template, props);
125            FileUtils.writeStringToFile(file, output);
126    
127            return file;
128        }
129    
130        /**
131         * -Dkey.propertyname= to override the property value for propertyname.
132         * @param props
133         */
134        public static void systemPropertiesOverride(Properties props, String key) {
135            Enumeration<?> names = props.propertyNames();
136            Object nameObject;
137            String name;
138            while (names.hasMoreElements()) {
139                nameObject = names.nextElement();
140                if (nameObject instanceof String) {
141                    name = (String)nameObject;
142                    props.setProperty(name, System.getProperty(key + "." + name, props.getProperty(name)));
143                }
144            }
145        }
146    
147    }