212 lines
8.2 KiB
Java
212 lines
8.2 KiB
Java
package org.gcube.informationsystem.resourceregistry.instances.base.properties;
|
|
|
|
import java.security.Key;
|
|
import java.util.Collection;
|
|
import java.util.HashSet;
|
|
import java.util.Set;
|
|
import java.util.UUID;
|
|
|
|
import org.gcube.com.fasterxml.jackson.databind.JsonNode;
|
|
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
|
|
import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode;
|
|
import org.gcube.com.fasterxml.jackson.databind.node.ObjectNode;
|
|
import org.gcube.common.encryption.encrypter.StringEncrypter;
|
|
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.reference.properties.Encrypted;
|
|
import org.gcube.informationsystem.model.reference.properties.Metadata;
|
|
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.MetadataUtility;
|
|
import org.gcube.informationsystem.resourceregistry.utils.DBUtility;
|
|
import org.gcube.informationsystem.resourceregistry.utils.UUIDUtility;
|
|
import org.gcube.informationsystem.types.reference.properties.PropertyType;
|
|
import org.gcube.informationsystem.utils.TypeUtility;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import com.arcadedb.database.Document;
|
|
import com.arcadedb.schema.DocumentType;
|
|
|
|
/**
|
|
* @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 Document getPropertyDocument(JsonNode jsonNodeOrig) throws ResourceRegistryException {
|
|
Document document = null;
|
|
if(jsonNodeOrig.isNull()) {
|
|
return null;
|
|
}
|
|
|
|
JsonNode jsonNode = jsonNodeOrig.deepCopy();
|
|
|
|
if(jsonNode.has(Element.SUPERTYPES_PROPERTY)) {
|
|
((ObjectNode) jsonNode).remove(Element.SUPERTYPES_PROPERTY);
|
|
}
|
|
|
|
String type = TypeUtility.getTypeName(jsonNode);
|
|
if(type!=null) {
|
|
// Complex type
|
|
DocumentType documentType = null;
|
|
|
|
try {
|
|
TypesCache typesCache = TypesCache.getInstance();
|
|
@SuppressWarnings("unchecked")
|
|
CachedType<PropertyType<PropertyElement>> cachedType = (CachedType<PropertyType<PropertyElement>>) typesCache.getCachedType(type);
|
|
documentType = cachedType.getDocumentType();
|
|
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 {
|
|
UUID uuid = UUIDUtility.getUUID(jsonNode);
|
|
if(uuid != null) {
|
|
throw new ResourceRegistryException("A property object cannot have an UUID");
|
|
}
|
|
} catch(Exception e) {
|
|
logger.warn("An invalid UUID has been provided. Anyway property object cannot have an UUID.");
|
|
throw new ResourceRegistryException("An property object cannot have an UUID");
|
|
}
|
|
|
|
try {
|
|
Metadata metadata = MetadataUtility.getMetadata(jsonNode);
|
|
if(metadata != null) {
|
|
throw new ResourceRegistryException("A property object cannot have a Metadata");
|
|
}
|
|
} catch(Exception e) {
|
|
logger.warn("An invalid Metadata has been provided. Anyway property object cannot have a Metadata.");
|
|
throw new ResourceRegistryException("An property object cannot have a Metadata");
|
|
}
|
|
|
|
|
|
/*
|
|
* 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(documentType.isSubTypeOf(Encrypted.NAME)) {
|
|
EncryptedOrient encrypted = new EncryptedOrient();
|
|
document = encrypted;
|
|
document.fromJSON(jsonNode.toString());
|
|
try {
|
|
String contextEncryptedValue = encrypted.getEncryptedValue();
|
|
|
|
// Decrypting with Context Key (default key)
|
|
String decryptedValue = StringEncrypter.getEncrypter().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 document;
|
|
}
|
|
|
|
document = new Document(type);
|
|
} else {
|
|
document = new Document();
|
|
}
|
|
return document.fromJSON(jsonNode.toString());
|
|
}
|
|
|
|
|
|
public static JsonNode getJsonNode(Document oDocument) throws ResourceRegistryException {
|
|
try {
|
|
String type = oDocument.getTypeName();
|
|
String json = DBUtility.toJsonString(oDocument);
|
|
|
|
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);
|
|
DocumentType documentType = cachedType.getDocumentType();
|
|
AccessType gotAccessType = cachedType.getAccessType();
|
|
if(!AccessType.PROPERTY_ELEMENT.getClass().isAssignableFrom(gotAccessType.getClass())) {
|
|
throw new SchemaException(type + " is not a " + AccessType.PROPERTY_ELEMENT.getName());
|
|
}
|
|
|
|
Collection<String> superClasses = cachedType.getSuperTypes();
|
|
ArrayNode arrayNode = objectMapper.valueToTree(superClasses);
|
|
((ObjectNode) jsonNode).replace(Element.SUPERTYPES_PROPERTY, arrayNode);
|
|
|
|
/*
|
|
* 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(documentType.isSubTypeOf(Encrypted.NAME)) {
|
|
try {
|
|
|
|
EncryptedOrient encrypted = null;
|
|
String encryptedValue = (String) oDocument.getString(Encrypted.VALUE);
|
|
|
|
if(oDocument instanceof EncryptedOrient) {
|
|
encrypted = (EncryptedOrient) oDocument;
|
|
if(encrypted.getDbEncryptedValue().compareTo(encryptedValue)==0) {
|
|
((ObjectNode) jsonNode).put(Encrypted.VALUE, encrypted.getContextEncryptedValue());
|
|
}
|
|
}else {
|
|
encrypted = new EncryptedOrient();
|
|
oDocument = (Document) encrypted;
|
|
|
|
// Decrypting with DB Key
|
|
Key databaseKey = DatabaseEnvironment.getDatabaseKey();
|
|
String decryptedValue = StringEncrypter.getEncrypter().decrypt(encryptedValue, databaseKey);
|
|
|
|
// Encrypting with Context Key (default key)
|
|
String contextEncryptedValue = StringEncrypter.getEncrypter().encrypt(decryptedValue);
|
|
|
|
// Setting the value encrypted with DB key
|
|
((ObjectNode) jsonNode).put(Encrypted.VALUE, contextEncryptedValue);
|
|
}
|
|
|
|
}catch (Exception e) {
|
|
throw new ResourceRegistryException("Errror while managing " + EncryptedOrient.NAME+ " "+ Property.NAME, e);
|
|
}
|
|
}
|
|
|
|
return jsonNode;
|
|
|
|
} catch (ResourceRegistryException e) {
|
|
throw e;
|
|
} catch (Exception e) {
|
|
throw new ResourceRegistryException(e);
|
|
}
|
|
}
|
|
}
|