Methods for publishing stock or fishery records added. The association thread that should associate the product to the groups fails. This needs to be fixed. Target selected as folder to be ignored

git-svn-id: https://svn.d4science.research-infrastructures.eu/gcube/trunk/data-catalogue/grsf-publisher-ws@133011 82a268e6-3cf1-43bd-a215-b396298e98cf
feature/17695
Costantino Perciante 8 years ago
parent 1c2d7f0246
commit 9fb01322c0

@ -15,6 +15,7 @@
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">

@ -5,11 +5,26 @@
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
@ -17,7 +32,11 @@
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
</natures>
</projectDescription>

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/main/webapp"/>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.WebProject">
<attributes>
<attribute name="hide" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
<classpathentry kind="output" path=""/>
</classpath>

@ -1,5 +1,8 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.7

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="grsf-publisher-ws">
<wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
<wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
<dependent-module archiveName="ckan-util-library-2.0.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/ckan-util-library/ckan-util-library">
<dependency-type>uses</dependency-type>
</dependent-module>
<property name="context-root" value="grsf-publisher-ws"/>
<property name="java-output-path" value="/grsf-publisher-ws/target/classes"/>
</wb-module>
</project-modules>

@ -0,0 +1,7 @@
<root>
<facet id="jst.jaxrs">
<node name="libprov">
<attribute name="provider-id" value="jaxrs-no-op-library-provider"/>
</node>
</facet>
</root>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<fixed facet="wst.jsdt.web"/>
<installed facet="java" version="1.7"/>
<installed facet="jst.web" version="3.0"/>
<installed facet="jst.jaxrs" version="2.0"/>
<installed facet="wst.jsdt.web" version="1.0"/>
</faceted-project>

@ -0,0 +1 @@
org.eclipse.wst.jsdt.launching.baseBrowserLibrary

@ -0,0 +1,2 @@
disabled=06target
eclipse.preferences.version=1

@ -12,7 +12,7 @@
<groupId>org.gcube.data-catalogue</groupId>
<artifactId>grsf-publisher-ws</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<packaging>war</packaging>
<name>grsf-publisher-ws</name>
<description>
@ -70,6 +70,11 @@
<version>[2.0.0-SNAPSHOT, 3.0.0-SNAPSHOT)</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-encryption</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>authorization-client</artifactId>
@ -112,6 +117,11 @@
<artifactId>common-smartgears</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.resources.discovery</groupId>
<artifactId>ic-client</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-jetty</artifactId>
@ -130,9 +140,9 @@
<executions>
<execution>
<phase>compile</phase>
<!-- <goals> -->
<!-- <goal>exploded</goal> -->
<!-- </goals> -->
<goals>
<goal>exploded</goal>
</goals>
</execution>
</executions>
<configuration>

