Client automatic loading from IS configuration

This commit is contained in:
Fabio Sinibaldi 2021-02-19 12:25:00 +01:00
parent 54b6f156da
commit 79c0533999
15 changed files with 324 additions and 171 deletions

View File

@ -7,7 +7,7 @@ import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import org.gcube.common.clients.Call;
import org.gcube.spatial.data.clients.AbstractGenericClient;
import org.gcube.spatial.data.clients.AbstractGenericRESTClient;
import org.gcube.spatial.data.clients.GenericLoginClient;
import org.gcube.spatial.data.clients.model.ConnectionDescriptor;
import org.gcube.spatial.data.sdi.model.credentials.Credentials;
@ -20,7 +20,7 @@ import org.json.simple.JSONObject;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class GSRESTClientImpl extends AbstractGenericClient implements GSRESTClient,GenericLoginClient{
public class GSRESTClientImpl extends AbstractGenericRESTClient implements GSRESTClient,GenericLoginClient{
private static final String API_BASE_PATH="rest";
@ -29,11 +29,11 @@ public class GSRESTClientImpl extends AbstractGenericClient implements GSRESTCli
private static final String STYLES_BASE_PATH="styles";
private static final String LAYERS_BASE_PATH="layers";
protected GSRESTClientImpl(ConnectionDescriptor conn) {
public GSRESTClientImpl(ConnectionDescriptor conn) {
super(conn);
// localhost:8080/geoserver/rest
// register(providerClass);
// getClient().
setBasePath(API_BASE_PATH);
log.info("Connecting to GS @ "+conn.getEndpoint());
Credentials cr=conn.getCredentials().get(0);

View File

@ -1,24 +1,25 @@
package org.gcube.spatial.data.clients.geoserver;
import org.gcube.spatial.data.clients.AbstractGenericClient;
import org.gcube.spatial.data.clients.SDIGenericClient;
import org.gcube.spatial.data.clients.model.ClientInfo;
import org.gcube.spatial.data.clients.model.ConnectionDescriptor;
import org.gcube.spatial.data.clients.model.engine.Engine;
import org.gcube.spatial.data.clients.model.engine.Range;
public class GeoServerClient implements SDIGenericClient{
public class GeoServerClient extends AbstractGenericClient implements SDIGenericClient{
public GeoServerClient() {
super(GSRESTClientImpl.class);
}
@Override
public ClientInfo getInfo() {
return new ClientInfo("gs-rest", "GeoServer REST", "GeoServer REST client", "come class",
new Engine(Engine.GS_ENGINE, "Default GeoServerVersion", new Range("2.0.0", null)));
}
@Override
public GSRESTClient getRESTClient(ConnectionDescriptor conn) {
return new GSRESTClientImpl(conn);
}
}

View File

@ -1,6 +1,9 @@
package org.gcube.spatial.data.clients.geoserver;
import org.gcube.spatial.data.clients.model.ConnectionDescriptor;
import org.gcube.spatial.data.clients.model.engine.Engine;
import org.gcube.spatial.data.sdi.model.credentials.AccessType;
import org.gcube.spatial.data.sdi.model.credentials.Credentials;
import org.gcube.spatial.data.sdi.model.faults.RemoteException;
import org.junit.BeforeClass;
import org.junit.Test;
@ -14,14 +17,28 @@ public class GSTests {
// String sdiHostname="sdi-d-d4s.d4science.org";
static String scope = "/gcube/devsec/devVRE";
static ConnectionDescriptor desc;
@BeforeClass
public static void gatherCredentials() {
desc=new ConnectionDescriptor("https://geoserver1.dev.d4science.org/geoserver");
desc.add(new Credentials("admin", "GS-d3v-98751", AccessType.ADMIN));
}
@BeforeClass
public static void setScope(){
TokenSetter.set(scope);
// TokenSetter.set(scope);
}
@Test
public void getWS() throws RemoteException, Exception {
System.out.println(new GSRESTClientImpl(new ConnectionDescriptor("https://geoserver1.dev.d4science.org/geoserver/rest")).getWorkspaces());
public void gets() throws RemoteException, Exception {
// System.out.println(new GSRESTClientImpl(new ConnectionDescriptor("https://geoserver1.dev.d4science.org/geoserver/rest")).getWorkspaces());
GSRESTClient client=new GSRESTClientImpl(desc);
System.out.println(client.getStyles());
System.out.println(client.getWorkspaces());
}

View File

@ -1,147 +1,34 @@
package org.gcube.spatial.data.clients;
import java.lang.reflect.InvocationTargetException;
import java.io.IOException;
import java.util.Set;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.gcube.common.clients.Call;
import org.gcube.spatial.data.clients.model.ClientInfo;
import org.gcube.spatial.data.clients.model.ConnectionDescriptor;
import org.gcube.spatial.data.sdi.model.faults.RemoteException;
import org.gcube.spatial.data.sdi.model.metadata.TemplateDescriptor;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.ClientProperties;
import org.json.simple.JSONObject;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
public abstract class AbstractGenericClient implements SDIGenericClient {
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public abstract class AbstractGenericClient {
private static ObjectMapper mapper = new ObjectMapper();
static {
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS,false);
mapper.configure(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS, false);
mapper.setSerializationInclusion(Include.NON_NULL);
}
@Getter
private ClientConfig config=new ClientConfig();
private ConnectionDescriptor conn;
private Class<?> restClientClass;
private Client client;
public AbstractGenericClient(Class<?> clazz) {
this.restClientClass=clazz;
}
protected AbstractGenericClient(ConnectionDescriptor conn) {
@Override
public Object getRESTClient() {
try {
return restClientClass.getConstructor(ConnectionDescriptor.class).newInstance(conn);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException e) {
throw new RuntimeException("Unable to instantiate class "+restClientClass,e);
}
}
@Override
public SDIGenericClient at(ConnectionDescriptor conn) {
this.conn=conn;
config.register(AuthorizationFilter.class);
}
protected void register(Class<?> providerClass) {
config.register(providerClass);
client=null;
}
protected void register(Object provider) {
config.register(provider);
client=null;
}
public Client getClient() {
if(client==null) {
client = ClientBuilder.newClient(config)
.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
}
return client;
}
protected WebTarget resolve() {
return getClient().target(conn.getEndpoint());
}
protected <T> T makeCall(Call<WebTarget, T> call) throws Exception{
try{
return call.call(resolve());
}catch(RemoteException e) {
throw e;
}catch(Throwable t) {
throw new Exception(t);
}
}
protected JSONObject get(String path) throws Exception {
return get(path,JSONObject.class);
}
protected void delete(String path) throws Exception {
check(resolve().path(path).request(MediaType.APPLICATION_JSON).delete(),null);
}
protected void post(String path,Entity<?> entity)throws Exception{
post(path,entity,null);
}
protected <T> T post(String path,Entity<?> entity,Class<T> returnClazz) throws Exception {
return makeCall(new Call<WebTarget, T>() {
public T call(WebTarget endpoint) throws Exception {
return check(endpoint.path(path).request(MediaType.APPLICATION_JSON).
post(entity),returnClazz);
};
});
}
protected <T> T get(String path, Class<T> clazz) throws Exception{
return makeCall(new Call<WebTarget, T>() {
public T call(WebTarget endpoint) throws Exception {
return check(endpoint.path(path).request(MediaType.APPLICATION_JSON).get(),clazz);
};
});
}
protected static <T> T check(Response resp, Class<T> clazz) throws RemoteException{
if(resp.getStatus()<200||resp.getStatus()>=300) {
String remoteMessage=resp.readEntity(String.class);
Integer httpCode=resp.getStatus();
RemoteException e=new RemoteException("RESP STATUS IS "+httpCode+". Message : "+remoteMessage);
e.setRemoteMessage(remoteMessage);
e.setResponseHTTPCode(httpCode);
throw e;
}else {
if(clazz==null) return null;
String respString=resp.readEntity(String.class);
if(clazz==String.class) return (T) respString;
try {
return mapper.readValue(respString, clazz);
} catch (IOException e) {
throw new RemoteException("Unable to parse response from Zenodo. Content was : \n "+respString,e);
}
}
return this;
}
}

View File

@ -0,0 +1,153 @@
package org.gcube.spatial.data.clients;
import java.io.IOException;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.gcube.common.clients.Call;
import org.gcube.spatial.data.clients.model.ConnectionDescriptor;
import org.gcube.spatial.data.sdi.model.faults.RemoteException;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.ClientProperties;
import org.json.simple.JSONObject;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public abstract class AbstractGenericRESTClient {
private static ObjectMapper mapper = new ObjectMapper();
static {
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS,false);
mapper.configure(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS, false);
mapper.setSerializationInclusion(Include.NON_NULL);
}
@Getter
private ClientConfig config=new ClientConfig();
private ConnectionDescriptor conn;
private Client client;
@Setter
private String basePath=null;
protected AbstractGenericRESTClient(ConnectionDescriptor conn) {
this.conn=conn;
config.register(AuthorizationFilter.class);
}
protected void register(Class<?> providerClass) {
config.register(providerClass);
client=null;
}
protected void register(Object provider) {
config.register(provider);
client=null;
}
public Client getClient() {
if(client==null) {
client = ClientBuilder.newClient(config)
.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
}
return client;
}
protected WebTarget resolve() {
WebTarget toReturn =getClient().target(conn.getEndpoint());
if(basePath!=null) return toReturn.path(basePath);
else return toReturn;
}
protected <T> T makeCall(Call<WebTarget, T> call) throws Exception{
try{
return call.call(resolve());
}catch(RemoteException e) {
throw e;
}catch(Throwable t) {
throw new Exception(t);
}
}
protected JSONObject get(String path) throws Exception {
return get(path,JSONObject.class);
}
protected void delete(String path) throws Exception {
check(resolve().path(path).request(MediaType.APPLICATION_JSON).delete(),null);
}
protected void post(String path,Entity<?> entity)throws Exception{
post(path,entity,null);
}
protected <T> T post(String path,Entity<?> entity,Class<T> returnClazz) throws Exception {
return makeCall(new Call<WebTarget, T>() {
public T call(WebTarget endpoint) throws Exception {
return check(endpoint.path(path).request(MediaType.APPLICATION_JSON).
post(entity),returnClazz);
};
});
}
protected <T> T get(String path, Class<T> clazz) throws Exception{
return makeCall(new Call<WebTarget, T>() {
public T call(WebTarget endpoint) throws Exception {
return check(endpoint.path(path).request(MediaType.APPLICATION_JSON).get(),clazz);
};
});
}
protected static <T> T check(Response resp, Class<T> clazz) throws RemoteException{
if(resp.getStatus()<200||resp.getStatus()>=300) {
String remoteMessage=resp.readEntity(String.class);
Integer httpCode=resp.getStatus();
RemoteException e=new RemoteException("RESP STATUS IS "+httpCode+". Message : "+remoteMessage);
e.setRemoteMessage(remoteMessage);
e.setResponseHTTPCode(httpCode);
throw e;
}else {
if(clazz==null) return null;
String respString=resp.readEntity(String.class);
if(clazz==String.class) return (T) respString;
try {
return mapper.readValue(respString, clazz);
} catch (IOException e) {
throw new RemoteException("Unable to parse response from Zenodo. Content was : \n "+respString,e);
}
}
}
}

View File

@ -3,7 +3,7 @@ package org.gcube.spatial.data.clients;
import org.gcube.spatial.data.clients.model.ConnectionDescriptor;
import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
public class TestClient extends AbstractGenericClient{
public class TestClient extends AbstractGenericRESTClient{

View File

@ -1,13 +1,48 @@
package org.gcube.spatial.data.clients;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.gcube.spatial.data.clients.model.ConnectionDescriptor;
import org.gcube.spatial.data.clients.model.engine.Engine;
import org.gcube.spatial.data.sdi.model.faults.RemoteException;
import org.junit.BeforeClass;
import org.junit.Test;
public class Tests {
// static String sdiHostname="sdi-t.pre.d4science.org";
// static String scope ="/pred4s/preprod/preVRE";
//
static String basePath="";
static String scope = "/gcube/devsec/devVRE";
static ConnectionDescriptor DEV_SDI=new ConnectionDescriptor("https://sdi.d4science.org/sdi-service/gcube/service/");
static ConnectionDescriptor DEV_GS=new ConnectionDescriptor("https://geoserver1.dev.d4science.org/geoserver/rest");
@BeforeClass
public static void setScope(){
TokenSetter.set(scope);
}
@Test
public void testContext() throws RemoteException, Exception {
new TestClient(DEV_SDI).get("SDI");
}
@Test
public void testBasicAuth() throws RemoteException, Exception {
TestClient c=new TestClient(DEV_GS);
c.setHttpBasicAuth("admin", "GS-d3v-98751");
c.get("workspaces");
}
}

View File

@ -2,14 +2,19 @@ package org.gcube.spatial.data.clients;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.ServiceLoader;
import org.gcube.spatial.data.clients.model.ClientInfo;
import org.gcube.spatial.data.clients.model.ConnectionDescriptor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class SDIClientManager {
private Collection<SDIGenericClient> clients=new ArrayList<SDIGenericClient>();
private List<SDIGenericClient> clients=new ArrayList<SDIGenericClient>();
public SDIClientManager() {
ServiceLoader.load(SDIGenericClient.class).forEach((SDIGenericClient c)->{clients.add(c);});
@ -36,4 +41,25 @@ public class SDIClientManager {
}
return null;
}
/**
* Returns the implementation for the target engine's Connection. Null if no suitable plugin is found
*
* @param engine
* @param version
* @return
* @throws Exception
*/
public SDIGenericClient get(ConnectionDescriptor conn) throws Exception {
SDIGenericClient toReturn=get(conn.getEngineUniqueID(),conn.getVersion());
if(toReturn==null) throw new Exception("Unable to get client for "+conn.getEngineUniqueID()+" "+conn.getVersion());
return toReturn.at(conn);
}
public List<ClientInfo> list(){
List<ClientInfo> toReturn=new ArrayList<ClientInfo>();
clients.forEach((SDIGenericClient c)->{toReturn.add(c.getInfo());});
return toReturn;
}
}

View File

@ -8,8 +8,8 @@ public interface SDIGenericClient {
public ClientInfo getInfo();
public Object getRESTClient(ConnectionDescriptor conn);
public Object getRESTClient();
public SDIGenericClient at(ConnectionDescriptor conn);
}

View File

@ -17,4 +17,7 @@ public class ConnectionDescriptor {
@Delegate
private List<Credentials> credentials=new ArrayList<Credentials>();
private String engineUniqueID;
private String version;
}

View File

@ -4,6 +4,8 @@ import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import org.gcube.spatial.data.clients.model.engine.ComparableVersion;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;
@ -26,4 +28,8 @@ public class Version {
public Version(Integer maj,Integer min, Integer build){
this(maj.shortValue(),min.shortValue(),build.shortValue());
}
public ComparableVersion asComparable() {
return new ComparableVersion(major+"."+minor+"."+build);
}
}

View File

@ -4,6 +4,8 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.gcube.spatial.data.clients.SDIClientManager;
import org.gcube.spatial.data.clients.model.ConnectionDescriptor;
import org.gcube.spatial.data.clients.model.engine.ComparableVersion;
import org.gcube.spatial.data.clients.model.engine.Range;
import org.junit.Test;

View File

@ -18,7 +18,12 @@ public class DumbGNClient implements SDIGenericClient{
}
@Override
public Object getRESTClient(ConnectionDescriptor conn) {
public Object getRESTClient() {
// TODO Auto-generated method stub
return null;
}
@Override
public SDIGenericClient at(ConnectionDescriptor conn) {
// TODO Auto-generated method stub
return null;
}

View File

@ -8,6 +8,8 @@ import org.gcube.common.clients.delegates.ProxyDelegate;
import org.gcube.spatia.data.model.profiles.ApplicationProfile;
import org.gcube.spatial.data.clients.SDIClientManager;
import org.gcube.spatial.data.clients.SDIGenericClient;
import org.gcube.spatial.data.clients.model.ClientInfo;
import org.gcube.spatial.data.clients.model.ConnectionDescriptor;
import org.gcube.spatial.data.clients.model.engine.Engine;
import org.gcube.spatial.data.sdi.interfaces.SDIManagement;
import org.gcube.spatial.data.sdi.model.ScopeConfiguration;
@ -21,15 +23,19 @@ import lombok.extern.slf4j.Slf4j;
public class DefaultSDIManagement implements SDIManagement{
private final ProxyDelegate<WebTarget> delegate;
private SDIClientManager clientManager=new SDIClientManager();
private SDIClientManager clientManager=null;
public DefaultSDIManagement(ProxyDelegate<WebTarget> delegate) {
this.delegate=delegate;
clientManager=new SDIClientManager();
log.debug("Available clients are ");
clientManager.list().forEach((ClientInfo c)->{
log.debug("{}",c);
});
}
@Override
public ScopeConfiguration getConfiguration() throws RemoteException {
Call<WebTarget, ScopeConfiguration> call=new Call<WebTarget,ScopeConfiguration>(){
@ -44,7 +50,7 @@ public class DefaultSDIManagement implements SDIManagement{
throw new RemoteException(e);
}
}
@Override
public HealthReport getReport() throws RemoteException {
Call<WebTarget, HealthReport> call=new Call<WebTarget,HealthReport>(){
@ -59,8 +65,8 @@ public class DefaultSDIManagement implements SDIManagement{
throw new RemoteException(e);
}
}
@Override
public ApplicationProfile getProfile(String serviceClass,String serviceName) throws RemoteException {
Call<WebTarget, ApplicationProfile> call=new Call<WebTarget,ApplicationProfile>(){
@ -76,14 +82,14 @@ public class DefaultSDIManagement implements SDIManagement{
throw new RemoteException(e);
}
}
@Override
public SDIGenericClient getClientByEngineId(String engineId) throws Exception {
ScopeConfiguration conf=getConfiguration();
GeoServiceDescriptor desc=null;
log.info("Looking for {} under {} ",engineId,conf.getContextName());
switch (engineId) {
case Engine.GN_ENGINE:
if(conf.getGeonetworkConfiguration().size()>0)
@ -100,10 +106,17 @@ public class DefaultSDIManagement implements SDIManagement{
default:
break;
}
if(desc==null) throw new Exception("No "+engineId+" available in current context. Check ScopeConfiguration object.");
else log.info("Getting client for "+desc);
return clientManager.get(engineId, desc.getVersion().toString());
SDIGenericClient c=clientManager.get(engineId, desc.getVersion().asComparable().getCanonical());
if(c==null) throw new RuntimeException("No implementation available for "+engineId +":"+desc.getVersion().asComparable().getCanonical());
ConnectionDescriptor conn=new ConnectionDescriptor(desc.getBaseEndpoint());
conn.addAll(desc.getAccessibleCredentials());
log.debug("Setting defult connection {}",conn);
return c.at(conn);
}
}

View File

@ -2,6 +2,7 @@ package org.gcube.spatial.data.sdi;
import java.net.MalformedURLException;
import org.gcube.spatial.data.clients.geoserver.GSRESTClient;
import org.gcube.spatial.data.clients.model.engine.Engine;
import org.gcube.spatial.data.sdi.interfaces.SDIManagement;
import org.gcube.spatial.data.sdi.model.faults.RemoteException;
@ -28,5 +29,9 @@ public class SDITests extends BasicScopedTests{
public void getGS() throws Exception {
System.out.println(
SDIAbstractPlugin.management().build().getClientByEngineId(Engine.GS_ENGINE).getInfo());
GSRESTClient gs=(GSRESTClient) SDIAbstractPlugin.management().build().getClientByEngineId(Engine.GS_ENGINE).getRESTClient();
gs.getWorkspaces();
}
}