Merge branch 'eugenp:master' into master

This commit is contained in:
Ashish Gupta
2021-08-16 11:49:48 +05:30
committed by GitHub
65 changed files with 1790 additions and 90 deletions
@@ -0,0 +1,32 @@
package com.baeldung.constructors.exception;
import java.io.File;
import java.io.IOException;
public class Animal {
public Animal() throws InstantiationException {
throw new InstantiationException("Cannot be instantiated");
}
public Animal(String id, int age) {
if (id == null)
throw new NullPointerException("Id cannot be null");
if (age < 0)
throw new IllegalArgumentException("Age cannot be negative");
}
public Animal(File file) throws SecurityException, IOException {
// Avoiding Path traversal attacks
if (file.isAbsolute()) {
throw new SecurityException("Traversal attack - absolute path not allowed");
}
// Avoiding directory traversal
// a/../..b/
if (!file.getCanonicalPath()
.equals(file.getAbsolutePath())) {
throw new SecurityException("Directory traversal attempt?");
}
}
}
@@ -0,0 +1,13 @@
package com.baeldung.constructors.exception;
public class Bird extends Animal {
// Note that we are throwing parent exception
public Bird() throws ReflectiveOperationException {
super();
}
public Bird(String id, int age) {
super(id, age);
}
}
@@ -0,0 +1,47 @@
package com.baeldung.constructors.exception;
import java.io.File;
import org.assertj.core.api.Assertions;
import org.junit.Test;
public class AnimalUnitTest {
@Test
public void givenNoArgument_thenFails() {
Assertions.assertThatThrownBy(() -> {
new Animal();
})
.isInstanceOf(Exception.class);
}
@Test
public void givenInvalidArg_thenFails() {
Assertions.assertThatThrownBy(() -> {
new Animal(null, 30);
})
.isInstanceOf(NullPointerException.class);
}
@Test(expected = Test.None.class)
public void givenValidArg_thenSuccess() {
new Animal("1234", 30);
}
@Test
public void givenAbsolutePath_thenFails() {
Assertions.assertThatThrownBy(() -> {
new Animal(new File("temp.txt").getAbsoluteFile());
})
.isInstanceOf(SecurityException.class);
}
@Test
public void givenDirectoryTraversalPath_thenFails() {
Assertions.assertThatThrownBy(() -> {
new Animal(new File(File.separator + ".." + File.separator + "temp.txt"));
})
.isInstanceOf(SecurityException.class);
}
}
@@ -5,3 +5,4 @@ This module contains articles about Java operators
## Relevant Articles:
- [Logical vs Bitwise OR Operator](https://www.baeldung.com/java-logical-vs-bitwise-or-operator)
- [Bitmasking in Java with Bitwise Operators](https://www.baeldung.com/java-bitmasking)
@@ -0,0 +1,61 @@
package com.baeldung.stringfilenamevalidaiton;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Arrays;
public class StringFilenameValidationUtils {
public static final Character[] INVALID_WINDOWS_SPECIFIC_CHARS = {'"', '*', ':', '<', '>', '?', '\\', '|', 0x7F};
public static final Character[] INVALID_UNIX_SPECIFIC_CHARS = {'\000'};
public static final String REGEX_PATTERN = "^[A-za-z0-9.]{1,255}$";
private StringFilenameValidationUtils() {
}
public static boolean validateStringFilenameUsingIO(String filename) throws IOException {
File file = new File(filename);
boolean created = false;
try {
created = file.createNewFile();
return created;
} finally {
if (created) {
file.delete();
}
}
}
public static boolean validateStringFilenameUsingNIO2(String filename) {
Paths.get(filename);
return true;
}
public static boolean validateStringFilenameUsingContains(String filename) {
if (filename == null || filename.isEmpty() || filename.length() > 255) {
return false;
}
return Arrays.stream(getInvalidCharsByOS())
.noneMatch(ch -> filename.contains(ch.toString()));
}
public static boolean validateStringFilenameUsingRegex(String filename) {
if (filename == null) {
return false;
}
return filename.matches(REGEX_PATTERN);
}
private static Character[] getInvalidCharsByOS() {
String os = System.getProperty("os.name").toLowerCase();
if (os.contains("win")) {
return INVALID_WINDOWS_SPECIFIC_CHARS;
} else if (os.contains("nix") || os.contains("nux") || os.contains("mac")) {
return INVALID_UNIX_SPECIFIC_CHARS;
} else {
return new Character[]{};
}
}
}
@@ -0,0 +1,130 @@
package com.baeldung.stringfilenamevalidaiton;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.RandomUtils;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledOnOs;
import org.junit.jupiter.api.condition.OS;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EmptySource;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.NullSource;
import java.io.IOException;
import java.nio.file.InvalidPathException;
import java.util.Arrays;
import java.util.stream.Stream;
import static com.baeldung.stringfilenamevalidaiton.StringFilenameValidationUtils.validateStringFilenameUsingContains;
import static com.baeldung.stringfilenamevalidaiton.StringFilenameValidationUtils.validateStringFilenameUsingIO;
import static com.baeldung.stringfilenamevalidaiton.StringFilenameValidationUtils.validateStringFilenameUsingNIO2;
import static com.baeldung.stringfilenamevalidaiton.StringFilenameValidationUtils.validateStringFilenameUsingRegex;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
public class StringFilenameValidationUnitTest {
private static final String CORRECT_FILENAME_PATTERN = "baeldung.txt";
@ParameterizedTest
@MethodSource("correctAlphanumericFilenamesProvider")
public void givenCorrectAlphanumericRandomFilenameString_whenValidateUsingIO_thenReturnTrue(String filename) throws IOException {
assertThat(validateStringFilenameUsingIO(filename)).isTrue();
assertThat(validateStringFilenameUsingNIO2(filename)).isTrue();
assertThat(validateStringFilenameUsingContains(filename)).isTrue();
assertThat(validateStringFilenameUsingRegex(filename)).isTrue();
}
@Test
public void givenTooLongFileNameString_whenValidate_thenIOAndCustomFailsNIO2Succeed() {
String filename = RandomStringUtils.randomAlphabetic(500);
assertThatThrownBy(() -> validateStringFilenameUsingIO(filename))
.isInstanceOf(IOException.class)
.hasMessageContaining("File name too long");
assertThat(validateStringFilenameUsingNIO2(filename)).isTrue();
assertThat(validateStringFilenameUsingContains(filename)).isFalse();
assertThat(validateStringFilenameUsingRegex(filename)).isFalse();
}
@ParameterizedTest
@NullSource
public void givenNullString_whenValidate_thenFails(String filename) {
assertThatThrownBy(() -> validateStringFilenameUsingIO(filename))
.isInstanceOf(NullPointerException.class);
assertThatThrownBy(() -> validateStringFilenameUsingNIO2(filename))
.isInstanceOf(NullPointerException.class);
assertThat(validateStringFilenameUsingContains(filename)).isFalse();
assertThat(validateStringFilenameUsingRegex(filename)).isFalse();
}
@ParameterizedTest
@EmptySource
public void givenEmptyString_whenValidate_thenIOAndCustomFailsNIO2Succeed(String filename) {
assertThatThrownBy(() -> validateStringFilenameUsingIO(filename))
.isInstanceOf(IOException.class);
assertThat(validateStringFilenameUsingNIO2(filename)).isTrue();
assertThat(validateStringFilenameUsingContains(filename)).isFalse();
assertThat(validateStringFilenameUsingRegex(filename)).isFalse();
}
@ParameterizedTest
@EnabledOnOs({OS.LINUX, OS.MAC})
@MethodSource("filenamesWithInvalidWindowsChars")
public void givenFilenameStringWithInvalidWindowsCharAndIsUnix_whenValidateUsingIO_thenReturnTrue(String filename) throws IOException {
assertThat(validateStringFilenameUsingIO(filename)).isTrue();
assertThat(validateStringFilenameUsingNIO2(filename)).isTrue();
assertThat(validateStringFilenameUsingContains(filename)).isTrue();
}
@ParameterizedTest
@EnabledOnOs(OS.WINDOWS)
@MethodSource("filenamesWithInvalidWindowsChars")
public void givenFilenameStringWithInvalidWindowsCharAndIsWindows_whenValidateUsingIO_thenRaiseException(String filename) {
assertThatThrownBy(() -> validateStringFilenameUsingIO(filename))
.isInstanceOf(IOException.class)
.hasMessageContaining("Invalid file path");
assertThatThrownBy(() -> validateStringFilenameUsingNIO2(filename))
.isInstanceOf(InvalidPathException.class)
.hasMessage("character not allowed");
assertThat(validateStringFilenameUsingContains(filename)).isFalse();
}
@ParameterizedTest
@EnabledOnOs({OS.LINUX, OS.MAC})
@MethodSource("filenamesWithInvalidUnixChars")
public void givenFilenameStringWithInvalidUnixCharAndIsUnix_whenValidate_thenRaiseException(String filename) {
assertThatThrownBy(() -> validateStringFilenameUsingIO(filename))
.isInstanceOf(IOException.class)
.hasMessageContaining("Invalid file path");
assertThatThrownBy(() -> validateStringFilenameUsingNIO2(filename))
.isInstanceOf(InvalidPathException.class)
.hasMessageContaining("character not allowed");
assertThat(validateStringFilenameUsingContains(filename)).isFalse();
}
private static Stream<String> correctAlphanumericFilenamesProvider() {
return Stream.generate(() -> RandomStringUtils.randomAlphanumeric(1, 10) + "." + RandomStringUtils.randomAlphabetic(3, 5)).limit(10);
}
private static Stream<String> filenamesWithInvalidWindowsChars() {
return Arrays.stream(StringFilenameValidationUtils.INVALID_WINDOWS_SPECIFIC_CHARS)
.map(character -> {
int idx = RandomUtils.nextInt(0, CORRECT_FILENAME_PATTERN.length());
return CORRECT_FILENAME_PATTERN.substring(0, idx) + character + CORRECT_FILENAME_PATTERN.substring(idx);
});
}
private static Stream<String> filenamesWithInvalidUnixChars() {
return Arrays.stream(StringFilenameValidationUtils.INVALID_UNIX_SPECIFIC_CHARS)
.map(character -> {
int idx = RandomUtils.nextInt(0, CORRECT_FILENAME_PATTERN.length());
return CORRECT_FILENAME_PATTERN.substring(0, idx) + character + CORRECT_FILENAME_PATTERN.substring(idx);
});
}
}