From 4efdfe79c753ed024724b02070a23053b3fd6a38 Mon Sep 17 00:00:00 2001 From: Ryley Kimmel Date: Fri, 27 Feb 2015 13:11:43 -0500 Subject: [PATCH] Rebase the resource provider; use NIO2 for HttpRequests. --- src/org/apollo/update/HttpRequestWorker.java | 21 +++---- .../apollo/update/JagGrabRequestWorker.java | 11 +--- .../resource/CombinedResourceProvider.java | 7 ++- .../resource/HypertextResourceProvider.java | 58 ++++++++++--------- .../update/resource/ResourceProvider.java | 19 +++--- .../resource/VirtualResourceProvider.java | 49 ++++++++-------- 6 files changed, 86 insertions(+), 79 deletions(-) diff --git a/src/org/apollo/update/HttpRequestWorker.java b/src/org/apollo/update/HttpRequestWorker.java index 5c7e82bb..de3e1954 100644 --- a/src/org/apollo/update/HttpRequestWorker.java +++ b/src/org/apollo/update/HttpRequestWorker.java @@ -9,11 +9,13 @@ import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; -import java.io.File; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Date; +import java.util.Optional; import org.apollo.fs.IndexedFileSystem; import org.apollo.update.resource.CombinedResourceProvider; @@ -21,6 +23,8 @@ import org.apollo.update.resource.HypertextResourceProvider; import org.apollo.update.resource.ResourceProvider; import org.apollo.update.resource.VirtualResourceProvider; +import com.google.common.base.Charsets; + /** * A worker which services HTTP requests. * @@ -31,7 +35,7 @@ public final class HttpRequestWorker extends RequestWorker buf = provider.get(path); - ByteBuf wrapped; HttpResponseStatus status = HttpResponseStatus.OK; - String mime = getMimeType(request.getUri()); - if (buf == null) { + if (!buf.isPresent()) { status = HttpResponseStatus.NOT_FOUND; - wrapped = createErrorPage(status, "The page you requested could not be found."); mime = "text/html"; - } else { - wrapped = Unpooled.wrappedBuffer(buf); } + + ByteBuf wrapped = buf.isPresent() ? Unpooled.wrappedBuffer(buf.get()) : createErrorPage(status, "The page you requested could not be found."); HttpResponse response = new DefaultHttpResponse(request.getProtocolVersion(), status); diff --git a/src/org/apollo/update/JagGrabRequestWorker.java b/src/org/apollo/update/JagGrabRequestWorker.java index f763f7f8..d709ec78 100644 --- a/src/org/apollo/update/JagGrabRequestWorker.java +++ b/src/org/apollo/update/JagGrabRequestWorker.java @@ -1,12 +1,12 @@ package org.apollo.update; -import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.ChannelFutureListener; import java.io.IOException; import java.nio.ByteBuffer; +import java.util.Optional; import org.apollo.fs.IndexedFileSystem; import org.apollo.net.codec.jaggrab.JagGrabRequest; @@ -38,13 +38,8 @@ public final class JagGrabRequestWorker extends RequestWorker buf = provider.get(request.getFilePath()); + buf.ifPresent(buffer -> channel.writeAndFlush(new JagGrabResponse(Unpooled.wrappedBuffer(buffer))).addListener(ChannelFutureListener.CLOSE)); } } \ No newline at end of file diff --git a/src/org/apollo/update/resource/CombinedResourceProvider.java b/src/org/apollo/update/resource/CombinedResourceProvider.java index b2487565..1395c55f 100644 --- a/src/org/apollo/update/resource/CombinedResourceProvider.java +++ b/src/org/apollo/update/resource/CombinedResourceProvider.java @@ -2,13 +2,14 @@ package org.apollo.update.resource; import java.io.IOException; import java.nio.ByteBuffer; +import java.util.Optional; /** * A resource provider composed of multiple resource providers. * * @author Graham */ -public final class CombinedResourceProvider extends ResourceProvider { +public final class CombinedResourceProvider implements ResourceProvider { /** * An array of resource providers. @@ -30,13 +31,13 @@ public final class CombinedResourceProvider extends ResourceProvider { } @Override - public ByteBuffer get(String path) throws IOException { + public Optional get(String path) throws IOException { for (ResourceProvider provider : providers) { if (provider.accept(path)) { return provider.get(path); } } - return null; + return Optional.empty(); } } \ No newline at end of file diff --git a/src/org/apollo/update/resource/HypertextResourceProvider.java b/src/org/apollo/update/resource/HypertextResourceProvider.java index 7b6fed1f..310d0135 100644 --- a/src/org/apollo/update/resource/HypertextResourceProvider.java +++ b/src/org/apollo/update/resource/HypertextResourceProvider.java @@ -1,62 +1,68 @@ package org.apollo.update.resource; -import java.io.File; import java.io.IOException; -import java.io.RandomAccessFile; import java.net.URI; import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; import java.nio.channels.FileChannel.MapMode; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Optional; /** * A {@link ResourceProvider} which provides additional hypertext resources. * * @author Graham */ -public final class HypertextResourceProvider extends ResourceProvider { +public final class HypertextResourceProvider implements ResourceProvider { /** - * The base directory from which documents are served. + * The base {@link Path} from which documents are served. */ - private final File base; + private final Path base; /** - * Creates a new hypertext resource provider with the specified base directory. + * Creates a new hypertext resource provider with the specified base + * directory. * * @param base The base directory. */ - public HypertextResourceProvider(File base) { + public HypertextResourceProvider(Path base) { this.base = base; } @Override public boolean accept(String path) throws IOException { - File file = new File(base, path); - URI target = file.toURI().normalize(); - if (target.toASCIIString().startsWith(base.toURI().normalize().toASCIIString())) { - if (file.isDirectory()) { - file = new File(file, "index.html"); - } - return file.exists(); + Path file = base.resolve(path); + + URI target = file.toUri().normalize(); + if (!target.toASCIIString().startsWith(base.toUri().normalize().toASCIIString())) { + return false; } - return false; + + if (Files.isDirectory(file)) { + file = file.resolve("index.html"); + } + + return Files.exists(file); } @Override - public ByteBuffer get(String path) throws IOException { - File file = new File(base, path); - if (file.isDirectory()) { - file = new File(file, "index.html"); - } - if (!file.exists()) { - return null; + public Optional get(String path) throws IOException { + Path root = base.resolve(path); + + if (Files.isDirectory(root)) { + root = root.resolve("index.html"); } - ByteBuffer buffer; - try (RandomAccessFile raf = new RandomAccessFile(file, "r")) { - buffer = raf.getChannel().map(MapMode.READ_ONLY, 0, raf.length()); + if (!Files.exists(root)) { + return Optional.empty(); } - return buffer; + try (FileChannel channel = FileChannel.open(root)) { + ByteBuffer buf = channel.map(MapMode.READ_ONLY, 0, Files.size(root)); + return Optional.of(buf); + } } } \ No newline at end of file diff --git a/src/org/apollo/update/resource/ResourceProvider.java b/src/org/apollo/update/resource/ResourceProvider.java index f250b90f..5e06d37c 100644 --- a/src/org/apollo/update/resource/ResourceProvider.java +++ b/src/org/apollo/update/resource/ResourceProvider.java @@ -2,30 +2,33 @@ package org.apollo.update.resource; import java.io.IOException; import java.nio.ByteBuffer; +import java.util.Optional; /** * A class which provides resources. * * @author Graham */ -public abstract class ResourceProvider { +public interface ResourceProvider { /** * Checks that this provider can fulfil a request to the specified resource. * * @param path The path to the resource, e.g. {@code /crc}. - * @return {@code true} if the provider can fulfil a request to the resource, {@code false} otherwise. + * @return {@code true} if the provider can fulfil a request to the + * resource, {@code false} otherwise. * @throws IOException If an I/O error occurs. */ - public abstract boolean accept(String path) throws IOException; + public boolean accept(String path) throws IOException; /** - * Gets a resource by its path. + * Returns a resource as a {@link ByteBuffer} if it exists. * - * @param path The path. - * @return The resource, or {@code null} if it doesn't exist. - * @throws IOException If an I/O error occurs. + * @param path The path to the resource. + * @return A {@code ByteBuffer} representation of a resource if it exists + * otherwise {@link Optional#empty()} is returned. + * @throws IOException If some I/O exception occurs. */ - public abstract ByteBuffer get(String path) throws IOException; + public Optional get(String path) throws IOException; } \ No newline at end of file diff --git a/src/org/apollo/update/resource/VirtualResourceProvider.java b/src/org/apollo/update/resource/VirtualResourceProvider.java index 51d76326..f1a9d5de 100644 --- a/src/org/apollo/update/resource/VirtualResourceProvider.java +++ b/src/org/apollo/update/resource/VirtualResourceProvider.java @@ -2,22 +2,25 @@ package org.apollo.update.resource; import java.io.IOException; import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.Optional; import org.apollo.fs.IndexedFileSystem; /** - * A {@link ResourceProvider} which maps virtual resources (such as {@code /media}) to files in an - * {@link IndexedFileSystem}. + * A {@link ResourceProvider} which maps virtual resources (such as + * {@code /media}) to files in an {@link IndexedFileSystem}. * * @author Graham */ -public final class VirtualResourceProvider extends ResourceProvider { +public final class VirtualResourceProvider implements ResourceProvider { /** - * An array of valid prefixes. + * A {@link List} of valid prefixes. */ - private static final String[] VALID_PREFIXES = { "crc", "title", "config", "interface", "media", "versionlist", "textures", - "wordenc", "sounds" }; + private static final List VALID_PREFIXES = Arrays.asList("/crc", "/title", "/config", "/interface", "/media", "/versionlist", "/textures", "/wordenc", "/sounds"); /** * The file system. @@ -26,7 +29,7 @@ public final class VirtualResourceProvider extends ResourceProvider { /** * Creates a new virtual resource provider with the specified file system. - * + * * @param fs The file system. */ public VirtualResourceProvider(IndexedFileSystem fs) { @@ -35,36 +38,34 @@ public final class VirtualResourceProvider extends ResourceProvider { @Override public boolean accept(String path) throws IOException { - for (String prefix : VALID_PREFIXES) { - if (path.startsWith("/" + prefix)) { - return true; - } - } - return false; + Objects.requireNonNull(path); + + return VALID_PREFIXES.stream().anyMatch(path::startsWith); } @Override - public ByteBuffer get(String path) throws IOException { + public Optional get(String path) throws IOException { if (path.startsWith("/crc")) { - return fs.getCrcTable(); + return Optional.of(fs.getCrcTable()); } else if (path.startsWith("/title")) { - return fs.getFile(0, 1); + return Optional.of(fs.getFile(0, 1)); } else if (path.startsWith("/config")) { - return fs.getFile(0, 2); + return Optional.of(fs.getFile(0, 2)); } else if (path.startsWith("/interface")) { - return fs.getFile(0, 3); + return Optional.of(fs.getFile(0, 3)); } else if (path.startsWith("/media")) { - return fs.getFile(0, 4); + return Optional.of(fs.getFile(0, 4)); } else if (path.startsWith("/versionlist")) { - return fs.getFile(0, 5); + return Optional.of(fs.getFile(0, 5)); } else if (path.startsWith("/textures")) { - return fs.getFile(0, 6); + return Optional.of(fs.getFile(0, 6)); } else if (path.startsWith("/wordenc")) { - return fs.getFile(0, 7); + return Optional.of(fs.getFile(0, 7)); } else if (path.startsWith("/sounds")) { - return fs.getFile(0, 8); + return Optional.of(fs.getFile(0, 8)); } - return null; + + return Optional.empty(); } } \ No newline at end of file