package org.gcube.informationsystem.resourceregistry.contexts; import java.util.HashMap; import java.util.Map; import java.util.NoSuchElementException; import java.util.UUID; import org.gcube.common.authorization.utils.manager.SecretManagerProvider; import org.gcube.common.scope.impl.ScopeBean; import org.gcube.informationsystem.contexts.reference.entities.Context; import org.gcube.informationsystem.contexts.reference.relations.IsParentOf; import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException; import org.gcube.informationsystem.resourceregistry.api.exceptions.contexts.ContextException; import org.gcube.informationsystem.resourceregistry.api.exceptions.contexts.ContextNotFoundException; import org.gcube.informationsystem.resourceregistry.contexts.security.AdminSecurityContext; import org.gcube.informationsystem.resourceregistry.contexts.security.SecurityContext; import org.gcube.informationsystem.resourceregistry.contexts.security.SecurityContext.PermissionMode; import org.gcube.informationsystem.resourceregistry.instances.base.ElementManagementUtility; import org.gcube.informationsystem.resourceregistry.utils.DBUtility; import org.gcube.informationsystem.resourceregistry.utils.UUIDUtility; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.arcadedb.graph.MutableVertex; import com.arcadedb.graph.Vertex; import com.arcadedb.graph.Vertex.DIRECTION; import com.arcadedb.query.sql.executor.Result; import com.arcadedb.query.sql.executor.ResultSet; import com.arcadedb.remote.RemoteDatabase; /** * @author Luca Frosini (ISTI - CNR) */ public class ContextUtility { private static final Logger logger = LoggerFactory.getLogger(ContextUtility.class); private Map contexts; private static ContextUtility contextUtility; public static ContextUtility getInstance() { if(contextUtility == null) { contextUtility = new ContextUtility(); } return contextUtility; } private ContextUtility() { contexts = new HashMap<>(); } public static String getCurrentContextFullName() { return SecretManagerProvider.instance.get().getContext(); } public static SecurityContext getCurrentSecurityContext() throws ResourceRegistryException { String fullName = getCurrentContextFullName(); if(fullName == null) { throw new ContextException("Null Token and Scope. Please set your token first."); } return ContextUtility.getInstance().getSecurityContextByFullName(fullName); } public static AdminSecurityContext getAdminSecurityContext() throws ResourceRegistryException { AdminSecurityContext adminSecurityContext = AdminSecurityContext.getInstance(); return adminSecurityContext; } public synchronized void addSecurityContext(SecurityContext securityContext) { contexts.put(securityContext.getUUID(), securityContext); } public synchronized void addSecurityContext(String fullname, SecurityContext securityContext) { contexts.put(securityContext.getUUID(), securityContext); } public synchronized SecurityContext getSecurityContextByFullName(String fullName) throws ContextException { // ODatabaseDocument current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal(); RemoteDatabase database = null; try { SecurityContext securityContext = null; logger.trace("Trying to get {} for {}", SecurityContext.class.getSimpleName(), fullName); UUID uuid = ServerContextCache.getInstance().getUUIDByFullName(fullName); if(uuid != null) { securityContext = contexts.get(uuid); } if(securityContext==null) { logger.trace("{} for {} is not in cache. Going to get it", SecurityContext.class.getSimpleName(), fullName); database = getAdminSecurityContext().getRemoteDatabase(PermissionMode.READER); MutableVertex contextVertex = getContextVertexByFullName(database, fullName); uuid = UUIDUtility.getUUID(contextVertex); securityContext = getSecurityContextByUUID(uuid, contextVertex); addSecurityContext(fullName, securityContext); } return securityContext; } catch(ContextException e) { throw e; } catch(Exception e) { throw new ContextException("Unable to retrieve Context UUID from current Context", e); } finally { if(database!=null) { database.close(); } // if(current!=null) { // current.activateOnCurrentThread(); // } } } public SecurityContext getSecurityContextByUUID(UUID uuid) throws ResourceRegistryException { return getSecurityContextByUUID(uuid, null); } public static RemoteDatabase getCurrentODatabaseDocumentFromThreadLocal() { RemoteDatabase current = null; try { // current = (RemoteDatabase) ODatabaseRecordThreadLocal.instance().get(); }catch (Exception e) { // It is possible that there is no current ODatabaseDocument } return current; } private Vertex getContextVertexByUUID(UUID uuid) throws ResourceRegistryException { RemoteDatabase current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal(); RemoteDatabase database = null; try { database = getAdminSecurityContext().getRemoteDatabase(PermissionMode.READER); Vertex vertex = DBUtility.getElementByUUID(database, Context.NAME, uuid, Vertex.class); return vertex; } finally { if(database!=null) { database.close(); } // if(current!=null) { // current.activateOnCurrentThread(); // } } } private SecurityContext getSecurityContextByUUID(UUID uuid, Vertex contextVertex) throws ResourceRegistryException { SecurityContext securityContext = contexts.get(uuid); if(securityContext == null) { securityContext = new SecurityContext(uuid); try { if(contextVertex == null) { contextVertex = getContextVertexByUUID(uuid); } Vertex parentVertex = contextVertex.getVertices(DIRECTION.IN, IsParentOf.NAME).iterator().next(); if(parentVertex != null) { UUID parentUUID = UUIDUtility.getUUID(parentVertex); securityContext.setParentSecurityContext(getSecurityContextByUUID(parentUUID, parentVertex)); } } catch(NoSuchElementException e) { // No parent } contexts.put(uuid, securityContext); } return securityContext; } /* protected UUID getContextUUIDFromFullName(String fullName) throws ResourceRegistryException { OVertex contextVertex = getContextVertexByFullName(fullName); return Utility.getUUID(contextVertex); } */ private MutableVertex getContextVertexByFullName(RemoteDatabase database , String fullName) throws ResourceRegistryException { logger.trace("Going to get {} {} with full name '{}'", Context.NAME, Vertex.class.getSimpleName(), fullName); ScopeBean scopeBean = new ScopeBean(fullName); String name = scopeBean.name(); // TODO Rewrite better query. This query works because all the scope parts has a different name String select = "SELECT FROM " + Context.class.getSimpleName() + " WHERE " + Context.NAME_PROPERTY + " = :name"; Map map = new HashMap<>(); map.put("name", name); ResultSet resultSet = database.command("sql", select, map); if(resultSet == null || !resultSet.hasNext()) { throw new ContextNotFoundException("Error retrieving context with name " + fullName); } Result result = resultSet.next(); MutableVertex context = (MutableVertex) ElementManagementUtility.getElementFromOptional(result.getVertex()); logger.trace("Context Representing Vertex : {}", DBUtility.getAsStringForLogging(context)); if(resultSet.hasNext()) { throw new ContextNotFoundException("Found more than one context with name " + name + "but required the one with path" + fullName + ". Please Reimplement the query"); } return context; } }