Browse Source

Switched ArbitraryDataFile.filePath from String to Path

qdn
CalDescent 3 years ago
parent
commit
51b12567e8
  1. 78
      src/main/java/org/qortal/arbitrary/ArbitraryDataFile.java
  2. 3
      src/main/java/org/qortal/arbitrary/ArbitraryDataFileChunk.java
  3. 4
      src/main/java/org/qortal/arbitrary/ArbitraryDataReader.java
  4. 2
      src/main/java/org/qortal/arbitrary/ArbitraryDataWriter.java

78
src/main/java/org/qortal/arbitrary/ArbitraryDataFile.java

@ -48,7 +48,7 @@ public class ArbitraryDataFile {
FILE_HASH, FILE_HASH,
TRANSACTION_DATA, TRANSACTION_DATA,
NAME NAME
}; }
private static final Logger LOGGER = LogManager.getLogger(ArbitraryDataFile.class); private static final Logger LOGGER = LogManager.getLogger(ArbitraryDataFile.class);
@ -56,7 +56,7 @@ public class ArbitraryDataFile {
public static final int CHUNK_SIZE = 1 * 1024 * 1024; // 1MiB public static final int CHUNK_SIZE = 1 * 1024 * 1024; // 1MiB
public static int SHORT_DIGEST_LENGTH = 8; public static int SHORT_DIGEST_LENGTH = 8;
protected String filePath; protected Path filePath;
protected String hash58; protected String hash58;
private ArrayList<ArbitraryDataFileChunk> chunks; private ArrayList<ArbitraryDataFileChunk> chunks;
private byte[] secret; private byte[] secret;
@ -80,8 +80,8 @@ public class ArbitraryDataFile {
this.hash58 = Base58.encode(Crypto.digest(fileContent)); this.hash58 = Base58.encode(Crypto.digest(fileContent));
LOGGER.trace(String.format("File digest: %s, size: %d bytes", this.hash58, fileContent.length)); LOGGER.trace(String.format("File digest: %s, size: %d bytes", this.hash58, fileContent.length));
String outputFilePath = getOutputFilePath(this.hash58, true); Path outputFilePath = getOutputFilePath(this.hash58, true);
File outputFile = new File(outputFilePath); File outputFile = outputFilePath.toFile();
try (FileOutputStream outputStream = new FileOutputStream(outputFile)) { try (FileOutputStream outputStream = new FileOutputStream(outputFile)) {
outputStream.write(fileContent); outputStream.write(fileContent);
this.filePath = outputFilePath; this.filePath = outputFilePath;
@ -104,8 +104,11 @@ public class ArbitraryDataFile {
return ArbitraryDataFile.fromHash58(Base58.encode(hash)); return ArbitraryDataFile.fromHash58(Base58.encode(hash));
} }
public static ArbitraryDataFile fromPath(String path) { public static ArbitraryDataFile fromPath(Path path) {
File file = new File(path); if (path == null) {
return null;
}
File file = path.toFile();
if (file.exists()) { if (file.exists()) {
try { try {
byte[] fileContent = Files.readAllBytes(file.toPath()); byte[] fileContent = Files.readAllBytes(file.toPath());
@ -113,15 +116,14 @@ public class ArbitraryDataFile {
ArbitraryDataFile arbitraryDataFile = ArbitraryDataFile.fromHash(digest); ArbitraryDataFile arbitraryDataFile = ArbitraryDataFile.fromHash(digest);
// Copy file to data directory if needed // Copy file to data directory if needed
Path filePath = Paths.get(path); if (Files.exists(path) && !arbitraryDataFile.isInBaseDirectory(path)) {
if (Files.exists(filePath) && !arbitraryDataFile.isInBaseDirectory(path)) { arbitraryDataFile.copyToDataDirectory(path);
arbitraryDataFile.copyToDataDirectory(filePath);
} }
// Or, if it's already in the data directory, we may need to move it // Or, if it's already in the data directory, we may need to move it
else if (!filePath.equals(arbitraryDataFile.getFilePath())) { else if (!path.equals(arbitraryDataFile.getFilePath())) {
// Wrong path, so relocate // Wrong path, so relocate
Path dest = Paths.get(arbitraryDataFile.getFilePath()); Path dest = arbitraryDataFile.getFilePath();
FilesystemUtils.moveFile(filePath, dest, true); FilesystemUtils.moveFile(path, dest, true);
} }
return arbitraryDataFile; return arbitraryDataFile;
@ -133,7 +135,7 @@ public class ArbitraryDataFile {
} }
public static ArbitraryDataFile fromFile(File file) { public static ArbitraryDataFile fromFile(File file) {
return ArbitraryDataFile.fromPath(file.getPath()); return ArbitraryDataFile.fromPath(Paths.get(file.getPath()));
} }
private boolean createDataDirectory() { private boolean createDataDirectory() {
@ -149,21 +151,21 @@ public class ArbitraryDataFile {
return true; return true;
} }
private String copyToDataDirectory(Path sourcePath) { private Path copyToDataDirectory(Path sourcePath) {
if (this.hash58 == null || this.filePath == null) { if (this.hash58 == null || this.filePath == null) {
return null; return null;
} }
String outputFilePath = getOutputFilePath(this.hash58, true); Path outputFilePath = getOutputFilePath(this.hash58, true);
sourcePath = sourcePath.toAbsolutePath(); sourcePath = sourcePath.toAbsolutePath();
Path destPath = Paths.get(outputFilePath).toAbsolutePath(); Path destPath = outputFilePath.toAbsolutePath();
try { try {
return Files.copy(sourcePath, destPath, StandardCopyOption.REPLACE_EXISTING).toString(); return Files.copy(sourcePath, destPath, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) { } catch (IOException e) {
throw new IllegalStateException("Unable to copy file to data directory"); throw new IllegalStateException("Unable to copy file to data directory");
} }
} }
public static String getOutputFilePath(String hash58, boolean createDirectories) { public static Path getOutputFilePath(String hash58, boolean createDirectories) {
if (hash58 == null) { if (hash58 == null) {
return null; return null;
} }
@ -179,20 +181,19 @@ public class ArbitraryDataFile {
throw new IllegalStateException("Unable to create data subdirectory"); throw new IllegalStateException("Unable to create data subdirectory");
} }
} }
return outputDirectory + File.separator + hash58; return Paths.get(outputDirectory, hash58);
} }
public ValidationResult isValid() { public ValidationResult isValid() {
try { try {
// Ensure the file exists on disk // Ensure the file exists on disk
Path path = Paths.get(this.filePath); if (!Files.exists(this.filePath)) {
if (!Files.exists(path)) {
LOGGER.error("File doesn't exist at path {}", this.filePath); LOGGER.error("File doesn't exist at path {}", this.filePath);
return ValidationResult.FILE_NOT_FOUND; return ValidationResult.FILE_NOT_FOUND;
} }
// Validate the file size // Validate the file size
long fileSize = Files.size(path); long fileSize = Files.size(this.filePath);
if (fileSize > MAX_FILE_SIZE) { if (fileSize > MAX_FILE_SIZE) {
LOGGER.error(String.format("ArbitraryDataFile is too large: %d bytes (max size: %d bytes)", fileSize, MAX_FILE_SIZE)); LOGGER.error(String.format("ArbitraryDataFile is too large: %d bytes (max size: %d bytes)", fileSize, MAX_FILE_SIZE));
return ArbitraryDataFile.ValidationResult.FILE_TOO_LARGE; return ArbitraryDataFile.ValidationResult.FILE_TOO_LARGE;
@ -276,7 +277,7 @@ public class ArbitraryDataFile {
File outputFile = new File(outputPath.toString()); File outputFile = new File(outputPath.toString());
try (BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(outputFile))) { try (BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(outputFile))) {
for (ArbitraryDataFileChunk chunk : this.chunks) { for (ArbitraryDataFileChunk chunk : this.chunks) {
File sourceFile = new File(chunk.filePath); File sourceFile = chunk.filePath.toFile();
BufferedInputStream in = new BufferedInputStream(new FileInputStream(sourceFile)); BufferedInputStream in = new BufferedInputStream(new FileInputStream(sourceFile));
byte[] buffer = new byte[2048]; byte[] buffer = new byte[2048];
int inSize; int inSize;
@ -306,13 +307,12 @@ public class ArbitraryDataFile {
public boolean delete() { public boolean delete() {
// Delete the complete file // Delete the complete file
// ... but only if it's inside the Qortal data or temp directory // ... but only if it's inside the Qortal data or temp directory
Path path = Paths.get(this.filePath); if (FilesystemUtils.pathInsideDataOrTempPath(this.filePath)) {
if (FilesystemUtils.pathInsideDataOrTempPath(path)) { if (Files.exists(this.filePath)) {
if (Files.exists(path)) {
try { try {
Files.delete(path); Files.delete(this.filePath);
this.cleanupFilesystem(); this.cleanupFilesystem();
LOGGER.debug("Deleted file {}", path.toString()); LOGGER.debug("Deleted file {}", this.filePath);
return true; return true;
} catch (IOException e) { } catch (IOException e) {
LOGGER.warn("Couldn't delete DataFileChunk at path {}", this.filePath); LOGGER.warn("Couldn't delete DataFileChunk at path {}", this.filePath);
@ -340,11 +340,9 @@ public class ArbitraryDataFile {
} }
protected void cleanupFilesystem() { protected void cleanupFilesystem() {
String path = this.filePath;
// Iterate through two levels of parent directories, and delete if empty // Iterate through two levels of parent directories, and delete if empty
for (int i=0; i<2; i++) { for (int i=0; i<2; i++) {
Path directory = Paths.get(path).getParent().toAbsolutePath(); Path directory = this.filePath.getParent().toAbsolutePath();
try (Stream<Path> files = Files.list(directory)) { try (Stream<Path> files = Files.list(directory)) {
final long count = files.count(); final long count = files.count();
if (count == 0) { if (count == 0) {
@ -355,14 +353,13 @@ public class ArbitraryDataFile {
} catch (IOException e) { } catch (IOException e) {
LOGGER.warn("Unable to count files in directory", e); LOGGER.warn("Unable to count files in directory", e);
} }
path = directory.toString(); this.filePath = directory;
} }
} }
public byte[] getBytes() { public byte[] getBytes() {
Path path = Paths.get(this.filePath);
try { try {
return Files.readAllBytes(path); return Files.readAllBytes(this.filePath);
} catch (IOException e) { } catch (IOException e) {
LOGGER.error("Unable to read bytes for file"); LOGGER.error("Unable to read bytes for file");
return null; return null;
@ -372,15 +369,15 @@ public class ArbitraryDataFile {
/* Helper methods */ /* Helper methods */
private boolean isInBaseDirectory(String filePath) { private boolean isInBaseDirectory(Path filePath) {
Path path = Paths.get(filePath).toAbsolutePath(); Path path = filePath.toAbsolutePath();
String dataPath = Settings.getInstance().getDataPath(); String dataPath = Settings.getInstance().getDataPath();
String basePath = Paths.get(dataPath).toAbsolutePath().toString(); String basePath = Paths.get(dataPath).toAbsolutePath().toString();
return path.startsWith(basePath); return path.startsWith(basePath);
} }
public boolean exists() { public boolean exists() {
File file = new File(this.filePath); File file = this.filePath.toFile();
return file.exists(); return file.exists();
} }
@ -422,9 +419,8 @@ public class ArbitraryDataFile {
} }
public long size() { public long size() {
Path path = Paths.get(this.filePath);
try { try {
return Files.size(path); return Files.size(this.filePath);
} catch (IOException e) { } catch (IOException e) {
return 0; return 0;
} }
@ -464,14 +460,14 @@ public class ArbitraryDataFile {
} }
private File getFile() { private File getFile() {
File file = new File(this.filePath); File file = this.filePath.toFile();
if (file.exists()) { if (file.exists()) {
return file; return file;
} }
return null; return null;
} }
public String getFilePath() { public Path getFilePath() {
return this.filePath; return this.filePath;
} }

3
src/main/java/org/qortal/arbitrary/ArbitraryDataFileChunk.java

@ -38,10 +38,9 @@ public class ArbitraryDataFileChunk extends ArbitraryDataFile {
return superclassValidationResult; return superclassValidationResult;
} }
Path path = Paths.get(this.filePath);
try { try {
// Validate the file size (chunks have stricter limits) // Validate the file size (chunks have stricter limits)
long fileSize = Files.size(path); long fileSize = Files.size(this.filePath);
if (fileSize > CHUNK_SIZE) { if (fileSize > CHUNK_SIZE) {
LOGGER.error(String.format("DataFileChunk is too large: %d bytes (max chunk size: %d bytes)", fileSize, CHUNK_SIZE)); LOGGER.error(String.format("DataFileChunk is too large: %d bytes (max chunk size: %d bytes)", fileSize, CHUNK_SIZE));
return ValidationResult.FILE_TOO_LARGE; return ValidationResult.FILE_TOO_LARGE;

4
src/main/java/org/qortal/arbitrary/ArbitraryDataReader.java

@ -218,7 +218,7 @@ public class ArbitraryDataReader {
// Load data file directly from the hash // Load data file directly from the hash
ArbitraryDataFile arbitraryDataFile = ArbitraryDataFile.fromHash58(resourceId); ArbitraryDataFile arbitraryDataFile = ArbitraryDataFile.fromHash58(resourceId);
// Set filePath to the location of the ArbitraryDataFile // Set filePath to the location of the ArbitraryDataFile
this.filePath = Paths.get(arbitraryDataFile.getFilePath()); this.filePath = arbitraryDataFile.getFilePath();
} }
private void fetchFromName() throws IllegalStateException, IOException, DataException { private void fetchFromName() throws IllegalStateException, IOException, DataException {
@ -294,7 +294,7 @@ public class ArbitraryDataReader {
throw new IllegalStateException("Unable to validate complete file hash"); throw new IllegalStateException("Unable to validate complete file hash");
} }
// Set filePath to the location of the ArbitraryDataFile // Set filePath to the location of the ArbitraryDataFile
this.filePath = Paths.get(arbitraryDataFile.getFilePath()); this.filePath = arbitraryDataFile.getFilePath();
} }
private void decrypt() { private void decrypt() {

2
src/main/java/org/qortal/arbitrary/ArbitraryDataWriter.java

@ -233,7 +233,7 @@ public class ArbitraryDataWriter {
} }
private void split() throws IOException { private void split() throws IOException {
this.arbitraryDataFile = ArbitraryDataFile.fromPath(this.filePath.toString()); this.arbitraryDataFile = ArbitraryDataFile.fromPath(this.filePath);
if (this.arbitraryDataFile == null) { if (this.arbitraryDataFile == null) {
throw new IOException("No file available when trying to split"); throw new IOException("No file available when trying to split");
} }

Loading…
Cancel
Save