/**
* License Agreement.
*
* Rich Faces - Natural Ajax for Java Server Faces (JSF)
*
* Copyright (C) 2007 Exadel, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.ajax4jsf.templatecompiler.ant;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.InputStream;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.ajax4jsf.templatecompiler.builder.CompilationContext;
import org.ajax4jsf.templatecompiler.builder.CompilationException;
import org.ajax4jsf.templatecompiler.builder.TemplateCompiler;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
import org.apache.velocity.Template;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
/**
* Task template compiler.
*
* @author ayukhovich@exadel.com (latest modification by $Author: alexsmirnov $)
* @version $Revision: 1.1.2.4 $ $Date: 2007/02/26 20:48:56 $
*
*/
public class TemplateCompilerTask extends Task implements FilenameFilter {
final private static String regexComponent = "^(.*)\\.xhtml$";
final private static Pattern patternComponent = Pattern
.compile(regexComponent);
private final static String TEMPLATE_FILE_EXT = ".xhtml";
/**
* classpath for load component/renderer classes for introspection.
*/
private Path classPath;
private File srcDir;
private File destDir;
protected Vector filesets = new Vector();
/**
* Default constructor
*
* @throws Exception
*/
public TemplateCompilerTask() throws Exception {
super();
}
/**
* getting srcDir
*
* @return Returns the destDir
*/
public File getSrcdir() {
return this.srcDir;
}
/**
* setting a srcDir
*
* @param destDir
* The srcDir to set.
*/
public void setSrcdir(File srcDir) {
this.srcDir = srcDir;
}
/**
* getting a destDit
*
* @return Returns the destDir.
*/
public File getDestdir() {
return this.destDir;
}
/**
* setting a destDir
*
* @param destDir
* The destDir to set.
*/
public void setDestdir(File destDir) {
this.destDir = destDir;
}
/**
* Generate java class name from template filename
*
* @param fileTemplateName
* a string contain template filename
* @return string contain java class name
*/
public String generateJavaClassName(final String fileTemplateName) {
String strJavaClassName = "Unknown";
Matcher mather = patternComponent.matcher(fileTemplateName);
if (mather.find()) {
strJavaClassName = mather.group(1);
} // if
return strJavaClassName;
}
/**
*
* @param sFileTemplate
*/
public void processTemplate(String sFileTemplate) {
// Generate java class name
ClassLoader loader = getClassLoader();
try {
CompilationContext componentBean = new AntCompilationContext(this,loader);
TemplateCompiler templateCompiler = new TemplateCompiler();
// componentBean.setDefaultVariables();
InputStream inputStream = null;
File inputFile = new File(sFileTemplate);
String sF = inputFile.getName().toString();
componentBean.setFullClassName(generateJavaClassName(sF));
inputStream = new FileInputStream(inputFile);
templateCompiler.processing(inputStream, componentBean);
String resultPath = componentBean.getComponentFileName() + ".java";
File javaFile = new File(getDestdir(), resultPath);
File javaDir = javaFile.getParentFile();
if (!javaDir.exists()) {
javaDir.mkdirs();
} // try
if (javaFile.exists()) {
javaFile.delete();
} // if
Writer out = new BufferedWriter(new FileWriter(javaFile));
templateCompiler.generateCode(componentBean, out);
out.flush();
out.close();
} catch (FileNotFoundException e) {
throw new BuildException(e);
} catch (Exception e) {
throw new BuildException(
"Error create new Component Java file, message "
+ e.getLocalizedMessage(), e);
} // catch
}
public ClassLoader getClassLoader() {
ClassLoader loader = getProject().createClassLoader(this.classPath);
if (null == loader) {
loader = this.getClass().getClassLoader();
}
return loader;
}
/**
* Adds a set of files to copy.
*
* @param set
* a set of files to copy
*/
public void addFileset(FileSet set) {
this.filesets.addElement(set);
}
final private static String VELOCITY_PROPERTIES = "velocity.properties";
private VelocityEngine engine;
private Map<String, Template> _templates = new HashMap<String, Template>();
public void init() throws BuildException {
super.init();
Properties velocityProperties = new Properties();
try {
InputStream streamVelosityProperties = TemplateCompilerTask.class.getResourceAsStream(VELOCITY_PROPERTIES);
velocityProperties.load(streamVelosityProperties);
engine = new VelocityEngine();
engine.init(velocityProperties);
} catch(Exception e){
throw new BuildException("Error init velocity engine",e);
}
}
/*
* (non-Javadoc)
*
* @see org.apache.tools.ant.Task#execute()
*/
public void execute() throws BuildException {
ArrayList arrayFiles = new ArrayList();
if (getSrcdir() != null) {
String directory = getSrcdir().toString();
String[] files = new File(directory).list(this);
for (int i = 0; i < files.length; i++) {
arrayFiles.add(directory + File.separatorChar + files[i]);
} // for
}
if (this.filesets.size() == 1) {
// deal with the filesets
for (int i = 0; i < this.filesets.size(); i++) {
FileSet fs = (FileSet) this.filesets.elementAt(i);
DirectoryScanner ds = null;
try {
ds = fs.getDirectoryScanner(getProject());
} catch (BuildException e) {
if (!e.getMessage().endsWith(" not found.")) {
throw e;
} else {
log("Warning: " + e.getMessage());
continue;
}
}
File fromDir = fs.getDir(getProject());
String[] srcFiles = ds.getIncludedFiles();
for (int j = 0; j < srcFiles.length; j++) {
String tempFile = fromDir.getAbsolutePath().toString()
+ File.separator + srcFiles[j];
arrayFiles.add(tempFile);
}
}
}
if (arrayFiles.size() == 0) {
log("Empty list");
} else {
for (Iterator iter = arrayFiles.iterator(); iter.hasNext();) {
String file = (String) iter.next();
log("Processing file :'" + file + "'");
processTemplate(file);
}
}
}
/**
* Tests if a specified file should be included in a file list.
*
* @param dir
* the directory in which the file was found.
* @param name
* the name of the file.
* @return true if and only if the name should be included in the file list;
* false otherwise.
*/
public boolean accept(File dir, String name) {
if (name.endsWith(TEMPLATE_FILE_EXT)) {
return true;
}
return false;
}
/**
* Gets the classpath to be used for this compilation.
*
* @return Returns the classpath.
*/
public Path getClasspath() {
return this.classPath;
}
/**
* Set the classpath to be used for this compilation
*
* @param classpath
* an Ant Path object containing the compilation classpath.
*/
public void setClasspath(Path classpath) {
if (null == this.classPath) {
this.classPath = classpath;
} else {
this.classPath.add(classpath);
}
}
/**
* Adds a reference to a classpath defined elsewhere.
*
* @param ref
* a reference to a classpath
*/
public void setClasspathRef(Reference ref) {
createClasspath().setRefid(ref);
}
/**
* Add a path to the classpath
*
* @return a class path to be configured
*/
public Path createClasspath() {
Path classpath = new Path(getProject());
if (null == this.classPath) {
this.classPath = classpath;
} else {
this.classPath.add(classpath);
}
return classpath;
}
public Template getTemplate(String name) throws CompilationException {
Template template = _templates.get(name);
if(null == template){
try {
template = engine.getTemplate(name);
} catch (ResourceNotFoundException e) {
throw new CompilationException(e.getLocalizedMessage());
} catch (ParseErrorException e) {
throw new CompilationException(e.getLocalizedMessage());
} catch (Exception e) {
throw new CompilationException(e.getLocalizedMessage());
}
_templates.put(name, template);
}
return template;
}
}