Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/9.4.x' into 10.0.x
Browse files Browse the repository at this point in the history
  • Loading branch information
joakime committed Feb 2, 2024
2 parents f06b4a4 + 1182948 commit 1b96cfd
Show file tree
Hide file tree
Showing 8 changed files with 294 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.toolchain.test.FS;
import org.eclipse.jetty.toolchain.test.MavenPaths;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.component.LifeCycle;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
Expand All @@ -41,7 +41,7 @@ public class ResourceHandlerFromFileSystemTest
@BeforeEach
public void startServer() throws Exception
{
Path resourcesRoot = MavenPaths.targetTestDir(ResourceHandlerFromFileSystemTest.class.getSimpleName());
Path resourcesRoot = MavenTestingUtils.getTargetTestingPath(ResourceHandlerFromFileSystemTest.class.getSimpleName());
FS.ensureDirExists(resourcesRoot);

exampleSha = StaticFileGen.generate(resourcesRoot.resolve("example.png"), exampleSize);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.toolchain.test.FS;
import org.eclipse.jetty.toolchain.test.MavenPaths;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.component.LifeCycle;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
Expand All @@ -42,7 +42,7 @@ public class ServletFileServerMultipleLocationsTest
@BeforeEach
public void startServer() throws Exception
{
Path resourcesRoot = MavenPaths.targetTestDir(ServletFileServerMultipleLocations.class.getSimpleName());
Path resourcesRoot = MavenTestingUtils.getTargetTestingPath(ServletFileServerMultipleLocations.class.getSimpleName());
FS.ensureDirExists(resourcesRoot);

exampleSha = StaticFileGen.generate(resourcesRoot.resolve("example.png"), exampleSize);
Expand Down
35 changes: 35 additions & 0 deletions embedded/metainf-resources/README.md
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.

38 changes: 38 additions & 0 deletions embedded/metainf-resources/pom.xml
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>
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);
}
}
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.
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())));
}
}
1 change: 1 addition & 0 deletions embedded/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<module>form-post</module>
<module>http-config</module>
<module>jndi</module>
<module>metainf-resources</module>
<module>redirect</module>
<module>rewrite</module>
<module>servlet-config</module>
Expand Down

0 comments on commit 1b96cfd

Please sign in to comment.