diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..fae1a2b --- /dev/null +++ b/.classpath @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..be24b5f --- /dev/null +++ b/.project @@ -0,0 +1,23 @@ + + + resource-registry-schema-client + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..29abf99 --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/main/resources=UTF-8 +encoding//src/test/java=UTF-8 +encoding//src/test/resources=UTF-8 +encoding/=UTF-8 diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..714351a --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..2b7e3c3 --- /dev/null +++ b/pom.xml @@ -0,0 +1,96 @@ + + 4.0.0 + + org.gcube.tools + maven-parent + 1.0.0 + + org.gcube.information-system + resource-registry-schema-client + 1.0.0-SNAPSHOT + Resource Registry Schema Client + Contains Non Idempotent API to manage Schemas in Resource Registry + + + UTF-8 + ${project.basedir}/distro + InformationSystem + + + + scm:https://svn.d4science.research-infrastructures.eu/gcube/trunk/information-system/${project.artifactId} + scm:https://svn.d4science.research-infrastructures.eu/gcube//trunk/information-system/${project.artifactId} + https://svn.d4science.research-infrastructures.eu/gcube/trunk/information-system/${project.artifactId} + + + + + + org.gcube.distribution + gcube-bom + LATEST + pom + import + + + org.gcube.information-system + information-system-bom + LATEST + pom + import + + + + + + + org.gcube.common + authorization-client + + + org.gcube.resources.discovery + ic-client + + + org.gcube.information-system + resource-registry-api + [1.0.0-SNAPSHOT, 2.0.0-SNAPSHOT) + + + org.gcube.information-system + information-system-model + + + org.slf4j + slf4j-api + + + + junit + junit + 4.11 + test + + + ch.qos.logback + logback-classic + 1.0.13 + test + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + make-servicearchive + package + + + + + + \ No newline at end of file diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/context/ResourceRegistrySchemaClient.java b/src/main/java/org/gcube/informationsystem/resourceregistry/context/ResourceRegistrySchemaClient.java new file mode 100644 index 0000000..2410751 --- /dev/null +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/context/ResourceRegistrySchemaClient.java @@ -0,0 +1,29 @@ +package org.gcube.informationsystem.resourceregistry.context; + +import java.util.List; + +import org.gcube.informationsystem.model.ISManageable; +import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException; +import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.SchemaException; +import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.SchemaNotFoundException; +import org.gcube.informationsystem.types.TypeBinder.TypeDefinition; + +/** + * @author Luca Frosini (ISTI - CNR) + */ +public interface ResourceRegistrySchemaClient { + + public TypeDefinition create(Class clazz) + throws SchemaException, ResourceRegistryException; + + public String create(String typeDefinitition) + throws SchemaException, ResourceRegistryException; + + + public List read(Class clazz, Boolean polymorphic) + throws SchemaNotFoundException, ResourceRegistryException; + + public String read(String type, Boolean polymorphic) + throws SchemaNotFoundException, ResourceRegistryException; + +} diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/context/ResourceRegistrySchemaClientFactory.java b/src/main/java/org/gcube/informationsystem/resourceregistry/context/ResourceRegistrySchemaClientFactory.java new file mode 100644 index 0000000..7b5669a --- /dev/null +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/context/ResourceRegistrySchemaClientFactory.java @@ -0,0 +1,127 @@ +package org.gcube.informationsystem.resourceregistry.context; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import org.gcube.common.authorization.library.provider.SecurityTokenProvider; +import org.gcube.common.resources.gcore.GCoreEndpoint; +import org.gcube.common.resources.gcore.ServiceEndpoint; +import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.informationsystem.resourceregistry.api.Constants; +import org.gcube.resources.discovery.client.queries.api.SimpleQuery; +import org.gcube.resources.discovery.icclient.ICFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Luca Frosini (ISTI - CNR) + */ +public class ResourceRegistrySchemaClientFactory { + + private static final Logger logger = LoggerFactory.getLogger(ResourceRegistrySchemaClientFactory.class); + + protected static Map clients; + + static { + clients = new HashMap<>(); + } + + private static String FORCED_URL = null; + + protected static void forceToURL(String url){ + FORCED_URL = url; + } + + private static String classFormat = "$resource/Profile/ServiceClass/text() eq '%1s'"; + private static String nameFormat = "$resource/Profile/ServiceName/text() eq '%1s'"; + private static String statusFormat = "$resource/Profile/DeploymentData/Status/text() eq 'ready'"; + private static String containsFormat = "$entry/@EntryName eq '%1s'"; + + + private static String serviceEndpointCategoryFormat = "$resource/Profile/Category/text() eq '%1s'"; + private static String serviceEndpointNameFormat = "$resource/Profile/Name/text() eq '%1s'"; + private static String serviceEndpointstatusFormat = "$resource/Profile/RunTime/Status/text() eq 'READY'"; + + + + private static SimpleQuery queryForService(){ + return ICFactory.queryFor(GCoreEndpoint.class) + .addCondition(String.format(classFormat, Constants.SERVICE_CLASS)) + .addCondition(String.format(nameFormat, Constants.SERVICE_NAME)) + .addCondition(String.format(statusFormat)) + .addVariable("$entry","$resource/Profile/AccessPoint/RunningInstanceInterfaces/Endpoint") + .addCondition(String.format(containsFormat, Constants.SERVICE_ENTRY_NAME)) + .setResult("$entry/text()"); + } + + private static SimpleQuery queryForProxy(){ + return ICFactory.queryFor(ServiceEndpoint.class) + .addCondition(String.format(serviceEndpointCategoryFormat, Constants.SERVICE_CLASS)) + .addCondition(String.format(serviceEndpointNameFormat, Constants.SERVICE_NAME)) + .addCondition(String.format(serviceEndpointstatusFormat)) + .addVariable("$entry","$resource/Profile/AccessPoint/Interface/Endpoint") + .addCondition(String.format(containsFormat, Constants.SERVICE_ENTRY_NAME)) + .setResult("$entry/text()"); + } + + + protected static List getAddresses(){ + List addresses = new ArrayList<>(); + + try { + SimpleQuery proxyQuery = queryForProxy(); + addresses = ICFactory.client().submit(proxyQuery); + if(addresses==null || addresses.isEmpty()){ + throw new Exception("No ResourceRegistry Proxy Found"); + } + } catch (Exception e) { + logger.debug("{}. Looking for RunningInstance.", e.getMessage()); + SimpleQuery serviceQuery = queryForService(); + addresses = ICFactory.client().submit(serviceQuery); + } + + return addresses; + } + + + public static ResourceRegistrySchemaClient create(){ + if(FORCED_URL!=null){ + return new ResourceRegistrySchemaClientImpl(FORCED_URL); + } + + String key = null; + if (SecurityTokenProvider.instance.get() == null) { + if (ScopeProvider.instance.get() == null) { + throw new RuntimeException( + "Null Token and Scope. Please set your token first."); + } + key = ScopeProvider.instance.get(); + } else { + key = SecurityTokenProvider.instance.get(); + } + + ResourceRegistrySchemaClient client = clients.get(key); + + if(client==null){ + + List addresses = getAddresses(); + + if(addresses==null || addresses.isEmpty()){ + String error = String.format("No %s:%s found in the current context", Constants.SERVICE_CLASS, Constants.SERVICE_NAME); + throw new RuntimeException(error); + } + + Random random = new Random(); + int index = random.nextInt(addresses.size()); + + client = new ResourceRegistrySchemaClientImpl(addresses.get(index)); + + } + + return client; + } + +} diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/context/ResourceRegistrySchemaClientImpl.java b/src/main/java/org/gcube/informationsystem/resourceregistry/context/ResourceRegistrySchemaClientImpl.java new file mode 100644 index 0000000..455c9c2 --- /dev/null +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/context/ResourceRegistrySchemaClientImpl.java @@ -0,0 +1,129 @@ +package org.gcube.informationsystem.resourceregistry.context; + +import java.io.StringWriter; +import java.net.MalformedURLException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.gcube.informationsystem.model.ISManageable; +import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException; +import org.gcube.informationsystem.resourceregistry.api.exceptions.context.ContextAlreadyPresentException; +import org.gcube.informationsystem.resourceregistry.api.exceptions.context.ContextNotFoundException; +import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.SchemaException; +import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.SchemaNotFoundException; +import org.gcube.informationsystem.resourceregistry.api.rest.AccessPath; +import org.gcube.informationsystem.resourceregistry.api.rest.SchemaPath; +import org.gcube.informationsystem.resourceregistry.api.rest.httputils.HTTPCall; +import org.gcube.informationsystem.resourceregistry.api.rest.httputils.HTTPCall.HTTPMETHOD; +import org.gcube.informationsystem.resourceregistry.api.utils.Utility; +import org.gcube.informationsystem.types.TypeBinder; +import org.gcube.informationsystem.types.TypeBinder.TypeDefinition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Luca Frosini (ISTI - CNR) + */ +public class ResourceRegistrySchemaClientImpl implements ResourceRegistrySchemaClient { + + private static final Logger logger = LoggerFactory.getLogger(ResourceRegistrySchemaClientImpl.class); + + public static final String PATH_SEPARATOR = "/"; + + protected final String address; + protected HTTPCall httpCall; + + public ResourceRegistrySchemaClientImpl(String address) { + this.address = address; + + } + + private HTTPCall getHTTPCall() throws MalformedURLException { + if(httpCall == null) { + httpCall = new HTTPCall(address, ResourceRegistrySchemaClient.class.getSimpleName()); + } + return httpCall; + } + + @Override + public TypeDefinition create(Class clazz) + throws SchemaException, ResourceRegistryException { + try { + String typeDefinition = TypeBinder.serializeType(clazz); + String res = create(typeDefinition); + return TypeBinder.deserializeTypeDefinition(res); + } catch(ResourceRegistryException e) { + throw e; + } catch(Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public String create(String typeDefinitition) throws ContextAlreadyPresentException, ResourceRegistryException { + try { + logger.trace("Going to create: {}", typeDefinitition); + StringWriter stringWriter = new StringWriter(); + stringWriter.append(PATH_SEPARATOR); + stringWriter.append(SchemaPath.SCHEMA_PATH_PART); + + HTTPCall httpCall = getHTTPCall(); + String c = httpCall.call(String.class, stringWriter.toString(), HTTPMETHOD.PUT, typeDefinitition); + + logger.trace("{} successfully created", c); + return c; + + } catch(ResourceRegistryException e) { + throw e; + } catch(Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public List read(Class clazz, Boolean polymorphic) + throws SchemaNotFoundException, ResourceRegistryException { + try { + String type = Utility.getType(clazz); + String res = read(type, polymorphic); + return TypeBinder.deserializeTypeDefinitions(res); + } catch(ResourceRegistryException e) { + throw e; + } catch(Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public String read(String type, Boolean polymorphic) throws ContextNotFoundException, ResourceRegistryException { + + try { + logger.info("Going to get {} schema", type); + StringWriter stringWriter = new StringWriter(); + stringWriter.append(PATH_SEPARATOR); + stringWriter.append(SchemaPath.SCHEMA_PATH_PART); + stringWriter.append(PATH_SEPARATOR); + stringWriter.append(AccessPath.SCHEMA_PATH_PART); + stringWriter.append(PATH_SEPARATOR); + stringWriter.append(type); + + Map parameters = new HashMap<>(); + if(polymorphic == null) { + polymorphic = false; + } + parameters.put(AccessPath.POLYMORPHIC_PARAM, polymorphic.toString()); + + HTTPCall httpCall = getHTTPCall(); + String json = httpCall.call(String.class, stringWriter.toString(), HTTPMETHOD.GET, parameters); + + logger.debug("Got schema for {} is {}", type, json); + return json; + } catch(ResourceRegistryException e) { + throw e; + } catch(Exception e) { + throw new RuntimeException(e); + } + } + +} diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml new file mode 100644 index 0000000..98493f2 --- /dev/null +++ b/src/test/resources/logback-test.xml @@ -0,0 +1,19 @@ + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{0}: %msg%n + + + + + + + + + + + + \ No newline at end of file