/*
* Copyright (c) 2002-2012 Alibaba Group Holding Limited.
* All rights reserved.
*
* 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.alibaba.citrus.util.templatelite;
import static com.alibaba.citrus.test.TestEnvStatic.*;
import static com.alibaba.citrus.test.TestUtil.*;
import static com.alibaba.citrus.util.StringUtil.*;
import static org.junit.Assert.*;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.net.URL;
import java.nio.charset.Charset;
import com.alibaba.citrus.util.IllegalPathException;
import com.alibaba.citrus.util.templatelite.Template.InputSource;
import org.junit.Test;
public class TemplateInputSourceTests extends AbstractTemplateTests {
private InputSource inputSource;
@Test
public void charsetDetection() throws IOException {
String content;
// -----------------
content = "";
content += "\n";
content += " ## comment\n";
content += " \\#@charset hello\n"; // 这行导致charset检查结束
content += "#@otherparam value value\n";
content += " #@charset GB18030\n";
assertEquals("default", detectCharset(content));
// -----------------
content = "";
content += "\n"; // 忽略空行
content += " \r\n"; // 忽略空行
content += " ## comment\n"; // 忽略注释
content += "#@otherparam value value\n"; // 忽略其它参数
content += " #@charset GB18030\n"; // 匹配charset
assertEquals("GB18030", detectCharset(content));
// -----------------
content = "";
content += "##@charset 8859_1\n"; // 忽略注释
content += " #@charset GB18030##comment\n"; // 匹配charset##comment
assertEquals("GB18030", detectCharset(content));
// -----------------
content = "";
content += "######\n"; // 无内容
assertEquals("default", detectCharset(content));
// -----------------
content = repeat("#", 1024 * 4) + "\n";
content += " #@charset GB18030\n"; // 超过了readlimit
assertEquals("default", detectCharset(content));
}
private String detectCharset(String content) throws IOException {
return Template.InputSource.detectCharset(
new BufferedInputStream(new ByteArrayInputStream(content.getBytes("ISO-8859-1"))), "default");
}
@Test
public void getRelative_File() throws Exception {
InputSource parentSource = new InputSource(new File("/aa/bb/cc.txt"));
assertNull(parentSource.getRelative(null));
assertNull(parentSource.getRelative(" "));
inputSource = parentSource.getRelative(" b.txt ");
assertEquals(new File("/aa/bb/b.txt").toURI().toURL().toExternalForm(), inputSource.systemId);
inputSource = parentSource.getRelative(" /b.txt ");
assertEquals(new File("/aa/bb/b.txt").toURI().toURL().toExternalForm(), inputSource.systemId);
inputSource = parentSource.getRelative(" ../b.txt ");
assertEquals(new File("/aa/b.txt").toURI().normalize().toURL().toExternalForm(), inputSource.systemId);
inputSource = parentSource.getRelative(" ../../b.txt ");
assertEquals(new File("/b.txt").toURI().normalize().toURL().toExternalForm(), inputSource.systemId);
try {
inputSource = parentSource.getRelative(" ../../../b.txt ");
fail();
} catch (IllegalPathException e) {
assertThat(e, exception("../../../b.txt"));
}
}
@Test
public void getRelative_URL() throws Exception {
InputSource parentSource = new InputSource(new URL("http://localhost:8080/aa/bb/cc.txt"));
assertNull(parentSource.getRelative(null));
assertNull(parentSource.getRelative(" "));
inputSource = parentSource.getRelative("b.txt ");
assertEquals("http://localhost:8080/aa/bb/b.txt", inputSource.systemId);
inputSource = parentSource.getRelative("/b.txt ");
assertEquals("http://localhost:8080/aa/bb/b.txt", inputSource.systemId);
inputSource = parentSource.getRelative(" ../b.txt ");
assertEquals("http://localhost:8080/aa/b.txt", inputSource.systemId);
inputSource = parentSource.getRelative(" ../../b.txt ");
assertEquals("http://localhost:8080/b.txt", inputSource.systemId);
try {
inputSource = parentSource.getRelative(" ../../../b.txt ");
fail();
} catch (IllegalPathException e) {
assertThat(e, exception("../../../b.txt"));
}
}
@Test
public void getRelative_Stream() throws Exception {
FileInputStream f = new FileInputStream(new File(srcdir, "test05_param_gbk.txt"));
InputSource parentSource = new InputSource(f, "test.txt");
assertNull(parentSource.getRelative(null));
assertNull(parentSource.getRelative(" "));
assertNull(parentSource.getRelative("b.txt "));
f.close();
}
@Test
public void getReader() throws IOException {
File f = new File(srcdir, "test05_param_gbk.txt");
// file as input source
inputSource = new InputSource(f);
assertReader("GBK", f, f.toURI().toString());
inputSource = new InputSource(new File(srcdir, "../templates/test05_param_gbk.txt"));
assertReader("GBK", f, f.toURI().toString());
// file: url as input source
inputSource = new InputSource(f.toURI().toURL());
assertReader("GBK", f, f.toURI().toURL().toExternalForm());
// url as input source
URL jarurl = copyFilesToJar("test.jar", "test05_param_gbk.txt", "gbk.txt");
URL url = new URL("jar:" + jarurl.toExternalForm() + "!/gbk.txt");
inputSource = new InputSource(url);
assertReader("GBK", url, url.toExternalForm());
// stream as input source
inputSource = new InputSource(new ByteArrayInputStream("#@charset UTF-8\n\nhello".getBytes("UTF-8")),
"utf8.txt");
assertReader("UTF-8", null, "utf8.txt");
// reader as input source
inputSource = new InputSource(new StringReader("#@charset UTF-8\n\nhello"), "utf8.txt");
assertReader(null, null, "utf8.txt");
}
private void assertReader(String charset, Object source, String systemId) throws IOException {
Reader reader = null;
try {
reader = inputSource.getReader();
assertNotNull(reader);
if (charset != null) {
assertTrue(reader instanceof InputStreamReader);
assertEquals(charset, Charset.forName(((InputStreamReader) reader).getEncoding()).name()); // canonical name
}
assertEquals(source, inputSource.source);
assertEquals(systemId, inputSource.systemId);
} finally {
if (reader != null) {
reader.close();
}
}
}
@Test
public void fileNotExist() throws Exception {
try {
loadTemplate("notexist.txt", 0, 0, 0);
fail();
} catch (TemplateParseException e) {
assertThat(e, exception(FileNotFoundException.class));
}
}
@Test
public void reloadTemplate() throws Exception {
source = "temp.txt";
// template from test07_reload_1.txt
copyFile("test07_reload_1.txt", source);
URL jarurl = copyFilesToJar("temp.jar", "test07_reload_1.txt", source);
URL url = new URL("jar:" + jarurl.toExternalForm() + "!/temp.txt");
File destFile = new File(destdir, source);
Template[] templates = new Template[] {
new Template(destFile), //
new Template(destFile.toURI().toURL()), //
new Template(url), //
new Template(destFile.toURI().toURL().openStream(), "temp.txt"), //
new Template(new InputStreamReader(destFile.toURI().toURL().openStream()), "temp.txt"), //
new Template(new BufferedReader(new InputStreamReader(destFile.toURI().toURL().openStream())),
"temp.txt"), //
};
boolean[] reloadable = new boolean[] { true, true, false, false, false, false };
boolean[] clearsource = new boolean[] { false, false, false, true, true, true };
for (int i = 0; i < templates.length; i++) {
Template t = templates[i];
assertEquals(clearsource[i], t.source.source == null);
assertTemplate(t, null, 2, 0, 0, null);
assertEquals("abc\n${abc}", t.renderToString(new FallbackTextWriter<StringBuilder>()));
}
// 由于文件系统的timestamp实际上是以秒计的,所以必须等待1s以上,文件的lastModified才会变化。
Thread.sleep(1001);
// template from test07_reload_2.txt
copyFile("test07_reload_2.txt", source);
copyFilesToJar("temp.jar", "test07_reload_2.txt", source);
for (int i = 0; i < templates.length; i++) {
Template t = templates[i];
if (reloadable[i]) {
assertEquals("xyz\n${xyz}", t.renderToString(new FallbackTextWriter<StringBuilder>()));
assertTemplate(t, null, 2, 0, 0, null);
} else {
assertEquals("abc\n${abc}", t.renderToString(new FallbackTextWriter<StringBuilder>()));
assertTemplate(t, null, 2, 0, 0, null);
}
}
}
@Test
public void reloadImportedTemplate() throws Exception {
source = "temp.txt";
// template from test07_reload_1.txt
copyFile("test07_reload_1.txt", "imported.txt");
copyFile("test07_reload_import.txt", source);
Template template = new Template(new File(destdir, source));
assertEquals("abc\n${abc}", template.renderToString(new FallbackTextWriter<StringBuilder>()));
// 由于文件系统的timestamp实际上是以秒计的,所以必须等待1s以上,文件的lastModified才会变化。
Thread.sleep(1001);
// template from test07_reload_2.txt
copyFile("test07_reload_2.txt", "imported.txt");
assertEquals("xyz\n${xyz}", template.renderToString(new FallbackTextWriter<StringBuilder>()));
}
}