Switch to Ant lib for tar/zip tasks

The commons wrapper we were using didn't support executable files
so Ant seems like the best choice ultimately, even if it has a
lot of features we don't use or need.
This commit is contained in:
Dave Syer
2017-02-20 11:20:09 +00:00
committed by Stephane Nicoll
parent 09fc98ef96
commit 06f314dc8c
11 changed files with 131 additions and 58 deletions

View File

@@ -52,11 +52,6 @@
<type>test-jar</type> <type>test-jar</type>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.rauschig</groupId>
<artifactId>jarchivelib</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>io.spring.initializr</groupId> <groupId>io.spring.initializr</groupId>
<artifactId>initializr-web</artifactId> <artifactId>initializr-web</artifactId>

0
initializr-generator/src/main/resources/project/gradle/gradlew.bat vendored Normal file → Executable file
View File

0
initializr-generator/src/main/resources/project/gradle3/gradlew.bat vendored Normal file → Executable file
View File

0
initializr-generator/src/main/resources/project/maven/mvnw vendored Normal file → Executable file
View File

0
initializr-generator/src/main/resources/project/maven/mvnw.cmd vendored Normal file → Executable file
View File

View File

@@ -217,6 +217,13 @@ public class ProjectAssert {
return this; return this;
} }
public ProjectAssert hasExecutableFile(String... localPaths) {
for (String localPath : localPaths) {
assertFile(localPath, true);
}
return this;
}
public ProjectAssert hasNoFile(String... localPaths) { public ProjectAssert hasNoFile(String... localPaths) {
for (String localPath : localPaths) { for (String localPath : localPaths) {
assertFile(localPath, false); assertFile(localPath, false);
@@ -231,6 +238,13 @@ public class ProjectAssert {
return this; return this;
} }
public ProjectAssert assertExecutableFile(String localPath, boolean executable) {
File candidate = file(localPath);
assertEquals("Invalid (\"" + executable + "\") for " + localPath, executable,
candidate.exists() && candidate.canExecute());
return this;
}
private File file(String localPath) { private File file(String localPath) {
return new File(dir, localPath); return new File(dir, localPath);
} }

View File

@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>io.spring.initializr</groupId> <groupId>io.spring.initializr</groupId>
@@ -38,8 +37,14 @@
<artifactId>caffeine</artifactId> <artifactId>caffeine</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.rauschig</groupId> <groupId>org.apache.ant</groupId>
<artifactId>jarchivelib</artifactId> <artifactId>ant</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.ant</groupId>
<artifactId>ant-launcher</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.json</groupId> <groupId>org.json</groupId>

View File

@@ -16,6 +16,10 @@
package io.spring.initializr.web.project; package io.spring.initializr.web.project;
import static io.spring.initializr.util.Agent.AgentId.CURL;
import static io.spring.initializr.util.Agent.AgentId.HTTPIE;
import static io.spring.initializr.util.Agent.AgentId.SPRING_BOOT_CLI;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
@@ -25,7 +29,31 @@ import java.nio.charset.StandardCharsets;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Tar;
import org.apache.tools.ant.taskdefs.Tar.TarCompressionMethod;
import org.apache.tools.ant.taskdefs.Tar.TarFileSet;
import org.apache.tools.ant.taskdefs.Zip;
import org.apache.tools.ant.types.ZipFileSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.CacheControl;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.ResponseEntity.BodyBuilder;
import org.springframework.stereotype.Controller;
import org.springframework.util.DigestUtils;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.resource.ResourceUrlProvider;
import com.samskivert.mustache.Mustache; import com.samskivert.mustache.Mustache;
import io.spring.initializr.generator.BasicProjectRequest; import io.spring.initializr.generator.BasicProjectRequest;
import io.spring.initializr.generator.CommandLineHelpGenerator; import io.spring.initializr.generator.CommandLineHelpGenerator;
import io.spring.initializr.generator.ProjectGenerator; import io.spring.initializr.generator.ProjectGenerator;
@@ -42,28 +70,6 @@ import io.spring.initializr.web.mapper.InitializrMetadataJsonMapper;
import io.spring.initializr.web.mapper.InitializrMetadataV21JsonMapper; import io.spring.initializr.web.mapper.InitializrMetadataV21JsonMapper;
import io.spring.initializr.web.mapper.InitializrMetadataV2JsonMapper; import io.spring.initializr.web.mapper.InitializrMetadataV2JsonMapper;
import io.spring.initializr.web.mapper.InitializrMetadataVersion; import io.spring.initializr.web.mapper.InitializrMetadataVersion;
import org.rauschig.jarchivelib.ArchiverFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.CacheControl;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.ResponseEntity.BodyBuilder;
import org.springframework.stereotype.Controller;
import org.springframework.util.DigestUtils;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.resource.ResourceUrlProvider;
import static io.spring.initializr.util.Agent.AgentId.CURL;
import static io.spring.initializr.util.Agent.AgentId.HTTPIE;
import static io.spring.initializr.util.Agent.AgentId.SPRING_BOOT_CLI;
/** /**
* The main initializr controller provides access to the configured metadata and serves as * The main initializr controller provides access to the configured metadata and serves as
@@ -257,10 +263,24 @@ public class MainController extends AbstractInitializrController {
File download = projectGenerator.createDistributionFile(dir, ".zip"); File download = projectGenerator.createDistributionFile(dir, ".zip");
String wrapperScript = getWrapperScript(request); String wrapperScript = getWrapperScript(request);
// TODO: file mode 755 for wrapper script? new File(dir, wrapperScript).setExecutable(true);
Zip zip = new Zip();
ArchiverFactory.createArchiver("zip").create(download.getName(), zip.setProject(new Project());
download.getCanonicalFile().getParentFile(), dir); zip.setDefaultexcludes(false);
ZipFileSet set = new ZipFileSet();
set.setDir(dir);
set.setFileMode("755");
set.setIncludes(wrapperScript);
set.setDefaultexcludes(false);
zip.addFileset(set);
set = new ZipFileSet();
set.setDir(dir);
set.setIncludes("**,");
set.setExcludes(wrapperScript);
set.setDefaultexcludes(false);
zip.addFileset(set);
zip.setDestFile(download.getCanonicalFile());
zip.execute();
return upload(download, dir, generateFileName(request, "zip"), "application/zip"); return upload(download, dir, generateFileName(request, "zip"), "application/zip");
} }
@@ -274,10 +294,25 @@ public class MainController extends AbstractInitializrController {
File download = projectGenerator.createDistributionFile(dir, ".tar.gz"); File download = projectGenerator.createDistributionFile(dir, ".tar.gz");
String wrapperScript = getWrapperScript(request); String wrapperScript = getWrapperScript(request);
// TODO: file mode 755 for wrapper script? new File(dir, wrapperScript).setExecutable(true);
Tar zip = new Tar();
ArchiverFactory.createArchiver("tar", "gz").create(download.getName(), zip.setProject(new Project());
download.getCanonicalFile().getParentFile(), dir); zip.setDefaultexcludes(false);
TarFileSet set = zip.createTarFileSet();
set.setDir(dir);
set.setFileMode("755");
set.setIncludes(wrapperScript);
set.setDefaultexcludes(false);
set = zip.createTarFileSet();
set.setDir(dir);
set.setIncludes("**,");
set.setExcludes(wrapperScript);
set.setDefaultexcludes(false);
zip.setDestFile(download.getCanonicalFile());
TarCompressionMethod method = new TarCompressionMethod();
method.setValue("gzip");
zip.setCompression(method );
zip.execute();
return upload(download, dir, generateFileName(request, "tar.gz"), return upload(download, dir, generateFileName(request, "tar.gz"),
"application/x-compress"); "application/x-compress");
} }

View File

@@ -16,6 +16,8 @@
package io.spring.initializr.web; package io.spring.initializr.web;
import static org.junit.Assert.assertTrue;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
@@ -25,23 +27,17 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import io.spring.initializr.metadata.InitializrMetadata; import org.apache.tools.ant.Project;
import io.spring.initializr.metadata.InitializrMetadataBuilder; import org.apache.tools.ant.taskdefs.Expand;
import io.spring.initializr.metadata.InitializrMetadataProvider; import org.apache.tools.ant.taskdefs.Untar;
import io.spring.initializr.metadata.InitializrProperties; import org.apache.tools.ant.taskdefs.Untar.UntarCompressionMethod;
import io.spring.initializr.test.generator.ProjectAssert;
import io.spring.initializr.web.AbstractInitializrIntegrationTests.Config;
import io.spring.initializr.web.mapper.InitializrMetadataVersion;
import io.spring.initializr.web.support.DefaultInitializrMetadataProvider;
import org.json.JSONObject; import org.json.JSONObject;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.rules.TemporaryFolder; import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.rauschig.jarchivelib.ArchiverFactory;
import org.skyscreamer.jsonassert.JSONAssert; import org.skyscreamer.jsonassert.JSONAssert;
import org.skyscreamer.jsonassert.JSONCompareMode; import org.skyscreamer.jsonassert.JSONCompareMode;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
@@ -57,7 +53,14 @@ import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.StreamUtils; import org.springframework.util.StreamUtils;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import static org.junit.Assert.assertTrue; import io.spring.initializr.metadata.InitializrMetadata;
import io.spring.initializr.metadata.InitializrMetadataBuilder;
import io.spring.initializr.metadata.InitializrMetadataProvider;
import io.spring.initializr.metadata.InitializrProperties;
import io.spring.initializr.test.generator.ProjectAssert;
import io.spring.initializr.web.AbstractInitializrIntegrationTests.Config;
import io.spring.initializr.web.mapper.InitializrMetadataVersion;
import io.spring.initializr.web.support.DefaultInitializrMetadataProvider;
/** /**
* @author Stephane Nicoll * @author Stephane Nicoll
@@ -183,10 +186,10 @@ public abstract class AbstractInitializrIntegrationTests {
File project = folder.newFolder(); File project = folder.newFolder();
switch (archiveType) { switch (archiveType) {
case ZIP: case ZIP:
ArchiverFactory.createArchiver("zip").extract(archiveFile, project); unzip(archiveFile, project);
break; break;
case TGZ: case TGZ:
ArchiverFactory.createArchiver("tar", "gz").extract(archiveFile, project); untar(archiveFile, project);
break; break;
} }
return new ProjectAssert(project); return new ProjectAssert(project);
@@ -196,6 +199,25 @@ public abstract class AbstractInitializrIntegrationTests {
} }
} }
private void untar(File archiveFile, File project) {
Untar expand = new Untar();
expand.setProject(new Project());
expand.setDest(project);
expand.setSrc(archiveFile);
UntarCompressionMethod method = new UntarCompressionMethod();
method.setValue("gzip");
expand.setCompression(method );
expand.execute();
}
private void unzip(File archiveFile, File project) {
Expand expand = new Expand();
expand.setProject(new Project());
expand.setDest(project);
expand.setSrc(archiveFile);
expand.execute();
}
protected File writeArchive(byte[] body) throws IOException { protected File writeArchive(byte[] body) throws IOException {
File archiveFile = folder.newFile(); File archiveFile = folder.newFile();
try (FileOutputStream stream = new FileOutputStream(archiveFile)) { try (FileOutputStream stream = new FileOutputStream(archiveFile)) {

View File

@@ -55,7 +55,8 @@ public class MainControllerIntegrationTests
@Test @Test
public void simpleZipProject() { public void simpleZipProject() {
downloadZip("/starter.zip?style=web&style=jpa").isJavaProject() downloadZip("/starter.zip?style=web&style=jpa").isJavaProject()
.hasFile(".gitignore").isMavenProject() .hasFile(".gitignore")
.hasExecutableFile("mvnw").isMavenProject()
.hasStaticAndTemplatesResources(true).pomAssert().hasDependenciesCount(3) .hasStaticAndTemplatesResources(true).pomAssert().hasDependenciesCount(3)
.hasSpringBootStarterDependency("web") .hasSpringBootStarterDependency("web")
.hasSpringBootStarterDependency("data-jpa") // alias jpa -> data-jpa .hasSpringBootStarterDependency("data-jpa") // alias jpa -> data-jpa
@@ -65,7 +66,8 @@ public class MainControllerIntegrationTests
@Test @Test
public void simpleTgzProject() { public void simpleTgzProject() {
downloadTgz("/starter.tgz?style=org.acme:foo").isJavaProject() downloadTgz("/starter.tgz?style=org.acme:foo").isJavaProject()
.hasFile(".gitignore").isMavenProject() .hasFile(".gitignore")
.hasExecutableFile("mvnw").isMavenProject()
.hasStaticAndTemplatesResources(false).pomAssert().hasDependenciesCount(2) .hasStaticAndTemplatesResources(false).pomAssert().hasDependenciesCount(2)
.hasDependency("org.acme", "foo", "1.3.5"); .hasDependency("org.acme", "foo", "1.3.5");
} }

View File

@@ -98,9 +98,9 @@
<version>1.5</version> <version>1.5</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.rauschig</groupId> <groupId>org.apache.ant</groupId>
<artifactId>jarchivelib</artifactId> <artifactId>ant</artifactId>
<version>0.7.1</version> <version>1.10.1</version>
</dependency> </dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>