Enjoy 3.2 release ^_^
This commit is contained in:
207
src/main/java/com/jfinal/template/source/ClassPathSource.java
Normal file
207
src/main/java/com/jfinal/template/source/ClassPathSource.java
Normal file
@@ -0,0 +1,207 @@
|
||||
/**
|
||||
* Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com).
|
||||
*
|
||||
* Licensed 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 com.jfinal.template.source;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import com.jfinal.template.EngineConfig;
|
||||
|
||||
/**
|
||||
* ClassPathSource 用于从 class path 以及 jar 包之中加载模板内容
|
||||
*
|
||||
* <pre>
|
||||
* 注意:
|
||||
* 1:如果被加载的文件是 class path 中的普通文件,则该文件支持热加载
|
||||
*
|
||||
* 2:如果被加载的文件处于 jar 包之中,则该文件不支持热加载,jar 包之中的文件在运行时通常不会被修改
|
||||
* 在极少数情况下如果需要对 jar 包之中的模板文件进行热加载,可以通过继承 ClassPathSource
|
||||
* 的方式进行扩展
|
||||
*
|
||||
* 3:JFinal Template Engine 开启热加载需要配置 engine.setDevMode(true)
|
||||
* </pre>
|
||||
*/
|
||||
public class ClassPathSource implements ISource {
|
||||
|
||||
protected String finalFileName;
|
||||
protected String fileName;
|
||||
protected String encoding;
|
||||
|
||||
protected boolean isInJar;
|
||||
protected long lastModified;
|
||||
protected ClassLoader classLoader;
|
||||
protected URL url;
|
||||
|
||||
public ClassPathSource(String fileName) {
|
||||
this(null, fileName, EngineConfig.DEFAULT_ENCODING);
|
||||
}
|
||||
|
||||
public ClassPathSource(String baseTemplatePath, String fileName) {
|
||||
this(baseTemplatePath, fileName, EngineConfig.DEFAULT_ENCODING);
|
||||
}
|
||||
|
||||
public ClassPathSource(String baseTemplatePath, String fileName, String encoding) {
|
||||
this.finalFileName = buildFinalFileName(baseTemplatePath, fileName);
|
||||
this.fileName = fileName;
|
||||
this.encoding= encoding;
|
||||
this.classLoader = getClassLoader();
|
||||
this.url = classLoader.getResource(finalFileName);
|
||||
if (url == null) {
|
||||
throw new IllegalArgumentException("File not found : \"" + finalFileName + "\"");
|
||||
}
|
||||
|
||||
processIsInJarAndlastModified();
|
||||
}
|
||||
|
||||
protected void processIsInJarAndlastModified() {
|
||||
try {
|
||||
URLConnection conn = url.openConnection();
|
||||
if ("jar".equals(url.getProtocol()) || conn instanceof JarURLConnection) {
|
||||
isInJar = true;
|
||||
lastModified = -1;
|
||||
} else {
|
||||
isInJar = false;
|
||||
lastModified = conn.getLastModified();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected ClassLoader getClassLoader() {
|
||||
ClassLoader ret = Thread.currentThread().getContextClassLoader();
|
||||
return ret != null ? ret : getClass().getClassLoader();
|
||||
}
|
||||
|
||||
protected String buildFinalFileName(String baseTemplatePath, String fileName) {
|
||||
String finalFileName;
|
||||
if (baseTemplatePath != null) {
|
||||
char firstChar = fileName.charAt(0);
|
||||
if (firstChar == '/' || firstChar == '\\') {
|
||||
finalFileName = baseTemplatePath + fileName;
|
||||
} else {
|
||||
finalFileName = baseTemplatePath + "/" + fileName;
|
||||
}
|
||||
} else {
|
||||
finalFileName = fileName;
|
||||
}
|
||||
|
||||
if (finalFileName.charAt(0) == '/') {
|
||||
finalFileName = finalFileName.substring(1);
|
||||
}
|
||||
|
||||
return finalFileName;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public String getEncoding() {
|
||||
return encoding;
|
||||
}
|
||||
|
||||
protected long getLastModified() {
|
||||
try {
|
||||
URLConnection conn = url.openConnection();
|
||||
return conn.getLastModified();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 模板文件在 jar 包文件之内则不支持热加载
|
||||
*/
|
||||
public boolean isModified() {
|
||||
return isInJar ? false : lastModified != getLastModified();
|
||||
}
|
||||
|
||||
public StringBuilder getContent() {
|
||||
// 与 FileSorce 不同,ClassPathSource 在构造方法中已经初始化了 lastModified
|
||||
// 下面的代码可以去掉,在此仅为了避免继承类忘了在构造中初始化 lastModified 的防卫式代码
|
||||
if (!isInJar) { // 如果模板文件不在 jar 包文件之中,则需要更新 lastModified 值
|
||||
lastModified = getLastModified();
|
||||
}
|
||||
|
||||
InputStream inputStream = classLoader.getResourceAsStream(finalFileName);
|
||||
if (inputStream == null) {
|
||||
throw new RuntimeException("File not found : \"" + finalFileName + "\"");
|
||||
}
|
||||
|
||||
return loadFile(inputStream, encoding);
|
||||
}
|
||||
|
||||
public static StringBuilder loadFile(InputStream inputStream, String encoding) {
|
||||
StringBuilder ret = new StringBuilder();
|
||||
BufferedReader br = null;
|
||||
try {
|
||||
br = new BufferedReader(new InputStreamReader(inputStream, encoding));
|
||||
// br = new BufferedReader(new FileReader(fileName));
|
||||
String line = br.readLine();
|
||||
if (line != null) {
|
||||
ret.append(line);
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
|
||||
while ((line=br.readLine()) != null) {
|
||||
ret.append('\n').append(line);
|
||||
}
|
||||
return ret;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
finally {
|
||||
if (br != null) {
|
||||
try {
|
||||
br.close();
|
||||
} catch (IOException e) {
|
||||
// com.jfinal.kit.LogKit.error(e.getMessage(), e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("In Jar File: ").append(isInJar).append("\n");
|
||||
sb.append("File name: ").append(fileName).append("\n");
|
||||
sb.append("Final file name: ").append(finalFileName).append("\n");
|
||||
sb.append("Last modified: ").append(lastModified).append("\n");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
protected File getFile(URL url) {
|
||||
try {
|
||||
// return new File(url.toURI().getSchemeSpecificPart());
|
||||
return new File(url.toURI());
|
||||
} catch (URISyntaxException ex) {
|
||||
// Fallback for URLs that are not valid URIs (should hardly ever happen).
|
||||
return new File(url.getFile());
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com).
|
||||
*
|
||||
* Licensed 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 com.jfinal.template.source;
|
||||
|
||||
/**
|
||||
* ClassPathSourceFactory 用于配置 Engine 使用 ClassPathSource 加载模板文件
|
||||
*
|
||||
* 配置示例:
|
||||
* engine.baseTemplatePath(null); // 清掉 base path
|
||||
* engine.setSourceFactory(new ClassPathSourceFactory());
|
||||
*/
|
||||
public class ClassPathSourceFactory implements ISourceFactory {
|
||||
|
||||
public ISource getSource(String baseTemplatePath, String fileName, String encoding) {
|
||||
return new ClassPathSource(baseTemplatePath, fileName, encoding);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
133
src/main/java/com/jfinal/template/source/FileSource.java
Normal file
133
src/main/java/com/jfinal/template/source/FileSource.java
Normal file
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
* Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com).
|
||||
*
|
||||
* Licensed 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 com.jfinal.template.source;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import com.jfinal.template.EngineConfig;
|
||||
|
||||
/**
|
||||
* FileSource 用于从普通文件中加载模板内容
|
||||
*/
|
||||
public class FileSource implements ISource {
|
||||
|
||||
private String finalFileName;
|
||||
private String fileName;
|
||||
private String encoding;
|
||||
|
||||
private long lastModified;
|
||||
|
||||
public FileSource(String baseTemplatePath, String fileName, String encoding) {
|
||||
this.finalFileName = buildFinalFileName(baseTemplatePath, fileName);
|
||||
this.fileName = fileName;
|
||||
this.encoding= encoding;
|
||||
}
|
||||
|
||||
public FileSource(String baseTemplatePath, String fileName) {
|
||||
this(baseTemplatePath, fileName, EngineConfig.DEFAULT_ENCODING);
|
||||
}
|
||||
|
||||
public boolean isModified() {
|
||||
return lastModified != new File(finalFileName).lastModified();
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public String getEncoding() {
|
||||
return encoding;
|
||||
}
|
||||
|
||||
public String getFinalFileName() {
|
||||
return finalFileName;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public StringBuilder getContent() {
|
||||
File file = new File(finalFileName);
|
||||
if (!file.exists()) {
|
||||
throw new RuntimeException("File not found : " + finalFileName);
|
||||
}
|
||||
|
||||
// 极为重要,否则在开发模式下 isModified() 一直返回 true,缓存一直失效(原因是 lastModified 默认值为 0)
|
||||
this.lastModified = file.lastModified();
|
||||
|
||||
return loadFile(file, encoding);
|
||||
}
|
||||
|
||||
private String buildFinalFileName(String baseTemplatePath, String fileName) {
|
||||
char firstChar = fileName.charAt(0);
|
||||
String finalFileName;
|
||||
if (firstChar == '/' || firstChar == '\\') {
|
||||
finalFileName = baseTemplatePath + fileName;
|
||||
} else {
|
||||
finalFileName = baseTemplatePath + File.separator + fileName;
|
||||
}
|
||||
return finalFileName;
|
||||
}
|
||||
|
||||
public static StringBuilder loadFile(File file, String encoding) {
|
||||
StringBuilder ret = new StringBuilder((int)file.length() + 3);
|
||||
BufferedReader br = null;
|
||||
try {
|
||||
br = new BufferedReader(new InputStreamReader(new FileInputStream(file), encoding));
|
||||
// br = new BufferedReader(new FileReader(fileName));
|
||||
String line = br.readLine();
|
||||
if (line != null) {
|
||||
ret.append(line);
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
|
||||
while ((line=br.readLine()) != null) {
|
||||
ret.append('\n').append(line);
|
||||
}
|
||||
return ret;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
finally {
|
||||
if (br != null) {
|
||||
try {
|
||||
br.close();
|
||||
} catch (IOException e) {
|
||||
// com.jfinal.kit.LogKit.error(e.getMessage(), e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("File name: ").append(fileName).append("\n");
|
||||
sb.append("Final file name: ").append(finalFileName).append("\n");
|
||||
sb.append("Last modified: ").append(lastModified).append("\n");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com).
|
||||
*
|
||||
* Licensed 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 com.jfinal.template.source;
|
||||
|
||||
/**
|
||||
* FileSourceFactory 用于配置 Engine 使用 FileSource 加载模板文件
|
||||
*
|
||||
* 注意:
|
||||
* FileSourceFactory 为模板引擎默认配置
|
||||
*/
|
||||
public class FileSourceFactory implements ISourceFactory {
|
||||
|
||||
public ISource getSource(String baseTemplatePath, String fileName, String encoding) {
|
||||
return new FileSource(baseTemplatePath, fileName, encoding);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
48
src/main/java/com/jfinal/template/source/ISource.java
Normal file
48
src/main/java/com/jfinal/template/source/ISource.java
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com).
|
||||
*
|
||||
* Licensed 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 com.jfinal.template.source;
|
||||
|
||||
/**
|
||||
* ISource 用于表示模板内容的来源
|
||||
*/
|
||||
public interface ISource {
|
||||
|
||||
/**
|
||||
* reload template if modified on devMode
|
||||
*/
|
||||
boolean isModified();
|
||||
|
||||
/**
|
||||
* key used to cache, return null if do not cache the template
|
||||
*
|
||||
* 注意:如果不希望缓存从该 ISource 解析出来的 Template 对象
|
||||
* 让 getKey() 返回 null 值即可
|
||||
*/
|
||||
String getKey();
|
||||
|
||||
/**
|
||||
* content of ISource
|
||||
*/
|
||||
StringBuilder getContent();
|
||||
|
||||
/**
|
||||
* encoding of content
|
||||
*/
|
||||
String getEncoding();
|
||||
}
|
||||
|
||||
|
34
src/main/java/com/jfinal/template/source/ISourceFactory.java
Normal file
34
src/main/java/com/jfinal/template/source/ISourceFactory.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com).
|
||||
*
|
||||
* Licensed 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 com.jfinal.template.source;
|
||||
|
||||
/**
|
||||
* ISourceFactory 用于为 engine 切换不同的 ISource 实现类
|
||||
*
|
||||
* FileSourceFactory 用于从指定的目录中加载模板文件
|
||||
* ClassPathSourceFactory 用于从 class path 以及 jar 文件中加载模板文件
|
||||
*
|
||||
* 配置示例:
|
||||
* engine.setSourceFactory(new ClassPathSourceFactory());
|
||||
*/
|
||||
public interface ISourceFactory {
|
||||
ISource getSource(String baseTemplatePath, String fileName, String encoding);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
81
src/main/java/com/jfinal/template/source/StringSource.java
Normal file
81
src/main/java/com/jfinal/template/source/StringSource.java
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com).
|
||||
*
|
||||
* Licensed 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 com.jfinal.template.source;
|
||||
|
||||
import com.jfinal.kit.HashKit;
|
||||
import com.jfinal.kit.StrKit;
|
||||
import com.jfinal.template.EngineConfig;
|
||||
|
||||
/**
|
||||
* StringSource 用于从 String 变量中加载模板内容
|
||||
*/
|
||||
public class StringSource implements ISource {
|
||||
|
||||
private String key;
|
||||
private StringBuilder content;
|
||||
|
||||
/**
|
||||
* 构造 StringSource
|
||||
* @param content 模板内容
|
||||
* @param cache true 则缓存 Template,否则不缓存
|
||||
*/
|
||||
public StringSource(String content, boolean cache) {
|
||||
if (StrKit.isBlank(content)) {
|
||||
throw new IllegalArgumentException("content can not be blank");
|
||||
}
|
||||
this.content = new StringBuilder(content);
|
||||
this.key = cache ? HashKit.md5(content) : null; // 不缓存只要将 key 值赋为 null 即可
|
||||
}
|
||||
|
||||
public StringSource(StringBuilder content, boolean cache) {
|
||||
if (content == null || content.length() == 0) {
|
||||
throw new IllegalArgumentException("content can not be blank");
|
||||
}
|
||||
this.content = content;
|
||||
this.key = cache ? HashKit.md5(content.toString()) : null; // 不缓存只要将 key 值赋为 null 即可
|
||||
}
|
||||
|
||||
public boolean isModified() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public StringBuilder getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public String getEncoding() {
|
||||
return EngineConfig.DEFAULT_ENCODING;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Key : ").append(key).append("\n");
|
||||
sb.append("Content : ").append(content).append("\n");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user