Skip to content

Commit

Permalink
more work
Browse files Browse the repository at this point in the history
  • Loading branch information
kashike committed Jan 19, 2024
1 parent bbcc879 commit 9ce2a96
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 131 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@
package io.papermc.bibliothek;

import io.papermc.bibliothek.configuration.AppConfiguration;
import io.papermc.bibliothek.configuration.StorageConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.ServletComponentScan;

@EnableConfigurationProperties({
AppConfiguration.class
AppConfiguration.class,
StorageConfiguration.class
})
@SpringBootApplication
@ServletComponentScan
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,69 +23,15 @@
*/
package io.papermc.bibliothek.configuration;

import jakarta.validation.constraints.NotNull;
import java.net.URL;
import java.nio.file.Path;
import org.jetbrains.annotations.Nullable;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;

@ConfigurationProperties(prefix = "app")
@Validated
public class AppConfiguration {
private URL apiBaseUrl;
private String apiTitle;
private String apiVersion;
private @NotNull Path storagePath;
private String cdnUrl;

@SuppressWarnings("checkstyle:MethodName")
public URL getApiBaseUrl() {
return this.apiBaseUrl;
}

@SuppressWarnings("checkstyle:MethodName")
public void setApiBaseUrl(final URL apiBaseUrl) {
this.apiBaseUrl = apiBaseUrl;
}

@SuppressWarnings("checkstyle:MethodName")
public String getApiTitle() {
return this.apiTitle;
}

@SuppressWarnings("checkstyle:MethodName")
public void setApiTitle(final String apiTitle) {
this.apiTitle = apiTitle;
}

@SuppressWarnings("checkstyle:MethodName")
public String getApiVersion() {
return this.apiVersion;
}

@SuppressWarnings("checkstyle:MethodName")
public void setApiVersion(final String apiVersion) {
this.apiVersion = apiVersion;
}

@SuppressWarnings("checkstyle:MethodName")
public Path getStoragePath() {
return this.storagePath;
}

@SuppressWarnings("checkstyle:MethodName")
public void setStoragePath(final Path storagePath) {
this.storagePath = storagePath;
}

@SuppressWarnings("checkstyle:MethodName")
public @Nullable String getCdnUrl() {
return this.cdnUrl;
}

@SuppressWarnings("checkstyle:MethodName")
public void setCdnUrl(final String cdnUrl) {
this.cdnUrl = cdnUrl;
}
public record AppConfiguration(
URL apiBaseUrl,
String apiTitle,
String apiVersion
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ OpenAPI openAPI(final AppConfiguration configuration) {
final OpenAPI api = new OpenAPI();
api.info(
new Info()
.title(configuration.getApiTitle())
.version(configuration.getApiVersion())
.title(configuration.apiTitle())
.version(configuration.apiVersion())
);
final URL apiBaseUrl = configuration.getApiBaseUrl();
final URL apiBaseUrl = configuration.apiBaseUrl();
if (apiBaseUrl != null) {
api.servers(List.of(new Server().url(apiBaseUrl.toExternalForm())));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* This file is part of bibliothek, licensed under the MIT License.
*
* Copyright (c) 2019-2023 PaperMC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.papermc.bibliothek.configuration;

import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import java.nio.file.Path;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;

@ConfigurationProperties(prefix = "app.storage")
@Validated
public record StorageConfiguration(
@NotNull Path cache,
@NotEmpty List<Source> sources
) {
public record Source(
String name,
Type type,
String value
) {
public enum Type {
LOCAL,
REMOTE;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
*/
package io.papermc.bibliothek.controller.v2;

import io.papermc.bibliothek.configuration.AppConfiguration;
import io.papermc.bibliothek.database.model.Build;
import io.papermc.bibliothek.database.model.Project;
import io.papermc.bibliothek.database.model.Version;
Expand All @@ -35,6 +34,7 @@
import io.papermc.bibliothek.exception.DownloadNotFound;
import io.papermc.bibliothek.exception.ProjectNotFound;
import io.papermc.bibliothek.exception.VersionNotFound;
import io.papermc.bibliothek.service.DownloadService;
import io.papermc.bibliothek.util.HTTP;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
Expand All @@ -43,17 +43,13 @@
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import jakarta.validation.constraints.Pattern;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Duration;
import java.util.Map;
import java.util.function.BiFunction;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.AbstractResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.CacheControl;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
Expand All @@ -69,22 +65,22 @@
@SuppressWarnings("checkstyle:FinalClass")
public class DownloadController {
private static final CacheControl CACHE = HTTP.sMaxAgePublicCache(Duration.ofDays(7));
private final AppConfiguration configuration;
private final ProjectCollection projects;
private final VersionCollection versions;
private final BuildCollection builds;
private final DownloadService service;

@Autowired
private DownloadController(
final AppConfiguration configuration,
final ProjectCollection projects,
final VersionCollection versions,
final BuildCollection builds
final BuildCollection builds,
final DownloadService service
) {
this.configuration = configuration;
this.projects = projects;
this.versions = versions;
this.builds = builds;
this.service = service;
}

@ApiResponse(
Expand Down Expand Up @@ -137,20 +133,12 @@ public ResponseEntity<?> download(
final Version version = this.versions.findByProjectAndName(project._id(), versionName).orElseThrow(VersionNotFound::new);
final Build build = this.builds.findByProjectAndVersionAndNumber(project._id(), version._id(), buildNumber).orElseThrow(BuildNotFound::new);

for (final Map.Entry<String, Build.Download> download : build.downloads().entrySet()) {
if (download.getValue().name().equals(downloadName)) {
for (final Map.Entry<String, Build.Download> entry : build.downloads().entrySet()) {
final Build.Download download = entry.getValue();
if (download.name().equals(downloadName)) {
try {
return JavaArchive.resolve(
this.configuration,
download.getValue(),
(cdn, file) -> URI.create(String.format("%s/%s/%s/%d/%s", cdn, project.name(), version.name(), build.number(), file.name())),
(path, file) -> path
.resolve(project.name())
.resolve(version.name())
.resolve(String.valueOf(build.number()))
.resolve(file.name()),
CACHE
);
final Path path = this.service.resolve(project, version, build, download);
return JavaArchive.forPath(download, path, CACHE);
} catch (final IOException e) {
throw new DownloadFailed(e);
}
Expand All @@ -160,52 +148,7 @@ public ResponseEntity<?> download(
}

private static class JavaArchive extends ResponseEntity<AbstractResource> {
public static JavaArchive resolve(
final AppConfiguration config,
final Build.Download download,
final BiFunction<String, Build.Download, URI> cdnGetter,
final BiFunction<Path, Build.Download, Path> localGetter,
final CacheControl cache
) throws IOException {
@Nullable IOException cdnException = null;
final @Nullable String cdnUrl = config.getCdnUrl();
if (cdnUrl != null) {
final @Nullable URI cdn = cdnGetter.apply(cdnUrl, download);
if (cdn != null) {
try {
return forUrl(download, cdn, cache);
} catch (final IOException e) {
cdnException = e;
}
}
}
@Nullable IOException localException = null;
final @Nullable Path local = localGetter.apply(config.getStoragePath(), download);
if (local != null) {
try {
return forPath(download, local, cache);
} catch (final IOException e) {
localException = e;
}
}
final IOException exception = new IOException("Could not resolve download via CDN or Local Storage");
if (cdnException != null) {
exception.addSuppressed(cdnException);
}
if (localException != null) {
exception.addSuppressed(localException);
}
throw exception;
}

private static JavaArchive forUrl(final Build.Download download, final URI uri, final CacheControl cache) throws IOException {
final UrlResource resource = new UrlResource(uri);
final HttpHeaders headers = headersFor(download, cache);
headers.setLastModified(resource.lastModified());
return new JavaArchive(resource, headers);
}

private static JavaArchive forPath(final Build.Download download, final Path path, final CacheControl cache) throws IOException {
static JavaArchive forPath(final Build.Download download, final Path path, final CacheControl cache) throws IOException {
final FileSystemResource resource = new FileSystemResource(path);
final HttpHeaders headers = headersFor(download, cache);
headers.setLastModified(Files.getLastModifiedTime(path).toInstant());
Expand Down
Loading

0 comments on commit 9ce2a96

Please sign in to comment.