Merge branch 'eugenp:master' into PR-7200
This commit is contained in:
commit
9dccb1c2c1
|
@ -28,7 +28,7 @@
|
|||
</modules>
|
||||
|
||||
<properties>
|
||||
<commons-codec.version>1.11</commons-codec.version>
|
||||
<commons-codec.version>1.16.0</commons-codec.version>
|
||||
<commons-math3.version>3.6.1</commons-math3.version>
|
||||
<cobertura.plugin.version>2.7</cobertura.plugin.version>
|
||||
<tradukisto.version>1.0.1</tradukisto.version>
|
||||
|
|
|
@ -234,7 +234,7 @@
|
|||
|
||||
<properties>
|
||||
<!-- util -->
|
||||
<commons-codec.version>1.10</commons-codec.version>
|
||||
<commons-codec.version>1.16.0</commons-codec.version>
|
||||
<httpasyncclient.version>4.1.5</httpasyncclient.version>
|
||||
<!-- testing -->
|
||||
<wiremock.version>2.5.1</wiremock.version>
|
||||
|
|
|
@ -14,3 +14,4 @@ You can build the project from the command line using: *mvn clean install*, or i
|
|||
- [Get Partition Count for a Topic in Kafka](https://www.baeldung.com/java-kafka-partition-count-topic)
|
||||
- [bootstrap-server in Kafka Configuration](https://www.baeldung.com/java-kafka-bootstrap-server)
|
||||
- [Introduction to Apache Kafka](https://www.baeldung.com/apache-kafka)
|
||||
- [Ensuring Message Ordering in Kafka: Strategies and Configurations](https://www.baeldung.com/kafka-message-ordering)
|
||||
|
|
|
@ -75,7 +75,7 @@
|
|||
<properties>
|
||||
<gson.version>2.10.1</gson.version>
|
||||
<dynamodblocal.version>1.21.1</dynamodblocal.version>
|
||||
<commons-codec-version>1.10.L001</commons-codec-version>
|
||||
<commons-codec-version>1.16.0</commons-codec-version>
|
||||
<jets3t-version>0.9.4.0006L</jets3t-version>
|
||||
<maven-plugins-version>3.1.1</maven-plugins-version>
|
||||
</properties>
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package com.baeldung.deserializationfilters;
|
||||
|
||||
import java.io.ObjectInputFilter;
|
||||
import java.util.function.BinaryOperator;
|
||||
|
||||
import com.baeldung.deserializationfilters.service.DeserializationService;
|
||||
import com.baeldung.deserializationfilters.service.LimitedArrayService;
|
||||
import com.baeldung.deserializationfilters.service.LowDepthService;
|
||||
import com.baeldung.deserializationfilters.service.SmallObjectService;
|
||||
import com.baeldung.deserializationfilters.utils.FilterUtils;
|
||||
|
||||
public class ContextSpecificDeserializationFilterFactory implements BinaryOperator<ObjectInputFilter> {
|
||||
|
||||
@Override
|
||||
public ObjectInputFilter apply(ObjectInputFilter current, ObjectInputFilter next) {
|
||||
if (current == null) {
|
||||
Class<?> caller = findInStack(DeserializationService.class);
|
||||
|
||||
if (caller == null) {
|
||||
current = FilterUtils.fallbackFilter();
|
||||
} else if (caller.equals(SmallObjectService.class)) {
|
||||
current = FilterUtils.safeSizeFilter(190);
|
||||
} else if (caller.equals(LowDepthService.class)) {
|
||||
current = FilterUtils.safeDepthFilter(2);
|
||||
} else if (caller.equals(LimitedArrayService.class)) {
|
||||
current = FilterUtils.safeArrayFilter(3);
|
||||
}
|
||||
}
|
||||
|
||||
return ObjectInputFilter.merge(current, next);
|
||||
}
|
||||
|
||||
private static Class<?> findInStack(Class<?> superType) {
|
||||
for (StackTraceElement element : Thread.currentThread()
|
||||
.getStackTrace()) {
|
||||
try {
|
||||
Class<?> subType = Class.forName(element.getClassName());
|
||||
if (superType.isAssignableFrom(subType)) {
|
||||
return subType;
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package com.baeldung.deserializationfilters.pojo;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public interface ContextSpecific extends Serializable {
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.baeldung.deserializationfilters.pojo;
|
||||
|
||||
public class NestedSample implements ContextSpecific {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Sample optional;
|
||||
|
||||
public NestedSample(Sample optional) {
|
||||
this.optional = optional;
|
||||
}
|
||||
|
||||
public Sample getOptional() {
|
||||
return optional;
|
||||
}
|
||||
|
||||
public void setOptional(Sample optional) {
|
||||
this.optional = optional;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package com.baeldung.deserializationfilters.pojo;
|
||||
|
||||
public class Sample implements ContextSpecific, Comparable<Sample> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private int[] array;
|
||||
private String name;
|
||||
private NestedSample nested;
|
||||
|
||||
public Sample(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Sample(int[] array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
public Sample(NestedSample nested) {
|
||||
this.nested = nested;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int[] getArray() {
|
||||
return array;
|
||||
}
|
||||
|
||||
public void setArray(int[] array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
public NestedSample getNested() {
|
||||
return nested;
|
||||
}
|
||||
|
||||
public void setNested(NestedSample nested) {
|
||||
this.nested = nested;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Sample o) {
|
||||
if (name == null)
|
||||
return -1;
|
||||
|
||||
if (o == null || o.getName() == null)
|
||||
return 1;
|
||||
|
||||
return getName().compareTo(o.getName());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.baeldung.deserializationfilters.pojo;
|
||||
|
||||
public class SampleExploit extends Sample {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public SampleExploit() {
|
||||
super("exploit");
|
||||
}
|
||||
|
||||
public static void maliciousCode() {
|
||||
System.out.println("exploit executed");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
maliciousCode();
|
||||
return "exploit";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Sample o) {
|
||||
maliciousCode();
|
||||
return super.compareTo(o);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.baeldung.deserializationfilters.service;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Set;
|
||||
|
||||
import com.baeldung.deserializationfilters.pojo.ContextSpecific;
|
||||
|
||||
public interface DeserializationService {
|
||||
|
||||
Set<ContextSpecific> process(InputStream... inputStreams);
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.baeldung.deserializationfilters.service;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Set;
|
||||
|
||||
import com.baeldung.deserializationfilters.pojo.ContextSpecific;
|
||||
import com.baeldung.deserializationfilters.utils.DeserializationUtils;
|
||||
|
||||
public class LimitedArrayService implements DeserializationService {
|
||||
|
||||
@Override
|
||||
public Set<ContextSpecific> process(InputStream... inputStreams) {
|
||||
return DeserializationUtils.deserializeIntoSet(inputStreams);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.baeldung.deserializationfilters.service;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputFilter;
|
||||
import java.util.Set;
|
||||
|
||||
import com.baeldung.deserializationfilters.pojo.ContextSpecific;
|
||||
import com.baeldung.deserializationfilters.utils.DeserializationUtils;
|
||||
|
||||
public class LowDepthService implements DeserializationService {
|
||||
|
||||
public Set<ContextSpecific> process(ObjectInputFilter filter, InputStream... inputStreams) {
|
||||
return DeserializationUtils.deserializeIntoSet(filter, inputStreams);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ContextSpecific> process(InputStream... inputStreams) {
|
||||
return process(null, inputStreams);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.baeldung.deserializationfilters.service;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Set;
|
||||
|
||||
import com.baeldung.deserializationfilters.pojo.ContextSpecific;
|
||||
import com.baeldung.deserializationfilters.utils.DeserializationUtils;
|
||||
|
||||
public class SmallObjectService implements DeserializationService {
|
||||
|
||||
@Override
|
||||
public Set<ContextSpecific> process(InputStream... inputStreams) {
|
||||
return DeserializationUtils.deserializeIntoSet(inputStreams);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package com.baeldung.deserializationfilters.utils;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InvalidClassException;
|
||||
import java.io.ObjectInputFilter;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import com.baeldung.deserializationfilters.pojo.ContextSpecific;
|
||||
|
||||
public class DeserializationUtils {
|
||||
private DeserializationUtils() {
|
||||
}
|
||||
|
||||
public static Object deserialize(InputStream inStream) {
|
||||
return deserialize(inStream, null);
|
||||
}
|
||||
|
||||
public static Object deserialize(InputStream inStream, ObjectInputFilter filter) {
|
||||
try (ObjectInputStream in = new ObjectInputStream(inStream)) {
|
||||
if (filter != null) {
|
||||
in.setObjectInputFilter(filter);
|
||||
}
|
||||
return in.readObject();
|
||||
} catch (InvalidClassException e) {
|
||||
return null;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Set<ContextSpecific> deserializeIntoSet(InputStream... inputStreams) {
|
||||
return deserializeIntoSet(null, inputStreams);
|
||||
}
|
||||
|
||||
public static Set<ContextSpecific> deserializeIntoSet(ObjectInputFilter filter, InputStream... inputStreams) {
|
||||
Set<ContextSpecific> set = new TreeSet<>();
|
||||
|
||||
for (InputStream inputStream : inputStreams) {
|
||||
Object object = deserialize(inputStream, filter);
|
||||
if (object != null) {
|
||||
set.add((ContextSpecific) object);
|
||||
}
|
||||
}
|
||||
|
||||
return set;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package com.baeldung.deserializationfilters.utils;
|
||||
|
||||
import java.io.ObjectInputFilter;
|
||||
|
||||
public class FilterUtils {
|
||||
|
||||
private static final String DEFAULT_PACKAGE_PATTERN = "java.base/*;!*";
|
||||
private static final String POJO_PACKAGE = "com.baeldung.deserializationfilters.pojo";
|
||||
|
||||
private FilterUtils() {
|
||||
}
|
||||
|
||||
private static ObjectInputFilter baseFilter(String parameter, int max) {
|
||||
return ObjectInputFilter.Config.createFilter(String.format("%s=%d;%s.**;%s", parameter, max, POJO_PACKAGE, DEFAULT_PACKAGE_PATTERN));
|
||||
}
|
||||
|
||||
public static ObjectInputFilter fallbackFilter() {
|
||||
return ObjectInputFilter.Config.createFilter(String.format("%s", DEFAULT_PACKAGE_PATTERN));
|
||||
}
|
||||
|
||||
public static ObjectInputFilter safeSizeFilter(int max) {
|
||||
return baseFilter("maxbytes", max);
|
||||
}
|
||||
|
||||
public static ObjectInputFilter safeArrayFilter(int max) {
|
||||
return baseFilter("maxarray", max);
|
||||
}
|
||||
|
||||
public static ObjectInputFilter safeDepthFilter(int max) {
|
||||
return baseFilter("maxdepth", max);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.baeldung.deserializationfilters.utils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class SerializationUtils {
|
||||
|
||||
private SerializationUtils() {
|
||||
}
|
||||
|
||||
public static void serialize(Object object, OutputStream outStream) throws IOException {
|
||||
try (ObjectOutputStream objStream = new ObjectOutputStream(outStream)) {
|
||||
objStream.writeObject(object);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
package com.baeldung.deserializationfilters;
|
||||
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputFilter;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.baeldung.deserializationfilters.pojo.ContextSpecific;
|
||||
import com.baeldung.deserializationfilters.pojo.NestedSample;
|
||||
import com.baeldung.deserializationfilters.pojo.Sample;
|
||||
import com.baeldung.deserializationfilters.pojo.SampleExploit;
|
||||
import com.baeldung.deserializationfilters.service.LimitedArrayService;
|
||||
import com.baeldung.deserializationfilters.service.LowDepthService;
|
||||
import com.baeldung.deserializationfilters.service.SmallObjectService;
|
||||
import com.baeldung.deserializationfilters.utils.DeserializationUtils;
|
||||
import com.baeldung.deserializationfilters.utils.FilterUtils;
|
||||
import com.baeldung.deserializationfilters.utils.SerializationUtils;
|
||||
|
||||
public class ContextSpecificDeserializationFilterIntegrationTest {
|
||||
|
||||
private static ByteArrayOutputStream serialSampleA = new ByteArrayOutputStream();
|
||||
private static ByteArrayOutputStream serialBigSampleA = new ByteArrayOutputStream();
|
||||
|
||||
private static ByteArrayOutputStream serialSampleB = new ByteArrayOutputStream();
|
||||
private static ByteArrayOutputStream serialBigSampleB = new ByteArrayOutputStream();
|
||||
|
||||
private static ByteArrayOutputStream serialSampleC = new ByteArrayOutputStream();
|
||||
private static ByteArrayOutputStream serialBigSampleC = new ByteArrayOutputStream();
|
||||
|
||||
private static ByteArrayInputStream bytes(ByteArrayOutputStream stream) {
|
||||
return new ByteArrayInputStream(stream.toByteArray());
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
static void setup() throws IOException {
|
||||
ObjectInputFilter.Config.setSerialFilterFactory(new ContextSpecificDeserializationFilterFactory());
|
||||
|
||||
SerializationUtils.serialize(new Sample("simple"), serialSampleA);
|
||||
SerializationUtils.serialize(new SampleExploit(), serialBigSampleA);
|
||||
|
||||
SerializationUtils.serialize(new Sample(new int[] { 1, 2, 3 }), serialSampleB);
|
||||
SerializationUtils.serialize(new Sample(new int[] { 1, 2, 3, 4, 5, 6 }), serialBigSampleB);
|
||||
|
||||
SerializationUtils.serialize(new Sample(new NestedSample(null)), serialSampleC);
|
||||
SerializationUtils.serialize(new Sample(new NestedSample(new Sample("deep"))), serialBigSampleC);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenSmallObjectContext_thenCorrectFilterApplied() {
|
||||
Set<ContextSpecific> result = new SmallObjectService().process( //
|
||||
bytes(serialSampleA), //
|
||||
bytes(serialBigSampleA));
|
||||
|
||||
assertEquals(1, result.size());
|
||||
assertEquals("simple", ((Sample) result.iterator()
|
||||
.next()).getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenLimitedArrayContext_thenCorrectFilterApplied() {
|
||||
Set<ContextSpecific> result = new LimitedArrayService().process( //
|
||||
bytes(serialSampleB), //
|
||||
bytes(serialBigSampleB));
|
||||
|
||||
assertEquals(1, result.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenLowDepthContext_thenCorrectFilterApplied() {
|
||||
Set<ContextSpecific> result = new LowDepthService().process( //
|
||||
bytes(serialSampleC), //
|
||||
bytes(serialBigSampleC));
|
||||
|
||||
assertEquals(1, result.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenExtraFilter_whenCombinedContext_thenMergedFiltersApplied() {
|
||||
Set<ContextSpecific> result = new LowDepthService().process( //
|
||||
FilterUtils.safeSizeFilter(190), //
|
||||
bytes(serialSampleA), //
|
||||
bytes(serialBigSampleA), //
|
||||
bytes(serialSampleC), //
|
||||
bytes(serialBigSampleC));
|
||||
|
||||
assertEquals(1, result.size());
|
||||
assertEquals("simple", ((Sample) result.iterator()
|
||||
.next()).getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenFallbackContext_whenUsingBaseClasses_thenRestrictiveFilterApplied() throws IOException {
|
||||
String a = new String("a");
|
||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
|
||||
SerializationUtils.serialize(a, outStream);
|
||||
|
||||
String deserializedA = (String) DeserializationUtils.deserialize(bytes(outStream));
|
||||
|
||||
assertEquals(a, deserializedA);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenFallbackContext_whenUsingAppClasses_thenRejected() throws IOException {
|
||||
Sample a = new Sample("a");
|
||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
|
||||
SerializationUtils.serialize(a, outStream);
|
||||
|
||||
Sample deserializedA = (Sample) DeserializationUtils.deserialize(bytes(outStream));
|
||||
|
||||
assertNull(deserializedA);
|
||||
}
|
||||
}
|
|
@ -18,19 +18,19 @@ public class VehicleUnitTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void givenCar_whenUsingReflectionAPI_thenSuperClassIsSealed() {
|
||||
public void givenCar_whenUsingReflectionAPI_thenSuperClassIsSealed() throws ClassNotFoundException {
|
||||
Assertions.assertThat(car.getClass().isSealed()).isEqualTo(false);
|
||||
Assertions.assertThat(car.getClass().getSuperclass().isSealed()).isEqualTo(true);
|
||||
Assertions.assertThat(car.getClass().getSuperclass().getPermittedSubclasses())
|
||||
.contains(ClassDesc.of(car.getClass().getCanonicalName()));
|
||||
.contains(Class.forName(car.getClass().getCanonicalName()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTruck_whenUsingReflectionAPI_thenSuperClassIsSealed() {
|
||||
public void givenTruck_whenUsingReflectionAPI_thenSuperClassIsSealed() throws ClassNotFoundException {
|
||||
Assertions.assertThat(truck.getClass().isSealed()).isEqualTo(false);
|
||||
Assertions.assertThat(truck.getClass().getSuperclass().isSealed()).isEqualTo(true);
|
||||
Assertions.assertThat(truck.getClass().getSuperclass().getPermittedSubclasses())
|
||||
.contains(ClassDesc.of(truck.getClass().getCanonicalName()));
|
||||
.contains(Class.forName(truck.getClass().getCanonicalName()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -18,19 +18,19 @@ public class VehicleUnitTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void givenCar_whenUsingReflectionAPI_thenInterfaceIsSealed() {
|
||||
public void givenCar_whenUsingReflectionAPI_thenInterfaceIsSealed() throws ClassNotFoundException {
|
||||
Assertions.assertThat(car.getClass().isSealed()).isEqualTo(false);
|
||||
Assertions.assertThat(car.getClass().getInterfaces()[0].isSealed()).isEqualTo(true);
|
||||
Assertions.assertThat(car.getClass().getInterfaces()[0].permittedSubclasses())
|
||||
.contains(ClassDesc.of(car.getClass().getCanonicalName()));
|
||||
Assertions.assertThat(car.getClass().getInterfaces()[0].getPermittedSubclasses())
|
||||
.contains(Class.forName(car.getClass().getCanonicalName()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTruck_whenUsingReflectionAPI_thenInterfaceIsSealed() {
|
||||
public void givenTruck_whenUsingReflectionAPI_thenInterfaceIsSealed() throws ClassNotFoundException {
|
||||
Assertions.assertThat(truck.getClass().isSealed()).isEqualTo(false);
|
||||
Assertions.assertThat(truck.getClass().getInterfaces()[0].isSealed()).isEqualTo(true);
|
||||
Assertions.assertThat(truck.getClass().getInterfaces()[0].permittedSubclasses())
|
||||
.contains(ClassDesc.of(truck.getClass().getCanonicalName()));
|
||||
Assertions.assertThat(truck.getClass().getInterfaces()[0].getPermittedSubclasses())
|
||||
.contains(Class.forName(truck.getClass().getCanonicalName()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -7,4 +7,5 @@
|
|||
- [Difference Between Instant and LocalDateTime](https://www.baeldung.com/java-instant-vs-localdatetime)
|
||||
- [Add Minutes to a Time String in Java](https://www.baeldung.com/java-string-time-add-mins)
|
||||
- [Round the Date in Java](https://www.baeldung.com/java-round-the-date)
|
||||
- [Representing Furthest Possible Date in Java](https://www.baeldung.com/java-date-represent-max)
|
||||
- [[<-- Prev]](/core-java-modules/core-java-datetime-java8-1)
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
|
||||
<properties>
|
||||
<commons-lang.version>2.2</commons-lang.version>
|
||||
<commons-lang3.version>3.12.0</commons-lang3.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -9,4 +9,5 @@
|
|||
- [Skipping the First Iteration in Java](https://www.baeldung.com/java-skip-first-iteration)
|
||||
- [Remove Elements From a Queue Using Loop](https://www.baeldung.com/java-remove-elements-queue)
|
||||
- [Intro to Vector Class in Java](https://www.baeldung.com/java-vector-guide)
|
||||
- [HashSet toArray() Method in Java](https://www.baeldung.com/java-hashset-toarray)
|
||||
- More articles: [[<-- prev]](/core-java-modules/core-java-collections-4)
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
package com.baeldung.collectionssortcomplexity;
|
||||
|
||||
import org.openjdk.jmh.annotations.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
||||
@Fork(value = 1, warmups = 1)
|
||||
@Warmup(iterations = 5, time = 1)
|
||||
@Measurement(iterations = 5, time = 1)
|
||||
public class CollectionsSortTimeComplexityJMH {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
org.openjdk.jmh.Main.main(args);
|
||||
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void measureCollectionsSortBestCase(BestCaseBenchmarkState state) {
|
||||
List<Integer> sortedList = new ArrayList<>(state.sortedList);
|
||||
Collections.sort(sortedList);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void measureCollectionsSortAverageWorstCase(AverageWorstCaseBenchmarkState state) {
|
||||
List<Integer> unsortedList = new ArrayList<>(state.unsortedList);
|
||||
Collections.sort(unsortedList);
|
||||
}
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
public static class BestCaseBenchmarkState {
|
||||
List<Integer> sortedList;
|
||||
|
||||
@Setup(Level.Trial)
|
||||
public void setUp() {
|
||||
sortedList = new ArrayList<>();
|
||||
for (int i = 1; i <= 1000000; i++) {
|
||||
sortedList.add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
public static class AverageWorstCaseBenchmarkState {
|
||||
List<Integer> unsortedList;
|
||||
|
||||
@Setup(Level.Trial)
|
||||
public void setUp() {
|
||||
unsortedList = new ArrayList<>();
|
||||
for (int i = 1000000; i > 0; i--) {
|
||||
unsortedList.add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.baeldung.collectionssortcomplexity;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class CollectionsSortTimeComplexityMain {
|
||||
// O(n log n) Time Complexity Example
|
||||
public static void worstAndAverageCasesTimeComplexity() {
|
||||
Integer[] sortedArray = {20, 21, 22, 23, 24, 25, 26, 17, 28, 29, 30, 31, 18, 19, 32, 33, 34, 27, 35};
|
||||
List<Integer> list = Arrays.asList(sortedArray);
|
||||
Collections.shuffle(list);
|
||||
long startTime = System.nanoTime();
|
||||
Collections.sort(list);
|
||||
long endTime = System.nanoTime();
|
||||
System.out.println("Execution Time for O(n log n): " + (endTime - startTime) + " nanoseconds");
|
||||
}
|
||||
|
||||
// O(n) Time Complexity Example
|
||||
public static void bestCaseTimeComplexity() {
|
||||
Integer[] sortedArray = {19, 22, 19, 22, 24, 25, 17, 11, 22, 23, 28, 23, 0, 1, 12, 9, 13, 27, 15};
|
||||
List<Integer> list = Arrays.asList(sortedArray);
|
||||
long startTime = System.nanoTime();
|
||||
Collections.sort(list);
|
||||
long endTime = System.nanoTime();
|
||||
System.out.println("Execution Time for O(n): " + (endTime - startTime) + " nanoseconds");
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
worstAndAverageCasesTimeComplexity();
|
||||
bestCaseTimeComplexity();
|
||||
}
|
||||
}
|
|
@ -66,7 +66,6 @@
|
|||
<properties>
|
||||
<jmh.version>1.21</jmh.version>
|
||||
<commons-lang.version>2.2</commons-lang.version>
|
||||
<commons-lang3.version>3.12.0</commons-lang3.version>
|
||||
<gson.version>2.10.1</gson.version>
|
||||
<jackson.version>2.15.2</jackson.version>
|
||||
<org.json.version>20230618</org.json.version>
|
||||
|
|
|
@ -33,6 +33,11 @@
|
|||
<artifactId>commons-csv</artifactId>
|
||||
<version>${csv.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>32.1.2-jre</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
package com.baeldung.map;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class BenchmarkMapMethods {
|
||||
public static void main(String[] args) {
|
||||
BenchmarkMapMethods bmm = new BenchmarkMapMethods();
|
||||
Map<String, Long> map = new HashMap<>();
|
||||
map.put("Guava", bmm.benchMarkGuavaMap());
|
||||
map.put("ContainsKey", bmm.benchContainsKeyMap());
|
||||
map.put("MergeMethod", bmm.benchMarkMergeMethod());
|
||||
map.put("ComputeMethod", bmm.benchMarComputeMethod());
|
||||
map.put("GetOrDefault", bmm.benchMarkGetOrDefaultMethod());
|
||||
}
|
||||
|
||||
private long benchMarkGuavaMap() {
|
||||
long startTime = System.nanoTime();
|
||||
IncrementMapValueWays im = new IncrementMapValueWays();
|
||||
im.charFrequencyUsingAtomicMap(getString());
|
||||
long endTime = System.nanoTime();
|
||||
return endTime - startTime;
|
||||
}
|
||||
|
||||
private long benchContainsKeyMap() {
|
||||
long startTime = System.nanoTime();
|
||||
IncrementMapValueWays im = new IncrementMapValueWays();
|
||||
im.charFrequencyUsingContainsKey(getString());
|
||||
long endTime = System.nanoTime();
|
||||
return endTime - startTime;
|
||||
}
|
||||
|
||||
private long benchMarComputeMethod() {
|
||||
long startTime = System.nanoTime();
|
||||
IncrementMapValueWays im = new IncrementMapValueWays();
|
||||
im.charFrequencyUsingCompute(getString());
|
||||
long endTime = System.nanoTime();
|
||||
return endTime - startTime;
|
||||
}
|
||||
|
||||
private long benchMarkMergeMethod() {
|
||||
long startTime = System.nanoTime();
|
||||
IncrementMapValueWays im = new IncrementMapValueWays();
|
||||
im.charFrequencyUsingMerge(getString());
|
||||
long endTime = System.nanoTime();
|
||||
return endTime - startTime;
|
||||
}
|
||||
|
||||
private long benchMarkGetOrDefaultMethod() {
|
||||
long startTime = System.nanoTime();
|
||||
IncrementMapValueWays im = new IncrementMapValueWays();
|
||||
im.charFrequencyUsingGetOrDefault(getString());
|
||||
long endTime = System.nanoTime();
|
||||
return endTime - startTime;
|
||||
}
|
||||
|
||||
private String getString() {
|
||||
return
|
||||
"Once upon a time in a quaint village nestled between rolling hills and whispering forests, there lived a solitary storyteller named Elias. Elias was known for spinning tales that transported listeners to magical realms and awakened forgotten dreams.\n"
|
||||
+ "\n"
|
||||
+ "His favorite spot was beneath an ancient oak tree, its sprawling branches offering shade to those who sought refuge from the bustle of daily life. Villagers of all ages would gather around Elias, their faces illuminated by the warmth of his stories.\n"
|
||||
+ "\n" + "One evening, as dusk painted the sky in hues of orange and purple, a curious young girl named Lily approached Elias. Her eyes sparkled with wonder as she asked for a tale unlike any other.\n" + "\n"
|
||||
+ "Elias smiled, sensing her thirst for adventure, and began a story about a forgotten kingdom veiled by mist, guarded by mystical creatures and enchanted by ancient spells. With each word, the air grew thick with anticipation, and the listeners were transported into a world where magic danced on the edges of reality.\n"
|
||||
+ "\n" + "As Elias weaved the story, Lily's imagination took flight. She envisioned herself as a brave warrior, wielding a shimmering sword against dark forces, her heart fueled by courage and kindness.\n" + "\n"
|
||||
+ "The night wore on, but the spell of the tale held everyone captive. The villagers laughed, gasped, and held their breaths, journeying alongside the characters through trials and triumphs.\n" + "\n"
|
||||
+ "As the final words lingered in the air, a sense of enchantment settled upon the listeners. They thanked Elias for the gift of his storytelling, each carrying a piece of the magical kingdom within their hearts.\n" + "\n"
|
||||
+ "Lily, inspired by the story, vowed to cherish the spirit of adventure and kindness in her own life. With a newfound spark in her eyes, she bid Elias goodnight, already dreaming of the countless adventures awaiting her.\n" + "\n"
|
||||
+ "Under the star-studded sky, Elias remained beneath the ancient oak, his heart aglow with the joy of sharing tales that ignited imagination and inspired dreams. And as the night embraced the village, whispers of the enchanted kingdom lingered in the breeze, promising endless possibilities to those who dared to believe.";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
package com.baeldung.map;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import com.google.common.util.concurrent.AtomicLongMap;
|
||||
|
||||
public class IncrementMapValueWays {
|
||||
|
||||
public Map<Character, Integer> charFrequencyUsingContainsKey(String sentence) {
|
||||
Map<Character, Integer> charMap = new HashMap<>();
|
||||
for (int c = 0; c < sentence.length(); c++) {
|
||||
int count = 0;
|
||||
if (charMap.containsKey(sentence.charAt(c))) {
|
||||
count = charMap.get(sentence.charAt(c));
|
||||
}
|
||||
charMap.put(sentence.charAt(c), count + 1);
|
||||
}
|
||||
return charMap;
|
||||
}
|
||||
|
||||
public Map<Character, Integer> charFrequencyUsingGetOrDefault(String sentence) {
|
||||
Map<Character, Integer> charMap = new HashMap<>();
|
||||
for (int c = 0; c < sentence.length(); c++) {
|
||||
charMap.put(sentence.charAt(c), charMap.getOrDefault(sentence.charAt(c), 0) + 1);
|
||||
}
|
||||
return charMap;
|
||||
}
|
||||
|
||||
public Map<Character, Integer> charFrequencyUsingMerge(String sentence) {
|
||||
Map<Character, Integer> charMap = new HashMap<>();
|
||||
for (int c = 0; c < sentence.length(); c++) {
|
||||
charMap.merge(sentence.charAt(c), 1, Integer::sum);
|
||||
}
|
||||
return charMap;
|
||||
}
|
||||
|
||||
public Map<Character, Integer> charFrequencyUsingCompute(String sentence) {
|
||||
Map<Character, Integer> charMap = new HashMap<>();
|
||||
for (int c = 0; c < sentence.length(); c++) {
|
||||
charMap.compute(sentence.charAt(c), (key, value) -> (value == null) ? 1 : value + 1);
|
||||
}
|
||||
return charMap;
|
||||
}
|
||||
|
||||
public Map<Character, Long> charFrequencyUsingAtomicMap(String sentence) {
|
||||
AtomicLongMap<Character> map = AtomicLongMap.create();
|
||||
for (int c = 0; c < sentence.length(); c++) {
|
||||
map.getAndIncrement(sentence.charAt(c));
|
||||
}
|
||||
return map.asMap();
|
||||
}
|
||||
|
||||
public Map<Character, Integer> charFrequencyWithConcurrentMap(String sentence, Map<Character, Integer> charMap) {
|
||||
for (int c = 0; c < sentence.length(); c++) {
|
||||
charMap.compute(sentence.charAt(c), (key, value) -> (value == null) ? 1 : value + 1);
|
||||
}
|
||||
return charMap;
|
||||
}
|
||||
|
||||
public Map<Character, AtomicInteger> charFrequencyWithGetAndIncrement(String sentence) {
|
||||
Map<Character, AtomicInteger> charMap = new HashMap<>();
|
||||
for (int c = 0; c < sentence.length(); c++) {
|
||||
charMap.putIfAbsent(sentence.charAt(c), new AtomicInteger(0));
|
||||
charMap.get(sentence.charAt(c))
|
||||
.incrementAndGet();
|
||||
}
|
||||
return charMap;
|
||||
}
|
||||
|
||||
public Map<Character, AtomicInteger> charFrequencyWithGetAndIncrementComputeIfAbsent(String sentence) {
|
||||
Map<Character, AtomicInteger> charMap = new HashMap<>();
|
||||
for (int c = 0; c < sentence.length(); c++) {
|
||||
charMap.computeIfAbsent(sentence.charAt(c), k -> new AtomicInteger(0))
|
||||
.incrementAndGet();
|
||||
}
|
||||
return charMap;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
package com.baeldung.map;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class IncrementMapValueUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenString_whenUsingContainsKey_thenReturnFreqMap() {
|
||||
String string = "the quick brown fox jumps over the lazy dog";
|
||||
IncrementMapValueWays ic = new IncrementMapValueWays();
|
||||
Map<Character, Integer> actualMap = ic.charFrequencyUsingContainsKey(string);
|
||||
Map<Character, Integer> expectedMap = getExpectedMap();
|
||||
Assert.assertEquals(expectedMap, actualMap);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenString_whenUsingGetOrDefault_thenReturnFreqMap() {
|
||||
String string = "the quick brown fox jumps over the lazy dog";
|
||||
IncrementMapValueWays ic = new IncrementMapValueWays();
|
||||
Map<Character, Integer> actualMap = ic.charFrequencyUsingGetOrDefault(string);
|
||||
Map<Character, Integer> expectedMap = getExpectedMap();
|
||||
Assert.assertEquals(expectedMap, actualMap);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenString_whenUsingMapMerge_thenReturnFreqMap() {
|
||||
String string = "the quick brown fox jumps over the lazy dog";
|
||||
IncrementMapValueWays ic = new IncrementMapValueWays();
|
||||
Map<Character, Integer> actualMap = ic.charFrequencyUsingMerge(string);
|
||||
Map<Character, Integer> expectedMap = getExpectedMap();
|
||||
Assert.assertEquals(expectedMap, actualMap);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenString_whenUsingMapCompute_thenReturnFreqMap() {
|
||||
String string = "the quick brown fox jumps over the lazy dog";
|
||||
IncrementMapValueWays ic = new IncrementMapValueWays();
|
||||
Map<Character, Integer> actualMap = ic.charFrequencyUsingCompute(string);
|
||||
Map<Character, Integer> expectedMap = getExpectedMap();
|
||||
Assert.assertEquals(expectedMap, actualMap);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenString_whenUsingGuava_thenReturnFreqMap() {
|
||||
String string = "the quick brown fox jumps over the lazy dog";
|
||||
IncrementMapValueWays ic = new IncrementMapValueWays();
|
||||
Map<Character, Long> actualMap = ic.charFrequencyUsingAtomicMap(string);
|
||||
Map<Character, Integer> expectedMap = getExpectedMap();
|
||||
Assert.assertEquals(expectedMap.keySet(), actualMap.keySet());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenString_whenUsingIncrementAndGet_thenReturnFreqMap() {
|
||||
String string = "the quick brown fox jumps over the lazy dog";
|
||||
IncrementMapValueWays ic = new IncrementMapValueWays();
|
||||
Map<Character, AtomicInteger> actualMap = ic.charFrequencyWithGetAndIncrement(string);
|
||||
Assert.assertEquals(getExpectedMap().keySet(), actualMap.keySet());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenString_whenUsingIncrementAndGetAndComputeIfAbsent_thenReturnFreqMap() {
|
||||
String string = "the quick brown fox jumps over the lazy dog";
|
||||
IncrementMapValueWays ic = new IncrementMapValueWays();
|
||||
Map<Character, AtomicInteger> actualMap = ic.charFrequencyWithGetAndIncrementComputeIfAbsent(string);
|
||||
Assert.assertEquals(getExpectedMap().keySet(), actualMap.keySet());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenString_whenUsingConcurrentMapCompute_thenReturnFreqMap() throws InterruptedException {
|
||||
Map<Character, Integer> charMap = new ConcurrentHashMap<>();
|
||||
Thread thread1 = new Thread(() -> {
|
||||
IncrementMapValueWays ic = new IncrementMapValueWays();
|
||||
ic.charFrequencyWithConcurrentMap("the quick brown", charMap);
|
||||
});
|
||||
|
||||
Thread thread2 = new Thread(() -> {
|
||||
IncrementMapValueWays ic = new IncrementMapValueWays();
|
||||
ic.charFrequencyWithConcurrentMap(" fox jumps over the lazy dog", charMap);
|
||||
});
|
||||
|
||||
thread1.start();
|
||||
thread2.start();
|
||||
thread1.join();
|
||||
thread2.join();
|
||||
|
||||
Map<Character, Integer> expectedMap = getExpectedMap();
|
||||
Assert.assertEquals(expectedMap, charMap);
|
||||
}
|
||||
|
||||
private Map<Character, Integer> getExpectedMap() {
|
||||
return Stream.of(
|
||||
new Object[][] { { ' ', 8 }, { 'a', 1 }, { 'b', 1 }, { 'c', 1 }, { 'd', 1 }, { 'e', 3 }, { 'f', 1 }, { 'g', 1 }, { 'h', 2 }, { 'i', 1 }, { 'j', 1 }, { 'k', 1 }, { 'l', 1 }, { 'm', 1 }, { 'n', 1 }, { 'o', 4 }, { 'p', 1 }, { 'q', 1 }, { 'r', 2 },
|
||||
{ 's', 1 }, { 't', 2 }, { 'u', 2 }, { 'v', 1 }, { 'w', 1 }, { 'x', 1 }, { 'y', 1 }, { 'z', 1 } })
|
||||
.collect(Collectors.toMap(data -> (Character) data[0], data -> (Integer) data[1]));
|
||||
}
|
||||
}
|
|
@ -12,4 +12,5 @@ This module contains articles about basic Java concurrency.
|
|||
- [CompletableFuture allOf().join() vs. CompletableFuture.join()](https://www.baeldung.com/java-completablefuture-allof-join)
|
||||
- [Retry Logic with CompletableFuture](https://www.baeldung.com/java-completablefuture-retry-logic)
|
||||
- [Convert From List of CompletableFuture to CompletableFuture List](https://www.baeldung.com/java-completablefuture-list-convert)
|
||||
- [Synchronize a Static Variable Among Different Threads](https://www.baeldung.com/java-synchronize-static-variable-different-threads)
|
||||
- [[<-- Prev]](../core-java-concurrency-basic-2)
|
||||
|
|
|
@ -7,3 +7,4 @@
|
|||
- [ASCII Art in Java](http://www.baeldung.com/ascii-art-in-java)
|
||||
- [System.console() vs. System.out](https://www.baeldung.com/java-system-console-vs-system-out)
|
||||
- [How to Log to the Console in Color](https://www.baeldung.com/java-log-console-in-color)
|
||||
- [Create Table Using ASCII in a Console in Java](https://www.baeldung.com/java-console-ascii-make-table)
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
<properties>
|
||||
<joda-time.version>2.12.5</joda-time.version>
|
||||
<commons-lang3.version>3.12.0</commons-lang3.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -1,32 +1,31 @@
|
|||
package com.baeldung.timestamptolong;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Date;
|
||||
|
||||
public class TimestampToLong {
|
||||
public void usingSimpleDateFormat() throws ParseException {
|
||||
|
||||
public long usingSimpleDateFormat(String timestampString) throws ParseException {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
String currentDateString = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
|
||||
long actualTimestamp = sdf.parse(currentDateString).getTime();
|
||||
Date date = sdf.parse(timestampString);
|
||||
String currentDateString = sdf.format(date);
|
||||
return sdf.parse(currentDateString).getTime();
|
||||
}
|
||||
|
||||
public void usingInstantClass() {
|
||||
Instant instant = Instant.now();
|
||||
long actualTimestamp = instant.toEpochMilli();
|
||||
public long usingInstantClass(String timestampString) {
|
||||
Instant instant = LocalDateTime.parse(timestampString, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
|
||||
.atZone(ZoneId.systemDefault())
|
||||
.toInstant();
|
||||
return instant.toEpochMilli();
|
||||
}
|
||||
|
||||
public void usingTimestamp() {
|
||||
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
|
||||
long actualTimestamp = timestamp.getTime();
|
||||
public long usingJava8DateTime(String timestampString) {
|
||||
LocalDateTime localDateTime = LocalDateTime.parse(timestampString.replace(" ", "T"));
|
||||
return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
|
||||
}
|
||||
|
||||
public void usingJava8DateTime() {
|
||||
LocalDateTime localDateTime = LocalDateTime.now();
|
||||
long actualTimestamp = localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,51 +2,42 @@ package com.baeldung.timestamptolong;
|
|||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Date;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class TimestampToLongUnitTest {
|
||||
|
||||
private static final long TOLERANCE = 1000;
|
||||
private static final String timestampString = "2023-11-15 01:02:03";
|
||||
|
||||
@Test
|
||||
public void givenSimpleDateFormat_whenFormattingDate_thenTConvertToLong() throws ParseException {
|
||||
public void givenSimpleDateFormat_whenFormattingDate_thenConvertToLong() throws ParseException {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
Date date = sdf.parse(timestampString);
|
||||
|
||||
String currentDateString = sdf.format(new Date());
|
||||
String currentDateString = sdf.format(date);
|
||||
long actualTimestamp = sdf.parse(currentDateString).getTime();
|
||||
|
||||
assertTrue(Math.abs(System.currentTimeMillis() - actualTimestamp) < TOLERANCE);
|
||||
assertEquals(1700010123000L, actualTimestamp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenInstantClass_whenGettingTimestamp_thenTConvertToLong() {
|
||||
Instant instant = Instant.now();
|
||||
public void givenInstantClass_whenGettingTimestamp_thenConvertToLong() {
|
||||
Instant instant = LocalDateTime.parse(timestampString, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
|
||||
.atZone(ZoneId.systemDefault())
|
||||
.toInstant();
|
||||
long actualTimestamp = instant.toEpochMilli();
|
||||
|
||||
assertTrue(Math.abs(System.currentTimeMillis() - actualTimestamp) < TOLERANCE);
|
||||
assertEquals(1700010123000L, actualTimestamp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTimestamp_whenCreatingTimestamp_thenTConvertToLong() {
|
||||
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
|
||||
long actualTimestamp = timestamp.getTime();
|
||||
|
||||
assertTrue(Math.abs(System.currentTimeMillis() - actualTimestamp) < TOLERANCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenJava8DateTime_whenGettingTimestamp_thenTConvertToLong() {
|
||||
LocalDateTime localDateTime = LocalDateTime.now();
|
||||
public void givenJava8DateTime_whenGettingTimestamp_thenConvertToLong() {
|
||||
LocalDateTime localDateTime = LocalDateTime.parse(timestampString.replace(" ", "T"));
|
||||
long actualTimestamp = localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
|
||||
|
||||
assertTrue(Math.abs(System.currentTimeMillis() - actualTimestamp) < TOLERANCE);
|
||||
assertEquals(1700010123000L, actualTimestamp);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,6 @@
|
|||
<properties>
|
||||
<mockito-inline.version>3.8.0</mockito-inline.version>
|
||||
<assertj.version>3.22.0</assertj.version>
|
||||
<commons-lang3.version>3.12.0</commons-lang3.version>
|
||||
<vavr.version>0.10.4</vavr.version>
|
||||
</properties>
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
<properties>
|
||||
<mockito-inline.version>3.8.0</mockito-inline.version>
|
||||
<assertj.version>3.22.0</assertj.version>
|
||||
<commons-lang3.version>3.12.0</commons-lang3.version>
|
||||
<vavr.version>0.10.4</vavr.version>
|
||||
</properties>
|
||||
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
## Relevant Articles
|
||||
- [Convert Hex to RGB Using Java](https://www.baeldung.com/java-convert-hex-to-rgb)
|
||||
- [Convert a Hex String to an Integer in Java](https://www.baeldung.com/java-convert-hex-string-to-integer)
|
||||
|
|
|
@ -12,4 +12,5 @@ This module contains articles about core Java input/output(IO) conversions.
|
|||
- [How to Convert InputStream to Base64 String](https://www.baeldung.com/java-inputstream-to-base64-string)
|
||||
- [Convert an OutputStream to an InputStream](https://www.baeldung.com/java-convert-outputstream-to-inputstream)
|
||||
- [Java PrintStream to String](https://www.baeldung.com/java-printstream-to-string)
|
||||
- [Convert File to Byte Array in Java](https://www.baeldung.com/java-convert-file-byte-array)
|
||||
- More articles: [[<-- prev]](/core-java-modules/core-java-io-conversions)
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
</build>
|
||||
|
||||
<properties>
|
||||
<commons-lang3.version>3.12.0</commons-lang3.version>
|
||||
<reflections.version>0.10.2</reflections.version>
|
||||
</properties>
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
<async-http-client.version>2.4.5</async-http-client.version>
|
||||
<jakarta.bind.version>2.3.3</jakarta.bind.version>
|
||||
<greenmail.version>2.0.0-alpha-3</greenmail.version>
|
||||
<commons-codec.version>1.15</commons-codec.version>
|
||||
<commons-codec.version>1.16.0</commons-codec.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -7,4 +7,5 @@
|
|||
- [Java Double vs. BigDecimal](https://www.baeldung.com/java-double-vs-bigdecimal)
|
||||
- [Finding the Square Root of a BigInteger in Java](https://www.baeldung.com/java-find-square-root-biginteger)
|
||||
- [Truncate a Double to Two Decimal Places in Java](https://www.baeldung.com/java-double-round-two-decimal-places)
|
||||
- [Comparing the Values of Two Generic Numbers in Java](https://www.baeldung.com/java-generic-numbers-comparison-methods)
|
||||
- More articles: [[<-- prev]](../core-java-numbers-5)
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
</build>
|
||||
|
||||
<properties>
|
||||
<commons-codec>1.15</commons-codec>
|
||||
<guava.version>32.1.2-jre</guava.version>
|
||||
<commons-codec>1.16.0</commons-codec>
|
||||
</properties>
|
||||
</project>
|
|
@ -52,7 +52,6 @@
|
|||
<source.version>1.8</source.version>
|
||||
<target.version>1.8</target.version>
|
||||
<reflections.version>0.10.2</reflections.version>
|
||||
<commons-lang3.version>3.12.0</commons-lang3.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -21,7 +21,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
<artifactId>bcprov-jdk18on</artifactId>
|
||||
<version>${bouncycastle.version}</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
|
||||
|
@ -33,8 +33,8 @@
|
|||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<bouncycastle.version>1.60</bouncycastle.version>
|
||||
<commons-codec.version>1.11</commons-codec.version>
|
||||
<bouncycastle.version>1.76</bouncycastle.version>
|
||||
<commons-codec.version>1.16.0</commons-codec.version>
|
||||
<jaxb-api.version>2.3.1</jaxb-api.version>
|
||||
</properties>
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
<artifactId>bcprov-jdk18on</artifactId>
|
||||
<version>${bouncycastle.version}</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
|
||||
|
@ -43,8 +43,8 @@
|
|||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<bouncycastle.version>1.70</bouncycastle.version>
|
||||
<commons-codec.version>1.15</commons-codec.version>
|
||||
<bouncycastle.version>1.76</bouncycastle.version>
|
||||
<commons-codec.version>1.16.0</commons-codec.version>
|
||||
<jaxb-api.version>2.3.1</jaxb-api.version>
|
||||
<spring-security-crypto.version>6.0.3</spring-security-crypto.version>
|
||||
</properties>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcpkix-jdk15on</artifactId>
|
||||
<artifactId>bcpkix-jdk18on</artifactId>
|
||||
<version>${bouncycastle.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -27,7 +27,7 @@
|
|||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<bouncycastle.version>1.70</bouncycastle.version>
|
||||
<bouncycastle.version>1.76</bouncycastle.version>
|
||||
<cryptacular.version>1.2.6</cryptacular.version>
|
||||
</properties>
|
||||
|
||||
|
|
|
@ -7,3 +7,4 @@
|
|||
- [Taking Every N-th Element from Finite and Infinite Streams in Java](https://www.baeldung.com/java-nth-element-finite-infinite-streams)
|
||||
- [Modifying Objects Within Stream While Iterating](https://www.baeldung.com/java-stream-modify-objects-during-iteration)
|
||||
- [Convert a Stream into a Map or Multimap in Java](https://www.baeldung.com/java-convert-stream-map-multimap)
|
||||
- [How to Avoid NoSuchElementException in Stream API](https://www.baeldung.com/java-streams-api-avoid-nosuchelementexception)
|
||||
|
|
|
@ -77,7 +77,6 @@
|
|||
<maven.compiler.source>12</maven.compiler.source>
|
||||
<maven.compiler.target>12</maven.compiler.target>
|
||||
<vavr.version>0.10.2</vavr.version>
|
||||
<guava.version>32.1.2-jre</guava.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -21,7 +21,7 @@
|
|||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${apache-commons-lang3.version}</version>
|
||||
<version>${commons-lang3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.vdurmont</groupId>
|
||||
|
@ -61,7 +61,6 @@
|
|||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<validator.version>1.7</validator.version>
|
||||
<apache-commons-lang3.version>3.12.0</apache-commons-lang3.version>
|
||||
<emoji-java.version>5.1.1</emoji-java.version>
|
||||
<apache-commons-text.version>1.10.0</apache-commons-text.version>
|
||||
</properties>
|
||||
|
|
|
@ -87,7 +87,7 @@
|
|||
<properties>
|
||||
<hibernate-validator.version>8.0.1.Final</hibernate-validator.version>
|
||||
<expressly.version>5.0.0</expressly.version>
|
||||
<commons-codec.version>1.14</commons-codec.version>
|
||||
<commons-codec.version>1.16.0</commons-codec.version>
|
||||
<spring-core.version>5.3.0</spring-core.version>
|
||||
</properties>
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${apache-commons-lang3.version}</version>
|
||||
<version>${commons-lang3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
|
@ -70,7 +70,6 @@
|
|||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<spring-core.version>5.3.9</spring-core.version>
|
||||
<apache-commons-lang3.version>3.12.0</apache-commons-lang3.version>
|
||||
<maven-artifact.version>3.6.3</maven-artifact.version>
|
||||
<gradle-core.version>6.1.1</gradle-core.version>
|
||||
<jackson-core.version>2.11.1</jackson-core.version>
|
||||
|
|
|
@ -27,12 +27,12 @@
|
|||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${apache-commons-lang3.version}</version>
|
||||
<version>${commons-lang3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-text</artifactId>
|
||||
<version>${apache-commons-text.version}</version>
|
||||
<version>${commons-text.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
|
@ -60,8 +60,7 @@
|
|||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<opencsv.version>5.8</opencsv.version>
|
||||
<spring-core.version>5.3.13</spring-core.version>
|
||||
<apache-commons-lang3.version>3.12.0</apache-commons-lang3.version>
|
||||
<apache-commons-text.version>1.10.0</apache-commons-text.version>
|
||||
<commons-text.version>1.10.0</commons-text.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -11,4 +11,3 @@
|
|||
- [Check if a String Has All Unique Characters in Java](https://www.baeldung.com/java-check-string-all-unique-chars)
|
||||
- [Performance Comparison Between Different Java String Concatenation Methods](https://www.baeldung.com/java-string-concatenation-methods)
|
||||
- [Replacing Single Quote with \’ in Java String](https://www.baeldung.com/java-replacing-single-quote-string)
|
||||
- [Check if a String Contains a Number Value in Java](https://www.baeldung.com/java-string-number-presence)
|
||||
|
|
|
@ -3,3 +3,5 @@
|
|||
- [How to Center Text Output in Java](https://www.baeldung.com/java-center-text-output)
|
||||
- [Capitalize the First Letter of Each Word in a String](https://www.baeldung.com/java-string-initial-capital-letter-every-word)
|
||||
- [Check if a String Contains Only Unicode Letters](https://www.baeldung.com/java-string-all-unicode-characters)
|
||||
- [Create a Mutable String in Java](https://www.baeldung.com/java-mutable-string)
|
||||
- [Check if a String Contains a Number Value in Java](https://www.baeldung.com/java-string-number-presence)
|
||||
|
|
|
@ -5,4 +5,6 @@ This module contains articles about the sun package
|
|||
### Relevant Articles:
|
||||
|
||||
- [Creating a Java Compiler Plugin](http://www.baeldung.com/java-build-compiler-plugin)
|
||||
- [Guide to sun.misc.Unsafe](http://www.baeldung.com/java-unsafe)
|
||||
- [Guide to sun.misc.Unsafe](http://www.baeldung.com/java-unsafe)
|
||||
- [Why Is sun.misc.Unsafe.park Actually Unsafe?](https://www.baeldung.com/java-sun-misc-unsafe-park-reason)
|
||||
- [Sharing Memory Between JVMs](https://www.baeldung.com/java-sharing-memory-between-jvms)
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<guava.version>32.1.2-jre</guava.version>
|
||||
<guava.version>32.1.3-jre</guava.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -49,7 +49,7 @@
|
|||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<guava.version>32.1.2-jre</guava.version>
|
||||
<guava.version>32.1.3-jre</guava.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -0,0 +1 @@
|
|||
!gradle-wrapper.jar
|
|
@ -1,5 +1,7 @@
|
|||
### Relevant Articles:
|
||||
|
||||
This module is using gradle-8.3.
|
||||
|
||||
- [Run a Java main Method Using Gradle](https://www.baeldung.com/gradle-run-java-main)
|
||||
- [Finding Unused Gradle Dependencies](https://www.baeldung.com/gradle-finding-unused-dependencies)
|
||||
- [Intro to Gradle Lint Plugin](https://www.baeldung.com/java-gradle-lint-intro)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
BIN
gradle-modules/gradle-customization/gradle-protobuf/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle-modules/gradle-customization/gradle-protobuf/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
|
@ -1,5 +1,7 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
//This default Shipkit configuration file was created automatically and is intended to be checked-in.
|
||||
//Default configuration is sufficient for local testing and trying out Shipkit.
|
||||
//To leverage Shipkit fully, please fix the TODO items, refer to our Getting Started Guide for help:
|
||||
//
|
||||
// https://github.com/mockito/shipkit/blob/master/docs/getting-started.md
|
||||
//
|
||||
shipkit {
|
||||
//TODO is the repository correct?
|
||||
gitHub.repository = "unspecified-user/unspecified-repo"
|
||||
|
||||
//TODO generate and use your own read-only GitHub personal access token
|
||||
gitHub.readOnlyAuthToken = "76826c9ec886612f504d12fd4268b16721c4f85d"
|
||||
|
||||
//TODO generate GitHub write token, and ensure your Travis CI has this env variable exported
|
||||
gitHub.writeAuthToken = System.getenv("GH_WRITE_TOKEN")
|
||||
}
|
||||
|
||||
allprojects {
|
||||
plugins.withId("com.jfrog.bintray") {
|
||||
|
||||
//Bintray configuration is handled by JFrog Bintray Gradle Plugin
|
||||
//For reference see the official documentation: https://github.com/bintray/gradle-bintray-plugin
|
||||
bintray {
|
||||
|
||||
//TODO sign up for free open source account with https://bintray.com, then look up your API key on your profile page in Bintray
|
||||
key = '7ea297848ca948adb7d3ee92a83292112d7ae989'
|
||||
//TODO don't check in the key, remove above line and use env variable exported on CI:
|
||||
//key = System.getenv("BINTRAY_API_KEY")
|
||||
|
||||
pkg {
|
||||
//TODO configure Bintray settings per your project (https://github.com/bintray/gradle-bintray-plugin)
|
||||
repo = 'bootstrap'
|
||||
user = 'shipkit-bootstrap-bot'
|
||||
userOrg = 'shipkit-bootstrap'
|
||||
name = 'maven'
|
||||
licenses = ['MIT']
|
||||
labels = ['continuous delivery', 'release automation', 'shipkit']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -1,6 +1,7 @@
|
|||
#Thu Oct 12 16:43:02 BDT 2017
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.2.1-bin.zip
|
||||
|
|
|
@ -205,7 +205,7 @@
|
|||
<properties>
|
||||
<java.version>17</java.version>
|
||||
<!-- util -->
|
||||
<commons-codec.version>1.10</commons-codec.version>
|
||||
<commons-codec.version>1.16.0</commons-codec.version>
|
||||
<!-- testing -->
|
||||
<wiremock.version>2.5.1</wiremock.version>
|
||||
<!-- http client & core 5 -->
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
|
||||
<properties>
|
||||
<gson.version>2.10.1</gson.version>
|
||||
<guava.version>32.1.2-jre</guava.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -74,7 +74,7 @@ public class OpenCsvIntegrationTest {
|
|||
|
||||
assertThat(contents.split(NEW_LINE))
|
||||
.containsExactly(
|
||||
"'colA','colB','colC'",
|
||||
"'COLA','COLB','COLC'",
|
||||
"'Test1','sample','data'",
|
||||
"'Test2','ipso','facto'"
|
||||
);
|
||||
|
|
|
@ -122,7 +122,7 @@
|
|||
<tink.version>1.2.2</tink.version>
|
||||
<cryptacular.version>1.2.2</cryptacular.version>
|
||||
<jasypt.version>1.9.2</jasypt.version>
|
||||
<bouncycastle.version>1.58</bouncycastle.version>
|
||||
<bouncycastle.version>1.68</bouncycastle.version>
|
||||
<jsch.version>0.1.55</jsch.version>
|
||||
<apache-mina.version>2.5.1</apache-mina.version>
|
||||
<spring-security-oauth2.version>2.4.0.RELEASE</spring-security-oauth2.version>
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
### Relevant Articles:
|
||||
- [How to Serialize a Singleton in Java](https://www.baeldung.com/java-serialize-singleton)
|
||||
- [Bill Pugh Singleton Implementation](https://www.baeldung.com/java-bill-pugh-singleton-implementation)
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
<itextpdf.version>5.5.13.3</itextpdf.version>
|
||||
<itextpdf.core.version>7.2.3</itextpdf.core.version>
|
||||
<itextpdf.cleanup.version>3.0.1</itextpdf.cleanup.version>
|
||||
<pdfbox.version>3.0.0-RC1</pdfbox.version>
|
||||
<pdfbox.version>3.0.0</pdfbox.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -1,29 +1,31 @@
|
|||
package com.baeldung.pdfinfo;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
public class PdfInfoITextUnitTest {
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class PdfInfoITextUnitTest {
|
||||
|
||||
private static final String PDF_FILE = "src/test/resources/input.pdf";
|
||||
|
||||
@Test
|
||||
public void givenPdf_whenGetNumberOfPages_thenOK() throws IOException {
|
||||
Assert.assertEquals(4, PdfInfoIText.getNumberOfPages(PDF_FILE));
|
||||
void givenPdf_whenGetNumberOfPages_thenOK() throws IOException {
|
||||
assertEquals(4, PdfInfoIText.getNumberOfPages(PDF_FILE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenPdf_whenIsPasswordRequired_thenOK() throws IOException {
|
||||
Assert.assertFalse(PdfInfoIText.isPasswordRequired(PDF_FILE));
|
||||
void givenPdf_whenIsPasswordRequired_thenOK() throws IOException {
|
||||
assertFalse(PdfInfoIText.isPasswordRequired(PDF_FILE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenPdf_whenGetInfo_thenOK() throws IOException {
|
||||
void givenPdf_whenGetInfo_thenOK() throws IOException {
|
||||
Map<String, String> info = PdfInfoIText.getInfo(PDF_FILE);
|
||||
Assert.assertEquals("LibreOffice 4.2", info.get("Producer"));
|
||||
Assert.assertEquals("Writer", info.get("Creator"));
|
||||
assertEquals("LibreOffice 4.2", info.get("Producer"));
|
||||
assertEquals("Writer", info.get("Creator"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,29 +1,31 @@
|
|||
package com.baeldung.pdfinfo;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class PdfInfoPdfBoxUnitTest {
|
||||
class PdfInfoPdfBoxUnitTest {
|
||||
|
||||
private static final String PDF_FILE = "src/test/resources/input.pdf";
|
||||
|
||||
@Test
|
||||
public void givenPdf_whenGetNumberOfPages_thenOK() throws IOException {
|
||||
Assert.assertEquals(4, PdfInfoPdfBox.getNumberOfPages(PDF_FILE));
|
||||
void givenPdf_whenGetNumberOfPages_thenOK() throws IOException {
|
||||
assertEquals(4, PdfInfoPdfBox.getNumberOfPages(PDF_FILE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenPdf_whenIsPasswordRequired_thenOK() throws IOException {
|
||||
Assert.assertFalse(PdfInfoPdfBox.isPasswordRequired(PDF_FILE));
|
||||
void givenPdf_whenIsPasswordRequired_thenOK() throws IOException {
|
||||
assertFalse(PdfInfoPdfBox.isPasswordRequired(PDF_FILE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenPdf_whenGetInfo_thenOK() throws IOException {
|
||||
void givenPdf_whenGetInfo_thenOK() throws IOException {
|
||||
PDDocumentInformation info = PdfInfoPdfBox.getInfo(PDF_FILE);
|
||||
Assert.assertEquals("LibreOffice 4.2", info.getProducer());
|
||||
Assert.assertEquals("Writer", info.getCreator());
|
||||
assertEquals("LibreOffice 4.2", info.getProducer());
|
||||
assertEquals("Writer", info.getCreator());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,7 +104,7 @@
|
|||
</build>
|
||||
|
||||
<properties>
|
||||
<pdfbox-tools.version>2.0.25</pdfbox-tools.version>
|
||||
<pdfbox-tools.version>3.0.0</pdfbox-tools.version>
|
||||
<pdf2dom.version>2.0.1</pdf2dom.version>
|
||||
<itextpdf.version>5.5.13.3</itextpdf.version>
|
||||
<xmlworker.version>5.5.10</xmlworker.version>
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
## Relevant Articles
|
||||
- [Convert ResultSet Into Map](https://www.baeldung.com/java-resultset-map)
|
|
@ -1,4 +1,5 @@
|
|||
# Relevant Articles
|
||||
- [How to Insert a HashMap Into MongoDB With Java?](https://www.baeldung.com/java-mongodb-insert-hashmap)
|
||||
- [MongoDB – Field Level Encryption](https://www.baeldung.com/mongodb-field-level-encryption)
|
||||
- [MongoDB Atlas Search Using the Java Driver and Spring Data](https://www.baeldung.com/mongodb-spring-data-atlas-search)
|
||||
- More articles: [[<--prev]](../spring-boot-persistence-mongodb-2)
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -1236,7 +1236,7 @@
|
|||
<maven-pmd-plugin.version>3.21.0</maven-pmd-plugin.version>
|
||||
<lombok.version>1.18.28</lombok.version>
|
||||
<h2.version>2.1.214</h2.version>
|
||||
<guava.version>32.1.2-jre</guava.version>
|
||||
<guava.version>32.1.3-jre</guava.version>
|
||||
<maven-jar-plugin.version>3.3.0</maven-jar-plugin.version>
|
||||
</properties>
|
||||
|
||||
|
|
|
@ -21,13 +21,13 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
<version>${bcprov-jdk15on.version}</version>
|
||||
<artifactId>bcprov-jdk18on</artifactId>
|
||||
<version>${bouncycastle.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcpkix-jdk15on</artifactId>
|
||||
<version>${bcpkix-jdk15on.version}</version>
|
||||
<artifactId>bcpkix-jdk18on</artifactId>
|
||||
<version>${bouncycastle.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
@ -69,8 +69,7 @@
|
|||
<httpPort>9080</httpPort>
|
||||
<httpsPort>9443</httpsPort>
|
||||
<nimbus-jose-jwt.version>7.3</nimbus-jose-jwt.version>
|
||||
<bcprov-jdk15on.version>1.62</bcprov-jdk15on.version>
|
||||
<bcpkix-jdk15on.version>1.62</bcpkix-jdk15on.version>
|
||||
<bouncycastle.version>1.76</bouncycastle.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -14,4 +14,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
|
|||
- [Spring Boot – Testing Redis With Testcontainers](https://www.baeldung.com/spring-boot-redis-testcontainers)
|
||||
- [Spring Boot – Keycloak Integration Testing with Testcontainers](https://www.baeldung.com/spring-boot-keycloak-integration-testing)
|
||||
- [Difference Between @Spy and @SpyBean](https://www.baeldung.com/spring-spy-vs-spybean)
|
||||
- [Overriding Spring Beans in Integration Test](https://www.baeldung.com/overriding-spring-beans-in-integration-test)
|
||||
- More articles: [[<-- prev]](../spring-boot-testing)
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
package com.baeldung.overridebean;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class Config {
|
||||
|
||||
@Bean
|
||||
public Service helloWorld() {
|
||||
return new ServiceImpl();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.baeldung.overridebean;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class Endpoint {
|
||||
|
||||
private final Service service;
|
||||
|
||||
public Endpoint(Service service) {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@GetMapping("/hello")
|
||||
public String helloWorldEndpoint() {
|
||||
return service.helloWorld();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package com.baeldung.overridebean;
|
||||
|
||||
public interface Service {
|
||||
String helloWorld();
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package com.baeldung.overridebean;
|
||||
|
||||
public class ServiceImpl implements Service {
|
||||
|
||||
public String helloWorld() {
|
||||
return "hello world";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package com.baeldung.overridebean.boot;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
|
||||
|
||||
@SpringBootApplication(exclude = { SecurityAutoConfiguration.class, OAuth2ResourceServerAutoConfiguration.class })
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.baeldung.overridebean.conditional;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import com.baeldung.overridebean.Service;
|
||||
import com.baeldung.overridebean.ServiceImpl;
|
||||
|
||||
@Configuration
|
||||
public class ConditionalConfig {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(name = "service.stub", havingValue = "false")
|
||||
public Service helloWorld() {
|
||||
return new ServiceImpl();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.baeldung.overridebean.profile;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
|
||||
import com.baeldung.overridebean.Service;
|
||||
import com.baeldung.overridebean.ServiceImpl;
|
||||
|
||||
@Configuration
|
||||
@Profile("prod")
|
||||
public class ProfileConfig {
|
||||
|
||||
@Bean
|
||||
public Service helloWorld() {
|
||||
return new ServiceImpl();
|
||||
}
|
||||
}
|
|
@ -1,2 +1,3 @@
|
|||
keycloak.enabled=true
|
||||
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8180/auth/realms/baeldung-api
|
||||
service.stub=false
|
|
@ -0,0 +1,30 @@
|
|||
package com.baeldung.overridebean.conditional;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import com.baeldung.overridebean.Endpoint;
|
||||
import com.baeldung.overridebean.boot.Application;
|
||||
|
||||
@SpringBootTest(classes = { Application.class, ConditionalConfig.class, Endpoint.class, ConditionalTestConfig.class }, properties = "service.stub=true")
|
||||
@AutoConfigureMockMvc
|
||||
class ConditionIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Test
|
||||
void givenConditionalConfig_whenServiceStubIsTrue_thenStubOk() throws Exception {
|
||||
this.mockMvc.perform(get("/hello"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(containsString("hello conditional stub")));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.baeldung.overridebean.conditional;
|
||||
|
||||
import com.baeldung.overridebean.Service;
|
||||
|
||||
public class ConditionalStub implements Service {
|
||||
|
||||
public String helloWorld() {
|
||||
return "hello conditional stub";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.baeldung.overridebean.conditional;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.test.context.TestConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import com.baeldung.overridebean.Service;
|
||||
|
||||
@TestConfiguration
|
||||
public class ConditionalTestConfig {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(name = "service.stub", havingValue = "true")
|
||||
public Service helloWorld() {
|
||||
return new ConditionalStub();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package com.baeldung.overridebean.mockbean;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import com.baeldung.overridebean.Endpoint;
|
||||
import com.baeldung.overridebean.Service;
|
||||
import com.baeldung.overridebean.boot.Application;
|
||||
|
||||
@SpringBootTest(classes = { Application.class, Endpoint.class })
|
||||
@AutoConfigureMockMvc
|
||||
class MockBeanIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@MockBean
|
||||
private Service service;
|
||||
|
||||
@Test
|
||||
void givenServiceMockBean_whenGetHelloEndpoint_thenMockOk() throws Exception {
|
||||
when(service.helloWorld()).thenReturn("hello mock bean");
|
||||
this.mockMvc.perform(get("/hello"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(containsString("hello mock bean")));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package com.baeldung.overridebean.overridebeandefinition;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import com.baeldung.overridebean.Config;
|
||||
import com.baeldung.overridebean.Endpoint;
|
||||
import com.baeldung.overridebean.boot.Application;
|
||||
|
||||
@SpringBootTest(classes = { Application.class, Config.class, Endpoint.class, OverrideBeanDefinitionTestConfig.class }, properties = "spring.main.allow-bean-definition-overriding=true")
|
||||
@AutoConfigureMockMvc
|
||||
class OverrideBeanDefinitionIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Test
|
||||
void givenNoProfile_whenAllowBeanDefinitionOverriding_thenStubOk() throws Exception {
|
||||
this.mockMvc.perform(get("/hello"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(containsString("hello no profile stub")));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.baeldung.overridebean.overridebeandefinition;
|
||||
|
||||
import com.baeldung.overridebean.Service;
|
||||
|
||||
public class OverrideBeanDefinitionServiceStub implements Service {
|
||||
|
||||
public String helloWorld() {
|
||||
return "hello no profile stub";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.baeldung.overridebean.overridebeandefinition;
|
||||
|
||||
import org.springframework.boot.test.context.TestConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import com.baeldung.overridebean.Service;
|
||||
|
||||
@TestConfiguration
|
||||
public class OverrideBeanDefinitionTestConfig {
|
||||
|
||||
@Bean
|
||||
public Service helloWorld() {
|
||||
return new OverrideBeanDefinitionServiceStub();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package com.baeldung.overridebean.primary;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import com.baeldung.overridebean.Config;
|
||||
import com.baeldung.overridebean.Endpoint;
|
||||
import com.baeldung.overridebean.boot.Application;
|
||||
|
||||
@SpringBootTest(classes = { Application.class, Config.class, Endpoint.class, PrimaryTestConfig.class })
|
||||
@AutoConfigureMockMvc
|
||||
class PrimaryIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Test
|
||||
void givenTestConfiguration_whenPrimaryBeanIsDefined_thenStubOk() throws Exception {
|
||||
this.mockMvc.perform(get("/hello"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(containsString("hello primary stub")));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.baeldung.overridebean.primary;
|
||||
|
||||
import com.baeldung.overridebean.Service;
|
||||
|
||||
public class PrimaryServiceStub implements Service {
|
||||
|
||||
public String helloWorld() {
|
||||
return "hello primary stub";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.baeldung.overridebean.primary;
|
||||
|
||||
import org.springframework.boot.test.context.TestConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
|
||||
import com.baeldung.overridebean.Service;
|
||||
|
||||
@TestConfiguration
|
||||
public class PrimaryTestConfig {
|
||||
|
||||
@Primary
|
||||
@Bean("service.stub")
|
||||
public Service helloWorld() {
|
||||
return new PrimaryServiceStub();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package com.baeldung.overridebean.profile;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import com.baeldung.overridebean.Endpoint;
|
||||
import com.baeldung.overridebean.Service;
|
||||
import com.baeldung.overridebean.boot.Application;
|
||||
|
||||
@SpringBootTest(classes = { Application.class, ProfileConfig.class, Endpoint.class, ProfileTestConfig.class })
|
||||
@AutoConfigureMockMvc
|
||||
@ActiveProfiles("mock")
|
||||
class ProfileMockIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Autowired
|
||||
private Service service;
|
||||
|
||||
@Test
|
||||
void givenConfigurationWithProfile_whenTestProfileIsActive_thenMockOk() throws Exception {
|
||||
when(service.helloWorld()).thenReturn("hello profile mock");
|
||||
this.mockMvc.perform(get("/hello"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(containsString("hello profile mock")));
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue