Google guice3.0 の toConstructor を VelocityEngine 生成で使用して
"file.resource.loader.path" をURL path で指定する。
Velocity を使うのにずっと悩んでたのがリソース読込の設定を如何に単純な手順で
済ませるかであった。
Google guice 3.0 のtoConstructor の登場で、かなりシンプルに Velocity
テンプレート生成までたどりつけるようになる。
import java.net.URL;
import java.util.Properties;
import java.util.ResourceBundle;
import org.apache.velocity.Template;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.resource.loader.FileResourceLoader;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
* Velocity テンプレートビルダー
*/
public class TemplateBuilder{
private Properties prop;
private Class<?> vmclass;
/*
* テンプレートファイルをCLASSPATH上に置いた同じパスのクラスを指定
*/
public TemplateBuilder(Class<?> vmclass){
this.prop = new Properties();
this.vmclass = vmclass;
this.defaultConfig();
}
/*
* Velocity設定を記述したProperties のリソース読込baseNameを指定
*/
public TemplateBuilder(String baseName){
this.prop = new Properties();
ResourceBundle rb = ResourceBundle.getBundle(baseName);
for(String key : rb.keySet()){
this.prop.put(key,rb.getString(key));
}
this.defaultConfig();
}
/*
* Velocity設定を記述したProperties を指定
*/
public TemplateBuilder(Properties prop){
this.prop = prop;
this.defaultConfig();
}
/*
* Velocity設定を記述したProperties のリソース読込baseName
* と、テンプレートファイルをCLASSPATH上に置いた同じパスのクラスを指定
*/
public TemplateBuilder(String baseName,Class<?> vmclass){
this.prop = new Properties();
this.vmclass = vmclass;
ResourceBundle rb = ResourceBundle.getBundle(baseName);
for(String key : rb.keySet()){
this.prop.put(key,rb.getString(key));
}
this.defaultConfig();
}
/*
* elocity設定を記述したPropertiesと、
* テンプレートファイルをCLASSPATH上に置いた同じパスのクラスを指定
*/
public TemplateBuilder(Properties prop,Class<?> vmclass){
this.prop = prop;
this.vmclass = vmclass;
this.defaultConfig();
}
private void defaultConfig(){
if (!this.prop.containsKey("resource.loader")){
this.prop.put("resource.loader","file");
this.prop.put("file.resource.loader.class"
,FileResourceLoader.class.getName());
}
this.prop.put("runtime.log.logsystem.class"
,"org.apache.velocity.runtime.log.NullLogSystem");
if (!this.prop.containsKey("input.encoding")){
this.prop.put("input.encoding",inputEncode());
}
if (!this.prop.containsKey("output.encoding")){
this.prop.put("output.encoding",outputEncode());
}
if (this.vmclass != null && !this.prop.containsKey("file.resource.loader.path")){
URL url = this.vmclass.getClassLoader()
.getResource(this.vmclass.getPackage().getName().replaceAll("\\.","/"));
this.prop.put("file.resource.loader.path",url.getPath());
}
}
/**
* テンプレート生成
* @param vmname テンプレートファイル名
* @return org.apache.velocity.Template
*/
public Template create(String vmname){
Injector injector = Guice.createInjector(new AbstractModule(){
@Override
protected void configure(){
binder().bind(Properties.class).toInstance(getProperties());
try{
binder().bind(VelocityEngine.class)
.toConstructor(VelocityEngine.class.getConstructor(Properties.class));
}catch(Exception e){
throw new RuntimeException(e);
}
}
});
VelocityEngine engine = injector.getInstance(VelocityEngine.class);
try{
return engine.getTemplate(vmname,(String)engine.getProperty("input.encoding"));
}catch(Exception e){
throw new RuntimeException(e);
}
}
protected Properties getProperties(){
return this.prop;
}
protected String inputEncode(){
return "UTF-8";
}
protected String outputEncode(){
return "UTF-8";
}
}
----------------------
このようにビルダーを作成すると properties ファイルを用意しないで、
inputEncode() 、outputEncode() をオーバーライドすることで、
文字エンコードを指定したり、
getProperties() で、別途 Velocityリソース設定をすることも
可能である。
@Inject を書いてないところも凄い