дробим проект на субмодули
This commit is contained in:
5
mirror-app/build.gradle
Normal file
5
mirror-app/build.gradle
Normal file
@@ -0,0 +1,5 @@
|
||||
apply plugin: 'java-library'
|
||||
|
||||
dependencies {
|
||||
api("com.squareup.okhttp3:okhttp:${okhttpVersion}")
|
||||
}
|
||||
12
mirror-app/src/main/java/ru/di9/mirror/app/Utils.java
Normal file
12
mirror-app/src/main/java/ru/di9/mirror/app/Utils.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package ru.di9.mirror.app;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public final class Utils {
|
||||
|
||||
public static boolean isEmptyString(String string) {
|
||||
return string == null || string.isEmpty() || string.isBlank();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package ru.di9.mirror.app.domain;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
public record FileRecord(String name, long size, InputStream inputStream) {
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package ru.di9.mirror.app.domain;
|
||||
|
||||
public record PathRecord(String name, PathType type) {
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package ru.di9.mirror.app.domain;
|
||||
|
||||
public enum PathType {
|
||||
FILE, DIRECTORY
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package ru.di9.mirror.app.domain;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record WalkerResult(PathType pathType, FileRecord fileRecord, List<PathRecord> filesList) {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package ru.di9.mirror.app.service;
|
||||
|
||||
import ru.di9.mirror.app.Utils;
|
||||
import ru.di9.mirror.app.domain.FileRecord;
|
||||
import ru.di9.mirror.app.domain.PathRecord;
|
||||
import ru.di9.mirror.app.domain.PathType;
|
||||
import ru.di9.mirror.app.domain.WalkerResult;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class FileStorageService implements StorageService {
|
||||
|
||||
private final Path storagePath;
|
||||
|
||||
public FileStorageService(String storagePath) {
|
||||
this.storagePath = Paths.get(storagePath).resolve("local");
|
||||
}
|
||||
|
||||
@SuppressWarnings("java:S112")
|
||||
@Override
|
||||
public Optional<FileRecord> getFile(String path) {
|
||||
Path fullPath = storageResolve(path);
|
||||
|
||||
if (Files.notExists(fullPath)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
try {
|
||||
return Optional.of(new FileRecord(
|
||||
fullPath.toFile().getName(),
|
||||
Files.size(fullPath),
|
||||
Files.newInputStream(fullPath)
|
||||
));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("java:S112")
|
||||
@Override
|
||||
public void putFile(String path, InputStream inputStream) {
|
||||
Path fullPath = storageResolve(path);
|
||||
try {
|
||||
Files.createDirectories(fullPath.getParent());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
try (OutputStream outputStream = Files.newOutputStream(fullPath)) {
|
||||
byte[] buff = new byte[8 * 1024];
|
||||
int len;
|
||||
while ((len = inputStream.read(buff)) > 0) {
|
||||
outputStream.write(buff, 0, len);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("java:S112")
|
||||
@Override
|
||||
public Optional<WalkerResult> walker(String path) {
|
||||
Path fullPath = storageResolve(path);
|
||||
|
||||
if (Files.notExists(fullPath)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
if (Files.isDirectory(fullPath)) {
|
||||
final List<PathRecord> list = new ArrayList<>();
|
||||
|
||||
try (Stream<Path> walk = Files.walk(fullPath, 1)) {
|
||||
walk.skip(1).forEach(path1 -> list.add(new PathRecord(
|
||||
path1.getFileName().toString(),
|
||||
Files.isDirectory(path1) ? PathType.DIRECTORY : PathType.FILE)));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return Optional.of(new WalkerResult(PathType.DIRECTORY, null, list));
|
||||
} else {
|
||||
try {
|
||||
var fileRecord = new FileRecord(
|
||||
fullPath.getFileName().toString(),
|
||||
Files.size(fullPath),
|
||||
Files.newInputStream(fullPath)
|
||||
);
|
||||
|
||||
return Optional.of(new WalkerResult(PathType.FILE, fileRecord, null));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Path storageResolve(String httpPath) {
|
||||
if (Utils.isEmptyString(httpPath)) {
|
||||
return storagePath;
|
||||
} else {
|
||||
return storagePath.resolve(httpPath.substring(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package ru.di9.mirror.app.service;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import ru.di9.mirror.app.domain.FileRecord;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
public class MavenCentralStorageService extends MirrorService {
|
||||
|
||||
private static final String MAVEN_CENTRAL_URL = "https://repo1.maven.org/maven2";
|
||||
private final OkHttpClient okHttpClient;
|
||||
|
||||
public MavenCentralStorageService(OkHttpClient okHttpClient) {
|
||||
this.okHttpClient = okHttpClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public Optional<FileRecord> getFile(String path) {
|
||||
Request request = new Request.Builder()
|
||||
.url(MAVEN_CENTRAL_URL + path)
|
||||
.build();
|
||||
|
||||
Response response = okHttpClient.newCall(request).execute();
|
||||
if (!response.isSuccessful()) {
|
||||
if (response.code() == 404) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
throw new IOException("Unexpected code " + response);
|
||||
}
|
||||
|
||||
return Optional.of(new FileRecord(
|
||||
path,
|
||||
Long.parseLong(Objects.requireNonNull(response.header("Content-Length"))),
|
||||
Objects.requireNonNull(response.body()).byteStream()
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package ru.di9.mirror.app.service;
|
||||
|
||||
import ru.di9.mirror.app.domain.WalkerResult;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Optional;
|
||||
|
||||
public abstract class MirrorService implements StorageService{
|
||||
|
||||
@Override
|
||||
public void putFile(String path, InputStream inputStream) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<WalkerResult> walker(String path) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package ru.di9.mirror.app.service;
|
||||
|
||||
import ru.di9.mirror.app.domain.FileRecord;
|
||||
import ru.di9.mirror.app.domain.WalkerResult;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@SuppressWarnings("ClassCanBeRecord")
|
||||
public class MirroredStorageService implements StorageService {
|
||||
|
||||
private final FileStorageService fileStorageService;
|
||||
private final List<MirrorService> mirrors;
|
||||
|
||||
public MirroredStorageService(FileStorageService fileStorageService,
|
||||
List<MirrorService> mirrors) {
|
||||
this.fileStorageService = fileStorageService;
|
||||
this.mirrors = mirrors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<FileRecord> getFile(String path) {
|
||||
Optional<FileRecord> optional;
|
||||
|
||||
optional = fileStorageService.getFile(path);
|
||||
if (optional.isPresent()) {
|
||||
return optional;
|
||||
}
|
||||
|
||||
for (StorageService mirror : mirrors) {
|
||||
optional = mirror.getFile(path);
|
||||
if (optional.isPresent()) {
|
||||
FileRecord fileRecord = optional.get();
|
||||
fileStorageService.putFile(fileRecord.name(), fileRecord.inputStream());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return fileStorageService.getFile(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putFile(String path, InputStream inputStream) {
|
||||
fileStorageService.putFile(path, inputStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<WalkerResult> walker(String path) {
|
||||
return fileStorageService.walker(path);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package ru.di9.mirror.app.service;
|
||||
|
||||
import ru.di9.mirror.app.domain.FileRecord;
|
||||
import ru.di9.mirror.app.domain.WalkerResult;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface StorageService {
|
||||
|
||||
Optional<FileRecord> getFile(String path);
|
||||
|
||||
void putFile(String path, InputStream inputStream);
|
||||
|
||||
Optional<WalkerResult> walker(String path);
|
||||
}
|
||||
Reference in New Issue
Block a user