408 lines
16 KiB
Java
408 lines
16 KiB
Java
package org.gcube.informationsystem.publisher;
|
|
|
|
import java.io.StringWriter;
|
|
import java.util.Arrays;
|
|
import java.util.HashSet;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.UUID;
|
|
|
|
import javax.xml.ws.soap.SOAPFaultException;
|
|
|
|
import org.gcube.common.clients.stubs.jaxws.JAXWSUtils;
|
|
import org.gcube.common.resources.gcore.Resource;
|
|
import org.gcube.common.resources.gcore.ResourceMediator;
|
|
import org.gcube.common.resources.gcore.Resources;
|
|
import org.gcube.common.resources.gcore.ScopeGroup;
|
|
import org.gcube.common.scope.api.ScopeProvider;
|
|
import org.gcube.common.scope.impl.ScopeBean;
|
|
import org.gcube.common.scope.impl.ScopeBean.Type;
|
|
import org.gcube.informationsystem.publisher.exception.RegistryNotFoundException;
|
|
import org.gcube.informationsystem.publisher.scope.ValidatorProvider;
|
|
import org.gcube.informationsystem.publisher.stubs.registry.RegistryStub;
|
|
import org.gcube.informationsystem.publisher.stubs.registry.faults.CreateException;
|
|
import org.gcube.informationsystem.publisher.stubs.registry.faults.InvalidResourceException;
|
|
import org.gcube.informationsystem.publisher.stubs.registry.faults.ResourceNotAcceptedException;
|
|
import org.gcube.informationsystem.publisher.stubs.registry.faults.UpdateException;
|
|
import org.gcube.informationsystem.publisher.utils.RegistryStubs;
|
|
import org.gcube.informationsystem.publisher.utils.ValidationUtils;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
|
public class RegistryPublisherImpl implements RegistryPublisher {
|
|
|
|
private static final Logger log = LoggerFactory.getLogger(RegistryPublisher.class);
|
|
private static final int REGISTRY_THRESHOLD = 5;
|
|
private RegistryStubs registry;
|
|
/**
|
|
* Used in create operation. If is not null the update on this scope will never be done
|
|
*/
|
|
private String scopeCreated;
|
|
|
|
protected RegistryPublisherImpl(){
|
|
registry=new RegistryStubs();
|
|
};
|
|
|
|
/**
|
|
* The resource is created in the current scope and it is updated in the other scopes that are presents in the resource.
|
|
* If is a VRE scope then in the resource will be added also the VO and INFRA scope if they are not present
|
|
* If is a VO scope then in the resource will be added also the INFRA scope if it is not present
|
|
* @throws RegistryNotFoundException if no service endpoints can be discovered
|
|
* @throws InvalidResourceExceptionwhen the resource type is invalid service.
|
|
* @throws ResourceNotAcceptedException when the resource is not accepted cause it doesn't satisfy a requirement
|
|
* @throws CreateException when something is failed on creation
|
|
*/
|
|
|
|
public < T extends Resource> T create(T resource){
|
|
String scope=ScopeProvider.instance.get();
|
|
T res = internalCreate(resource, scope);
|
|
scopeCreated=scope;
|
|
res=update(res);
|
|
return res;
|
|
}
|
|
|
|
public < T extends Resource> T vosCreate(T resource, List<String> scopes){
|
|
T res = internalVosCreate(resource, scopes);
|
|
return res;
|
|
}
|
|
|
|
private < T extends Resource> T internalVosCreate(T resource, List<String> scopes){
|
|
String currentScope=ScopeProvider.instance.get();
|
|
ValidationUtils.valid("resource", resource);// helper that throws an IllegalArgumentException if resource are null
|
|
ValidationUtils.valid("scopes", scopes);// helper that throws an IllegalArgumentException if scopes are null
|
|
if ((resource.id()== null) || (resource.id().isEmpty())){
|
|
// set id
|
|
String id=UUID.randomUUID().toString();
|
|
log.debug("id generated: "+id);
|
|
ResourceMediator.setId(resource, id);
|
|
}
|
|
|
|
HashSet<String> vosScopes = new HashSet<String>();
|
|
for(String scope: scopes){
|
|
ScopeBean scopeBean = new ScopeBean(scope);
|
|
if(scopeBean.is(Type.VRE))
|
|
vosScopes.add(scopeBean.enclosingScope().toString());
|
|
else vosScopes.add(scope);
|
|
log.debug("[VOCREATE] scope found {}",scope);
|
|
ResourceMediator.setScope(resource, scope);
|
|
}
|
|
|
|
try {
|
|
Resources.validate(resource);
|
|
} catch (Exception e) {
|
|
log.error("the resource is not valid", e);
|
|
throw new IllegalArgumentException("the resource is not valid ", e.getCause());
|
|
}
|
|
|
|
try{
|
|
for (String voScope: vosScopes){
|
|
// if update is calling on create operation and the scope is not equal to create operation scope or if is a simple update operation, try to update it
|
|
log.trace("[VOCREATE] resource "+resource.id()+" update in scope {} with scopes {} ",voScope, resource.scopes().asCollection());
|
|
ScopeProvider.instance.set(voScope);
|
|
//retrieve registry stub
|
|
RegistryStub stub = getRegistryStub();
|
|
createResource(resource, voScope, stub);
|
|
}
|
|
}finally{
|
|
ScopeProvider.instance.set(currentScope);
|
|
}
|
|
log.trace("[VOCREATE] resource created with scopes {}",resource.scopes().asCollection());
|
|
return resource;
|
|
}
|
|
|
|
private < T extends Resource> T internalCreate(T resource, String scope){
|
|
log.trace("registry-publisher: create method");
|
|
|
|
ValidationUtils.valid("resource", resource);// helper that throws an IllegalArgumentException if resource are null
|
|
ValidationUtils.valid("scopes", scope);// helper that throws an IllegalArgumentException if scopes are null
|
|
if(ValidationUtils.isPresent(resource, scope))
|
|
throw new IllegalStateException("The scope "+scope+" is already present in the resource. The create operation can't be performed ");
|
|
log.debug("resource id found: "+resource.id());
|
|
if ((resource.id()== null) || (resource.id().isEmpty())){
|
|
// set id
|
|
String id=UUID.randomUUID().toString();
|
|
log.debug("id generated: "+id);
|
|
ResourceMediator.setId(resource, id);
|
|
}
|
|
// set scope on resource
|
|
log.debug("scope set in resource: {} ",scope);
|
|
ResourceMediator.setScope(resource, scope);
|
|
// check if the scope is compatible with the scopes defined in the resources
|
|
ValidatorProvider.getValidator(resource).checkScopeCompatibility(resource, Arrays.asList(scope));
|
|
// add enclosing scopes to the resource with filtering on GenericResource, RunningIstance, and Service resources
|
|
String type=resource.type().toString();
|
|
|
|
/*
|
|
if((!type.equalsIgnoreCase("GenericResource")) && (!(type.equalsIgnoreCase("RunningInstance"))) && (!(type.equalsIgnoreCase("Service")))){
|
|
ValidationUtils.addEnclosingScopesOnResource(resource, scope);
|
|
}else{
|
|
log.debug(" Resource type: "+type+": for this type of resource there isn't scope promotion");
|
|
}*/
|
|
try {
|
|
Resources.validate(resource);
|
|
} catch (Exception e) {
|
|
log.error("the resource is not valid", e);
|
|
throw new IllegalArgumentException("the resource is not valid ", e.getCause());
|
|
}
|
|
//retrieve registry stub
|
|
RegistryStub stub = getRegistryStub();
|
|
createResource(resource, scope, stub);
|
|
log.trace("resource created in scope {} with scopes {}",scope, resource.scopes().asCollection());
|
|
return resource;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* The resource will be updated on all the scopes that are defined in the resource.
|
|
* If an updating operation fail. It will be repeated with best-effort delivery approach
|
|
* @throws RegistryNotFoundException if no service endpoints can be discovered
|
|
* @throws InvalidResourceException when the resource type is invalid service.
|
|
* @throws ResourceNotAcceptedException when the resource is not accepted cause it doesn't satisfy a requirement
|
|
* @throws CreateException when something is failed on creation
|
|
*/
|
|
public <T extends Resource> T update(T resource){
|
|
log.trace("[UPDATE] update resource with id : "+resource.id());
|
|
String currentScope=ScopeProvider.instance.get();
|
|
ValidationUtils.valid("resource", resource);// helper that throws an IllegalArgumentException if resource are null
|
|
validateScope(resource); // is empty
|
|
try {
|
|
Resources.validate(resource);
|
|
} catch (Exception e) {
|
|
log.error("the resource is not valid", e);
|
|
throw new IllegalArgumentException("the resource is not valid", e);
|
|
}
|
|
// retrieves the scopes on resource
|
|
ScopeGroup<String> scopes=resource.scopes();
|
|
int tries=0;
|
|
try{
|
|
for(String scope: scopes){
|
|
log.debug("[UPDATE] check update operation on scope "+scope);
|
|
// if update is calling on create operation and the scope is not equal to create operation scope or if is a simple update operation, try to update it
|
|
if((scopeCreated == null) || ((scopeCreated!=null) && (!scopeCreated.equals(scope)))){
|
|
log.trace("[UPDATE] resource update in scope {} with scopes {} ",scope, resource.scopes().asCollection());
|
|
ScopeProvider.instance.set(scope);
|
|
registryUpdate(resource, tries);
|
|
tries=0;
|
|
}else{
|
|
log.trace("skip updating on scope "+scopeCreated);
|
|
}
|
|
|
|
}
|
|
}finally{
|
|
scopeCreated=null;
|
|
// reset the scope
|
|
ScopeProvider.instance.set(currentScope);
|
|
}
|
|
return resource;
|
|
}
|
|
|
|
@Override
|
|
public <T extends Resource> T vosUpdate(T resource) {
|
|
log.trace("[VOUPDATE] update resource with id : "+resource.id());
|
|
String currentScope=ScopeProvider.instance.get();
|
|
ValidationUtils.valid("resource", resource);// helper that throws an IllegalArgumentException if resource are null
|
|
validateScope(resource); // is empty
|
|
try {
|
|
Resources.validate(resource);
|
|
} catch (Exception e) {
|
|
log.error("the resource is not valid", e);
|
|
throw new IllegalArgumentException("the resource is not valid", e);
|
|
}
|
|
|
|
HashSet<String> vosScopes = new HashSet<String>();
|
|
int tries=0;
|
|
for(String scope: resource.scopes().asCollection()){
|
|
ScopeBean scopeBean = new ScopeBean(scope);
|
|
if(scopeBean.is(Type.VRE))
|
|
vosScopes.add(scopeBean.enclosingScope().toString());
|
|
else vosScopes.add(scope);
|
|
log.debug("[VOUPDATE] scope found {}",scope);
|
|
}
|
|
|
|
log.debug("[VOUPDATE] scopes in resources {}",resource.scopes().asCollection());
|
|
|
|
try{
|
|
for (String voScope: vosScopes){
|
|
log.debug("[VOUPDATE] check update operation on scope {} ",voScope);
|
|
// if update is calling on create operation and the scope is not equal to create operation scope or if is a simple update operation, try to update it
|
|
if((scopeCreated == null) || ((scopeCreated!=null) && (!scopeCreated.equals(voScope)))){
|
|
log.trace("[VOUPDATE] resource "+resource.id()+" update in scope {} with scopes {} ",voScope, resource.scopes().asCollection());
|
|
ScopeProvider.instance.set(voScope);
|
|
registryUpdate(resource, tries);
|
|
tries=0;
|
|
}else{
|
|
log.trace("[VOUPDATE] skip updating on scope {}",scopeCreated);
|
|
}
|
|
|
|
}
|
|
}finally{
|
|
scopeCreated=null;
|
|
ScopeProvider.instance.set(currentScope);
|
|
}
|
|
return resource;
|
|
}
|
|
|
|
/**
|
|
* The resource will be removed from current scope
|
|
* if the scope is the last scope in the resource, the profile will be deleted from IS else
|
|
* if it is a VRE scope then the profile will be updated without the VRE scope,
|
|
* if it is a VO scope but there is another VRE scope, belong to the VO, defined in the resource then throw IllegalArgumentException
|
|
*
|
|
* @throws IllegalArgumentException if no service endpoints can be discovered or if there is another VRE scope defined in the resource
|
|
*/
|
|
public <T extends Resource> T remove(T resource){
|
|
String currentScope=ScopeProvider.instance.get();
|
|
log.info(" remove resource with id : "+resource.id()+" from scope: "+currentScope);
|
|
ValidationUtils.valid("resource", resource);// helper that throws an IllegalArgumentException if resource are null
|
|
ValidationUtils.valid("scopes", currentScope);// helper that throws an IllegalArgumentException if scopes are null
|
|
validateScope(resource);
|
|
try {
|
|
Resources.validate(resource);
|
|
} catch (Exception e) {
|
|
log.error("the resource is not valid", e);
|
|
throw new IllegalArgumentException("the resource is not valid", e);
|
|
}
|
|
log.info(" remove "+currentScope+" scope from resource "+resource.id());
|
|
ResourceMediator.removeScope(resource, currentScope);
|
|
// retrieves the scopes on resource and update it
|
|
// updateResource(resource, currentScope);
|
|
try{
|
|
updateResourceRemoveOperation(resource, currentScope);
|
|
}catch(Exception e){
|
|
ResourceMediator.setScope(resource, currentScope);
|
|
log.error("exception message: "+e.getMessage());
|
|
throw new RuntimeException(e.getMessage());
|
|
}
|
|
return resource;
|
|
}
|
|
|
|
|
|
private void registryUpdate(Resource resource, int tries){
|
|
log.trace("try to update resource with id: "+resource.id()+" times "+(tries+1)+" on scope: "+ScopeProvider.instance.get());
|
|
try{
|
|
registry.getStubs().update(resource.id(),resource.type().toString(), toXml(resource) );
|
|
}catch(RegistryNotFoundException e){
|
|
throw new IllegalArgumentException(e.getCause());
|
|
}catch(InvalidResourceException e){
|
|
throw new IllegalArgumentException(e.getCause());
|
|
}catch(ResourceNotAcceptedException e){
|
|
throw new IllegalArgumentException(e.getCause());
|
|
}catch(UpdateException e){
|
|
throw new IllegalArgumentException(e.getCause());
|
|
}catch(SOAPFaultException e) {
|
|
log.warn("Failed update resource on "+registry.getEndPoints().get(0)+" times: "+(tries+1));
|
|
if(tries< REGISTRY_THRESHOLD){
|
|
tries++;
|
|
try {
|
|
Thread.sleep(3000);
|
|
} catch (InterruptedException e1) {
|
|
// TODO Auto-generated catch block
|
|
e1.printStackTrace();
|
|
}
|
|
registryUpdate(resource, tries);
|
|
}
|
|
throw new IllegalArgumentException(JAXWSUtils.remoteCause(e));
|
|
}
|
|
}
|
|
|
|
|
|
private String toXml(Resource resource){
|
|
StringWriter writer = new StringWriter();
|
|
Resources.marshal(resource, writer);
|
|
return writer.toString();
|
|
}
|
|
|
|
private void validateScope(Resource resource){
|
|
ValidatorProvider.getValidator(resource).validate(resource);
|
|
}
|
|
|
|
/**
|
|
* If is the last scope on Resource, the resource will be removed else the resource will be updated
|
|
* @param resource
|
|
* @param currentScope
|
|
*/
|
|
private <T extends Resource> void updateResourceRemoveOperation(T resource, String currentScope) {
|
|
if(!isRemoveNeeded(resource, currentScope)){
|
|
updateResource(resource, currentScope);
|
|
}else{ // remove the profile from IC
|
|
log.info("the resource have only the "+currentScope+" scope defined. Remove the resource "+resource.id()+" from IC");
|
|
// if the resource not have any scope, the resource will be removed
|
|
try {
|
|
log.debug("remove from IS scope "+currentScope);
|
|
registry.getStubs().remove(resource.id(), resource.type().toString());
|
|
} catch (Exception e) {
|
|
log.error("the resource can't be removed ", e);
|
|
throw new IllegalArgumentException("the resource can't be removed from scope "+currentScope, e);
|
|
}
|
|
// ScopeBean currentScopeBean=new ScopeBean(currentScope);
|
|
// if(currentScopeBean.is(Type.VRE)){
|
|
// log.debug("remove from resource scope "+currentScopeBean.enclosingScope().toString());
|
|
// ResourceMediator.removeScope(resource, currentScopeBean.enclosingScope().toString());
|
|
// log.debug("remove from resource scope "+currentScope);
|
|
// ResourceMediator.removeScope(resource, currentScope);
|
|
// }else if(currentScopeBean.is(Type.VO)){
|
|
// log.debug("remove from resource scope "+currentScope);
|
|
// ResourceMediator.removeScope(resource, currentScope);
|
|
// }
|
|
updateResource(resource, currentScope);
|
|
}
|
|
}
|
|
|
|
|
|
private <T extends Resource> boolean isRemoveNeeded(T resource, String scope){
|
|
if(ValidationUtils.isCompatibleScopeForRemove(resource, scope)){
|
|
return true;
|
|
}else{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private <T extends Resource> void createResource(T resource, String scope, RegistryStub stub) {
|
|
try{
|
|
log.info("create resource with id "+resource.id()+" in scope: "+scope);
|
|
String type=null;
|
|
type=resource.type().toString();
|
|
log.info("resource type is: "+type);
|
|
if(resource.type().equals("ServiceEndpoint"))
|
|
type="RuntimeResource";
|
|
stub.create(toXml(resource), type);
|
|
}catch(InvalidResourceException e){
|
|
throw new IllegalArgumentException(e.getCause());
|
|
}catch(ResourceNotAcceptedException e){
|
|
throw new IllegalArgumentException(e.getCause());
|
|
}catch(CreateException e){
|
|
throw new IllegalArgumentException(e.getCause());
|
|
}catch(SOAPFaultException e) {
|
|
throw new IllegalArgumentException(JAXWSUtils.remoteCause(e));
|
|
}
|
|
log.info("created resource "+resource.id()+" on scope "+scope);
|
|
}
|
|
|
|
private RegistryStub getRegistryStub() {
|
|
RegistryStub stub=null;
|
|
try{
|
|
stub=registry.getStubs();
|
|
}catch(RegistryNotFoundException e){
|
|
throw new IllegalArgumentException(e.getCause());
|
|
}
|
|
return stub;
|
|
}
|
|
|
|
private <T extends Resource> void updateResource(T resource, String currentScope) {
|
|
ScopeGroup scopes=resource.scopes();
|
|
int tries=0;
|
|
for(Iterator it=scopes.iterator();it.hasNext();){
|
|
String scope=(String)it.next();
|
|
ScopeProvider.instance.set(scope);
|
|
registryUpdate(resource, tries);
|
|
|
|
}
|
|
// reset the scope
|
|
ScopeProvider.instance.set(currentScope);
|
|
}
|
|
|
|
|
|
}
|