package org.gcube.datatransfer.resolver.services; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.annotation.Nullable; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.QueryParam; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.ResponseBuilder; import javax.ws.rs.core.StreamingOutput; import org.apache.commons.io.IOUtils; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.datatransfer.resolver.ConstantsResolver; import org.gcube.datatransfer.resolver.caches.LoadingGeonetworkInstanceCache; import org.gcube.datatransfer.resolver.gis.GeonetworkInstance; import org.gcube.datatransfer.resolver.gis.geonetwork.FilterGetRecords; import org.gcube.datatransfer.resolver.gis.geonetwork.GNAuthentication; import org.gcube.datatransfer.resolver.gis.geonetwork.GeonetworkRequestFilterParameters.MODE; import org.gcube.datatransfer.resolver.gis.geonetwork.GeonetworkRequestFilterParameters.VISIBILITY; import org.gcube.datatransfer.resolver.gis.geonetwork.ReusableInputStream; import org.gcube.datatransfer.resolver.services.error.ExceptionManager; import org.gcube.datatransfer.resolver.util.GetResponseRecordFilter; import org.gcube.datatransfer.resolver.util.HTTPCallsUtils; import org.gcube.datatransfer.resolver.util.HTTPCallsUtils.HttpResponse; import org.gcube.datatransfer.resolver.util.ScopeUtil; import org.gcube.datatransfer.resolver.util.SingleFileStreamingOutput; import org.gcube.spatial.data.geonetwork.configuration.Configuration; import org.gcube.spatial.data.geonetwork.extension.ServerAccess.Version; import org.gcube.spatial.data.geonetwork.model.Account; import org.gcube.spatial.data.geonetwork.model.Account.Type; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; /** * The GeonetworkResolver is a "middle tier" (like a Proxy) to perform queries * on D4Science Geonetwork services. * * Request format * [GEONETWORK_RESOLVER_BASE_URL]/[SCOPE]/[MODE]/[VISIBILITY]/[FILTER_KEY]/[FILTER_VALUE]/$$ * * See more at * https://gcube.wiki.gcube-system.org/gcube/URI_Resolver#Geonetwork_Resolver * * @author Francesco Mangiacrapa at ISTI-CNR (francesco.mangiacrapa@isti.cnr.it) * Oct 23, 2018 */ @Path("geonetwork") public class GeonetworkResolver { /** * */ public static final String REPLACED_A_PUBLIC_UUID_PLEASE_IGNORE = "Replaced a public UUID, please ignore"; public static final String REPLACED_UUID_BY_FILTER_PLEASE_IGNORE = "Replaced UUID by " + GeonetworkResolver.class.getSimpleName() + " filters, please ignore"; private static Logger logger = LoggerFactory.getLogger(GeonetworkResolver.class); public static final String PATH_PARAM_MODE = "mode"; public static final String PATH_PARAM_REQUEST_DELIMITER = "requestDelimiter"; // public static final String PATH_PARAM_OWNER = "owner"; private static final String PATH_PARAM_VISIBILITY = "visibility"; private static final String PATH_PARAM_SCOPE = "scope"; public static final String CSW_SERVER = "srv/en/csw"; public static final String VALUE_OF_REQUEST_DELIMITIER = "$$"; public static final String PATH_PARAM_REMAINPATH = "remainPath"; public static final String QUERY_PARAM_RESET_CACHE_PARAM = "resetcache"; public static final String QUERY_PARAM_RESET_CACHED_SCOPE_PARAM = "resetcachedscope"; public static final String SRV_EN_MEF_EXPORT = "/srv/en/mef.export"; // MEF Geonetwork service public static final String UUID = "uuid"; public static final String SCOPE_SEPARATOR = "|"; // protected Map cacheGNInstances; private String helpURI = "https://wiki.gcube-system.org/gcube/GCube_Resource_Catalogue#Geonetwork_Resolver"; /** * Gets the geonetwork request criteria. Creates a request criteria from input * parameter pathWithoutGN The parameter pathWithoutGN should be an ordered * string (like REST request): SCOPE/MODE/VISIBILITY/OWNER/$$ SCOPE must be: * ROOT|VO|VRE MODE must be: {@link MODE} VISIBILITY must be: {@link VISIBILITY} * OWNER (is optional): filter by owner * * @param req the req * @param scope the scope * @param mode the mode * @param visibility the visibility * @param filterKey the filter key * @param filterValue the filter value * @param remainPath the remain path * @param resetCache the reset cache * @param resetScope the reset scope * @return the geonetwork request criteria * @throws WebApplicationException the web application exception */ @GET @Path("/{" + PATH_PARAM_SCOPE + "}/{" + PATH_PARAM_MODE + "}/{" + PATH_PARAM_VISIBILITY + "}/{filterKey}/{filterValue}/$${" + PATH_PARAM_REMAINPATH + ":(/[^?$]+)?}") public Response submitGet(@Context HttpServletRequest req, @PathParam(PATH_PARAM_SCOPE) @Nullable String scope, @PathParam(PATH_PARAM_MODE) @Nullable String mode, @PathParam(PATH_PARAM_VISIBILITY) @Nullable String visibility, @PathParam("filterKey") @Nullable String filterKey, @PathParam("filterValue") @Nullable String filterValue, @PathParam(PATH_PARAM_REMAINPATH) @Nullable String remainPath, @QueryParam(QUERY_PARAM_RESET_CACHE_PARAM) @Nullable String resetCache, @QueryParam(QUERY_PARAM_RESET_CACHED_SCOPE_PARAM) @Nullable String resetScope) throws WebApplicationException { logger.info(this.getClass().getSimpleName() + " GET starts..."); String gnGetlURL = null; try { logger.info( "Params are [mode: " + mode + ", scope: " + scope + ", visibility: " + visibility + ", filterKey: " + filterKey + ", filterValue: " + filterValue + ", remainPath: " + remainPath + "]"); if (scope == null || scope.isEmpty()) { logger.error("Path Parameter 'scope' not found"); throw ExceptionManager.badRequestException(req, "Missing mandatory path parameter 'scope'", this.getClass(), helpURI); } if (mode == null || mode.isEmpty()) { logger.error("Path Parameter 'scope' not found"); throw ExceptionManager.badRequestException(req, "Missing mandatory path parameter 'mode'", this.getClass(), helpURI); } scope = ScopeUtil.normalizeScope(scope, "|"); mode = mode.toUpperCase(); try { MODE.valueOf(mode); } catch (Exception e) { List toPrint = Arrays.asList(MODE.values()); logger.error( "The 'mode' parameter is wrong, Have you pass a valid parameter MODE like " + toPrint + "?"); throw ExceptionManager.wrongParameterException(req, "The 'mode' parameter must be value of " + toPrint, this.getClass(), helpURI); } if (visibility == null) { logger.error("Path Parameter 'visibility' not found"); throw ExceptionManager.badRequestException(req, "Missing mandatory path parameter 'visibility'", this.getClass(), helpURI); } visibility = visibility.toUpperCase(); try { VISIBILITY.valueOf(visibility); } catch (Exception e) { List toPrint = Arrays.asList(VISIBILITY.values()); logger.error("The 'visibility' parameter is wrong, Have you pass a valid parameter VISIBILITY like " + toPrint + "?"); throw ExceptionManager.wrongParameterException(req, "The 'visibility' parameter must be value of " + toPrint, this.getClass(), helpURI); } logger.info("Remaining path is: " + remainPath); try { // I'M LOADING GN CONFIGURATIONS (ENDPOINT, USER, PWD AND SO ON..) FOR PASSED // SCOPE FROM GN LIBRARY BY A GENERAL METHOD WITHOUT TO PERFORM AUTHENTICATION // ON GN, // AFTER THAT I'M USING THEM TO PERFORM AUTHENTICATION ON GN VIA HTTP_CLIENTS IF // NEEDED GeonetworkInstance gnInstance = getGeonetworkInstanceForScope(scope); logger.info("set scope provider " + scope); ScopeProvider.instance.set(scope); Account account = gnInstance.getAccount(); Version version = gnInstance.getVersion(); String geonetworkUrl = gnInstance.getEndPoint(); Configuration config = gnInstance.getConfig() != null ? gnInstance.getConfig() : null; if (account == null || account.getUser() == null || account.getPassword() == null || config == null) { logger.info("Loading GN instance and configurations via Geonetwork Library..."); config = gnInstance.getGeonetworkPublisher().getConfiguration(); account = config.getScopeConfiguration().getAccounts().get(Type.CKAN); version = config.getGeoNetworkVersion(); geonetworkUrl = config.getGeoNetworkEndpoint(); } logger.info("SCOPE: {}, CKAN user used is: {}, GN EndPoint: {}", scope, account.getUser(), geonetworkUrl); HTTPCallsUtils httpUtils = new HTTPCallsUtils(); if (visibility.equals(VISIBILITY.PRV.name())) { if (account.getUser() != null) { switch (version) { case DUE: boolean authorized = GNAuthentication.login(httpUtils, geonetworkUrl, account.getUser(), account.getPassword()); logger.info("Authorized on GN2 " + geonetworkUrl + " ? " + authorized); break; default: httpUtils = new HTTPCallsUtils(account.getUser(), account.getPassword()); logger.info("Authorized on GN3 via HTTCallsUtils..."); break; } } else { logger.warn("I'm not able to perform authentication, the user read from config with " + Type.CKAN + " is null"); } } String baseURL = remainPath == null || remainPath.isEmpty() ? geonetworkUrl + "/" + CSW_SERVER : geonetworkUrl + "/" + CSW_SERVER + remainPath; logger.info("The base URL is: " + baseURL); String queryString = req.getQueryString() == null || req.getQueryString().isEmpty() ? "" : "?" + req.getQueryString(); gnGetlURL = baseURL + queryString; logger.info("Sending get request to URL: " + gnGetlURL); HttpResponse proxedGNResponse = httpUtils.get(gnGetlURL); switch (proxedGNResponse.getStatus()) { case HttpServletResponse.SC_OK: // Building the response InputStream streamToWrite = IOUtils.toInputStream(proxedGNResponse.getResponse()); StreamingOutput so = new SingleFileStreamingOutput(streamToWrite); logger.info("Response return Content-Type: " + httpUtils.getLastContentType()); ResponseBuilder responseBuilder = Response.ok(so).header(ConstantsResolver.CONTENT_TYPE, httpUtils.getLastContentType()); return responseBuilder.build(); case HttpServletResponse.SC_FORBIDDEN: throw ExceptionManager.forbiddenException(req, "You are not authorized to perform the request " + gnGetlURL, this.getClass(), helpURI); default: throw ExceptionManager.internalErrorException(req, "Sorry, an error occurred performing the geonetwork request " + gnGetlURL + " with scope " + scope, this.getClass(), helpURI); } } catch (Exception e) { logger.error("Exception:", e); String error = "Sorry, an error occurred on resolving geonetwork request with scope " + scope + ". Please, contact support!"; throw ExceptionManager.internalErrorException(req, error, this.getClass(), helpURI); } } catch (Exception e) { if (!(e instanceof WebApplicationException)) { // UNEXPECTED EXCEPTION managing it as WebApplicationException String error = "Error during perform GET operation to: " + gnGetlURL + ". Please, contact the support!"; throw ExceptionManager.internalErrorException(req, error, this.getClass(), helpURI); } // ALREADY MANAGED AS WebApplicationException logger.error("Exception:", e); throw (WebApplicationException) e; } } /** * Submit post. * * @param req the req * @param scope the scope * @param mode the mode * @param visibility the visibility * @param filterKey the filter key * @param filterValue the filter value * @param remainPath the remain path * @param resetCache the reset cache * @param resetScope the reset scope * @return the response * @throws WebApplicationException the web application exception */ @POST @Path("/{" + PATH_PARAM_SCOPE + "}/{" + PATH_PARAM_MODE + "}/{" + PATH_PARAM_VISIBILITY + "}/{filterKey}/{filterValue}/$${" + PATH_PARAM_REMAINPATH + ":(/[^?$]+)?}") public Response submitPost(@Context HttpServletRequest req, @PathParam(PATH_PARAM_SCOPE) @Nullable String scope, @PathParam(PATH_PARAM_MODE) @Nullable String mode, @PathParam(PATH_PARAM_VISIBILITY) @Nullable String visibility, @PathParam("filterKey") @Nullable String filterKey, @PathParam("filterValue") @Nullable String filterValue, @PathParam(PATH_PARAM_REMAINPATH) @Nullable String remainPath, @QueryParam(QUERY_PARAM_RESET_CACHE_PARAM) @Nullable String resetCache, @QueryParam(QUERY_PARAM_RESET_CACHED_SCOPE_PARAM) @Nullable String resetScope) throws WebApplicationException { logger.info(this.getClass().getSimpleName() + " POST starts..."); String gnCSWlURL = null; try { logger.info( "Params are [mode: " + mode + ", scope: " + scope + ", visibility: " + visibility + ", filterKey: " + filterKey + ", filterValue: " + filterValue + ", remainPath: " + remainPath + "]"); if (scope == null || scope.isEmpty()) { logger.error("Path Parameter 'scope' not found"); throw ExceptionManager.badRequestException(req, "Missing mandatory path parameter 'scope'", this.getClass(), helpURI); } if (mode == null || mode.isEmpty()) { logger.error("Path Parameter 'scope' not found"); ExceptionManager.badRequestException(req, "Missing mandatory path parameter 'mode'", this.getClass(), helpURI); } scope = ScopeUtil.normalizeScope(scope, "|"); mode = mode.toUpperCase(); try { MODE.valueOf(mode); } catch (Exception e) { List toPrint = Arrays.asList(MODE.values()); logger.error( "The 'mode' parameter is wrong, Have you pass a valid parameter MODE like " + toPrint + "?"); throw ExceptionManager.wrongParameterException(req, "The 'mode' parameter must be value of " + toPrint, this.getClass(), helpURI); } if (visibility == null) { logger.error("Path Parameter 'visibility' not found"); throw ExceptionManager.badRequestException(req, "Missing mandatory path parameter 'visibility'", this.getClass(), helpURI); } visibility = visibility.toUpperCase(); try { VISIBILITY.valueOf(visibility); } catch (Exception e) { List toPrint = Arrays.asList(VISIBILITY.values()); logger.error("The 'visibility' parameter is wrong, Have you pass a valid parameter VISIBILITY like " + toPrint + "?"); throw ExceptionManager.wrongParameterException(req, "The 'visibility' parameter must be value of " + toPrint, this.getClass(), helpURI); } // HOW TO PASS ANY FILTER? // TODO INVESTIGATE ON HOW TO PASS MORE THAN ONE FILTER... Map filters = new HashMap(); if (filterKey != null && filterValue != null) { // IGNORING THE EMPTY FILTER 'null|null' if (filterKey.compareToIgnoreCase("null") != 0) { filters.put(filterKey, filterValue); logger.debug("Added filter parmas to map filters: " + filters); } } try { // I'M LOADING GN CONFIGURATIONS (ENDPOINT, USER, PWD AND SO ON..) FOR PASSED // SCOPE FROM GN LIBRARY BY A GENERAL METHOD WITHOUT TO PERFORM AUTHENTICATION // ON GN, // AFTER THAT I'M USING THEM TO PERFORM AUTHENTICATION ON GN VIA HTTP_CLIENTS IF // NEEDED GeonetworkInstance gnInstance = getGeonetworkInstanceForScope(scope); logger.info("set scope provider " + scope); ScopeProvider.instance.set(scope); Account account = gnInstance.getAccount(); Version version = gnInstance.getVersion(); String geonetworkUrl = gnInstance.getEndPoint(); Configuration config = gnInstance.getConfig() != null ? gnInstance.getConfig() : null; if (account == null || account.getUser() == null || account.getPassword() == null || config == null) { logger.info("Loading GN instance and configurations via Geonetwork Library..."); config = gnInstance.getGeonetworkPublisher().getConfiguration(); account = config.getScopeConfiguration().getAccounts().get(Type.CKAN); version = config.getGeoNetworkVersion(); geonetworkUrl = config.getGeoNetworkEndpoint(); } logger.info("SCOPE: {}, CKAN user used is: {}, GN EndPoint: {}", scope, account.getUser(), geonetworkUrl); // logger.info("Parameters.."); // for (Enumeration e = req.getParameterNames(); e.hasMoreElements();){ // String p = e.nextElement(); // logger.debug("param "+p + " value // "+Arrays.toString(req.getParameterValues(p))); // } // DEBUG BODY // String readBody = IOUtils.toString(req.getReader()); // logger.debug("doPost read body request: "+readBody); ByteArrayOutputStream byteArray = new ByteArrayOutputStream(); // SPECIFIC HANDLER FOR GEONETWORK REQUEST: /srv/en/mef.export if (remainPath != null && remainPath.compareTo(SRV_EN_MEF_EXPORT) == 0) { logger.info("In case of mef.export, perfoming a custom handler"); gnCSWlURL = geonetworkUrl + SRV_EN_MEF_EXPORT; String[] uuidValues = req.getParameterValues(UUID); if (uuidValues != null) { String data = null; for (String uuid : uuidValues) { data = UUID + "=" + uuid; } if (data != null) { logger.debug("Writing " + data + " into byte array"); byteArray.write(data.getBytes()); } else IOUtils.copy(req.getInputStream(), byteArray); } else IOUtils.copy(req.getInputStream(), byteArray); } else { logger.debug("IS NOT A REQUEST TO " + SRV_EN_MEF_EXPORT); gnCSWlURL = remainPath == null || remainPath.isEmpty() ? geonetworkUrl + "/" + CSW_SERVER : geonetworkUrl + "/" + CSW_SERVER + remainPath; IOUtils.copy(req.getInputStream(), byteArray); } HTTPCallsUtils httpUtils = new HTTPCallsUtils(); // PRIVATE LAYERS if (visibility.equals(VISIBILITY.PRV.name())) { logger.info("Visibility: " + VISIBILITY.PRV + " getting private layers.."); // VRE LAYERS if (mode.equals(MODE.VRE.name())) { logger.info("Getting " + MODE.VRE + " layers.."); // HARVESTED LAYERS } else { filters.put("isHarvested", "y"); logger.info("Getting " + MODE.HARVEST + " layers, I added 'isHarvested = y' to the filters [" + filters + "]"); } if (account.getUser() != null) { switch (version) { case DUE: boolean authorized = GNAuthentication.login(httpUtils, geonetworkUrl, account.getUser(), account.getPassword()); logger.info("Authorized on GN2 " + geonetworkUrl + " ? " + authorized); break; default: httpUtils = new HTTPCallsUtils(account.getUser(), account.getPassword()); logger.info("Authorized on GN3 via HTTCallsUtils..."); break; } } else { logger.warn("I'm not able to perform authentication, the user read from config with " + Type.CKAN + " is null"); } // PUBLIC LAYERS } else { logger.info("Visibility: " + VISIBILITY.PUB + " getting public layers.."); // VRE LAYERS if (mode.equals(MODE.VRE.name())) { logger.info("Getting " + MODE.VRE + " layers, the VRE account: " + account.getUser() + " will be used as owner user for filtering... Is it right?"); filters.put("ownername", account.getUser()); // HARVESTED LAYERS } else { // filters.put("isHarvested", "y"); logger.info("Getting " + MODE.HARVEST + " layers, I'm applying the filters [" + filters + "]"); } } logger.info("Sending CSW POST request to URL: " + gnCSWlURL); logger.debug("Content-Type: " + req.getContentType()); // DEBUG // logger.debug("POST - BODY : "+byteArray.toString()); InputStream in = httpUtils.post(gnCSWlURL, new ByteArrayInputStream(byteArray.toByteArray()), req.getContentType(), req.getParameterMap()); if (in == null) { logger.warn("Input stream returned is null, sending " + HttpServletResponse.SC_NOT_FOUND); throw ExceptionManager.notFoundException(req, "Input stream is null to the request " + gnCSWlURL + " with body: " + byteArray.toString(), this.getClass(), helpURI); } try { ReusableInputStream reus = new ReusableInputStream(in); if (visibility.equals(VISIBILITY.PRV.name())) { logger.info( "Private VISIBILITY requested, retrieving public file identifiers to apply filtering.."); FilterGetRecords filterGetRecords = new FilterGetRecords(byteArray.toString(), geonetworkUrl); if (filterGetRecords.getFoundPublicIds() != null && filterGetRecords.getFoundPublicIds().size() > 0) { logger.info("I'm removing list of public IDs with " + filterGetRecords.getFoundPublicIds().size() + " item/s. Is it right?"); in = GetResponseRecordFilter.overrideResponseIdsByListIds(reus, filterGetRecords.getFoundPublicIds(), REPLACED_A_PUBLIC_UUID_PLEASE_IGNORE); } } if (filters.size() > 0) { logger.info("Applying filtering on geonet:info... filter/s used: " + filters); Document doc = GetResponseRecordFilter.inputStreamToW3CDocument(reus); List fileIdentifiers = GetResponseRecordFilter.getTextContentStringsForTagName(doc, "gmd:fileIdentifier"); List noMatchingFilter = new ArrayList(); for (String fileId : fileIdentifiers) { // CKECKING THE FILTERS for (String fkey : filters.keySet()) { String value = GetResponseRecordFilter.getMetadataValueByFileIdentifier(fileId, config.getGeoNetworkEndpoint(), config.getAdminAccount().getUser(), config.getAdminAccount().getPassword(), fkey); // String own = GetResponseRecordFilter.getMetaOwnerNameByFileIdentifier(fileId, // config.getGeoNetworkEndpoint(),config.getAdminAccount().getUser(), // config.getAdminAccount().getPassword()); String fValue = filters.get(fkey); // Either the filter KEY doesn't matching any geonet:info (value==null) // or the value of filterKey in geonet:info doesn't matching the passed // filterValue (value.compareTo(fValue)!=0) if (value == null || value.compareTo(fValue) != 0) { logger.trace(fkey + " of File Identifier " + fileId + " not matching the filter: " + fkey + " with value: " + fValue + ", adding it to list to remove file identifier and exit from loop.."); noMatchingFilter.add(fileId); // WHEN I ADD THE FILE IDENTIFIER TO FILTERED ID, I CAN EXIT FROM CKECKING // FILTERS LOOP break; } } } if (noMatchingFilter.size() > 0) { logger.info("Removing " + noMatchingFilter.size() + " layer/s that not macthing the filters: " + filters); // Document doc2 = GetResponseRecordFilter.inputStreamToW3CDocument(reus); in = GetResponseRecordFilter.overrideResponseIdsByListIds(reus, noMatchingFilter, REPLACED_UUID_BY_FILTER_PLEASE_IGNORE); // in = GetResponseRecordFilter.w3CDocumentToInputStream(doc); } else { logger.info("No replace on UUIDs was applied from filters: " + filters); in = reus; } } ReusableInputStream reusIs = new ReusableInputStream(in); // END DEBUG logger.info("Response return Content-Type: " + httpUtils.getLastContentType()); return Response.ok(reusIs) // .header(ConstantsResolver.CONTENT_DISPOSITION,"attachment; filename = // \""+fileName+"\"") .header(ConstantsResolver.CONTENT_TYPE, httpUtils.getLastContentType()).build(); } catch (Exception e) { logger.error("Error on copy the response to send to client: ", e); throw ExceptionManager.internalErrorException(req, "Error on copy the response!", this.getClass(), helpURI); } finally { IOUtils.closeQuietly(in); } } catch (IllegalArgumentException e) { logger.error("IllegalArgumentException:", e); throw ExceptionManager.badRequestException(req, "Illegal argument to carry out the request!", this.getClass(), helpURI); } catch (Exception e) { logger.error("Exception:", e); String error = "Sorry, an error occurred on resolving geonetwork request with scope " + scope + ". Please, contact support!"; throw ExceptionManager.internalErrorException(req, error, this.getClass(), helpURI); } } catch (Exception e) { if (!(e instanceof WebApplicationException)) { // UNEXPECTED EXCEPTION managing it as WebApplicationException String error = "Error during perform POST operation to: " + gnCSWlURL + ". Please, contact the support!"; if (e.getCause() != null) error += "\n\nCaused: " + e.getCause().getMessage(); throw ExceptionManager.internalErrorException(req, error, this.getClass(), helpURI); } // ALREADY MANAGED AS WebApplicationException logger.error("Exception:", e); throw (WebApplicationException) e; } } /** * Gets the geonetwork instance for scope. * * @param scope the scope * @return the geonetwork instance for scope * @throws Exception the exception */ protected GeonetworkInstance getGeonetworkInstanceForScope(String scope) throws Exception { logger.info("Trying to read the {} from cache for scope: {}", GeonetworkInstance.class.getSimpleName(), scope); GeonetworkInstance geoInstance; try { geoInstance = LoadingGeonetworkInstanceCache.get(scope); } catch (Exception e) { logger.error("An error occurred on reading GeonetworkInstance for scope " + scope, e); throw new Exception("Sorry, An error occurred on reading GeonetworkInstance for scope " + scope); } return geoInstance; } }