Fixed various warnings raised by the IDE.

This commit is contained in:
CalDescent 2021-11-19 16:11:37 +00:00
parent 844501d6cd
commit a061a7cc4d
18 changed files with 114 additions and 133 deletions

View File

@ -41,7 +41,6 @@ import org.qortal.data.account.AccountData;
import org.qortal.data.arbitrary.ArbitraryResourceInfo;
import org.qortal.data.naming.NameData;
import org.qortal.data.transaction.ArbitraryTransactionData;
import org.qortal.data.transaction.ArbitraryTransactionData.*;
import org.qortal.data.transaction.TransactionData;
import org.qortal.repository.DataException;
import org.qortal.repository.Repository;
@ -185,13 +184,11 @@ public class ArbitraryResource {
service, name, address, confirmationStatus, limit, offset, reverse);
// Expand signatures to transactions
List<TransactionData> transactions = new ArrayList<TransactionData>(signatures.size());
List<TransactionData> transactions = new ArrayList<>(signatures.size());
for (byte[] signature : signatures)
transactions.add(repository.getTransactionRepository().fromSignature(signature));
return transactions;
} catch (ApiException e) {
throw e;
} catch (DataException e) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
@ -331,7 +328,7 @@ public class ArbitraryResource {
String path) {
Security.checkApiCallAllowed(request);
return this.upload(null, Service.valueOf(serviceString), name, null, path, null);
return this.upload(Service.valueOf(serviceString), name, null, path, null);
}
@POST
@ -365,7 +362,7 @@ public class ArbitraryResource {
String string) {
Security.checkApiCallAllowed(request);
return this.upload(null, Service.valueOf(serviceString), name, null, null, string);
return this.upload(Service.valueOf(serviceString), name, null, null, string);
}
@ -401,7 +398,7 @@ public class ArbitraryResource {
String path) {
Security.checkApiCallAllowed(request);
return this.upload(null, Service.valueOf(serviceString), name, identifier, path, null);
return this.upload(Service.valueOf(serviceString), name, identifier, path, null);
}
@POST
@ -436,10 +433,10 @@ public class ArbitraryResource {
String string) {
Security.checkApiCallAllowed(request);
return this.upload(null, Service.valueOf(serviceString), name, identifier, null, string);
return this.upload(Service.valueOf(serviceString), name, identifier, null, string);
}
private String upload(Method method, Service service, String name, String identifier, String path, String string) {
private String upload(Service service, String name, String identifier, String path, String string) {
// Fetch public key from registered name
try (final Repository repository = RepositoryManager.getRepository()) {
NameData nameData = repository.getNameRepository().fromName(name);
@ -473,7 +470,7 @@ public class ArbitraryResource {
try {
ArbitraryDataTransactionBuilder transactionBuilder = new ArbitraryDataTransactionBuilder(
publicKey58, Paths.get(path), name, method, service, identifier
publicKey58, Paths.get(path), name, null, service, identifier
);
transactionBuilder.build();
@ -514,12 +511,11 @@ public class ArbitraryResource {
}
Thread.sleep(3000L);
continue;
}
}
java.nio.file.Path outputPath = arbitraryDataReader.getFilePath();
if (filepath == null || filepath.isEmpty()) {
if (filepath.isEmpty()) {
// No file path supplied - so check if this is a single file resource
String[] files = ArrayUtils.removeElement(outputPath.toFile().list(), ".qortal");
if (files.length == 1) {

View File

@ -70,11 +70,10 @@ public class RenderResource {
@SecurityRequirement(name = "apiKey")
public String preview(String directoryPath) {
Security.checkApiCallAllowed(request);
String name = null;
Method method = Method.PUT;
Compression compression = Compression.ZIP;
ArbitraryDataWriter arbitraryDataWriter = new ArbitraryDataWriter(Paths.get(directoryPath), name, Service.WEBSITE, null, method, compression);
ArbitraryDataWriter arbitraryDataWriter = new ArbitraryDataWriter(Paths.get(directoryPath), null, Service.WEBSITE, null, method, compression);
try {
arbitraryDataWriter.save();
} catch (IOException | DataException | InterruptedException | MissingDataException e) {

View File

@ -10,11 +10,11 @@ import java.io.IOException;
public class ArbitraryDataBuildQueueItem {
private String resourceId;
private ResourceIdType resourceIdType;
private Service service;
private String identifier;
private Long creationTimestamp = null;
private final String resourceId;
private final ResourceIdType resourceIdType;
private final Service service;
private final String identifier;
private final Long creationTimestamp;
private Long buildStartTimestamp = null;
private Long buildEndTimestamp = null;
private boolean failed = false;

View File

@ -19,22 +19,22 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
public class ArbitraryDataBuilder {
private static final Logger LOGGER = LogManager.getLogger(ArbitraryDataBuilder.class);
private String name;
private Service service;
private String identifier;
private final String name;
private final Service service;
private final String identifier;
private boolean canRequestMissingFiles;
private List<ArbitraryTransactionData> transactions;
private ArbitraryTransactionData latestPutTransaction;
private List<Path> paths;
private final List<Path> paths;
private byte[] latestSignature;
private Path finalPath;
private int layerCount;
@ -118,7 +118,7 @@ public class ArbitraryDataBuilder {
// Verify that the signature of the first transaction matches the latest PUT
ArbitraryTransactionData firstTransaction = transactionDataList.get(0);
if (!Objects.equals(firstTransaction.getSignature(), latestPut.getSignature())) {
if (!Arrays.equals(firstTransaction.getSignature(), latestPut.getSignature())) {
throw new IllegalStateException("First transaction did not match latest PUT transaction");
}
@ -126,9 +126,8 @@ public class ArbitraryDataBuilder {
transactionDataList.remove(0);
for (ArbitraryTransactionData transactionData : transactionDataList) {
if (!(transactionData instanceof ArbitraryTransactionData)) {
String sig58 = Base58.encode(transactionData.getSignature());
throw new IllegalStateException(String.format("Received non-arbitrary transaction: %s", sig58));
if (transactionData == null) {
throw new IllegalStateException("Transaction not found");
}
if (transactionData.getMethod() != Method.PATCH) {
throw new IllegalStateException("Expected PATCH but received PUT");
@ -198,8 +197,8 @@ public class ArbitraryDataBuilder {
}
private void validatePaths() {
if (this.paths == null || this.paths.isEmpty()) {
throw new IllegalStateException(String.format("No paths available from which to build latest state"));
if (this.paths.isEmpty()) {
throw new IllegalStateException("No paths available from which to build latest state");
}
}
@ -236,11 +235,15 @@ public class ArbitraryDataBuilder {
this.finalPath = pathBefore;
}
private void cacheLatestSignature() throws IOException {
private void cacheLatestSignature() throws IOException, DataException {
byte[] latestTransactionSignature = this.transactions.get(this.transactions.size()-1).getSignature();
if (latestTransactionSignature == null) {
throw new IllegalStateException("Missing latest transaction signature");
}
Long now = NTP.getTime();
if (now == null) {
throw new DataException("NTP time not synced yet");
}
ArbitraryDataMetadataCache cache = new ArbitraryDataMetadataCache(this.finalPath);
cache.setSignature(latestTransactionSignature);

View File

@ -17,12 +17,12 @@ import java.util.Arrays;
public class ArbitraryDataCache {
private boolean overwrite;
private Path filePath;
private String resourceId;
private ResourceIdType resourceIdType;
private Service service;
private String identifier;
private final boolean overwrite;
private final Path filePath;
private final String resourceId;
private final ResourceIdType resourceIdType;
private final Service service;
private final String identifier;
public ArbitraryDataCache(Path filePath, boolean overwrite, String resourceId,
ResourceIdType resourceIdType, Service service, String identifier) {
@ -125,10 +125,7 @@ public class ArbitraryDataCache {
}
// Check if they match
if (!Arrays.equals(latestTransactionSig, cachedSig)) {
return true;
}
return false;
return !Arrays.equals(latestTransactionSig, cachedSig);
}
private byte[] fetchLatestTransactionSignature() {

View File

@ -21,9 +21,9 @@ public class ArbitraryDataCombiner {
private static final Logger LOGGER = LogManager.getLogger(ArbitraryDataCombiner.class);
private Path pathBefore;
private Path pathAfter;
private byte[] signatureBefore;
private final Path pathBefore;
private final Path pathAfter;
private final byte[] signatureBefore;
private boolean shouldValidateHashes;
private Path finalPath;
private ArbitraryDataMetadataPatch metadata;
@ -81,10 +81,10 @@ public class ArbitraryDataCombiner {
private void preExecute() {
if (this.pathBefore == null || this.pathAfter == null) {
throw new IllegalStateException(String.format("No paths available to build patch"));
throw new IllegalStateException("No paths available to build patch");
}
if (!Files.exists(this.pathBefore) || !Files.exists(this.pathAfter)) {
throw new IllegalStateException(String.format("Unable to create patch because at least one path doesn't exist"));
throw new IllegalStateException("Unable to create patch because at least one path doesn't exist");
}
}

View File

@ -16,9 +16,9 @@ public class ArbitraryDataCreatePatch {
private static final Logger LOGGER = LogManager.getLogger(ArbitraryDataCreatePatch.class);
private Path pathBefore;
private final Path pathBefore;
private Path pathAfter;
private byte[] previousSignature;
private final byte[] previousSignature;
private Path finalPath;
private int totalFileCount;
@ -50,10 +50,10 @@ public class ArbitraryDataCreatePatch {
private void preExecute() {
if (this.pathBefore == null || this.pathAfter == null) {
throw new IllegalStateException(String.format("No paths available to build patch"));
throw new IllegalStateException("No paths available to build patch");
}
if (!Files.exists(this.pathBefore) || !Files.exists(this.pathAfter)) {
throw new IllegalStateException(String.format("Unable to create patch because at least one path doesn't exist"));
throw new IllegalStateException("Unable to create patch because at least one path doesn't exist");
}
this.createRandomIdentifier();

View File

@ -17,7 +17,7 @@ import java.util.*;
public class ArbitraryDataDiff {
/** Only create a patch if both the before and after file sizes are within defined limit **/
private static long MAX_DIFF_FILE_SIZE = 100 * 1024L; // 100kiB
private static final long MAX_DIFF_FILE_SIZE = 100 * 1024L; // 100kiB
public enum DiffType {
@ -61,17 +61,17 @@ public class ArbitraryDataDiff {
private static final Logger LOGGER = LogManager.getLogger(ArbitraryDataDiff.class);
private Path pathBefore;
private Path pathAfter;
private byte[] previousSignature;
private final Path pathBefore;
private final Path pathAfter;
private final byte[] previousSignature;
private byte[] previousHash;
private byte[] currentHash;
private Path diffPath;
private String identifier;
private List<Path> addedPaths;
private List<ModifiedPath> modifiedPaths;
private List<Path> removedPaths;
private final List<Path> addedPaths;
private final List<ModifiedPath> modifiedPaths;
private final List<Path> removedPaths;
private int totalFileCount;
@ -141,7 +141,7 @@ public class ArbitraryDataDiff {
final ArbitraryDataDiff diff = this;
// Check for additions or modifications
Files.walkFileTree(this.pathAfter, new FileVisitor<Path>() {
Files.walkFileTree(this.pathAfter, new FileVisitor<>() {
@Override
public FileVisitResult preVisitDirectory(Path after, BasicFileAttributes attrs) {
@ -216,10 +216,10 @@ public class ArbitraryDataDiff {
final ArbitraryDataDiff diff = this;
// Check for removals
Files.walkFileTree(this.pathBefore, new FileVisitor<Path>() {
Files.walkFileTree(this.pathBefore, new FileVisitor<>() {
@Override
public FileVisitResult preVisitDirectory(Path before, BasicFileAttributes attrs) throws IOException {
public FileVisitResult preVisitDirectory(Path before, BasicFileAttributes attrs) {
Path directoryPathBefore = pathBeforeAbsolute.relativize(before.toAbsolutePath());
Path directoryPathAfter = pathAfterAbsolute.resolve(directoryPathBefore);
@ -238,7 +238,7 @@ public class ArbitraryDataDiff {
}
@Override
public FileVisitResult visitFile(Path before, BasicFileAttributes attrs) throws IOException {
public FileVisitResult visitFile(Path before, BasicFileAttributes attrs) {
Path filePathBefore = pathBeforeAbsolute.relativize(before.toAbsolutePath());
Path filePathAfter = pathAfterAbsolute.resolve(filePathBefore);

View File

@ -1,7 +1,5 @@
package org.qortal.arbitrary;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.qortal.utils.Base58;
import java.io.IOException;
@ -11,15 +9,12 @@ import java.nio.file.Path;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class ArbitraryDataDigest {
private static final Logger LOGGER = LogManager.getLogger(ArbitraryDataDigest.class);
private Path path;
private final Path path;
private byte[] hash;
public ArbitraryDataDigest(Path path) {
@ -27,11 +22,10 @@ public class ArbitraryDataDigest {
}
public void compute() throws IOException {
List<Path> allPaths = Files.walk(path).filter(Files::isRegularFile).collect(Collectors.toList());
Collections.sort(allPaths);
List<Path> allPaths = Files.walk(path).filter(Files::isRegularFile).sorted().collect(Collectors.toList());
Path basePathAbsolute = this.path.toAbsolutePath();
MessageDigest sha256 = null;
MessageDigest sha256;
try {
sha256 = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {

View File

@ -6,8 +6,6 @@ import org.qortal.utils.Base58;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class ArbitraryDataFileChunk extends ArbitraryDataFile {

View File

@ -20,8 +20,8 @@ public class ArbitraryDataMerge {
private static final Logger LOGGER = LogManager.getLogger(ArbitraryDataMerge.class);
private Path pathBefore;
private Path pathAfter;
private final Path pathBefore;
private final Path pathAfter;
private Path mergePath;
private String identifier;
private ArbitraryDataMetadataPatch metadata;

View File

@ -41,19 +41,18 @@ public class ArbitraryDataReader {
private static final Logger LOGGER = LogManager.getLogger(ArbitraryDataReader.class);
private String resourceId;
private ResourceIdType resourceIdType;
private Service service;
private String identifier;
private final String resourceId;
private final ResourceIdType resourceIdType;
private final Service service;
private final String identifier;
private ArbitraryTransactionData transactionData;
private String secret58;
private Path filePath;
private boolean canRequestMissingFiles;
// Intermediate paths
private Path workingPath;
private Path uncompressedPath;
private Path unencryptedPath;
private final Path workingPath;
private final Path uncompressedPath;
// Stats (available for synchronous builds only)
private int layerCount;
@ -66,7 +65,7 @@ public class ArbitraryDataReader {
}
// If identifier is a blank string, treat it as null
if (identifier == "") {
if (identifier == null || identifier.equals("")) {
identifier = null;
}
@ -116,8 +115,7 @@ public class ArbitraryDataReader {
* This adds the build task to a queue, and the result will be cached when complete
* To check the status of the build, periodically call isCachedDataAvailable()
* Once it returns true, you can then use getFilePath() to access the data itself.
* TODO: create API to check the status
* @return
* @return true if added or already present in queue; false if not
*/
public boolean loadAsynchronously() {
ArbitraryDataBuildQueueItem queueItem =
@ -136,6 +134,7 @@ public class ArbitraryDataReader {
* @throws IllegalStateException
* @throws IOException
* @throws DataException
* @throws MissingDataException
*/
public void loadSynchronously(boolean overwrite) throws IllegalStateException, IOException, DataException, MissingDataException {
try {
@ -195,7 +194,7 @@ public class ArbitraryDataReader {
if (Files.exists(uncompressedPath)) {
LOGGER.trace("Attempting to delete path {}", this.uncompressedPath);
try {
Files.walkFileTree(uncompressedPath, new SimpleFileVisitor<Path>() {
Files.walkFileTree(uncompressedPath, new SimpleFileVisitor<>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
@ -290,7 +289,7 @@ public class ArbitraryDataReader {
try (final Repository repository = RepositoryManager.getRepository()) {
transactionData = (ArbitraryTransactionData) repository.getTransactionRepository().fromSignature(Base58.decode(resourceId));
}
if (!(transactionData instanceof ArbitraryTransactionData)) {
if (transactionData == null) {
throw new IllegalStateException(String.format("Transaction data not found for signature %s", this.resourceId));
}
@ -298,7 +297,7 @@ public class ArbitraryDataReader {
}
private void fetchFromTransactionData(ArbitraryTransactionData transactionData) throws IllegalStateException, IOException, MissingDataException {
if (!(transactionData instanceof ArbitraryTransactionData)) {
if (transactionData == null) {
throw new IllegalStateException(String.format("Transaction data not found for signature %s", this.resourceId));
}
@ -364,13 +363,13 @@ public class ArbitraryDataReader {
byte[] secret = this.secret58 != null ? Base58.decode(this.secret58) : null;
if (secret != null && secret.length == Transformer.AES256_LENGTH) {
try {
this.unencryptedPath = Paths.get(this.workingPath.toString() + File.separator + "zipped.zip");
Path unencryptedPath = Paths.get(this.workingPath.toString() + File.separator + "zipped.zip");
SecretKey aesKey = new SecretKeySpec(secret, 0, secret.length, "AES");
AES.decryptFile("AES", aesKey, this.filePath.toString(), this.unencryptedPath.toString());
AES.decryptFile("AES", aesKey, this.filePath.toString(), unencryptedPath.toString());
// Replace filePath pointer with the encrypted file path
// Don't delete the original ArbitraryDataFile, as this is handled in the cleanup phase
this.filePath = this.unencryptedPath;
this.filePath = unencryptedPath;
} catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException | NoSuchPaddingException
| BadPaddingException | IllegalBlockSizeException | IOException | InvalidKeyException e) {
@ -454,12 +453,9 @@ public class ArbitraryDataReader {
if (this.filePath.compareTo(this.uncompressedPath) != 0) {
File source = new File(this.filePath.toString());
File dest = new File(this.uncompressedPath.toString());
if (source == null || !source.exists()) {
if (!source.exists()) {
throw new IllegalStateException("Source directory doesn't exist");
}
if (dest == null) {
throw new IllegalStateException("Destination is null");
}
// Ensure destination directory doesn't exist
FileUtils.deleteDirectory(dest);
// Move files to destination
@ -515,7 +511,7 @@ public class ArbitraryDataReader {
* Use the below setter to ensure that we only read existing
* data without requesting any missing files,
*
* @param canRequestMissingFiles
* @param canRequestMissingFiles - whether or not fetching missing files is allowed
*/
public void setCanRequestMissingFiles(boolean canRequestMissingFiles) {
this.canRequestMissingFiles = canRequestMissingFiles;

View File

@ -27,17 +27,17 @@ public class ArbitraryDataRenderer {
private static final Logger LOGGER = LogManager.getLogger(ArbitraryDataRenderer.class);
private String resourceId;
private ResourceIdType resourceIdType;
private Service service;
private final String resourceId;
private final ResourceIdType resourceIdType;
private final Service service;
private String inPath;
private String secret58;
private String prefix;
private boolean usePrefix;
private boolean async;
private HttpServletRequest request;
private HttpServletResponse response;
private ServletContext context;
private final String secret58;
private final String prefix;
private final boolean usePrefix;
private final boolean async;
private final HttpServletRequest request;
private final HttpServletResponse response;
private final ServletContext context;
public ArbitraryDataRenderer(String resourceId, ResourceIdType resourceIdType, Service service, String inPath,
String secret58, String prefix, boolean usePrefix, boolean async,
@ -77,12 +77,12 @@ public class ArbitraryDataRenderer {
} catch (Exception e) {
LOGGER.info(String.format("Unable to load %s %s: %s", service, resourceId, e.getMessage()));
return this.getResponse(response, 500, "Error 500: Internal Server Error");
return ArbitraryDataRenderer.getResponse(response, 500, "Error 500: Internal Server Error");
}
java.nio.file.Path path = arbitraryDataReader.getFilePath();
if (path == null) {
return this.getResponse(response, 404, "Error 404: File Not Found");
return ArbitraryDataRenderer.getResponse(response, 404, "Error 404: File Not Found");
}
String unzippedPath = path.toString();
@ -128,7 +128,7 @@ public class ArbitraryDataRenderer {
LOGGER.info("Unable to serve file at path: {}", inPath, e);
}
return this.getResponse(response, 404, "Error 404: File Not Found");
return ArbitraryDataRenderer.getResponse(response, 404, "Error 404: File Not Found");
}
private String getFilename(String directory, String userPath) {
@ -146,14 +146,14 @@ public class ArbitraryDataRenderer {
}
private HttpServletResponse getLoadingResponse() {
String responseString = null;
String responseString = "";
URL url = Resources.getResource("loading/index.html");
try {
responseString = Resources.toString(url, StandardCharsets.UTF_8);
} catch (IOException e) {
LOGGER.info("Unable to show loading screen: {}", e.getMessage());
}
return this.getResponse(response, 503, responseString);
return ArbitraryDataRenderer.getResponse(response, 503, responseString);
}
public static HttpServletResponse getResponse(HttpServletResponse response, int responseCode, String responseString) {

View File

@ -12,10 +12,10 @@ import java.io.IOException;
public class ArbitraryDataResource {
private String resourceId;
private ResourceIdType resourceIdType;
private Service service;
private String identifier;
private final String resourceId;
private final ResourceIdType resourceIdType;
private final Service service;
private final String identifier;
public ArbitraryDataResource(String resourceId, ResourceIdType resourceIdType, Service service, String identifier) {
this.resourceId = resourceId;

View File

@ -42,12 +42,12 @@ public class ArbitraryDataTransactionBuilder {
// Maximum proportion of files modified relative to total
private static final double MAX_FILE_DIFF = 0.5f;
private String publicKey58;
private Path path;
private String name;
private final String publicKey58;
private final Path path;
private final String name;
private Method method;
private Service service;
private String identifier;
private final Service service;
private final String identifier;
private ArbitraryTransactionData arbitraryTransactionData;
@ -137,11 +137,14 @@ public class ArbitraryDataTransactionBuilder {
ArbitraryDataFile arbitraryDataFile = null;
try (final Repository repository = RepositoryManager.getRepository()) {
Long now = NTP.getTime();
if (now == null) {
throw new DataException("NTP time not synced yet");
}
// Ensure that this chain supports transactions necessary for complex arbitrary data
int transactionVersion = Transaction.getVersionByTimestamp(now);
if (transactionVersion < MIN_TRANSACTION_VERSION) {
throw new DataException(String.format("Transaction version unsupported on this blockchain."));
throw new DataException("Transaction version unsupported on this blockchain.");
}
if (publicKey58 == null || path == null) {

View File

@ -33,11 +33,11 @@ public class ArbitraryDataWriter {
private static final Logger LOGGER = LogManager.getLogger(ArbitraryDataWriter.class);
private Path filePath;
private String name;
private Service service;
private String identifier;
private Method method;
private Compression compression;
private final String name;
private final Service service;
private final String identifier;
private final Method method;
private final Compression compression;
private SecretKey aesKey;
private ArbitraryDataFile arbitraryDataFile;

View File

@ -1,7 +1,5 @@
package org.qortal.arbitrary.misc;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.json.JSONObject;
import org.qortal.transaction.Transaction;
@ -36,8 +34,6 @@ public enum Service {
private final Long maxSize;
private final List<String> requiredKeys;
private static final Logger LOGGER = LogManager.getLogger(Service.class);
private static final Map<Integer, Service> map = stream(Service.values())
.collect(toMap(service -> service.value, service -> service));

View File

@ -26,9 +26,9 @@ public class UnifiedDiffPatch {
private static final Logger LOGGER = LogManager.getLogger(UnifiedDiffPatch.class);
private Path before;
private Path after;
private Path destination;
private final Path before;
private final Path after;
private final Path destination;
private String identifier;
private Path validationPath;
@ -95,7 +95,6 @@ public class UnifiedDiffPatch {
* it works correctly and is smaller than the original file
*
* @return true if valid, false if invalid
* @throws IOException
*/
public boolean isValid() {
this.createRandomIdentifier();