Merge branch 'eugenp:master' into JAVA-18149

This commit is contained in:
timis1 2023-02-18 20:36:10 +02:00 committed by GitHub
commit 104f8ece81
12 changed files with 170 additions and 39 deletions

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<artifactId>core-java-collections-maps-6</artifactId>
<version>0.1.0-SNAPSHOT</version>
<name>core-java-collections-maps-6</name>
<packaging>jar</packaging>
<parent>
<artifactId>core-java-modules</artifactId>
<groupId>com.baeldung.core-java-modules</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<properties>
<spring.version>5.2.5.RELEASE</spring.version>
</properties>
</project>

View File

@ -0,0 +1,47 @@
package com.baeldung.map.hashmapcopy;
import java.util.Map;
import com.google.common.collect.MapDifference;
import com.google.common.collect.Maps;
public class CopyingAHashMapToAnother {
public Map<String, String> copyByIteration(Map<String, String> sourceMap, Map<String, String> targetMap) {
for (Map.Entry<String, String> entry : sourceMap.entrySet()) {
if (!targetMap.containsKey(entry.getKey())) {
targetMap.put(entry.getKey(), entry.getValue());
}
}
return targetMap;
}
public Map<String, String> copyUsingPutAll(Map<String, String> sourceMap, Map<String, String> targetMap) {
sourceMap.keySet()
.removeAll(targetMap.keySet());
targetMap.putAll(sourceMap);
return targetMap;
}
public Map<String, String> copyUsingPutIfAbsent(Map<String, String> sourceMap, Map<String, String> targetMap) {
for (Map.Entry<String, String> entry : sourceMap.entrySet()) {
targetMap.putIfAbsent(entry.getKey(), entry.getValue());
}
return targetMap;
}
public Map<String, String> copyUsingPutIfAbsentForEach(Map<String, String> sourceMap, Map<String, String> targetMap) {
sourceMap.forEach(targetMap::putIfAbsent);
return targetMap;
}
public Map<String, String> copyUsingMapMerge(Map<String, String> sourceMap, Map<String, String> targetMap) {
sourceMap.forEach((key, value) -> targetMap.merge(key, value, (oldVal, newVal) -> oldVal));
return targetMap;
}
public Map<String, String> copyUsingGuavaMapDifference(Map<String, String> sourceMap, Map<String, String> targetMap) {
MapDifference<String, String> differenceMap = Maps.difference(sourceMap, targetMap);
targetMap.putAll(differenceMap.entriesOnlyOnLeft());
return targetMap;
}
}

View File

@ -0,0 +1,68 @@
package com.baeldung.map.hashmapcopy;
import java.util.HashMap;
import java.util.Map;
import org.junit.Assert;
import org.junit.Test;
import com.baeldung.map.hashmapcopy.CopyingAHashMapToAnother;
public class CopyHashMapIntoAnotherUnitTest {
@Test
public void givenSourceAndTargetMapsWhenIteratedOverThenCopyingSuccess(){
CopyingAHashMapToAnother obj = new CopyingAHashMapToAnother();
Assert.assertEquals(generateExpectedResultMap(), obj.copyByIteration(generateSourceMap(), generateTargetMap()));
}
@Test
public void givenSourceAndTargetMapsWhenUsedPutAllThenCopyingSuccess(){
CopyingAHashMapToAnother obj = new CopyingAHashMapToAnother();
Assert.assertEquals(generateExpectedResultMap(), obj.copyUsingPutAll(generateSourceMap(), generateTargetMap()));
}
@Test
public void givenSourceAndTargetMapsWhenUsedPutIfAbsentThenCopyingSuccess(){
CopyingAHashMapToAnother obj = new CopyingAHashMapToAnother();
Assert.assertEquals(generateExpectedResultMap(), obj.copyUsingPutIfAbsent(generateSourceMap(), generateTargetMap()));
Assert.assertEquals(generateExpectedResultMap(), obj.copyUsingPutIfAbsentForEach(generateSourceMap(), generateTargetMap()));
}
@Test
public void givenSourceAndTargetMapsWhenUsedMapMergeThenCopyingSuccess(){
CopyingAHashMapToAnother obj = new CopyingAHashMapToAnother();
Assert.assertEquals(generateExpectedResultMap(), obj.copyUsingMapMerge(generateSourceMap(), generateTargetMap()));
}
@Test
public void givenSourceAndTargetMapsWhenMapDifferenceUsedThenCopyingSuccess(){
CopyingAHashMapToAnother obj = new CopyingAHashMapToAnother();
Assert.assertEquals(generateExpectedResultMap(), obj.copyUsingGuavaMapDifference(generateSourceMap(), generateTargetMap()));
}
private Map<String, String> generateSourceMap(){
Map<String, String> sourceMap = new HashMap<>();
sourceMap.put("India", "Delhi");
sourceMap.put("United States", "Washington D.C.");
sourceMap.put("United Kingdom", "London DC");
return sourceMap;
}
private Map<String, String> generateTargetMap(){
Map<String, String> targetMap = new HashMap<>();
targetMap.put("Zimbabwe", "Harare");
targetMap.put("Norway", "Oslo");
targetMap.put("United Kingdom", "London");
return targetMap;
}
private Map<String, String> generateExpectedResultMap(){
Map<String, String> resultMap = new HashMap<>();
resultMap.put("India", "Delhi");
resultMap.put("United States", "Washington D.C.");
resultMap.put("United Kingdom", "London");
resultMap.put("Zimbabwe", "Harare");
resultMap.put("Norway", "Oslo");
return resultMap;
}
}

