Merge branch '1.5.x'
commit
b527e71474
@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2017 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.boot.context.embedded;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.jar.JarEntry;
|
||||||
|
import java.util.jar.JarFile;
|
||||||
|
|
||||||
|
import org.springframework.util.FileSystemUtils;
|
||||||
|
import org.springframework.util.StreamUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link AbstractApplicationLauncher} that launches a Spring Boot application with a
|
||||||
|
* classpath similar to that used when run with Maven or Gradle.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
class BootRunApplicationLauncher extends AbstractApplicationLauncher {
|
||||||
|
|
||||||
|
private final File exploded = new File("target/run");
|
||||||
|
|
||||||
|
BootRunApplicationLauncher(ApplicationBuilder applicationBuilder) {
|
||||||
|
super(applicationBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<String> getArguments(File archive) {
|
||||||
|
try {
|
||||||
|
explodeArchive(archive);
|
||||||
|
deleteLauncherClasses();
|
||||||
|
File targetClasses = populateTargetClasses(archive);
|
||||||
|
File dependencies = populateDependencies(archive);
|
||||||
|
populateSrcMainWebapp();
|
||||||
|
List<String> classpath = new ArrayList<String>();
|
||||||
|
classpath.add(targetClasses.getAbsolutePath());
|
||||||
|
for (File dependency : dependencies.listFiles()) {
|
||||||
|
classpath.add(dependency.getAbsolutePath());
|
||||||
|
}
|
||||||
|
return Arrays.asList("-cp",
|
||||||
|
StringUtils.collectionToDelimitedString(classpath,
|
||||||
|
File.pathSeparator),
|
||||||
|
"com.example.ResourceHandlingApplication");
|
||||||
|
}
|
||||||
|
catch (IOException ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteLauncherClasses() {
|
||||||
|
FileSystemUtils.deleteRecursively(new File(this.exploded, "org"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private File populateTargetClasses(File archive) {
|
||||||
|
File targetClasses = new File(this.exploded, "target/classes");
|
||||||
|
targetClasses.mkdirs();
|
||||||
|
new File(this.exploded, getClassesPath(archive)).renameTo(targetClasses);
|
||||||
|
return targetClasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
private File populateDependencies(File archive) {
|
||||||
|
File dependencies = new File(this.exploded, "dependencies");
|
||||||
|
dependencies.mkdirs();
|
||||||
|
List<String> libPaths = getLibPaths(archive);
|
||||||
|
for (String libPath : libPaths) {
|
||||||
|
for (File jar : new File(this.exploded, libPath).listFiles()) {
|
||||||
|
jar.renameTo(new File(dependencies, jar.getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dependencies;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void populateSrcMainWebapp() {
|
||||||
|
File srcMainWebapp = new File(this.exploded, "src/main/webapp");
|
||||||
|
srcMainWebapp.mkdirs();
|
||||||
|
new File(this.exploded, "webapp-resource.txt")
|
||||||
|
.renameTo(new File(srcMainWebapp, "webapp-resource.txt"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getClassesPath(File archive) {
|
||||||
|
return archive.getName().endsWith(".jar") ? "BOOT-INF/classes"
|
||||||
|
: "WEB-INF/classes";
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getLibPaths(File archive) {
|
||||||
|
return archive.getName().endsWith(".jar")
|
||||||
|
? Collections.singletonList("BOOT-INF/lib")
|
||||||
|
: Arrays.asList("WEB-INF/lib", "WEB-INF/lib-provided");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void explodeArchive(File archive) throws IOException {
|
||||||
|
FileSystemUtils.deleteRecursively(this.exploded);
|
||||||
|
JarFile jarFile = new JarFile(archive);
|
||||||
|
Enumeration<JarEntry> entries = jarFile.entries();
|
||||||
|
while (entries.hasMoreElements()) {
|
||||||
|
JarEntry jarEntry = entries.nextElement();
|
||||||
|
File extracted = new File(this.exploded, jarEntry.getName());
|
||||||
|
if (jarEntry.isDirectory()) {
|
||||||
|
extracted.mkdirs();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
FileOutputStream extractedOutputStream = new FileOutputStream(extracted);
|
||||||
|
StreamUtils.copy(jarFile.getInputStream(jarEntry), extractedOutputStream);
|
||||||
|
extractedOutputStream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
jarFile.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected File getWorkingDirectory() {
|
||||||
|
return this.exploded;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getDescription(String packaging) {
|
||||||
|
return "build system run " + packaging + " project";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2017 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.boot.context.embedded;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.Parameterized;
|
||||||
|
import org.junit.runners.Parameterized.Parameters;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests for Spring Boot's embedded servlet container support when developing
|
||||||
|
* a jar application.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
@RunWith(Parameterized.class)
|
||||||
|
public class EmbeddedServletContainerJarDevelopmentIntegrationTests
|
||||||
|
extends AbstractEmbeddedServletContainerIntegrationTests {
|
||||||
|
|
||||||
|
@Parameters(name = "{0}")
|
||||||
|
public static Object[] parameters() {
|
||||||
|
return AbstractEmbeddedServletContainerIntegrationTests.parameters("jar", Arrays
|
||||||
|
.asList(BootRunApplicationLauncher.class, IdeApplicationLauncher.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public EmbeddedServletContainerJarDevelopmentIntegrationTests(String name,
|
||||||
|
AbstractApplicationLauncher launcher) {
|
||||||
|
super(name, launcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void metaInfResourceFromDependencyIsAvailableViaHttp() throws Exception {
|
||||||
|
ResponseEntity<String> entity = this.rest
|
||||||
|
.getForEntity("/nested-meta-inf-resource.txt", String.class);
|
||||||
|
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void metaInfResourceFromDependencyIsAvailableViaServletContext()
|
||||||
|
throws Exception {
|
||||||
|
ResponseEntity<String> entity = this.rest
|
||||||
|
.getForEntity("/nested-meta-inf-resource.txt", String.class);
|
||||||
|
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2017 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.boot.context.embedded;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.Parameterized;
|
||||||
|
import org.junit.runners.Parameterized.Parameters;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests for Spring Boot's embedded servlet container support when developing
|
||||||
|
* a war application.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
@RunWith(Parameterized.class)
|
||||||
|
public class EmbeddedServletContainerWarDevelopmentIntegrationTests
|
||||||
|
extends AbstractEmbeddedServletContainerIntegrationTests {
|
||||||
|
|
||||||
|
@Parameters(name = "{0}")
|
||||||
|
public static Object[] parameters() {
|
||||||
|
return AbstractEmbeddedServletContainerIntegrationTests.parameters("war", Arrays
|
||||||
|
.asList(BootRunApplicationLauncher.class, IdeApplicationLauncher.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public EmbeddedServletContainerWarDevelopmentIntegrationTests(String name,
|
||||||
|
AbstractApplicationLauncher launcher) {
|
||||||
|
super(name, launcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void metaInfResourceFromDependencyIsAvailableViaHttp() throws Exception {
|
||||||
|
ResponseEntity<String> entity = this.rest
|
||||||
|
.getForEntity("/nested-meta-inf-resource.txt", String.class);
|
||||||
|
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void metaInfResourceFromDependencyIsAvailableViaServletContext()
|
||||||
|
throws Exception {
|
||||||
|
ResponseEntity<String> entity = this.rest
|
||||||
|
.getForEntity("/nested-meta-inf-resource.txt", String.class);
|
||||||
|
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void webappResourcesAreAvailableViaHttp() throws Exception {
|
||||||
|
ResponseEntity<String> entity = this.rest.getForEntity("/webapp-resource.txt",
|
||||||
|
String.class);
|
||||||
|
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2017 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.boot.context.embedded;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.jar.JarEntry;
|
||||||
|
import java.util.jar.JarFile;
|
||||||
|
|
||||||
|
import org.springframework.util.FileSystemUtils;
|
||||||
|
import org.springframework.util.StreamUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link AbstractApplicationLauncher} that launches a Spring Boot application with a
|
||||||
|
* classpath similar to that used when run in an IDE.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
class IdeApplicationLauncher extends AbstractApplicationLauncher {
|
||||||
|
|
||||||
|
private final File exploded = new File("target/ide");
|
||||||
|
|
||||||
|
IdeApplicationLauncher(ApplicationBuilder applicationBuilder) {
|
||||||
|
super(applicationBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected File getWorkingDirectory() {
|
||||||
|
return this.exploded;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getDescription(String packaging) {
|
||||||
|
return "IDE run " + packaging + " project";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<String> getArguments(File archive) {
|
||||||
|
try {
|
||||||
|
explodeArchive(archive, this.exploded);
|
||||||
|
deleteLauncherClasses();
|
||||||
|
File targetClasses = populateTargetClasses(archive);
|
||||||
|
File dependencies = populateDependencies(archive);
|
||||||
|
File resourcesProject = explodedResourcesProject(dependencies);
|
||||||
|
populateSrcMainWebapp();
|
||||||
|
List<String> classpath = new ArrayList<String>();
|
||||||
|
classpath.add(targetClasses.getAbsolutePath());
|
||||||
|
for (File dependency : dependencies.listFiles()) {
|
||||||
|
classpath.add(dependency.getAbsolutePath());
|
||||||
|
}
|
||||||
|
classpath.add(resourcesProject.getAbsolutePath());
|
||||||
|
return Arrays.asList("-cp",
|
||||||
|
StringUtils.collectionToDelimitedString(classpath,
|
||||||
|
File.pathSeparator),
|
||||||
|
"com.example.ResourceHandlingApplication");
|
||||||
|
}
|
||||||
|
catch (IOException ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private File populateTargetClasses(File archive) {
|
||||||
|
File targetClasses = new File(this.exploded, "target/classes");
|
||||||
|
targetClasses.mkdirs();
|
||||||
|
new File(this.exploded, getClassesPath(archive)).renameTo(targetClasses);
|
||||||
|
return targetClasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
private File populateDependencies(File archive) {
|
||||||
|
File dependencies = new File(this.exploded, "dependencies");
|
||||||
|
dependencies.mkdirs();
|
||||||
|
List<String> libPaths = getLibPaths(archive);
|
||||||
|
for (String libPath : libPaths) {
|
||||||
|
for (File jar : new File(this.exploded, libPath).listFiles()) {
|
||||||
|
jar.renameTo(new File(dependencies, jar.getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dependencies;
|
||||||
|
}
|
||||||
|
|
||||||
|
private File explodedResourcesProject(File dependencies) throws IOException {
|
||||||
|
File resourcesProject = new File(this.exploded,
|
||||||
|
"resources-project/target/classes");
|
||||||
|
File resourcesJar = new File(dependencies, "resources-1.0.jar");
|
||||||
|
explodeArchive(resourcesJar, resourcesProject);
|
||||||
|
resourcesJar.delete();
|
||||||
|
return resourcesProject;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void populateSrcMainWebapp() {
|
||||||
|
File srcMainWebapp = new File(this.exploded, "src/main/webapp");
|
||||||
|
srcMainWebapp.mkdirs();
|
||||||
|
new File(this.exploded, "webapp-resource.txt")
|
||||||
|
.renameTo(new File(srcMainWebapp, "webapp-resource.txt"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteLauncherClasses() {
|
||||||
|
FileSystemUtils.deleteRecursively(new File(this.exploded, "org"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getClassesPath(File archive) {
|
||||||
|
return archive.getName().endsWith(".jar") ? "BOOT-INF/classes"
|
||||||
|
: "WEB-INF/classes";
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getLibPaths(File archive) {
|
||||||
|
return archive.getName().endsWith(".jar")
|
||||||
|
? Collections.singletonList("BOOT-INF/lib")
|
||||||
|
: Arrays.asList("WEB-INF/lib", "WEB-INF/lib-provided");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void explodeArchive(File archive, File destination) throws IOException {
|
||||||
|
FileSystemUtils.deleteRecursively(destination);
|
||||||
|
JarFile jarFile = new JarFile(archive);
|
||||||
|
Enumeration<JarEntry> entries = jarFile.entries();
|
||||||
|
while (entries.hasMoreElements()) {
|
||||||
|
JarEntry jarEntry = entries.nextElement();
|
||||||
|
File extracted = new File(destination, jarEntry.getName());
|
||||||
|
if (jarEntry.isDirectory()) {
|
||||||
|
extracted.mkdirs();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
FileOutputStream extractedOutputStream = new FileOutputStream(extracted);
|
||||||
|
StreamUtils.copy(jarFile.getInputStream(jarEntry), extractedOutputStream);
|
||||||
|
extractedOutputStream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
jarFile.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2017 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.boot.context.embedded.tomcat;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.naming.directory.DirContext;
|
||||||
|
|
||||||
|
import org.apache.catalina.Context;
|
||||||
|
import org.apache.catalina.WebResourceRoot.ResourceSetType;
|
||||||
|
import org.apache.catalina.core.StandardContext;
|
||||||
|
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstraction to add resources that works with both Tomcat 8 and 7.
|
||||||
|
*
|
||||||
|
* @author Dave Syer
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
abstract class TomcatResources {
|
||||||
|
|
||||||
|
private final Context context;
|
||||||
|
|
||||||
|
TomcatResources(Context context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addResourceJars(List<URL> resourceJarUrls) {
|
||||||
|
for (URL url : resourceJarUrls) {
|
||||||
|
String file = url.getFile();
|
||||||
|
if (file.endsWith(".jar") || file.endsWith(".jar!/")) {
|
||||||
|
String jar = url.toString();
|
||||||
|
if (!jar.startsWith("jar:")) {
|
||||||
|
// A jar file in the file system. Convert to Jar URL.
|
||||||
|
jar = "jar:" + jar + "!/";
|
||||||
|
}
|
||||||
|
addJar(jar);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addDir(file, url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final Context getContext() {
|
||||||
|
return this.context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to add a JAR to the resources.
|
||||||
|
* @param jar the URL spec for the jar
|
||||||
|
*/
|
||||||
|
protected abstract void addJar(String jar);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to add a dir to the resource.
|
||||||
|
* @param dir the dir
|
||||||
|
* @param url the URL
|
||||||
|
*/
|
||||||
|
protected abstract void addDir(String dir, URL url);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a {@link TomcatResources} instance for the currently running Tomcat version.
|
||||||
|
* @param context the tomcat context
|
||||||
|
* @return a {@link TomcatResources} instance.
|
||||||
|
*/
|
||||||
|
public static TomcatResources get(Context context) {
|
||||||
|
if (ClassUtils.isPresent("org.apache.catalina.deploy.ErrorPage", null)) {
|
||||||
|
return new Tomcat7Resources(context);
|
||||||
|
}
|
||||||
|
return new Tomcat8Resources(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link TomcatResources} for Tomcat 7.
|
||||||
|
*/
|
||||||
|
private static class Tomcat7Resources extends TomcatResources {
|
||||||
|
|
||||||
|
private final Method addResourceJarUrlMethod;
|
||||||
|
|
||||||
|
Tomcat7Resources(Context context) {
|
||||||
|
super(context);
|
||||||
|
this.addResourceJarUrlMethod = ReflectionUtils.findMethod(context.getClass(),
|
||||||
|
"addResourceJarUrl", URL.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addJar(String jar) {
|
||||||
|
URL url = getJarUrl(jar);
|
||||||
|
if (url != null) {
|
||||||
|
try {
|
||||||
|
this.addResourceJarUrlMethod.invoke(getContext(), url);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
throw new IllegalStateException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private URL getJarUrl(String jar) {
|
||||||
|
try {
|
||||||
|
return new URL(jar);
|
||||||
|
}
|
||||||
|
catch (MalformedURLException ex) {
|
||||||
|
// Ignore
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addDir(String dir, URL url) {
|
||||||
|
if (getContext() instanceof StandardContext) {
|
||||||
|
try {
|
||||||
|
Class<?> fileDirContextClass = Class
|
||||||
|
.forName("org.apache.naming.resources.FileDirContext");
|
||||||
|
Method setDocBaseMethod = ReflectionUtils
|
||||||
|
.findMethod(fileDirContextClass, "setDocBase", String.class);
|
||||||
|
Object fileDirContext = fileDirContextClass.newInstance();
|
||||||
|
setDocBaseMethod.invoke(fileDirContext, dir);
|
||||||
|
Method addResourcesDirContextMethod = ReflectionUtils.findMethod(
|
||||||
|
StandardContext.class, "addResourcesDirContext",
|
||||||
|
DirContext.class);
|
||||||
|
addResourcesDirContextMethod.invoke(getContext(), fileDirContext);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
throw new IllegalStateException("Tomcat 7 reflection failed", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link TomcatResources} for Tomcat 8.
|
||||||
|
*/
|
||||||
|
static class Tomcat8Resources extends TomcatResources {
|
||||||
|
|
||||||
|
Tomcat8Resources(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addJar(String jar) {
|
||||||
|
addResourceSet(jar);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addDir(String dir, URL url) {
|
||||||
|
addResourceSet(url.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addResourceSet(String resource) {
|
||||||
|
try {
|
||||||
|
if (isInsideNestedJar(resource)) {
|
||||||
|
// It's a nested jar but we now don't want the suffix because Tomcat
|
||||||
|
// is going to try and locate it as a root URL (not the resource
|
||||||
|
// inside it)
|
||||||
|
resource = resource.substring(0, resource.length() - 2);
|
||||||
|
}
|
||||||
|
URL url = new URL(resource);
|
||||||
|
String path = "/META-INF/resources";
|
||||||
|
getContext().getResources().createWebResourceSet(
|
||||||
|
ResourceSetType.RESOURCE_JAR, "/", url, path);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
// Ignore (probably not a directory)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isInsideNestedJar(String dir) {
|
||||||
|
return dir.indexOf("!/") < dir.lastIndexOf("!/");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue