package com.kryptnostic.kodex.v1.serialization.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.google.common.base.Optional;
import com.kryptnostic.kodex.v1.constants.Names;
import com.kryptnostic.kodex.v1.crypto.keys.CryptoServiceLoader;
import com.kryptnostic.kodex.v1.exceptions.types.SecurityConfigurationException;
import com.kryptnostic.kodex.v1.serialization.crypto.Encryptable;
/**
* @author sinaiman
* @author Matthew Tamayo-Rios <matthew@kryptnostic.com>
*
*/
@SuppressWarnings( "rawtypes" )
public class EncryptableSerializer extends JsonSerializer<Encryptable> {
private static final String SECURITY_ERROR_MSG = "Security configuration error";
private final Optional<CryptoServiceLoader> loader;
/**
* @param loader
*/
public EncryptableSerializer( Optional<CryptoServiceLoader> loader ) {
this.loader = loader;
}
@Override
public void serializeWithType(
Encryptable value,
JsonGenerator jgen,
SerializerProvider provider,
TypeSerializer typeSer ) throws IOException, JsonProcessingException {
typeSer.writeTypePrefixForObject( value, jgen );
try {
writeFields( value, jgen, provider );
} catch ( SecurityConfigurationException | ClassNotFoundException e ) {
throw new IOException( SECURITY_ERROR_MSG, e );
}
typeSer.writeTypeSuffixForObject( value, jgen );
};
@Override
public void serialize( Encryptable value, JsonGenerator jgen, SerializerProvider provider ) throws IOException,
JsonGenerationException {
jgen.writeStartObject();
try {
writeFields( value, jgen, provider );
} catch ( SecurityConfigurationException | ClassNotFoundException e ) {
throw new IOException( SECURITY_ERROR_MSG, e );
}
jgen.writeEndObject();
}
private void writeFields( Encryptable value, JsonGenerator jgen, SerializerProvider provider ) throws IOException,
SecurityConfigurationException, ClassNotFoundException {
if ( loader.isPresent() || ( !loader.isPresent() && value.isEncrypted() ) ) {
// Only serialize if we can encrypt or it is already encrypted
Encryptable<?> encryptedValue = value;
if ( loader.isPresent() ) {
// We have a crypto service loader so we can try to encrypt.
encryptedValue = value.encrypt( loader.get() );
}
jgen.writeObjectField( Names.DATA_FIELD, encryptedValue.getEncryptedData() );
jgen.writeObjectField( Names.USERNAME_FIELD, encryptedValue.getEncryptedClassName() );
jgen.writeObjectField( Names.KEY_FIELD, encryptedValue.getCryptoServiceId() );
} else {
throw new JsonMappingException( "Refusing to serialize unencrypted" );
}
}
}