Merge remote-tracking branch 'origin/smartgears_4'

This commit is contained in:
Lucio Lelii 2023-04-04 14:42:35 +02:00
commit d2f50ac761
15 changed files with 217 additions and 293 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target/
/bin/

View File

@ -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/<project>=UTF-8

View File

@ -0,0 +1,8 @@
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.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.8

View File

@ -3,8 +3,7 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [v2.1.1] - [2023-03-29]
## [v3.0.0-SNAPSHOT] - [2022-05-13]
- see #24727 upgrade version just for removing the gcube-staging dependencies
porting to gcube bom 3.0.0

26
FUNDING.md Normal file
View File

@ -0,0 +1,26 @@
# Acknowledgments
The projects leading to this software have received funding from a series of European Union programmes including:
- the Sixth Framework Programme for Research and Technological Development
- [DILIGENT](https://cordis.europa.eu/project/id/004260) (grant no. 004260).
- the Seventh Framework Programme for research, technological development and demonstration
- [D4Science](https://cordis.europa.eu/project/id/212488) (grant no. 212488);
- [D4Science-II](https://cordis.europa.eu/project/id/239019) (grant no.239019);
- [ENVRI](https://cordis.europa.eu/project/id/283465) (grant no. 283465);
- [iMarine](https://cordis.europa.eu/project/id/283644) (grant no. 283644);
- [EUBrazilOpenBio](https://cordis.europa.eu/project/id/288754) (grant no. 288754).
- the H2020 research and innovation programme
- [SoBigData](https://cordis.europa.eu/project/id/654024) (grant no. 654024);
- [PARTHENOS](https://cordis.europa.eu/project/id/654119) (grant no. 654119);
- [EGI-Engage](https://cordis.europa.eu/project/id/654142) (grant no. 654142);
- [ENVRI PLUS](https://cordis.europa.eu/project/id/654182) (grant no. 654182);
- [BlueBRIDGE](https://cordis.europa.eu/project/id/675680) (grant no. 675680);
- [PerformFISH](https://cordis.europa.eu/project/id/727610) (grant no. 727610);
- [AGINFRA PLUS](https://cordis.europa.eu/project/id/731001) (grant no. 731001);
- [DESIRA](https://cordis.europa.eu/project/id/818194) (grant no. 818194);
- [ARIADNEplus](https://cordis.europa.eu/project/id/823914) (grant no. 823914);
- [RISIS 2](https://cordis.europa.eu/project/id/824091) (grant no. 824091);
- [EOSC-Pillar](https://cordis.europa.eu/project/id/857650) (grant no. 857650);
- [Blue Cloud](https://cordis.europa.eu/project/id/862409) (grant no. 862409);
- [SoBigData-PlusPlus](https://cordis.europa.eu/project/id/871042) (grant no. 871042);

View File

@ -1,6 +1,24 @@
# common-clients
# Common clients
A library to allow client calls to smartgears
## Structure of the project
* The source code is present in the src folder.
## Built With
* [OpenJDK](https://openjdk.java.net/) - The JDK used
* [Maven](https://maven.apache.org/) - Dependency Management
## Change log
See [Releases](https://code-repo.d4science.org/gCubeSystem/common-clients/releases).
## Authors
* **Lucio Lelii** ([ISTI-CNR Infrascience Group](http://nemis.isti.cnr.it/groups/infrascience)
## License

View File

@ -1 +0,0 @@
${gcube.license}

View File

@ -1,61 +0,0 @@
The gCube System - ${name}
--------------------------------------------------
${description}
${gcube.description}
${gcube.funding}
Version
--------------------------------------------------
${version} (${buildDate})
Please see the file named "changelog.xml" in this directory for the release notes.
Authors
--------------------------------------------------
* Fabio Simeoni (fabio.simeoni-AT-fao.org), FAO of the UN, Italy.
Maintainers
-----------
* Fabio Simeoni (fabio.simeoni-AT-fao.org), FAO of the UN, Italy.
Download information
--------------------------------------------------
Source code is available from SVN:
${scm.url}
Binaries can be downloaded from the gCube website:
${gcube.website}
Installation
--------------------------------------------------
Installation documentation is available on-line in the gCube Wiki:
${gcube.wikiRoot}
Documentation
-------------
Documentation is available on-line from the Projects Documentation Wiki:
https://https://gcube.wiki.gcube-system.org/gcube/index.php/Integration_and_Interoperability_Facilities_Framework:_Client_Libraries_Framework
Support
--------------------------------------------------
Bugs and support requests can be reported in the gCube issue tracking tool:
${gcube.issueTracking}
Licensing
--------------------------------------------------
This software is licensed under the terms you may find in the file named "LICENSE" in this directory.

View File

@ -1,17 +0,0 @@
<ReleaseNotes>
<Changeset component="common-clients-1.0.0" date="2012-04-27">
<Change>First Release</Change>
</Changeset>
<Changeset component="common-clients-2.0.0" date="2012-09-01">
<Change>Rewritten as a framework for the implementation of client libraries that comply with the CL Design Model</Change>
</Changeset>
<Changeset component="common-clients-2.0.1" date="2013-01-11">
<Change>Improved error handling in Plugin#convert()</Change>
</Changeset>
<Changeset component="common-clients-2.0.2" date="2013-15-04">
<Change>AddressUtils preserve protocol from URIs/URLs</Change>
</Changeset>
<Changeset component="${build.finalName}" date="2013-10-10">
<Change>internal refactoring</Change>
</Changeset>
</ReleaseNotes>

View File

@ -1,36 +0,0 @@
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>servicearchive</id>
<formats>
<format>tar.gz</format>
</formats>
<baseDirectory>/</baseDirectory>
<fileSets>
<fileSet>
<directory>${distroDirectory}</directory>
<outputDirectory>/</outputDirectory>
<useDefaultExcludes>true</useDefaultExcludes>
<includes>
<include>README</include>
<include>LICENSE</include>
<include>changelog.xml</include>
<include>profile.xml</include>
</includes>
<fileMode>755</fileMode>
<filtered>true</filtered>
</fileSet>
</fileSets>
<files>
<file>
<source>${distroDirectory}/profile.xml</source>
<outputDirectory>/</outputDirectory>
<filtered>true</filtered>
</file>
<file>
<source>target/${build.finalName}.jar</source>
<outputDirectory>/${artifactId}</outputDirectory>
</file>
</files>
</assembly>

View File

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Resource xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ID />
<Type>Service</Type>
<Profile>
<Description>${description}</Description>
<Class>Common</Class>
<Name>${artifactId}</Name>
<Version>1.0.0</Version>
<Packages>
<Software>
<Name>${artifactId}</Name>
<Version>${version}</Version>
<MavenCoordinates>
<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<version>${version}</version>
</MavenCoordinates>
<Files>
<File>${build.finalName}.jar</File>
</Files>
</Software>
</Packages>
</Profile>
</Resource>

94
pom.xml
View File

@ -7,111 +7,57 @@
<version>1.1.0</version>
<relativePath />
</parent>
<groupId>org.gcube.core</groupId>
<artifactId>common-clients</artifactId>
<version>2.1.1</version>
<version>3.0.0-SNAPSHOT</version>
<name>Common Clients</name>
<description>A framework for client APIs</description>
<properties>
<distroDirectory>distro</distroDirectory>
</properties>
<scm>
<connection>scm:git:https://code-repo.d4science.org/gCubeSystem/${project.artifactId}.git</connection>
<developerConnection>scm:git:https://code-repo.d4science.org/gCubeSystem/${project.artifactId}.git</developerConnection>
<url>https://code-repo.d4science.org/gCubeSystem/${project.artifactId}</url>
<connection>scm:git:https://code-repo.d4science.org/gCubeSystem/${project.artifactId}.git</connection>
<developerConnection>scm:git:https://code-repo.d4science.org/gCubeSystem/${project.artifactId}.git</developerConnection>
<url>https://code-repo.d4science.org/gCubeSystem/${project.artifactId}</url>
</scm>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.gcube.distribution</groupId>
<artifactId>gcube-bom</artifactId>
<version>3.0.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-scope</artifactId>
<version>[1.0.0-SNAPSHOT,2.0.0-SNAPSHOT)</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.4</version>
</dependency>
<dependency>
<groupId>javax.xml.ws</groupId>
<artifactId>jaxws-api</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.8.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.6.4</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>copy-profile</id>
<phase>install</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>target</outputDirectory>
<resources>
<resource>
<directory>${distroDirectory}</directory>
<filtering>true</filtering>
<includes>
<include>profile.xml</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>${distroDirectory}/descriptor.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>servicearchive</id>
<phase>install</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
</project>

View File

@ -1,7 +1,7 @@
package org.gcube.common.clients.cache;
import org.gcube.common.clients.queries.Query;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.common.security.providers.SecretManagerProvider;
/**
* Keys for cross-service {@link EndpointCache}s comprised of a service name, a {@link Query}, and a scope.
@ -32,7 +32,7 @@ public final class Key {
private Key(String name, Query<?> query) {
this.name = name;
this.query = query;
this.scope = ScopeProvider.instance.get();
this.scope = SecretManagerProvider.instance.get().getContext();
}
@Override

View File

@ -11,7 +11,8 @@ import java.util.concurrent.TimeoutException;
import org.gcube.common.clients.Call;
import org.gcube.common.clients.config.ProxyConfig;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.common.security.providers.SecretManagerProvider;
import org.gcube.common.security.secrets.Secret;
/**
* A {@link ProxyDelegate} that delivers the outcome of {@link Call}s asynchronously, either through polling or
@ -96,7 +97,7 @@ public class AsyncProxyDelegate<S> implements ProxyDelegate<S> {
*/
public <V> Future<V> makeAsync(final Call<S, V> call, ExecutorService service) throws RejectedExecutionException {
final String callScope = ScopeProvider.instance.get();
final Secret secret = SecretManagerProvider.instance.get();
// create task from call
Callable<V> callTask = new Callable<V>() {
@ -104,7 +105,7 @@ public class AsyncProxyDelegate<S> implements ProxyDelegate<S> {
@Override
public V call() throws Exception {
ScopeProvider.instance.set(callScope);
SecretManagerProvider.instance.set(secret);
return inner.make(call);
}

View File

@ -1,11 +1,18 @@
package org.gcube.common.clients;
import static java.util.concurrent.TimeUnit.*;
import static junit.framework.Assert.*;
import static org.gcube.common.clients.delegates.MockDelegate.*;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
import static java.util.concurrent.TimeUnit.SECONDS;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
import static org.gcube.common.clients.delegates.MockDelegate.mockDelegate;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.Map;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
@ -15,7 +22,9 @@ import java.util.concurrent.TimeoutException;
import org.gcube.common.clients.delegates.AsyncProxyDelegate;
import org.gcube.common.clients.delegates.Callback;
import org.gcube.common.clients.delegates.ProxyPlugin;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.common.security.Owner;
import org.gcube.common.security.providers.SecretManagerProvider;
import org.gcube.common.security.secrets.Secret;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -28,16 +37,16 @@ import org.mockito.stubbing.Answer;
public class AsyncDelegateTest {
AsyncProxyDelegate<Object> delegate;
@Mock ProxyPlugin<Object,Object,?> plugin;
@Mock Object endpoint;
@Mock Call<Object,Object> call;
@Mock Object value;
@Mock Exception original;
@Mock Exception converted;
@Before
@SuppressWarnings("all")
public void setup() throws Exception {
@ -45,34 +54,34 @@ public class AsyncDelegateTest {
//create subject-under-testing
delegate =new AsyncProxyDelegate<Object>(mockDelegate(plugin,endpoint));
//common configuration staging: mocking a delegate is not that immediate..
when(plugin.name()).thenReturn("some service");
when(plugin.convert(original,delegate.config())).thenReturn(converted);
}
@Test
public void asyncCallsReturnFutureValues() throws Exception {
//stage call
when(call.call(endpoint)).thenReturn(value);
Future<Object> future = delegate.makeAsync(call);
Object output = future.get();
assertEquals(value,output);
assertFalse(future.isCancelled());
assertTrue(future.isDone());
}
@Test
public void asyncCallsTimeout() throws Exception {
//stage call
Answer<?> slowly = new Answer<Object>() {
@Override
@ -82,47 +91,72 @@ public class AsyncDelegateTest {
}
};
when(call.call(endpoint)).thenAnswer(slowly);
Future<Object> future = delegate.makeAsync(call);
try {
future.get(100,TimeUnit.MILLISECONDS);
fail();
}
catch(TimeoutException e) {}
}
@Test
public void asyncCallsExecuteInCallScope() throws Exception {
final String scope = "a/b/c";
ScopeProvider.instance.set(scope);
SecretManagerProvider.instance.set(new Secret() {
@Override
public boolean isExpired() {
// TODO Auto-generated method stub
return false;
}
@Override
public Owner getOwner() {
// TODO Auto-generated method stub
return null;
}
@Override
public Map<String, String> getHTTPAuthorizationHeaders() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getContext() {
return scope;
}
});
//stage call
Answer<?> checkingScope= new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
assertEquals(scope,ScopeProvider.instance.get());
assertEquals(scope,SecretManagerProvider.instance.get().getContext());
return value;
}
};
when(call.call(endpoint)).thenAnswer(checkingScope);
Future<Object> future = delegate.makeAsync(call);
future.get();
}
@Test
public void asyncCallReturnConvertedFaultsAsInnerCauses() throws Exception {
//stage call
when(call.call(endpoint)).thenThrow(original);
Future<Object> future = delegate.makeAsync(call);
try {
future.get();
fail();
@ -130,15 +164,40 @@ public class AsyncDelegateTest {
catch(Exception fault) {
assertEquals(converted,fault.getCause());
}
}
@Test
public void asyncCallsAreInterrupted() throws Exception {
final String scope = "a/b/c";
ScopeProvider.instance.set(scope);
SecretManagerProvider.instance.set(new Secret() {
@Override
public boolean isExpired() {
// TODO Auto-generated method stub
return false;
}
@Override
public Owner getOwner() {
// TODO Auto-generated method stub
return null;
}
@Override
public Map<String, String> getHTTPAuthorizationHeaders() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getContext() {
return scope;
}
});
//stage call
Answer<?> slowly = new Answer<Object>() {
@Override
@ -153,12 +212,12 @@ public class AsyncDelegateTest {
new Thread() {
public void run() {
future.cancel(true);
};
}.start();
try {
future.get();
fail();
@ -166,12 +225,12 @@ public class AsyncDelegateTest {
catch(CancellationException fault) {
assertTrue(future.isCancelled());
}
}
@Test
public void callbacksGetResults() throws Exception {
//stage call
Answer<?> answer = new Answer<Object>() {
@Override
@ -179,9 +238,9 @@ public class AsyncDelegateTest {
return value;
}
};
when(call.call(endpoint)).thenAnswer(answer);
@SuppressWarnings("all")
Callback<Object> callback = mock(Callback.class);
@ -189,16 +248,16 @@ public class AsyncDelegateTest {
//make sure the callback has had time to arrive
Thread.sleep(400);
verify(callback).done(value);
assertTrue(future.isDone());
}
@Test
public void callbacksGetTimeoutErrors() throws Exception {
//stage call
Answer<?> slowly = new Answer<Object>() {
@Override
@ -207,15 +266,15 @@ public class AsyncDelegateTest {
return value;
}
};
when(call.call(endpoint)).thenAnswer(slowly);
@SuppressWarnings("all")
Callback<Object> callback = mock(Callback.class);
when(callback.timeout()).thenReturn(100L);
final CountDownLatch latch = new CountDownLatch(1);
Answer<?> unblock = new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
@ -223,27 +282,27 @@ public class AsyncDelegateTest {
return value;
}
};
doAnswer(unblock).when(callback).onFailure(any(TimeoutException.class));
Future<?> future = delegate.makeAsync(call,callback);
//makes sure callback has been invoked
latch.await(5,SECONDS);
assertTrue(future.isCancelled());
}
@Test
public void callbacksGetFaults() throws Exception {
when(call.call(endpoint)).thenThrow(original);
@SuppressWarnings("all")
Callback<Object> callback = mock(Callback.class);
final CountDownLatch latch = new CountDownLatch(1);
Answer<?> unblock = new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
@ -254,14 +313,14 @@ public class AsyncDelegateTest {
return null;
}
};
doAnswer(unblock).when(callback).onFailure(any(Throwable.class));
delegate.makeAsync(call,callback);
//makes sure callback has been invoked
latch.await(1,SECONDS);
}
}