MemoryResource (#8451)

Added MemoryResource to simplify favicon and similar handling
This commit is contained in:
Greg Wilkins 2022-08-12 10:36:23 +10:00 committed by GitHub
parent 7d2f9fa3c0
commit e249d39427
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 166 additions and 5 deletions

View File

@ -671,12 +671,10 @@ public class Server extends Handler.Wrapper implements Attributes
*/
private Resource newResource(String name)
{
// TODO replace this. It is needlessly complex and inefficient as it holds a mount of the server jar
// just for things like favicon and default stylesheet
URL url = getClass().getResource(name);
if (url == null)
throw new IllegalStateException("Missing server resource: " + name);
return ResourceFactory.of(this).newResource(URI.create(url.toExternalForm()));
return ResourceFactory.root().newMemoryResource(url);
}
@Override

View File

@ -29,7 +29,9 @@ import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class DefaultHandlerTest
@ -134,6 +136,9 @@ public class DefaultHandlerTest
assertEquals(HttpStatus.OK_200, response.getStatus());
assertEquals("image/x-icon", response.get(HttpHeader.CONTENT_TYPE));
byte[] bytes = response.getContentBytes();
assertThat(bytes, notNullValue());
assertThat(bytes.length, greaterThan(0));
}
}
}

View File

@ -0,0 +1,113 @@
//
// ========================================================================
// Copyright (c) 1995-2022 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 org.eclipse.jetty.util.resource;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.file.Path;
import java.util.Objects;
import org.eclipse.jetty.util.IO;
/**
* <p>An in memory Resource created from a {@link URL}</p>
*/
public class MemoryResource extends Resource
{
private final URI _uri;
private final long _created = System.currentTimeMillis();
private final byte[] _bytes;
MemoryResource(URL url)
{
try
{
_uri = Objects.requireNonNull(url).toURI();
try (InputStream in = url.openStream())
{
_bytes = IO.readBytes(in);
}
}
catch (IOException | URISyntaxException e)
{
throw new RuntimeException(e);
}
}
@Override
public Path getPath()
{
return Path.of(_uri);
}
@Override
public boolean isContainedIn(Resource r)
{
return getPath().startsWith(r.getPath());
}
@Override
public URI getURI()
{
return _uri;
}
@Override
public String getName()
{
return getPath().toAbsolutePath().toString();
}
@Override
public long lastModified()
{
return _created;
}
@Override
public long length()
{
return _bytes.length;
}
@Override
public InputStream newInputStream() throws IOException
{
return new ByteArrayInputStream(_bytes);
}
@Override
public ReadableByteChannel newReadableByteChannel() throws IOException
{
return Channels.newChannel(newInputStream());
}
@Override
public boolean exists()
{
return true;
}
@Override
public String toString()
{
return getName();
}
}

View File

@ -275,6 +275,8 @@ public abstract class Resource
*/
public List<String> list() // TODO: should return Path's
{
if (!isDirectory())
return null;
try (DirectoryStream<Path> dir = Files.newDirectoryStream(getPath()))
{
List<String> entries = new ArrayList<>();

View File

@ -104,8 +104,6 @@ public interface ResourceFactory
* Find a classpath resource.
* The {@link Class#getResource(String)} method is used to lookup the resource. If it is not
* found, then the {@link Loader#getResource(String)} method is used.
* If it is still not found, then {@link ClassLoader#getSystemResource(String)} is used.
* Unlike {@link ClassLoader#getSystemResource(String)} this method does not check for normal resources.
*
* @param resource the relative name of the resource
* @return Resource or null
@ -129,6 +127,17 @@ public interface ResourceFactory
}
}
/**
* Load a URL into a memory resource.
* @param url the URL to load into memory
* @return Resource or null
* @see #newClassPathResource(String)
*/
default Resource newMemoryResource(URL url)
{
return new MemoryResource(url);
}
/**
* Construct a resource from a string.
*

View File

@ -0,0 +1,34 @@
//
// ========================================================================
// Copyright (c) 1995-2022 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 org.eclipse.jetty.util.resource;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.Loader;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class MemoryResourceTest
{
@Test
public void testJettyLogging() throws Exception
{
Resource resource = ResourceFactory.root().newMemoryResource(Loader.getResource("jetty-logging.properties"));
assertTrue(resource.exists());
String contents = IO.toString(resource.newInputStream());
assertThat(contents, startsWith("#org.eclipse.jetty.util.LEVEL=DEBUG"));
}
}