diff --git a/distro/README b/distro/README index 054cd4a..d5d57c8 100644 --- a/distro/README +++ b/distro/README @@ -21,7 +21,6 @@ Authors -------------------------------------------------- * Luca Frosini (luca.frosini-AT-isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy). -* Costantino Perciante (costantino.perciante@isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy). Maintainers ----------- diff --git a/distro/changelog.xml b/distro/changelog.xml index 9d50d14..0d635f9 100644 --- a/distro/changelog.xml +++ b/distro/changelog.xml @@ -1,31 +1,7 @@ - - - - - Complete refactoring of code - Item Port type is now RESTful (old methods are still allowed) - Added update support for Item #11516 - Changed caching mechanism from ehcache API to JSR-107. Ehcache is still used as runtime library. - Solved random NullPointer Exception on catalogue-ws related to old caching mechanism #11466 - Fixed normalization of the organization name #12506 - Added the possibility to deny social post on catalogue-ws #12514 - - - Item purge method enhanced - - - Minor fixes while checking user's permissions - Namespaces are no longer transparently managed - Fixed 'default' value for metadata - Improved exception handling - - + First Release diff --git a/pom.xml b/pom.xml index b416acb..e98146a 100644 --- a/pom.xml +++ b/pom.xml @@ -34,11 +34,6 @@ pom import - - org.gcube.common - gxRest - 1.0.1-SNAPSHOT - @@ -52,9 +47,9 @@ - scm:https://svn.d4science.research-infrastructures.eu/gcube/trunk/data-catalogue/${project.artifactId} - scm:https://svn.d4science.research-infrastructures.eu/gcube//trunk/data-catalogue/${project.artifactId} - https://svn.d4science.research-infrastructures.eu/gcube/trunk/data-catalogue/${project.artifactId} + scm:https://svn.d4science.research-infrastructures.eu/gcube/trunk/data-publishing/${project.artifactId} + scm:https://svn.d4science.research-infrastructures.eu/gcube//trunk/data-publishing/${project.artifactId} + https://svn.d4science.research-infrastructures.eu/gcube/trunk/data-publishing/${project.artifactId} @@ -144,6 +139,14 @@ provided + + + org.gcube.common + gxRest + [1.0.0-SNAPSHOT,2.0.0-SNAPSHOT) + + + com.fasterxml.jackson.core @@ -233,15 +236,14 @@ 20140107 + + org.gcube.data-publishing + storagehub-application-persistence + [1.0.0-SNAPSHOT,2.0.0-SNAPSHOT) + - - org.glassfish.jersey.test-framework.providers - jersey-test-framework-provider-grizzly2 - ${version.jersey} - test - junit junit diff --git a/src/main/java/org/gcube/gcat/oldutils/CachesManager.java b/src/main/java/org/gcube/gcat/oldutils/CachesManager.java index a37621d..8ea017c 100644 --- a/src/main/java/org/gcube/gcat/oldutils/CachesManager.java +++ b/src/main/java/org/gcube/gcat/oldutils/CachesManager.java @@ -8,37 +8,36 @@ import javax.cache.expiry.CreatedExpiryPolicy; import javax.cache.expiry.Duration; import javax.cache.spi.CachingProvider; -import org.gcube.datacatalogue.metadatadiscovery.DataCalogueMetadataFormatReader; +// import org.gcube.datacatalogue.metadatadiscovery.DataCalogueMetadataFormatReader; import com.fasterxml.jackson.databind.JsonNode; /** - * Handle caches via Ehcache stuff. * @author Costantino Perciante (ISTI - CNR) * @author Luca Frosini (ISTI - CNR) */ public class CachesManager { // the following caches are declared within the ehcache.xml (no default is available, so pay attention) - public static final String PROFILES_READERS_CACHE = "profile_readers"; + // public static final String PROFILES_READERS_CACHE = "profile_readers"; public static final String PROFILES_USERS_CACHE = "profile_users"; private static final CacheManager cacheManager; - private static final Cache readerCache; + // private static final Cache readerCache; private static final Cache userCache; static { CachingProvider provider = Caching.getCachingProvider(); cacheManager = provider.getCacheManager(); + /* MutableConfiguration readerConfiguration = new MutableConfiguration() .setTypes(String.class, DataCalogueMetadataFormatReader.class) .setStoreByValue(false) .setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(Duration.ONE_MINUTE)); readerCache = cacheManager.createCache(PROFILES_READERS_CACHE, readerConfiguration); - - + */ MutableConfiguration userConfiguration = new MutableConfiguration() @@ -50,9 +49,11 @@ public class CachesManager { private CachesManager() {} + /* public static Cache getReaderCache() { return readerCache; } + */ public static Cache getUserCache() { return userCache; diff --git a/src/main/java/org/gcube/gcat/oldutils/Validator.java b/src/main/java/org/gcube/gcat/oldutils/Validator.java index 4f28780..f992930 100644 --- a/src/main/java/org/gcube/gcat/oldutils/Validator.java +++ b/src/main/java/org/gcube/gcat/oldutils/Validator.java @@ -16,8 +16,6 @@ import javax.ws.rs.BadRequestException; import org.apache.commons.lang.math.NumberUtils; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.datacatalogue.ckanutillibrary.server.utils.CatalogueUtilMethods; -import org.gcube.datacatalogue.metadatadiscovery.DataCalogueMetadataFormatReader; -import org.gcube.datacatalogue.metadatadiscovery.bean.MetadataProfile; import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.DataType; import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.MetadataField; import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.MetadataFormat; @@ -27,8 +25,7 @@ import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.NamespaceCategory; import org.gcube.gcat.persistence.ckan.CKAN; import org.gcube.gcat.persistence.ckan.CKANPackage; import org.gcube.gcat.persistence.ckan.CKANUtility; -import org.gcube.gcat.rest.Namespace; -import org.gcube.gcat.rest.Profile; +import org.gcube.gcat.profile.MetadataUtility; import org.gcube.gcat.social.SocialService; import org.geojson.GeoJsonObject; import org.json.simple.JSONArray; @@ -66,12 +63,11 @@ public class Validator { return jsonObject; } - public static void validateAgainstProfile(String json, List profiles) throws Exception { + public static void validateAgainstProfile(String json) throws Exception { JSONObject jsonObject = getJSONObject(json); - validateAgainstProfile(jsonObject, profiles); + validateAgainstProfile(jsonObject); } - /** * This method validate the incoming json dataset wrt a metadata profile * @param json @@ -80,14 +76,14 @@ public class Validator { * @return * @throws Exception */ - public static void validateAgainstProfile(JSONObject obj, List profiles) throws Exception { + public static void validateAgainstProfile(JSONObject obj) throws Exception { JSONArray extrasArrayOriginal = (JSONArray) obj.get(CKANPackage.EXTRA_TYPES_KEY); JSONArray groupsArrayOriginal = (JSONArray) obj.get(CKANPackage.GROUPS_KEY); JSONArray tagsArrayOriginal = (JSONArray) obj.get(CKANPackage.TAGS_KEY); if(extrasArrayOriginal == null || extrasArrayOriginal.isEmpty()) { - throw new Exception("'extras' field is missing in context where metadata profile(s) are defined!"); + throw new BadRequestException("'extras' field is missing in context where metadata profile(s) are defined!"); } if(groupsArrayOriginal == null) { @@ -115,26 +111,18 @@ public class Validator { } if(metadataTypeCF == null) { - throw new Exception("'" + CKANPackage.EXTRA_TYPES_KEY_VALUE_SYSTEM_TYPE + throw new BadRequestException("'" + CKANPackage.EXTRA_TYPES_KEY_VALUE_SYSTEM_TYPE + "' extra field is missing in context where metadata profile(s) are defined!"); } - + String profileName = metadataTypeCF.getValue(); // fetch the profile by metadata type specified above - MetadataFormat profile = null; - for(String profileName : profiles) { - profile = Validator.getMetadataProfile(profileName); - if(profile.getType().equals(metadataTypeCF.getValue())) { - break; - } else { - profile = null; - } - } - + MetadataUtility metadataUtility = MetadataUtility.getInstance(); + MetadataFormat profile = metadataUtility.getMetadataFormat(profileName); if(profile == null) { - throw new Exception("'" + CKANPackage.EXTRA_TYPES_KEY_VALUE_SYSTEM_TYPE - + "' extra field's value ('" + metadataTypeCF.getValue() + - "') specified as custom field doesn't match any of the profiles defined in this context!"); + throw new BadRequestException("'" + CKANPackage.EXTRA_TYPES_KEY_VALUE_SYSTEM_TYPE + "' extra field's value ('" + + profileName + + "') specified as custom field doesn't match any of the profiles defined in this context!"); } else { JSONArray extrasArrayUpdated = null; List metadataFields = profile.getMetadataFields(); @@ -144,7 +132,7 @@ public class Validator { } else { extrasArrayUpdated = new JSONArray(); - List categories = Namespace.getNamespaceCategories(); + List categories = metadataUtility.getNamespaceCategories(); logger.debug("Retrieved namespaces are {}", categories); List categoriesIds = new ArrayList(categories == null ? 0 : categories.size()); if(categories == null || categories.isEmpty()) { @@ -196,7 +184,7 @@ public class Validator { + " times and its lower bound is " + lowerBound + " and upper bound " + upperBound); if(inserted < lowerBound || inserted > upperBound) { - throw new Exception("Field with key '" + entry.getKey() + throw new BadRequestException("Field with key '" + entry.getKey() + "' is mandatory, but it's not present among the provided fields or its cardinality is not respected ([min = " + lowerBound + ", max=" + upperBound + "])."); } @@ -204,7 +192,7 @@ public class Validator { // if there are no tags, throw an exception if(tagsArrayOriginal.isEmpty()) { - throw new Exception("Please define at least one tag for this item!"); + throw new BadRequestException("Please define at least one tag for this item!"); } // sort validated custom fields and add to the extrasArrayUpdated json array @@ -422,7 +410,8 @@ public class Validator { JSONObject group = new JSONObject(); group.put("name", CatalogueUtilMethods.fromGroupTitleToName(title)); if(propagateUp) { - List parents = Validator.getGroupHierarchyNames(CatalogueUtilMethods.fromGroupTitleToName(title)); + List parents = Validator + .getGroupHierarchyNames(CatalogueUtilMethods.fromGroupTitleToName(title)); for(String parent : parents) { JSONObject groupP = new JSONObject(); groupP.put("name", parent); @@ -464,7 +453,7 @@ public class Validator { if((value == null || value.isEmpty())) if(metadataField.getMandatory() || hasControlledVocabulary) - throw new Exception("Mandatory field with name '" + key + throw new BadRequestException("Mandatory field with name '" + key + "' doesn't have a value but it is mandatory or has a controlled vocabulary!"); else { if(defaultValue != null && !defaultValue.isEmpty()) { @@ -480,7 +469,7 @@ public class Validator { case Text: if(regex != null && !value.matches(regex)) - throw new Exception("Field with key '" + key + "' doesn't match the provided regular expression (" + throw new BadRequestException("Field with key '" + key + "' doesn't match the provided regular expression (" + regex + ")!"); if(hasControlledVocabulary) { @@ -498,7 +487,7 @@ public class Validator { } if(!match) - throw new Exception("Field with key '" + key + "' has a value '" + value + throw new BadRequestException("Field with key '" + key + "' has a value '" + value + "' but it doesn't match any of the vocabulary's values (" + valuesVocabulary + ")!"); } @@ -507,7 +496,7 @@ public class Validator { case Time: if(!isValidDate(value)) - throw new Exception("Field with key '" + key + "' doesn't seem a valid time!"); + throw new BadRequestException("Field with key '" + key + "' doesn't seem a valid time!"); break; case Time_Interval: @@ -516,7 +505,7 @@ public class Validator { for(int i = 0; i < timeValues.length; i++) { String time = timeValues[i]; if(!isValidDate(time)) - throw new Exception("Field with key '" + key + "' doesn't seem a valid time interval!"); + throw new BadRequestException("Field with key '" + key + "' doesn't seem a valid time interval!"); } break; @@ -526,11 +515,11 @@ public class Validator { for(int i = 0; i < timeIntervals.length; i++) { String[] timeIntervalValues = timeIntervals[i].split("/"); if(timeIntervalValues.length > 2) - throw new Exception("Field with key '" + key + "' doesn't seem a valid list of times!"); + throw new BadRequestException("Field with key '" + key + "' doesn't seem a valid list of times!"); for(i = 0; i < timeIntervalValues.length; i++) { String time = timeIntervalValues[i]; if(!isValidDate(time)) - throw new Exception("Field with key '" + key + "' doesn't seem a valid list of times!"); + throw new BadRequestException("Field with key '" + key + "' doesn't seem a valid list of times!"); } } @@ -540,13 +529,13 @@ public class Validator { if(value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false")) { } else - throw new Exception("Field with key '" + key + "' doesn't seem a valid boolean value!"); + throw new BadRequestException("Field with key '" + key + "' doesn't seem a valid boolean value!"); break; case Number: if(!NumberUtils.isNumber(value)) - throw new Exception("Field's value with key '" + key + "' is not a valid number!"); + throw new BadRequestException("Field's value with key '" + key + "' is not a valid number!"); break; case GeoJSON: @@ -554,7 +543,7 @@ public class Validator { try { new ObjectMapper().readValue(fieldToValidate.getValue(), GeoJsonObject.class); } catch(Exception e) { - throw new Exception("GeoJSON field with key '" + key + "' seems not valid!"); + throw new BadRequestException("GeoJSON field with key '" + key + "' seems not valid!"); } break; @@ -607,27 +596,4 @@ public class Validator { return toReturn; } - - /** - * Returns the metadataform of the metadata profile (specified via name) in a given context - * @param context - * @return - * @throws Exception - */ - public static MetadataFormat getMetadataProfile(String profileName) throws Exception { - - DataCalogueMetadataFormatReader reader = Profile.getDataCalogueMetadataFormatReader(); - List listProfiles = reader.getListOfMetadataProfiles(); - - if(listProfiles != null && !listProfiles.isEmpty()) { - for(MetadataProfile profile : listProfiles) { - if(profile.getName().equals(profileName)) { - return reader.getMetadataFormatForMetadataProfile(profile); - } - } - } - - return null; - } - } diff --git a/src/main/java/org/gcube/gcat/persistence/ckan/CKAN.java b/src/main/java/org/gcube/gcat/persistence/ckan/CKAN.java index be772d9..2402906 100644 --- a/src/main/java/org/gcube/gcat/persistence/ckan/CKAN.java +++ b/src/main/java/org/gcube/gcat/persistence/ckan/CKAN.java @@ -1,6 +1,11 @@ package org.gcube.gcat.persistence.ckan; +import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; import java.util.HashMap; import java.util.Map; @@ -10,12 +15,13 @@ import javax.ws.rs.NotAuthorizedException; import javax.ws.rs.NotFoundException; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response.Status; +import org.gcube.common.gxhttp.request.GXHTTPStringRequest; import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogue; import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogueFactory; +import org.gcube.gcat.utils.Constants; import org.gcube.gcat.utils.ContextUtility; -import org.gcube.gcat.utils.HTTPCall; -import org.gcube.gcat.utils.HTTPCall.HTTPMETHOD; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,6 +49,9 @@ public abstract class CKAN { protected static final String RESULT_KEY = "result"; protected static final String SUCCESS_KEY = "success"; + public static final String LIMIT_KEY = "limit"; + public static final String OFFSET_KEY = "offset"; + protected static final String NOT_FOUND_ERROR = "Not Found Error"; protected static final String AUTHORIZATION_ERROR = "Authorization Error"; protected static final String VALIDATION_ERROR = "Validation Error"; @@ -53,6 +62,8 @@ public abstract class CKAN { // ckan header authorization public final static String AUTH_CKAN_HEADER = "Authorization"; + public final static String NAME_REGEX = "^[a-z0-9_\\\\-]{2,100}$"; + protected String LIST; protected String CREATE; protected String READ; @@ -68,24 +79,24 @@ public abstract class CKAN { protected String apiKey; protected JsonNode result; - + protected String nameRegex; public String getApiKey() { - if(apiKey==null) { + if(apiKey == null) { try { return CKANUtility.getApiKey(); - }catch (Exception e) { + } catch(Exception e) { throw new InternalServerErrorException(e); } } return apiKey; } - + public void setApiKey(String apiKey) { this.apiKey = apiKey; } - + public String getName() { return name; } @@ -106,7 +117,8 @@ public abstract class CKAN { try { this.mapper = new ObjectMapper(); this.dataCatalogue = getCatalogue(); - }catch (Exception e) { + this.nameRegex = CKAN.NAME_REGEX; + } catch(Exception e) { throw new InternalServerErrorException(e); } } @@ -130,7 +142,6 @@ public abstract class CKAN { return DataCatalogueFactory.getFactory().getUtilsPerScope(context); } - /** * Validate the CKAN response and return the * @param json @@ -150,7 +161,6 @@ public abstract class CKAN { throw new BadRequestException(getAsString(error)); } - String message = error.get(MESSAGE_KEY).asText(); if(errorType.compareTo(NOT_FOUND_ERROR) == 0) { @@ -161,8 +171,6 @@ public abstract class CKAN { throw new NotAuthorizedException(message); } - - // TODO parse more cases } catch(WebApplicationException e) { throw e; @@ -185,14 +193,18 @@ public abstract class CKAN { protected JsonNode checkName(JsonNode jsonNode) { try { String gotName = jsonNode.get(NAME_KEY).asText(); - if(name==null) { + if(!gotName.matches(nameRegex)) { + throw new BadRequestException("The 'name' must be between 2 and 100 characters long and contain only lowercase alphanumeric characters, '-' and '_'. You can validate your name using the regular expression : " + NAME_REGEX); + } + + if(name == null) { name = gotName; } if(gotName != null && gotName.compareTo(name) != 0) { String error = String.format( - "The name (%s) does not match with the '%s' contained in the provided content (%s).", - name, NAME_KEY, gotName); + "The name (%s) does not match with the '%s' contained in the provided content (%s).", name, + NAME_KEY, gotName); throw new BadRequestException(error); } return jsonNode; @@ -229,35 +241,83 @@ public abstract class CKAN { return map; } - public JsonNode sendRequest(HTTPMETHOD httpMethod, String path, Map parameters, String body) { - String catalogueURL = dataCatalogue.getCatalogueUrl().endsWith("/") ? dataCatalogue.getCatalogueUrl() : dataCatalogue.getCatalogueUrl() + "/"; - HTTPCall httpCall = new HTTPCall(catalogueURL); - httpCall.setgCubeTargetService(false); - httpCall.addHeader(AUTH_CKAN_HEADER, getApiKey()); - String ret = httpCall.call(path, httpMethod, parameters, body, MediaType.APPLICATION_JSON); - JsonNode result = validateCKANResponse(ret); - if(result instanceof NullNode) { - result = mapper.createObjectNode(); + protected StringBuilder getStringBuilder(InputStream inputStream) throws IOException { + StringBuilder result = new StringBuilder(); + try(BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { + String line; + while((line = reader.readLine()) != null) { + result.append(line); + } } + return result; } - public String sendGetRequest(String path, Map parameters) { - result = sendRequest(HTTPMETHOD.GET, path, parameters, null); + protected GXHTTPStringRequest getGXHTTPStringRequest(String path) throws UnsupportedEncodingException { + String catalogueURL = dataCatalogue.getCatalogueUrl(); + GXHTTPStringRequest gxhttpStringRequest = GXHTTPStringRequest.newRequest(catalogueURL); + gxhttpStringRequest.from(Constants.CATALOGUE_NAME); + gxhttpStringRequest.header("Content-type", MediaType.APPLICATION_JSON); + gxhttpStringRequest.isExternalCall(true); + gxhttpStringRequest.header(AUTH_CKAN_HEADER, getApiKey()); + gxhttpStringRequest.path(path); + return gxhttpStringRequest; + } + + protected String getResultAsString(HttpURLConnection httpURLConnection) throws IOException { + int responseCode = httpURLConnection.getResponseCode(); + if(responseCode >= Status.BAD_REQUEST.getStatusCode()) { + Status status = Status.fromStatusCode(responseCode); + throw new WebApplicationException(status); + } + InputStream inputStream = httpURLConnection.getInputStream(); + String ret = getStringBuilder(inputStream).toString(); + logger.trace("Got Respose is {}", ret); + result = validateCKANResponse(ret); + if(result instanceof NullNode) { + result = mapper.createObjectNode(); + } return getAsString(result); } - public String sendPostRequest(String path, String body) { - result = sendRequest(HTTPMETHOD.POST, path, null, body); - return getAsString(result); + protected String sendGetRequest(String path, Map parameters) { + try { + GXHTTPStringRequest gxhttpStringRequest = getGXHTTPStringRequest(path); + gxhttpStringRequest.queryParams(parameters); + HttpURLConnection httpURLConnection = gxhttpStringRequest.get(); + return getResultAsString(httpURLConnection); + } catch(WebApplicationException e) { + throw e; + } catch(Exception e) { + throw new InternalServerErrorException(e); + } } - public String sendPostRequest(String path, JsonNode jsonNode) { + protected String sendPostRequest(String path, String body) { + try { + GXHTTPStringRequest gxhttpStringRequest = getGXHTTPStringRequest(path); + HttpURLConnection httpURLConnection = gxhttpStringRequest.post(body); + return getResultAsString(httpURLConnection); + } catch(WebApplicationException e) { + throw e; + } catch(Exception e) { + throw new InternalServerErrorException(e); + } + } + + protected String sendPostRequest(String path, JsonNode jsonNode) { return sendPostRequest(path, getAsString(jsonNode)); } - public String list() { - return sendGetRequest(LIST, null); + public String list(int limit, int offset) { + Map parameters = new HashMap<>(); + if(limit > 0) { + parameters.put(LIMIT_KEY, String.valueOf(limit)); + } + if(offset >= 0) { + parameters.put(OFFSET_KEY, String.valueOf(offset)); + } + return sendGetRequest(LIST, parameters); } public String create(String json) { diff --git a/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackage.java b/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackage.java index f430ad9..5397de7 100644 --- a/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackage.java +++ b/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackage.java @@ -20,7 +20,7 @@ import org.gcube.common.scope.impl.ScopeBean; import org.gcube.common.scope.impl.ScopeBean.Type; import org.gcube.gcat.annotation.PURGE; import org.gcube.gcat.oldutils.Validator; -import org.gcube.gcat.rest.Profile; +import org.gcube.gcat.profile.MetadataUtility; import org.gcube.gcat.social.SocialService; import org.gcube.gcat.utils.ContextUtility; import org.gcube.gcat.utils.URIResolver; @@ -155,9 +155,9 @@ public class CKANPackage extends CKAN { ObjectNode objectNode = checkBaseInformation(json); // Validating against profiles if any - List profiles = Profile.getProfilesNames(); - if(profiles != null && !profiles.isEmpty()) { - Validator.validateAgainstProfile(getAsString(objectNode), profiles); + MetadataUtility metadataUtility = MetadataUtility.getInstance(); + if(!metadataUtility.getMetadataProfiles().isEmpty()) { + Validator.validateAgainstProfile(getAsString(objectNode)); } return objectNode; @@ -170,8 +170,8 @@ public class CKANPackage extends CKAN { // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.get.package_list @Override - public String list() { - return super.list(); + public String list(int limit, int offset) { + return super.list(limit, offset); } protected void rollbackManagedResources() { @@ -337,7 +337,7 @@ public class CKANPackage extends CKAN { for(JsonNode jsonNode : arrayNode) { CKANResource ckanResource = new CKANResource(itemID); ckanResource.setPreviousRepresentation(jsonNode); - ckanResource.deleteFile(); + ckanResource.deleteFile(); // Only delete file is required because the item has been deleted } } super.purge(); diff --git a/src/main/java/org/gcube/gcat/persistence/ckan/CKANResource.java b/src/main/java/org/gcube/gcat/persistence/ckan/CKANResource.java index b112aef..b23d276 100644 --- a/src/main/java/org/gcube/gcat/persistence/ckan/CKANResource.java +++ b/src/main/java/org/gcube/gcat/persistence/ckan/CKANResource.java @@ -1,5 +1,6 @@ package org.gcube.gcat.persistence.ckan; +import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.UUID; @@ -14,10 +15,12 @@ import javax.ws.rs.OPTIONS; import javax.ws.rs.PUT; import javax.ws.rs.WebApplicationException; -import org.gcube.gcat.utils.ApplicationMode; +import org.apache.commons.io.FilenameUtils; +import org.gcube.common.gxhttp.request.GXHTTPStringRequest; +import org.gcube.gcat.utils.Constants; import org.gcube.gcat.utils.ContextUtility; import org.gcube.gcat.utils.HTTPCall; -import org.gcube.gcat.workspace.StorageHubManagement; +import org.gcube.gcat.workspace.CatalogueStorageHubManagement; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,7 +47,7 @@ public class CKANResource extends CKAN { /* TODO Remove this code ASAP. It requires a function from Storage HUB */ private static final String URI_RESOLVER_STORAGE_HUB_HOST_PROD = "data.d4science.org"; - private static final String URI_RESOLVER_STORAGE_HUB_HOST_DEV = "data-d.d4science.org"; + private static final String URI_RESOLVER_STORAGE_HUB_HOST_DEV = "data1-d.d4science.org"; public static final String URI_RESOLVER_STORAGE_HUB_HOST; public static final String URI_RESOLVER_STORAGE_HUB_PATH = "/shub/"; @@ -58,6 +61,7 @@ public class CKANResource extends CKAN { private static final String TEMP = "TEMP_"; + public final static String RESOURCE_NAME_REGEX = "^[\\s\\S]*$"; static { String context = ContextUtility.getCurrentContext(); @@ -78,14 +82,14 @@ public class CKANResource extends CKAN { protected String resourceID; - protected Boolean persisted; + protected boolean persisted; protected URL persistedURL; protected String mimeType; protected JsonNode previousRepresentation; - protected StorageHubManagement storageHubManagement; + protected CatalogueStorageHubManagement storageHubManagement; public URL getPersistedURL() { return persistedURL; @@ -111,6 +115,7 @@ public class CKANResource extends CKAN { } public void setPreviousRepresentation(JsonNode jsonNode) { + validate(jsonNode); previousRepresentation = jsonNode; } @@ -125,6 +130,7 @@ public class CKANResource extends CKAN { public CKANResource(String itemID) { super(); + this.nameRegex = RESOURCE_NAME_REGEX; this.itemID = itemID; CREATE = RESOURCE_CREATE; READ = RESOURCE_SHOW; @@ -132,11 +138,15 @@ public class CKANResource extends CKAN { PATCH = RESOURCE_PATCH; DELETE = RESOURCE_DELETE; PURGE = null; - persisted = null; + persisted = false; previousRepresentation = null; } @Override + public String list(int limit, int offeset) { + return list(); + } + public String list() { CKANPackage ckanPackage = new CKANPackage(); ckanPackage.setName(itemID); @@ -160,6 +170,10 @@ public class CKANResource extends CKAN { url = copyStorageResource(url); + if(name!=null) { + objectNode.put(NAME_KEY, name); + } + if(mimeType!=null) { objectNode.put(MIME_TYPE_KEY, mimeType); } @@ -219,13 +233,13 @@ public class CKANResource extends CKAN { protected URL getFinalURL(String url) { try { URL urlURL = new URL(url); - return getFinalURL(urlURL); + return CKANResource.getFinalURL(urlURL); } catch(MalformedURLException e) { throw new BadRequestException(e); } } - protected URL getFinalURL(URL url) { + public static URL getFinalURL(URL url) { HTTPCall httpCall = new HTTPCall(url.toString()); httpCall.setgCubeTargetService(false); URL finalURL = httpCall.getFinalURL(url); @@ -250,40 +264,40 @@ public class CKANResource extends CKAN { protected URL copyStorageResource(URL url) { persistedURL = getFinalURL(url); if(isStorageFile(persistedURL)) { - ApplicationMode applicationMode = new ApplicationMode(); - applicationMode.start(); - storageHubManagement = new StorageHubManagement(); - persistedURL = storageHubManagement.ensureResourcePersistence(persistedURL, itemID, resourceID, name); - mimeType = storageHubManagement.getMimeType(); - persisted = true; - applicationMode.end(); + storageHubManagement = new CatalogueStorageHubManagement(); + try { + persistedURL = storageHubManagement.ensureResourcePersistence(persistedURL, itemID, resourceID); + name = FilenameUtils.removeExtension(storageHubManagement.getOriginalFilename()); + mimeType = storageHubManagement.getMimeType(); + persisted = true; + }catch (Exception e) { + throw new InternalServerErrorException(e); + } } return persistedURL; } - protected void deleteStorageResource(URL url) { + protected void deleteStorageResource(URL url, String resourceID, String mimetype) { persistedURL = getFinalURL(url); if(isStorageFile(persistedURL)) { - ApplicationMode applicationMode = new ApplicationMode(); - applicationMode.start(); - storageHubManagement = new StorageHubManagement(); - storageHubManagement.deleteResourcePersistence(persistedURL, itemID); - applicationMode.end(); - } - } - - public boolean isPersisted() { - if(persisted == null) { - persistedURL = getFinalURL(persistedURL); - if(isStorageFile(persistedURL)) { - ApplicationMode applicationMode = new ApplicationMode(); - applicationMode.start(); - storageHubManagement = new StorageHubManagement(); - persisted = storageHubManagement.isItemPersistedFile(persistedURL, itemID); - applicationMode.end(); + try { + GXHTTPStringRequest gxhttpStringRequest = GXHTTPStringRequest.newRequest(url.toString()); + HttpURLConnection httpURLConnection = gxhttpStringRequest.from(Constants.CATALOGUE_NAME).head(); + String storageHubContentType = httpURLConnection.getContentType().split(";")[0]; + if(mimetype.compareTo(storageHubContentType)!=0) { + mimetype = storageHubContentType; + // Using storage hub mimetype + } + }catch (Exception e) { + // using provided mimetype + } + storageHubManagement = new CatalogueStorageHubManagement(); + try { + storageHubManagement.deleteResourcePersistence(itemID, resourceID, mimetype); + } catch(Exception e) { + throw new InternalServerErrorException(e); } } - return persisted; } protected String create(JsonNode jsonNode) { @@ -291,16 +305,20 @@ public class CKANResource extends CKAN { ObjectNode objectNode = validate(jsonNode); objectNode = persistStorageFile(objectNode); String ret = super.create(getAsString(objectNode)); - String gotResourceID = result.get(ID_KEY).asText(); - if(gotResourceID.compareTo(resourceID)!=0) { - resourceID = gotResourceID; - String revisionID = result.get(REVISION_ID_KEY).asText(); - storageHubManagement.renameFile(resourceID, revisionID); + if(persisted) { + String gotResourceID = result.get(ID_KEY).asText(); + if(gotResourceID!=null && gotResourceID.compareTo(resourceID)!=0) { + resourceID = gotResourceID; + String revisionID = result.get(REVISION_ID_KEY).asText(); + storageHubManagement.renameFile(resourceID, revisionID); + } } return ret; } catch(WebApplicationException e) { + // TODO Remove created file if any throw e; } catch(Exception e) { + // TODO Remove created file if any throw new InternalServerErrorException(e); } } @@ -359,6 +377,11 @@ public class CKANResource extends CKAN { throw new NotAllowedException(OPTIONS.class.getSimpleName(), moreAllowed); } + @Override + public void delete(boolean purge) { + delete(); + } + @Override public void delete() { try { @@ -392,7 +415,8 @@ public class CKANResource extends CKAN { try { getPreviousRepresentation(); URL url = new URL(previousRepresentation.get(URL_KEY).asText()); - deleteStorageResource(url); + mimeType = previousRepresentation.get(MIME_TYPE_KEY).asText(); + deleteStorageResource(url, resourceID, mimeType); } catch(Exception e) { logger.error("Unable to delete resource {}", previousRepresentation!=null ? getAsString(previousRepresentation) : ""); } diff --git a/src/main/java/org/gcube/gcat/persistence/ckan/CKANUtility.java b/src/main/java/org/gcube/gcat/persistence/ckan/CKANUtility.java index fe38a89..7f6b956 100644 --- a/src/main/java/org/gcube/gcat/persistence/ckan/CKANUtility.java +++ b/src/main/java/org/gcube/gcat/persistence/ckan/CKANUtility.java @@ -54,6 +54,7 @@ public class CKANUtility { } protected static JsonNode createCKANUser(String ckanUsername) { + ckanUsername = CKANUtility.getCKANUsername(ckanUsername); CKANUser ckanUser = new CKANUser(); ckanUser.setApiKey(getSysAdminAPI()); try { @@ -77,7 +78,7 @@ public class CKANUtility { ckanOrganization.setApiKey(getSysAdminAPI()); String organizationName = CKANOrganization.getCKANOrganizationName(); ckanOrganization.setName(organizationName); - ckanOrganization.addUserToOrganisation(ContextUtility.getUsername(), role, force); + ckanOrganization.addUserToOrganisation(ckanUsername, role, force); } public static String getApiKey() throws Exception { diff --git a/src/main/java/org/gcube/gcat/profile/MetadataUtility.java b/src/main/java/org/gcube/gcat/profile/MetadataUtility.java new file mode 100644 index 0000000..810c881 --- /dev/null +++ b/src/main/java/org/gcube/gcat/profile/MetadataUtility.java @@ -0,0 +1,107 @@ +package org.gcube.gcat.profile; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.ws.rs.InternalServerErrorException; + +import org.gcube.datacatalogue.metadatadiscovery.DataCalogueMetadataFormatReader; +import org.gcube.datacatalogue.metadatadiscovery.bean.MetadataProfile; +import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.MetadataFormat; +import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.NamespaceCategory; + +public class MetadataUtility { + + private DataCalogueMetadataFormatReader dataCalogueMetadataFormatReader; + + /* + * this map contains the Metadata Profiles. The key is the name of the profile. + */ + private Map metadataProfiles; + + private static DataCalogueMetadataFormatReader getDataCalogueMetadataFormatReaderInstance() throws Exception { + /* + Cache readerCache = CachesManager.getReaderCache(); + String context = ScopeProvider.instance.get(); + DataCalogueMetadataFormatReader reader + if(readerCache.containsKey(context)) { + reader = (DataCalogueMetadataFormatReader) readerCache.get(context); + } else { + reader = new DataCalogueMetadataFormatReader(); + readerCache.put(context, reader); + } + */ + return new DataCalogueMetadataFormatReader(); + } + + public static void clearCache() { + /* + Cache readerCache = CachesManager.getReaderCache(); + readerCache.clear(); + */ + } + + private MetadataUtility() throws Exception{ + dataCalogueMetadataFormatReader = getDataCalogueMetadataFormatReaderInstance(); + } + + private static final InheritableThreadLocal metadataUtility = new InheritableThreadLocal() { + + @Override + protected MetadataUtility initialValue() { + try { + return new MetadataUtility(); + } catch(Exception e) { + throw new InternalServerErrorException("Unable to instantiate MetadataUtility."); + } + } + + }; + + public static MetadataUtility getInstance() { + return metadataUtility.get(); + } + + + public DataCalogueMetadataFormatReader getDataCalogueMetadataFormatReader() { + return dataCalogueMetadataFormatReader; + } + + public Map getMetadataProfiles() throws Exception{ + if(metadataProfiles==null) { + metadataProfiles = new HashMap<>(); + List list = dataCalogueMetadataFormatReader.getListOfMetadataProfiles(); + for(MetadataProfile profile : list) { + metadataProfiles.put(profile.getName(), profile); + } + } + return metadataProfiles; + } + + /** + * Returns the names of the metadata profiles in a given context + * @param context + * @return + * @throws Exception + */ + public Set getProfilesNames() throws Exception { + return getMetadataProfiles().keySet(); + } + + public MetadataFormat getMetadataFormat(String profileName) throws Exception { + MetadataProfile profile = getMetadataProfiles().get(profileName); + if(profile!=null) { + return dataCalogueMetadataFormatReader.getMetadataFormatForMetadataProfile(profile); + } + return null; + } + + + public List getNamespaceCategories() throws Exception { + return dataCalogueMetadataFormatReader.getListOfNamespaceCategories(); + + } + +} diff --git a/src/main/java/org/gcube/gcat/rest/BaseREST.java b/src/main/java/org/gcube/gcat/rest/BaseREST.java index 2bad7cf..f5756b8 100644 --- a/src/main/java/org/gcube/gcat/rest/BaseREST.java +++ b/src/main/java/org/gcube/gcat/rest/BaseREST.java @@ -31,6 +31,9 @@ public class BaseREST { protected static final String LOCATION_HEADER = "Location"; + public static final String LIMIT_PARAMETER = "limit"; + public static final String OFFSET_PARAMETER = "offset"; + protected void setCalledMethod(String method) { CalledMethodProvider.instance.set(method); logger.info("{}", uriInfo.getAbsolutePath()); diff --git a/src/main/java/org/gcube/gcat/rest/Group.java b/src/main/java/org/gcube/gcat/rest/Group.java index 21c2ec4..e8f157c 100644 --- a/src/main/java/org/gcube/gcat/rest/Group.java +++ b/src/main/java/org/gcube/gcat/rest/Group.java @@ -32,8 +32,9 @@ public class Group extends REST { @GET @Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) @Override - public String list() { - return super.list(); + public String list(@QueryParam(BaseREST.LIMIT_PARAMETER) @DefaultValue("10") int limit, + @QueryParam(BaseREST.OFFSET_PARAMETER) @DefaultValue("0") int offset) { + return super.list(limit, offset); } @POST @@ -72,8 +73,6 @@ public class Group extends REST { @DELETE @Path("/{" + GROUP_ID_PARAMETER + "}") - @Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) - @Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) @Override public Response delete(@PathParam(GROUP_ID_PARAMETER) String id, @QueryParam(BaseREST.PURGE_QUERY_PARAMETER) @DefaultValue("false") Boolean purge) { @@ -82,8 +81,6 @@ public class Group extends REST { @PURGE @Path("/{" + GROUP_ID_PARAMETER + "}") - @Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) - @Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) @Override public Response purge(@PathParam(GROUP_ID_PARAMETER) String id) { return delete(id, true); diff --git a/src/main/java/org/gcube/gcat/rest/Item.java b/src/main/java/org/gcube/gcat/rest/Item.java index 7cafb16..2fa4cbb 100644 --- a/src/main/java/org/gcube/gcat/rest/Item.java +++ b/src/main/java/org/gcube/gcat/rest/Item.java @@ -31,8 +31,9 @@ public class Item extends REST { @GET @Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) @Override - public String list() { - return super.list(); + public String list(@QueryParam(BaseREST.LIMIT_PARAMETER) @DefaultValue("10") int limit, + @QueryParam(BaseREST.OFFSET_PARAMETER) @DefaultValue("0") int offset) { + return super.list(limit, offset); } @POST @@ -73,8 +74,6 @@ public class Item extends REST { @DELETE @Path("/{" + ITEM_ID_PARAMETER + "}") - @Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) - @Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) @Override public Response delete(@PathParam(ITEM_ID_PARAMETER) String id, @QueryParam(BaseREST.PURGE_QUERY_PARAMETER) @DefaultValue("false") Boolean purge) { @@ -83,8 +82,6 @@ public class Item extends REST { @PURGE @Path("/{" + ITEM_ID_PARAMETER + "}") - @Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) - @Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) @Override public Response purge(@PathParam(ITEM_ID_PARAMETER) String id) { return super.purge(id); diff --git a/src/main/java/org/gcube/gcat/rest/License.java b/src/main/java/org/gcube/gcat/rest/License.java index 6213fe6..d974db7 100644 --- a/src/main/java/org/gcube/gcat/rest/License.java +++ b/src/main/java/org/gcube/gcat/rest/License.java @@ -19,9 +19,8 @@ public class License extends REST { @GET @Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) - @Override public String list() { - return super.list(); + return super.list(-1, -1); } } diff --git a/src/main/java/org/gcube/gcat/rest/Namespace.java b/src/main/java/org/gcube/gcat/rest/Namespace.java index 82398dd..430a01d 100644 --- a/src/main/java/org/gcube/gcat/rest/Namespace.java +++ b/src/main/java/org/gcube/gcat/rest/Namespace.java @@ -7,9 +7,9 @@ import javax.ws.rs.InternalServerErrorException; import javax.ws.rs.Path; import javax.ws.rs.Produces; -import org.gcube.datacatalogue.metadatadiscovery.DataCalogueMetadataFormatReader; import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.NamespaceCategory; import org.gcube.gcat.ResourceInitializer; +import org.gcube.gcat.profile.MetadataUtility; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; @@ -21,18 +21,6 @@ import com.fasterxml.jackson.databind.node.ObjectNode; @Path(BaseREST.NAMESPACES) public class Namespace extends BaseREST { - /** - * Returns the categories. - * @param context - * @return - * @throws Exception - */ - public static List getNamespaceCategories() throws Exception { - DataCalogueMetadataFormatReader reader = Profile.getDataCalogueMetadataFormatReader(); - return reader.getListOfNamespaceCategories(); - - } - @GET @Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) public String list() { @@ -42,7 +30,7 @@ public class Namespace extends BaseREST { ArrayNode arrayNode = mapper.createArrayNode(); try { - List namespaces = Namespace.getNamespaceCategories(); + List namespaces = MetadataUtility.getInstance().getNamespaceCategories(); for(NamespaceCategory namespaceCategory : namespaces) { ObjectNode namespace = mapper.createObjectNode(); namespace.put("id", namespaceCategory.getId()); diff --git a/src/main/java/org/gcube/gcat/rest/Organization.java b/src/main/java/org/gcube/gcat/rest/Organization.java index 7ac0bf8..3e5a25d 100644 --- a/src/main/java/org/gcube/gcat/rest/Organization.java +++ b/src/main/java/org/gcube/gcat/rest/Organization.java @@ -32,8 +32,9 @@ public class Organization extends REST { @GET @Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) @Override - public String list() { - return super.list(); + public String list(@QueryParam(BaseREST.LIMIT_PARAMETER) @DefaultValue("10") int limit, + @QueryParam(BaseREST.OFFSET_PARAMETER) @DefaultValue("0") int offset) { + return super.list(limit, offset); } @POST @@ -72,8 +73,6 @@ public class Organization extends REST { @DELETE @Path("/{" + ORGANIZATION_ID_PARAMETER + "}") - @Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) - @Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) @Override public Response delete(@PathParam(ORGANIZATION_ID_PARAMETER) String id, @QueryParam(BaseREST.PURGE_QUERY_PARAMETER) @DefaultValue("false") Boolean purge) { @@ -82,8 +81,6 @@ public class Organization extends REST { @PURGE @Path("/{" + ORGANIZATION_ID_PARAMETER + "}") - @Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) - @Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) public Response purge(@PathParam(ORGANIZATION_ID_PARAMETER) String id) { return super.purge(id); } diff --git a/src/main/java/org/gcube/gcat/rest/Profile.java b/src/main/java/org/gcube/gcat/rest/Profile.java index 8b243a7..22c0513 100644 --- a/src/main/java/org/gcube/gcat/rest/Profile.java +++ b/src/main/java/org/gcube/gcat/rest/Profile.java @@ -1,100 +1,58 @@ package org.gcube.gcat.rest; -import java.util.ArrayList; +import java.io.StringWriter; import java.util.List; +import java.util.Set; -import javax.cache.Cache; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.HeaderParam; import javax.ws.rs.InternalServerErrorException; +import javax.ws.rs.NotFoundException; +import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; -import org.gcube.common.scope.api.ScopeProvider; -import org.gcube.datacatalogue.metadatadiscovery.DataCalogueMetadataFormatReader; -import org.gcube.datacatalogue.metadatadiscovery.bean.MetadataProfile; +import org.gcube.common.resources.gcore.GenericResource; +import org.gcube.common.resources.gcore.Resources; +import org.gcube.datacatalogue.metadatadiscovery.reader.MetadataFormatDiscovery; +import org.gcube.datacatalogue.metadatadiscovery.reader.QueryForResourceUtil; import org.gcube.gcat.ResourceInitializer; -import org.gcube.gcat.oldutils.CachesManager; +import org.gcube.gcat.profile.MetadataUtility; +import org.gcube.gcat.utils.Constants; +import org.gcube.informationsystem.publisher.RegistryPublisher; +import org.gcube.informationsystem.publisher.RegistryPublisherFactory; +import org.gcube.resources.discovery.client.api.DiscoveryClient; +import org.gcube.resources.discovery.client.queries.api.Query; +import org.gcube.resources.discovery.client.queries.impl.QueryBox; +import org.gcube.resources.discovery.icclient.ICFactory; import org.json.JSONObject; import org.json.XML; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; - /** * @author Luca Frosini (ISTI - CNR) */ @Path(BaseREST.PROFILES) public class Profile extends BaseREST { + private static Logger logger = LoggerFactory.getLogger(Profile.class); + public static final String PROFILE_NAME_PARAMETER = "PROFILE_NAME"; - - public static DataCalogueMetadataFormatReader getDataCalogueMetadataFormatReader() throws Exception { - Cache readerCache = CachesManager.getReaderCache(); - String context = ScopeProvider.instance.get(); - DataCalogueMetadataFormatReader reader; - if(readerCache.containsKey(context)) - reader = (DataCalogueMetadataFormatReader) readerCache.get(context); - else { - reader = new DataCalogueMetadataFormatReader(); - readerCache.put(context, reader); - } - return reader; - } - - /** - * Returns the names of the metadata profiles in a given context - * @param context - * @return - * @throws Exception - */ - public static List getProfilesNames() throws Exception { - - DataCalogueMetadataFormatReader reader = getDataCalogueMetadataFormatReader(); - - List toReturn = new ArrayList(); - List listProfiles = reader.getListOfMetadataProfiles(); - - if(listProfiles != null && !listProfiles.isEmpty()) { - for(MetadataProfile profile : listProfiles) { - toReturn.add(profile.getName()); - } - } - - return toReturn; - } - - /** - * Returns the source xml of the metadata profile (specified via name) in a given context - * @param context - * @return - * @throws Exception - */ - public static String getProfileSource(String profileName) throws Exception { - - DataCalogueMetadataFormatReader reader = Profile.getDataCalogueMetadataFormatReader(); - - List listProfiles = reader.getListOfMetadataProfiles(); - String xmlToReturn = null; - - if(listProfiles != null && !listProfiles.isEmpty()) { - for(MetadataProfile profile : listProfiles) { - if(profile.getName().equals(profileName)) { - xmlToReturn = reader.getMetadataFormatForMetadataProfile(profile).getMetadataSource(); - break; - } - } - } - - return xmlToReturn; - } @GET - @Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) + @Produces(MediaType.APPLICATION_JSON) public String list() { setCalledMethod("GET /" + BaseREST.PROFILES); @@ -102,7 +60,7 @@ public class Profile extends BaseREST { ArrayNode arrayNode = mapper.createArrayNode(); try { - List names = getProfilesNames(); + Set names = MetadataUtility.getInstance().getProfilesNames(); for(String name : names) { arrayNode.add(name); } @@ -117,21 +75,165 @@ public class Profile extends BaseREST { @GET @Path("/{" + PROFILE_NAME_PARAMETER + "}") @Produces({MediaType.APPLICATION_XML, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8}) - public String read(@PathParam(PROFILE_NAME_PARAMETER) String id, + public String read(@PathParam(PROFILE_NAME_PARAMETER) String name, @DefaultValue(MediaType.APPLICATION_JSON) @HeaderParam("Accept") String accept) { setCalledMethod("GET /" + BaseREST.PROFILES + "/{" + PROFILE_NAME_PARAMETER + "}"); try { - String profile = Profile.getProfileSource(id); - if(accept.startsWith(MediaType.APPLICATION_XML)){ - return profile; - }else { - JSONObject xmlJSONObj = XML.toJSONObject(profile); - String jsonString = xmlJSONObj.toString(PRETTY_PRINT_INDENT_FACTOR); - return jsonString; - } + String profile = MetadataUtility.getInstance().getMetadataFormat(name).getMetadataSource(); + if(profile != null) { + if(accept.startsWith(MediaType.APPLICATION_XML)) { + return profile; + } else { + JSONObject xmlJSONObj = XML.toJSONObject(profile); + String jsonString = xmlJSONObj.toString(PRETTY_PRINT_INDENT_FACTOR); + return jsonString; + } + } else { + throw new NotFoundException("Profile with name " + name + " not found"); + } + } catch(WebApplicationException e) { + throw e; } catch(Exception e) { throw new InternalServerErrorException(e.getMessage()); } } + /* + public static void appendXmlFragment(org.gcube.common.resources.gcore.GenericResource.Profile profile, String xml) throws Exception { + try { + DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Element elem = profile.newBody(); + Node fragmentNode = docBuilder.parse(new InputSource(new StringReader(xml))).getDocumentElement(); + fragmentNode = elem.getOwnerDocument().importNode(fragmentNode, true); + elem.appendChild(fragmentNode); + } catch (Exception e) { + profile.newBody(xml); + } + + } + */ + + /* + * TODO Check the Queries because the name in the Profile differs from the name in + * + * + */ + protected GenericResource instantiateGenericResource(String name, String xml) throws Exception { + GenericResource genericResource = new GenericResource(); + org.gcube.common.resources.gcore.GenericResource.Profile profile = genericResource.newProfile(); + profile.type(MetadataFormatDiscovery.DATA_CATALOGUE_METADATA_SECONDARY_TYPE); + profile.name(name); + profile.description("Profile create using " + Constants.CATALOGUE_NAME); + // appendXmlFragment(profile, xml); + profile.newBody(xml); + StringWriter stringWriter = new StringWriter(); + Resources.marshal(genericResource, stringWriter); + logger.debug("The generated {} is\n{}", GenericResource.class.getSimpleName(), stringWriter.toString()); + return genericResource; + } + + protected void createGenericResource(String name, String xml) throws Exception { + GenericResource genericResource = instantiateGenericResource(name, xml); + RegistryPublisher registryPublisher = RegistryPublisherFactory.create(); + genericResource = registryPublisher.create(genericResource); + StringWriter stringWriter = new StringWriter(); + Resources.marshal(genericResource, stringWriter); + logger.trace("The {} with ID {} has been created \n{}", GenericResource.class.getSimpleName(), + genericResource.id(), stringWriter.toString()); + } + + protected GenericResource getGenericResource(String name) { + String query = QueryForResourceUtil.getGcubeGenericQueryStringForSecondaryTypeAndName(name, + MetadataFormatDiscovery.DATA_CATALOGUE_METADATA_SECONDARY_TYPE); + Query q = new QueryBox(query); + DiscoveryClient client = ICFactory.clientFor(GenericResource.class); + List resources = client.submit(q); + + if(resources == null || resources.size() == 0) { + throw new InternalServerErrorException( + "No Resources with secondaryType '" + MetadataFormatDiscovery.DATA_CATALOGUE_METADATA_SECONDARY_TYPE + + "' and name '" + name + "' exists in the current context"); + } else { + if(resources.size() == 1) { + GenericResource genericResource = resources.get(0); + return genericResource; + } else { + throw new InternalServerErrorException("More than one Resource with secondaryType '" + + MetadataFormatDiscovery.DATA_CATALOGUE_METADATA_SECONDARY_TYPE + "' and name '" + name + + "' exists in the current context"); + } + } + } + + protected void updateGenericResource(String name, String xml) { + + GenericResource genericResource = getGenericResource(name); + logger.info("The {} with ID {} is going to be updated", GenericResource.class.getSimpleName(), + genericResource.id()); + + genericResource.profile().newBody(xml); + RegistryPublisher registryPublisher = RegistryPublisherFactory.create(); + registryPublisher.update(genericResource); + + StringWriter stringWriter = new StringWriter(); + Resources.marshal(genericResource, stringWriter); + logger.trace("The {} with ID {} has been updated to \n{}", GenericResource.class.getSimpleName(), + genericResource.id(), stringWriter.toString()); + + } + + protected void removeGenericResource(String name) { + GenericResource genericResource = getGenericResource(name); + RegistryPublisher registryPublisher = RegistryPublisherFactory.create(); + registryPublisher.remove(genericResource); + } + + @PUT + @Path("/{" + PROFILE_NAME_PARAMETER + "}") + @Consumes(MediaType.APPLICATION_XML) + @Produces(MediaType.APPLICATION_XML) + public String createOrUpdate(@PathParam(PROFILE_NAME_PARAMETER) String name, String xml) { + setCalledMethod("PUT /" + BaseREST.PROFILES + "/{" + PROFILE_NAME_PARAMETER + "}"); + try { + MetadataUtility metadataUtility = MetadataUtility.getInstance(); + metadataUtility.getDataCalogueMetadataFormatReader().validateProfile(xml); + if(metadataUtility.getMetadataFormat(name) == null) { + createGenericResource(name, xml); + } else { + updateGenericResource(name, xml); + } + return xml; + } catch(WebApplicationException e) { + throw e; + } catch(Exception e) { + throw new InternalServerErrorException(e.getMessage()); + }finally { + // TOOD Actually Cache has been removed. Remove the following code if it will not be re-introduced + // Cleaning the cache + MetadataUtility.clearCache(); + } + } + + @DELETE + @Path("/{" + PROFILE_NAME_PARAMETER + "}") + public Response delete(@PathParam(PROFILE_NAME_PARAMETER) String name) { + setCalledMethod("DELETE /" + BaseREST.PROFILES + "/{" + PROFILE_NAME_PARAMETER + "}"); + try { + MetadataUtility metadataUtility = MetadataUtility.getInstance(); + if(metadataUtility.getMetadataFormat(name) == null) { + throw new NotFoundException("Profile with name " + name + " not found"); + } else { + removeGenericResource(name); + return Response.status(Status.NO_CONTENT).build(); + } + } catch(WebApplicationException e) { + throw e; + } catch(Exception e) { + throw new InternalServerErrorException(e.getMessage()); + } finally { + // Cleaning the cache + MetadataUtility.clearCache(); + } + } + } diff --git a/src/main/java/org/gcube/gcat/rest/REST.java b/src/main/java/org/gcube/gcat/rest/REST.java index 0ef15c4..76d6f45 100644 --- a/src/main/java/org/gcube/gcat/rest/REST.java +++ b/src/main/java/org/gcube/gcat/rest/REST.java @@ -29,10 +29,10 @@ public class REST extends BaseREST { } } - public String list() { + public String list(int limit, int offset) { setCalledMethod("GET /" + COLLECTION_PARAMETER); C ckan = getInstance(); - return ckan.list(); + return ckan.list(limit, offset); } public Response create(String json) { diff --git a/src/main/java/org/gcube/gcat/rest/Resource.java b/src/main/java/org/gcube/gcat/rest/Resource.java index 9351947..b2feb69 100644 --- a/src/main/java/org/gcube/gcat/rest/Resource.java +++ b/src/main/java/org/gcube/gcat/rest/Resource.java @@ -79,8 +79,6 @@ public class Resource extends BaseREST { @DELETE @Path("/{" + RESOURCE_ID_PARAMETER + "}") - @Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) - @Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) public void delete(@PathParam(ITEM_ID_PARAMETER) String itemID, @PathParam(RESOURCE_ID_PARAMETER) String resourceID) { setCalledMethod("DELETE /" + COLLECTION + "/{" + RESOURCE_ID_PARAMETER + "}"); diff --git a/src/main/java/org/gcube/gcat/rest/User.java b/src/main/java/org/gcube/gcat/rest/User.java index 3c52a8e..2782d1d 100644 --- a/src/main/java/org/gcube/gcat/rest/User.java +++ b/src/main/java/org/gcube/gcat/rest/User.java @@ -25,12 +25,10 @@ public class User extends REST { super(BaseREST.USERS, USER_ID_PARAMETER, CKANUser.class); } - @GET @Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) - @Override public String list() { - return super.list(); + return super.list(-1,-1); } @POST @@ -60,8 +58,6 @@ public class User extends REST { @DELETE @Path("/{" + USER_ID_PARAMETER + "}") - @Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) - @Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) public Response delete(@PathParam(USER_ID_PARAMETER) String id) { return super.delete(id, false); } diff --git a/src/main/java/org/gcube/gcat/social/SocialService.java b/src/main/java/org/gcube/gcat/social/SocialService.java index 5343ad8..a66c13f 100644 --- a/src/main/java/org/gcube/gcat/social/SocialService.java +++ b/src/main/java/org/gcube/gcat/social/SocialService.java @@ -1,20 +1,19 @@ package org.gcube.gcat.social; import java.io.StringWriter; +import java.net.HttpURLConnection; import java.util.ArrayList; import java.util.List; -import java.util.Map; import javax.cache.Cache; import javax.ws.rs.core.MediaType; +import org.gcube.common.gxhttp.request.GXHTTPStringRequest; import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogue; import org.gcube.gcat.oldutils.CachesManager; import org.gcube.gcat.persistence.ckan.CKAN; -import org.gcube.gcat.utils.ApplicationMode; +import org.gcube.gcat.utils.Constants; import org.gcube.gcat.utils.ContextUtility; -import org.gcube.gcat.utils.HTTPCall; -import org.gcube.gcat.utils.HTTPCall.HTTPMETHOD; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -101,10 +100,15 @@ public class SocialService extends Thread { return userCache.get(username); else { String socialServiceBasePath = socialService.getServiceBasePath(); - HTTPCall httpCall = new HTTPCall(socialServiceBasePath); - String response = httpCall.call(SOCIAL_SERVICE_GET_USER_INFO_PATH, HTTPMETHOD.GET, (Map) null, - MediaType.APPLICATION_JSON); - JsonNode jsonNode = objectMapper.readTree(response); + + GXHTTPStringRequest gxhttpStringRequest = GXHTTPStringRequest.newRequest(socialServiceBasePath); + gxhttpStringRequest.header("User-Agent", Constants.CATALOGUE_NAME); + gxhttpStringRequest.header("Accept", MediaType.APPLICATION_JSON); + gxhttpStringRequest.path(SOCIAL_SERVICE_GET_USER_INFO_PATH); + HttpURLConnection httpURLConnection = gxhttpStringRequest.get(); + + String message = httpURLConnection.getResponseMessage(); + JsonNode jsonNode = objectMapper.readTree(message); userCache.put(username, jsonNode); return jsonNode; } @@ -175,14 +179,17 @@ public class SocialService extends Thread { // Do not use ApplicationMode class here because is a thread and change the current token could impact // on the other threads. - HTTPCall httpCall = new HTTPCall(basePath); - httpCall.setgCubeTargetService(false); - httpCall.addHeader(org.gcube.common.authorization.client.Constants.TOKEN_HEADER_ENTRY, - ApplicationMode.getCatalogueApplicationToken()); - String response = httpCall.call(SOCIAL_SERVICE_WRITE_APPLICATION_POST_PATH, HTTPMETHOD.POST, - objectMapper.writeValueAsString(objectNode), MediaType.APPLICATION_JSON); - JsonNode jsonNode = objectMapper.readTree(response); + + GXHTTPStringRequest gxhttpStringRequest = GXHTTPStringRequest.newRequest(basePath); + gxhttpStringRequest.header("User-Agent", Constants.CATALOGUE_NAME); + gxhttpStringRequest.setSecurityToken(Constants.getCatalogueApplicationToken()); + gxhttpStringRequest.path(SOCIAL_SERVICE_WRITE_APPLICATION_POST_PATH); + + + HttpURLConnection httpURLConnection = gxhttpStringRequest.post(objectMapper.writeValueAsString(objectNode)); + String ret = httpURLConnection.getResponseMessage(); + JsonNode jsonNode = objectMapper.readTree(ret); if(jsonNode.get(SOCIAL_POST_RESPONSE_SUCCESS_KEY).asBoolean()) { logger.info("Post written : {}", message); } else { diff --git a/src/main/java/org/gcube/gcat/utils/ApplicationMode.java b/src/main/java/org/gcube/gcat/utils/ApplicationMode.java deleted file mode 100644 index dfbcfe1..0000000 --- a/src/main/java/org/gcube/gcat/utils/ApplicationMode.java +++ /dev/null @@ -1,92 +0,0 @@ -package org.gcube.gcat.utils; - -import java.io.InputStream; -import java.util.Properties; - -import javax.ws.rs.WebApplicationException; - -import org.gcube.common.authorization.client.Constants; -import org.gcube.common.authorization.library.AuthorizationEntry; -import org.gcube.common.authorization.library.provider.AuthorizationProvider; -import org.gcube.common.authorization.library.provider.ClientInfo; -import org.gcube.common.authorization.library.provider.SecurityTokenProvider; -import org.gcube.common.authorization.library.utils.Caller; -import org.gcube.common.scope.api.ScopeProvider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * @author Luca Frosini (ISTI - CNR) - */ -public class ApplicationMode { - - private static final Logger logger = LoggerFactory.getLogger(ApplicationMode.class); - - private static final String PROPERTY_FILENAME = "config.properties"; - private static final String TOKEN_VARNAME = "TOKEN"; - private static final String CATALOGUE_APPLICATION_TOKEN; - - public static String getCatalogueApplicationToken() { - return CATALOGUE_APPLICATION_TOKEN; - } - - static { - try { - Properties properties = new Properties(); - InputStream input = Constants.class.getClassLoader().getResourceAsStream(PROPERTY_FILENAME); - // load a properties file - properties.load(input); - CATALOGUE_APPLICATION_TOKEN = properties.getProperty(TOKEN_VARNAME); - }catch (Exception e) { - throw new WebApplicationException(e); - } - } - - - - private final String originalToken; - - public ApplicationMode() { - String applicationtoken = SecurityTokenProvider.instance.get(); - if(applicationtoken.compareTo(CATALOGUE_APPLICATION_TOKEN)!=0) { - this.originalToken = applicationtoken; - }else { - logger.warn("You are already in application Mode. Operation on this instance will not have any effect."); - this.originalToken = null; - } - } - - public static void setToken(String token) { - SecurityTokenProvider.instance.set(token); - ScopeProvider.instance.set(ContextUtility.getCurrentContext()); - try { - AuthorizationEntry authorizationEntry = Constants.authorizationService().get(token); - ClientInfo clientInfo = authorizationEntry.getClientInfo(); - logger.debug("User : {} - Type : {}", clientInfo.getId(), clientInfo.getType().name()); - String qualifier = authorizationEntry.getQualifier(); - Caller caller = new Caller(clientInfo, qualifier); - AuthorizationProvider.instance.set(caller); - }catch (Exception e) { - logger.error("Unable to set Caller"); - } - - } - - - public synchronized void start() { - if(originalToken!=null) { - setToken(CATALOGUE_APPLICATION_TOKEN); - }else { - logger.warn("You are already in application Mode. start() does not provide any effect."); - } - } - - public synchronized void end() { - if(originalToken!=null) { - setToken(originalToken); - }else { - logger.warn("You are already in application Mode. end() does not provide any effect."); - } - } - -} diff --git a/src/main/java/org/gcube/gcat/utils/Constants.java b/src/main/java/org/gcube/gcat/utils/Constants.java index a45f7ff..73f7c2c 100644 --- a/src/main/java/org/gcube/gcat/utils/Constants.java +++ b/src/main/java/org/gcube/gcat/utils/Constants.java @@ -1,10 +1,35 @@ package org.gcube.gcat.utils; +import java.io.InputStream; +import java.util.Properties; + +import javax.ws.rs.WebApplicationException; + /** * @author Luca Frosini (ISTI - CNR) */ public class Constants { - public static final String CATALOGUE_NAME = "ScienceCatalogue"; + public static final String CATALOGUE_NAME = "gCat"; + + private static final String PROPERTY_FILENAME = "config.properties"; + private static final String TOKEN_VARNAME = "TOKEN"; + private static final String CATALOGUE_APPLICATION_TOKEN; + + public static String getCatalogueApplicationToken() { + return CATALOGUE_APPLICATION_TOKEN; + } + + static { + try { + Properties properties = new Properties(); + InputStream input = Constants.class.getClassLoader().getResourceAsStream(PROPERTY_FILENAME); + // load a properties file + properties.load(input); + CATALOGUE_APPLICATION_TOKEN = properties.getProperty(TOKEN_VARNAME); + }catch (Exception e) { + throw new WebApplicationException(e); + } + } } diff --git a/src/main/java/org/gcube/gcat/utils/HTTPCall.java b/src/main/java/org/gcube/gcat/utils/HTTPCall.java index 71fa716..31da9cd 100644 --- a/src/main/java/org/gcube/gcat/utils/HTTPCall.java +++ b/src/main/java/org/gcube/gcat/utils/HTTPCall.java @@ -1,61 +1,26 @@ package org.gcube.gcat.utils; -import java.io.BufferedReader; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.StringWriter; -import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; -import java.net.URLEncoder; -import java.util.HashMap; -import java.util.Map; import javax.ws.rs.InternalServerErrorException; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response.Status; -import org.gcube.common.authorization.library.provider.SecurityTokenProvider; -import org.gcube.common.scope.api.ScopeProvider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class HTTPCall { - private static final Logger logger = LoggerFactory.getLogger(HTTPCall.class); - protected static final String USER_AGENT_KEY = "User-Agent"; - protected static final String USER_AGENT_NAME = Constants.CATALOGUE_NAME; - - public enum HTTPMETHOD { - HEAD, GET, POST, PUT, DELETE; - - @Override - public String toString() { - return this.name(); - } - } - - public static final String PATH_SEPARATOR = "/"; - public static final String PARAM_STARTER = "?"; - public static final String PARAM_EQUALS = "="; - public static final String PARAM_SEPARATOR = "&"; - public static final String UTF8 = "UTF-8"; + protected static final String USER_AGENT_NAME = "gCat"; protected final String address; - protected final String userAgent; - - protected Map headers; /** * When the target service is a gCube Service it adds the HTTP header * to provide gCube authorization token and/or scope */ protected boolean gCubeTargetService; - + public boolean isgCubeTargetService() { return gCubeTargetService; } @@ -70,63 +35,7 @@ public class HTTPCall { protected HTTPCall(String address, String userAgent) { this.address = address; - this.userAgent = userAgent; this.gCubeTargetService = true; - this.headers = new HashMap<>(); - addHeader(USER_AGENT_KEY, this.userAgent); - } - - public void addHeader(String key, String value) { - headers.put(key, value); - } - - protected String getParametersDataString(Map parameters) throws UnsupportedEncodingException { - - if(parameters == null) { - return null; - } - - StringBuilder result = new StringBuilder(); - boolean first = true; - for(String key : parameters.keySet()) { - if(first) { - first = false; - } else { - result.append(PARAM_SEPARATOR); - } - - result.append(URLEncoder.encode(key, UTF8)); - result.append(PARAM_EQUALS); - result.append(URLEncoder.encode(parameters.get(key), UTF8)); - - } - - return result.toString(); - } - - protected URL getURL(String address, String path, String urlParameters) throws MalformedURLException { - - StringWriter stringWriter = new StringWriter(); - stringWriter.append(address); - - if(address.endsWith(PATH_SEPARATOR)) { - if(path.startsWith(PATH_SEPARATOR)) { - path = path.substring(1); - } - } else { - if(path.compareTo("") != 0 && !path.startsWith(PATH_SEPARATOR)) { - stringWriter.append(PATH_SEPARATOR); - } - } - - stringWriter.append(path); - - if(urlParameters != null) { - stringWriter.append(PARAM_STARTER); - stringWriter.append(urlParameters); - } - - return getURL(stringWriter.toString()); } protected URL getURL(String urlString) throws MalformedURLException { @@ -137,27 +46,23 @@ public class HTTPCall { return url; } - protected HttpURLConnection getConnection(String path, String urlParameters, HTTPMETHOD method, String body, - InputStream inputStream, String contentType) throws Exception { - URL url = getURL(address, path, urlParameters); - return getConnection(url, method, body, inputStream, contentType); - } - public URL getFinalURL(URL url) { try { URL finalURL = url; HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setInstanceFollowRedirects(false); + connection.setRequestProperty(USER_AGENT_KEY, USER_AGENT_NAME); + // connection.setRequestMethod(HEAD.class.getSimpleName()); int responseCode = connection.getResponseCode(); - String responseMessage = connection.getResponseMessage(); if(responseCode >= Status.BAD_REQUEST.getStatusCode()) { Status status = Status.fromStatusCode(responseCode); + String responseMessage = connection.getResponseMessage(); throw new WebApplicationException(responseMessage, status); } - + if(responseCode == HttpURLConnection.HTTP_MOVED_TEMP || responseCode == HttpURLConnection.HTTP_MOVED_PERM || responseCode == HttpURLConnection.HTTP_SEE_OTHER || responseCode == Status.TEMPORARY_REDIRECT.getStatusCode() || responseCode == 308) { @@ -168,140 +73,6 @@ public class HTTPCall { return finalURL; - }catch (WebApplicationException e) { - throw e; - }catch (Exception e) { - throw new InternalServerErrorException(e); - } - - } - - - protected HttpURLConnection getConnection(URL url, HTTPMETHOD method, String body, InputStream inputStream, - String contentType) throws Exception { - - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - - if(gCubeTargetService) { - if(SecurityTokenProvider.instance.get() == null) { - if(ScopeProvider.instance.get() == null) { - throw new RuntimeException("Null Token and Scope. Please set your token first."); - } - connection.setRequestProperty("gcube-scope", ScopeProvider.instance.get()); - } else { - connection.setRequestProperty(org.gcube.common.authorization.client.Constants.TOKEN_HEADER_ENTRY, - SecurityTokenProvider.instance.get()); - } - } - - connection.setDoOutput(true); - - connection.setRequestProperty("Content-type", contentType); - for(String key : headers.keySet()) { - connection.setRequestProperty(key, headers.get(key)); - } - - connection.setRequestMethod(method.toString()); - - if(inputStream != null && (method == HTTPMETHOD.POST || method == HTTPMETHOD.PUT)) { - - DataOutputStream wr = new DataOutputStream(connection.getOutputStream()); - byte[] buffer = new byte[1024]; - - int len; - while((len = inputStream.read(buffer)) > 0) { - wr.write(buffer, 0, len); - } - wr.flush(); - wr.close(); - } - - if(body != null && (method == HTTPMETHOD.POST || method == HTTPMETHOD.PUT)) { - - DataOutputStream wr = new DataOutputStream(connection.getOutputStream()); - wr.writeBytes(body); - wr.flush(); - wr.close(); - } - - int responseCode = connection.getResponseCode(); - String responseMessage = connection.getResponseMessage(); - logger.trace("{} {} : {} - {}", method, connection.getURL(), responseCode, responseMessage); - - // 308 Permanent Redirect https://tools.ietf.org/html/rfc7538#section-3 - if(responseCode == HttpURLConnection.HTTP_MOVED_TEMP || responseCode == HttpURLConnection.HTTP_MOVED_PERM - || responseCode == HttpURLConnection.HTTP_SEE_OTHER - || responseCode == Status.TEMPORARY_REDIRECT.getStatusCode() || responseCode == 308) { - - URL redirectURL = getURL(connection.getHeaderField("Location")); - - logger.trace("{} is going to be redirect to {}", url.toString(), redirectURL.toString()); - - connection = getConnection(redirectURL, method, body, inputStream, contentType); - } - - return connection; - - } - - protected StringBuilder getStringBuilder(InputStream inputStream) throws IOException { - StringBuilder result = new StringBuilder(); - try(BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { - String line; - while((line = reader.readLine()) != null) { - result.append(line); - } - } - - return result; - } - - public String call(String path, HTTPMETHOD method, Map parameters, String contentType) { - return call(path, method, parameters, null, contentType); - } - - public String call(String path, HTTPMETHOD method, String body, String contentType) { - return call(path, method, null, body, contentType); - } - - public String call(String path, HTTPMETHOD method, Map parameters, String body, String contentType) { - return call(path, method, body, null, parameters, contentType); - } - - public String call(String path, HTTPMETHOD method, InputStream inputStream, Map parameters, - String contentType) { - return call(path, method, null, inputStream, parameters, contentType); - } - - private String call(String path, HTTPMETHOD method, String body, InputStream inputStream, - Map parameters, String contentType) { - HttpURLConnection connection; - try { - String urlParameters = getParametersDataString(parameters); - connection = getConnection(path, urlParameters, method, body, inputStream, contentType); - int responseCode = connection.getResponseCode(); - String responseMessage = connection.getResponseMessage(); - logger.info("{} {} : {} - {}", method, connection.getURL(), responseCode, responseMessage); - - if(responseCode >= Status.BAD_REQUEST.getStatusCode()) { - try { - StringBuilder result = getStringBuilder(connection.getErrorStream()); - String res = result.toString(); - logger.trace("Server returned content : {}", res); - return res; - }catch (Exception e) { - Status status = Status.fromStatusCode(responseCode); - throw new WebApplicationException(responseMessage, status); - } - } - StringBuilder result = getStringBuilder(connection.getInputStream()); - String res = result.toString(); - logger.trace("Server returned content : {}", res); - - connection.disconnect(); - - return res; - } catch(WebApplicationException e) { throw e; } catch(Exception e) { diff --git a/src/main/java/org/gcube/gcat/utils/URIResolver.java b/src/main/java/org/gcube/gcat/utils/URIResolver.java index 7d7377b..bad211f 100644 --- a/src/main/java/org/gcube/gcat/utils/URIResolver.java +++ b/src/main/java/org/gcube/gcat/utils/URIResolver.java @@ -1,12 +1,13 @@ package org.gcube.gcat.utils; -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.MediaType; +import java.net.HttpURLConnection; +import javax.ws.rs.WebApplicationException; + +import org.gcube.common.gxhttp.request.GXHTTPStringRequest; import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogue; import org.gcube.datacatalogue.ckanutillibrary.server.utils.url.EntityContext; import org.gcube.gcat.persistence.ckan.CKAN; -import org.gcube.gcat.utils.HTTPCall.HTTPMETHOD; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -29,18 +30,20 @@ public class URIResolver { DataCatalogue dataCatalogue = CKAN.getCatalogue(); String uriResolverURL = dataCatalogue.getUriResolverUrl(); - HTTPCall httpCall = new HTTPCall(uriResolverURL); - ObjectNode requestContent = objectMapper.createObjectNode(); requestContent.put(CATALOGUE_CONTEXT, ContextUtility.getCurrentContext()); requestContent.put(ENTITY_TYPE, EntityContext.PRODUCT.toString()); requestContent.put(ENTITY_NAME, name); requestContent.put(CATALOGUE_PLAIN_URL, true); - String url = httpCall.call("", HTTPMETHOD.POST, objectMapper.writeValueAsString(requestContent), - MediaType.APPLICATION_JSON); + GXHTTPStringRequest gxhttpStringRequest = GXHTTPStringRequest.newRequest(uriResolverURL); + gxhttpStringRequest.header("User-Agent", Constants.CATALOGUE_NAME); + HttpURLConnection httpURLConnection = gxhttpStringRequest.post(objectMapper.writeValueAsString(requestContent)); + + String url = httpURLConnection.getResponseMessage(); return url; + } catch(Exception e) { throw new WebApplicationException(e); } diff --git a/src/main/java/org/gcube/gcat/workspace/CatalogueMetadata.java b/src/main/java/org/gcube/gcat/workspace/CatalogueMetadata.java new file mode 100644 index 0000000..630860e --- /dev/null +++ b/src/main/java/org/gcube/gcat/workspace/CatalogueMetadata.java @@ -0,0 +1,44 @@ +package org.gcube.gcat.workspace; + +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +import org.gcube.common.storagehub.model.Metadata; +import org.gcube.storagehub.MetadataMatcher; + +public class CatalogueMetadata implements MetadataMatcher { + + public static final String ORIGINAL_URL = "OriginalURL"; + public static final String ORIGINAL_NAME = "OriginalName"; + + public static final String CATALOGUE_ITEM_ID = "CatalogueItemID"; + public static final String CATALOGUE_RESOURCE_ID = "CatalogueResourceID"; + public static final String CATALOGUE_RESOURCE_REVISION_ID = "CatalogueResourceRevisionID"; + + protected String itemID; + + public CatalogueMetadata(String itemID) { + this.itemID = itemID; + } + + @Override + public boolean check(Metadata metadata) { + Map map = metadata.getMap(); + if(map.get(CATALOGUE_ITEM_ID).toString().compareTo(itemID) == 0) { + return true; + } + return false; + } + + public Metadata getMetadata(URL url, String originalName, String resourceID) { + Map map = new HashMap<>(); + map.put(ORIGINAL_URL, url.toString()); + map.put(ORIGINAL_NAME, originalName); + map.put(CATALOGUE_ITEM_ID, itemID); + map.put(CATALOGUE_RESOURCE_ID, resourceID); + Metadata metadata = new Metadata(map); + return metadata; + } + +} diff --git a/src/main/java/org/gcube/gcat/workspace/CatalogueStorageHubManagement.java b/src/main/java/org/gcube/gcat/workspace/CatalogueStorageHubManagement.java new file mode 100644 index 0000000..b448d74 --- /dev/null +++ b/src/main/java/org/gcube/gcat/workspace/CatalogueStorageHubManagement.java @@ -0,0 +1,109 @@ +package org.gcube.gcat.workspace; + +import java.net.HttpURLConnection; +import java.net.URL; +import java.text.ParseException; +import java.util.Map; + +import org.gcube.common.gxhttp.request.GXHTTPStringRequest; +import org.gcube.common.storagehub.client.dsl.FileContainer; +import org.gcube.common.storagehub.model.Metadata; +import org.gcube.gcat.utils.Constants; +import org.gcube.storagehub.ApplicationMode; +import org.gcube.storagehub.StorageHubManagement; +import org.glassfish.jersey.media.multipart.ContentDisposition; + +public class CatalogueStorageHubManagement { + + protected StorageHubManagement storageHubManagement; + + protected String originalFilename; + protected String mimeType; + + public String getOriginalFilename() { + return originalFilename; + } + + public String getMimeType() { + return mimeType; + } + + public CatalogueStorageHubManagement() { + this.storageHubManagement = new StorageHubManagement(); + } + + protected String getOriginalFileName(HttpURLConnection httpURLConnection) throws ParseException { + String contentDisposition = httpURLConnection.getHeaderFields().get("Content-Disposition").get(0); + contentDisposition = contentDisposition.replaceAll("= ", "=").replaceAll(" =", "="); + ContentDisposition formDataContentDisposition = new ContentDisposition(contentDisposition); + return formDataContentDisposition.getFileName(); + } + + public URL ensureResourcePersistence(URL persistedURL, String itemID, String resourceID) throws Exception { + ApplicationMode applicationMode = new ApplicationMode(Constants.getCatalogueApplicationToken()); + try { + applicationMode.start(); + GXHTTPStringRequest gxhttpStringRequest = GXHTTPStringRequest.newRequest(persistedURL.toString()); + gxhttpStringRequest.isExternalCall(true); + HttpURLConnection httpURLConnection = gxhttpStringRequest.get(); + mimeType = httpURLConnection.getContentType().split(";")[0]; + originalFilename = getOriginalFileName(httpURLConnection); + CatalogueMetadata catalogueMetadata = new CatalogueMetadata(itemID); + storageHubManagement.setCheckMetadata(catalogueMetadata); + Metadata metadata = catalogueMetadata.getMetadata(persistedURL, originalFilename, resourceID); + persistedURL = storageHubManagement.persistFile(httpURLConnection.getInputStream(), resourceID, mimeType, metadata); + mimeType = storageHubManagement.getMimeType(); + return persistedURL; + } finally { + applicationMode.end(); + } + } + + public void deleteResourcePersistence(String itemID, String resourceID, String mimeType) throws Exception { + ApplicationMode applicationMode = new ApplicationMode(Constants.getCatalogueApplicationToken()); + try { + applicationMode.start(); + storageHubManagement = new StorageHubManagement(); + CatalogueMetadata catalogueMetadata = new CatalogueMetadata(itemID); + storageHubManagement.setCheckMetadata(catalogueMetadata); + storageHubManagement.removePersistedFile(resourceID, mimeType); + } finally { + applicationMode.end(); + } + } + + + protected void internalAddRevisionID(String resourceID, String revisionID) { + FileContainer fileContainer = storageHubManagement.getCreatedFile(); + Metadata metadata = fileContainer.get().getMetadata(); + Map map = metadata.getMap(); + map.put(CatalogueMetadata.CATALOGUE_RESOURCE_ID, resourceID); + map.put(CatalogueMetadata.CATALOGUE_RESOURCE_REVISION_ID, revisionID); + metadata.setMap(map); + fileContainer.setMetadata(metadata); + } + + public void renameFile(String resourceID, String revisionID) { + ApplicationMode applicationMode = new ApplicationMode(Constants.getCatalogueApplicationToken()); + try { + applicationMode.start(); + FileContainer createdfile = storageHubManagement.getCreatedFile(); + createdfile.rename(resourceID); + internalAddRevisionID(resourceID, revisionID); + }finally { + applicationMode.end(); + } + + } + + public void addRevisionID(String resourceID, String revisionID) { + ApplicationMode applicationMode = new ApplicationMode(Constants.getCatalogueApplicationToken()); + try { + applicationMode.start(); + internalAddRevisionID(resourceID, revisionID); + }finally { + applicationMode.end(); + } + } + +} diff --git a/src/main/java/org/gcube/gcat/workspace/StorageHubManagement.java b/src/main/java/org/gcube/gcat/workspace/StorageHubManagement.java deleted file mode 100644 index 5cff1a2..0000000 --- a/src/main/java/org/gcube/gcat/workspace/StorageHubManagement.java +++ /dev/null @@ -1,295 +0,0 @@ -package org.gcube.gcat.workspace; - -import java.io.StringWriter; -import java.net.URL; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.ws.rs.InternalServerErrorException; - -import org.gcube.common.homelibrary.home.Home; -import org.gcube.common.homelibrary.home.HomeLibrary; -import org.gcube.common.homelibrary.home.HomeManager; -import org.gcube.common.homelibrary.home.HomeManagerFactory; -import org.gcube.common.homelibrary.home.User; -import org.gcube.common.homelibrary.home.workspace.Workspace; -import org.gcube.common.storagehub.client.StreamDescriptor; -import org.gcube.common.storagehub.client.dsl.ContainerType; -import org.gcube.common.storagehub.client.dsl.FileContainer; -import org.gcube.common.storagehub.client.dsl.FolderContainer; -import org.gcube.common.storagehub.client.dsl.ItemContainer; -import org.gcube.common.storagehub.client.dsl.ListResolver; -import org.gcube.common.storagehub.client.dsl.ListResolverTyped; -import org.gcube.common.storagehub.client.dsl.OpenResolver; -import org.gcube.common.storagehub.client.dsl.StorageHubClient; -import org.gcube.common.storagehub.model.Metadata; -import org.gcube.common.storagehub.model.items.AbstractFileItem; -import org.gcube.common.storagehub.model.items.Item; -import org.gcube.gcat.utils.Constants; -import org.gcube.gcat.utils.ContextUtility; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class StorageHubManagement { - - private static final Logger logger = LoggerFactory.getLogger(StorageHubManagement.class); - - public static final String ORIGINAL_URL = "OriginalURL"; - public static final String ORIGINAL_NAME = "OriginalName"; - - public static final String CATALOGUE_ITEM_ID = "CatalogueItemID"; - public static final String CATALOGUE_RESOURCE_ID = "CatalogueResourceID"; - public static final String CATALOGUE_RESOURCE_REVISION_ID = "CatalogueResourceRevisionID"; - - public static final String CATALOGUE_FOLDER_DESCRIPTION = "Catalogue Folder used to persist Resources"; - - protected final StorageHubClient storageHubClient; - - protected FileContainer createdFile; - protected String mimeType; - - public String getMimeType() { - return mimeType; - } - - public StorageHubManagement() { - storageHubClient = new StorageHubClient(); - } - - protected void recursiveList(FolderContainer folder, int level) { - ListResolverTyped listResolverTyped = folder.list(); - List> containers = listResolverTyped.getContainers(); - for(ItemContainer itemContainer : containers) { - Item item = itemContainer.get(); - String name = item.getName(); - ContainerType containerType = itemContainer.getType(); - StringWriter indent = new StringWriter(level + 1); - for(int i = 0; i < level + 1; i++) { - indent.append('-'); - } - logger.debug("{} {} {} (ID:{})", indent.toString(), containerType, name, itemContainer.getId()); - switch(containerType) { - case FOLDER: - FolderContainer folderContainer = (FolderContainer) itemContainer; - //if(item.getName().compareTo("553095a0-a14a-4e41-b014-2e6f3a1aeac7")!=0) - recursiveList(folderContainer, level + 1); - break; - - case FILE: - break; - - case GENERIC_ITEM: - break; - - default: - break; - } - } - } - - protected FolderContainer getWorkspaceRoot() { - try { - return storageHubClient.getWSRoot(); - }catch (Exception e) { - String username = ContextUtility.getUsername(); - logger.info("Unable to obtain the Workspace Root for {}. Going to create it.", username); - try { - HomeManagerFactory factory = HomeLibrary.getHomeManagerFactory(); - HomeManager manager = factory.getHomeManager(); - User user = manager.createUser(username); - @SuppressWarnings("deprecation") - Home home = manager.getHome(user); - Workspace ws = home.getWorkspace(); - ws.getRoot(); - return storageHubClient.getWSRoot(); - }catch (Exception ex) { - logger.info("Unable to create the Workspace Root for {}.", username); - throw new InternalServerErrorException(e); - } - } - } - - - protected FolderContainer getOrCreateFolder(FolderContainer parent, String name, String description) { - try { - FolderContainer destinationFolder = null; - ListResolverTyped listResolverTyped = parent.list(); - List> containers = listResolverTyped.getContainers(); - for(ItemContainer itemContainer : containers) { - if(itemContainer instanceof FolderContainer) { - if(itemContainer.get().getName().compareTo(name) == 0) { - destinationFolder = (FolderContainer) itemContainer; - } - } - } - if(destinationFolder == null) { - destinationFolder = parent.newFolder(name, description); - } - return destinationFolder; - } catch(Exception e) { - throw new InternalServerErrorException(e); - } - } - - public static String getFolderName() { - String currentContext = ContextUtility.getCurrentContext(); - String folderName = currentContext.replaceFirst("/", "").replace("/", "_"); - return folderName; - } - - protected FolderContainer getCatalogueFolder() { - FolderContainer destinationFolder = getWorkspaceRoot(); - String folderName = getFolderName(); - destinationFolder = getOrCreateFolder(destinationFolder, folderName, ContextUtility.getCurrentContext() + " folder"); - destinationFolder = getOrCreateFolder(destinationFolder, Constants.CATALOGUE_NAME, CATALOGUE_FOLDER_DESCRIPTION); - return destinationFolder; - } - - protected FolderContainer getDestinationFolder(AbstractFileItem item) { - FolderContainer destinationFolder = getCatalogueFolder(); - mimeType = item.getContent().getMimeType(); - String[] splittedMimeType = mimeType.split("/"); - for(String name : splittedMimeType) { - try { - destinationFolder = getOrCreateFolder(destinationFolder, name, - "Automatic Folder Created using mimetype"); - } catch(Exception e) { - throw new InternalServerErrorException(e); - } - } - return destinationFolder; - } - - protected FileContainer copyFile(FileContainer sourceFileContainer, FolderContainer destinationFolder, - String copiedFilename) { - StreamDescriptor streamDescriptor = sourceFileContainer.download(""); - FileContainer createdFile = destinationFolder.uploadFile(streamDescriptor.getStream(), copiedFilename, - sourceFileContainer.get().getDescription()); - /* - FileContainer copiedFile = sourceFileContainer.copy(destinationFolder, copiedFilename); - */ - return createdFile; - } - - protected ItemContainer getContainerByStorageURL(URL url) { - URL finalURL = url; - String path = finalURL.getPath(); - String fileID = path.substring(path.lastIndexOf('/') + 1); - - OpenResolver openResolver = storageHubClient.open(fileID); - ItemContainer itemContainer = openResolver.asItem(); - Item item = itemContainer.get(); - if(item instanceof AbstractFileItem) { - logger.debug("The resource with ID {} is a file", fileID); - return openResolver.asFile(); - } - return itemContainer; - } - - protected boolean isItemPersistedFile(FileContainer fileContainer, FolderContainer destinationFolder, String itemID) { - // Checking if the file is already a file of the science catalogue folder of the scope related to such an item. - ListResolver listResolver = fileContainer.getAnchestors(); - List> itemContainers = listResolver.getContainers(); - for(ItemContainer itemContainer : itemContainers) { - if(itemContainer.getId().compareTo(destinationFolder.getId()) == 0) { - Metadata metadata = fileContainer.get().getPropertyMap(); - Map map = metadata.getValues(); - if(map.get(CATALOGUE_ITEM_ID).toString().compareTo(itemID) == 0) { - return true; - } - } - } - return false; - } - - public boolean isItemPersistedFile(URL url, String itemID) { - ItemContainer itemContainer = getContainerByStorageURL(url); - FileContainer fileContainer; - if(itemContainer instanceof FileContainer) { - fileContainer = (FileContainer) itemContainer; - }else { - return false; - } - FolderContainer destinationFolder = getDestinationFolder(fileContainer.get()); - return isItemPersistedFile(fileContainer, destinationFolder, itemID); - } - - protected void tree(FolderContainer folderContainer) throws Exception { - logger.debug("{} (ID:{})", folderContainer.get().getName(), folderContainer.getId()); - recursiveList(folderContainer, 0); - } - - protected FileContainer getFileByID(String id) throws Exception { - OpenResolver openResolver = storageHubClient.open(id); - FileContainer fileContainer = (FileContainer) openResolver.asFile(); - return fileContainer; - } - - protected void deleteFileByID(String id) throws Exception { - FileContainer fileContainer = getFileByID(id); - fileContainer.delete(); - } - - - public URL ensureResourcePersistence(URL url, String itemID, String resourceID, String name) { - ItemContainer itemContainer = getContainerByStorageURL(url); - FileContainer fileContainer; - if(itemContainer instanceof FileContainer) { - fileContainer = (FileContainer) itemContainer; - }else { - return url; - } - - FolderContainer destinationFolder = getDestinationFolder(fileContainer.get()); - - if(isItemPersistedFile(fileContainer, destinationFolder, itemID)) { - return url; - } - - createdFile = copyFile(fileContainer, destinationFolder, resourceID); - - Map map = new HashMap<>(); - map.put(ORIGINAL_URL, url.toString()); - map.put(ORIGINAL_NAME, name); - map.put(CATALOGUE_ITEM_ID, itemID); - map.put(CATALOGUE_RESOURCE_ID, resourceID); - Metadata metadata = new Metadata(map); - createdFile.setMetadata(metadata); - - URL finalURL = createdFile.getPublicLink(); - logger.debug("Original File URL was {} - Final URL to ensure persistency is {}", url, finalURL); - return finalURL; - } - - public void deleteResourcePersistence(URL url, String itemID) { - FileContainer fileContainer = (FileContainer) getContainerByStorageURL(url); - FolderContainer destinationFolder = getDestinationFolder(fileContainer.get()); - if(isItemPersistedFile(fileContainer, destinationFolder, itemID)) { - fileContainer.delete(); - } - } - - protected void addRevisionID(FileContainer fileContainer, String resourceID, String revisionID) { - Metadata metadata = fileContainer.get().getPropertyMap(); - Map map = metadata.getValues(); - map.put(CATALOGUE_RESOURCE_ID, resourceID); - map.put(CATALOGUE_RESOURCE_REVISION_ID, revisionID); - metadata.setValues(map); - fileContainer.setMetadata(metadata);; - } - - public void addRevisionID(String resourceID, String revisionID) { - addRevisionID(createdFile, resourceID, revisionID); - } - - public void renameFile(String resourceID, String revisionID) { - renameFile(createdFile, resourceID); - addRevisionID(createdFile, resourceID, revisionID); - } - - protected void renameFile(FileContainer fileContainer, String newName) { - fileContainer.rename(newName); - } - -} diff --git a/src/main/webapp/WEB-INF/LICENSE b/src/main/webapp/WEB-INF/LICENSE deleted file mode 100644 index 9724bfe..0000000 --- a/src/main/webapp/WEB-INF/LICENSE +++ /dev/null @@ -1,316 +0,0 @@ -gCube System - License ------------------------------------------------------------- - -European Union Public Licence V. 1.1 - - -EUPL © the European Community 2007 - - -This European Union Public Licence (the “EUPL”) applies to the Work or Software -(as defined below) which is provided under the terms of this Licence. Any use of -the Work, other than as authorised under this Licence is prohibited (to the -extent such use is covered by a right of the copyright holder of the Work). - -The Original Work is provided under the terms of this Licence when the Licensor -(as defined below) has placed the following notice immediately following the -copyright notice for the Original Work: - -Licensed under the EUPL V.1.1 - -or has expressed by any other mean his willingness to license under the EUPL. - - - -1. Definitions - -In this Licence, the following terms have the following meaning: - -- The Licence: this Licence. - -- The Original Work or the Software: the software distributed and/or - communicated by the Licensor under this Licence, available as Source Code and - also as Executable Code as the case may be. - -- Derivative Works: the works or software that could be created by the Licensee, - based upon the Original Work or modifications thereof. This Licence does not - define the extent of modification or dependence on the Original Work required - in order to classify a work as a Derivative Work; this extent is determined by - copyright law applicable in the country mentioned in Article 15. - -- The Work: the Original Work and/or its Derivative Works. - -- The Source Code: the human-readable form of the Work which is the most - convenient for people to study and modify. - -- The Executable Code: any code which has generally been compiled and which is - meant to be interpreted by a computer as a program. - -- The Licensor: the natural or legal person that distributes and/or communicates - the Work under the Licence. - -- Contributor(s): any natural or legal person who modifies the Work under the - Licence, or otherwise contributes to the creation of a Derivative Work. - -- The Licensee or “You”: any natural or legal person who makes any usage of the - Software under the terms of the Licence. - -- Distribution and/or Communication: any act of selling, giving, lending, - renting, distributing, communicating, transmitting, or otherwise making - available, on-line or off-line, copies of the Work or providing access to its - essential functionalities at the disposal of any other natural or legal - person. - - - -2. Scope of the rights granted by the Licence - -The Licensor hereby grants You a world-wide, royalty-free, non-exclusive, -sub-licensable licence to do the following, for the duration of copyright vested -in the Original Work: - -- use the Work in any circumstance and for all usage, reproduce the Work, modify -- the Original Work, and make Derivative Works based upon the Work, communicate -- to the public, including the right to make available or display the Work or -- copies thereof to the public and perform publicly, as the case may be, the -- Work, distribute the Work or copies thereof, lend and rent the Work or copies -- thereof, sub-license rights in the Work or copies thereof. - -Those rights can be exercised on any media, supports and formats, whether now -known or later invented, as far as the applicable law permits so. - -In the countries where moral rights apply, the Licensor waives his right to -exercise his moral right to the extent allowed by law in order to make effective -the licence of the economic rights here above listed. - -The Licensor grants to the Licensee royalty-free, non exclusive usage rights to -any patents held by the Licensor, to the extent necessary to make use of the -rights granted on the Work under this Licence. - - - -3. Communication of the Source Code - -The Licensor may provide the Work either in its Source Code form, or as -Executable Code. If the Work is provided as Executable Code, the Licensor -provides in addition a machine-readable copy of the Source Code of the Work -along with each copy of the Work that the Licensor distributes or indicates, in -a notice following the copyright notice attached to the Work, a repository where -the Source Code is easily and freely accessible for as long as the Licensor -continues to distribute and/or communicate the Work. - - - -4. Limitations on copyright - -Nothing in this Licence is intended to deprive the Licensee of the benefits from -any exception or limitation to the exclusive rights of the rights owners in the -Original Work or Software, of the exhaustion of those rights or of other -applicable limitations thereto. - - - -5. Obligations of the Licensee - -The grant of the rights mentioned above is subject to some restrictions and -obligations imposed on the Licensee. Those obligations are the following: - -Attribution right: the Licensee shall keep intact all copyright, patent or -trademarks notices and all notices that refer to the Licence and to the -disclaimer of warranties. The Licensee must include a copy of such notices and a -copy of the Licence with every copy of the Work he/she distributes and/or -communicates. The Licensee must cause any Derivative Work to carry prominent -notices stating that the Work has been modified and the date of modification. - -Copyleft clause: If the Licensee distributes and/or communicates copies of the -Original Works or Derivative Works based upon the Original Work, this -Distribution and/or Communication will be done under the terms of this Licence -or of a later version of this Licence unless the Original Work is expressly -distributed only under this version of the Licence. The Licensee (becoming -Licensor) cannot offer or impose any additional terms or conditions on the Work -or Derivative Work that alter or restrict the terms of the Licence. - -Compatibility clause: If the Licensee Distributes and/or Communicates Derivative -Works or copies thereof based upon both the Original Work and another work -licensed under a Compatible Licence, this Distribution and/or Communication can -be done under the terms of this Compatible Licence. For the sake of this clause, -“Compatible Licence” refers to the licences listed in the appendix attached to -this Licence. Should the Licensee’s obligations under the Compatible Licence -conflict with his/her obligations under this Licence, the obligations of the -Compatible Licence shall prevail. - -Provision of Source Code: When distributing and/or communicating copies of the -Work, the Licensee will provide a machine-readable copy of the Source Code or -indicate a repository where this Source will be easily and freely available for -as long as the Licensee continues to distribute and/or communicate the Work. - -Legal Protection: This Licence does not grant permission to use the trade names, -trademarks, service marks, or names of the Licensor, except as required for -reasonable and customary use in describing the origin of the Work and -reproducing the content of the copyright notice. - - - -6. Chain of Authorship - -The original Licensor warrants that the copyright in the Original Work granted -hereunder is owned by him/her or licensed to him/her and that he/she has the -power and authority to grant the Licence. - -Each Contributor warrants that the copyright in the modifications he/she brings -to the Work are owned by him/her or licensed to him/her and that he/she has the -power and authority to grant the Licence. - -Each time You accept the Licence, the original Licensor and subsequent -Contributors grant You a licence to their contributions to the Work, under the -terms of this Licence. - - - -7. Disclaimer of Warranty - -The Work is a work in progress, which is continuously improved by numerous -contributors. It is not a finished work and may therefore contain defects or -“bugs” inherent to this type of software development. - -For the above reason, the Work is provided under the Licence on an “as is” basis -and without warranties of any kind concerning the Work, including without -limitation merchantability, fitness for a particular purpose, absence of defects -or errors, accuracy, non-infringement of intellectual property rights other than -copyright as stated in Article 6 of this Licence. - -This disclaimer of warranty is an essential part of the Licence and a condition -for the grant of any rights to the Work. - - - -8. Disclaimer of Liability - -Except in the cases of wilful misconduct or damages directly caused to natural -persons, the Licensor will in no event be liable for any direct or indirect, -material or moral, damages of any kind, arising out of the Licence or of the use -of the Work, including without limitation, damages for loss of goodwill, work -stoppage, computer failure or malfunction, loss of data or any commercial -damage, even if the Licensor has been advised of the possibility of such -damage. However, the Licensor will be liable under statutory product liability -laws as far such laws apply to the Work. - - - -9. Additional agreements - -While distributing the Original Work or Derivative Works, You may choose to -conclude an additional agreement to offer, and charge a fee for, acceptance of -support, warranty, indemnity, or other liability obligations and/or services -consistent with this Licence. However, in accepting such obligations, You may -act only on your own behalf and on your sole responsibility, not on behalf of -the original Licensor or any other Contributor, and only if You agree to -indemnify, defend, and hold each Contributor harmless for any liability incurred -by, or claims asserted against such Contributor by the fact You have accepted -any such warranty or additional liability. - - - -10. Acceptance of the Licence - -The provisions of this Licence can be accepted by clicking on an icon “I agree” -placed under the bottom of a window displaying the text of this Licence or by -affirming consent in any other similar way, in accordance with the rules of -applicable law. Clicking on that icon indicates your clear and irrevocable -acceptance of this Licence and all of its terms and conditions. - -Similarly, you irrevocably accept this Licence and all of its terms and -conditions by exercising any rights granted to You by Article 2 of this Licence, -such as the use of the Work, the creation by You of a Derivative Work or the -Distribution and/or Communication by You of the Work or copies thereof. - - - -11. Information to the public - -In case of any Distribution and/or Communication of the Work by means of -electronic communication by You (for example, by offering to download the Work -from a remote location) the distribution channel or media (for example, a -website) must at least provide to the public the information requested by the -applicable law regarding the Licensor, the Licence and the way it may be -accessible, concluded, stored and reproduced by the Licensee. - - - -12. Termination of the Licence - -The Licence and the rights granted hereunder will terminate automatically upon -any breach by the Licensee of the terms of the Licence. - -Such a termination will not terminate the licences of any person who has -received the Work from the Licensee under the Licence, provided such persons -remain in full compliance with the Licence. - - - -13. Miscellaneous - -Without prejudice of Article 9 above, the Licence represents the complete -agreement between the Parties as to the Work licensed hereunder. - -If any provision of the Licence is invalid or unenforceable under applicable -law, this will not affect the validity or enforceability of the Licence as a -whole. Such provision will be construed and/or reformed so as necessary to make -it valid and enforceable. - -The European Commission may publish other linguistic versions and/or new -versions of this Licence, so far this is required and reasonable, without -reducing the scope of the rights granted by the Licence. New versions of the -Licence will be published with a unique version number. - -All linguistic versions of this Licence, approved by the European Commission, -have identical value. Parties can take advantage of the linguistic version of -their choice. - - - -14. Jurisdiction - -Any litigation resulting from the interpretation of this License, arising -between the European Commission, as a Licensor, and any Licensee, will be -subject to the jurisdiction of the Court of Justice of the European Communities, -as laid down in article 238 of the Treaty establishing the European Community. - -Any litigation arising between Parties, other than the European Commission, and -resulting from the interpretation of this License, will be subject to the -exclusive jurisdiction of the competent court where the Licensor resides or -conducts its primary business. - - - -15. Applicable Law - -This Licence shall be governed by the law of the European Union country where -the Licensor resides or has his registered office. - -This licence shall be governed by the Belgian law if: - -- a litigation arises between the European Commission, as a Licensor, and any -- Licensee; the Licensor, other than the European Commission, has no residence -- or registered office inside a European Union country. - - -=== - - -Appendix - - - -“Compatible Licences” according to article 5 EUPL are: - - -- GNU General Public License (GNU GPL) v. 2 - -- Open Software License (OSL) v. 2.1, v. 3.0 - -- Common Public License v. 1.0 - -- Eclipse Public License v. 1.0 - -- Cecill v. 2.0 \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/README b/src/main/webapp/WEB-INF/README deleted file mode 100644 index 832485c..0000000 --- a/src/main/webapp/WEB-INF/README +++ /dev/null @@ -1,76 +0,0 @@ -The gCube System - gCube Catalogue Service --------------------------------------------------- - -This service allows any client to publish on the gCube Catalogue. - - -This software is part of the gCube Framework (https://www.gcube-system.org/): an -open-source software toolkit used for building and operating Hybrid Data -Infrastructures enabling the dynamic deployment of Virtual Research Environments -by favouring the realisation of reuse oriented policies. - -The projects leading to this software have received funding from a series of -European Union programmes including: -* the Sixth Framework Programme for Research and Technological Development - -DILIGENT (grant no. 004260); -* the Seventh Framework Programme for research, technological development and -demonstration - D4Science (grant no. 212488), D4Science-II (grant no. -239019),ENVRI (grant no. 283465), EUBrazilOpenBio (grant no. 288754), iMarine -(grant no. 283644); -* the H2020 research and innovation programme - BlueBRIDGE (grant no. 675680), -EGIEngage (grant no. 654142), ENVRIplus (grant no. 654182), Parthenos (grant -no. 654119), SoBigData (grant no. 654024), AGINFRA PLUS (grant no. 731001). - - -Version --------------------------------------------------- - -1.0.0-SNAPSHOT (2019-01-10) - -Please see the file named "changelog.xml" in this directory for the release notes. - - -Authors --------------------------------------------------- - -* Luca Frosini (luca.frosini-AT-isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy). -* Costantino Perciante (costantino.perciante@isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy). - -Maintainers ------------ - -* Luca Frosini (luca.frosini-AT-isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy). - -Download information --------------------------------------------------- - -Source code is available from SVN: - https://svn.d4science.research-infrastructures.eu/gcube/trunk/data-catalogue/gcat - -Binaries can be downloaded from the gCube website: - https://www.gcube-system.org/ - - -Installation --------------------------------------------------- - -Installation documentation is available on-line in the gCube Wiki: - https://wiki.gcube-system.org/gcube/index.php - -Documentation --------------------------------------------------- - -Documentation is available on-line in the gCube Wiki: - https://wiki.gcube-system.org/gcube/index.php - -Support --------------------------------------------------- - -Bugs and support requests can be reported in the gCube issue tracking tool: - https://support.d4science.org/projects/gcube/ - - -Licensing --------------------------------------------------- - -This software is licensed under the terms you may find in the file named "LICENSE" in this directory. \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/changelog.xml b/src/main/webapp/WEB-INF/changelog.xml deleted file mode 100644 index c9a58d8..0000000 --- a/src/main/webapp/WEB-INF/changelog.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - Complete refactoring of code - Item Port type is now RESTful (old methods are still allowed) - Added update support for Item #11516 - Changed caching mechanism from ehcache API to JSR-107. Ehcache is still used as runtime library. - Solved random NullPointer Exception on catalogue-ws related to old caching mechanism #11466 - Fixed normalization of the organization name #12506 - Added the possibility to deny social post on catalogue-ws #12514 - - - Item purge method enhanced - - - Minor fixes while checking user's permissions - Namespaces are no longer transparently managed - Fixed 'default' value for metadata - Improved exception handling - - - First Release - - diff --git a/src/main/webapp/WEB-INF/descriptor.xml b/src/main/webapp/WEB-INF/descriptor.xml deleted file mode 100644 index 997d367..0000000 --- a/src/main/webapp/WEB-INF/descriptor.xml +++ /dev/null @@ -1,31 +0,0 @@ - - servicearchive - - tar.gz - - / - - - /home/lucafrosini/workspace/gcat/distro - / - true - - README - LICENSE - changelog.xml - profile.xml - - 755 - true - - - - - target/gcat-1.0.0-SNAPSHOT.war - /gcat - - - \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/gcube-app.xml b/src/main/webapp/WEB-INF/gcube-app.xml deleted file mode 100644 index a41541e..0000000 --- a/src/main/webapp/WEB-INF/gcube-app.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - gcat - DataPublishing - 1.0.0-SNAPSHOT - This service allows any client to publish on the gCube Catalogue. - - - diff --git a/src/main/webapp/WEB-INF/profile.xml b/src/main/webapp/WEB-INF/profile.xml deleted file mode 100644 index 198aa2a..0000000 --- a/src/main/webapp/WEB-INF/profile.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - Service - - This service allows any client to publish on the gCube Catalogue. - DataPublishing - gcat - 1.0.0 - -
- This service allows any client to publish on the gCube Catalogue. - gcat - 1.0.0-SNAPSHOT - - org.gcube.data-publishing - gcat - 1.0.0-SNAPSHOT - - - gcat-1.0.0-SNAPSHOT.war - -
-
-
-
diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 491ae36..0000000 --- a/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - org.gcube.gcat.ResourceInitializer - - - org.gcube.gcat.ResourceInitializer - /* - - \ No newline at end of file diff --git a/src/test/java/org/gcube/gcat/persistence/ckan/CKANLicenseTest.java b/src/test/java/org/gcube/gcat/persistence/ckan/CKANLicenseTest.java index 182225d..de98b72 100644 --- a/src/test/java/org/gcube/gcat/persistence/ckan/CKANLicenseTest.java +++ b/src/test/java/org/gcube/gcat/persistence/ckan/CKANLicenseTest.java @@ -18,7 +18,7 @@ public class CKANLicenseTest extends ContextTest { @Test public void list() throws Exception { CKANLicense license = new CKANLicense(); - String ret = license.list(); + String ret = license.list(-1,-1); ObjectMapper mapper = new ObjectMapper(); JsonNode gotList = mapper.readTree(ret); Assert.assertTrue(gotList instanceof ArrayNode); diff --git a/src/test/java/org/gcube/gcat/persistence/ckan/CKANPackageTest.java b/src/test/java/org/gcube/gcat/persistence/ckan/CKANPackageTest.java index fe32959..f6a8737 100644 --- a/src/test/java/org/gcube/gcat/persistence/ckan/CKANPackageTest.java +++ b/src/test/java/org/gcube/gcat/persistence/ckan/CKANPackageTest.java @@ -1,9 +1,9 @@ package org.gcube.gcat.persistence.ckan; +import java.util.HashMap; +import java.util.Map; + import org.gcube.gcat.ContextTest; -import org.gcube.gcat.persistence.ckan.CKAN; -import org.gcube.gcat.persistence.ckan.CKANPackage; -import org.gcube.gcat.persistence.ckan.CKANResource; import org.junit.Assert; import org.junit.Test; import org.slf4j.Logger; @@ -27,37 +27,58 @@ public class CKANPackageTest extends ContextTest { private static final String ITEM_NAME_VALUE = "restful_transaction_model"; private static final String LICENSE_VALUE = "CC-BY-SA-4.0"; - private static final String EXTRAS_TYPE_VALUE_VALUE = "EmptyType"; + private static final String EXTRAS_TYPE_VALUE_VALUE = "EmptyProfile"; @Test public void list() throws Exception { CKANPackage ckanPackage = new CKANPackage(); ObjectMapper mapper = new ObjectMapper(); - String ret = ckanPackage.list(); + String ret = ckanPackage.list(-1,0); JsonNode gotList = mapper.readTree(ret); Assert.assertTrue(gotList instanceof ArrayNode); logger.debug("List :\n{}", mapper.writeValueAsString(gotList)); } /* - * DEV + * PRE + * * Workspace(luca.frosini) > RESTful Transaction Model.pdf - * https://data-d.d4science.org/shub/e03355cd-058a-4e3a-8d5b-cf3676a46840 - * URL url = new URL("https://goo.gl/fSZH1o"); + * https://data1-d.d4science.org/shub/E_YjI4STdKKzRlNjgzMm9jQWxjcmtReDNwbDFYR3lpTHo3SjdtN1RDZ3c2OGk0ZHZhdE5iZElBKzNxUDAyTGFqZw== + * https://goo.gl/HcUWni * * * Workspace(luca.frosini) > RESTful Transaction Model v 1.0.pdf - * https://data-d.d4science.org/shub/8ad187c4-8f94-4c47-a780-706d0d33c1bb - * URL url = new URL("https://goo.gl/6vZSmp"); + * https://data1-d.d4science.org/shub/E_aThRa1NpWFJpTGEydEU2bEJhMXNjZy8wK3BxekJKYnpYTy81cUkwZVdicEZ0aGFRZmY4MkRnUC8xWW0zYzVoVg== + * https://goo.gl/J8AwQW * * * Workspace(luca.frosini) > RESTful Transaction Model v 1.1.pdf - * https://data-d.d4science.org/shub/7b6628e4-b397-4df9-b387-2d643ae0095c - * URL url = new URL("https://goo.gl/jvXMcd"); + * https://data1-d.d4science.org/shub/E_NkhrbVV4VTluT0RKVUtCRldobFZTQU5ySTZneFdpUzJ2UjJBNlZWNDlURDVHamo4WjY5RnlrcHZGTGNkT2prUg== + * https://goo.gl/78ViuR * */ + @Test + public void testNameRegex() { + Map stringsToTest = new HashMap<>(); + stringsToTest.put("Test", false); // Fails for T + stringsToTest.put("test-test+test-test", false); // Fails for + + stringsToTest.put("t", false); // Fails because is too short. Min length is 2 characters + stringsToTest.put("te", true); + stringsToTest.put("test-test_test-test", true); + stringsToTest.put("test-test_test-test_test-test_test-test_test-test_test-test_test-test_test-test_test-test_test-test_", true); + // // Fails because is too long. Max length is 100 characters + stringsToTest.put("test-test_test-test_test-test_test-test_test-test_test-test_test-test_test-test_test-test_test-test_t", false); + + for(String testString : stringsToTest.keySet()) { + boolean match = testString.matches(CKANPackage.NAME_REGEX); + logger.debug("'{}' does {}match the regex {}", testString, match ? "" : "NOT ", CKANPackage.NAME_REGEX); + Assert.assertEquals(stringsToTest.get(testString), match); + } + + } + protected CKANPackage createPackage(ObjectMapper mapper) throws Exception { @@ -78,7 +99,7 @@ public class CKANPackageTest extends ContextTest { ObjectNode resourceNode = mapper.createObjectNode(); resourceNode.put(CKANResource.NAME_KEY, "RESTful Transaction Model"); // Workspace(luca.frosini) > RESTful Transaction Model v 1.0.pdf - resourceNode.put(CKANResource.URL_KEY, "https://goo.gl/6vZSmp"); + resourceNode.put(CKANResource.URL_KEY, "https://goo.gl/J8AwQW"); resourceArrayNode.add(resourceNode); ArrayNode extraArrayNode = itemObjectNode.putArray(CKANPackage.EXTRA_TYPES_KEY); @@ -123,7 +144,7 @@ public class CKANPackageTest extends ContextTest { ArrayNode resources = (ArrayNode) readItemObjectNode.get(CKANPackage.RESOURCES_KEY); ObjectNode objectNode = (ObjectNode) resources.get(0); // Workspace(luca.frosini) > RESTful Transaction Model v 1.1.pdf - objectNode.put(CKANResource.URL_KEY, "https://goo.gl/jvXMcd"); + objectNode.put(CKANResource.URL_KEY, "https://goo.gl/78ViuR"); resources.set(0, objectNode); ((ObjectNode) readItemObjectNode).replace(CKANPackage.RESOURCES_KEY, resources); diff --git a/src/test/java/org/gcube/gcat/persistence/ckan/CKANResourceTest.java b/src/test/java/org/gcube/gcat/persistence/ckan/CKANResourceTest.java index 19a03a9..6af4dce 100644 --- a/src/test/java/org/gcube/gcat/persistence/ckan/CKANResourceTest.java +++ b/src/test/java/org/gcube/gcat/persistence/ckan/CKANResourceTest.java @@ -4,7 +4,8 @@ import java.net.URL; import java.util.UUID; import org.gcube.gcat.ContextTest; -import org.gcube.gcat.persistence.ckan.CKANResource; +import org.gcube.gcat.utils.Constants; +import org.gcube.storagehub.ApplicationMode; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -16,55 +17,64 @@ public class CKANResourceTest extends ContextTest { private static final Logger logger = LoggerFactory.getLogger(CKANResourceTest.class); - /* - * PROD - * Workspace(luca.frosini) > RESTful Transaction Model.pdf - * https://data.d4science.org/shub/ab4daec8-2ce4-43d7-9d37-00b2051e3530 - * URL url = new URL("https://goo.gl/bFME6Q"); - */ - /* - * DEV + * PRE + * * Workspace(luca.frosini) > RESTful Transaction Model.pdf - * https://data-d.d4science.org/shub/e03355cd-058a-4e3a-8d5b-cf3676a46840 - * URL url = new URL("https://goo.gl/fSZH1o"); + * https://data1-d.d4science.org/shub/E_YjI4STdKKzRlNjgzMm9jQWxjcmtReDNwbDFYR3lpTHo3SjdtN1RDZ3c2OGk0ZHZhdE5iZElBKzNxUDAyTGFqZw== + * https://goo.gl/HcUWni * * * Workspace(luca.frosini) > RESTful Transaction Model v 1.0.pdf - * https://data-d.d4science.org/shub/5df695ea-986a-437d-abaf-ed1542a7f5af - * URL url = new URL("https://goo.gl/7ofQwn"); + * https://data1-d.d4science.org/shub/E_aThRa1NpWFJpTGEydEU2bEJhMXNjZy8wK3BxekJKYnpYTy81cUkwZVdicEZ0aGFRZmY4MkRnUC8xWW0zYzVoVg== + * https://goo.gl/J8AwQW * * * Workspace(luca.frosini) > RESTful Transaction Model v 1.1.pdf - * https://data-d.d4science.org/shub/7b6628e4-b397-4df9-b387-2d643ae0095c - * URL url = new URL("https://goo.gl/jvXMcd"); + * https://data1-d.d4science.org/shub/E_NkhrbVV4VTluT0RKVUtCRldobFZTQU5ySTZneFdpUzJ2UjJBNlZWNDlURDVHamo4WjY5RnlrcHZGTGNkT2prUg== + * https://goo.gl/78ViuR * */ - @Test + public void test() throws Exception { + ApplicationMode applicationMode = new ApplicationMode(Constants.getCatalogueApplicationToken()); + applicationMode.start(); + // + applicationMode.end(); + } + + // @Test public void testCopyStorageResource() throws Exception { - URL url = new URL("https://goo.gl/fSZH1o"); + URL url = new URL("https://goo.gl/HcUWni"); String itemID = UUID.randomUUID().toString(); CKANResource ckanResource = new CKANResource(itemID); ckanResource.resourceID = UUID.randomUUID().toString(); URL finalURL = ckanResource.copyStorageResource(url); logger.debug("Initial URL is {} - Final URL is {}", url, finalURL); - ckanResource.deleteStorageResource(finalURL); + ckanResource.deleteStorageResource(finalURL, ckanResource.resourceID, ckanResource.mimeType); } - // @Test + @Test public void testCreate() throws Exception { ObjectMapper objectMapper = new ObjectMapper(); ObjectNode objectNode = objectMapper.createObjectNode(); - objectNode.put(CKANResource.URL_KEY, "https://data.d4science.org/shub/ab4daec8-2ce4-43d7-9d37-00b2051e3530"); - objectNode.put(CKANResource.ID_KEY, "8422b5d4-626b-46f2-9121-bbc6d443071d"); + objectNode.put(CKANResource.NAME_KEY, "MyTestTy_rest_upload"); + objectNode.put(CKANResource.URL_KEY, "https://data.d4science.org/shub/58a13287-3e91-4afd-bd80-cf4605a0edaa"); + objectNode.put("description", "i uploaded this file using the REST API"); + // objectNode.put(CKANResource.ID_KEY, "ba7ab7e8-c268-4219-98cd-c73470870999"); - CKANResource ckanResource = new CKANResource("f9221556-4b1f-49f2-8951-a4c30d71cd37"); + CKANResource ckanResource = new CKANResource("ba7ab7e8-c268-4219-98cd-c73470870999"); String json = ckanResource.getAsString(objectNode); logger.debug("Going to create Resource {}", json); - ckanResource.create(json); - + ckanResource.create(objectNode); + } + + // @Test + public void testDelete() throws Exception { + CKANResource ckanResource = new CKANResource("f0326fec-d8ac-42c7-abff-c7905b4d938e"); + ckanResource.setResourceID("fcf98272-41e7-4f05-9294-fdafb1a33074"); + ckanResource.delete(); } } diff --git a/src/test/java/org/gcube/gcat/persistence/ckan/CKANUserTest.java b/src/test/java/org/gcube/gcat/persistence/ckan/CKANUserTest.java index b3ec109..09f228f 100644 --- a/src/test/java/org/gcube/gcat/persistence/ckan/CKANUserTest.java +++ b/src/test/java/org/gcube/gcat/persistence/ckan/CKANUserTest.java @@ -27,7 +27,7 @@ public class CKANUserTest extends ContextTest { @Test public void list() throws Exception { CKANUser ckanUser = getCKANUser(); - String ret = ckanUser.list(); + String ret = ckanUser.list(-1,-1); logger.debug("{}", ret); } diff --git a/src/test/java/org/gcube/gcat/rest/ProfileTest.java b/src/test/java/org/gcube/gcat/rest/ProfileTest.java index b0fbc0e..0533dfd 100644 --- a/src/test/java/org/gcube/gcat/rest/ProfileTest.java +++ b/src/test/java/org/gcube/gcat/rest/ProfileTest.java @@ -1,11 +1,14 @@ package org.gcube.gcat.rest; +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; import java.util.Iterator; +import java.util.stream.Collectors; import javax.ws.rs.core.MediaType; import org.gcube.gcat.ContextTest; -import org.gcube.gcat.rest.Profile; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -53,4 +56,24 @@ public class ProfileTest extends ContextTest { } } + public static String PROFILE_EXAMPLE_FILENAME = "EmptyProfileExample.xml"; + + public static String PROFILE_NAME_EXAMPLE = "EmptyProfile"; + + @Test + public void testCreateUpdateDeleteGenericResource() throws Exception { + InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(PROFILE_EXAMPLE_FILENAME); + String xml = new BufferedReader(new InputStreamReader(inputStream)).lines() + .collect(Collectors.joining("\n")); + logger.debug("Body\n{}", xml); + Profile profile = new Profile(); + profile.createOrUpdate(PROFILE_NAME_EXAMPLE, xml); + /* + Thread.sleep(TimeUnit.SECONDS.toMillis(30)); + profile.createOrUpdate(PROFILE_NAME_EXAMPLE, ""); + Thread.sleep(TimeUnit.SECONDS.toMillis(30)); + profile.delete(PROFILE_NAME_EXAMPLE); + */ + } + } diff --git a/src/test/java/org/gcube/gcat/workspace/CatalogueStorageHubManagementTest.java b/src/test/java/org/gcube/gcat/workspace/CatalogueStorageHubManagementTest.java new file mode 100644 index 0000000..a836994 --- /dev/null +++ b/src/test/java/org/gcube/gcat/workspace/CatalogueStorageHubManagementTest.java @@ -0,0 +1,125 @@ +package org.gcube.gcat.workspace; + +import java.net.URL; +import java.util.Map; + +import org.gcube.common.storagehub.client.dsl.FileContainer; +import org.gcube.common.storagehub.model.Metadata; +import org.gcube.gcat.ContextTest; +import org.gcube.gcat.persistence.ckan.CKANResource; +import org.gcube.storagehub.StorageHubManagement; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CatalogueStorageHubManagementTest extends ContextTest { + + private static final Logger logger = LoggerFactory.getLogger(CatalogueStorageHubManagementTest.class); + + /* + * PRE + * + * Workspace(luca.frosini) > RESTful Transaction Model.pdf + * https://data1-d.d4science.org/shub/E_YjI4STdKKzRlNjgzMm9jQWxjcmtReDNwbDFYR3lpTHo3SjdtN1RDZ3c2OGk0ZHZhdE5iZElBKzNxUDAyTGFqZw== + * https://goo.gl/HcUWni + * + * Workspace(luca.frosini) > RESTful Transaction Model v 1.0.pdf + * https://data1-d.d4science.org/shub/E_aThRa1NpWFJpTGEydEU2bEJhMXNjZy8wK3BxekJKYnpYTy81cUkwZVdicEZ0aGFRZmY4MkRnUC8xWW0zYzVoVg== + * https://goo.gl/J8AwQW + * + * + * Workspace(luca.frosini) > RESTful Transaction Model v 1.1.pdf + * https://data1-d.d4science.org/shub/E_NkhrbVV4VTluT0RKVUtCRldobFZTQU5ySTZneFdpUzJ2UjJBNlZWNDlURDVHamo4WjY5RnlrcHZGTGNkT2prUg== + * https://goo.gl/78ViuR + * + */ + + public static final String ORIGINAL_STORAGE_URL_STRING = "https://data1-d.d4science.org/shub/E_YjI4STdKKzRlNjgzMm9jQWxjcmtReDNwbDFYR3lpTHo3SjdtN1RDZ3c2OGk0ZHZhdE5iZElBKzNxUDAyTGFqZw=="; + public static final URL ORIGINAL_STORAGE_URL; + + public static final String SHORT_URL_STRING = "https://goo.gl/HcUWni"; + public static final URL SHORT_STORAGE_URL; + + + + public static final String MIME_TYPE = "application/pdf"; + + + static { + try { + ORIGINAL_STORAGE_URL = new URL(ORIGINAL_STORAGE_URL_STRING); + SHORT_STORAGE_URL = new URL(SHORT_URL_STRING); + }catch (Exception e) { + throw new RuntimeException(e); + } + + } + + public static final String ITEM_ID = "MyItem"; + public static final String RESOURCE_ID = "1234"; + + protected CatalogueStorageHubManagement catalogueStorageHubManagement; + protected StorageHubManagement storageHubManagement; + protected CatalogueMetadata catalogueMetadata; + + + public CatalogueStorageHubManagementTest() { + catalogueStorageHubManagement = new CatalogueStorageHubManagement(); + storageHubManagement = catalogueStorageHubManagement.storageHubManagement; + catalogueMetadata = new CatalogueMetadata(ITEM_ID); + } + + @Test + public void getFinalURL() { + URL finalURL = CKANResource.getFinalURL(SHORT_STORAGE_URL); + Assert.assertTrue(finalURL.toString().compareTo(ORIGINAL_STORAGE_URL_STRING)==0); + } + + protected void checkMetadata(FileContainer fileContainer, String version) { + Metadata gotMetadata = fileContainer.get().getMetadata(); + Map gotMap = gotMetadata.getMap(); + + CatalogueMetadata catalogueMetadata = new CatalogueMetadata(ITEM_ID); + + Metadata expectedMetadata = catalogueMetadata.getMetadata(ORIGINAL_STORAGE_URL, fileContainer.get().getName(), RESOURCE_ID); + Map expectedMap = expectedMetadata.getMap(); + + for(String key : gotMap.keySet()) { + String value = (String) gotMap.get(key); + if(key.compareTo(CatalogueMetadata.CATALOGUE_RESOURCE_REVISION_ID)==0) { + Assert.assertTrue(value.compareTo(version)==0); + }else { + String expectedValue = (String) expectedMap.get(key); + Assert.assertTrue(value.compareTo(expectedValue)==0); + } + } + } + + + @Test + public void testPersistence() throws Exception { + + URL persistedURL = catalogueStorageHubManagement.ensureResourcePersistence(ORIGINAL_STORAGE_URL, ITEM_ID, RESOURCE_ID); + logger.debug("Publick Link of persisted file is {}", persistedURL); + + Assert.assertTrue(catalogueStorageHubManagement.getMimeType().compareTo(MIME_TYPE)==0); + + FileContainer createdFileContainer = storageHubManagement.getCreatedFile(); + + + String version = "2"; + catalogueStorageHubManagement.renameFile(RESOURCE_ID, version); + checkMetadata(createdFileContainer, version); + + + version = "3"; + catalogueStorageHubManagement.addRevisionID(RESOURCE_ID, version); + checkMetadata(createdFileContainer, version); + + + catalogueStorageHubManagement.deleteResourcePersistence(ITEM_ID, RESOURCE_ID, MIME_TYPE); + + } + +} diff --git a/src/test/java/org/gcube/gcat/workspace/StorageHubManagementTest.java b/src/test/java/org/gcube/gcat/workspace/StorageHubManagementTest.java deleted file mode 100644 index 6264f98..0000000 --- a/src/test/java/org/gcube/gcat/workspace/StorageHubManagementTest.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.gcube.gcat.workspace; - -import java.util.List; -import java.util.Map; - -import org.gcube.common.homelibrary.home.Home; -import org.gcube.common.homelibrary.home.HomeLibrary; -import org.gcube.common.homelibrary.home.HomeManager; -import org.gcube.common.homelibrary.home.HomeManagerFactory; -import org.gcube.common.homelibrary.home.User; -import org.gcube.common.homelibrary.home.workspace.Workspace; -import org.gcube.common.homelibrary.home.workspace.WorkspaceFolder; -import org.gcube.common.homelibrary.home.workspace.WorkspaceItem; -import org.gcube.common.storagehub.client.dsl.FileContainer; -import org.gcube.common.storagehub.client.dsl.FolderContainer; -import org.gcube.common.storagehub.client.dsl.ItemContainer; -import org.gcube.common.storagehub.client.dsl.ListResolver; -import org.gcube.common.storagehub.model.Metadata; -import org.gcube.common.storagehub.model.items.Item; -import org.gcube.common.storagehub.model.service.Version; -import org.gcube.gcat.ContextTest; -import org.gcube.gcat.utils.ApplicationMode; -import org.gcube.gcat.utils.ContextUtility; -import org.gcube.gcat.workspace.StorageHubManagement; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class StorageHubManagementTest extends ContextTest { - - private static final Logger logger = LoggerFactory.getLogger(StorageHubManagementTest.class); - - @Test - public void testHL() throws Exception { - ApplicationMode applicationMode = new ApplicationMode(); - applicationMode.start(); - String username = ContextUtility.getUsername(); - HomeManagerFactory factory = HomeLibrary.getHomeManagerFactory(); - HomeManager manager = factory.getHomeManager(); - User user = manager.createUser(username); - @SuppressWarnings("deprecation") - Home home = manager.getHome(user); - Workspace ws = home.getWorkspace(); - WorkspaceFolder workspaceFolder = ws.getRoot(); - List workspaceItems = workspaceFolder.getChildren(true); - for(WorkspaceItem workspaceItem : workspaceItems) { - logger.debug("{} {}{}", workspaceFolder.getType(), workspaceItem.getName(), workspaceItem.isHidden()? " (hidden)":""); - } - } - - @Test - public void myTest() throws Exception { - String folderName = StorageHubManagement.getFolderName(); - logger.debug(folderName); - } - - @Test - public void test() throws Exception { - ApplicationMode applicationMode = new ApplicationMode(); - applicationMode.start(); - StorageHubManagement storageHubManagement = new StorageHubManagement(); - FolderContainer root = storageHubManagement.getWorkspaceRoot(); - storageHubManagement.tree(root); - } - - @Test - public void listFolders() throws Exception { - ApplicationMode applicationMode = new ApplicationMode(); - applicationMode.start(); - StorageHubManagement storageHubManagement = new StorageHubManagement(); - FolderContainer root = storageHubManagement.getWorkspaceRoot(); - storageHubManagement.getCatalogueFolder(); - storageHubManagement.tree(root); - applicationMode.end(); - } - - // @Test - public void deleteFile() throws Exception { - StorageHubManagement storageHubManagement = new StorageHubManagement(); - String id = ""; - storageHubManagement.deleteFileByID(id); - } - - @Test - public void getFileInfo() throws Exception { - StorageHubManagement storageHubManagement = new StorageHubManagement(); - String id = ""; - FileContainer fileContainer = storageHubManagement.getFileByID(id); - logger.debug("StorageHub ID {} - File Name {}", id, fileContainer.get().getName()); - ListResolver listResolver = fileContainer.getAnchestors(); - List> itemContainers = listResolver.getContainers(); - for(ItemContainer itemContainer : itemContainers) { - logger.debug("{}", itemContainer.get().getName()); - } - - Metadata metadata = fileContainer.get().getPropertyMap(); - Map map = metadata.getValues(); - logger.debug("{}", map); - - List versions = fileContainer.getVersions(); - for(Version version : versions){ - logger.debug("Version {} {}", version.getId(), version.getName()); - } - } - -} diff --git a/src/test/resources/EmptyProfileExample.xml b/src/test/resources/EmptyProfileExample.xml new file mode 100644 index 0000000..f0cffcf --- /dev/null +++ b/src/test/resources/EmptyProfileExample.xml @@ -0,0 +1,9 @@ + + + test + false + String + 1 + Test Field + + \ No newline at end of file diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index 1e138b1..4da43d9 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -10,7 +10,7 @@ - + diff --git a/src/test/resources/workspace-gce-id.txt b/src/test/resources/workspace-gce-id.txt deleted file mode 100644 index 7cffc37..0000000 --- a/src/test/resources/workspace-gce-id.txt +++ /dev/null @@ -1 +0,0 @@ -227af25a-7631-4abd-a866-a67ff7f63276 diff --git a/src/test/resources/workspace-rep-preprod.txt b/src/test/resources/workspace-rep-preprod.txt deleted file mode 100644 index 048425f..0000000 --- a/src/test/resources/workspace-rep-preprod.txt +++ /dev/null @@ -1,3 +0,0 @@ -DO CANCEL THIS FILE IN PRODUCTION and DEV ENVIRONMENTS - -The presence of this file indicates the home library client to look for the preprod instance of the workspace repository. \ No newline at end of file