package org.gcube.informationsystem.resourceregistry.context; import java.io.IOException; import java.net.HttpURLConnection; import java.util.List; import java.util.UUID; import org.gcube.com.fasterxml.jackson.core.JsonProcessingException; import org.gcube.common.gxhttp.reference.GXConnection; import org.gcube.common.gxhttp.request.GXHTTPStringRequest; import org.gcube.informationsystem.context.reference.entities.Context; import org.gcube.informationsystem.model.impl.properties.HeaderImpl; import org.gcube.informationsystem.model.reference.properties.Header; import org.gcube.informationsystem.resourceregistry.api.contexts.ContextCache; import org.gcube.informationsystem.resourceregistry.api.contexts.ContextCacheRenewal; import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException; import org.gcube.informationsystem.resourceregistry.api.exceptions.context.ContextAlreadyPresentException; import org.gcube.informationsystem.resourceregistry.api.exceptions.context.ContextNotFoundException; import org.gcube.informationsystem.resourceregistry.api.rest.AccessPath; import org.gcube.informationsystem.resourceregistry.api.rest.ContextPath; import org.gcube.informationsystem.resourceregistry.api.rest.httputils.HTTPUtility; import org.gcube.informationsystem.utils.ElementMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Luca Frosini (ISTI - CNR) */ public class ResourceRegistryContextClientImpl implements ResourceRegistryContextClient { private static final Logger logger = LoggerFactory.getLogger(ResourceRegistryContextClientImpl.class); protected final String address; protected ContextCacheRenewal contextCacheRenewal = new ContextCacheRenewal() { @Override public List renew() throws ResourceRegistryException { return getAllContextFromServer(); } }; public ResourceRegistryContextClientImpl(String address) { this.address = address; ContextCache contextCache = ContextCache.getInstance(); contextCache.setContextCacheRenewal(contextCacheRenewal); } private void forceCacheRefresh() { try { ContextCache contextCache = ContextCache.getInstance(); contextCache.cleanCache(); contextCache.refreshContextsIfNeeded(); }catch (Exception e) { logger.warn("Unable to force cache refresh.", e); } } protected String internalCreate(Context context) throws ContextAlreadyPresentException, ResourceRegistryException { try { Header header = context.getHeader(); if(header == null) { header = new HeaderImpl(UUID.randomUUID()); context.setHeader(header); } UUID uuid = context.getHeader().getUUID(); String contextString = ElementMapper.marshal(context); logger.trace("Going to create {}", contextString); GXHTTPStringRequest gxHTTPStringRequest = GXHTTPStringRequest.newRequest(address); gxHTTPStringRequest.from(ResourceRegistryContextClient.class.getSimpleName()); gxHTTPStringRequest.header("Accept", GXConnection.APPLICATION_JSON_CHARSET_UTF_8); gxHTTPStringRequest.header("Content-type", GXConnection.APPLICATION_JSON_CHARSET_UTF_8); gxHTTPStringRequest.path(ContextPath.CONTEXTS_PATH_PART); gxHTTPStringRequest.path(uuid.toString()); HttpURLConnection httpURLConnection = gxHTTPStringRequest.put(contextString); String c = HTTPUtility.getResponse(String.class, httpURLConnection); forceCacheRefresh(); logger.trace("{} successfully created", c); return c; } catch(ResourceRegistryException e) { // logger.trace("Error Creating {}", facet, e); throw e; } catch(Exception e) { // logger.trace("Error Creating {}", facet, e); throw new RuntimeException(e); } } @Override public Context create(Context context) throws ContextAlreadyPresentException, ResourceRegistryException { try { String res = internalCreate(context); return ElementMapper.unmarshal(Context.class, res); } catch(ResourceRegistryException e) { // logger.trace("Error Creating {}", facet, e); throw e; } catch(Exception e) { // logger.trace("Error Creating {}", facet, e); throw new RuntimeException(e); } } @Override public String create(String context) throws ContextAlreadyPresentException, ResourceRegistryException { try { Context c = ElementMapper.unmarshal(Context.class, context); return internalCreate(c); } catch(ResourceRegistryException e) { // logger.trace("Error Creating {}", facet, e); throw e; } catch(Exception e) { // logger.trace("Error Creating {}", facet, e); throw new RuntimeException(e); } } @Override public Context read(Context context) throws ContextNotFoundException, ResourceRegistryException { return read(context.getHeader().getUUID()); } @Override public Context read(UUID uuid) throws ContextNotFoundException, ResourceRegistryException { ContextCache contextCache = ContextCache.getInstance(); Context context = ContextCache.getInstance().getContextByUUID(uuid);; if(context == null) { String contextJson = readFromServer(uuid.toString()); try { context = ElementMapper.unmarshal(Context.class, contextJson); } catch (IOException e) { throw new RuntimeException(e); } forceCacheRefresh(); Context c = contextCache.getContextByUUID(context.getHeader().getUUID()); if(c!=null){ context = c; }else { logger.error("Context with UUID {} is {}. It is possibile to get it from the server but not from the cache. This is very strange and should not occur.", uuid, context); } } return context; } @Override public Context readCurrentContext() throws ContextNotFoundException, ResourceRegistryException { String contextFullName = ResourceRegistryContextClientFactory.getCurrentContextFullName(); ContextCache contextCache = ContextCache.getInstance(); UUID uuid = contextCache.getUUIDByFullName(contextFullName); Context context = null; if(uuid == null) { String contextJson = readFromServer(AccessPath.CURRENT_CONTEXT); try { context = ElementMapper.unmarshal(Context.class, contextJson); } catch (IOException e) { throw new RuntimeException(e); } contextCache.cleanCache(); contextCache.refreshContextsIfNeeded(); Context c = contextCache.getContextByUUID(context.getHeader().getUUID()); if(c!=null){ context = c; }else { logger.error("Current Context is {}. It is possibile to get it from the server but not from the cache. This is very strange and should not occur.", contextFullName); } }else { context = contextCache.getContextByUUID(uuid); } return context; } @Override public String read(String uuid) throws ContextNotFoundException, ResourceRegistryException { try { return ElementMapper.marshal(read(UUID.fromString(uuid))); } catch (ContextNotFoundException e) { throw e; } catch (JsonProcessingException e) { throw new RuntimeException(e); } catch (ResourceRegistryException e) { throw e; } } public String readFromServer(String uuid) throws ContextNotFoundException, ResourceRegistryException { try { logger.trace("Going to read {} with UUID {}", Context.NAME, uuid); GXHTTPStringRequest gxHTTPStringRequest = GXHTTPStringRequest.newRequest(address); gxHTTPStringRequest.from(ResourceRegistryContextClient.class.getSimpleName()); gxHTTPStringRequest.header("Accept", GXConnection.APPLICATION_JSON_CHARSET_UTF_8); gxHTTPStringRequest.path(ContextPath.CONTEXTS_PATH_PART); gxHTTPStringRequest.path(uuid); HttpURLConnection httpURLConnection = gxHTTPStringRequest.get(); String c = HTTPUtility.getResponse(String.class, httpURLConnection); logger.debug("Got {} is {}", Context.NAME, c); return c; } catch(ResourceRegistryException e) { // logger.trace("Error Creating {}", facet, e); throw e; } catch(Exception e) { // logger.trace("Error Creating {}", facet, e); throw new RuntimeException(e); } } public String internalUpdate(Context context) throws ContextNotFoundException, ResourceRegistryException { try { String contextString = ElementMapper.marshal(context); logger.trace("Going to update {}", contextString); UUID uuid = context.getHeader().getUUID(); GXHTTPStringRequest gxHTTPStringRequest = GXHTTPStringRequest.newRequest(address); gxHTTPStringRequest.from(ResourceRegistryContextClient.class.getSimpleName()); gxHTTPStringRequest.header("Accept", GXConnection.APPLICATION_JSON_CHARSET_UTF_8); gxHTTPStringRequest.header("Content-type", GXConnection.APPLICATION_JSON_CHARSET_UTF_8); gxHTTPStringRequest.path(ContextPath.CONTEXTS_PATH_PART); gxHTTPStringRequest.path(uuid.toString()); HttpURLConnection httpURLConnection = gxHTTPStringRequest.put(contextString); String c = HTTPUtility.getResponse(String.class, httpURLConnection); forceCacheRefresh(); logger.trace("{} successfully updated", c); return c; } catch(ResourceRegistryException e) { // logger.trace("Error Creating {}", facet, e); throw e; } catch(Exception e) { // logger.trace("Error Creating {}", facet, e); throw new RuntimeException(e); } } @Override public Context update(Context context) throws ContextNotFoundException, ResourceRegistryException { try { String res = internalUpdate(context); return ElementMapper.unmarshal(Context.class, res); } catch(ResourceRegistryException e) { // logger.trace("Error Updating {}", facet, e); throw e; } catch(Exception e) { // logger.trace("Error Updating {}", facet, e); throw new RuntimeException(e); } } @Override public String update(String context) throws ContextNotFoundException, ResourceRegistryException { try { Context c = ElementMapper.unmarshal(Context.class, context); return internalUpdate(c); } catch(ResourceRegistryException e) { // logger.trace("Error Updating {}", facet, e); throw e; } catch(Exception e) { // logger.trace("Error Updating {}", facet, e); throw new RuntimeException(e); } } @Override public boolean delete(Context context) throws ContextNotFoundException, ResourceRegistryException { return delete(context.getHeader().getUUID()); } @Override public boolean delete(UUID uuid) throws ContextNotFoundException, ResourceRegistryException { return delete(uuid.toString()); } @Override public boolean delete(String uuid) throws ContextNotFoundException, ResourceRegistryException { try { logger.trace("Going to delete {} with UUID {}", Context.NAME, uuid); GXHTTPStringRequest gxHTTPStringRequest = GXHTTPStringRequest.newRequest(address); gxHTTPStringRequest.from(ResourceRegistryContextClient.class.getSimpleName()); gxHTTPStringRequest.header("Accept", GXConnection.APPLICATION_JSON_CHARSET_UTF_8); gxHTTPStringRequest.path(ContextPath.CONTEXTS_PATH_PART); gxHTTPStringRequest.path(uuid); HttpURLConnection httpURLConnection = gxHTTPStringRequest.delete(); HTTPUtility.getResponse(String.class, httpURLConnection); boolean deleted = true; logger.info("{} with UUID {} {}", Context.NAME, uuid, deleted ? " successfully deleted" : "was NOT deleted"); return deleted; } catch(ResourceRegistryException e) { // logger.trace("Error Creating {}", facet, e); throw e; } catch(Exception e) { // logger.trace("Error Creating {}", facet, e); throw new RuntimeException(e); }finally { try { ContextCache contextCache = ContextCache.getInstance(); contextCache.cleanCache(); contextCache.refreshContextsIfNeeded(); }catch (Exception e) { } } } protected List getAllContextFromServer() throws ResourceRegistryException { try { logger.trace("Going to read {} with UUID {}", Context.NAME); GXHTTPStringRequest gxHTTPStringRequest = GXHTTPStringRequest.newRequest(address); gxHTTPStringRequest.from(ResourceRegistryContextClient.class.getSimpleName()); gxHTTPStringRequest.header("Accept", GXConnection.APPLICATION_JSON_CHARSET_UTF_8); gxHTTPStringRequest.path(ContextPath.CONTEXTS_PATH_PART); HttpURLConnection httpURLConnection = gxHTTPStringRequest.get(); String all = HTTPUtility.getResponse(String.class, httpURLConnection); logger.debug("Got contexts are {}", Context.NAME, all); return ElementMapper.unmarshalList(Context.class, all); } catch(ResourceRegistryException e) { // logger.trace("Error Creating {}", facet, e); throw e; } catch(Exception e) { // logger.trace("Error Creating {}", facet, e); throw new RuntimeException(e); } } @Override public List all() throws ResourceRegistryException { ContextCache contextCache = ContextCache.getInstance(); return contextCache.getContexts(); } }