resource-registry/src/main/java/org/gcube/informationsystem/resourceregistry/instances/base/properties/PropertyElementManagement.java

188 lines
7.4 KiB
Java

package org.gcube.informationsystem.resourceregistry.instances.base.properties;
import java.security.Key;
import java.util.HashSet;
import java.util.Set;
import org.gcube.com.fasterxml.jackson.databind.JsonNode;
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
import org.gcube.com.fasterxml.jackson.databind.node.ObjectNode;
import org.gcube.informationsystem.base.reference.AccessType;
import org.gcube.informationsystem.base.reference.Element;
import org.gcube.informationsystem.base.reference.properties.PropertyElement;
import org.gcube.informationsystem.model.impl.properties.EncryptedImpl;
import org.gcube.informationsystem.model.reference.properties.Encrypted;
import org.gcube.informationsystem.model.reference.properties.Header;
import org.gcube.informationsystem.model.reference.properties.Property;
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.types.SchemaException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.types.SchemaNotFoundException;
import org.gcube.informationsystem.resourceregistry.dbinitialization.DatabaseEnvironment;
import org.gcube.informationsystem.resourceregistry.instances.base.ElementManagement;
import org.gcube.informationsystem.resourceregistry.types.CachedType;
import org.gcube.informationsystem.resourceregistry.types.TypesCache;
import org.gcube.informationsystem.resourceregistry.utils.EncryptedOrient;
import org.gcube.informationsystem.resourceregistry.utils.HeaderUtility;
import org.gcube.informationsystem.types.reference.properties.PropertyType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.orientechnologies.orient.core.metadata.schema.OClass;
import com.orientechnologies.orient.core.record.impl.ODocument;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public class PropertyElementManagement {
private static Logger logger = LoggerFactory.getLogger(PropertyElementManagement.class);
public static final Set<String> PROPERTY_IGNORE_KEYS;
public static final Set<String> PROPERTY_IGNORE_START_WITH_KEYS;
static {
PROPERTY_IGNORE_KEYS = new HashSet<String>();
PROPERTY_IGNORE_START_WITH_KEYS = new HashSet<String>();
PROPERTY_IGNORE_START_WITH_KEYS.add(ElementManagement.AT);
PROPERTY_IGNORE_START_WITH_KEYS.add(ElementManagement.UNDERSCORE);
}
public static ODocument getPropertyDocument(JsonNode jsonNode) throws ResourceRegistryException {
ODocument oDocument = null;
if(jsonNode.isNull()) {
return null;
}
if(jsonNode.has(Element.CLASS_PROPERTY)) {
// Complex type
String type = ElementManagement.getClassProperty(jsonNode);
OClass oClass = null;
try {
TypesCache typesCache = TypesCache.getInstance();
@SuppressWarnings("unchecked")
CachedType<PropertyType<PropertyElement>> cachedType = (CachedType<PropertyType<PropertyElement>>) typesCache.getCachedType(type);
oClass = cachedType.getOClass();
AccessType gotAccessType = cachedType.getAccessType();
if(!AccessType.PROPERTY_ELEMENT.getClass().isAssignableFrom(gotAccessType.getClass())) {
throw new SchemaException(type + " is not a " + AccessType.PROPERTY_ELEMENT.getName());
}
} catch(SchemaNotFoundException e) {
throw e;
}
try {
Header header = HeaderUtility.getHeader(jsonNode, false);
if(header != null) {
throw new ResourceRegistryException("A property object cannot have an Header");
}
} catch(Exception e) {
logger.warn("An invalid Header has been provided. Anyway property object cannot have an Header.");
throw new ResourceRegistryException("An property object cannot have an Header");
}
/*
* In case it is an Encrypted type the Value received arrives encrypted with the Context Key
* Resource Registry must decrypt the value with the Context Key and Encrypt it with DB key.
* The opposite operation is done when the value is read by clients.
*/
if(oClass.isSubClassOf(Encrypted.NAME)) {
EncryptedOrient encrypted = new EncryptedOrient();
oDocument = encrypted;
oDocument.fromJSON(jsonNode.toString());
try {
String contextEncryptedValue = encrypted.getEncryptedValue();
// Decrypting with Context Key (default key)
String decryptedValue = EncryptedImpl.decrypt(contextEncryptedValue);
encrypted.setDecryptedValue(decryptedValue, false);
} catch(Exception e) {
throw new ResourceRegistryException("Unable to manage "+Encrypted.NAME+" "+org.gcube.informationsystem.model.reference.properties.Property.NAME);
}
return oDocument;
}
oDocument = new ODocument(type);
} else {
oDocument = new ODocument();
}
return oDocument.fromJSON(jsonNode.toString());
}
public static JsonNode getJsonNode(ODocument oDocument) throws ResourceRegistryException {
try {
String type = oDocument.getClassName();
String json = oDocument.toJSON("class");
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(json);
if(type==null) {
return jsonNode;
}
TypesCache typesCache = TypesCache.getInstance();
@SuppressWarnings("unchecked")
CachedType<PropertyType<PropertyElement>> cachedType = (CachedType<PropertyType<PropertyElement>>) typesCache.getCachedType(type);
OClass oClass = cachedType.getOClass();
AccessType gotAccessType = cachedType.getAccessType();
if(!AccessType.PROPERTY_ELEMENT.getClass().isAssignableFrom(gotAccessType.getClass())) {
throw new SchemaException(type + " is not a " + AccessType.PROPERTY_ELEMENT.getName());
}
/*
* In case it is an Encrypted type the value is encrypted with the DB Key
* Resource Registry must decrypt the value with the DB Key and Encrypt it with Context key.
* The opposite operation is done when the value is set from clients.
* see {@link PropertyManagement#getPropertyDocument(JsonNode) getPropertyDocument()}
*/
if(oClass.isSubClassOf(Encrypted.NAME)) {
try {
EncryptedOrient encrypted = null;
String encryptedValue = (String) oDocument.getProperty(Encrypted.VALUE);
if(oDocument instanceof EncryptedOrient) {
encrypted = (EncryptedOrient) oDocument;
if(encrypted.getDbEncryptedValue().compareTo(encryptedValue)==0) {
// encrypted.setEncryptedValue(encrypted.getContextEncryptedValue());
((ObjectNode) jsonNode).put(Encrypted.VALUE, encrypted.getContextEncryptedValue());
}
}else {
encrypted = new EncryptedOrient();
oDocument = (ODocument) encrypted;
// Decrypting with DB Key
Key databaseKey = DatabaseEnvironment.getDatabaseKey();
String decryptedValue = EncryptedImpl.decrypt(encryptedValue, databaseKey);
// encrypted.setDecryptedValue(decryptedValue, true);
// Encrypting with Context Key (default key)
String contextEncryptedValue = EncryptedImpl.encrypt(decryptedValue);
// Setting the value encrypted with DB key
//encrypted.setEncryptedValue(contextEncryptedValue);
((ObjectNode) jsonNode).put(Encrypted.VALUE, contextEncryptedValue);
}
}catch (Exception e) {
throw new ResourceRegistryException("Errror while managing " + Encrypted.NAME+ " "+ Property.NAME, e);
}
}
return jsonNode;
} catch (ResourceRegistryException e) {
throw e;
} catch (Exception e) {
throw new ResourceRegistryException(e);
}
}
}