3939import org .springframework .util .ObjectUtils ;
4040
4141/**
42+ * Default implementation of {@link EncryptingConverter}. Properties used with this converter must be annotated with
43+ * {@link Encrypted @Encrypted} to provide key and algorithm metadata.
44+ *
4245 * @author Christoph Strobl
4346 * @since 4.1
4447 */
4548public class MongoEncryptionConverter implements EncryptingConverter <Object , Object > {
4649
4750 private static final Log LOGGER = LogFactory .getLog (MongoEncryptionConverter .class );
4851
49- private Encryption <BsonValue , BsonBinary > encryption ;
52+ private final Encryption <BsonValue , BsonBinary > encryption ;
5053 private final EncryptionKeyResolver keyResolver ;
5154
5255 public MongoEncryptionConverter (Encryption <BsonValue , BsonBinary > encryption , EncryptionKeyResolver keyResolver ) {
@@ -70,7 +73,7 @@ public Object decrypt(Object encryptedValue, EncryptionContext context) {
7073 if (encryptedValue instanceof Binary || encryptedValue instanceof BsonBinary ) {
7174
7275 if (LOGGER .isDebugEnabled ()) {
73- LOGGER .debug (String .format ("Decrypting %s.%s." , getProperty (context ).getOwner ().getName (),
76+ LOGGER .debug (String .format ("Decrypting %s.%s." , getProperty (context ).getOwner ().getName (),
7477 getProperty (context ).getName ()));
7578 }
7679
@@ -83,18 +86,20 @@ public Object decrypt(Object encryptedValue, EncryptionContext context) {
8386 }
8487 }
8588
86- MongoPersistentProperty persistentProperty = getProperty (context );
89+ MongoPersistentProperty persistentProperty = getProperty (context );
8790
8891 if (getProperty (context ).isCollectionLike () && decryptedValue instanceof Iterable <?> iterable ) {
92+
93+ int size = iterable instanceof Collection <?> c ? c .size () : 10 ;
94+
8995 if (!persistentProperty .isEntity ()) {
90- Collection <Object > collection = CollectionFactory .createCollection (persistentProperty .getType (), 10 );
96+ Collection <Object > collection = CollectionFactory .createCollection (persistentProperty .getType (), size );
9197 iterable .forEach (it -> collection .add (BsonUtils .toJavaType ((BsonValue ) it )));
9298 return collection ;
9399 } else {
94- Collection <Object > collection = CollectionFactory .createCollection (persistentProperty .getType (), 10 );
100+ Collection <Object > collection = CollectionFactory .createCollection (persistentProperty .getType (), size );
95101 iterable .forEach (it -> {
96- collection .add (context .read (BsonUtils .toJavaType ((BsonValue ) it ),
97- persistentProperty .getActualType ()));
102+ collection .add (context .read (BsonUtils .toJavaType ((BsonValue ) it ), persistentProperty .getActualType ()));
98103 });
99104 return collection ;
100105 }
@@ -109,17 +114,12 @@ public Object decrypt(Object encryptedValue, EncryptionContext context) {
109114 }
110115
111116 if (persistentProperty .isEntity () && decryptedValue instanceof BsonDocument bsonDocument ) {
112- return context .read (BsonUtils .toJavaType (bsonDocument ),
113- persistentProperty .getTypeInformation ().getType ());
117+ return context .read (BsonUtils .toJavaType (bsonDocument ), persistentProperty .getTypeInformation ().getType ());
114118 }
115119
116120 return decryptedValue ;
117121 }
118122
119- private MongoPersistentProperty getProperty (EncryptionContext context ) {
120- return context .getProperty ();
121- }
122-
123123 @ Override
124124 public Object encrypt (Object value , EncryptionContext context ) {
125125
@@ -128,15 +128,19 @@ public Object encrypt(Object value, EncryptionContext context) {
128128 getProperty (context ).getName ()));
129129 }
130130
131- MongoPersistentProperty persistentProperty = getProperty (context );
131+ MongoPersistentProperty persistentProperty = getProperty (context );
132132
133133 Encrypted annotation = persistentProperty .findAnnotation (Encrypted .class );
134- if (annotation == null ) {
134+ if (annotation == null ) {
135135 annotation = persistentProperty .getOwner ().findAnnotation (Encrypted .class );
136136 }
137137
138- EncryptionOptions encryptionOptions = new EncryptionOptions (annotation .algorithm ());
139- encryptionOptions .setKey (keyResolver .getKey (context ));
138+ if (annotation == null ) {
139+ throw new IllegalStateException (String .format ("Property %s.%s is not annotated with @Encrypted" ,
140+ getProperty (context ).getOwner ().getName (), getProperty (context ).getName ()));
141+ }
142+
143+ EncryptionOptions encryptionOptions = new EncryptionOptions (annotation .algorithm (), keyResolver .getKey (context ));
140144
141145 if (!persistentProperty .isEntity ()) {
142146
@@ -162,36 +166,44 @@ public Object encrypt(Object value, EncryptionContext context) {
162166 return encryption .encrypt (BsonUtils .simpleToBsonValue (write ), encryptionOptions );
163167 }
164168
165- public BsonValue collectionLikeToBsonValue (Object value , MongoPersistentProperty property ,
169+ private BsonValue collectionLikeToBsonValue (Object value , MongoPersistentProperty property ,
166170 EncryptionContext context ) {
167171
168172 BsonArray bsonArray = new BsonArray ();
169- if (!property .isEntity ()) {
170- if (value instanceof Collection values ) {
171- values .forEach (it -> bsonArray .add (BsonUtils .simpleToBsonValue (it )));
172- } else if (ObjectUtils .isArray (value )) {
173- for (Object o : ObjectUtils .toObjectArray (value )) {
174- bsonArray .add (BsonUtils .simpleToBsonValue (o ));
173+ boolean isEntity = property .isEntity ();
174+
175+ if (value instanceof Collection <?> values ) {
176+ values .forEach (it -> {
177+
178+ if (isEntity ) {
179+ Document document = (Document ) context .write (it , property .getTypeInformation ());
180+ bsonArray .add (document == null ? null : document .toBsonDocument ());
181+ } else {
182+ bsonArray .add (BsonUtils .simpleToBsonValue (it ));
175183 }
176- }
177- return bsonArray ;
178- } else {
179- if (value instanceof Collection values ) {
180- values .forEach (it -> {
181- Document write = (Document ) context .write (it , property .getTypeInformation ());
182- bsonArray .add (write .toBsonDocument ());
183- });
184- } else if (ObjectUtils .isArray (value )) {
185- for (Object o : ObjectUtils .toObjectArray (value )) {
186- Document write = (Document ) context .write (o , property .getTypeInformation ());
187- bsonArray .add (write .toBsonDocument ());
184+ });
185+ } else if (ObjectUtils .isArray (value )) {
186+
187+ for (Object o : ObjectUtils .toObjectArray (value )) {
188+
189+ if (isEntity ) {
190+ Document document = (Document ) context .write (o , property .getTypeInformation ());
191+ bsonArray .add (document == null ? null : document .toBsonDocument ());
192+ } else {
193+ bsonArray .add (BsonUtils .simpleToBsonValue (o ));
188194 }
189195 }
190- return bsonArray ;
191196 }
197+
198+ return bsonArray ;
192199 }
193200
201+ @ Override
194202 public EncryptionContext buildEncryptionContext (MongoConversionContext context ) {
195203 return new ExplicitEncryptionContext (context );
196204 }
205+
206+ protected MongoPersistentProperty getProperty (EncryptionContext context ) {
207+ return context .getProperty ();
208+ }
197209}
0 commit comments