Skip to content

Commit

Permalink
Use AutoCloseable TempFile
Browse files Browse the repository at this point in the history
Added AutoCloseable TempFile, so that a created file is always deleted after use.
  • Loading branch information
amvanbaren committed Apr 6, 2023
1 parent c5e7a7e commit 238e161
Show file tree
Hide file tree
Showing 21 changed files with 204 additions and 306 deletions.
39 changes: 17 additions & 22 deletions server/src/main/java/org/eclipse/openvsx/ExtensionProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,37 +9,32 @@
********************************************************************************/
package org.eclipse.openvsx;

import java.io.EOFException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.MissingNode;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;

import org.apache.commons.codec.digest.DigestUtils;
import org.eclipse.openvsx.entities.ExtensionVersion;
import org.eclipse.openvsx.entities.FileResource;
import org.eclipse.openvsx.util.ArchiveUtil;
import org.eclipse.openvsx.util.ErrorResultException;
import org.eclipse.openvsx.util.LicenseDetection;
import org.eclipse.openvsx.util.TargetPlatform;
import org.eclipse.openvsx.util.*;
import org.elasticsearch.common.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.util.Pair;

import java.io.EOFException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

/**
* Processes uploaded extension files and extracts their metadata.
*/
Expand All @@ -55,12 +50,12 @@ public class ExtensionProcessor implements AutoCloseable {

protected final Logger logger = LoggerFactory.getLogger(ExtensionProcessor.class);

private final Path extensionFile;
private final TempFile extensionFile;
private ZipFile zipFile;
private JsonNode packageJson;
private JsonNode vsixManifest;

public ExtensionProcessor(Path extensionFile) {
public ExtensionProcessor(TempFile extensionFile) {
this.extensionFile = extensionFile;
}

Expand All @@ -80,7 +75,7 @@ private void readInputStream() {
return;
}
try {
zipFile = new ZipFile(extensionFile.toFile());
zipFile = new ZipFile(extensionFile.getPath().toFile());
} catch (ZipException exc) {
throw new ErrorResultException("Could not read zip file: " + exc.getMessage());
} catch (EOFException exc) {
Expand Down Expand Up @@ -357,7 +352,7 @@ public String getBinaryName(ExtensionVersion extVersion) {

public FileResource generateSha256Checksum(ExtensionVersion extVersion) {
String hash = null;
try(var input = Files.newInputStream(extensionFile)) {
try(var input = Files.newInputStream(extensionFile.getPath())) {
hash = DigestUtils.sha256Hex(input);
} catch (IOException e) {
logger.error("Failed to read extensionFile", e);
Expand Down
12 changes: 6 additions & 6 deletions server/src/main/java/org/eclipse/openvsx/ExtensionService.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDateTime;
import java.util.LinkedHashSet;

Expand All @@ -28,6 +27,7 @@
import org.eclipse.openvsx.repositories.RepositoryService;
import org.eclipse.openvsx.search.SearchUtilService;
import org.eclipse.openvsx.util.ErrorResultException;
import org.eclipse.openvsx.util.TempFile;
import org.eclipse.openvsx.util.TimeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
Expand Down Expand Up @@ -55,7 +55,7 @@ public class ExtensionService {
boolean requireLicense;

@Transactional
public ExtensionVersion mirrorVersion(Path extensionFile, PersonalAccessToken token, String binaryName, String timestamp) {
public ExtensionVersion mirrorVersion(TempFile extensionFile, PersonalAccessToken token, String binaryName, String timestamp) {
var download = doPublish(extensionFile, token, TimeUtil.fromUTCString(timestamp), false);
publishHandler.mirror(download, extensionFile);
download.setName(binaryName);
Expand All @@ -69,7 +69,7 @@ public ExtensionVersion publishVersion(InputStream content, PersonalAccessToken
return download.getExtension();
}

private FileResource doPublish(Path extensionFile, PersonalAccessToken token, LocalDateTime timestamp, boolean checkDependencies) {
private FileResource doPublish(TempFile extensionFile, PersonalAccessToken token, LocalDateTime timestamp, boolean checkDependencies) {
try (var processor = new ExtensionProcessor(extensionFile)) {
var extVersion = publishHandler.createExtensionVersion(processor, token, timestamp, checkDependencies);
if (requireLicense) {
Expand All @@ -82,16 +82,16 @@ private FileResource doPublish(Path extensionFile, PersonalAccessToken token, Lo
}
}

private Path createExtensionFile(InputStream content) {
private TempFile createExtensionFile(InputStream content) {
try (var input = new BufferedInputStream(content)) {
input.mark(0);
var skipped = input.skip(MAX_CONTENT_SIZE + 1);
if (skipped > MAX_CONTENT_SIZE) {
throw new ErrorResultException("The extension package exceeds the size limit of 512 MB.", HttpStatus.PAYLOAD_TOO_LARGE);
}

var extensionFile = Files.createTempFile("extension_", ".vsix");
try(var out = Files.newOutputStream(extensionFile)) {
var extensionFile = new TempFile("extension_", ".vsix");
try(var out = Files.newOutputStream(extensionFile.getPath())) {
input.reset();
input.transferTo(out);
}
Expand Down
10 changes: 2 additions & 8 deletions server/src/main/java/org/eclipse/openvsx/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -241,10 +241,10 @@ public ResultJson updateNamespaceDetails(NamespaceDetailsJson details) {
}

boolean contentEquals;
var oldLogo = storageUtil.downloadNamespaceLogo(namespace);
try (
var oldLogo = storageUtil.downloadNamespaceLogo(namespace);
var newLogoInput = new ByteArrayInputStream(details.logoBytes);
var oldLogoInput = Files.newInputStream(oldLogo)
var oldLogoInput = Files.newInputStream(oldLogo.getPath())
) {
contentEquals = IOUtils.contentEquals(newLogoInput, oldLogoInput);
} catch (IOException e) {
Expand All @@ -268,12 +268,6 @@ public ResultJson updateNamespaceDetails(NamespaceDetailsJson details) {
}
}

try {
Files.delete(oldLogo);
} catch (IOException e) {
throw new RuntimeException(e);
}

return ResultJson.success("Updated details for namespace " + details.name);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,11 @@ public void run(MigrationJobRequest jobRequest) throws Exception {

service.deleteResources(extVersion);
var entry = migrations.getDownload(extVersion);
var extensionFile = migrations.getExtensionFile(entry);
var download = entry.getKey();
try(var extProcessor = new ExtensionProcessor(extensionFile)) {
try(
var extensionFile = migrations.getExtensionFile(entry);
var extProcessor = new ExtensionProcessor(extensionFile);
) {
extProcessor.processEachResource(download.getExtension(), (resource) -> {
resource.setStorageType(download.getStorageType());
migrations.uploadFileResource(resource);
Expand All @@ -52,6 +54,5 @@ public void run(MigrationJobRequest jobRequest) throws Exception {
}

service.deleteWebResources(extVersion);
Files.delete(extensionFile);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.nio.file.Files;
import java.util.AbstractMap;

@Component
Expand All @@ -46,14 +45,14 @@ public void run(MigrationJobRequest jobRequest) throws Exception {
}

var content = migrations.getContent(download);
var extensionFile = migrations.getExtensionFile(new AbstractMap.SimpleEntry<>(download, content));
try(var extProcessor = new ExtensionProcessor(extensionFile)) {
try(
var extensionFile = migrations.getExtensionFile(new AbstractMap.SimpleEntry<>(download, content));
var extProcessor = new ExtensionProcessor(extensionFile)
) {
var vsixManifest = extProcessor.getVsixManifest(extVersion);
vsixManifest.setStorageType(download.getStorageType());
migrations.uploadFileResource(vsixManifest);
migrations.persistFileResource(vsixManifest);
}

Files.delete(extensionFile);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,22 +49,20 @@ public void run(MigrationJobRequest jobRequest) throws Exception {
var download = migrations.getResource(jobRequest);
var extVersion = download.getExtension();
var content = migrations.getContent(download);
var extensionFile = migrations.getExtensionFile(new AbstractMap.SimpleEntry<>(download, content));

boolean fixTargetPlatform;
try(var extProcessor = new ExtensionProcessor(extensionFile)) {
fixTargetPlatform = !extProcessor.getMetadata().getTargetPlatform().equals(extVersion.getTargetPlatform());
}
try (var extensionFile = migrations.getExtensionFile(new AbstractMap.SimpleEntry<>(download, content))) {
boolean fixTargetPlatform;
try (var extProcessor = new ExtensionProcessor(extensionFile)) {
fixTargetPlatform = !extProcessor.getMetadata().getTargetPlatform().equals(extVersion.getTargetPlatform());
}

if(fixTargetPlatform) {
logger.info("Fixing target platform for: {}.{}-{}@{}", extVersion.getExtension().getNamespace().getName(), extVersion.getExtension().getName(), extVersion.getVersion(), extVersion.getTargetPlatform());
deleteExtension(extVersion);
try (var input = Files.newInputStream(extensionFile)) {
extensions.publishVersion(input, extVersion.getPublishedWith());
if (fixTargetPlatform) {
logger.info("Fixing target platform for: {}.{}-{}@{}", extVersion.getExtension().getNamespace().getName(), extVersion.getExtension().getName(), extVersion.getVersion(), extVersion.getTargetPlatform());
deleteExtension(extVersion);
try (var input = Files.newInputStream(extensionFile.getPath())) {
extensions.publishVersion(input, extVersion.getPublishedWith());
}
}
}

Files.delete(extensionFile);
}

private void deleteExtension(ExtensionVersion extVersion) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ public void run(MigrationJobRequest jobRequest) throws Exception {
}

var content = migrations.getContent(download);
var extensionFile = migrations.getExtensionFile(new AbstractMap.SimpleEntry<>(download, content));
try(var extProcessor = new ExtensionProcessor(extensionFile)) {
try(
var extensionFile = migrations.getExtensionFile(new AbstractMap.SimpleEntry<>(download, content));
var extProcessor = new ExtensionProcessor(extensionFile)
) {
var checksum = extProcessor.generateSha256Checksum(extVersion);
checksum.setStorageType(download.getStorageType());
migrations.uploadFileResource(checksum);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.eclipse.openvsx.storage.AzureBlobStorageService;
import org.eclipse.openvsx.storage.GoogleCloudStorageService;
import org.eclipse.openvsx.storage.IStorageService;
import org.eclipse.openvsx.util.TempFile;
import org.jobrunr.jobs.lambdas.JobRequestHandler;
import org.jobrunr.scheduling.JobRequestScheduler;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -29,7 +30,6 @@
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.AbstractMap;
import java.util.Map;
import java.util.UUID;
Expand Down Expand Up @@ -73,32 +73,23 @@ public FileResource getResource(MigrationJobRequest jobRequest) {
}

@Retryable
public Path getExtensionFile(Map.Entry<FileResource, byte[]> entry) {
Path extensionFile;
try {
extensionFile = Files.createTempFile("extension_", ".vsix");
} catch (IOException e) {
throw new RuntimeException("Failed to create extension file", e);
}
public TempFile getExtensionFile(Map.Entry<FileResource, byte[]> entry) throws IOException {
var extensionFile = new TempFile("migration-extension_", ".vsix");

var content = entry.getValue();
if(content == null) {
var download = entry.getKey();
var storage = getStorage(download);
var uri = storage.getLocation(download);
backgroundRestTemplate.execute("{extensionLocation}", HttpMethod.GET, null, response -> {
try(var out = Files.newOutputStream(extensionFile)) {
try(var out = Files.newOutputStream(extensionFile.getPath())) {
response.getBody().transferTo(out);
}

return extensionFile;
}, Map.of("extensionLocation", uri.toString()));
} else {
try {
Files.write(extensionFile, content);
} catch (IOException e) {
throw new RuntimeException("Failed to write to extension file", e);
}
Files.write(extensionFile.getPath(), content);
}

return extensionFile;
Expand All @@ -116,7 +107,7 @@ public void uploadFileResource(FileResource resource) {
}

@Retryable
public void uploadFileResource(FileResource resource, Path extensionFile) {
public void uploadFileResource(FileResource resource, TempFile extensionFile) {
if(resource.getStorageType().equals(FileResource.STORAGE_DB)) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,15 @@ public void run(MigrationJobRequest jobRequest) throws Exception {

logger.info("Renaming download {}", download.getName());
var content = migrations.getContent(download);
var extensionFile = migrations.getExtensionFile(new AbstractMap.SimpleEntry<>(download, content));
var newDownload = service.cloneResource(download, name);
migrations.uploadFileResource(newDownload, extensionFile);
migrations.removeFile(download);

download.setName(name);
service.updateResource(download);
Files.delete(extensionFile);
try(var extensionFile = migrations.getExtensionFile(new AbstractMap.SimpleEntry<>(download, content))) {
var newDownload = service.cloneResource(download, name);
migrations.uploadFileResource(newDownload, extensionFile);
migrations.removeFile(download);

download.setName(name);
service.updateResource(download);
}

logger.info("Updated download name to: {}", name);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.nio.file.Files;

@Component
@ConditionalOnProperty(value = "ovsx.data.mirror.enabled", havingValue = "false", matchIfMissing = true)
public class SetPreReleaseJobRequestHandler implements JobRequestHandler<MigrationJobRequest> {

protected final Logger logger = new JobRunrDashboardLogger(LoggerFactory.getLogger(ExtractResourcesJobRequestHandler.class));

@Autowired
MigrationService migrations;

@Autowired
SetPreReleaseJobService service;

Expand All @@ -34,10 +35,10 @@ public class SetPreReleaseJobRequestHandler implements JobRequestHandler<Migrati
public void run(MigrationJobRequest jobRequest) throws Exception {
var extVersions = service.getExtensionVersions(jobRequest, logger);
for(var extVersion : extVersions) {
var entry = service.getDownload(extVersion);
var extensionFile = service.getExtensionFile(entry);
service.updatePreviewAndPreRelease(extVersion, extensionFile);
Files.delete(extensionFile);
var entry = migrations.getDownload(extVersion);
try (var extensionFile = migrations.getExtensionFile(entry)) {
service.updatePreviewAndPreRelease(extVersion, extensionFile);
}
}
}
}
Loading

0 comments on commit 238e161

Please sign in to comment.