/*
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.
*/
package org.opentides.util;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.opentides.bean.BeanDefinition;
/**
* @author allantan
*
*/
public class CloningUtil {
private static final Logger _log = Logger.getLogger(CloningUtil.class.getName());
public static final String ENCODING = "utf-8";
/**
* Hides the constructor. This is a singleton.
*/
private CloningUtil() {
}
/**
* Outputs the velocity template along with specified parameters
* to the given output writer.
* @param path
* @param params
* @param output
*/
public static void mergeVmTemplate(String path, Map<String, Object> params, Writer output) {
try {
// initialize velocity to read from Jar
Properties p = new Properties();
p.put("resource.loader", "class");
p.put("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
VelocityEngine ve = new VelocityEngine();
ve.init(p);
VelocityContext context = new VelocityContext();
// Put all params to context
for (Entry<String,Object> entry:params.entrySet()) {
context.put(entry.getKey(), entry.getValue());
}
Template template = ve.getTemplate(path, ENCODING);
template.merge(context, output);
} catch (ResourceNotFoundException e) {
// handle this templating error
_log.log(Level.SEVERE, e.getMessage(), e);
} catch (ParseErrorException e) {
// handle this templating error
_log.log(Level.SEVERE, e.getMessage(), e);
} catch (MethodInvocationException e) {
// handle this templating error
_log.log(Level.SEVERE, e.getMessage(), e);
} catch (Exception e) {
// report this unknown error
throw new RuntimeException(e);
} finally {
// just make sure file is closed
try { output.close(); } catch (IOException e) { };
}
}
/**
* Builds the path to the output file.
* params.get("templateSourceBase") = templates/opentides
* params.get("package") = org.opentides
*
* @param template - classpath reference to the template (e.g. templates/opentides/dao/classNameDao.java.vm)
* @param params
* @return the output file name = com/ideyatech/dao/SystemCodesDao.java
*/
public static String getOutputName(String template, Map<String, Object> params) {
// find the appropriate path of output file
String base = PackageUtil.toFolderName(""+params.get("templateSourceBase"));
String output = template;
int idx = template.indexOf(base);
if (idx >= 0) {
idx += base.length();
output = template.substring(idx);
}
BeanDefinition bean = (BeanDefinition) params.get("bean");
// now build the filename
String outputName = PackageUtil.toFolderName(""+bean.getPackage_()) +
output.replace("className", bean.getClassName())
.replace("modelName", bean.getModelName())
.replaceAll(".java.vm$", "").replaceAll(".vm$", "");
return outputName;
}
/**
* Helper method that retrieves all templates available inside the template
* jar file.
* @return
*/
public static List<String> getJarTemplates() {
List<String> templates = new ArrayList<String>();
Set<String> templateJars = PackageUtil.getTemplateJars();
for (String jarName : templateJars) {
// traverse the jar files
// Reference - jarName: /Users/allantan/.m2/repository/org/opentides/opentides3-template/3.0.1-SNAPSHOT/opentides3-template-3.0.1-SNAPSHOT.jar
JarFile jarFile = null;
try {
jarFile = new JarFile(jarName);
for (Enumeration<JarEntry> e = jarFile.entries(); e.hasMoreElements();) {
JarEntry jarEntry = e.nextElement();
// Reference - templateName: templates/opentides/dao/classNameDao.java.vm
// Reference - outputFile: com/ideyatech/dao/SystemCodesDao.java
BufferedWriter bw = null;
String templateName = jarEntry.getName();
if (templateName.endsWith(".vm"))
templates.add(templateName);
}
} catch (IOException e1) {
_log.log(Level.SEVERE,"Failed to read template jar files.",e1);
} finally {
try {
if (jarFile != null) jarFile.close();
} catch (IOException e) {
}
}
}
return templates;
}
/**
* Helper method that retrieves all the templates available from a
* given folder location.
* @return
*/
public static List<String> getFolderTemplates() {
List<String> templates = new ArrayList<String>();
Set<String> templateFolders = PackageUtil.getTemplateFolders();
for (String folderName : templateFolders) {
// traverse the jar files
// Reference - jarName: /Users/allantan/.m2/repository/org/opentides/opentides3-template/3.0.1-SNAPSHOT/opentides3-template-3.0.1-SNAPSHOT.jar
File folderFile = new File(folderName);
File folder = folderFile.getParentFile();
if (folder!=null && folder.isDirectory()) {
walkFiles(folder, folderFile.getParent() + File.separatorChar, ".vm", templates);
}
}
return templates;
}
/**
* Internal helper function to recursively list all files in the folder.
* @param folder
* @param limit
*/
private static void walkFiles(File folder, String prefix, String suffix, List<String> templates) {
if (folder.isDirectory()) {
File[] files = folder.listFiles();
for (File file:files)
walkFiles(file, prefix, suffix, templates);
} else if (folder.getName().endsWith(suffix)) {
String path = folder.getAbsolutePath().replace(prefix, "");
templates.add(path);
}
}
}