Support running executable-jars exploded
Allow the Launcher to detect ans run exploded (unpacked) jar/war files. This change is primarily driven by the fact that Cloud Foundry will unpack uploaded files. Issue: #53066255pull/7/head
parent
3ba700a861
commit
324abe88b4
@ -0,0 +1,91 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" 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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.zero.launcher.it</groupId>
|
||||
<artifactId>executable-jar</artifactId>
|
||||
<version>0.0.1.BUILD-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>unpack</id>
|
||||
<phase>prepare-package</phase>
|
||||
<goals>
|
||||
<goal>unpack</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>@project.groupId@</groupId>
|
||||
<artifactId>@project.artifactId@</artifactId>
|
||||
<version>@project.version@</version>
|
||||
<type>jar</type>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
<outputDirectory>${project.build.directory}/assembly</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy</id>
|
||||
<phase>prepare-package</phase>
|
||||
<goals>
|
||||
<goal>copy-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.directory}/assembly/lib</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>src/main/assembly/jar-with-dependencies.xml</descriptor>
|
||||
</descriptors>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>org.springframework.launcher.JarLauncher</mainClass>
|
||||
</manifest>
|
||||
<manifestEntries>
|
||||
<Start-Class>org.springframework.launcher.it.jar.EmbeddedJarStarter</Start-Class>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>jar-with-dependencies</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-webapp</artifactId>
|
||||
<version>8.1.8.v20121106</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-annotations</artifactId>
|
||||
<version>8.1.8.v20121106</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<assembly
|
||||
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
|
||||
<id>full</id>
|
||||
<formats>
|
||||
<format>jar</format>
|
||||
</formats>
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
<dependencySets>
|
||||
<dependencySet>
|
||||
<useProjectArtifact/>
|
||||
<includes>
|
||||
<include>${project.groupId}:${project.artifactId}</include>
|
||||
</includes>
|
||||
<unpack>true</unpack>
|
||||
</dependencySet>
|
||||
</dependencySets>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<directory>${project.build.directory}/assembly</directory>
|
||||
<outputDirectory>/</outputDirectory>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
</assembly>
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.launcher.it.jar;
|
||||
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
|
||||
/**
|
||||
* Main class to start the embedded server.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public final class EmbeddedJarStarter {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Server server = new Server(8080);
|
||||
|
||||
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
||||
context.setContextPath("/");
|
||||
server.setHandler(context);
|
||||
|
||||
AnnotationConfigWebApplicationContext webApplicationContext = new AnnotationConfigWebApplicationContext();
|
||||
webApplicationContext.register(SpringConfiguration.class);
|
||||
DispatcherServlet dispatcherServlet = new DispatcherServlet(webApplicationContext);
|
||||
context.addServlet(new ServletHolder(dispatcherServlet), "/*");
|
||||
|
||||
server.start();
|
||||
server.join();
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.launcher.it.jar;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
/**
|
||||
* Simple example Spring MVC Controller.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@Controller
|
||||
public class ExampleController {
|
||||
|
||||
@RequestMapping("/")
|
||||
@ResponseBody
|
||||
public String helloWorld() {
|
||||
return "Hello Embedded Jar World!";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.launcher.it.jar;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
|
||||
/**
|
||||
* Spring configuration.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
@ComponentScan
|
||||
public class SpringConfiguration {
|
||||
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" 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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.zero.launcher.it</groupId>
|
||||
<artifactId>executable-war</artifactId>
|
||||
<version>0.0.1.BUILD-SNAPSHOT</version>
|
||||
<packaging>war</packaging>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>2.3</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>org.springframework.launcher.WarLauncher</mainClass>
|
||||
</manifest>
|
||||
<manifestEntries>
|
||||
<Start-Class>org.springframework.launcher.it.war.embedded.EmbeddedWarStarter</Start-Class>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>unpack</id>
|
||||
<phase>prepare-package</phase>
|
||||
<goals>
|
||||
<goal>unpack</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>@project.groupId@</groupId>
|
||||
<artifactId>@project.artifactId@</artifactId>
|
||||
<version>@project.version@</version>
|
||||
<type>jar</type>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
<outputDirectory>${project.build.directory}/${project.artifactId}-${project.version}</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-webapp</artifactId>
|
||||
<version>8.1.8.v20121106</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-plus</artifactId>
|
||||
<version>8.1.8.v20121106</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-annotations</artifactId>
|
||||
<version>8.1.8.v20121106</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.launcher.it.war;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
/**
|
||||
* Simple example Spring MVC Controller.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@Controller
|
||||
public class ExampleController {
|
||||
|
||||
@RequestMapping("/")
|
||||
@ResponseBody
|
||||
public String helloWorld() {
|
||||
return "Hello Embedded WAR World!";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.launcher.it.war;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
|
||||
/**
|
||||
* Spring configuration.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
@ComponentScan
|
||||
public class SpringConfiguration {
|
||||
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.launcher.it.war;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import org.springframework.web.WebApplicationInitializer;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
|
||||
/**
|
||||
* Spring {@link WebApplicationInitializer} for classic WAR deployment.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class SpringInitializer implements WebApplicationInitializer {
|
||||
|
||||
@Override
|
||||
public void onStartup(ServletContext servletContext) throws ServletException {
|
||||
AnnotationConfigWebApplicationContext webApplicationContext = new AnnotationConfigWebApplicationContext();
|
||||
webApplicationContext.register(SpringConfiguration.class);
|
||||
servletContext.addServlet("dispatcherServlet",
|
||||
new DispatcherServlet(webApplicationContext)).addMapping("/*");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.launcher.it.war.embedded;
|
||||
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.webapp.Configuration;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.springframework.launcher.it.war.SpringInitializer;
|
||||
|
||||
/**
|
||||
* Starter to launch the embedded server. NOTE: Jetty annotation scanning is not
|
||||
* compatible with executable WARs so we must specify the {@link SpringInitializer}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public final class EmbeddedWarStarter {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Server server = new Server(8080);
|
||||
|
||||
WebAppContext webAppContext = new WebAppContext();
|
||||
webAppContext.setContextPath("/");
|
||||
webAppContext.setConfigurations(new Configuration[] {
|
||||
new WebApplicationInitializersConfiguration(SpringInitializer.class) });
|
||||
|
||||
webAppContext.setParentLoaderPriority(true);
|
||||
server.setHandler(webAppContext);
|
||||
server.start();
|
||||
|
||||
server.join();
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.launcher.it.war.embedded;
|
||||
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
|
||||
import org.eclipse.jetty.webapp.AbstractConfiguration;
|
||||
import org.eclipse.jetty.webapp.Configuration;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.WebApplicationInitializer;
|
||||
|
||||
/**
|
||||
* Jetty {@link Configuration} that allows Spring {@link WebApplicationInitializer} to be
|
||||
* started. This is required because Jetty annotation scanning does not work with packaged
|
||||
* WARs.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class WebApplicationInitializersConfiguration extends AbstractConfiguration {
|
||||
|
||||
private Class<?>[] webApplicationInitializers;
|
||||
|
||||
public WebApplicationInitializersConfiguration(Class<?> webApplicationInitializer,
|
||||
Class<?>... webApplicationInitializers) {
|
||||
this.webApplicationInitializers = new Class<?>[webApplicationInitializers.length + 1];
|
||||
this.webApplicationInitializers[0] = webApplicationInitializer;
|
||||
System.arraycopy(webApplicationInitializers, 0, this.webApplicationInitializers,
|
||||
1, webApplicationInitializers.length);
|
||||
for (Class<?> i : webApplicationInitializers) {
|
||||
Assert.notNull(i, "WebApplicationInitializer must not be null");
|
||||
Assert.isAssignable(WebApplicationInitializer.class, i);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(WebAppContext context) throws Exception {
|
||||
context.getServletContext().addListener(new ServletContextListener() {
|
||||
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce) {
|
||||
try {
|
||||
for (Class<?> webApplicationInitializer : webApplicationInitializers) {
|
||||
WebApplicationInitializer initializer = (WebApplicationInitializer) webApplicationInitializer.newInstance();
|
||||
initializer.onStartup(sce.getServletContext());
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent sce) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<settings>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>it-repo</id>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>local.central</id>
|
||||
<url>@localRepositoryUrl@</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>local.central</id>
|
||||
<url>@localRepositoryUrl@</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
</profile>
|
||||
</profiles>
|
||||
</settings>
|
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.launcher;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
/**
|
||||
* An archive that can be launched by the {@link Launcher}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @see JarFileArchive
|
||||
*/
|
||||
public interface Archive {
|
||||
|
||||
/**
|
||||
* Returns the manifest of the archive.
|
||||
* @return the manifest
|
||||
* @throws IOException
|
||||
*/
|
||||
Manifest getManifest() throws IOException;
|
||||
|
||||
/**
|
||||
* Returns archive entries.
|
||||
* @return the archive entries
|
||||
*/
|
||||
Iterable<Entry> getEntries();
|
||||
|
||||
/**
|
||||
* Returns a URL that can be used to load the archive.
|
||||
* @return the archive URL
|
||||
* @throws MalformedURLException
|
||||
*/
|
||||
URL getUrl() throws MalformedURLException;
|
||||
|
||||
/**
|
||||
* Returns a nest archive from on the the contained entries.
|
||||
* @param entry the entry (may be a directory or file)
|
||||
* @return the nested archive
|
||||
* @throws IOException
|
||||
*/
|
||||
Archive getNestedArchive(Entry entry) throws IOException;
|
||||
|
||||
/**
|
||||
* Returns a filtered version of the archive.
|
||||
* @param filter the filter to apply
|
||||
* @return a filter archive
|
||||
* @throws IOException
|
||||
*/
|
||||
Archive getFilteredArchive(EntryFilter filter) throws IOException;
|
||||
|
||||
/**
|
||||
* Represents a single entry in the archive.
|
||||
*/
|
||||
public static interface Entry {
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the entry represents a directory.
|
||||
* @return if the entry is a directory
|
||||
*/
|
||||
boolean isDirectory();
|
||||
|
||||
/**
|
||||
* Returns the name of the entry
|
||||
* @return the name of the entry
|
||||
*/
|
||||
String getName();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A filter for archive entries.
|
||||
*/
|
||||
public static interface EntryFilter {
|
||||
|
||||
/**
|
||||
* Apply the jar entry filter.
|
||||
* @param entryName the current entry name. This may be different that the
|
||||
* original entry name if a previous filter has been applied
|
||||
* @param entry the entry to filter
|
||||
* @return the new name of the entry or {@code null} if the entry should not be
|
||||
* included.
|
||||
*/
|
||||
String apply(String entryName, Entry entry);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.launcher;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLStreamHandler;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
/**
|
||||
* {@link Archive} implementation backed by an exploded archive directory.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class ExplodedArchive implements Archive {
|
||||
|
||||
private static final Set<String> SKIPPED_NAMES = new HashSet<String>(Arrays.asList(
|
||||
".", ".."));
|
||||
|
||||
private static final Object MANIFEST_ENTRY_NAME = "META-INF/MANIFEST.MF";
|
||||
|
||||
private File root;
|
||||
|
||||
private Map<String, Entry> entries = new LinkedHashMap<String, Entry>();
|
||||
|
||||
private Manifest manifest;
|
||||
|
||||
public ExplodedArchive(File root) {
|
||||
if (!root.exists() || !root.isDirectory()) {
|
||||
throw new IllegalArgumentException("Invalid source folder " + root);
|
||||
}
|
||||
this.root = root;
|
||||
buildEntries(root);
|
||||
this.entries = Collections.unmodifiableMap(this.entries);
|
||||
}
|
||||
|
||||
private ExplodedArchive(File root, Map<String, Entry> entries) {
|
||||
this.root = root;
|
||||
this.entries = Collections.unmodifiableMap(entries);
|
||||
}
|
||||
|
||||
private void buildEntries(File file) {
|
||||
if (!file.equals(this.root)) {
|
||||
String name = file.getAbsolutePath().substring(
|
||||
this.root.getAbsolutePath().length() + 1);
|
||||
if (file.isDirectory()) {
|
||||
name += "/";
|
||||
}
|
||||
this.entries.put(name, new FileEntry(name, file));
|
||||
}
|
||||
if (file.isDirectory()) {
|
||||
for (File child : file.listFiles()) {
|
||||
if (!SKIPPED_NAMES.contains(child.getName())) {
|
||||
buildEntries(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Manifest getManifest() throws IOException {
|
||||
if (this.manifest == null && this.entries.containsKey(MANIFEST_ENTRY_NAME)) {
|
||||
FileEntry entry = (FileEntry) this.entries.get(MANIFEST_ENTRY_NAME);
|
||||
FileInputStream inputStream = new FileInputStream(entry.getFile());
|
||||
try {
|
||||
this.manifest = new Manifest(inputStream);
|
||||
}
|
||||
finally {
|
||||
inputStream.close();
|
||||
}
|
||||
}
|
||||
return this.manifest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Entry> getEntries() {
|
||||
return this.entries.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getUrl() throws MalformedURLException {
|
||||
FilteredURLStreamHandler handler = new FilteredURLStreamHandler();
|
||||
return new URL("file", "", -1, this.root.getAbsolutePath() + "/", handler);
|
||||
// return this.root.toURI().toURL();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Archive getNestedArchive(Entry entry) throws IOException {
|
||||
File file = ((FileEntry) entry).getFile();
|
||||
return (file.isDirectory() ? new ExplodedArchive(file) : new JarFileArchive(file));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Archive getFilteredArchive(EntryFilter filter) throws IOException {
|
||||
Map<String, Entry> filteredEntries = new LinkedHashMap<String, Archive.Entry>();
|
||||
for (Map.Entry<String, Entry> entry : this.entries.entrySet()) {
|
||||
String filteredName = filter.apply(entry.getKey(), entry.getValue());
|
||||
if (filteredName != null) {
|
||||
filteredEntries.put(filteredName, new FileEntry(filteredName,
|
||||
((FileEntry) entry.getValue()).getFile()));
|
||||
}
|
||||
}
|
||||
return new ExplodedArchive(this.root, filteredEntries);
|
||||
}
|
||||
|
||||
private class FileEntry implements Entry {
|
||||
|
||||
private final String name;
|
||||
private final File file;
|
||||
|
||||
public FileEntry(String name, File file) {
|
||||
this.name = name;
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
public File getFile() {
|
||||
return this.file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirectory() {
|
||||
return this.file.isDirectory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link URLStreamHandler} that respects filtered entries.
|
||||
*/
|
||||
private class FilteredURLStreamHandler extends URLStreamHandler {
|
||||
|
||||
public FilteredURLStreamHandler() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected URLConnection openConnection(URL url) throws IOException {
|
||||
String name = url.getPath().substring(
|
||||
ExplodedArchive.this.root.getAbsolutePath().length() + 1);
|
||||
if (ExplodedArchive.this.entries.containsKey(name)) {
|
||||
return new URL(url.toString()).openConnection();
|
||||
}
|
||||
return new FileNotFoundURLConnection(url, name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link URLConnection} used to represent a filtered file.
|
||||
*/
|
||||
private static class FileNotFoundURLConnection extends URLConnection {
|
||||
|
||||
private String name;
|
||||
|
||||
public FileNotFoundURLConnection(URL url, String name) {
|
||||
super(url);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() throws IOException {
|
||||
throw new FileNotFoundException(this.name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.launcher;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
import org.springframework.launcher.jar.JarEntryFilter;
|
||||
import org.springframework.launcher.jar.RandomAccessJarFile;
|
||||
|
||||
/**
|
||||
* {@link Archive} implementation backed by a {@link RandomAccessJarFile}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class JarFileArchive implements Archive {
|
||||
|
||||
private final RandomAccessJarFile jarFile;
|
||||
|
||||
private final List<Entry> entries;
|
||||
|
||||
public JarFileArchive(File file) throws IOException {
|
||||
this(new RandomAccessJarFile(file));
|
||||
}
|
||||
|
||||
public JarFileArchive(RandomAccessJarFile jarFile) {
|
||||
this.jarFile = jarFile;
|
||||
ArrayList<Entry> jarFileEntries = new ArrayList<Entry>();
|
||||
Enumeration<JarEntry> entries = jarFile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
jarFileEntries.add(new JarFileEntry(entries.nextElement()));
|
||||
}
|
||||
this.entries = Collections.unmodifiableList(jarFileEntries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Manifest getManifest() throws IOException {
|
||||
return this.jarFile.getManifest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Entry> getEntries() {
|
||||
return this.entries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getUrl() throws MalformedURLException {
|
||||
return this.jarFile.getUrl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Archive getNestedArchive(Entry entry) throws IOException {
|
||||
JarEntry jarEntry = ((JarFileEntry) entry).getJarEntry();
|
||||
RandomAccessJarFile jarFile = this.jarFile.getNestedJarFile(jarEntry);
|
||||
return new JarFileArchive(jarFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Archive getFilteredArchive(final EntryFilter filter) throws IOException {
|
||||
RandomAccessJarFile filteredJar = this.jarFile
|
||||
.getFilteredJarFile(new JarEntryFilter() {
|
||||
@Override
|
||||
public String apply(String name, JarEntry entry) {
|
||||
return filter.apply(name, new JarFileEntry(entry));
|
||||
}
|
||||
});
|
||||
return new JarFileArchive(filteredJar);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Archive.Entry} implementation backed by a {@link JarEntry}.
|
||||
*/
|
||||
private static class JarFileEntry implements Entry {
|
||||
|
||||
private final JarEntry jarEntry;
|
||||
|
||||
public JarFileEntry(JarEntry jarEntry) {
|
||||
this.jarEntry = jarEntry;
|
||||
}
|
||||
|
||||
public JarEntry getJarEntry() {
|
||||
return this.jarEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirectory() {
|
||||
return this.jarEntry.isDirectory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.jarEntry.getName();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.launcher;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.springframework.launcher.Archive.Entry;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link ExplodedArchive}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class ExplodedArchiveTests {
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
private File rootFolder;
|
||||
|
||||
private ExplodedArchive archive;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
File file = this.temporaryFolder.newFile();
|
||||
TestJarCreator.createTestJar(file);
|
||||
|
||||
this.rootFolder = this.temporaryFolder.newFolder();
|
||||
JarFile jarFile = new JarFile(file);
|
||||
Enumeration<JarEntry> entries = jarFile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
JarEntry entry = entries.nextElement();
|
||||
File destination = new File(this.rootFolder.getAbsolutePath()
|
||||
+ File.separator + entry.getName());
|
||||
destination.getParentFile().mkdirs();
|
||||
if (entry.isDirectory()) {
|
||||
destination.mkdir();
|
||||
}
|
||||
else {
|
||||
copy(jarFile.getInputStream(entry), new FileOutputStream(destination));
|
||||
}
|
||||
}
|
||||
this.archive = new ExplodedArchive(this.rootFolder);
|
||||
}
|
||||
|
||||
private void copy(InputStream in, OutputStream out) throws IOException {
|
||||
byte[] buffer = new byte[1024];
|
||||
int len = in.read(buffer);
|
||||
while (len != -1) {
|
||||
out.write(buffer, 0, len);
|
||||
len = in.read(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getManifest() throws Exception {
|
||||
assertThat(this.archive.getManifest().getMainAttributes().getValue("Built-By"),
|
||||
equalTo("j1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEntries() throws Exception {
|
||||
Map<String, Archive.Entry> entries = getEntriesMap(this.archive);
|
||||
assertThat(entries.size(), equalTo(7));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUrl() throws Exception {
|
||||
URL url = this.archive.getUrl();
|
||||
assertThat(url, equalTo(this.rootFolder.toURI().toURL()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNestedArchive() throws Exception {
|
||||
Entry entry = getEntriesMap(this.archive).get("nested.jar");
|
||||
Archive nested = this.archive.getNestedArchive(entry);
|
||||
assertThat(nested.getUrl().toString(),
|
||||
equalTo("jar:file:" + this.rootFolder.getPath() + "/nested.jar!/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nestedDirArchive() throws Exception {
|
||||
Entry entry = getEntriesMap(this.archive).get("d/");
|
||||
Archive nested = this.archive.getNestedArchive(entry);
|
||||
Map<String, Entry> nestedEntries = getEntriesMap(nested);
|
||||
assertThat(nestedEntries.size(), equalTo(1));
|
||||
assertThat(nested.getUrl().toString(),
|
||||
equalTo("file:" + this.rootFolder.getPath() + "/d/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFilteredArchive() throws Exception {
|
||||
Archive filteredArchive = this.archive
|
||||
.getFilteredArchive(new Archive.EntryFilter() {
|
||||
@Override
|
||||
public String apply(String entryName, Entry entry) {
|
||||
if (entryName.equals("1.dat")) {
|
||||
return entryName;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
Map<String, Entry> entries = getEntriesMap(filteredArchive);
|
||||
assertThat(entries.size(), equalTo(1));
|
||||
URLClassLoader classLoader = new URLClassLoader(
|
||||
new URL[] { filteredArchive.getUrl() });
|
||||
assertThat(classLoader.getResourceAsStream("1.dat").read(), equalTo(1));
|
||||
assertThat(classLoader.getResourceAsStream("2.dat"), nullValue());
|
||||
}
|
||||
|
||||
private Map<String, Archive.Entry> getEntriesMap(Archive archive) {
|
||||
Map<String, Archive.Entry> entries = new HashMap<String, Archive.Entry>();
|
||||
for (Archive.Entry entry : archive.getEntries()) {
|
||||
entries.put(entry.getName(), entry);
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.launcher;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.springframework.launcher.Archive.Entry;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link JarFileArchive}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class JarFileArchiveTests {
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
private File rootJarFile;
|
||||
|
||||
private JarFileArchive archive;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
this.rootJarFile = this.temporaryFolder.newFile();
|
||||
TestJarCreator.createTestJar(this.rootJarFile);
|
||||
this.archive = new JarFileArchive(this.rootJarFile);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getManifest() throws Exception {
|
||||
assertThat(this.archive.getManifest().getMainAttributes().getValue("Built-By"),
|
||||
equalTo("j1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEntries() throws Exception {
|
||||
Map<String, Archive.Entry> entries = getEntriesMap(this.archive);
|
||||
assertThat(entries.size(), equalTo(7));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUrl() throws Exception {
|
||||
URL url = this.archive.getUrl();
|
||||
assertThat(url.toString(), equalTo("jar:file:" + this.rootJarFile.getPath()
|
||||
+ "!/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNestedArchive() throws Exception {
|
||||
Entry entry = getEntriesMap(this.archive).get("nested.jar");
|
||||
Archive nested = this.archive.getNestedArchive(entry);
|
||||
assertThat(nested.getUrl().toString(),
|
||||
equalTo("jar:file:" + this.rootJarFile.getPath() + "!/nested.jar!/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFilteredArchive() throws Exception {
|
||||
Archive filteredArchive = this.archive
|
||||
.getFilteredArchive(new Archive.EntryFilter() {
|
||||
@Override
|
||||
public String apply(String entryName, Entry entry) {
|
||||
if (entryName.equals("1.dat")) {
|
||||
return entryName;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
Map<String, Entry> entries = getEntriesMap(filteredArchive);
|
||||
assertThat(entries.size(), equalTo(1));
|
||||
}
|
||||
|
||||
private Map<String, Archive.Entry> getEntriesMap(Archive archive) {
|
||||
Map<String, Archive.Entry> entries = new HashMap<String, Archive.Entry>();
|
||||
for (Archive.Entry entry : archive.getEntries()) {
|
||||
entries.put(entry.getName(), entry);
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.launcher;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarOutputStream;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.zip.CRC32;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
/**
|
||||
* Creates a simple test jar.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public abstract class TestJarCreator {
|
||||
|
||||
public static void createTestJar(File file) throws Exception {
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(file);
|
||||
JarOutputStream jarOutputStream = new JarOutputStream(fileOutputStream);
|
||||
try {
|
||||
writeManifest(jarOutputStream, "j1");
|
||||
writeEntry(jarOutputStream, "1.dat", 1);
|
||||
writeEntry(jarOutputStream, "2.dat", 2);
|
||||
writeDirEntry(jarOutputStream, "d/");
|
||||
writeEntry(jarOutputStream, "d/9.dat", 9);
|
||||
|
||||
JarEntry nestedEntry = new JarEntry("nested.jar");
|
||||
byte[] nestedJarData = getNestedJarData();
|
||||
nestedEntry.setSize(nestedJarData.length);
|
||||
nestedEntry.setCompressedSize(nestedJarData.length);
|
||||
CRC32 crc32 = new CRC32();
|
||||
crc32.update(nestedJarData);
|
||||
nestedEntry.setCrc(crc32.getValue());
|
||||
|
||||
nestedEntry.setMethod(ZipEntry.STORED);
|
||||
jarOutputStream.putNextEntry(nestedEntry);
|
||||
jarOutputStream.write(nestedJarData);
|
||||
jarOutputStream.closeEntry();
|
||||
}
|
||||
finally {
|
||||
jarOutputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] getNestedJarData() throws Exception {
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
JarOutputStream jarOutputStream = new JarOutputStream(byteArrayOutputStream);
|
||||
writeManifest(jarOutputStream, "j2");
|
||||
writeEntry(jarOutputStream, "3.dat", 3);
|
||||
writeEntry(jarOutputStream, "4.dat", 4);
|
||||
jarOutputStream.close();
|
||||
return byteArrayOutputStream.toByteArray();
|
||||
}
|
||||
|
||||
private static void writeManifest(JarOutputStream jarOutputStream, String name)
|
||||
throws Exception {
|
||||
writeDirEntry(jarOutputStream, "META-INF/");
|
||||
Manifest manifest = new Manifest();
|
||||
manifest.getMainAttributes().putValue("Built-By", name);
|
||||
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
|
||||
jarOutputStream.putNextEntry(new ZipEntry("META-INF/MANIFEST.MF"));
|
||||
manifest.write(jarOutputStream);
|
||||
jarOutputStream.closeEntry();
|
||||
}
|
||||
|
||||
private static void writeDirEntry(JarOutputStream jarOutputStream, String name)
|
||||
throws IOException {
|
||||
jarOutputStream.putNextEntry(new JarEntry(name));
|
||||
jarOutputStream.closeEntry();
|
||||
}
|
||||
|
||||
private static void writeEntry(JarOutputStream jarOutputStream, String name, int data)
|
||||
throws IOException {
|
||||
jarOutputStream.putNextEntry(new JarEntry(name));
|
||||
jarOutputStream.write(new byte[] { (byte) data });
|
||||
jarOutputStream.closeEntry();
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue