diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0f63015 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target/ +/bin/ 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..2f5cc74 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -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 diff --git a/CHANGELOG.md b/CHANGELOG.md index 64e4f74..af3dfdd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/FUNDING.md b/FUNDING.md new file mode 100644 index 0000000..6fa9eac --- /dev/null +++ b/FUNDING.md @@ -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); \ No newline at end of file diff --git a/README.md b/README.md index a4466ac..03206cb 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/distro/LICENSE b/distro/LICENSE deleted file mode 100644 index 3695e26..0000000 --- a/distro/LICENSE +++ /dev/null @@ -1 +0,0 @@ -${gcube.license} diff --git a/distro/README b/distro/README deleted file mode 100644 index 32fd9b3..0000000 --- a/distro/README +++ /dev/null @@ -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. diff --git a/distro/changelog.xml b/distro/changelog.xml deleted file mode 100644 index 6a64ab1..0000000 --- a/distro/changelog.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - First Release - - - Rewritten as a framework for the implementation of client libraries that comply with the CL Design Model - - - Improved error handling in Plugin#convert() - - - AddressUtils preserve protocol from URIs/URLs - - - internal refactoring - - \ No newline at end of file diff --git a/distro/descriptor.xml b/distro/descriptor.xml deleted file mode 100644 index 0320287..0000000 --- a/distro/descriptor.xml +++ /dev/null @@ -1,36 +0,0 @@ - - servicearchive - - tar.gz - - / - - - ${distroDirectory} - / - true - - README - LICENSE - changelog.xml - profile.xml - - 755 - true - - - - - ${distroDirectory}/profile.xml - / - true - - - target/${build.finalName}.jar - /${artifactId} - - - diff --git a/distro/profile.xml b/distro/profile.xml deleted file mode 100644 index 91c49e4..0000000 --- a/distro/profile.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - Service - - ${description} - Common - ${artifactId} - 1.0.0 - - - ${artifactId} - ${version} - - ${groupId} - ${artifactId} - ${version} - - - ${build.finalName}.jar - - - - - - diff --git a/pom.xml b/pom.xml index 1f0a849..7a38ad7 100644 --- a/pom.xml +++ b/pom.xml @@ -7,111 +7,57 @@ 1.1.0 - org.gcube.core common-clients - 2.1.1 - + 3.0.0-SNAPSHOT Common Clients A framework for client APIs - - - distro - - - scm:git:https://code-repo.d4science.org/gCubeSystem/${project.artifactId}.git - scm:git:https://code-repo.d4science.org/gCubeSystem/${project.artifactId}.git - https://code-repo.d4science.org/gCubeSystem/${project.artifactId} + scm:git:https://code-repo.d4science.org/gCubeSystem/${project.artifactId}.git + scm:git:https://code-repo.d4science.org/gCubeSystem/${project.artifactId}.git + https://code-repo.d4science.org/gCubeSystem/${project.artifactId} - + + + + org.gcube.distribution + gcube-bom + 3.0.0-SNAPSHOT + pom + import + + + - org.gcube.core common-scope - [1.0.0-SNAPSHOT,2.0.0-SNAPSHOT) - org.slf4j slf4j-api - 1.6.4 - + + javax.xml.ws + jaxws-api + junit junit 4.10 test - org.mockito mockito-core 1.8.5 test - org.slf4j slf4j-simple 1.6.4 test - - - - - - - - org.apache.maven.plugins - maven-resources-plugin - 2.5 - - - copy-profile - install - - copy-resources - - - target - - - ${distroDirectory} - true - - profile.xml - - - - - - - - - - org.apache.maven.plugins - maven-assembly-plugin - - - ${distroDirectory}/descriptor.xml - - - - - servicearchive - install - - single - - - - - - - - + \ No newline at end of file diff --git a/src/main/java/org/gcube/common/clients/cache/Key.java b/src/main/java/org/gcube/common/clients/cache/Key.java index a00ffef..6d90326 100644 --- a/src/main/java/org/gcube/common/clients/cache/Key.java +++ b/src/main/java/org/gcube/common/clients/cache/Key.java @@ -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 diff --git a/src/main/java/org/gcube/common/clients/delegates/AsyncProxyDelegate.java b/src/main/java/org/gcube/common/clients/delegates/AsyncProxyDelegate.java index a9c19d9..20625b2 100644 --- a/src/main/java/org/gcube/common/clients/delegates/AsyncProxyDelegate.java +++ b/src/main/java/org/gcube/common/clients/delegates/AsyncProxyDelegate.java @@ -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 implements ProxyDelegate { */ public Future makeAsync(final Call call, ExecutorService service) throws RejectedExecutionException { - final String callScope = ScopeProvider.instance.get(); + final Secret secret = SecretManagerProvider.instance.get(); // create task from call Callable callTask = new Callable() { @@ -104,7 +105,7 @@ public class AsyncProxyDelegate implements ProxyDelegate { @Override public V call() throws Exception { - ScopeProvider.instance.set(callScope); + SecretManagerProvider.instance.set(secret); return inner.make(call); } diff --git a/src/test/java/org/gcube/common/clients/AsyncDelegateTest.java b/src/test/java/org/gcube/common/clients/AsyncDelegateTest.java index 2995be5..458b0b0 100644 --- a/src/test/java/org/gcube/common/clients/AsyncDelegateTest.java +++ b/src/test/java/org/gcube/common/clients/AsyncDelegateTest.java @@ -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 delegate; - + @Mock ProxyPlugin plugin; @Mock Object endpoint; - + @Mock Call 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(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 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() { @Override @@ -82,47 +91,72 @@ public class AsyncDelegateTest { } }; when(call.call(endpoint)).thenAnswer(slowly); - + Future 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 getHTTPAuthorizationHeaders() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getContext() { + return scope; + } + }); + //stage call Answer checkingScope= new Answer() { @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 future = delegate.makeAsync(call); - + future.get(); } - + @Test public void asyncCallReturnConvertedFaultsAsInnerCauses() throws Exception { - + //stage call when(call.call(endpoint)).thenThrow(original); - + Future 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 getHTTPAuthorizationHeaders() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getContext() { + return scope; + } + }); + //stage call Answer slowly = new Answer() { @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() { @Override @@ -179,9 +238,9 @@ public class AsyncDelegateTest { return value; } }; - + when(call.call(endpoint)).thenAnswer(answer); - + @SuppressWarnings("all") Callback 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() { @Override @@ -207,15 +266,15 @@ public class AsyncDelegateTest { return value; } }; - + when(call.call(endpoint)).thenAnswer(slowly); - + @SuppressWarnings("all") Callback callback = mock(Callback.class); when(callback.timeout()).thenReturn(100L); final CountDownLatch latch = new CountDownLatch(1); - + Answer unblock = new Answer() { @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 callback = mock(Callback.class); - + final CountDownLatch latch = new CountDownLatch(1); - + Answer unblock = new Answer() { @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); - + } - + }