Default LC Plugins refactoring

This commit is contained in:
Fabio Sinibaldi 2022-03-29 18:06:09 +02:00
parent e2d728042f
commit 3d6f86ef91
21 changed files with 821 additions and 395 deletions

View File

@ -12,7 +12,10 @@ import org.gcube.application.geoportal.common.model.useCaseDescriptor.UseCaseDes
public interface IndexerPluginInterface extends InitializablePlugin{
public IndexDocumentReport index(IndexDocumentRequest request) throws InvalidPluginRequestException;
public IndexDocumentReport deindex(IndexDocumentRequest request) throws InvalidPluginRequestException;
public Index getIndex(BaseRequest request) throws ConfigurationException;
}

View File

@ -9,4 +9,6 @@ public interface MaterializationPlugin extends InitializablePlugin{
public MaterializationReport materialize(MaterializationRequest request) throws MaterializationException, InvalidPluginRequestException;
public MaterializationReport dematerialize(MaterializationRequest request) throws MaterializationException, InvalidPluginRequestException;
}

View File

@ -0,0 +1,22 @@
package org.gcube.application.cms.plugins.faults;
public class UnrecognizedEventException extends EventException{
public UnrecognizedEventException() {
}
public UnrecognizedEventException(String message) {
super(message);
}
public UnrecognizedEventException(String message, Throwable cause) {
super(message, cause);
}
public UnrecognizedEventException(Throwable cause) {
super(cause);
}
public UnrecognizedEventException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View File

@ -0,0 +1,22 @@
package org.gcube.application.cms.plugins.faults;
public class UnrecognizedStepException extends StepException{
public UnrecognizedStepException() {
}
public UnrecognizedStepException(String message) {
super(message);
}
public UnrecognizedStepException(String message, Throwable cause) {
super(message, cause);
}
public UnrecognizedStepException(Throwable cause) {
super(cause);
}
public UnrecognizedStepException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View File

@ -5,15 +5,11 @@ import lombok.extern.slf4j.Slf4j;
import org.gcube.application.cms.plugins.LifecycleManager;
import org.gcube.application.cms.plugins.PluginManagerInterface;
import org.gcube.application.cms.plugins.faults.*;
import org.gcube.application.cms.plugins.model.StepAccess;
import org.gcube.application.cms.plugins.reports.EventExecutionReport;
import org.gcube.application.cms.plugins.reports.InitializationReport;
import org.gcube.application.cms.plugins.reports.Report;
import org.gcube.application.cms.plugins.reports.StepExecutionReport;
import org.gcube.application.cms.plugins.model.PluginDescriptor;
import org.gcube.application.cms.plugins.reports.*;
import org.gcube.application.cms.plugins.requests.BaseRequest;
import org.gcube.application.cms.plugins.requests.EventExecutionRequest;
import org.gcube.application.cms.plugins.requests.StepExecutionRequest;
import org.gcube.application.cms.serialization.Serialization;
import org.gcube.application.geoportal.common.model.configuration.Configuration;
import org.gcube.application.geoportal.common.model.document.accounting.User;
import org.gcube.application.geoportal.common.model.document.lifecycle.LifecycleInformation;
@ -22,7 +18,8 @@ import org.gcube.application.geoportal.common.model.rest.ConfigurationException;
import org.gcube.application.geoportal.common.model.useCaseDescriptor.HandlerDeclaration;
import org.gcube.application.geoportal.common.utils.ContextUtils;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
@Slf4j
public abstract class AbstractLifeCycleManager extends AbstractPlugin implements LifecycleManager {
@ -30,43 +27,116 @@ public abstract class AbstractLifeCycleManager extends AbstractPlugin implements
@Setter
protected PluginManagerInterface pluginManager;
private Map<String,GuardedStepExecution> registeredSteps=new HashMap<>();
private Map<String,GuardedEventManager> registeredEvent=new HashMap<>();
protected void setEvent(String event,GuardedEventManager m){registeredEvent.put(event,m);}
protected void setStep(String step,GuardedStepExecution e){registeredSteps.put(step,e);}
private GuardedEventManager defaultUpdateManager= new GuardedEventManager() {
@Override
protected EventExecutionReport run() throws Exception {
theReport = validate(theReport);
theReport = setDefault(theReport);
return theReport;
}
};
private GuardedEventManager noOp = new GuardedEventManager() {
@Override
protected EventExecutionReport run() throws Exception {
return theReport;
}
};
public AbstractLifeCycleManager() {
registerEvents();
registerSteps();
}
protected EventExecutionReport onDeleteDocument(EventExecutionReport report) throws ConfigurationException, InvalidPluginRequestException, MaterializationException, EventException {return report;}
protected EventExecutionReport onDeleteFileSet(EventExecutionReport report) throws ConfigurationException, InvalidPluginRequestException, MaterializationException, EventException {return report;}
protected EventExecutionReport onUpdateDocument(EventExecutionReport report){
report = validate(report);
report = setDefault(report);
return report;
}
protected EventExecutionReport onInitDocument(EventExecutionReport report) throws InvalidPluginRequestException {
report = validate(report);
report = setDefault(report);
return report;
}
protected void registerEvents(){
setEvent(EventExecutionRequest.Events.ON_INIT_DOCUMENT, new GuardedEventManager() {
@Override
protected EventExecutionReport run() throws Exception {
return onInitDocument(theReport);
}
});
setEvent(EventExecutionRequest.Events.ON_UPDATE_DOCUMENT, new GuardedEventManager() {
@Override
protected EventExecutionReport run() throws Exception {
return onUpdateDocument(theReport);
}
});
setEvent(EventExecutionRequest.Events.ON_DELETE_DOCUMENT, new GuardedEventManager() {
@Override
protected EventExecutionReport run() throws Exception {
return onDeleteDocument(theReport);
}
});
setEvent(EventExecutionRequest.Events.ON_DELETE_FILESET, new GuardedEventManager() {
@Override
protected EventExecutionReport run() throws Exception {
return onDeleteFileSet(theReport);
}
});
}
protected void registerSteps(){}
protected PluginDescriptor DESCRIPTOR=new PluginDescriptor(";;;", PluginDescriptor.BaseTypes.LIFECYCLE_MANAGER);
@Override
public StepExecutionReport performStep(StepExecutionRequest request) throws StepException, InvalidPluginRequestException, InvalidProfileException, ConfigurationException, InsufficientPrivileges {
log.info("Serving Request {}",request);
StepExecutionReport report=new StepExecutionReport(request);
report.setStatus(Report.Status.OK);
LifecycleInformation info=report.getToSetLifecycleInformation();
info.setLastOperationStatus(LifecycleInformation.Status.OK);
info.setLastInvokedStep(request.getStep());
if(!canInvokeStep(request.getStep(),request.getCaller(),
getConfigurationFromProfile(request.getUseCaseDescriptor())))
throw new InsufficientPrivileges("User is not allowed to invoke "+request.getStep());
if(!registeredSteps.containsKey(request.getStep()))
throw new UnrecognizedStepException(("Invalid Step " + request.getStep()));
LifecycleInformation info=report.getToSetLifecycleInformation();
info.setLastOperationStatus(LifecycleInformation.Status.OK);
info.setLastInvokedStep(request.getStep());
try {
return registeredSteps.get(request.getStep())
.setTheReport(report).execute();
}catch (StepException | InvalidPluginRequestException e){
throw e;
}catch (Throwable t) {
log.error("Unable to perform step " + request.getStep(), t);
String msg = "Unable to execute Step " + request.getStep() + ". Error was " + t.getMessage();
report.setStatus(Report.Status.ERROR);
report.putMessage(msg);
info.setLastOperationStatus(LifecycleInformation.Status.ERROR);
info.addErrorMessage(msg);
}
return report;
}
protected static boolean canInvokeStep(String stepID, User u, HandlerDeclaration config) throws ConfigurationException {
log.debug("Checking if {} can access STEP {}",u,stepID);
log.trace("Config is {}",config);
List l =config.getConfiguration().get("step_access", List.class);
if(l==null|| l.isEmpty()) throw new ConfigurationException("Missing Role management in UCD");
for (Object o : l) {
StepAccess a= Serialization.convert(o,StepAccess.class);
if(a.getStepId().equals(stepID)){
// found step ID
log.trace("Found Step ID declaration {} ",a);
for (String s : a.getRoles()) {
if (u.getRoles().contains(s))
return true;
}
}
}
return false;
protected boolean canInvokeStep(String stepID, User u, HandlerDeclaration config) throws ConfigurationException {
return new RoleManager(config).canInvokeStep(stepID,u);
}
@ -97,6 +167,53 @@ public abstract class AbstractLifeCycleManager extends AbstractPlugin implements
return report;
}
@Override
public PluginDescriptor getDescriptor() {
return DESCRIPTOR;
}
@Override
public EventExecutionReport onEvent(EventExecutionRequest request) throws EventException, InvalidPluginRequestException {
EventExecutionReport report=new EventExecutionReport(request);
TriggeredEvents info = report.getToSetLifecycleInformation().getLastEvent();
try {
if(!registeredEvent.containsKey(request.getEvent()))
throw new UnrecognizedEventException("Unexpected Event "+request.getEvent());
return registeredEvent.get(request.getEvent()).setTheReport(report).execute();
}catch (EventException e){
throw e;
}catch (Throwable t){
log.error("Unable to execute on event "+request.getEvent(),t);
String msg = "Unable to execute on event "+request.getEvent()+". Error was "+t.getMessage();
info.setLastOperationStatus(LifecycleInformation.Status.ERROR);
info.addErrorMessage(msg);
report.setStatus(Report.Status.ERROR);
report.putMessage(msg);
}
return report;
}
/**
* Override this method for programmatic default values management
*
* @param currentReport
* @return
*/
public EventExecutionReport setDefault(EventExecutionReport currentReport){
// Default implementation is no op
return currentReport;
}
public EventExecutionReport validate(EventExecutionReport currentReport){
// Default implementation is no op
return currentReport;
}
@Override
public void shutdown() throws ShutDownException {}
@ -104,17 +221,4 @@ public abstract class AbstractLifeCycleManager extends AbstractPlugin implements
public Configuration getCurrentConfiguration(BaseRequest request) throws ConfigurationException {
return new Configuration();
}
@Override
public EventExecutionReport onEvent(EventExecutionRequest request) throws EventException, InvalidPluginRequestException {
log.info("Executing Event {}",request);
EventExecutionReport report=new EventExecutionReport(request);
TriggeredEvents info=new TriggeredEvents();
info.setEvent(request.getEvent());
info.setLastOperationStatus(LifecycleInformation.Status.OK);
report.setStatus(Report.Status.OK);
report.getToSetLifecycleInformation().addEventReport(info);
return report;
}
}

View File

@ -1,41 +1,33 @@
package org.gcube.application.cms.plugins.implementations;
import com.sun.xml.internal.xsom.impl.scd.Step;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.gcube.application.cms.plugins.IndexerPluginInterface;
import org.gcube.application.cms.plugins.MaterializationPlugin;
import org.gcube.application.cms.plugins.implementations.AbstractLifeCycleManager;
import org.gcube.application.cms.plugins.LifecycleManager;
import org.gcube.application.cms.plugins.faults.*;
import org.gcube.application.cms.plugins.model.PluginDescriptor;
import org.gcube.application.cms.plugins.model.StepAccess;
import org.gcube.application.cms.plugins.reports.*;
import org.gcube.application.cms.plugins.requests.*;
import org.gcube.application.cms.plugins.model.ComparableVersion;
import org.gcube.application.cms.serialization.Serialization;
import org.gcube.application.geoportal.common.model.configuration.Configuration;
import org.gcube.application.geoportal.common.model.configuration.Index;
import org.gcube.application.geoportal.common.model.document.accounting.User;
import org.gcube.application.geoportal.common.model.document.lifecycle.LifecycleInformation;
import org.gcube.application.geoportal.common.model.document.lifecycle.TriggeredEvents;
import org.gcube.application.geoportal.common.model.rest.ConfigurationException;
import org.gcube.application.geoportal.common.model.useCaseDescriptor.HandlerDeclaration;
import org.gcube.application.geoportal.common.utils.Files;
import java.util.ArrayList;
import java.util.List;
@Slf4j
public class Default3PhaseManager extends AbstractLifeCycleManager implements LifecycleManager {
public class Default3PhaseManager extends SimpleLifeCycleManager implements LifecycleManager {
private static class Phases {
public static final String PENDING_APPROVAL="Pending Approval";
public static final String PUBLISHED="PUBLISHED";
public static final String PUBLISHED="Published";
}
private static class STEPS{
public static final String SUBMIT="SUBMIT-FOR-REVIEW";
public static final String REJECT="REJECT-DRAFT";
@ -46,53 +38,186 @@ public class Default3PhaseManager extends AbstractLifeCycleManager implements Li
public static final String NOTES="notes";
}
@Override
protected EventExecutionReport onDeleteDocument(EventExecutionReport report) throws ConfigurationException, InvalidPluginRequestException, MaterializationException, EventException {
report = super.onDeleteDocument(report);
return deIndex(report,getIndexer(),getInternalIndexParams(report.getTheRequest()));
}
protected PluginDescriptor DESCRIPTOR=new PluginDescriptor("DEFAULT-3PHASE", PluginDescriptor.BaseTypes.LIFECYCLE_MANAGER);
@Override
protected EventExecutionReport onDeleteFileSet(EventExecutionReport theReport) throws ConfigurationException, InvalidPluginRequestException, MaterializationException, EventException {
theReport = super.onDeleteFileSet(theReport);
String phase = theReport.getTheRequest().getDocument().getLifecycleInformation().getPhase();
if(phase.equals(Phases.PENDING_APPROVAL))
return index(theReport,getIndexer(),getInternalIndexParams(theReport.getTheRequest()));
if(phase.equals(Phases.PUBLISHED))
return index(theReport,getIndexer(),getPublicIndexParams(theReport.getTheRequest()));
return theReport;
}
@Override
protected void registerSteps() {
// register steps
setStep(STEPS.SUBMIT, new GuardedStepExecution() {
@Override
protected StepExecutionReport run() throws Exception {
if(!theReport.getTheRequest().getDocument().getLifecycleInformation().getPhase().equals(LifecycleInformation.CommonPhases.DRAFT_PHASE))
throw new StepException("Document is not in "+LifecycleInformation.CommonPhases.DRAFT_PHASE+" phase");
// Materialize
theReport = materializeDocument(theReport,getMaterializer(),getMaterializationParameters(theReport.getTheRequest()));
if(theReport.getToSetLifecycleInformation().getLastOperationStatus().equals(LifecycleInformation.Status.OK)){
// Index
theReport = index(theReport,getIndexer(),
getInternalIndexParams(theReport.getTheRequest()));
// setPhase
if(theReport.getToSetLifecycleInformation().getLastOperationStatus().equals(LifecycleInformation.Status.OK))
theReport.getToSetLifecycleInformation().setPhase(Phases.PENDING_APPROVAL);
}
return theReport;
}
});
setStep(STEPS.APPROVE, new GuardedStepExecution() {
@Override
protected StepExecutionReport run() throws Exception {
if(!theReport.getTheRequest().getDocument().getLifecycleInformation().getPhase().equals(Phases.PENDING_APPROVAL))
throw new StepException("Document is not in "+Phases.PENDING_APPROVAL+" phase");
// Index
theReport = index(theReport,getIndexer(),
getPublicIndexParams(theReport.getTheRequest()));
// setPhase
if(theReport.getToSetLifecycleInformation().getLastOperationStatus().equals(LifecycleInformation.Status.OK))
theReport.getToSetLifecycleInformation().setPhase(Phases.PUBLISHED);
return theReport;
}
});
setStep(STEPS.REJECT, new GuardedStepExecution() {
@Override
protected StepExecutionReport run() throws Exception {
if(!theReport.getTheRequest().getDocument().getLifecycleInformation().getPhase().equals(Phases.PENDING_APPROVAL))
throw new StepException("Document is not in "+Phases.PENDING_APPROVAL+" phase");
if(theReport.getToSetLifecycleInformation().getLastOperationStatus().equals(LifecycleInformation.Status.OK))
theReport.getToSetLifecycleInformation().setPhase(LifecycleInformation.CommonPhases.DRAFT_PHASE);
return theReport;
}
});
}
public Default3PhaseManager() {
DESCRIPTOR.setDescription("Default 3-phase lifecycle manager. This plugin supports a simple moderated publication lifecycle.");
DESCRIPTOR.setVersion(new ComparableVersion("1.0.0"));
}
protected static boolean canInvokeStep(String stepID, User u, HandlerDeclaration config) throws ConfigurationException {
List l =config.getConfiguration().get("step_access", List.class);
if(l==null|| l.isEmpty()) throw new ConfigurationException("Missing Role management in UCD");
boolean existingRule=false;
for (Object o : l) {
StepAccess a= Serialization.convert(o, StepAccess.class);
if(a.getStepId().equals(stepID)) {
existingRule = true;
log.trace("Found role {}",a);
for (String role : a.getRoles())
if (u.getRoles().contains(role))
return true;
}
}
if(!existingRule) throw new ConfigurationException("Missing step "+stepID+" access definition");
// nothing matches
return false;
}
// @Override
// public StepExecutionReport performStep(StepExecutionRequest request) throws StepException, InvalidPluginRequestException, InvalidProfileException, ConfigurationException, InsufficientPrivileges {
// StepExecutionReport report = super.performStep(request);
// LifecycleInformation info=report.getToSetLifecycleInformation();
// try {
// if(!canInvokeStep(request.getStep(),request.getCaller(),getConfigurationFromProfile(request.getUseCaseDescriptor())))
// throw new InsufficientPrivileges("Insufficient privileges for executing step "+request.getStep());
//
// MaterializationPlugin plugin;
// IndexerPluginInterface indexerPlugin;
// plugin= (MaterializationPlugin) pluginManager.getById("SDI-Default-Materializer");
// indexerPlugin = (IndexerPluginInterface) pluginManager.getById("SDI-Indexer-Plugin");
//
//
//
// switch (request.getStep()) {
// case STEPS.SUBMIT:{
// //TODO validation
//
// if(!request.getDocument().getLifecycleInformation().getPhase().equals(LifecycleInformation.CommonPhases.DRAFT_PHASE))
// throw new StepException("Document is not in "+LifecycleInformation.CommonPhases.DRAFT_PHASE+" phase");
// //Materialize layers
// MaterializationRequest matReq = new MaterializationRequest(request.getUseCaseDescriptor(),request.getCaller(), request.getContext(), request.getDocument());
//
// matReq.setDocument(request.getDocument());
// matReq.setUseCaseDescriptor(request.getUseCaseDescriptor());
// Document params = new Document();
// String workspace = request.getUseCaseDescriptor().getId() + request.getContext().getId();
// params.put("workspace", Files.fixFilename(workspace));
//
//
// matReq.setCallParameters(params);
// MaterializationReport matRep = plugin.materialize(matReq);
//
//
// report.setResultingDocument(matRep.getResultingDocument());
//
//
// switch(matRep.getStatus()){
// case OK : {
// index(report,indexerPlugin);
// //TODO Optional Notifications
// break;
// }
// case ERROR : {
// info.setLastOperationStatus(LifecycleInformation.Status.ERROR);
// matRep.getMessages().forEach(s -> info.addErrorMessage(s));
// break;
// }
// case WARNING : {
// info.setLastOperationStatus(LifecycleInformation.Status.WARNING);
// matRep.getMessages().forEach(s -> info.addWarningMessage(s));
// break;
// }
// }
//
// }
// break;
// case STEPS.REJECT:{
// if(!request.getDocument().getLifecycleInformation().getPhase().equals(Phases.PENDING_APPROVAL))
// throw new StepException("Document is not in "+Phases.PENDING_APPROVAL+" phase");
// // TODO OPTIONAL Notification
//
// info.setPhase(Phases.PENDING_APPROVAL);
// if(request.getCallParameters()!=null&&request.getCallParameters().containsKey(PARAMETERS.NOTES))
// info.setNotes(request.getCallParameters().getString(PARAMETERS.NOTES));
// break;
// }
//
// case STEPS.APPROVE:{
// // Index-published
// if(!request.getDocument().getLifecycleInformation().getPhase()
// .equals(Phases.PENDING_APPROVAL))
// throw new StepException("Document is not in "+Phases.PENDING_APPROVAL+" phase");
//
// index(report,indexerPlugin);
// break;
// }
//
// default:
// throw new StepException("Invalid Step " + request.getStep());
// }
// }catch (StepException e){
// throw e;
// }catch (Throwable t){
// log.error("Unable to perform step "+request.getStep(),t);
// String msg = "Unable to execute Step "+request.getStep()+". Error was "+t.getMessage();
// report.setStatus(Report.Status.ERROR);
// report.putMessage(msg);
// info.setLastOperationStatus(LifecycleInformation.Status.ERROR);
// info.addErrorMessage(msg);
// }
// return report;
// }
@Override
public Configuration getCurrentConfiguration(BaseRequest req) throws ConfigurationException {
Configuration toReturn = super.getCurrentConfiguration(req);
toReturn.setIndexes(new ArrayList<>());
IndexerPluginInterface indexerPlugin;
indexerPlugin = (IndexerPluginInterface) pluginManager.getById("SDI-Indexer-Plugin");
BaseRequest indexRequest = new BaseRequest(req.getUseCaseDescriptor(),req.getCaller(),req.getContext());
// Info on Public index
try {
indexRequest.setCallParameters(getPublicIndexParams(req));
Index publicIndex = indexerPlugin.getIndex(indexRequest);
publicIndex.put("flag", "public");
toReturn.getIndexes().add(publicIndex);
}catch(ConfigurationException e){
toReturn.addErrorMessage("Unable to gather information on public GIS Centroids Index : "+e.getMessage());
log.error("Unable to gather information on public GIS Centroids Index",e);
}
// Info on internal_index
try {
indexRequest.setCallParameters(getInternalIndexParams(req));
@ -106,7 +231,6 @@ public class Default3PhaseManager extends AbstractLifeCycleManager implements Li
return toReturn;
}
private Document getInternalIndexParams(BaseRequest req){
Document callParameters = new Document();
@ -114,210 +238,4 @@ public class Default3PhaseManager extends AbstractLifeCycleManager implements Li
callParameters.put("indexName",Files.fixFilename(req.getUseCaseDescriptor().getId()+"_internal_"+req.getContext().getName()+"_centroids"));
return callParameters;
}
private Document getPublicIndexParams(BaseRequest req){
Document callParameters = new Document();
callParameters.put("workspace",Files.fixFilename(req.getUseCaseDescriptor().getId()+req.getContext().getName()));
callParameters.put("indexName",Files.fixFilename(req.getUseCaseDescriptor().getId()+req.getContext().getName()+"_centroids"));
return callParameters;
}
@Override
public EventExecutionReport onEvent(EventExecutionRequest request) throws EventException, InvalidPluginRequestException {
EventExecutionReport report=super.onEvent(request);
TriggeredEvents info = report.getToSetLifecycleInformation().getLastEvent();
try {
switch(request.getEvent()){
case EventExecutionRequest.Events.ON_INIT_DOCUMENT:
// Set Defaults as for on update
case EventExecutionRequest.Events.ON_UPDATE_DOCUMENT: {
log.debug("Setting default values..");
report=setDefault(report);
break;
}
case EventExecutionRequest.Events.ON_DELETE_DOCUMENT: {
//DELETE ALL
break;
}
default: throw new EventException("Unexpected Event "+request.getEvent());
}
}catch (EventException e){
throw e;
}catch (Throwable t){
log.error("Unable to execute on event "+request.getEvent(),t);
String msg = "Unable to execute on event "+request.getEvent()+". Error was "+t.getMessage();
info.setLastOperationStatus(LifecycleInformation.Status.ERROR);
info.addErrorMessage(msg);
report.setStatus(Report.Status.ERROR);
report.putMessage(msg);
}
return report;
}
@Override
public StepExecutionReport performStep(StepExecutionRequest request) throws StepException, InvalidPluginRequestException, InvalidProfileException, ConfigurationException, InsufficientPrivileges {
StepExecutionReport report = super.performStep(request);
LifecycleInformation info=report.getToSetLifecycleInformation();
try {
if(!canInvokeStep(request.getStep(),request.getCaller(),getConfigurationFromProfile(request.getUseCaseDescriptor())))
throw new InsufficientPrivileges("Insufficient privileges for executing step "+request.getStep());
MaterializationPlugin plugin;
IndexerPluginInterface indexerPlugin;
plugin= (MaterializationPlugin) pluginManager.getById("SDI-Default-Materializer");
indexerPlugin = (IndexerPluginInterface) pluginManager.getById("SDI-Indexer-Plugin");
switch (request.getStep()) {
case STEPS.SUBMIT:{
//TODO validation
if(!request.getDocument().getLifecycleInformation().getPhase().equals(LifecycleInformation.DRAFT_PHASE))
throw new StepException("Document is not in "+LifecycleInformation.DRAFT_PHASE+" phase");
//Materialize layers
MaterializationRequest matReq = new MaterializationRequest(request.getUseCaseDescriptor(),request.getCaller(), request.getContext(), request.getDocument());
matReq.setDocument(request.getDocument());
matReq.setUseCaseDescriptor(request.getUseCaseDescriptor());
Document params = new Document();
String workspace = request.getUseCaseDescriptor().getId() + request.getContext().getId();
params.put("workspace", Files.fixFilename(workspace));
matReq.setCallParameters(params);
MaterializationReport matRep = plugin.materialize(matReq);
report.setResultingDocument(matRep.getResultingDocument());
switch(matRep.getStatus()){
case OK : {
index(report,indexerPlugin);
//TODO Optional Notifications
break;
}
case ERROR : {
info.setLastOperationStatus(LifecycleInformation.Status.ERROR);
matRep.getMessages().forEach(s -> info.addErrorMessage(s));
break;
}
case WARNING : {
info.setLastOperationStatus(LifecycleInformation.Status.WARNING);
matRep.getMessages().forEach(s -> info.addWarningMessage(s));
break;
}
}
}
break;
case STEPS.REJECT:{
if(!request.getDocument().getLifecycleInformation().getPhase().equals(Phases.PENDING_APPROVAL))
throw new StepException("Document is not in "+Phases.PENDING_APPROVAL+" phase");
// TODO OPTIONAL Notification
info.setPhase(Phases.PENDING_APPROVAL);
if(request.getCallParameters()!=null&&request.getCallParameters().containsKey(PARAMETERS.NOTES))
info.setNotes(request.getCallParameters().getString(PARAMETERS.NOTES));
break;
}
case STEPS.APPROVE:{
// Index-published
if(!request.getDocument().getLifecycleInformation().getPhase()
.equals(Phases.PENDING_APPROVAL))
throw new StepException("Document is not in "+Phases.PENDING_APPROVAL+" phase");
index(report,indexerPlugin);
break;
}
default:
throw new StepException("Invalid Step " + request.getStep());
}
}catch (StepException e){
throw e;
}catch (Throwable t){
log.error("Unable to perform step "+request.getStep(),t);
String msg = "Unable to execute Step "+request.getStep()+". Error was "+t.getMessage();
report.setStatus(Report.Status.ERROR);
report.putMessage(msg);
info.setLastOperationStatus(LifecycleInformation.Status.ERROR);
info.addErrorMessage(msg);
}
return report;
}
private IndexDocumentReport index(StepExecutionReport report,IndexerPluginInterface indexer) throws InvalidPluginRequestException {
StepExecutionRequest request = report.getTheRequest();
LifecycleInformation info=report.getToSetLifecycleInformation();
IndexDocumentRequest indexRequest = new IndexDocumentRequest(
request.getUseCaseDescriptor(),request.getCaller(), request.getContext(),request.getDocument());
indexRequest.setCallParameters(new Document());
if(request.getStep().equals(STEPS.APPROVE)) {
// public index
indexRequest.getCallParameters().putAll(getPublicIndexParams(request));
}
else {
// private index
indexRequest.getCallParameters().putAll(getPublicIndexParams(request));
}
IndexDocumentReport indexReport = indexer.index(indexRequest);
switch(indexReport.getStatus()){
case OK : {
if(request.getStep().equals(STEPS.APPROVE)) {
// public index
info.setPhase(Phases.PUBLISHED);
}
else {
// private index
info.setPhase(Phases.PENDING_APPROVAL);
}
report.setToSetSpatialReference(indexReport.getToSetSpatialReference());
break;
}
case ERROR : {
info.setLastOperationStatus(LifecycleInformation.Status.ERROR);
indexReport.getMessages().forEach(s -> info.addErrorMessage(s));
break;
}
case WARNING : {
info.setLastOperationStatus(LifecycleInformation.Status.WARNING);
indexReport.getMessages().forEach(s -> info.addWarningMessage(s));
break;
}
}
return indexReport;
}
/**
* Override this method for programmatic default values management
*
* @param currentReport
* @return
*/
public EventExecutionReport setDefault(EventExecutionReport currentReport){
// Default implementation is no op
return currentReport;
}
@Override
public PluginDescriptor getDescriptor() {
return DESCRIPTOR;
}
}

View File

@ -0,0 +1,15 @@
package org.gcube.application.cms.plugins.implementations;
import lombok.extern.slf4j.Slf4j;
import org.gcube.application.cms.plugins.faults.EventException;
import org.gcube.application.cms.plugins.faults.InvalidPluginRequestException;
import org.gcube.application.cms.plugins.reports.EventExecutionReport;
import org.gcube.application.cms.plugins.requests.EventExecutionRequest;
import javax.ws.rs.WebApplicationException;
@Slf4j
public abstract class GuardedEventManager extends GuardedExecution<EventExecutionRequest,EventExecutionReport>{
}

View File

@ -0,0 +1,35 @@
package org.gcube.application.cms.plugins.implementations;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.gcube.application.cms.plugins.reports.DocumentHandlingReport;
import org.gcube.application.cms.plugins.requests.BaseExecutionRequest;
@Slf4j
public abstract class GuardedExecution<R extends BaseExecutionRequest,T extends DocumentHandlingReport> {
@Getter
protected T result = null;
protected T theReport;
public T execute() throws Exception {
log.trace("Executing {} ",theReport.getTheRequest());
if(theReport==null) throw new RuntimeException("Unexpected state : request cannot be null");
result = run();
log.trace("Report is {} ",theReport);
return result;
}
public T getResult() {
return result;
}
protected abstract T run() throws Exception;
public GuardedExecution<R, T> setTheReport(T theReport) {
this.theReport = theReport;
return this;
}
}

View File

@ -0,0 +1,7 @@
package org.gcube.application.cms.plugins.implementations;
import org.gcube.application.cms.plugins.reports.StepExecutionReport;
import org.gcube.application.cms.plugins.requests.StepExecutionRequest;
public abstract class GuardedStepExecution extends GuardedExecution<StepExecutionRequest, StepExecutionReport>{
}

View File

@ -0,0 +1,60 @@
package org.gcube.application.cms.plugins.implementations;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.gcube.application.cms.serialization.Serialization;
import org.gcube.application.geoportal.common.model.document.accounting.User;
import org.gcube.application.geoportal.common.model.rest.ConfigurationException;
import org.gcube.application.geoportal.common.model.useCaseDescriptor.HandlerDeclaration;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.HashMap;
import java.util.List;
@Slf4j
public class RoleManager {
HashMap<String,StepAccess> accessMap=new HashMap<>();
public RoleManager(HandlerDeclaration config) throws ConfigurationException {
List l =config.getConfiguration().get("step_access", List.class);
if(l==null|| l.isEmpty()) throw new ConfigurationException("Missing Role management in UCD");
for (Object o : l) {
StepAccess a= Serialization.convert(o, StepAccess.class);
accessMap.put(a.getStepId(),a);
}
}
public boolean canInvokeStep(String stepID,User u) throws ConfigurationException {
if(!accessMap.containsKey(stepID)) throw new ConfigurationException("Missing step "+stepID+" access definition");
for (String role : accessMap.get(stepID).getRoles())
if (u.getRoles().contains(role))
return true;
return false;
}
@XmlRootElement
@AllArgsConstructor
@Getter
@Setter
@ToString(callSuper = true)
public static class StepAccess {
public static final String STEP="STEP";
public static final String ROLES="roles";
@JsonProperty(STEP)
private String stepId;
@JsonProperty(ROLES)
private List<String> roles;
}
}

View File

@ -0,0 +1,238 @@
package org.gcube.application.cms.plugins.implementations;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.gcube.application.cms.plugins.IndexerPluginInterface;
import org.gcube.application.cms.plugins.LifecycleManager;
import org.gcube.application.cms.plugins.MaterializationPlugin;
import org.gcube.application.cms.plugins.faults.*;
import org.gcube.application.cms.plugins.reports.*;
import org.gcube.application.cms.plugins.requests.*;
import org.gcube.application.geoportal.common.model.JSONPathWrapper;
import org.gcube.application.geoportal.common.model.configuration.Configuration;
import org.gcube.application.geoportal.common.model.configuration.Index;
import org.gcube.application.geoportal.common.model.document.filesets.RegisteredFileSet;
import org.gcube.application.geoportal.common.model.document.lifecycle.LifecycleInformation;
import org.gcube.application.geoportal.common.model.rest.ConfigurationException;
import org.gcube.application.geoportal.common.utils.Files;
import java.util.ArrayList;
@Slf4j
public class SimpleLifeCycleManager extends AbstractLifeCycleManager implements LifecycleManager {
@Override
public Configuration getCurrentConfiguration(BaseRequest req) throws ConfigurationException {
Configuration toReturn = super.getCurrentConfiguration(req);
toReturn.setIndexes(new ArrayList<>());
IndexerPluginInterface indexerPlugin;
indexerPlugin = (IndexerPluginInterface) pluginManager.getById("SDI-Indexer-Plugin");
BaseRequest indexRequest = new BaseRequest(req.getUseCaseDescriptor(),req.getCaller(),req.getContext());
// Info on Public index
try {
indexRequest.setCallParameters(getPublicIndexParams(req));
Index publicIndex = indexerPlugin.getIndex(indexRequest);
publicIndex.put("flag", "public");
toReturn.getIndexes().add(publicIndex);
}catch(ConfigurationException e){
toReturn.addErrorMessage("Unable to gather information on public GIS Centroids Index : "+e.getMessage());
log.error("Unable to gather information on public GIS Centroids Index",e);
}
return toReturn;
}
protected Document getPublicIndexParams(BaseRequest req){
Document callParameters = new Document();
callParameters.put("workspace",Files.fixFilename(req.getUseCaseDescriptor().getId()+req.getContext().getName()));
callParameters.put("indexName",Files.fixFilename(req.getUseCaseDescriptor().getId()+req.getContext().getName()+"_centroids"));
return callParameters;
}
protected Document getMaterializationParameters(BaseRequest request){
Document params = new Document();
String workspace = request.getUseCaseDescriptor().getId() + request.getContext().getId();
params.put("workspace", Files.fixFilename(workspace));
return params;
}
@Override
protected void registerSteps() {
setStep("PUBLISH", new GuardedStepExecution() {
@Override
protected StepExecutionReport run() throws Exception {
if(!theReport.getTheRequest().getDocument().getLifecycleInformation().getPhase().equals(LifecycleInformation.CommonPhases.DRAFT_PHASE))
throw new StepException("Document is not in "+LifecycleInformation.CommonPhases.DRAFT_PHASE+" phase");
// Materialize
theReport = materializeDocument(theReport, getMaterializer(),
getMaterializationParameters(theReport.getTheRequest()));
if(theReport.getToSetLifecycleInformation().getLastOperationStatus().equals(LifecycleInformation.Status.OK)){
// Index
theReport = index(theReport,getIndexer(),
getPublicIndexParams(theReport.getTheRequest()));
// setPhase
if(theReport.getToSetLifecycleInformation().getLastOperationStatus().equals(LifecycleInformation.Status.OK))
theReport.getToSetLifecycleInformation().setPhase("PUBLISHED");
}
return theReport;
}
});
}
protected void blockNonDraft(EventExecutionReport report) throws InvalidPluginRequestException {
Boolean force = Boolean.parseBoolean(report.getTheRequest().getMandatory("force"));
if(!report.getTheRequest().getDocument().getLifecycleInformation().getPhase().equals(LifecycleInformation.CommonPhases.DRAFT_PHASE) && ! force)
throw new InvalidPluginRequestException("Document is not in "+LifecycleInformation.CommonPhases.DRAFT_PHASE+" phase");
}
@Override
protected EventExecutionReport onInitDocument(EventExecutionReport report) throws InvalidPluginRequestException {
blockNonDraft(report);
return super.onInitDocument(report);
}
@Override
protected EventExecutionReport onUpdateDocument(EventExecutionReport report) {
return super.onUpdateDocument(report);
}
@Override
protected EventExecutionReport onDeleteDocument(EventExecutionReport report) throws ConfigurationException, InvalidPluginRequestException, MaterializationException, EventException {
// dematerialize all
blockNonDraft(report);
JSONPathWrapper wrapper = new JSONPathWrapper(report.getTheRequest().getDocument().getTheDocument().toJson());
for (String s : wrapper.getMatchingPaths("..*[?(@." + RegisteredFileSet.PAYLOADS + ")]")){
log.info("Requesting dematerialization for {} ",s);
report = deMaterialize(report,getMaterializer(),new Document("fileSetPath",s));
if(!report.getToSetLifecycleInformation().getLastOperationStatus().equals(LifecycleInformation.Status.OK))
break;
}
if(report.getToSetLifecycleInformation().getLastOperationStatus().equals(LifecycleInformation.Status.OK)) {
report = deIndex(report,getIndexer(),getPublicIndexParams(report.getTheRequest()));
}
return report;
}
@Override
protected EventExecutionReport onDeleteFileSet(EventExecutionReport theReport) throws ConfigurationException, InvalidPluginRequestException, MaterializationException, EventException {
// dematerialize selected
blockNonDraft(theReport);
deMaterialize(theReport,getMaterializer(),
theReport.getTheRequest().getCallParameters());
// de index
if(theReport.getToSetLifecycleInformation().getLastOperationStatus().equals(LifecycleInformation.Status.OK))
deIndex(theReport,getIndexer(),getPublicIndexParams(theReport.getTheRequest()));
return theReport;
}
@Override
protected void registerEvents() {
super.registerEvents();
// register events
setEvent(EventExecutionRequest.Events.ON_DELETE_DOCUMENT, new GuardedEventManager() {
@Override
protected EventExecutionReport run() throws Exception {
return onDeleteDocument(theReport);
}
});
setEvent(EventExecutionRequest.Events.ON_DELETE_FILESET, new GuardedEventManager() {
@Override
protected EventExecutionReport run() throws Exception {
return onDeleteFileSet(theReport);
}
});
}
protected IndexerPluginInterface getIndexer() throws ConfigurationException {
return (IndexerPluginInterface) pluginManager.getById("SDI-Indexer-Plugin");
}
protected MaterializationPlugin getMaterializer() throws ConfigurationException {
return (MaterializationPlugin) pluginManager.getById("SDI-Default-Materializer");
}
protected <T extends DocumentHandlingReport> T deIndex(T report, IndexerPluginInterface indexer, Document parameters) throws InvalidPluginRequestException {
BaseExecutionRequest request = report.getTheRequest();
IndexDocumentRequest indexRequest = new IndexDocumentRequest(
request.getUseCaseDescriptor(),request.getCaller(), request.getContext(),request.getDocument());
indexRequest.setCallParameters(parameters);
IndexDocumentReport indexReport = indexer.deindex(indexRequest);
return handleReport(indexReport,report);
}
protected <T extends DocumentHandlingReport> T deMaterialize(T report, MaterializationPlugin plugin, Document parameters) throws InvalidPluginRequestException, MaterializationException {
BaseExecutionRequest request = report.getTheRequest();
MaterializationRequest matReq =
new MaterializationRequest(request.getUseCaseDescriptor(),request.getCaller(), request.getContext(), request.getDocument());
Document params = new Document();
String workspace = request.getUseCaseDescriptor().getId() + request.getContext().getId();
params.put("workspace", Files.fixFilename(workspace));
matReq.setCallParameters(params);
MaterializationReport matRep = plugin.dematerialize(matReq);
return handleReport(matRep,report);
}
protected <T extends DocumentHandlingReport> T index(T report, IndexerPluginInterface indexer, Document parameters) throws InvalidPluginRequestException {
BaseExecutionRequest request = report.getTheRequest();
IndexDocumentRequest indexRequest = new IndexDocumentRequest(
request.getUseCaseDescriptor(),request.getCaller(), request.getContext(),request.getDocument());
indexRequest.setCallParameters(parameters);
IndexDocumentReport indexReport = indexer.index(indexRequest);
return handleReport(indexReport,report);
}
protected <T extends DocumentHandlingReport> T materializeDocument(T report,MaterializationPlugin plugin,Document parameters) throws InvalidPluginRequestException, MaterializationException {
BaseExecutionRequest request = report.getTheRequest();
MaterializationRequest matReq =
new MaterializationRequest(request.getUseCaseDescriptor(),request.getCaller(), request.getContext(), request.getDocument());
matReq.setCallParameters(parameters);
MaterializationReport matRep = plugin.materialize(matReq);
return handleReport(matRep,report);
}
private <T extends DocumentHandlingReport> T handleReport(DocumentHandlingReport toHandle, T toUpdate){
toUpdate.setResultingDocument(toHandle.getResultingDocument());
LifecycleInformation info = toUpdate.getToSetLifecycleInformation();
switch(toHandle.getStatus()){
case OK : {
info.setLastOperationStatus(LifecycleInformation.Status.OK);
if(toHandle instanceof IndexDocumentReport)
toUpdate.setToSetSpatialReference(((IndexDocumentReport)toHandle).getToSetSpatialReference());
break;
}
case ERROR : {
info.setLastOperationStatus(LifecycleInformation.Status.ERROR);
toHandle.getMessages().forEach(s -> info.addErrorMessage(s));
break;
}
case WARNING : {
info.setLastOperationStatus(LifecycleInformation.Status.WARNING);
toHandle.getMessages().forEach(s -> info.addWarningMessage(s));
break;
}
}
return toUpdate;
}
}

View File

@ -1,29 +0,0 @@
package org.gcube.application.cms.plugins.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;
@XmlRootElement
@AllArgsConstructor
@Getter
@Setter
@ToString(callSuper = true)
public class StepAccess {
public static final String STEP="STEP";
public static final String ROLES="roles";
@JsonProperty(STEP)
private String stepId;
@JsonProperty(ROLES)
private List<String> roles;
}

View File

@ -10,6 +10,7 @@ import org.gcube.application.cms.plugins.faults.PluginExecutionException;
import org.gcube.application.cms.plugins.requests.BaseExecutionRequest;
import org.gcube.application.geoportal.common.model.document.Project;
import org.gcube.application.geoportal.common.model.document.lifecycle.LifecycleInformation;
import org.gcube.application.geoportal.common.model.document.temporal.TemporalReference;
@Data
@ -23,6 +24,10 @@ public class DocumentHandlingReport<T extends BaseExecutionRequest> extends Repo
LifecycleInformation toSetLifecycleInformation;
TemporalReference toSetTemporalReference;
Document toSetSpatialReference;
public DocumentHandlingReport(@NonNull T theRequest) throws InvalidPluginRequestException {
theRequest.validate();
this.theRequest = theRequest;
@ -71,6 +76,8 @@ public class DocumentHandlingReport<T extends BaseExecutionRequest> extends Repo
break;
}
}
if(toSetSpatialReference != null) toReturn.setSpatialReference(toSetSpatialReference);
if(toSetTemporalReference != null) toReturn.setTemporalReference(toSetTemporalReference);
return toReturn;
}
}

View File

@ -30,8 +30,6 @@ public class StepExecutionReport extends DocumentHandlingReport<StepExecutionReq
List<StepExecutionRequest> cascadeSteps;
public TemporalReference toSetTemporalReference;
public Document toSetSpatialReference;
public StepExecutionReport addToTriggerEvent(EventExecutionRequest req){
@ -50,8 +48,7 @@ public class StepExecutionReport extends DocumentHandlingReport<StepExecutionReq
@Override
public Project prepareResult() throws JsonProcessingException, PluginExecutionException {
Project toReturn= super.prepareResult();
if(toSetSpatialReference != null) toReturn.setSpatialReference(toSetSpatialReference);
if(toSetTemporalReference != null) toReturn.setTemporalReference(toSetTemporalReference);
return toReturn;
}
}

View File

@ -12,9 +12,10 @@ import org.gcube.application.geoportal.common.model.useCaseDescriptor.UseCaseDes
public class EventExecutionRequest extends BaseExecutionRequest{
public static class Events{
public static final String ON_INIT_DOCUMENT="@@@INIT_DOCUMENT@@";
public static final String ON_UPDATE_DOCUMENT="@@@UPDATE_DOCUMENT@@";
public static final String ON_DELETE_DOCUMENT="@@@DELETE_DOCUMENT@@";
public static final String ON_INIT_DOCUMENT="INIT_DOCUMENT";
public static final String ON_UPDATE_DOCUMENT="UPDATE_DOCUMENT";
public static final String ON_DELETE_DOCUMENT="DELETE_DOCUMENT";
public static final String ON_DELETE_FILESET="DELETE_FILESET";
}
public EventExecutionRequest(@NonNull UseCaseDescriptor useCaseDescriptor, @NonNull User caller, @NonNull Context context, Project document, String event) {

View File

@ -23,6 +23,11 @@ public class DummyPlugin implements LifecycleManager, IndexerPluginInterface, Ma
return new IndexDocumentReport(request);
}
@Override
public IndexDocumentReport deindex(IndexDocumentRequest request) throws InvalidPluginRequestException {
return null;
}
@Override
public Index getIndex(BaseRequest request) throws ConfigurationException {
return new Index("Dummy index");
@ -69,6 +74,11 @@ public class DummyPlugin implements LifecycleManager, IndexerPluginInterface, Ma
return new MaterializationReport(request);
}
@Override
public MaterializationReport dematerialize(MaterializationRequest request) throws MaterializationException, InvalidPluginRequestException {
return null;
}
@Override
public PluginDescriptor getDescriptor() {
return new PluginDescriptor("DUMMY-PLUGIN","DUMMY-TYPE","Dummy","No op plugin", new ComparableVersion("1.0.0"));

View File

@ -10,9 +10,11 @@ import java.util.List;
@Data
public class LifecycleInformation {
public static final class CommonPhases{
public static final String DRAFT_PHASE="DRAFT";
}
//COMMON PHASES
public static final String DRAFT_PHASE="DRAFT";
public static final String PUBLISHED_PHASE="PUBLISHED";
public static final String PHASE="_phase";

View File

@ -26,7 +26,7 @@ public interface MongoManagerI<T> {
// delete
public void delete(String id,boolean force) throws DeletionException, InvalidUserRoleException, ProjectLockedException, ProjectNotFoundException, UnauthorizedAccess, JsonProcessingException;
public void delete(String id,boolean force) throws DeletionException, InvalidUserRoleException, ProjectLockedException, ProjectNotFoundException, UnauthorizedAccess, JsonProcessingException, InvalidLockException;
// get By ID

View File

@ -18,6 +18,7 @@ import org.gcube.application.cms.plugins.faults.InsufficientPrivileges;
import org.gcube.application.cms.plugins.faults.StepException;
import org.gcube.application.cms.plugins.model.PluginDescriptor;
import org.gcube.application.cms.plugins.reports.DocumentHandlingReport;
import org.gcube.application.cms.plugins.reports.EventExecutionReport;
import org.gcube.application.cms.plugins.reports.StepExecutionReport;
import org.gcube.application.cms.plugins.requests.BaseRequest;
import org.gcube.application.cms.plugins.requests.EventExecutionRequest;
@ -218,7 +219,7 @@ public class ProfiledMongoManager extends MongoManager implements MongoManagerI<
LifecycleInformation draftInfo=new LifecycleInformation().cleanState();
draftInfo.setPhase(LifecycleInformation.DRAFT_PHASE);
draftInfo.setPhase(LifecycleInformation.CommonPhases.DRAFT_PHASE);
draftInfo.setLastOperationStatus(LifecycleInformation.Status.OK);
toRegister.setLifecycleInformation(draftInfo);
@ -274,39 +275,39 @@ public class ProfiledMongoManager extends MongoManager implements MongoManagerI<
@Override
public void delete(String id,boolean force) throws DeletionException, InvalidUserRoleException, ProjectLockedException, ProjectNotFoundException, UnauthorizedAccess, JsonProcessingException {
log.debug("Deleting by ID {}, force {}",id,force);
public void delete(String id,boolean force) throws DeletionException, InvalidUserRoleException, ProjectLockedException, ProjectNotFoundException, UnauthorizedAccess, JsonProcessingException, InvalidLockException {
log.info("Deleting by ID {}, force {}",id,force);
Project doc =lock(id,"Deletion { force : "+force+"}");
try {
User u = UserUtils.getCurrent().asInfo().getUser();
final DataAccessPolicy policy = useCaseDescriptor.getMatching(u);
log.info("Registering Fileset for {} [{}] , policy for {} is {} ",id,useCaseDescriptor.getId(),u,policy);
// NB cannot check ownership on returned values, must specify filter
if(policy == null) {
log.warn("No policy found for {}. Returning empty ", u);
throw new InvalidUserRoleException("No policy defined for current user roles " + u.getRoles());
final DataAccessPolicy policy = useCaseDescriptor.getMatching(u);
log.debug("Delete project {} [{}] , policy for {} is {} ", id, useCaseDescriptor.getId(), u, policy);
if (policy == null) throw new InvalidUserRoleException("No policy defined for current user roles " + u.getRoles());
if (!policy.canWrite(doc, u)) throw new UnauthorizedAccess("No edit rights on project " + id);
doc = triggerEvent(doc, EventExecutionRequest.Events.ON_DELETE_DOCUMENT, new Document("force", force));
//Only continue deleting if event was ok
if(doc.getLifecycleInformation().getLastOperationStatus().equals(LifecycleInformation.Status.OK)) {
try {
WorkspaceManager ws = new WorkspaceManager();
// Get All registered Filesets with payloads
JSONPathWrapper wrapper = new JSONPathWrapper(useCaseDescriptor.getSchema().toJson());
for (Object obj : wrapper.getByPath("..*[?(@." + RegisteredFileSet.PAYLOADS + ")]")) {
Document fs = Serialization.asDocument(obj);
log.debug("Deleting {}",obj);
String folderId = fs.getString(RegisteredFileSet.FOLDER_ID);
ws.deleteItem(folderId);
}
}finally {
if(force) super.deleteDoc(asId(id));
}
}
if(!policy.canWrite(doc,u)) throw new UnauthorizedAccess("No edit rights on project "+id);
// TODO INVOKE LIFECYCLE
//if(!force&&isPublished(id)) throw new Exception("Cannot delete published documents. Unpublish it or use force = true");
try{
// TODO CHECK PHASE AND STATUS
// DEINDEX
// DEMATERIALIZE
// DELETE CONTENT
// DELETE ENTRY
throw new DeletionException("IMPLEMENT THIS");
// delete(asId(id), getCollectionName());
}catch(DeletionException e) {
//storing updated - partially deleted
// concessione=onUpdate(concessione);
// replace(asDocumentWithId(concessione), collectionName);
throw e;
}
} catch (ConfigurationException | StorageHubException e) {
log.error("Exception while trying to delete {} [UCID {}]",id,useCaseDescriptor.getId());
throw new DeletionException("Unable to contact Storage ",e);
} finally{
if(doc!=null) unlockAndUpdate(doc);
}
}
@Override
@ -512,9 +513,11 @@ public class ProfiledMongoManager extends MongoManager implements MongoManagerI<
throw new WebApplicationException("Cannot replace repeatable field " + request.getFieldDefinitionPath() + ".", Response.Status.BAD_REQUEST);
// DELETE EXISTING AND PUT
RegisteredFileSet toDelete = Serialization.convert(parent.get(request.getFieldName()), RegisteredFileSet.class);
if (!(toDelete == null) && !(toDelete.isEmpty()))
deleteFileSetRoutine(toDelete, false, ws);
if (!(toDelete == null) && !(toDelete.isEmpty())) {
String path = parentMatchingPath+"."+request.getFieldName();
deleteFileSetRoutine(doc, false, path);
}
RegisteredFileSet fs = prepareRegisteredFileSet(doc.getInfo(), doc.getId(), useCaseDescriptor.getId(), request.getAttributes(), files, storage, ws);
log.debug("Registered Fileset for [ID {} useCaseDescriptor {}] is {} ", fs, doc.getId(), doc.getProfileID());
docWrapper.putElement(parentMatchingPath, request.getFieldName(), fs);
@ -564,44 +567,59 @@ public class ProfiledMongoManager extends MongoManager implements MongoManagerI<
@Override
public Project deleteFileSet(String id, String path, Boolean force) throws ConfigurationException, StorageHubException, JsonProcessingException, DeletionException, EventException, ProjectLockedException, ProjectNotFoundException, InvalidLockException, InvalidUserRoleException, UnauthorizedAccess {
log.info("Deleting Fileset for {} [useCaseDescriptor ID {}], at {} [force {} ]",id, useCaseDescriptor.getId(),path,force);
Project doc = lock(id,"Fileset Deletion");
try {
User u = UserUtils.getCurrent().asInfo().getUser();
final DataAccessPolicy policy = useCaseDescriptor.getMatching(u);
log.info("Registering Fileset for {} [{}] , policy for {} is {} ",id,useCaseDescriptor.getId(),u,policy);
log.debug("Deleting Fileset for {} [{}] , policy for {} is {} ",doc.getId(),useCaseDescriptor.getId(),u,policy);
// NB cannot check ownership on returned values, must specify filter
if(policy == null) {
log.warn("No policy found for {}. Returning empty ", u);
throw new InvalidUserRoleException("No policy defined for current user roles " + u.getRoles());
}
if(!policy.canWrite(doc,u)) throw new UnauthorizedAccess("No edit rights on project "+id);
if(!policy.canWrite(doc,u)) throw new UnauthorizedAccess("No edit rights on project "+doc.getId());
doc.getLifecycleInformation().cleanState();
doc.getLifecycleInformation().cleanState().setLastOperationStatus(LifecycleInformation.Status.OK);
JSONPathWrapper wrapper = new JSONPathWrapper(doc.getTheDocument().toJson());
List<String> matchingPaths = wrapper.getMatchingPaths(path);
if (matchingPaths.isEmpty())
throw new WebApplicationException("No Registered FileSet found at " + path, Response.Status.BAD_REQUEST);
if (matchingPaths.size() > 1)
throw new WebApplicationException("Multiple Fileset (" + matchingPaths.size() + ") matching " + path, Response.Status.BAD_REQUEST);
RegisteredFileSet fs = Serialization.convert(wrapper.getByPath(path), RegisteredFileSet.class);
log.debug("Going to delete {}", fs);
deleteFileSetRoutine(fs, force, new WorkspaceManager());
log.debug("Removing FS from document [ID : ] by path {}", id, path);
wrapper.setElement(path, null);
doc= deleteFileSetRoutine(doc,force,path);
doc = onUpdate(doc);
return doc;
}finally {
return unlockAndUpdate(doc);
}
}
private Project deleteFileSetRoutine(Project doc,Boolean force, String path) throws ConfigurationException, StorageHubException {
JSONPathWrapper wrapper = new JSONPathWrapper(doc.getTheDocument().toJson());
List<String> matchingPaths = wrapper.getMatchingPaths(path);
if (matchingPaths.isEmpty())
throw new WebApplicationException("No Registered FileSet found at " + path, Response.Status.BAD_REQUEST);
if (matchingPaths.size() > 1)
throw new WebApplicationException("Multiple Fileset (" + matchingPaths.size() + ") matching " + path, Response.Status.BAD_REQUEST);
RegisteredFileSet fs = Serialization.convert(wrapper.getByPath(path), RegisteredFileSet.class);
log.debug("Going to delete {}", fs);
doc = triggerEvent(doc,EventExecutionRequest.Events.ON_DELETE_FILESET,new Document("force",force).append("path",path));
// Actually delete only if event was ok
if(doc.getLifecycleInformation().getLastOperationStatus().equals(LifecycleInformation.Status.OK)) {
// Delete from storage
if(fs.getFolderId()!=null) {
log.info("Deleting Fileset Folder ID {} ",fs.getFolderId());
new WorkspaceManager().deleteItem(fs.getFolderId());
}
log.debug("Removing FS from document [ID : ] by path {}", doc.getId(), path);
// Delete from document
wrapper.setElement(path, null);
}
return doc;
}
@Override
public Configuration getConfiguration() throws ConfigurationException{
log.debug("Asking configuration for {} in {} ", useCaseDescriptor.getId(), UserUtils.getCurrent().getContext());
@ -653,6 +671,8 @@ public class ProfiledMongoManager extends MongoManager implements MongoManagerI<
}
private Project step(Project theDocument, String step, Document callParameters) throws InsufficientPrivileges, ConfigurationException {
try {
log.info("[UseCaseDescriptor {}] Invoking Step {} on {}", useCaseDescriptor.getId(), step, getManager().getDescriptor());
@ -768,19 +788,6 @@ public class ProfiledMongoManager extends MongoManager implements MongoManagerI<
}
private static void deleteFileSetRoutine(RegisteredFileSet fs, Boolean force, WorkspaceManager ws) throws DeletionException, StorageHubException {
log.debug("Deleting Registered FS {}");
if(fs.getMaterializations()!=null && !fs.getMaterializations().isEmpty()){
if(!force) throw new DeletionException("Fileset (uuid "+fs.getUUID()+") already materialized. Use force = true");
else throw new RuntimeException("Implement this");
// TODO manager force deletion
// NB handlers for materialization types
}
log.trace("FileSet ID {} : deleting ws folder {}",fs.getUUID(),fs.getFolderId());
if(fs.getPayloads()!=null)
ws.deleteItem(fs.getFolderId());
}
private static Field getFieldDefinition(UseCaseDescriptor useCaseDescriptor, String fieldPath)throws WebApplicationException{
JSONPathWrapper schemaWrapper= new JSONPathWrapper(useCaseDescriptor.getSchema().toJson());

View File

@ -77,7 +77,7 @@ public class LockTests extends BasicServiceTestUnit {
}
@Test
public void testUnlock() throws StepException, EventException, IOException, ProjectNotFoundException, ProjectLockedException, InvalidLockException, DeletionException, ConfigurationException, StorageHubException, StorageException {
public void testUnlock() throws StepException, EventException, IOException, ProjectNotFoundException, ProjectLockedException, InvalidLockException, DeletionException, ConfigurationException, StorageHubException, StorageException, InvalidUserRoleException, UnauthorizedAccess {
assumeTrue(GCubeTest.isTestInfrastructureEnabled());
MongoManagerI<Project> managerInterface = manager;
// create
@ -107,7 +107,7 @@ public class LockTests extends BasicServiceTestUnit {
checkIsLockCleaned(p.getId());
}
private void checkIsLockCleaned(String id) throws ProjectNotFoundException {
private void checkIsLockCleaned(String id) throws ProjectNotFoundException, InvalidUserRoleException, UnauthorizedAccess {
assertNull(manager.getByID(id).getLock());
}
}

View File

@ -153,6 +153,11 @@ public class SDIMaterializerPlugin extends AbstractPlugin implements Materializa
}
}
@Override
public MaterializationReport dematerialize(MaterializationRequest request) throws MaterializationException, InvalidPluginRequestException {
return null;
}
private static final PluginDescriptor DESCRIPTOR=new PluginDescriptor("SDI-Default-Materializer", PluginDescriptor.BaseTypes.MATERIALIZER);
static {
DESCRIPTOR.setDescription("SDI Materializer. " +