@ -8,7 +8,6 @@ import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.CustomField;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Group;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Tag;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Source;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Status;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Type;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@ -26,14 +25,14 @@ public class Common {
@JsonProperty("license")
private String license;
@JsonProperty("author")// filled automatically by the server
// filled automatically by the server
private String author;
@JsonProperty("version")
private Long version;
@JsonProperty("author_contact")// filled automatically by the service
// filled automatically by the service
private String authorContact;
@JsonProperty("maintainer")
@ -65,11 +64,6 @@ public class Common {
@CustomField(key="Type")
private Type type;
@JsonProperty("status")
@Tag
@CustomField(key="Status")
private Status status;
@JsonProperty("resources")
private List<Resource> resources;
@ -88,7 +82,7 @@ public class Common {
Long version, String authorContact, String maintainer,
String maintainerContact, String catchesOrLandings,
Source databaseSources, String sourceOfInformation,
String dataOwner, Type type, Status status,
String dataOwner, Type type,
List<Resource> resources, Map<String, String> extras,
String spatial) {
super();
@ -104,7 +98,6 @@ public class Common {
this.sourceOfInformation = sourceOfInformation;
this.dataOwner = dataOwner;
this.type = type;
this.status = status;
this.resources = resources;
this.extras = extras;
this.spatial = spatial;
@ -149,7 +142,7 @@ public class Common {
public void setVersion(Long version) {
this.version = version;
}
public String getAuthorContact() {
return authorContact;
}
@ -214,14 +207,6 @@ public class Common {
this.type = type;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
public List<Resource> getResources() {
return resources;
}
@ -247,9 +232,9 @@ public class Common {
+ ", catchesOrLandings=" + catchesOrLandings
+ ", databaseSources=" + databaseSources
+ ", sourceOfInformation=" + sourceOfInformation
+ ", dataOwner=" + dataOwner + ", type=" + type + ", status="
+ status + ", resources=" + resources + ", extras="
+ extras + ", spatial=" + spatial + "]";
+ ", dataOwner=" + dataOwner + ", type=" + type
+ ", resources=" + resources + ", extras=" + extras
+ ", spatial=" + spatial + "]";
}
}

@ -4,6 +4,7 @@ import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.CustomField;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Group;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Tag;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Production_System_Type;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Status;
import com.fasterxml.jackson.annotation.JsonProperty;
@ -57,6 +58,10 @@ public class FisheryRecord extends Common{
@CustomField(key="Fishing gear")
private String fishingGear;
@JsonProperty("status")
@CustomField(key="Status")
private Status status;
public FisheryRecord() {
super();
}
@ -171,6 +176,14 @@ public class FisheryRecord extends Common{
this.fishingGear = fishingGear;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
@Override
public String toString() {
return "FisheryRecord [" + super.toString() + ", fisheryName=" + fisheryName + ", fisheryId="
@ -180,8 +193,7 @@ public class FisheryRecord extends Common{
+ ", jurisdictionArea=" + jurisdictionArea
+ ", productionSystemType=" + productionSystemType
+ ", flagState=" + flagState + ", fishingGear=" + fishingGear
+ "]";
+ ", status=" + status + "]";
}
}

@ -5,6 +5,7 @@ import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Group;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Tag;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Abundance_Level;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Exploitation_Rate;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Status;
import com.fasterxml.jackson.annotation.JsonProperty;
@ -71,6 +72,11 @@ public class StockRecord extends Common{
@JsonProperty("reporting_year")
@CustomField(key="Reporting year")
private Long reportingYear;
@JsonProperty("status")
@Tag
@CustomField(key="Status")
private Status status;
/**
*
@ -230,6 +236,14 @@ public class StockRecord extends Common{
public void setReportingYear(Long reportingYear) {
this.reportingYear = reportingYear;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
@Override
public String toString() {
@ -244,6 +258,7 @@ public class StockRecord extends Common{
+ ", narrativeStateAndTrend=" + narrativeStateAndTrend
+ ", scientificAdvice=" + scientificAdvice
+ ", reportingEntity=" + reportingEntity + ", reportingYear="
+ reportingYear + "]";
+ reportingYear + ", status=" + status + "]";
}
}

@ -1,17 +1,34 @@
package org.gcube.data_catalogue.grsf_publish_ws.services;
import java.util.UUID;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
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.gcube.data_catalogue.grsf_publish_ws.json.input.FisheryRecord;
import org.gcube.data_catalogue.grsf_publish_ws.json.input.Resource;
import org.gcube.data_catalogue.grsf_publish_ws.json.output.ResponseCreationBean;
import org.gcube.data_catalogue.grsf_publish_ws.utils.AssociationToGroupThread;
import org.gcube.data_catalogue.grsf_publish_ws.utils.HelperMethods;
import org.gcube.datacatalogue.ckanutillibrary.DataCatalogue;
import org.gcube.datacatalogue.ckanutillibrary.models.ResourceBean;
import org.gcube.datacatalogue.ckanutillibrary.models.RolesCkanGroupOrOrg;
import org.gcube.datacatalogue.ckanutillibrary.utils.UtilMethods;
import org.slf4j.LoggerFactory;
/**
@ -20,9 +37,21 @@ import org.slf4j.LoggerFactory;
*/
@Path("fishery/")
public class GrsfPublisherFisheryService {
// the context
@Context
ServletContext contextServlet;
// Logger
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(GrsfPublisherFisheryService.class);
@GET
@Path("hello")
@Produces(MediaType.TEXT_PLAIN)
public Response hello(){
return Response.ok("Hello.. Fishery service is here").build();
}
@POST
@Path("publish-product")
@ -30,11 +59,164 @@ public class GrsfPublisherFisheryService {
@Produces(MediaType.APPLICATION_JSON)
public Response publishFishery(FisheryRecord record){
logger.info("Incoming request for creating a fishery record");
System.out.println(record);
// retrieve context and username
Caller caller = AuthorizationProvider.instance.get();
String username = caller.getClient().getId();
String context = ScopeProvider.instance.get();
logger.info("Incoming request for creating a fishery record = " + record);
logger.info("Request coming from user " + username + " in context " + context);
ResponseCreationBean responseBean = new ResponseCreationBean();
Status status = Status.INTERNAL_SERVER_ERROR;
String id = "";
try{
// determine the organization in which this product should be put
String contextInWhichPublish = HelperMethods.getContextFromStatus(record.getStatus(), contextServlet);
if(contextInWhichPublish == null || !contextInWhichPublish.equals(context)){
// stop, this value must be defined
status = Status.BAD_REQUEST;
responseBean.setId(id);
throw new IllegalArgumentException("Status attribute is not defined or the Token you are using is not correct to perform such request!");
}else{
DataCatalogue catalogue = HelperMethods.getDataCatalogueRunningInstance(context);
if(catalogue == null){
status = Status.INTERNAL_SERVER_ERROR;
responseBean.setId(null);
throw new Exception("There was a problem while serving your request");
}else{
// check the user has editor/admin role into the org
String organization = HelperMethods.retrieveOrgNameFromScope(contextInWhichPublish);
if(catalogue.getRoleOfUserInOrganization(username, organization, catalogue.getApiKeyFromUsername(username)).equals(RolesCkanGroupOrOrg.MEMBER)){
status = Status.FORBIDDEN;
responseBean.setId(null);
throw new Exception("You are not authorized to create a product. Please check you have at least the editor role!");
}
// check the record has a name, at least
String futureTitle = record.getFisheryName();
if(!HelperMethods.isValid(futureTitle)){
status = Status.BAD_REQUEST;
responseBean.setId(null);
throw new Exception("The name requested for the product is not correct! It should contain only alphanumeric characters, and symbols like '.' or '_', '-'");
}else{
logger.debug("Checking if such name [" + futureTitle + "]doesn't exist yet...");
String futureName = UtilMethods.fromProductTitleToName(futureTitle);
logger.info("Transformed name is " + futureName);
boolean alreadyExist = catalogue.existProductWithNameOrId(futureName);
if(alreadyExist){
logger.debug("A product with name " + futureName + " already exists");
responseBean.setId(null);
status = Status.BAD_REQUEST;
throw new Exception("Sorry but a product with such name already exists!");
}else{
// evaluate the tags of the product
List<String> tags = new ArrayList<String>();
HelperMethods.getTags(tags, record);
// evaluate the groups
List<String> groups = new ArrayList<String>();
HelperMethods.getGroups(groups, record);
// evaluate the custom fields
Map<String, String> customFields = new HashMap<String, String>();
if(record.getExtras() != null)
customFields = record.getExtras();
// automatically retrieve the other ones
HelperMethods.getExtras(customFields, record);
// retrieve the user's email and fullname
String authorMail = HelperMethods.getUserEmail(context, SecurityTokenProvider.instance.get());
String authorFullname = HelperMethods.getUserFullname(context, SecurityTokenProvider.instance.get());
if(authorMail == null || authorFullname == null){
logger.debug("Author fullname or mail missing, cannot continue");
responseBean.setId(null);
status = Status.INTERNAL_SERVER_ERROR;
throw new Exception("Sorry but there was not possible to retrieve your fullname/email!");
}else{
// evaluate the resources TODO
List<Resource> resourcesRecord = record.getResources();
List<ResourceBean> resources = null;
if(resourcesRecord != null && !resourcesRecord.isEmpty()){
resources = new ArrayList<ResourceBean>();
for (Resource res : resourcesRecord) {
logger.debug("Trying to add resource " + res);
if(res.getName() != null && res.getUrl() != null)
resources.add(new ResourceBean(res.getUrl(), res.getName(), res.getDescription(), null, username, null, null));
else
logger.warn("Unable to add resource because url or name is null");
}
}
// if confirmed, set to visible TODO anyway if it is confirmed we should another method
boolean setPublic = record.getStatus() == org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Status.Confirmed;
// create the product
id = catalogue.createCKanDataset(
catalogue.getApiKeyFromUsername(username),
futureTitle,
organization,
authorFullname,
authorMail,
record.getMaintainer(),
record.getMaintainerContact(),
record.getVersion(),
record.getDescription(),
record.getLicense(),
tags,
customFields,
resources,
setPublic); // TODO
if(id != null){
logger.info("Product created! Id is " + id);
responseBean.setId(id);
status = Status.CREATED;
responseBean.setError(null);
if(!groups.isEmpty()){
logger.info("Launching thread for association to the list of groups " + groups);
new AssociationToGroupThread(groups, id, organization, username, catalogue).start();
}
}
}
}
}
}
}
}catch(Exception e){
logger.error("Failed to create fishery record", e);
responseBean.setError(e.getMessage());
}
// TODO
return Response.status(Status.CREATED).entity(new ResponseCreationBean(UUID.randomUUID().toString(), null)).build();
return Response.status(status).entity(responseBean).build();
}

@ -1,23 +1,34 @@
package org.gcube.data_catalogue.grsf_publish_ws.services;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
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.gcube.data_catalogue.grsf_publish_ws.json.input.Resource;
import org.gcube.data_catalogue.grsf_publish_ws.json.input.StockRecord;
import org.gcube.data_catalogue.grsf_publish_ws.json.output.ResponseCreationBean;
import org.gcube.data_catalogue.grsf_publish_ws.utils.AssociationToGroupThread;
import org.gcube.data_catalogue.grsf_publish_ws.utils.HelperMethods;
import org.gcube.datacatalogue.ckanutillibrary.DataCatalogue;
import org.gcube.datacatalogue.ckanutillibrary.models.ResourceBean;
import org.gcube.datacatalogue.ckanutillibrary.models.RolesCkanGroupOrOrg;
import org.gcube.datacatalogue.ckanutillibrary.utils.UtilMethods;
import org.slf4j.LoggerFactory;
/**
@ -27,8 +38,19 @@ import org.slf4j.LoggerFactory;
@Path("stock/")
public class GrsfPublisherStockService {
// the context
@Context
ServletContext contextServlet;
// Logger
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(GrsfPublisherStockService.class);
@GET
@Path("hello")
@Produces(MediaType.TEXT_PLAIN)
public Response hello(){
return Response.ok("Hello.. Stock service is here").build();
}
@POST
@Path("publish-product")
@ -41,40 +63,160 @@ public class GrsfPublisherStockService {
String username = caller.getClient().getId();
String context = ScopeProvider.instance.get();
logger.info("Incoming request for creating a stock record by user with id " + username);
logger.info("Incoming request for creating a stock record = " + record);
logger.info("Request coming from user " + username + " in context " + context);
ResponseCreationBean responseBean = new ResponseCreationBean();
Status status = Status.CREATED;
Status status = Status.INTERNAL_SERVER_ERROR;
String id = "";
try{
DataCatalogue catalogue = HelperMethods.getDataCatalogueRunningInstance(context);
// check the user has editor/admin role into the org TODO pending or accepted?
// check the record has a name, at least
// evaluate the tags of the product
// evaluate the resources
// evaluate tags and groups using reflection
List<String> tags = new ArrayList<String>();
List<String> groups = new ArrayList<String>();
// create the product
//catalogue.createCKanDataset(apiKey, title, organizationNameOrId, author, authorMail, maintainer, maintainerMail, version, description, licenseId, tags, customFields, resources, setPublic)
// determine the organization in which this product should be put
String contextInWhichPublish = HelperMethods.getContextFromStatus(record.getStatus(), contextServlet);
if(contextInWhichPublish == null || !contextInWhichPublish.equals(context)){
// stop, this value must be defined
status = Status.BAD_REQUEST;
responseBean.setId(id);
throw new IllegalArgumentException("Status attribute is not defined or the Token you are using is not correct to perform such request!");
}else{
DataCatalogue catalogue = HelperMethods.getDataCatalogueRunningInstance(context);
if(catalogue == null){
status = Status.INTERNAL_SERVER_ERROR;
responseBean.setId(null);
throw new Exception("There was a problem while serving your request");
}else{
// check the user has editor/admin role into the org
String organization = HelperMethods.retrieveOrgNameFromScope(contextInWhichPublish);
if(catalogue.getRoleOfUserInOrganization(username, organization, catalogue.getApiKeyFromUsername(username)).equals(RolesCkanGroupOrOrg.MEMBER)){
status = Status.FORBIDDEN;
responseBean.setId(null);
throw new Exception("You are not authorized to create a product. Please check you have at least the editor role!");
}
// check the record has a name, at least
String futureTitle = record.getStockName();
if(!HelperMethods.isValid(futureTitle)){
status = Status.BAD_REQUEST;
responseBean.setId(null);
throw new Exception("The name requested for the product is not correct! It should contain only alphanumeric characters, and symbols like '.' or '_', '-'");
}else{
logger.debug("Checking if such name [" + futureTitle + "]doesn't exist yet...");
String futureName = UtilMethods.fromProductTitleToName(futureTitle);
logger.info("Transformed name is " + futureName);
boolean alreadyExist = catalogue.existProductWithNameOrId(futureName);
if(alreadyExist){
logger.debug("A product with name " + futureName + " already exists");
responseBean.setId(null);
status = Status.BAD_REQUEST;
throw new Exception("Sorry but a product with such name already exists!");
}else{
// evaluate the tags of the product
List<String> tags = new ArrayList<String>();
HelperMethods.getTags(tags, record);
// evaluate the groups
List<String> groups = new ArrayList<String>();
HelperMethods.getGroups(groups, record);
// evaluate the custom fields
Map<String, String> customFields = new HashMap<String, String>();
if(record.getExtras() != null)
customFields = record.getExtras();
// automatically retrieve the other ones
HelperMethods.getExtras(customFields, record);
// retrieve the user's email and fullname
String authorMail = HelperMethods.getUserEmail(context, SecurityTokenProvider.instance.get());
String authorFullname = HelperMethods.getUserFullname(context, SecurityTokenProvider.instance.get());
if(authorMail == null || authorFullname == null){
logger.debug("Author fullname or mail missing, cannot continue");
responseBean.setId(null);
status = Status.INTERNAL_SERVER_ERROR;
throw new Exception("Sorry but there was not possible to retrieve your fullname/email!");
}else{
// evaluate the resources TODO
List<Resource> resourcesRecord = record.getResources();
List<ResourceBean> resources = null;
if(resourcesRecord != null && !resourcesRecord.isEmpty()){
resources = new ArrayList<ResourceBean>();
for (Resource res : resourcesRecord) {
logger.debug("Trying to add resource " + res);
if(res.getName() != null && res.getUrl() != null)
resources.add(new ResourceBean(res.getUrl(), res.getName(), res.getDescription(), null, username, null, null));
else
logger.warn("Unable to add resource because url or name is null");
}
}
// if confirmed, set to visible TODO anyway if it is confirmed we should another method
boolean setPublic = record.getStatus() == org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Status.Confirmed;
// create the product
id = catalogue.createCKanDataset(
catalogue.getApiKeyFromUsername(username),
futureTitle,
organization,
authorFullname,
authorMail,
record.getMaintainer(),
record.getMaintainerContact(),
record.getVersion(),
record.getDescription(),
record.getLicense(),
tags,
customFields,
resources,
setPublic); // TODO
if(id != null){
logger.info("Product created! Id is " + id);
responseBean.setId(id);
status = Status.CREATED;
responseBean.setError(null);
if(!groups.isEmpty()){
logger.info("Launching thread for association to the list of groups " + groups);
new AssociationToGroupThread(groups, id, organization, username, catalogue).start();
}
}
}
}
}
}
}
}catch(Exception e){
logger.error("Failed to create stock record", e);
status = Status.INTERNAL_SERVER_ERROR;
responseBean.setError(e.toString());
responseBean.setId(id);
responseBean.setError(e.getMessage());
}
return Response.status(status).entity(responseBean).build();
}
}

@ -19,40 +19,51 @@ public class AssociationToGroupThread extends Thread {
private String datasetId;
private String username;
private DataCatalogue catalogue;
private String organizationId;
/**
* @param groupTitle
* @param datasetId
* @param username
* @param organizationId
* @param catalogue
*/
public AssociationToGroupThread(List<String> groupsTitles, String datasetId,
public AssociationToGroupThread(List<String> groupsTitles, String datasetId, String organizationId,
String username, DataCatalogue catalogue) {
this.groupsTitles = groupsTitles;
this.datasetId = datasetId;
this.username = username;
this.catalogue = catalogue;
this.organizationId = organizationId;
}
@Override
public void run() {
logger.info("Association thread started to put the dataset with id="+ datasetId + " into group with title(s) " + groupsTitles + " for user " + username);
String userApiKey = catalogue.getApiKeyFromUsername(username);
// retrieve the role to be assigned according the one the user has into the organization of the dataset
RolesCkanGroupOrOrg role = RolesCkanGroupOrOrg.valueOf(catalogue.getRoleOfUserInOrganization(username, organizationId, catalogue.getApiKeyFromUsername(username)).toUpperCase());
for (String groupTitle : groupsTitles) {
// check the user has enough privileges to associate it
if(catalogue.checkRoleIntoGroup(username, groupTitle, RolesCkanGroupOrOrg.MEMBER)){
logger.warn("The user " + username + " has not enough privileges to associate the dataset into group " + groupTitle);
logger.debug("Setting role " + role + " into group " + groupTitle + " to user " + username);
boolean assigned = catalogue.checkRoleIntoGroup(username, groupTitle, role);
if(!assigned){
logger.warn("The user " + username + " has not enough privileges to associate the dataset into group OR the group doesn't exist" + groupTitle);
continue;
}
else{
boolean putIntoGroup = catalogue.assignDatasetToGroup(groupTitle, datasetId, catalogue.getApiKeyFromUsername(username));
logger.info("Was product put into group? " + putIntoGroup);
boolean putIntoGroup = catalogue.assignDatasetToGroup(groupTitle, datasetId, userApiKey);
logger.info("Was product put into group " + groupTitle + "? " + putIntoGroup);
}
}
}

@ -0,0 +1,73 @@
/**
*
*/
package org.gcube.data_catalogue.grsf_publish_ws.utils;
import static org.gcube.resources.discovery.icclient.ICFactory.client;
import static org.gcube.resources.discovery.icclient.ICFactory.queryFor;
import java.util.List;
import org.gcube.common.resources.gcore.GCoreEndpoint;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.resources.discovery.client.api.DiscoveryClient;
import org.gcube.resources.discovery.client.queries.api.SimpleQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class GcoreEndpointReaderSocialWS {
private static final String resource = "jersey-servlet";
private static final String serviceName = "SocialNetworking";
private static final String serviceClass = "Portal";
private static Logger logger = LoggerFactory.getLogger(GcoreEndpointReaderSocialWS.class);
/**
* Instantiates a new gcore endpoint reader.
*
* @param scope the scope
* @throws Exception the exception
*/
public static String getUrlSocialWS(String scope) throws Exception {
if(scope == null || scope.isEmpty())
throw new IllegalArgumentException();
String oldScope = ScopeProvider.instance.get();
try{
logger.info("set scope "+scope);
ScopeProvider.instance.set(scope);
SimpleQuery query = queryFor(GCoreEndpoint.class);
query.addCondition(String.format("$resource/Profile/ServiceClass/text() eq '%s'",serviceClass));
query.addCondition("$resource/Profile/DeploymentData/Status/text() eq 'ready'");
query.addCondition(String.format("$resource/Profile/ServiceName/text() eq '%s'",serviceName));
query.setResult("$resource/Profile/AccessPoint/RunningInstanceInterfaces//Endpoint[@EntryName/string() eq \""+resource+"\"]/text()");
logger.debug("submitting quey "+query.toString());
DiscoveryClient<String> client = client();
List<String> endpoints = client.submit(query);
if (endpoints == null || endpoints.isEmpty()) throw new Exception("Cannot retrieve the GCoreEndpoint serviceName: "+serviceName +", serviceClass: " +serviceClass +", in scope: "+scope);
String urlFound = endpoints.get(0);
if(urlFound==null)
throw new Exception("Endpoint:"+resource+", is null for serviceName: "+serviceName +", serviceClass: " +serviceClass +", in scope: "+scope);
logger.info("found entyname "+urlFound+" for ckanResource: "+resource);
return urlFound;
}catch(Exception e){
String error = "An error occurred during GCoreEndpoint discovery, serviceName: "+serviceName +", serviceClass: " +serviceClass +", in scope: "+scope +".";
logger.error(error, e);
throw new Exception(error);
}finally{
if(oldScope != null)
ScopeProvider.instance.set(oldScope);
}
}
}

@ -1,18 +1,29 @@
package org.gcube.data_catalogue.grsf_publish_ws.utils;
import java.beans.PropertyDescriptor;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.CustomField;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Group;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Tag;
import org.gcube.data_catalogue.grsf_publish_ws.json.input.Common;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Status;
import org.gcube.datacatalogue.ckanutillibrary.DataCatalogue;
import org.gcube.datacatalogue.ckanutillibrary.DataCatalogueFactory;
import org.gcube.datacatalogue.ckanutillibrary.DataCatalogueImpl;
import org.slf4j.LoggerFactory;
import eu.trentorise.opendata.jackan.internal.org.apache.http.HttpResponse;
import eu.trentorise.opendata.jackan.internal.org.apache.http.client.methods.HttpGet;
import eu.trentorise.opendata.jackan.internal.org.apache.http.impl.client.CloseableHttpClient;
import eu.trentorise.opendata.jackan.internal.org.apache.http.impl.client.HttpClientBuilder;
/**
* Helper methods
@ -22,6 +33,10 @@ public abstract class HelperMethods {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(HelperMethods.class);
// to be retrieved from the web.xml
private static final String PENDING_CONTEX_KEY = "PendingContext";
private static final String CONFIRMED_CONTEX_KEY = "ConfirmedContext";
/**
* Convert a group name to its id on ckan
* @param origName
@ -32,8 +47,13 @@ public abstract class HelperMethods {
if(origName == null)
throw new IllegalArgumentException("origName cannot be null");
return origName.trim().toLowerCase().replaceAll("[^A-Za-z0-9_.]", "_");
String modified = origName.trim().toLowerCase().replaceAll("[^A-Za-z0-9-]", "-");
if(modified.startsWith("-"))
modified = modified.substring(1);
if(modified.endsWith("-"))
modified = modified.substring(0, modified.length() -1);
return modified;
}
/**
@ -43,7 +63,14 @@ public abstract class HelperMethods {
*/
public static DataCatalogue getDataCatalogueRunningInstance(String scope) throws Exception{
return DataCatalogueFactory.getFactory().getUtilsPerScope(scope);
try{
DataCatalogueImpl instance = DataCatalogueFactory.getFactory().getUtilsPerScope(scope);
return instance;
}catch(Exception e){
logger.error("Failed to instanciate data catalogue lib", e);
}
return null;
}
@ -73,7 +100,7 @@ public abstract class HelperMethods {
}
/**
* Retrieve the list of groups for this object
* Retrieve the list of groups' names for this object
*/
public static void getGroups(List<String> groups, Common record){
Class<?> current = record.getClass();
@ -101,7 +128,7 @@ public abstract class HelperMethods {
/**
* Retrieve the list of extras for this object
*/
public static void getExtras(Map<String, Object> extras, Common record){
public static void getExtras(Map<String, String> extras, Common record){
Class<?> current = record.getClass();
do{
Field[] fields = current.getDeclaredFields();
@ -124,4 +151,136 @@ public abstract class HelperMethods {
while((current = current.getSuperclass())!=null);
}
/**
* Retrieve the organization name in which the user wants to publish starting from the scope
* @param contextInWhichPublish
* @return
*/
public static String retrieveOrgNameFromScope(String scope) {
String[] splittedScope = scope.split("/");
return splittedScope[splittedScope.length - 1].toLowerCase();
}
/**
* Return the context in which the user wants to publish by the status information
* @param status
* @param contextServlet
* @return
*/
public static String getContextFromStatus(Status status, ServletContext contextServlet) {
String toReturn = null;
switch(status){
case Confirmed :
toReturn = (String)contextServlet.getInitParameter(CONFIRMED_CONTEX_KEY);
break;
case Pending:
toReturn = (String)contextServlet.getInitParameter(PENDING_CONTEX_KEY);
break;
default: break;
}
logger.debug("Context evaluated is " + toReturn);
return toReturn;
}
/**
* Validate the name the product will have
* @param futureName
* @return
*/
public static boolean isValid(String futureName) {
if(futureName == null || futureName.isEmpty())
return false;
else{
return futureName.matches("[\\sA-Za-z0-9_.-]+");
}
}
/**
* Retrieve the user's email given his/her username
* @param context
* @param token
* @return
* @throws Exception
*/
public static String getUserEmail(String context, String token){
try(CloseableHttpClient client = HttpClientBuilder.create().build();){
String baseUrl = GcoreEndpointReaderSocialWS.getUrlSocialWS(context);
logger.debug("Base url is " + baseUrl);
String url = baseUrl.replace("80", "") + "/users/getUserEmail?gcube-token=" + token;
logger.debug("Request url is " + url);
HttpGet getRequest = new HttpGet(url);
HttpResponse response = client.execute(getRequest);
if (response.getStatusLine().getStatusCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ response.getStatusLine().getStatusCode());
}
BufferedReader br = new BufferedReader(
new InputStreamReader((response.getEntity().getContent())));
String email = "";
String temp = null;
while ((temp = br.readLine()) != null) {
email+= temp;
}
return email;
}catch(Exception e){
logger.error("error while performing post method " + e.toString());
}
return null;
}
/**
* Retrieve the user's fullname given his/her username
* @param context
* @param token
* @return
* @throws Exception
*/
public static String getUserFullname(String context, String token){
try(CloseableHttpClient client = HttpClientBuilder.create().build();){
String baseUrl = GcoreEndpointReaderSocialWS.getUrlSocialWS(context);
logger.debug("Base url is " + baseUrl);
String url = baseUrl.replace("80", "") + "/users/getUserFullname?gcube-token=" + token;
logger.debug("Request url is " + url);
HttpGet getRequest = new HttpGet(url);
HttpResponse response = client.execute(getRequest);
if (response.getStatusLine().getStatusCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ response.getStatusLine().getStatusCode());
}
BufferedReader br = new BufferedReader(
new InputStreamReader((response.getEntity().getContent())));
String fullName = "";
String temp = null;
while ((temp = br.readLine()) != null) {
fullName+= temp;
}
return fullName;
}catch(Exception e){
logger.error("error while performing post method " + e.toString());
}
return null;
}
}

@ -4,7 +4,7 @@
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>Restful Web Application</display-name>
<display-name>GRSF Restful Web App</display-name>
<servlet>
<servlet-name>jersey-servlet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
@ -17,10 +17,24 @@
<servlet-mapping>
<servlet-name>jersey-servlet</servlet-name>
<url-pattern>/*</url-pattern>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<context-param>
<description>Scope of pending products</description>
<param-name>PendingContext</param-name>
<!-- <param-value>/d4science.research-infrastructures.eu/FARM/GRSF</param-value> -->
<param-value>/gcube/devNext/NextNext</param-value>
</context-param>
<context-param>
<description>Scope of confirmed products</description>
<param-name>ConfirmedContext</param-name>
<!-- <param-value>/d4science.research-infrastructures.eu/FARM/GRSFAccepted</param-value> -->
<param-value>/gcube/devNext/NextNext</param-value>
</context-param>
</web-app>

@ -0,0 +1,5 @@
<html>
<body>
<h2>The social networking web service is up and running!</h2>
</body>
</html>

@ -2,7 +2,9 @@ package org.gcube.data_catalogue.grsf_publish_ws;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
@ -14,6 +16,8 @@ import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.CustomField;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Group;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Tag;
import org.gcube.data_catalogue.grsf_publish_ws.json.input.FisheryRecord;
import org.gcube.data_catalogue.grsf_publish_ws.json.input.StockRecord;
import org.gcube.data_catalogue.grsf_publish_ws.utils.HelperMethods;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Abundance_Level;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Source;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Status;
@ -21,8 +25,15 @@ import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Type;
import com.fasterxml.jackson.databind.ObjectMapper;
import eu.trentorise.opendata.jackan.internal.org.apache.http.HttpResponse;
import eu.trentorise.opendata.jackan.internal.org.apache.http.client.methods.HttpGet;
import eu.trentorise.opendata.jackan.internal.org.apache.http.impl.client.CloseableHttpClient;
import eu.trentorise.opendata.jackan.internal.org.apache.http.impl.client.HttpClientBuilder;
public class JTests {
private static final String TEST_TOKEN = "d423aed7-e9e2-424a-b9e7-2bbbd151d9c4-98187548";
//@Test
public void test() throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, IntrospectionException {
@ -105,29 +116,65 @@ public class JTests {
//@Test
public void testJSONMapping() throws IOException{
FisheryRecord recordFishery = new FisheryRecord();
StockRecord recordFishery = new StockRecord();
recordFishery.setType(Type.Fishing_Description);
recordFishery.setDatabaseSources(Source.FIRMS);
recordFishery.setAuthor("Costantino Perciante");
recordFishery.setMaintainer("Costantino Perciante");
recordFishery.setAuthorContact("costantino.perciante@isti.cnr.it");
recordFishery.setStatus(Status.Pending);
recordFishery.setVersion(new Long(10));
HashMap<String, String> extras = new HashMap<String, String>();
extras.put("test1", "testValue");
extras.put("test2", "test2Value");
extras.put("type", "Polygon");
extras.put("coordinates", "[[[2.05827, 49.8625],[2.05827, 55.7447], [-6.41736, 55.7447], [-6.41736, 49.8625], [2.05827, 49.8625]]]");
recordFishery.setExtras(extras);
recordFishery.setVersion(new Long(1));
ObjectMapper mapper = new ObjectMapper();
//Object to JSON in String
String jsonInString = mapper.writeValueAsString(recordFishery);
System.out.println(jsonInString);
// JSON back to object
FisheryRecord converted = mapper.readValue(jsonInString, recordFishery.getClass());
StockRecord converted = mapper.readValue(jsonInString, recordFishery.getClass());
System.out.println(converted);
}
//@Test
public void instanciateGCoreReader() throws Exception{
String baseUrl = org.gcube.data_catalogue.grsf_publish_ws.utils.GcoreEndpointReaderSocialWS.getUrlSocialWS("/gcube/devNext/NextNext");
System.out.println("Base url is " + baseUrl);
try(CloseableHttpClient client = HttpClientBuilder.create().build();){
String url = baseUrl.replace("80", "") + "/users/getUserEmail?gcube-token=" + TEST_TOKEN;
System.out.println("Request url is " + url);
HttpGet getRequest = new HttpGet(url);
HttpResponse response = client.execute(getRequest);
if (response.getStatusLine().getStatusCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ response.getStatusLine().getStatusCode());
}
BufferedReader br = new BufferedReader(
new InputStreamReader((response.getEntity().getContent())));
String output;
System.out.println("Output from Server .... \n");
while ((output = br.readLine()) != null) {
System.out.println(output);
}
System.out.println(response.toString());
}catch(Exception e){
System.err.println("error while performing post method " + e.toString());
}
}
//@Test
public void testFromScopeToOrgName(){
System.out.println("Valid ? " + HelperMethods.isValid("this is not valid"));
// System.out.println(HelperMethods.retrieveOrgNameFromScope("/gcube/devNext/NextNext"));
}
}

Loading…
Cancel
Save