package org.gcube.spatial.data.clients; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import javax.ws.rs.client.Entity; import javax.ws.rs.core.MediaType; import org.gcube.common.clients.Call; import org.gcube.common.gxrest.request.GXWebTargetAdapterRequest; import org.gcube.common.gxrest.response.inbound.GXInboundResponse; import org.gcube.spatial.data.clients.model.ConnectionDescriptor; 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.glassfish.jersey.client.authentication.HttpAuthenticationFeature; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; @Slf4j public abstract class AbstractGenericRESTClient implements GenericLoginClient{ @Getter private ConnectionDescriptor conn; @Setter private String basePath=null; @Setter private MediaType defaultMediaType=MediaType.APPLICATION_JSON_TYPE; private Set> toRegisterClasses=new HashSet>(); private Set toRegisterObjects=new HashSet<>(); protected AbstractGenericRESTClient(ConnectionDescriptor conn) { this.conn=conn; // defaults toRegisterClasses.add(FollowRedirectFilter.class); } protected String getExistsPath() { return conn.getEndpoint(); } @Override public boolean exist() { try { get(getExistsPath()); return true; }catch(IOException e) { log.warn("Unable to check instance "+conn,e); return false; } catch (Exception e) { log.info("Server replied with error. Ignore this if it requires authentication. "+conn,e); return true; } } @Override public ConnectionDescriptor getInstance() { return conn; } public void authenticate(AccessType type) { log.info("Setting access type {} ",type); conn.getCredentials().forEach((Credentials c)->{ if(c.getAccessType().equals(type)) setHTTPBasicAuth(c.getUsername(), c.getPassword()); }); } public void authenticate() { log.info("Setting default access type between credentials {}",conn.getCredentials()); if(conn.getCredentials().size()>0) { Credentials c =conn.getCredentials().get(0); setHTTPBasicAuth(c.getUsername(), c.getPassword()); }else log.info("No credentials found in connection descriptor {} ",conn); }; public void setHTTPBasicAuth(String user,String pwd) { log.info("Setting basic authentication, user : {} ",user); toRegisterObjects.add(HttpAuthenticationFeature.universal(user, pwd)); } protected void register(Class providerClass) { toRegisterClasses.add(providerClass); } protected void register(Object provider) { toRegisterObjects.add(provider); } protected GXWebTargetAdapterRequest resolve() throws UnsupportedEncodingException { GXWebTargetAdapterRequest toReturn =GXWebTargetAdapterRequest.newHTTPSRequest(conn.getEndpoint()); toRegisterClasses.forEach((Class clazz)->{toReturn.register(clazz);}); toRegisterObjects.forEach((Object obj)->{toReturn.register(obj);}); if(basePath!=null) return toReturn.path(basePath); else return toReturn; } protected T makeCall(Call call) throws RemoteException, Exception{ try{ return call.call(resolve()); }catch(RemoteException e) { throw e; }catch(Throwable t) { throw new Exception(t); } } //****** METHODS protected void delete(String path) throws RemoteException,Exception { makeCall(new Call() { public Object call(GXWebTargetAdapterRequest endpoint) throws Exception { return check(resolve().path(path).delete(),null); }; }); } protected void post(String path,Object obj) throws RemoteException,Exception { post(path,Entity.entity(obj, MediaType.APPLICATION_JSON_TYPE)); } protected T post (String path,Entity entity,Class returnClazz,Map queryParams) throws RemoteException,Exception{ return makeCall(new Call() { public T call(GXWebTargetAdapterRequest endpoint) throws Exception { Map actualMap=new HashMap(); queryParams.forEach((String k, Object v)->{ Object[] theArray=null; if(v instanceof Collection) {} else theArray=new Object[] {v}; actualMap.put(k, theArray); }); // for(java.util.Map.Entry e:queryParams.entrySet()) { // String k=e.getKey(); // if(!actualMap.containsKey(k))actualMap. // } return check(endpoint.path(path).queryParams(actualMap).post(entity),returnClazz); }; }); } protected void post(String path,Entity entity)throws RemoteException,Exception{ post(path,entity,null,Collections.emptyMap()); } protected T post(String path,Entity entity,Class returnClazz)throws RemoteException,Exception{ return post(path,entity,returnClazz,Collections.emptyMap()); } protected void put(String path,Object obj) throws Exception { post(path,Entity.entity(obj, MediaType.APPLICATION_JSON_TYPE)); } protected T put(String path,Entity entity,Class returnClazz) throws Exception { return makeCall(new Call() { public T call(GXWebTargetAdapterRequest endpoint) throws Exception { return check(endpoint.path(path).post(entity),returnClazz); }; }); } protected String get(String path) throws Exception { return get(path,String.class); } protected T get(String path, Class clazz) throws Exception { return get(path,clazz,defaultMediaType); } protected T get(String path, Class clazz, String mediaType) throws Exception{ return makeCall(new Call() { public T call(GXWebTargetAdapterRequest endpoint) throws Exception { return check(endpoint.path(path).header("accept",mediaType).get(),clazz); }; }); } protected T get(String path, Class clazz, MediaType type) throws Exception{ return get(path,clazz,type+""); } protected static T check(GXInboundResponse resp, Class clazz) throws RemoteException{ try { log.debug("Checking Response [Status : {}, Msg : {}]",resp.getHTTPCode(),resp.getMessage()); if(!resp.isSuccessResponse()) { RemoteException e=new RemoteException("Error received from server "); e.setRemoteMessage(resp.getMessage()); e.setResponseHTTPCode(resp.getHTTPCode()); e.setContent(resp.getStreamedContentAsString()); throw e; }else { if(clazz==null) return null; if(clazz==String.class) return (T) resp.getStreamedContentAsString(); return resp.tryConvertStreamedContentFromJson(clazz); } }catch(RemoteException e) { throw e; }catch(Exception e1) { log.error("Reporting Remote Exception for ",e1); RemoteException e = new RemoteException("Unable to read response from server.", e1); e.setRemoteMessage(resp.getMessage()); e.setResponseHTTPCode(resp.getHTTPCode()); try{ e.setContent(resp.getStreamedContentAsString()); }catch(IOException e2) { log.error("Error while reading resposne content",e2); } throw e; } } }