View File

@ -16,7 +16,7 @@ public class BadPaddingExamples {
SecretKey encryptionKey = CryptoUtils.getKeyForText("BaeldungIsASuperCoolSite"); SecretKey encryptionKey = CryptoUtils.getKeyForText("BaeldungIsASuperCoolSite");
SecretKey differentKey = CryptoUtils.getKeyForText("ThisGivesUsAnAlternative"); SecretKey differentKey = CryptoUtils.getKeyForText("ThisGivesUsAnAlternative");
Cipher cipher = Cipher.getInstance("AES/ECB/ISO10126Padding"); Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, encryptionKey); cipher.init(Cipher.ENCRYPT_MODE, encryptionKey);
byte[] cipherTextBytes = cipher.doFinal(plainTextBytes); byte[] cipherTextBytes = cipher.doFinal(plainTextBytes);
@ -28,12 +28,12 @@ public class BadPaddingExamples {
public static byte[] encryptAndDecryptUsingDifferentAlgorithms(SecretKey key, IvParameterSpec ivParameterSpec, public static byte[] encryptAndDecryptUsingDifferentAlgorithms(SecretKey key, IvParameterSpec ivParameterSpec,
byte[] plainTextBytes) throws InvalidKeyException, GeneralSecurityException { byte[] plainTextBytes) throws InvalidKeyException, GeneralSecurityException {
Cipher cipher = Cipher.getInstance("AES/CBC/ISO10126Padding"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec); cipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec);
byte[] cipherTextBytes = cipher.doFinal(plainTextBytes); byte[] cipherTextBytes = cipher.doFinal(plainTextBytes);
cipher = Cipher.getInstance("AES/ECB/ISO10126Padding"); cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key); cipher.init(Cipher.DECRYPT_MODE, key);

View File

@ -132,6 +132,7 @@
<module>core-java-regex-2</module> <module>core-java-regex-2</module>
<module>core-java-uuid</module> <module>core-java-uuid</module>
<module>pre-jpms</module> <module>pre-jpms</module>
<module>core-java-collections-maps-6</module>
</modules> </modules>
<dependencyManagement> <dependencyManagement>

View File

@ -14,9 +14,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration;
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
import com.baeldung.boot.csfle.config.converter.BinaryConverter;
import com.mongodb.AutoEncryptionSettings; import com.mongodb.AutoEncryptionSettings;
import com.mongodb.ClientEncryptionSettings; import com.mongodb.ClientEncryptionSettings;
import com.mongodb.ConnectionString; import com.mongodb.ConnectionString;
@ -50,11 +48,6 @@ public class MongoClientConfig extends AbstractMongoClientConfiguration {
return db; return db;
} }
@Override
public MongoCustomConversions customConversions() {
return new MongoCustomConversions(Arrays.asList(new BinaryConverter()));
}
@Bean @Bean
@Override @Override
public MongoClient mongoClient() { public MongoClient mongoClient() {

View File

@ -1,13 +0,0 @@
package com.baeldung.boot.csfle.config.converter;
import org.bson.BsonBinary;
import org.bson.types.Binary;
import org.springframework.core.convert.converter.Converter;
public class BinaryConverter implements Converter<Binary, BsonBinary> {
@Override
public BsonBinary convert(Binary source) {
return new BsonBinary(source.getType(), source.getData());
}
}

View File

@ -13,7 +13,9 @@ public class Citizen {
} }
public Citizen(EncryptedCitizen encryptedCitizen) { public Citizen(EncryptedCitizen encryptedCitizen) {
this.name = encryptedCitizen.getName(); if (encryptedCitizen != null) {
this.name = encryptedCitizen.getName();
}
} }
public String getName() { public String getName() {

View File

@ -1,14 +1,14 @@
package com.baeldung.boot.csfle.data; package com.baeldung.boot.csfle.data;
import org.bson.BsonBinary; import org.bson.types.Binary;
import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.Document;
@Document("citizens") @Document("citizens")
public class EncryptedCitizen { public class EncryptedCitizen {
private String name; private String name;
private BsonBinary email; private Binary email;
private BsonBinary birthYear; private Binary birthYear;
public EncryptedCitizen() { public EncryptedCitizen() {
} }
@ -25,19 +25,19 @@ public class EncryptedCitizen {
this.name = name; this.name = name;
} }
public BsonBinary getEmail() { public Binary getEmail() {
return email; return email;
} }
public void setEmail(BsonBinary email) { public void setEmail(Binary email) {
this.email = email; this.email = email;
} }
public BsonBinary getBirthYear() { public Binary getBirthYear() {
return birthYear; return birthYear;
} }
public void setBirthYear(BsonBinary birthYear) { public void setBirthYear(Binary birthYear) {
this.birthYear = birthYear; this.birthYear = birthYear;
} }

View File

@ -7,6 +7,7 @@ import org.bson.BsonBinary;
import org.bson.BsonInt32; import org.bson.BsonInt32;
import org.bson.BsonString; import org.bson.BsonString;
import org.bson.BsonValue; import org.bson.BsonValue;
import org.bson.types.Binary;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Criteria;
@ -65,7 +66,7 @@ public class CitizenService {
} }
} }
public BsonBinary encrypt(Object value, String algorithm) { public Binary encrypt(Object value, String algorithm) {
if (value == null) if (value == null)
return null; return null;
@ -80,17 +81,22 @@ public class CitizenService {
EncryptOptions options = new EncryptOptions(algorithm); EncryptOptions options = new EncryptOptions(algorithm);
options.keyId(encryptionConfig.getDataKeyId()); options.keyId(encryptionConfig.getDataKeyId());
return clientEncryption.encrypt(bsonValue, options);
BsonBinary encryptedValue = clientEncryption.encrypt(bsonValue, options);
return new Binary(encryptedValue.getType(), encryptedValue.getData());
} }
public BsonValue decryptProperty(BsonBinary value) { public BsonValue decryptProperty(Binary value) {
if (value == null) if (value == null)
return null; return null;
return clientEncryption.decrypt(value); return clientEncryption.decrypt(new BsonBinary(value.getType(), value.getData()));
} }
private Citizen decrypt(EncryptedCitizen encrypted) { private Citizen decrypt(EncryptedCitizen encrypted) {
if (encrypted == null)
return null;
Citizen citizen = new Citizen(encrypted); Citizen citizen = new Citizen(encrypted);
BsonValue decryptedBirthYear = decryptProperty(encrypted.getBirthYear()); BsonValue decryptedBirthYear = decryptProperty(encrypted.getBirthYear());

View File

@ -1,8 +1,10 @@
package com.baeldung.boot.csfle; package com.baeldung.boot.csfle;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import org.bson.BsonBinary; import org.bson.types.Binary;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -36,7 +38,7 @@ public class CitizenServiceLiveTest {
citizen.setName("Foo"); citizen.setName("Foo");
citizen.setEmail("foo@citizen.com"); citizen.setEmail("foo@citizen.com");
BsonBinary encryptedEmail = service.encrypt(citizen.getEmail(), CitizenService.DETERMINISTIC_ALGORITHM); Binary encryptedEmail = service.encrypt(citizen.getEmail(), CitizenService.DETERMINISTIC_ALGORITHM);
EncryptedCitizen saved = service.save(citizen); EncryptedCitizen saved = service.save(citizen);
assertEquals(encryptedEmail, saved.getEmail()); assertEquals(encryptedEmail, saved.getEmail());

View File

@ -3,4 +3,9 @@ spring.datasource.username=sa
spring.datasource.password=sa spring.datasource.password=sa
spring.jpa.properties.hibernate.globally_quoted_identifiers=true spring.jpa.properties.hibernate.globally_quoted_identifiers=true
logging.level.com.baeldung.spring.data.persistence.search=debug logging.level.com.baeldung.spring.data.persistence.search=debug
spring.jpa.show-sql=true
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
spring.jpa.properties.hibernate.format_sql=true