MetaFetcher.java
/*
* Copyright 2022 The Sigstore Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.sigstore.tuf;
import static dev.sigstore.json.GsonSupplier.GSON;
import com.google.common.base.Preconditions;
import dev.sigstore.tuf.model.Root;
import dev.sigstore.tuf.model.SignedTufMeta;
import dev.sigstore.tuf.model.TufMeta;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
import java.util.Optional;
import javax.annotation.Nullable;
public class MetaFetcher {
private static final int MAX_META_BYTES = 99 * 1024; // 99 KB
private final Fetcher fetcher;
private MetaFetcher(Fetcher fetcher) {
this.fetcher = fetcher;
}
public static MetaFetcher newFetcher(Fetcher fetcher) {
return new MetaFetcher(fetcher);
}
public String getSource() {
return fetcher.getSource();
}
public Optional<MetaFetchResult<Root>> getRootAtVersion(int version)
throws IOException, FileExceedsMaxLengthException {
String versionFileName = version + ".root.json";
return getMeta(versionFileName, Root.class, null);
}
public <T extends SignedTufMeta<? extends TufMeta>> Optional<MetaFetchResult<T>> getMeta(
String role, Class<T> t) throws IOException, FileExceedsMaxLengthException {
return getMeta(getFileName(role, null), t, null);
}
public <T extends SignedTufMeta<? extends TufMeta>> Optional<MetaFetchResult<T>> getMeta(
String role, int version, Class<T> t, Integer maxSize)
throws IOException, FileExceedsMaxLengthException {
Preconditions.checkArgument(version > 0, "version should be positive, got: %s", version);
return getMeta(getFileName(role, version), t, maxSize);
}
private static String getFileName(String role, @Nullable Integer version) {
return version == null
? role + ".json"
: String.format(Locale.ROOT, "%d.%s.json", version, role);
}
<T extends SignedTufMeta<? extends TufMeta>> Optional<MetaFetchResult<T>> getMeta(
String filename, Class<T> t, Integer maxSize)
throws IOException, FileExceedsMaxLengthException {
byte[] roleBytes = fetcher.fetchResource(filename, maxSize == null ? MAX_META_BYTES : maxSize);
if (roleBytes == null) {
return Optional.empty();
}
var result =
new MetaFetchResult<T>(
roleBytes, GSON.get().fromJson(new String(roleBytes, StandardCharsets.UTF_8), t));
return Optional.of(result);
}
}