-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/10.0.x' into 11.0.x
- Loading branch information
Showing
8 changed files
with
294 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# Using META-INF/resources with ServletContextHandler | ||
|
||
There are many jars available to you on the Global Central Maven Repository System that | ||
provide web resources in the `META-INF/resources` directories contained within those jars. | ||
|
||
Using `META-INF/resources` with embedded-jetty can be accomplished with a full blown | ||
`WebAppContext` and the use of WAR files, but that is often overkill when working | ||
with embedded-jetty. | ||
|
||
Users of embedded-jetty often want to work with the `ServletContextHandler` and | ||
also take advantage of the `META-INF/resources` JAR files. | ||
|
||
This project is an example of combining JAR files from [central.maven.org](https://search.maven.org/) | ||
that contain `META-INF/resources` directories and the `ServletContextHandler` from embedded-jetty. | ||
|
||
What you should pay attention to in this project. | ||
|
||
1. [pom.xml](pom.xml) - the `maven-dependency-plugin` configuration that | ||
unpack's all of the dependencies that have `META-INF/resources` directories | ||
|
||
2. [src/main/resources/META-INF/resources/MYREADME.txt](src/main/resources/META-INF/resources/MYREADME.txt) - | ||
this file is searched for, and should be uniquely named to your project. It can be any resource | ||
a css, an html, a javascript, an image, whatever. Just as long as its name is unique to your | ||
project. | ||
|
||
3. [ExampleServer](src/main/java/examples/MetaInfResourceDemo.java) - this is where | ||
the actual embedded-jetty server resides. | ||
|
||
1. Create a `ServletContextHandler` | ||
2. Find the special resource URL location | ||
3. Create a "Base Resource" that points to the directory location of | ||
the special resource file | ||
4. Create a `DefaultServlet` that will serve the static files | ||
from the "Base Resource" location you provided. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
<?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/maven-v4_0_0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<parent> | ||
<groupId>org.eclipse.jetty.examples.embedded</groupId> | ||
<artifactId>jetty-embedded-examples</artifactId> | ||
<version>9.4.x</version> | ||
</parent> | ||
<artifactId>metainf-resources</artifactId> | ||
<version>9.4.x</version> | ||
<packaging>jar</packaging> | ||
<name>Jetty Examples :: Jetty 9.4.x :: Embedded :: Integrating jars with META-INF/resources without WebAppContext</name> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>org.eclipse.jetty</groupId> | ||
<artifactId>jetty-server</artifactId> | ||
<version>${jetty.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.eclipse.jetty</groupId> | ||
<artifactId>jetty-servlet</artifactId> | ||
<version>${jetty.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.webjars</groupId> | ||
<artifactId>bootstrap</artifactId> | ||
<version>5.3.2</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.eclipse.jetty.toolchain</groupId> | ||
<artifactId>jetty-test-helper</artifactId> | ||
<version>${jetty-test-helper.version}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
|
||
</project> |
74 changes: 74 additions & 0 deletions
74
embedded/metainf-resources/src/main/java/examples/MetaInfResourceDemo.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// | ||
// ======================================================================== | ||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others. | ||
// | ||
// This program and the accompanying materials are made available under the | ||
// terms of the Eclipse Public License v. 2.0 which is available at | ||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 | ||
// which is available at https://www.apache.org/licenses/LICENSE-2.0. | ||
// | ||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 | ||
// ======================================================================== | ||
// | ||
|
||
package examples; | ||
|
||
import java.io.IOException; | ||
import java.net.URL; | ||
import java.util.Collections; | ||
import java.util.List; | ||
|
||
import org.eclipse.jetty.server.Server; | ||
import org.eclipse.jetty.server.handler.DefaultHandler; | ||
import org.eclipse.jetty.server.handler.HandlerList; | ||
import org.eclipse.jetty.servlet.DefaultServlet; | ||
import org.eclipse.jetty.servlet.ServletContextHandler; | ||
import org.eclipse.jetty.servlet.ServletHolder; | ||
import org.eclipse.jetty.util.resource.Resource; | ||
import org.eclipse.jetty.util.resource.ResourceCollection; | ||
|
||
public class MetaInfResourceDemo | ||
{ | ||
public static void main(String[] args) throws Exception | ||
{ | ||
Server server = MetaInfResourceDemo.newServer(8080); | ||
server.start(); | ||
server.join(); | ||
} | ||
|
||
public static Server newServer(int port) throws Exception | ||
{ | ||
Server server = new Server(port); | ||
|
||
HandlerList handlers = new HandlerList(); | ||
|
||
ServletContextHandler context = new ServletContextHandler(); | ||
context.setContextPath("/"); | ||
|
||
Resource manifestResources = findManifestResources(MetaInfResourceDemo.class.getClassLoader()); | ||
context.setBaseResource(manifestResources); | ||
|
||
// Add something to serve the static files | ||
// It's named "default" to conform to servlet spec | ||
ServletHolder staticHolder = new ServletHolder("default", DefaultServlet.class); | ||
context.addServlet(staticHolder, "/"); | ||
|
||
handlers.addHandler(context); | ||
handlers.addHandler(new DefaultHandler()); // always last handler | ||
|
||
server.setHandler(handlers); | ||
return server; | ||
} | ||
|
||
private static Resource findManifestResources(ClassLoader classLoader) throws IOException | ||
{ | ||
List<URL> hits = Collections.list(classLoader.getResources("META-INF/resources")); | ||
int size = hits.size(); | ||
Resource[] resources = new Resource[hits.size()]; | ||
for (int i = 0; i < size; i++) | ||
{ | ||
resources[i] = Resource.newResource(hits.get(i)); | ||
} | ||
return new ResourceCollection(resources); | ||
} | ||
} |
3 changes: 3 additions & 0 deletions
3
embedded/metainf-resources/src/main/resources/META-INF/resources/MYREADME.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
This file exists in META-INF/resources/ purely so we can find it during Java runtime execution. | ||
|
||
Be sure you pick a filename that is unique and will not be overwritten by your unpacked dependencies. |
139 changes: 139 additions & 0 deletions
139
embedded/metainf-resources/src/test/java/examples/MetaInfResourceDemoTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
// | ||
// ======================================================================== | ||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others. | ||
// | ||
// This program and the accompanying materials are made available under the | ||
// terms of the Eclipse Public License v. 2.0 which is available at | ||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 | ||
// which is available at https://www.apache.org/licenses/LICENSE-2.0. | ||
// | ||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 | ||
// ======================================================================== | ||
// | ||
|
||
package examples; | ||
|
||
import java.io.IOException; | ||
import java.net.HttpURLConnection; | ||
import java.net.URI; | ||
import java.net.URL; | ||
import java.util.Collections; | ||
import java.util.List; | ||
|
||
import org.eclipse.jetty.server.Server; | ||
import org.eclipse.jetty.util.component.LifeCycle; | ||
import org.eclipse.jetty.util.resource.Resource; | ||
import org.junit.jupiter.api.AfterAll; | ||
import org.junit.jupiter.api.BeforeAll; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
|
||
public class MetaInfResourceDemoTest | ||
{ | ||
public static Server server; | ||
|
||
public static URI serverBaseURI; | ||
|
||
@BeforeAll | ||
public static void initServer() throws Exception | ||
{ | ||
server = MetaInfResourceDemo.newServer(0); | ||
server.start(); | ||
serverBaseURI = server.getURI().resolve("/"); | ||
} | ||
|
||
@AfterAll | ||
public static void stopServer() | ||
{ | ||
LifeCycle.stop(server); | ||
} | ||
|
||
@Test | ||
public void testGetMyReadmeResource() throws Exception | ||
{ | ||
HttpURLConnection http = (HttpURLConnection)serverBaseURI.resolve("/MYREADME.txt").toURL().openConnection(); | ||
http.connect(); | ||
dumpRequestResponse(http); | ||
assertEquals(HttpURLConnection.HTTP_OK, http.getResponseCode()); | ||
assertEquals("text/plain", http.getHeaderField("Content-Type")); | ||
} | ||
|
||
@Test | ||
public void testGetBootStrapResource() throws Exception | ||
{ | ||
String bootstrapFile = findMetaInfResourceFile(MetaInfResourceDemoTest.class.getClassLoader(), "/webjars/bootstrap/", "bootstrap\\.css"); | ||
|
||
HttpURLConnection http = (HttpURLConnection)serverBaseURI.resolve(bootstrapFile).toURL().openConnection(); | ||
http.connect(); | ||
dumpRequestResponse(http); | ||
assertEquals(HttpURLConnection.HTTP_OK, http.getResponseCode()); | ||
assertEquals("text/css", http.getHeaderField("Content-Type")); | ||
} | ||
|
||
/** | ||
* Find the actual version in the jar files, so we don't have to hardcode the version in the testcases. | ||
* | ||
* @param classLoader the classloader to look in | ||
* @param prefix the prefix webjar to look for. | ||
* @param regex the regex to match the first hit against. | ||
* @return the found resource | ||
*/ | ||
private String findMetaInfResourceFile(ClassLoader classLoader, String prefix, String regex) throws IOException | ||
{ | ||
List<URL> hits = Collections.list(classLoader.getResources("META-INF/resources" + prefix)); | ||
for (URL hit : hits) | ||
{ | ||
try (Resource res = Resource.newResource(hit)) | ||
{ | ||
Resource match = findNestedResource(res, regex); | ||
if (match != null) | ||
{ | ||
String rawpath = match.toString(); | ||
int idx; | ||
|
||
// use only part after `!/` | ||
idx = rawpath.lastIndexOf("!/"); | ||
if (idx >= 0) | ||
rawpath = rawpath.substring(idx + 2); | ||
|
||
// find substring starting at prefix | ||
idx = rawpath.indexOf(prefix); | ||
if (idx >= 0) | ||
return rawpath.substring(idx); | ||
return rawpath; | ||
} | ||
} | ||
} | ||
throw new RuntimeException("Unable to find resource [" + regex + "] in " + prefix); | ||
} | ||
|
||
private Resource findNestedResource(Resource res, String regex) throws IOException | ||
{ | ||
for (String content : res.list()) | ||
{ | ||
Resource subresource = res.addPath(content); | ||
if (content.matches(regex)) | ||
return subresource; | ||
if (subresource.isDirectory()) | ||
{ | ||
Resource nested = findNestedResource(subresource, regex); | ||
if (nested != null) | ||
return nested; | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
private static void dumpRequestResponse(HttpURLConnection http) | ||
{ | ||
System.out.println(); | ||
System.out.println("----"); | ||
System.out.printf("%s %s HTTP/1.1%n", http.getRequestMethod(), http.getURL()); | ||
System.out.println("----"); | ||
System.out.printf("%s%n", http.getHeaderField(null)); | ||
http.getHeaderFields().entrySet().stream() | ||
.filter(entry -> entry.getKey() != null) | ||
.forEach((entry) -> System.out.printf("%s: %s%n", entry.getKey(), http.getHeaderField(entry.getKey()))); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters