You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by dd...@apache.org on 2016/01/24 19:19:05 UTC
incubator-freemarker git commit: FREEMARKER-15 fixed: Got rid of
jar-s (and class binaries inside) in the test source code. I haven't
implemented this as part of the build script,
to help migrating to other build tools later. Instead, the JUnit test itse
Repository: incubator-freemarker
Updated Branches:
refs/heads/2.3.24-gae-stabilization ec3d4618b -> 99d939c99
FREEMARKER-15 fixed: Got rid of jar-s (and class binaries inside) in the test source code. I haven't implemented this as part of the build script, to help migrating to other build tools later. Instead, the JUnit test itself builds the required jar-s on the fly.
Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/99d939c9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/99d939c9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/99d939c9
Branch: refs/heads/2.3.24-gae-stabilization
Commit: 99d939c99ab062a3be8491f5f64100bcc931b100
Parents: ec3d461
Author: ddekany <dd...@apache.org>
Authored: Sun Jan 24 19:18:50 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sun Jan 24 19:18:50 2016 +0100
----------------------------------------------------------------------
NOTICE | 4 -
.../config/WebappLocalFreemarkerServlet.java | 25 ++
.../freemarker/test/ResourcesExtractor.java | 296 +++++++++++++++++++
.../freemarker/test/servlet/WebAppTestCase.java | 175 +++++++----
.../ext/jsp/webapps/basic/CONTENTS.txt | 33 +++
.../ext/jsp/webapps/config/CONTENTS.txt | 33 +++
.../lib/WebappLocalFreemarkerServlet.jar | Bin 936 -> 0 bytes
.../webapps/config/WEB-INF/lib/templates.jar | Bin 1018 -> 0 bytes
.../WEB-INF/lib/templates.jar/sub/test2.ftl | 19 ++
.../ext/jsp/webapps/config/WEB-INF/web.xml | 4 +-
.../ext/jsp/webapps/errors/CONTENTS.txt | 28 ++
.../jsp/webapps/multipleLoaders/CONTENTS.txt | 24 ++
.../ext/jsp/webapps/tldDiscovery/CONTENTS.txt | 37 +++
.../tldDiscovery/WEB-INF/lib/taglib-foo.jar | Bin 1221 -> 0 bytes
.../lib/taglib-foo.jar/META-INF/foo bar.tld | 32 ++
.../webapps/tldDiscovery/WEB-INF/taglib 2.jar | Bin 1179 -> 0 bytes
.../WEB-INF/taglib 2.jar/META-INF/taglib.tld | 31 ++
17 files changed, 672 insertions(+), 69 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/NOTICE
----------------------------------------------------------------------
diff --git a/NOTICE b/NOTICE
index af3d669..4c7b803 100644
--- a/NOTICE
+++ b/NOTICE
@@ -25,9 +25,5 @@ license of the FreeMarker project:
src/main/misc/overloadedNumberRules/prices.ods
src/manual/en_US/docgen-originals/figures/overview.odg
- src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/WebappLocalFreemarkerServlet.jar
- src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/templates.jar
- src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/lib/taglib-foo.jar
- src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/taglib 2.jar
=========================================================================
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/java/freemarker/ext/jsp/webapps/config/WebappLocalFreemarkerServlet.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/ext/jsp/webapps/config/WebappLocalFreemarkerServlet.java b/src/test/java/freemarker/ext/jsp/webapps/config/WebappLocalFreemarkerServlet.java
new file mode 100644
index 0000000..9411633
--- /dev/null
+++ b/src/test/java/freemarker/ext/jsp/webapps/config/WebappLocalFreemarkerServlet.java
@@ -0,0 +1,25 @@
+/*
+ * 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 freemarker.ext.jsp.webapps.config;
+
+import freemarker.ext.servlet.FreemarkerServlet;
+
+public class WebappLocalFreemarkerServlet extends FreemarkerServlet {
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/java/freemarker/test/ResourcesExtractor.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/test/ResourcesExtractor.java b/src/test/java/freemarker/test/ResourcesExtractor.java
new file mode 100644
index 0000000..88e1bed
--- /dev/null
+++ b/src/test/java/freemarker/test/ResourcesExtractor.java
@@ -0,0 +1,296 @@
+/*
+ * 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 freemarker.test;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.jar.JarOutputStream;
+import java.util.zip.ZipEntry;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.io.Files;
+
+import freemarker.template.utility.StringUtil;
+
+/**
+ * Extracts a collection of resources from a Java package into a file system directory, based on the {@value ResourcesExtractor#CONTENTS_TXT}
+ * resource in it. It won't scan to find resources automatically, so everything has to be added to this file.
+ *
+ * <p>Regarding the content of {@value ResourcesExtractor#CONTENTS_TXT}:
+ * <ul>
+ * <li>Lines starting with {code //} or {code /*} or {code *} are comments.
+ * <li>Each non-empty line in the {@value ResourcesExtractor#CONTENTS_TXT} that isn't comment, there must be
+ * a resource path relative to the "directory" that contains {@value ResourcesExtractor#CONTENTS_TXT}. Only the
+ * files referred this way will be copied. (Referring to directories doesn't copy the files in them.)
+ * <li>If the entry ends with {@code "/"}, then it denotes a directory that must be created even if there will be
+ * no files in it. Otherwise it's redundant to add such entries.
+ * <li>The content of "subdirectories" whose name ends with {@value ResourcesExtractor#SUFFIX_JAR} will be copied
+ * into a jar file with similar name, instead of into a directory.
+ * <li>An line may contains {@value #ARROW}, in which case the left side of the {@value #ARROW} is the
+ * <em>absolute</em> path of the copied resource, and the right side of the {@value #ARROW} is the target
+ * relative path (like the path in the usual lines). This is useful for copying class files generated by
+ * the normal Java compilation mechanism into target subdirectories like {@code WEB-INF\classes\com\example}.
+ * </ul>
+ */
+public final class ResourcesExtractor {
+
+ private static final String ARROW = "->";
+ private static final String DOT_TMP = ".tmp";
+ public static final String CONTENTS_TXT = "CONTENTS.txt";
+ public static final String SUFFIX_JAR = ".jar";
+
+ private static final Logger LOG = LoggerFactory.getLogger(ResourcesExtractor.class);
+
+ private ResourcesExtractor() {
+ // Not meant to be instantiated
+ }
+
+ /**
+ * @param resolverClass
+ * The class with which the resources are loaded.
+ * @param srcDirResourcePath
+ * The resource path to which the paths in {@value ResourcesExtractor#CONTENTS_TXT} are relative to. If
+ * the value of this parameter doesn't start with {@code "/"}, then it's relative to the package of the
+ * {@code resolverClass}.
+ *
+ * @return The temporary directory into which the resource where extracted to. Don't forget to delete it when it's
+ * not used anymore.
+ */
+ public static File extract(Class resolverClass, String srcDirResourcePath, File dstRootDir) throws IOException {
+ if (!srcDirResourcePath.endsWith("/")) {
+ srcDirResourcePath += "/";
+ }
+
+ String contResource = srcDirResourcePath + CONTENTS_TXT;
+ InputStream contIn = resolverClass.getResourceAsStream(contResource);
+ if (contIn == null) {
+ throw new IOException("Can't find resource: class=" + resolverClass + ", path=" + contResource);
+ }
+
+ boolean deleteDstRootDir;
+ if (dstRootDir == null) {
+ dstRootDir = Files.createTempDir();
+ deleteDstRootDir = true;
+ } else {
+ deleteDstRootDir = !dstRootDir.exists();
+ }
+ try {
+ BufferedReader contR = new BufferedReader(new InputStreamReader(contIn, "UTF-8"));
+ try {
+ String contLine;
+ while ((contLine = contR.readLine()) != null) {
+ processLine(contLine, resolverClass, srcDirResourcePath, dstRootDir, contResource);
+ }
+ } finally {
+ contR.close();
+ }
+ jarMarkedSubdirectories(dstRootDir);
+ deleteDstRootDir = false;
+ } finally {
+ if (deleteDstRootDir) {
+ try {
+ if (dstRootDir.getParentFile() == null) {
+ throw new IOException("Won't delete the root directory");
+ }
+ FileUtils.deleteDirectory(dstRootDir);
+ } catch (IOException e) {
+ LOG.error("Failed to delete destination directory: " + dstRootDir, e);
+ }
+ }
+ }
+
+ return dstRootDir;
+ }
+
+ private static void processLine(String contLine, Class<?> resolverClass, String srcDirResourcePath, File dstRootDir,
+ String contResource) throws IOException {
+ contLine = contLine.trim();
+ if (contLine.isEmpty() || contLine.startsWith("//") || contLine.startsWith("/*")
+ || contLine.startsWith("*")) {
+ return;
+ }
+
+ String contSrcPath = contLine;
+ String contDstPath = contLine;
+ boolean contSrcPathRelative;
+ int arrowIdx = contLine.indexOf(ARROW);
+ if (arrowIdx != -1) {
+ if (!contLine.startsWith("/")) {
+ throw new IOException("In " + StringUtil.jQuote(contResource) + ", this line must start with "
+ + "\"/\" as it uses the " + StringUtil.jQuote(ARROW) + " operator : "
+ + contLine);
+ }
+ contSrcPath = contLine.substring(0, arrowIdx).trim();
+ contDstPath = contLine.substring(arrowIdx + ARROW.length()).trim();
+ contSrcPathRelative = false;
+ } else {
+ if (contLine.startsWith("/")) {
+ throw new IOException("In " + StringUtil.jQuote(contResource)
+ + ", this line can't start with \"/\": " + contLine);
+ }
+ contSrcPathRelative = true;
+ contSrcPath = contLine;
+ contDstPath = contLine;
+ }
+ File dstFile = new File(dstRootDir, contDstPath);
+ if (contLine.endsWith("/")) {
+ if (!dstFile.mkdirs()) {
+ throw new IOException("Failed to create directory: " + dstFile);
+ }
+ } else {
+ String srcEntryPath = contSrcPathRelative ? srcDirResourcePath + contSrcPath : contSrcPath;
+ InputStream entryIn = resolverClass.getResourceAsStream(srcEntryPath);
+ if (entryIn == null) {
+ throw new IOException("Can't find resource: class=" + resolverClass + ", path=" + srcEntryPath);
+ }
+ try {
+ if (dstFile.exists()) {
+ throw new IOException(
+ "Destination already exists; check if " + StringUtil.jQuote(contDstPath)
+ + " occurs for multiple times in \"" + CONTENTS_TXT + "\".");
+ }
+ FileUtils.copyInputStreamToFile(entryIn, dstFile);
+ } catch (IOException e) {
+ File parent = dstFile;
+ while ((parent = dstFile.getParentFile()) != null) {
+ if (parent.isFile()) {
+ throw new IOException("An ancestor directory of " + StringUtil.jQuote(dstFile) + ", "
+ + StringUtil.jQuote(parent) + " already exists, but as a file, not as a directory. "
+ + "Check if you have accidentally added the directory itself to \"" + CONTENTS_TXT
+ + "\". Only files should be listed there.");
+ }
+ }
+ throw e;
+ } finally {
+ entryIn.close();
+ }
+ }
+ }
+
+ /**
+ * @param extension
+ * The file extension of the resulting jar archive, or {@code null} if the archive name will be the same
+ * as the directory name.
+ */
+ private static File replaceDirectoryWithJar(File srcDir, String extension) throws IOException {
+ String workJarFileName;
+ String finalJarFileName;
+ if (extension == null) {
+ finalJarFileName = srcDir.getName();
+ workJarFileName = finalJarFileName + DOT_TMP;
+ } else {
+ finalJarFileName = srcDir.getName() + "." + extension;
+ workJarFileName = finalJarFileName;
+ }
+
+ File workJarFile = new File(srcDir.getParentFile(), workJarFileName);
+ jarDirectory(srcDir, workJarFile);
+
+ if (srcDir.getParentFile() == null) {
+ throw new IOException("Won't delete the root directory");
+ }
+ FileUtils.deleteDirectory(srcDir);
+
+ File finalJarFile;
+ if (!workJarFileName.equals(finalJarFileName)) {
+ finalJarFile = new File(workJarFile.getParentFile(), finalJarFileName);
+ FileUtils.moveFile(workJarFile, finalJarFile);
+ } else {
+ finalJarFile = workJarFile;
+ }
+
+ return finalJarFile;
+ }
+
+ private static void jarDirectory(File srcDir, File jarFile) throws FileNotFoundException, IOException {
+ boolean finished = false;
+ try {
+ FileOutputStream fileOut = new FileOutputStream(jarFile);
+ try {
+ JarOutputStream jarOut = new JarOutputStream(fileOut);
+ try {
+ addFilesToJar("", srcDir, jarOut);
+ } finally {
+ jarOut.close();
+ }
+ } finally {
+ fileOut.close();
+ }
+ finished = true;
+ } finally {
+ if (!finished) {
+ if (!jarFile.delete()) {
+ LOG.error("Failed to delete file: {}", jarFile);
+ }
+ }
+ }
+ }
+
+ private static void jarMarkedSubdirectories(File dir) throws IOException {
+ File[] entries = dir.listFiles();
+ if (entries == null) {
+ throw new IOException("Failed to list directory: " + dir);
+ }
+ for (File entry : entries) {
+ if (entry.isDirectory()) {
+ jarMarkedSubdirectories(entry);
+ if (entry.getName().endsWith(SUFFIX_JAR)) {
+ replaceDirectoryWithJar(entry, null);
+ }
+ }
+ }
+ }
+
+ private static void addFilesToJar(String entryBasePath, File dir, JarOutputStream jarOut) throws IOException {
+ File[] entries = dir.listFiles();
+ if (entries == null) {
+ throw new IOException("Couldn't list directory: " + dir);
+ }
+ for (File entry : entries) {
+ if (entry.isFile()) {
+ jarOut.putNextEntry(new ZipEntry(entryBasePath + entry.getName()));
+ FileInputStream fileIn = new FileInputStream(entry);
+ try {
+ IOUtils.copy(fileIn, jarOut);
+ } finally {
+ fileIn.close();
+ }
+ jarOut.closeEntry();
+ } else if (entry.isDirectory()) {
+ String dirPath = entryBasePath + entry.getName() + "/";
+ jarOut.putNextEntry(new ZipEntry(dirPath));
+ jarOut.closeEntry();
+ addFilesToJar(dirPath, entry, jarOut);
+ } else {
+ throw new IOException("Couldn't open source entry: " + entry);
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/java/freemarker/test/servlet/WebAppTestCase.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/test/servlet/WebAppTestCase.java b/src/test/java/freemarker/test/servlet/WebAppTestCase.java
index 223c696..6bd7f44 100644
--- a/src/test/java/freemarker/test/servlet/WebAppTestCase.java
+++ b/src/test/java/freemarker/test/servlet/WebAppTestCase.java
@@ -21,17 +21,18 @@ package freemarker.test.servlet;
import static org.junit.Assert.*;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URI;
-import java.net.URISyntaxException;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
+import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
@@ -42,10 +43,11 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import freemarker.test.ResourcesExtractor;
import freemarker.test.TestUtil;
public class WebAppTestCase {
-
+
public static final String IGNORED_MASK = "[IGNORED]";
private static final Logger LOG = LoggerFactory.getLogger(WebAppTestCase.class);
@@ -53,32 +55,35 @@ public class WebAppTestCase {
private static final String ATTR_JETTY_CONTAINER_INCLUDE_JAR_PATTERN
= "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern";
- private static final String EXPECTED_DIR = "/WEB-INF/expected/";
+ private static final String EXPECTED_DIR = "WEB-INF/expected/";
private static Server server;
private static ContextHandlerCollection contextHandlers;
- private static Map<String, WebAppContext> deployedWebApps = new HashMap<String, WebAppContext>();
-
+ private static Map<String, WebAppContext> deployedWebApps = new HashMap<String, WebAppContext>();
+ private static volatile File testTempDirectory;
+
@BeforeClass
public static void beforeClass() throws Exception {
// Work around Java 5 bug(?) that causes Jasper to fail with "zip file closed" when it reads the JSTL jar:
org.eclipse.jetty.util.resource.Resource.setDefaultUseCaches(false);
-
+
LOG.info("Starting embedded Jetty...");
-
+
server = new Server(0);
-
+
contextHandlers = new ContextHandlerCollection();
server.setHandler(contextHandlers);
-
+
server.start();
}
-
+
@AfterClass
public static void afterClass() throws Exception {
LOG.info("Stopping embedded Jetty...");
server.stop();
- server.join(); // TODO redundant?
+ server.join();
+ LOG.info("Jetty stopped.");
+ deleteTemporaryDirectories();
}
protected final String getResponseContent(String webAppName, String webAppRelURL) throws Exception {
@@ -95,7 +100,7 @@ public class WebAppTestCase {
HTTPResponse resp = getHTTPResponse(webAppName, webAppRelURL);
return resp.getStatusCode();
}
-
+
protected final HTTPResponse getHTTPResponse(String webAppName, String webAppRelURL) throws Exception {
if (webAppName.startsWith("/") || webAppName.endsWith("/")) {
throw new IllegalArgumentException("\"webAppName\" can't start or end with \"/\": " + webAppName);
@@ -103,9 +108,9 @@ public class WebAppTestCase {
if (webAppRelURL.startsWith("/") || webAppRelURL.endsWith("/")) {
throw new IllegalArgumentException("\"webappRelURL\" can't start or end with \"/\": " + webAppRelURL);
}
-
+
ensureWebAppIsDeployed(webAppName);
-
+
final URI uri = new URI("http://localhost:" + server.getConnectors()[0].getLocalPort()
+ "/" + webAppName + "/" + webAppRelURL);
@@ -115,7 +120,7 @@ public class WebAppTestCase {
LOG.debug("HTTP GET: {}", uri);
final int responseCode = httpCon.getResponseCode();
-
+
final String content;
if (responseCode == 200) {
InputStream in = httpCon.getInputStream();
@@ -127,7 +132,7 @@ public class WebAppTestCase {
} else {
content = null;
}
-
+
return new HTTPResponse(
responseCode, httpCon.getResponseMessage(),
content,
@@ -136,12 +141,13 @@ public class WebAppTestCase {
httpCon.disconnect();
}
}
-
+
/**
* Compares the output of the JSP and the FTL version of the same page, ignoring some of the whitespace differences.
- * @param webAppRelURLWithoutExt something like {@code "tester?view=foo"}, which will be extended to
- * {@code "tester?view=foo.jsp"} and {@code "tester?view=foo.ftl"}, and then the output of these extended
- * URL-s will be compared.
+ *
+ * @param webAppRelURLWithoutExt
+ * something like {@code "tester?view=foo"}, which will be extended to {@code "tester?view=foo.jsp"} and
+ * {@code "tester?view=foo.ftl"}, and then the output of these extended URL-s will be compared.
*/
protected void assertJSPAndFTLOutputEquals(String webAppName, String webAppRelURLWithoutExt) throws Exception {
assertOutputsEqual(webAppName, webAppRelURLWithoutExt + ".jsp", webAppRelURLWithoutExt + ".ftl");
@@ -163,7 +169,7 @@ public class WebAppTestCase {
boolean compressWS) throws Exception {
assertExpectedEqualsOutput(webAppName, expectedFileName, webAppRelURL, compressWS, null);
}
-
+
/**
* @param expectedFileName
* The name of the file that stores the expected content, relatively to
@@ -177,7 +183,9 @@ public class WebAppTestCase {
final String actual = normalizeWS(getResponseContent(webAppName, webAppRelURL), compressWS);
final String expected;
{
- final InputStream in = new URL(getWebAppDirURL(webAppName) + EXPECTED_DIR + expectedFileName).openStream();
+ ClassPathResource cpResource = findWebAppDirectoryResource(webAppName);
+ final InputStream in = cpResource.resolverClass.getResourceAsStream(
+ cpResource.path + EXPECTED_DIR + expectedFileName);
try {
expected = TestUtil.removeTxtCopyrightComment(normalizeWS(IOUtils.toString(in, "utf-8"), compressWS));
} finally {
@@ -186,10 +194,10 @@ public class WebAppTestCase {
}
assertEquals(maskIgnored(expected, ignoredParts), maskIgnored(actual, ignoredParts));
}
-
+
private String maskIgnored(String s, List<Pattern> ignoredParts) {
if (ignoredParts == null) return s;
-
+
for (Pattern ignoredPart : ignoredParts) {
s = ignoredPart.matcher(s).replaceAll(IGNORED_MASK);
}
@@ -203,11 +211,11 @@ public class WebAppTestCase {
context.start();
}
}
-
- private Pattern BR = Pattern.compile("\r\n|\r");
- private Pattern MULTI_LINE_WS = Pattern.compile("[\t ]*[\r\n][\t \r\n]*", Pattern.DOTALL);
- private Pattern SAME_LINE_WS = Pattern.compile("[\t ]+", Pattern.DOTALL);
-
+
+ private Pattern BR = Pattern.compile("\r\n|\r");
+ private Pattern MULTI_LINE_WS = Pattern.compile("[\t ]*[\r\n][\t \r\n]*", Pattern.DOTALL);
+ private Pattern SAME_LINE_WS = Pattern.compile("[\t ]+", Pattern.DOTALL);
+
private String normalizeWS(String s, boolean compressWS) {
if (compressWS) {
return SAME_LINE_WS.matcher(
@@ -223,65 +231,106 @@ public class WebAppTestCase {
if (deployedWebApps.containsKey(webAppName)) {
return;
}
-
- final String webAppDirURL = getWebAppDirURL(webAppName);
-
+
+ final String webAppDirURL = createWebAppDirAndGetURI(webAppName);
+
WebAppContext context = new WebAppContext(webAppDirURL, "/" + webAppName);
-
+
// Pattern of jar file names scanned for META-INF/*.tld:
context.setAttribute(
ATTR_JETTY_CONTAINER_INCLUDE_JAR_PATTERN,
".*taglib.*\\.jar$");
-
contextHandlers.addHandler(context);
// As we add this after the Server was started, it has to be started manually:
context.start();
-
+
deployedWebApps.put(webAppName, context);
LOG.info("Deployed web app.: {}", webAppName);
}
- @SuppressFBWarnings(value="UI_INHERITANCE_UNSAFE_GETRESOURCE", justification="By design relative to subclass")
- private String getWebAppDirURL(String webAppName) throws IOException {
- final URL webXmlURL;
- {
- final String relResPath = "webapps/" + webAppName + "/WEB-INF/web.xml";
-
- Class<?> baseClass = this.getClass();
- findWebXmlURL: do {
- URL r = baseClass.getResource(relResPath);
- if (r != null) {
- webXmlURL = r;
- break findWebXmlURL;
- }
-
- baseClass = baseClass.getSuperclass();
- if (!WebAppTestCase.class.isAssignableFrom(baseClass)) {
- throw new IOException("Can't find test class relative resource: " + relResPath);
- }
- } while (true);
+ private static void deleteTemporaryDirectories() throws IOException {
+ if (testTempDirectory.getParentFile() == null) {
+ throw new IOException("Won't delete the root directory");
}
-
try {
- return webXmlURL.toURI().resolve("..").toString();
- } catch (URISyntaxException e) {
- throw new RuntimeException("Failed to get grandparent URL for " + webXmlURL, e);
+ FileUtils.forceDelete(testTempDirectory);
+ } catch (IOException e) {
+ LOG.warn("Failed to delete temporary file or directory; will re-try on JVM shutdown: "
+ + testTempDirectory);
+ FileUtils.forceDeleteOnExit(testTempDirectory);
}
}
+
+ @SuppressFBWarnings(value = "UI_INHERITANCE_UNSAFE_GETRESOURCE", justification = "By design relative to subclass")
+ private String createWebAppDirAndGetURI(String webAppName) throws IOException {
+ ClassPathResource resourceDir = findWebAppDirectoryResource(webAppName);
+ File temporaryDir = ResourcesExtractor.extract(
+ resourceDir.resolverClass, resourceDir.path, new File(getTestTempDirectory(), webAppName));
+ return temporaryDir.toURI().toString();
+ }
+
+ private ClassPathResource findWebAppDirectoryResource(String webAppName) throws IOException {
+ final String appRelResPath = "webapps/" + webAppName + "/";
+ final String relResPath = appRelResPath + "WEB-INF/web.xml";
+
+ Class<?> baseClass = this.getClass();
+ do {
+ URL r = baseClass.getResource(relResPath);
+ if (r != null) {
+ return new ClassPathResource(baseClass, appRelResPath);
+ }
+
+ baseClass = baseClass.getSuperclass();
+ if (!WebAppTestCase.class.isAssignableFrom(baseClass)) {
+ throw new IOException("Can't find test class relative resource: " + relResPath);
+ }
+ } while (true);
+ }
+ private File getTestTempDirectory() throws IOException {
+ if (testTempDirectory == null) {
+ // As at least on Windows we have problem deleting the directories once Jetty has used them (the file
+ // handles of the jars remain open), we always use the same name, so that at most one will remain there.
+ File d = new File(
+ new File(System.getProperty("java.io.tmpdir")),
+ "freemarker-jetty-junit-tests-(delete-it)");
+ if (d.exists()) {
+ FileUtils.deleteDirectory(d);
+ }
+ if (!d.mkdirs()) {
+ throw new IOException("Failed to create Jetty temp directory: " + d);
+ }
+ testTempDirectory = d;
+ }
+ return testTempDirectory;
+ }
+
+ private static class ClassPathResource {
+
+ private final Class<?> resolverClass;
+ private final String path;
+
+ public ClassPathResource(Class<?> resolverClass, String path) {
+ this.resolverClass = resolverClass;
+ this.path = path;
+ }
+
+ }
+
private static class HTTPResponse {
+
private final int statusCode;
private final String content;
private final String statusMessage;
private final URI uri;
-
+
public HTTPResponse(int statusCode, String statusMessage, String content, URI uri) {
this.statusCode = statusCode;
this.content = content;
this.statusMessage = statusMessage;
this.uri = uri;
}
-
+
public String getStatusMessage() {
return statusMessage;
}
@@ -289,7 +338,7 @@ public class WebAppTestCase {
public int getStatusCode() {
return statusCode;
}
-
+
public String getContent() {
return content;
}
@@ -297,7 +346,7 @@ public class WebAppTestCase {
public URI getURI() {
return uri;
}
-
+
}
-
+
}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/basic/CONTENTS.txt
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/basic/CONTENTS.txt b/src/test/resources/freemarker/ext/jsp/webapps/basic/CONTENTS.txt
new file mode 100644
index 0000000..c3f6857
--- /dev/null
+++ b/src/test/resources/freemarker/ext/jsp/webapps/basic/CONTENTS.txt
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+// Only the files listed here will be part of the tested Web application deployment!
+
+attributes.ftl
+customELFunctions1.ftl
+customELFunctions1.jsp
+customTags1.ftl
+trivial-jstl-@Ignore.ftl
+trivial.ftl
+trivial.jsp
+
+WEB-INF/el-functions.tld
+WEB-INF/expected
+WEB-INF/test.tld
+WEB-INF/web.xml
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/config/CONTENTS.txt
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/config/CONTENTS.txt b/src/test/resources/freemarker/ext/jsp/webapps/config/CONTENTS.txt
new file mode 100644
index 0000000..3157059
--- /dev/null
+++ b/src/test/resources/freemarker/ext/jsp/webapps/config/CONTENTS.txt
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+// Only the files listed here will be part of the tested Web application deployment!
+
+test.ftl
+
+WEB-INF/web.xml
+
+WEB-INF/classes/test.ftl
+
+WEB-INF/classes/sub/test.ftl
+
+WEB-INF/lib/templates.jar/sub/test2.ftl
+/freemarker/ext/jsp/webapps/config/WebappLocalFreemarkerServlet.class -> WEB-INF/lib/WebappLocalFreemarkerServlet.jar/freemarker/ext/jsp/webapps/config/WebappLocalFreemarkerServlet.class
+
+WEB-INF/templates/test.ftl
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/WebappLocalFreemarkerServlet.jar
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/WebappLocalFreemarkerServlet.jar b/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/WebappLocalFreemarkerServlet.jar
deleted file mode 100644
index 5af54da..0000000
Binary files a/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/WebappLocalFreemarkerServlet.jar and /dev/null differ
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/templates.jar
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/templates.jar b/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/templates.jar
deleted file mode 100644
index 8e5f2e5..0000000
Binary files a/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/templates.jar and /dev/null differ
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/templates.jar/sub/test2.ftl b/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/templates.jar/sub/test2.ftl
new file mode 100644
index 0000000..71b1d86
--- /dev/null
+++ b/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/templates.jar/sub/test2.ftl
@@ -0,0 +1,19 @@
+<#--
+ 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.
+-->
+from WEB-INF/lib/templates.jar/sub
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/templates.jar/sub/test2.ftl
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/templates.jar/sub/test2.ftl b/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/templates.jar/sub/test2.ftl
new file mode 100644
index 0000000..71b1d86
--- /dev/null
+++ b/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/templates.jar/sub/test2.ftl
@@ -0,0 +1,19 @@
+<#--
+ 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.
+-->
+from WEB-INF/lib/templates.jar/sub
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/web.xml b/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/web.xml
index a8328b4..8818368 100644
--- a/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/web.xml
+++ b/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/web.xml
@@ -35,7 +35,7 @@
<!-- Must use a webapp-local class for "class:", otherwise it won't find local resources. -->
<servlet>
<servlet-name>freemarker-class-root</servlet-name>
- <servlet-class>webapps.cfg.WebappLocalFreemarkerServlet</servlet-class>
+ <servlet-class>freemarker.ext.jsp.webapps.config.WebappLocalFreemarkerServlet</servlet-class>
<init-param>
<param-name>TemplatePath</param-name>
<param-value>class://</param-value>
@@ -43,7 +43,7 @@
</servlet>
<servlet>
<servlet-name>freemarker-class-sub</servlet-name>
- <servlet-class>webapps.cfg.WebappLocalFreemarkerServlet</servlet-class>
+ <servlet-class>freemarker.ext.jsp.webapps.config.WebappLocalFreemarkerServlet</servlet-class>
<init-param>
<param-name>TemplatePath</param-name>
<param-value>class://sub</param-value>
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/errors/CONTENTS.txt
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/errors/CONTENTS.txt b/src/test/resources/freemarker/ext/jsp/webapps/errors/CONTENTS.txt
new file mode 100644
index 0000000..62d711e
--- /dev/null
+++ b/src/test/resources/freemarker/ext/jsp/webapps/errors/CONTENTS.txt
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+// Only the files listed here will be part of the tested Web application deployment!
+
+failing-parsetime.ftlnv
+failing-parsetime.jsp
+failing-runtime.ftl
+failing-runtime.jsp
+not-failing.ftl
+
+WEB-INF/web.xml
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/multipleLoaders/CONTENTS.txt
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/multipleLoaders/CONTENTS.txt b/src/test/resources/freemarker/ext/jsp/webapps/multipleLoaders/CONTENTS.txt
new file mode 100644
index 0000000..5453db8
--- /dev/null
+++ b/src/test/resources/freemarker/ext/jsp/webapps/multipleLoaders/CONTENTS.txt
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// Only the files listed here will be part of the tested Web application deployment!
+
+WEB-INF/web.xml
+
+WEB-INF/templates/test.ftl
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/CONTENTS.txt
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/CONTENTS.txt b/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/CONTENTS.txt
new file mode 100644
index 0000000..d38119e
--- /dev/null
+++ b/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/CONTENTS.txt
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+// Only the files listed here will be part of the tested Web application deployment!
+
+test-noClasspath.ftl
+test1.ftl
+
+WEB-INF/fmtesttag 2.tld
+WEB-INF/fmtesttag4.tld
+WEB-INF/web.xml
+
+WEB-INF/taglib 2.jar/META-INF/taglib.tld
+
+WEB-INF/lib/taglib-foo.jar/META-INF/foo bar.tld
+
+WEB-INF/subdir-with-tld/fmtesttag3.tld
+
+not-auto-scanned/fmtesttag.tld
+
+subdir/test-rel.ftl
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/lib/taglib-foo.jar
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/lib/taglib-foo.jar b/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/lib/taglib-foo.jar
deleted file mode 100644
index aa6c542..0000000
Binary files a/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/lib/taglib-foo.jar and /dev/null differ
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/lib/taglib-foo.jar/META-INF/foo bar.tld b/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/lib/taglib-foo.jar/META-INF/foo bar.tld
new file mode 100644
index 0000000..3f2e096
--- /dev/null
+++ b/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/lib/taglib-foo.jar/META-INF/foo bar.tld
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!--
+ 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.
+-->
+<!DOCTYPE taglib
+ PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
+ "http://java.sun.com/j2ee/dtds/web-jsptaglib_1_1.dtd">
+<taglib>
+ <tlibversion>2.0</tlibversion>
+ <jspversion>1.2</jspversion>
+ <shortname>FreeMarker JUnit Test Support 3</shortname>
+ <uri>http://freemarker.sf.net/taglibs/freemarker-junit-test-tag-2.2-foo</uri>
+ <tag>
+ <name>testtag</name>
+ <tagclass>freemarker.ext.jsp.taglibmembers.TestTag3</tagclass>
+ </tag>
+</taglib>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/lib/taglib-foo.jar/META-INF/foo bar.tld
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/lib/taglib-foo.jar/META-INF/foo bar.tld b/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/lib/taglib-foo.jar/META-INF/foo bar.tld
new file mode 100644
index 0000000..3f2e096
--- /dev/null
+++ b/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/lib/taglib-foo.jar/META-INF/foo bar.tld
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!--
+ 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.
+-->
+<!DOCTYPE taglib
+ PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
+ "http://java.sun.com/j2ee/dtds/web-jsptaglib_1_1.dtd">
+<taglib>
+ <tlibversion>2.0</tlibversion>
+ <jspversion>1.2</jspversion>
+ <shortname>FreeMarker JUnit Test Support 3</shortname>
+ <uri>http://freemarker.sf.net/taglibs/freemarker-junit-test-tag-2.2-foo</uri>
+ <tag>
+ <name>testtag</name>
+ <tagclass>freemarker.ext.jsp.taglibmembers.TestTag3</tagclass>
+ </tag>
+</taglib>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/taglib 2.jar
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/taglib 2.jar b/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/taglib 2.jar
deleted file mode 100644
index a915da1..0000000
Binary files a/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/taglib 2.jar and /dev/null differ
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/taglib 2.jar/META-INF/taglib.tld b/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/taglib 2.jar/META-INF/taglib.tld
new file mode 100644
index 0000000..ce5d873
--- /dev/null
+++ b/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/taglib 2.jar/META-INF/taglib.tld
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!--
+ 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.
+-->
+<!DOCTYPE taglib
+ PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
+ "http://java.sun.com/j2ee/dtds/web-jsptaglib_1_1.dtd">
+<taglib>
+ <tlibversion>2.0</tlibversion>
+ <jspversion>1.2</jspversion>
+ <shortname>FreeMarker JUnit Test Support 2</shortname>
+ <tag>
+ <name>testtag</name>
+ <tagclass>freemarker.ext.jsp.taglibmembers.TestTag2</tagclass>
+ </tag>
+</taglib>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/taglib 2.jar/META-INF/taglib.tld
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/taglib 2.jar/META-INF/taglib.tld b/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/taglib 2.jar/META-INF/taglib.tld
new file mode 100644
index 0000000..ce5d873
--- /dev/null
+++ b/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/taglib 2.jar/META-INF/taglib.tld
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!--
+ 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.
+-->
+<!DOCTYPE taglib
+ PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
+ "http://java.sun.com/j2ee/dtds/web-jsptaglib_1_1.dtd">
+<taglib>
+ <tlibversion>2.0</tlibversion>
+ <jspversion>1.2</jspversion>
+ <shortname>FreeMarker JUnit Test Support 2</shortname>
+ <tag>
+ <name>testtag</name>
+ <tagclass>freemarker.ext.jsp.taglibmembers.TestTag2</tagclass>
+ </tag>
+</taglib>
\ No newline at end of file