Skip to content

Commit

Permalink
Merge pull request #4 from skjolber/master
Browse files Browse the repository at this point in the history
Add support for parent classloading and Jetty JSP example
  • Loading branch information
mjeanroy authored Jun 17, 2017
2 parents e008d2d + 6a9015e commit 59e4376
Show file tree
Hide file tree
Showing 15 changed files with 729 additions and 22 deletions.
18 changes: 13 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# Junit-Servers
---------------------

[![Build Status](https://travis-ci.org/mjeanroy/junit-servers.svg?branch=master)](https://travis-ci.org/mjeanroy/junit-servers)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.mjeanroy/junit-servers/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.mjeanroy/junit-servers)
Expand All @@ -15,7 +14,7 @@ With Maven, add explicit dependency:
<dependency>
<groupId>com.github.mjeanroy</groupId>
<artifactId>junit-servers-jetty</artifactId>
<version>0.4.2</version>
<version>0.4.3</version>
<scope>test</scope>
</dependency>
```
Expand All @@ -24,7 +23,7 @@ With Maven, add explicit dependency:
<dependency>
<groupId>com.github.mjeanroy</groupId>
<artifactId>junit-servers-tomcat</artifactId>
<version>0.4.2</version>
<version>0.4.3</version>
<scope>test</scope>
</dependency>
```
Expand Down Expand Up @@ -132,6 +131,8 @@ public class MyTest {
When embedded jetty is created, you can easyly use a custom configuration using a fluent API:

- Define custom enironment properties that will be initialized before server startup and removed after server shutdown.
- Define an override descriptor for web.xml, for example for loading a spring configuration with additional setup from test resources.
- Define additional parent classpath from either existing Maven dependencies or jar files in a directory, helping with JSPs.
- Define custom hooks to execute custom code before server startup and after server shutdown.

```java
Expand All @@ -153,6 +154,13 @@ public class MyTest {
.withWebapp("webapp")
.withPort(9090)
.withProperty("spring.profiles.active", "test")
.withOverrideDescriptor("src/test/resources/WEB-INF/web.xml")
.withParentClasspath(WebAppContext.class, new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.getName().startsWith("apache-jstl");
}
})
.withHook(new Hook() {
@Override
public void pre(EmbeddedServer server) {
Expand Down Expand Up @@ -418,10 +426,10 @@ public class MyTest {
}
```

## Licence
## Licence

MIT License (MIT)

## Contributing
## Contributing

If you found a bug or you thing something is missing, feel free to contribute and submit an issue or a pull request.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
import static java.util.Collections.unmodifiableList;
import static java.util.Collections.unmodifiableMap;

import java.net.URL;

/**
* Generic configuration that should be extended for
* each custom embedded server.
Expand Down Expand Up @@ -79,6 +81,16 @@ public abstract class AbstractConfiguration {
*/
private final String classpath;

/**
* Additional parent (classloader) classpath.
*
* The path will be added to application parent classlodaer classpath
* before server is started.
*
*/

private final List<URL> parentClasspath;

/**
* Map of environment properties to set before server start.
*
Expand All @@ -101,6 +113,8 @@ public abstract class AbstractConfiguration {
*/
private final List<Hook> hooks;

private String overrideDescriptor;

/**
* Initialize configuration.
*
Expand All @@ -114,6 +128,8 @@ protected AbstractConfiguration(AbstractConfigurationBuilder builder) {
this.port = builder.getPort();
this.envProperties = builder.getEnvProperties();
this.hooks = builder.getHooks();
this.parentClasspath = builder.getParentClasspath();
this.overrideDescriptor = builder.getOverrideDescriptor();
}

public String getPath() {
Expand All @@ -128,9 +144,17 @@ public String getClasspath() {
return classpath;
}

public List<URL> getParentClasspath() {
return parentClasspath;
}

public int getPort() {
return port;
}

public String getOverrideDescriptor() {
return overrideDescriptor ;
}

public Map<String, String> getEnvProperties() {
return unmodifiableMap(envProperties);
Expand All @@ -152,7 +176,9 @@ public boolean equals(Object o) {
Objects.equals(webapp, c.webapp) &&
Objects.equals(classpath, c.classpath) &&
Objects.equals(envProperties, c.envProperties) &&
Objects.equals(hooks, c.hooks);
Objects.equals(hooks, c.hooks) &&
Objects.equals(overrideDescriptor, c.overrideDescriptor) &&
Objects.equals(parentClasspath, c.parentClasspath);
}
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,17 @@
import com.github.mjeanroy.junit.servers.servers.Hook;

import java.io.File;
import java.io.FileFilter;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static com.github.mjeanroy.junit.servers.commons.Preconditions.notBlank;
import static com.github.mjeanroy.junit.servers.commons.Preconditions.notNull;
Expand Down Expand Up @@ -73,6 +80,13 @@ public abstract class AbstractConfigurationBuilder<T extends AbstractConfigurati
* @see com.github.mjeanroy.junit.servers.servers.configuration.AbstractConfiguration#classpath
*/
private String classpath;

/**
* Parent classpath URLs
*
*/

private List<URL> parentClasspath;

/**
* Map of properties.
Expand All @@ -88,6 +102,8 @@ public abstract class AbstractConfigurationBuilder<T extends AbstractConfigurati
*/
private final List<Hook> hooks;

private String overrideDescriptor;

/**
* Build default configuration.
*/
Expand Down Expand Up @@ -216,4 +232,59 @@ public T withHook(Hook hook) {
this.hooks.add(notNull(hook, "hook"));
return self();
}


/**
* Change parent classpath value.
*
* @param classpath New webapp value.
* @return this
*/
public T withParentClasspath(List<URL> classpath) {
this.parentClasspath = classpath;
return self();
}

/**
* Change parent classpath value.
*
* @param classpath New webapp value.
* @return this
*/
public T withParentClasspath(Class<?> cls, FileFilter filter) {
URLClassLoader urlClassLoader = (URLClassLoader) cls.getClassLoader();

Set<URL> urls = new HashSet<>();
for(URL url : urlClassLoader.getURLs()) {
if(filter.accept(new File(url.getFile()))) {
urls.add(url);
}
}
this.parentClasspath = new ArrayList<>(urls);
return self();
}

/**
* Change parent classpath value.
*
* @param classpath New webapp value.
* @return this
*/
public T withParentClasspath(URL ... classpath) {
this.parentClasspath = Arrays.asList(classpath);
return self();
}

public List<URL> getParentClasspath() {
return parentClasspath;
}

public T withOverrideDescriptor (String overrideDescriptor) {
this.overrideDescriptor = overrideDescriptor;
return self();
}

public String getOverrideDescriptor() {
return overrideDescriptor;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,23 @@

package com.github.mjeanroy.junit.servers.jetty;

import com.github.mjeanroy.junit.servers.exceptions.ServerInitializationException;
import com.github.mjeanroy.junit.servers.exceptions.ServerStartException;
import com.github.mjeanroy.junit.servers.exceptions.ServerStopException;
import com.github.mjeanroy.junit.servers.servers.AbstractEmbeddedServer;
import static com.github.mjeanroy.junit.servers.commons.Strings.isNotBlank;
import static com.github.mjeanroy.junit.servers.jetty.EmbeddedJettyConfiguration.defaultConfiguration;
import static org.eclipse.jetty.util.resource.Resource.newResource;

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;

import javax.servlet.ServletContext;

import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.util.resource.FileResource;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.FragmentConfiguration;
import org.eclipse.jetty.webapp.JettyWebXmlConfiguration;
Expand All @@ -41,12 +49,10 @@
import org.eclipse.jetty.webapp.WebInfConfiguration;
import org.eclipse.jetty.webapp.WebXmlConfiguration;

import javax.servlet.ServletContext;
import java.io.File;

import static com.github.mjeanroy.junit.servers.commons.Strings.isNotBlank;
import static com.github.mjeanroy.junit.servers.jetty.EmbeddedJettyConfiguration.defaultConfiguration;
import static org.eclipse.jetty.util.resource.Resource.newResource;
import com.github.mjeanroy.junit.servers.exceptions.ServerInitializationException;
import com.github.mjeanroy.junit.servers.exceptions.ServerStartException;
import com.github.mjeanroy.junit.servers.exceptions.ServerStopException;
import com.github.mjeanroy.junit.servers.servers.AbstractEmbeddedServer;

/**
* Jetty Embedded Server.
Expand Down Expand Up @@ -128,23 +134,42 @@ protected WebAppContext createdWebAppContext() throws Exception {
final String path = configuration.getPath();
final String webapp = configuration.getWebapp();
final String classpath = configuration.getClasspath();
final List<URL> parentClasspath = configuration.getParentClasspath();
final String overrideDescriptor = configuration.getOverrideDescriptor ();
final Resource baseResource = configuration.getBaseResource();

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

if(parentClasspath != null && !parentClasspath.isEmpty()) {
classLoader = new URLClassLoader(parentClasspath.toArray(new URL[parentClasspath.size()]), classLoader);
}

WebAppContext ctx = new WebAppContext();
ctx.setClassLoader(Thread.currentThread().getContextClassLoader());
ctx.setClassLoader(classLoader);
ctx.setContextPath(path);

// Useful for WebXmlConfiguration
ctx.setBaseResource(newResource(webapp));
if(baseResource == null) {
// use default base resource
ctx.setBaseResource(newResource(webapp));
} else {
ctx.setBaseResource(baseResource);
}

if(overrideDescriptor != null) {
ctx.setOverrideDescriptor(overrideDescriptor);
}

ctx.setConfigurations(new Configuration[]{
new WebInfConfiguration(),
new WebInfConfiguration(),
new WebXmlConfiguration(),
new AnnotationConfiguration(),
new JettyWebXmlConfiguration(),
new MetaInfConfiguration(),
new FragmentConfiguration(),
new FragmentConfiguration()
});

ctx.addOverrideDescriptor(overrideDescriptor);

if (isNotBlank(classpath)) {
// Fix to scan Spring WebApplicationInitializer
// This will add compiled classes to jetty classpath
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@

import static com.github.mjeanroy.junit.servers.commons.Preconditions.positive;

import org.eclipse.jetty.util.resource.Resource;

/**
* Jetty configuration settings.
*/
Expand All @@ -46,6 +48,8 @@ public final class EmbeddedJettyConfiguration extends AbstractConfiguration {
*/
private final boolean stopAtShutdown;

private Resource baseResource;

/**
* Get configuration builder.
*
Expand All @@ -69,6 +73,7 @@ private EmbeddedJettyConfiguration(Builder builder) {
super(builder);
this.stopTimeout = builder.getStopTimeout();
this.stopAtShutdown = builder.isStopAtShutdown();
this.baseResource = builder.getBaseResource();
}

public int getStopTimeout() {
Expand All @@ -89,12 +94,18 @@ public int hashCode() {
return super.hashCode();
}

public Resource getBaseResource() {
return baseResource;
}

public static class Builder extends AbstractConfigurationBuilder<Builder, EmbeddedJettyConfiguration> {

private int stopTimeout;

private boolean stopAtShutdown;

private Resource baseResource;

private Builder() {
stopTimeout = 30000;
stopAtShutdown = true;
Expand All @@ -118,6 +129,10 @@ public boolean isStopAtShutdown() {
return stopAtShutdown;
}

public Resource getBaseResource() {
return baseResource;
}

/**
* Update stop timeout value.
* @param stopTimeout New stop timeout value.
Expand All @@ -141,5 +156,11 @@ private Builder toggleStopAtShutdown(boolean stopAtShutdown) {
this.stopAtShutdown = stopAtShutdown;
return this;
}

public Builder withBaseResource(Resource resource) {
this.baseResource = resource;
return this;
}

}
}
Empty file.
Loading

0 comments on commit 59e4376

Please sign in to comment.